smallstep-certificates/authority/provisioner/claims.go
2023-07-27 15:05:04 -07:00

259 lines
10 KiB
Go

package provisioner
import (
"time"
"github.com/pkg/errors"
"golang.org/x/crypto/ssh"
)
// Claims so that individual provisioners can override global claims.
type Claims struct {
// TLS CA properties
MinTLSDur *Duration `json:"minTLSCertDuration,omitempty"`
MaxTLSDur *Duration `json:"maxTLSCertDuration,omitempty"`
DefaultTLSDur *Duration `json:"defaultTLSCertDuration,omitempty"`
// SSH CA properties
MinUserSSHDur *Duration `json:"minUserSSHCertDuration,omitempty"`
MaxUserSSHDur *Duration `json:"maxUserSSHCertDuration,omitempty"`
DefaultUserSSHDur *Duration `json:"defaultUserSSHCertDuration,omitempty"`
MinHostSSHDur *Duration `json:"minHostSSHCertDuration,omitempty"`
MaxHostSSHDur *Duration `json:"maxHostSSHCertDuration,omitempty"`
DefaultHostSSHDur *Duration `json:"defaultHostSSHCertDuration,omitempty"`
EnableSSHCA *bool `json:"enableSSHCA,omitempty"`
// Renewal properties
DisableRenewal *bool `json:"disableRenewal,omitempty"`
AllowRenewalAfterExpiry *bool `json:"allowRenewalAfterExpiry,omitempty"`
// Other properties
DisableSmallstepExtensions *bool `json:"disableSmallstepExtensions,omitempty"`
}
// Claimer is the type that controls claims. It provides an interface around the
// current claim and the global one.
type Claimer struct {
global Claims
claims *Claims
}
// NewClaimer initializes a new claimer with the given claims.
func NewClaimer(claims *Claims, global Claims) (*Claimer, error) {
c := &Claimer{global: global, claims: claims}
err := c.Validate()
return c, err
}
// Claims returns the merge of the inner and global claims.
func (c *Claimer) Claims() Claims {
disableRenewal := c.IsDisableRenewal()
allowRenewalAfterExpiry := c.AllowRenewalAfterExpiry()
enableSSHCA := c.IsSSHCAEnabled()
disableSmallstepExtensions := c.IsDisableSmallstepExtensions()
return Claims{
MinTLSDur: &Duration{c.MinTLSCertDuration()},
MaxTLSDur: &Duration{c.MaxTLSCertDuration()},
DefaultTLSDur: &Duration{c.DefaultTLSCertDuration()},
MinUserSSHDur: &Duration{c.MinUserSSHCertDuration()},
MaxUserSSHDur: &Duration{c.MaxUserSSHCertDuration()},
DefaultUserSSHDur: &Duration{c.DefaultUserSSHCertDuration()},
MinHostSSHDur: &Duration{c.MinHostSSHCertDuration()},
MaxHostSSHDur: &Duration{c.MaxHostSSHCertDuration()},
DefaultHostSSHDur: &Duration{c.DefaultHostSSHCertDuration()},
EnableSSHCA: &enableSSHCA,
DisableRenewal: &disableRenewal,
AllowRenewalAfterExpiry: &allowRenewalAfterExpiry,
DisableSmallstepExtensions: &disableSmallstepExtensions,
}
}
// DefaultTLSCertDuration returns the default TLS cert duration for the
// provisioner. If the default is not set within the provisioner, then the global
// default from the authority configuration will be used.
func (c *Claimer) DefaultTLSCertDuration() time.Duration {
if c.claims == nil || c.claims.DefaultTLSDur == nil {
return c.global.DefaultTLSDur.Duration
}
return c.claims.DefaultTLSDur.Duration
}
// MinTLSCertDuration returns the minimum TLS cert duration for the provisioner.
// If the minimum is not set within the provisioner, then the global
// minimum from the authority configuration will be used.
func (c *Claimer) MinTLSCertDuration() time.Duration {
if c.claims == nil || c.claims.MinTLSDur == nil {
if c.claims != nil && c.claims.DefaultTLSDur != nil && c.claims.DefaultTLSDur.Duration < c.global.MinTLSDur.Duration {
return c.claims.DefaultTLSDur.Duration
}
return c.global.MinTLSDur.Duration
}
return c.claims.MinTLSDur.Duration
}
// MaxTLSCertDuration returns the maximum TLS cert duration for the provisioner.
// If the maximum is not set within the provisioner, then the global
// maximum from the authority configuration will be used.
func (c *Claimer) MaxTLSCertDuration() time.Duration {
if c.claims == nil || c.claims.MaxTLSDur == nil {
if c.claims != nil && c.claims.DefaultTLSDur != nil && c.claims.DefaultTLSDur.Duration > c.global.MaxTLSDur.Duration {
return c.claims.DefaultTLSDur.Duration
}
return c.global.MaxTLSDur.Duration
}
return c.claims.MaxTLSDur.Duration
}
// IsDisableRenewal returns if the renewal flow is disabled for the
// provisioner. If the property is not set within the provisioner, then the
// global value from the authority configuration will be used.
func (c *Claimer) IsDisableRenewal() bool {
if c.claims == nil || c.claims.DisableRenewal == nil {
return *c.global.DisableRenewal
}
return *c.claims.DisableRenewal
}
// IsDisableSmallstepExtensions returns whether Smallstep extensions, such as
// the provisioner extension, should be excluded from the certificate.
func (c *Claimer) IsDisableSmallstepExtensions() bool {
if c.claims == nil || c.claims.DisableSmallstepExtensions == nil {
return *c.global.DisableSmallstepExtensions
}
return *c.claims.DisableSmallstepExtensions
}
// AllowRenewalAfterExpiry returns if the renewal flow is authorized if the
// certificate is expired. If the property is not set within the provisioner
// then the global value from the authority configuration will be used.
func (c *Claimer) AllowRenewalAfterExpiry() bool {
if c.claims == nil || c.claims.AllowRenewalAfterExpiry == nil {
return *c.global.AllowRenewalAfterExpiry
}
return *c.claims.AllowRenewalAfterExpiry
}
// DefaultSSHCertDuration returns the default SSH certificate duration for the
// given certificate type.
func (c *Claimer) DefaultSSHCertDuration(certType uint32) (time.Duration, error) {
switch certType {
case ssh.UserCert:
return c.DefaultUserSSHCertDuration(), nil
case ssh.HostCert:
return c.DefaultHostSSHCertDuration(), nil
case 0:
return 0, errors.New("ssh certificate type has not been set")
default:
return 0, errors.Errorf("ssh certificate has an unknown type: %d", certType)
}
}
// DefaultUserSSHCertDuration returns the default SSH user cert duration for the
// provisioner. If the default is not set within the provisioner, then the
// global default from the authority configuration will be used.
func (c *Claimer) DefaultUserSSHCertDuration() time.Duration {
if c.claims == nil || c.claims.DefaultUserSSHDur == nil {
return c.global.DefaultUserSSHDur.Duration
}
return c.claims.DefaultUserSSHDur.Duration
}
// MinUserSSHCertDuration returns the minimum SSH user cert duration for the
// provisioner. If the minimum is not set within the provisioner, then the
// global minimum from the authority configuration will be used.
func (c *Claimer) MinUserSSHCertDuration() time.Duration {
if c.claims == nil || c.claims.MinUserSSHDur == nil {
if c.claims != nil && c.claims.DefaultUserSSHDur != nil && c.claims.DefaultUserSSHDur.Duration < c.global.MinUserSSHDur.Duration {
return c.claims.DefaultUserSSHDur.Duration
}
return c.global.MinUserSSHDur.Duration
}
return c.claims.MinUserSSHDur.Duration
}
// MaxUserSSHCertDuration returns the maximum SSH user cert duration for the
// provisioner. If the maximum is not set within the provisioner, then the
// global maximum from the authority configuration will be used.
func (c *Claimer) MaxUserSSHCertDuration() time.Duration {
if c.claims == nil || c.claims.MaxUserSSHDur == nil {
if c.claims != nil && c.claims.DefaultUserSSHDur != nil && c.claims.DefaultUserSSHDur.Duration > c.global.MaxUserSSHDur.Duration {
return c.claims.DefaultUserSSHDur.Duration
}
return c.global.MaxUserSSHDur.Duration
}
return c.claims.MaxUserSSHDur.Duration
}
// DefaultHostSSHCertDuration returns the default SSH host cert duration for the
// provisioner. If the default is not set within the provisioner, then the
// global default from the authority configuration will be used.
func (c *Claimer) DefaultHostSSHCertDuration() time.Duration {
if c.claims == nil || c.claims.DefaultHostSSHDur == nil {
return c.global.DefaultHostSSHDur.Duration
}
return c.claims.DefaultHostSSHDur.Duration
}
// MinHostSSHCertDuration returns the minimum SSH host cert duration for the
// provisioner. If the minimum is not set within the provisioner, then the
// global minimum from the authority configuration will be used.
func (c *Claimer) MinHostSSHCertDuration() time.Duration {
if c.claims == nil || c.claims.MinHostSSHDur == nil {
if c.claims != nil && c.claims.DefaultHostSSHDur != nil && c.claims.DefaultHostSSHDur.Duration < c.global.MinHostSSHDur.Duration {
return c.claims.DefaultHostSSHDur.Duration
}
return c.global.MinHostSSHDur.Duration
}
return c.claims.MinHostSSHDur.Duration
}
// MaxHostSSHCertDuration returns the maximum SSH Host cert duration for the
// provisioner. If the maximum is not set within the provisioner, then the
// global maximum from the authority configuration will be used.
func (c *Claimer) MaxHostSSHCertDuration() time.Duration {
if c.claims == nil || c.claims.MaxHostSSHDur == nil {
if c.claims != nil && c.claims.DefaultHostSSHDur != nil && c.claims.DefaultHostSSHDur.Duration > c.global.MaxHostSSHDur.Duration {
return c.claims.DefaultHostSSHDur.Duration
}
return c.global.MaxHostSSHDur.Duration
}
return c.claims.MaxHostSSHDur.Duration
}
// IsSSHCAEnabled returns if the SSH CA is enabled for the provisioner. If the
// property is not set within the provisioner, then the global value from the
// authority configuration will be used.
func (c *Claimer) IsSSHCAEnabled() bool {
if c.claims == nil || c.claims.EnableSSHCA == nil {
return *c.global.EnableSSHCA
}
return *c.claims.EnableSSHCA
}
// Validate validates and modifies the Claims with default values.
func (c *Claimer) Validate() error {
var (
min = c.MinTLSCertDuration()
max = c.MaxTLSCertDuration()
def = c.DefaultTLSCertDuration()
)
switch {
case min <= 0:
return errors.Errorf("claims: MinTLSCertDuration must be greater than 0")
case max <= 0:
return errors.Errorf("claims: MaxTLSCertDuration must be greater than 0")
case def <= 0:
return errors.Errorf("claims: DefaultTLSCertDuration must be greater than 0")
case max < min:
return errors.Errorf("claims: MaxCertDuration cannot be less "+
"than MinCertDuration: MaxCertDuration - %v, MinCertDuration - %v", max, min)
case def < min:
return errors.Errorf("claims: DefaultCertDuration cannot be less than MinCertDuration: DefaultCertDuration - %v, MinCertDuration - %v", def, min)
case max < def:
return errors.Errorf("claims: MaxCertDuration cannot be less than DefaultCertDuration: MaxCertDuration - %v, DefaultCertDuration - %v", max, def)
default:
return nil
}
}