Contain policy engines inside provisioner Controller

pull/788/head
Herman Slatman 2 years ago
parent ef110a94df
commit c40a4d2694
No known key found for this signature in database
GPG Key ID: F4D8A44EA0A75A4F

@ -7,6 +7,7 @@ import (
"go.step.sm/linkedca"
"github.com/smallstep/certificates/authority/admin"
authPolicy "github.com/smallstep/certificates/authority/policy"
policy "github.com/smallstep/certificates/policy"
)
@ -228,7 +229,10 @@ func (a *Authority) reloadPolicyEngines(ctx context.Context) error {
linkedPolicy, err := a.adminDB.GetAuthorityPolicy(ctx)
if err != nil {
return fmt.Errorf("error getting policy to (re)load policy engines: %w", err)
var ae *admin.Error
if isAdminError := errors.As(err, &ae); (isAdminError && ae.Type != admin.ErrorNotFoundType.String()) || !isAdminError {
return fmt.Errorf("error getting policy to (re)load policy engines: %w", err)
}
}
policyOptions = policyToCertificates(linkedPolicy)
} else {

@ -8,8 +8,6 @@ import (
"time"
"github.com/pkg/errors"
"github.com/smallstep/certificates/authority/policy"
)
// ACME is the acme provisioner type, an entity that can authorize the ACME
@ -28,8 +26,7 @@ type ACME struct {
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
ctl *Controller
x509Policy policy.X509Policy
ctl *Controller
}
// GetID returns the provisioner unique identifier.
@ -86,12 +83,7 @@ func (p *ACME) Init(config Config) (err error) {
return errors.New("provisioner name cannot be empty")
}
// Initialize the x509 allow/deny policy engine
if p.x509Policy, err = policy.NewX509PolicyEngine(p.Options.GetX509Options()); err != nil {
return err
}
p.ctl, err = NewController(p, p.Claims, config)
p.ctl, err = NewController(p, p.Claims, config, p.Options)
return
}
@ -115,8 +107,10 @@ type ACMEIdentifier struct {
// certificate for an ACME Order Identifier.
func (p *ACME) AuthorizeOrderIdentifier(ctx context.Context, identifier ACMEIdentifier) error {
x509Policy := p.ctl.GetPolicy().GetX509()
// identifier is allowed if no policy is configured
if p.x509Policy == nil {
if x509Policy == nil {
return nil
}
@ -124,9 +118,9 @@ func (p *ACME) AuthorizeOrderIdentifier(ctx context.Context, identifier ACMEIden
var err error
switch identifier.Type {
case IP:
_, err = p.x509Policy.IsIPAllowed(net.ParseIP(identifier.Value))
_, err = x509Policy.IsIPAllowed(net.ParseIP(identifier.Value))
case DNS:
_, err = p.x509Policy.IsDNSAllowed(identifier.Value)
_, err = x509Policy.IsDNSAllowed(identifier.Value)
default:
err = fmt.Errorf("invalid ACME identifier type '%s' provided", identifier.Type)
}
@ -147,7 +141,7 @@ func (p *ACME) AuthorizeSign(ctx context.Context, token string) ([]SignOption, e
// validators
defaultPublicKeyValidator{},
newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()),
newX509NamePolicyValidator(p.x509Policy),
newX509NamePolicyValidator(p.ctl.GetPolicy().GetX509()),
}
return opts, nil

@ -17,11 +17,12 @@ import (
"time"
"github.com/pkg/errors"
"github.com/smallstep/certificates/authority/policy"
"github.com/smallstep/certificates/errs"
"go.step.sm/crypto/jose"
"go.step.sm/crypto/sshutil"
"go.step.sm/crypto/x509util"
"github.com/smallstep/certificates/errs"
)
// awsIssuer is the string used as issuer in the generated tokens.
@ -267,8 +268,6 @@ type AWS struct {
Options *Options `json:"options,omitempty"`
config *awsConfig
ctl *Controller
x509Policy policy.X509Policy
sshHostPolicy policy.HostPolicy
}
// GetID returns the provisioner unique identifier.
@ -423,18 +422,8 @@ func (p *AWS) Init(config Config) (err error) {
}
}
// Initialize the x509 allow/deny policy engine
if p.x509Policy, err = policy.NewX509PolicyEngine(p.Options.GetX509Options()); err != nil {
return err
}
// Initialize the SSH allow/deny policy engine for host certificates
if p.sshHostPolicy, err = policy.NewSSHHostPolicyEngine(p.Options.GetSSHOptions()); err != nil {
return err
}
config.Audiences = config.Audiences.WithFragment(p.GetIDForToken())
p.ctl, err = NewController(p, p.Claims, config)
p.ctl, err = NewController(p, p.Claims, config, p.Options)
return
}
@ -489,7 +478,7 @@ func (p *AWS) AuthorizeSign(ctx context.Context, token string) ([]SignOption, er
defaultPublicKeyValidator{},
commonNameValidator(payload.Claims.Subject),
newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()),
newX509NamePolicyValidator(p.x509Policy),
newX509NamePolicyValidator(p.ctl.GetPolicy().GetX509()),
), nil
}
@ -769,6 +758,6 @@ func (p *AWS) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption,
// Require all the fields in the SSH certificate
&sshCertDefaultValidator{},
// Ensure that all principal names are allowed
newSSHNamePolicyValidator(p.sshHostPolicy, nil),
newSSHNamePolicyValidator(p.ctl.GetPolicy().GetSSHHost(), nil),
), nil
}

@ -18,7 +18,6 @@ import (
"go.step.sm/crypto/sshutil"
"go.step.sm/crypto/x509util"
"github.com/smallstep/certificates/authority/policy"
"github.com/smallstep/certificates/errs"
)
@ -103,8 +102,6 @@ type Azure struct {
oidcConfig openIDConfiguration
keyStore *keyStore
ctl *Controller
x509Policy policy.X509Policy
sshHostPolicy policy.HostPolicy
}
// GetID returns the provisioner unique identifier.
@ -224,17 +221,7 @@ func (p *Azure) Init(config Config) (err error) {
return
}
// Initialize the x509 allow/deny policy engine
if p.x509Policy, err = policy.NewX509PolicyEngine(p.Options.GetX509Options()); err != nil {
return err
}
// Initialize the SSH allow/deny policy engine for host certificates
if p.sshHostPolicy, err = policy.NewSSHHostPolicyEngine(p.Options.GetSSHOptions()); err != nil {
return err
}
p.ctl, err = NewController(p, p.Claims, config)
p.ctl, err = NewController(p, p.Claims, config, p.Options)
return
}
@ -375,7 +362,7 @@ func (p *Azure) AuthorizeSign(ctx context.Context, token string) ([]SignOption,
// validators
defaultPublicKeyValidator{},
newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()),
newX509NamePolicyValidator(p.x509Policy),
newX509NamePolicyValidator(p.ctl.GetPolicy().GetX509()),
), nil
}
@ -442,7 +429,7 @@ func (p *Azure) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOptio
// Require all the fields in the SSH certificate
&sshCertDefaultValidator{},
// Ensure that all principal names are allowed
newSSHNamePolicyValidator(p.sshHostPolicy, nil),
newSSHNamePolicyValidator(p.ctl.GetPolicy().GetSSHHost(), nil),
), nil
}

@ -21,14 +21,19 @@ type Controller struct {
IdentityFunc GetIdentityFunc
AuthorizeRenewFunc AuthorizeRenewFunc
AuthorizeSSHRenewFunc AuthorizeSSHRenewFunc
policy *policyEngine
}
// NewController initializes a new provisioner controller.
func NewController(p Interface, claims *Claims, config Config) (*Controller, error) {
func NewController(p Interface, claims *Claims, config Config, options *Options) (*Controller, error) {
claimer, err := NewClaimer(claims, config.Claims)
if err != nil {
return nil, err
}
policy, err := newPolicyEngine(options)
if err != nil {
return nil, err
}
return &Controller{
Interface: p,
Audiences: &config.Audiences,
@ -36,6 +41,7 @@ func NewController(p Interface, claims *Claims, config Config) (*Controller, err
IdentityFunc: config.GetIdentityFunc,
AuthorizeRenewFunc: config.AuthorizeRenewFunc,
AuthorizeSSHRenewFunc: config.AuthorizeSSHRenewFunc,
policy: policy,
}, nil
}
@ -192,3 +198,10 @@ func SanitizeSSHUserPrincipal(email string) string {
}
}, strings.ToLower(email))
}
func (c *Controller) GetPolicy() *policyEngine {
if c == nil {
return nil
}
return c.policy
}

@ -9,6 +9,8 @@ import (
"time"
"golang.org/x/crypto/ssh"
"github.com/smallstep/certificates/authority/policy"
)
var trueValue = true
@ -30,11 +32,40 @@ func mustDuration(t *testing.T, s string) *Duration {
return d
}
func mustNewPolicyEngine(t *testing.T, options *Options) *policyEngine {
t.Helper()
c, err := newPolicyEngine(options)
if err != nil {
t.Fatal(err)
}
return c
}
func TestNewController(t *testing.T) {
options := &Options{
X509: &X509Options{
AllowedNames: &policy.X509NameOptions{
DNSDomains: []string{"*.local"},
},
},
SSH: &SSHOptions{
Host: &policy.SSHHostCertificateOptions{
AllowedNames: &policy.SSHNameOptions{
DNSDomains: []string{"*.local"},
},
},
User: &policy.SSHUserCertificateOptions{
AllowedNames: &policy.SSHNameOptions{
EmailAddresses: []string{"@example.com"},
},
},
},
}
type args struct {
p Interface
claims *Claims
config Config
p Interface
claims *Claims
config Config
options *Options
}
tests := []struct {
name string
@ -45,7 +76,7 @@ func TestNewController(t *testing.T) {
{"ok", args{&JWK{}, nil, Config{
Claims: globalProvisionerClaims,
Audiences: testAudiences,
}}, &Controller{
}, nil}, &Controller{
Interface: &JWK{},
Audiences: &testAudiences,
Claimer: mustClaimer(t, nil, globalProvisionerClaims),
@ -55,24 +86,49 @@ func TestNewController(t *testing.T) {
}, Config{
Claims: globalProvisionerClaims,
Audiences: testAudiences,
}}, &Controller{
}, nil}, &Controller{
Interface: &JWK{},
Audiences: &testAudiences,
Claimer: mustClaimer(t, &Claims{
DisableRenewal: &defaultDisableRenewal,
}, globalProvisionerClaims),
}, false},
{"ok with claims and options", args{&JWK{}, &Claims{
DisableRenewal: &defaultDisableRenewal,
}, Config{
Claims: globalProvisionerClaims,
Audiences: testAudiences,
}, options}, &Controller{
Interface: &JWK{},
Audiences: &testAudiences,
Claimer: mustClaimer(t, &Claims{
DisableRenewal: &defaultDisableRenewal,
}, globalProvisionerClaims),
policy: mustNewPolicyEngine(t, options),
}, false},
{"fail claimer", args{&JWK{}, &Claims{
MinTLSDur: mustDuration(t, "24h"),
MaxTLSDur: mustDuration(t, "2h"),
}, Config{
Claims: globalProvisionerClaims,
Audiences: testAudiences,
}, nil}, nil, true},
{"fail options", args{&JWK{}, &Claims{
DisableRenewal: &defaultDisableRenewal,
}, Config{
Claims: globalProvisionerClaims,
Audiences: testAudiences,
}, &Options{
X509: &X509Options{
AllowedNames: &policy.X509NameOptions{
DNSDomains: []string{"**.local"},
},
},
}}, nil, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := NewController(tt.args.p, tt.args.claims, tt.args.config)
got, err := NewController(tt.args.p, tt.args.claims, tt.args.config, tt.args.options)
if (err != nil) != tt.wantErr {
t.Errorf("NewController() error = %v, wantErr %v", err, tt.wantErr)
return

@ -14,11 +14,12 @@ import (
"time"
"github.com/pkg/errors"
"github.com/smallstep/certificates/authority/policy"
"github.com/smallstep/certificates/errs"
"go.step.sm/crypto/jose"
"go.step.sm/crypto/sshutil"
"go.step.sm/crypto/x509util"
"github.com/smallstep/certificates/errs"
)
// gcpCertsURL is the url that serves Google OAuth2 public keys.
@ -92,8 +93,6 @@ type GCP struct {
config *gcpConfig
keyStore *keyStore
ctl *Controller
x509Policy policy.X509Policy
sshHostPolicy policy.HostPolicy
}
// GetID returns the provisioner unique identifier. The name should uniquely
@ -214,18 +213,8 @@ func (p *GCP) Init(config Config) (err error) {
return
}
// Initialize the x509 allow/deny policy engine
if p.x509Policy, err = policy.NewX509PolicyEngine(p.Options.GetX509Options()); err != nil {
return err
}
// Initialize the SSH allow/deny policy engine for host certificates
if p.sshHostPolicy, err = policy.NewSSHHostPolicyEngine(p.Options.GetSSHOptions()); err != nil {
return err
}
config.Audiences = config.Audiences.WithFragment(p.GetIDForToken())
p.ctl, err = NewController(p, p.Claims, config)
p.ctl, err = NewController(p, p.Claims, config, p.Options)
return
}
@ -283,7 +272,7 @@ func (p *GCP) AuthorizeSign(ctx context.Context, token string) ([]SignOption, er
// validators
defaultPublicKeyValidator{},
newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()),
newX509NamePolicyValidator(p.x509Policy),
newX509NamePolicyValidator(p.ctl.GetPolicy().GetX509()),
), nil
}
@ -447,6 +436,6 @@ func (p *GCP) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption,
// Require all the fields in the SSH certificate
&sshCertDefaultValidator{},
// Ensure that all principal names are allowed
newSSHNamePolicyValidator(p.sshHostPolicy, nil),
newSSHNamePolicyValidator(p.ctl.GetPolicy().GetSSHHost(), nil),
), nil
}

@ -12,7 +12,6 @@ import (
"go.step.sm/crypto/sshutil"
"go.step.sm/crypto/x509util"
"github.com/smallstep/certificates/authority/policy"
"github.com/smallstep/certificates/errs"
)
@ -31,17 +30,14 @@ type stepPayload struct {
// signature requests.
type JWK struct {
*base
ID string `json:"-"`
Type string `json:"type"`
Name string `json:"name"`
Key *jose.JSONWebKey `json:"key"`
EncryptedKey string `json:"encryptedKey,omitempty"`
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
ctl *Controller
x509Policy policy.X509Policy
sshHostPolicy policy.HostPolicy
sshUserPolicy policy.UserPolicy
ID string `json:"-"`
Type string `json:"type"`
Name string `json:"name"`
Key *jose.JSONWebKey `json:"key"`
EncryptedKey string `json:"encryptedKey,omitempty"`
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
ctl *Controller
}
// GetID returns the provisioner unique identifier. The name and credential id
@ -103,22 +99,7 @@ func (p *JWK) Init(config Config) (err error) {
return errors.New("provisioner key cannot be empty")
}
// Initialize the x509 allow/deny policy engine
if p.x509Policy, err = policy.NewX509PolicyEngine(p.Options.GetX509Options()); err != nil {
return err
}
// Initialize the SSH allow/deny policy engine for user certificates
if p.sshUserPolicy, err = policy.NewSSHUserPolicyEngine(p.Options.GetSSHOptions()); err != nil {
return err
}
// Initialize the SSH allow/deny policy engine for host certificates
if p.sshHostPolicy, err = policy.NewSSHHostPolicyEngine(p.Options.GetSSHOptions()); err != nil {
return err
}
p.ctl, err = NewController(p, p.Claims, config)
p.ctl, err = NewController(p, p.Claims, config, p.Options)
return
}
@ -202,7 +183,7 @@ func (p *JWK) AuthorizeSign(ctx context.Context, token string) ([]SignOption, er
defaultPublicKeyValidator{},
defaultSANsValidator(claims.SANs),
newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()),
newX509NamePolicyValidator(p.x509Policy),
newX509NamePolicyValidator(p.ctl.GetPolicy().GetX509()),
}, nil
}
@ -285,7 +266,7 @@ func (p *JWK) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption,
// Require and validate all the default fields in the SSH certificate.
&sshCertDefaultValidator{},
// Ensure that all principal names are allowed
newSSHNamePolicyValidator(p.sshHostPolicy, p.sshUserPolicy),
newSSHNamePolicyValidator(p.ctl.GetPolicy().GetSSHHost(), p.ctl.GetPolicy().GetSSHUser()),
), nil
}

@ -16,7 +16,6 @@ import (
"go.step.sm/crypto/sshutil"
"go.step.sm/crypto/x509util"
"github.com/smallstep/certificates/authority/policy"
"github.com/smallstep/certificates/errs"
)
@ -52,11 +51,8 @@ type K8sSA struct {
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
//kauthn kauthn.AuthenticationV1Interface
pubKeys []interface{}
ctl *Controller
x509Policy policy.X509Policy
sshHostPolicy policy.HostPolicy
sshUserPolicy policy.UserPolicy
pubKeys []interface{}
ctl *Controller
}
// GetID returns the provisioner unique identifier. The name and credential id
@ -144,22 +140,7 @@ func (p *K8sSA) Init(config Config) (err error) {
p.kauthn = k8s.AuthenticationV1()
*/
// Initialize the x509 allow/deny policy engine
if p.x509Policy, err = policy.NewX509PolicyEngine(p.Options.GetX509Options()); err != nil {
return err
}
// Initialize the SSH allow/deny policy engine for user certificates
if p.sshUserPolicy, err = policy.NewSSHUserPolicyEngine(p.Options.GetSSHOptions()); err != nil {
return err
}
// Initialize the SSH allow/deny policy engine for host certificates
if p.sshHostPolicy, err = policy.NewSSHHostPolicyEngine(p.Options.GetSSHOptions()); err != nil {
return err
}
p.ctl, err = NewController(p, p.Claims, config)
p.ctl, err = NewController(p, p.Claims, config, p.Options)
return
}
@ -261,7 +242,7 @@ func (p *K8sSA) AuthorizeSign(ctx context.Context, token string) ([]SignOption,
// validators
defaultPublicKeyValidator{},
newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()),
newX509NamePolicyValidator(p.x509Policy),
newX509NamePolicyValidator(p.ctl.GetPolicy().GetX509()),
}, nil
}
@ -305,7 +286,7 @@ func (p *K8sSA) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOptio
// Require and validate all the default fields in the SSH certificate.
&sshCertDefaultValidator{},
// Ensure that all principal names are allowed
newSSHNamePolicyValidator(p.sshHostPolicy, p.sshUserPolicy),
newSSHNamePolicyValidator(p.ctl.GetPolicy().GetSSHHost(), p.ctl.GetPolicy().GetSSHUser()),
), nil
}

@ -10,13 +10,14 @@ import (
"github.com/pkg/errors"
nebula "github.com/slackhq/nebula/cert"
"github.com/smallstep/certificates/authority/policy"
"github.com/smallstep/certificates/errs"
"go.step.sm/crypto/jose"
"go.step.sm/crypto/sshutil"
"go.step.sm/crypto/x25519"
"go.step.sm/crypto/x509util"
"golang.org/x/crypto/ssh"
"github.com/smallstep/certificates/errs"
)
const (
@ -35,16 +36,14 @@ const (
// https://signal.org/docs/specifications/xeddsa/#xeddsa and implemented by
// go.step.sm/crypto/x25519.
type Nebula struct {
ID string `json:"-"`
Type string `json:"type"`
Name string `json:"name"`
Roots []byte `json:"roots"`
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
caPool *nebula.NebulaCAPool
ctl *Controller
x509Policy policy.X509Policy
sshHostPolicy policy.HostPolicy
ID string `json:"-"`
Type string `json:"type"`
Name string `json:"name"`
Roots []byte `json:"roots"`
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
caPool *nebula.NebulaCAPool
ctl *Controller
}
// Init verifies and initializes the Nebula provisioner.
@ -63,18 +62,8 @@ func (p *Nebula) Init(config Config) (err error) {
return errs.InternalServer("failed to create ca pool: %v", err)
}
// Initialize the x509 allow/deny policy engine
if p.x509Policy, err = policy.NewX509PolicyEngine(p.Options.GetX509Options()); err != nil {
return err
}
// Initialize the SSH allow/deny policy engine for host certificates
if p.sshHostPolicy, err = policy.NewSSHHostPolicyEngine(p.Options.GetSSHOptions()); err != nil {
return err
}
config.Audiences = config.Audiences.WithFragment(p.GetIDForToken())
p.ctl, err = NewController(p, p.Claims, config)
p.ctl, err = NewController(p, p.Claims, config, p.Options)
return
}
@ -174,7 +163,7 @@ func (p *Nebula) AuthorizeSign(ctx context.Context, token string) ([]SignOption,
},
defaultPublicKeyValidator{},
newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()),
newX509NamePolicyValidator(p.x509Policy),
newX509NamePolicyValidator(p.ctl.GetPolicy().GetX509()),
}, nil
}
@ -271,7 +260,7 @@ func (p *Nebula) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOpti
// Require all the fields in the SSH certificate
&sshCertDefaultValidator{},
// Ensure that all principal names are allowed
newSSHNamePolicyValidator(p.sshHostPolicy, nil),
newSSHNamePolicyValidator(p.ctl.GetPolicy().GetSSHHost(), nil),
), nil
}

@ -17,7 +17,6 @@ import (
"go.step.sm/crypto/sshutil"
"go.step.sm/crypto/x509util"
"github.com/smallstep/certificates/authority/policy"
"github.com/smallstep/certificates/errs"
)
@ -96,9 +95,6 @@ type OIDC struct {
configuration openIDConfiguration
keyStore *keyStore
ctl *Controller
x509Policy policy.X509Policy
sshHostPolicy policy.HostPolicy
sshUserPolicy policy.UserPolicy
}
func sanitizeEmail(email string) string {
@ -201,22 +197,7 @@ func (o *OIDC) Init(config Config) (err error) {
return err
}
// Initialize the x509 allow/deny policy engine
if o.x509Policy, err = policy.NewX509PolicyEngine(o.Options.GetX509Options()); err != nil {
return err
}
// Initialize the SSH allow/deny policy engine for user certificates
if o.sshUserPolicy, err = policy.NewSSHUserPolicyEngine(o.Options.GetSSHOptions()); err != nil {
return err
}
// Initialize the SSH allow/deny policy engine for host certificates
if o.sshHostPolicy, err = policy.NewSSHHostPolicyEngine(o.Options.GetSSHOptions()); err != nil {
return err
}
o.ctl, err = NewController(o, o.Claims, config)
o.ctl, err = NewController(o, o.Claims, config, o.Options)
return
}
@ -374,7 +355,7 @@ func (o *OIDC) AuthorizeSign(ctx context.Context, token string) ([]SignOption, e
// validators
defaultPublicKeyValidator{},
newValidityValidator(o.ctl.Claimer.MinTLSCertDuration(), o.ctl.Claimer.MaxTLSCertDuration()),
newX509NamePolicyValidator(o.x509Policy),
newX509NamePolicyValidator(o.ctl.GetPolicy().GetX509()),
}, nil
}
@ -462,7 +443,7 @@ func (o *OIDC) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption
// Require all the fields in the SSH certificate
&sshCertDefaultValidator{},
// Ensure that all principal names are allowed
newSSHNamePolicyValidator(o.sshHostPolicy, o.sshUserPolicy),
newSSHNamePolicyValidator(o.ctl.GetPolicy().GetSSHHost(), o.ctl.GetPolicy().GetSSHUser()),
), nil
}

@ -0,0 +1,65 @@
package provisioner
import "github.com/smallstep/certificates/authority/policy"
type policyEngine struct {
x509Policy policy.X509Policy
sshHostPolicy policy.HostPolicy
sshUserPolicy policy.UserPolicy
}
func newPolicyEngine(options *Options) (*policyEngine, error) {
if options == nil {
return nil, nil
}
var (
x509Policy policy.X509Policy
sshHostPolicy policy.HostPolicy
sshUserPolicy policy.UserPolicy
err error
)
// Initialize the x509 allow/deny policy engine
if x509Policy, err = policy.NewX509PolicyEngine(options.GetX509Options()); err != nil {
return nil, err
}
// Initialize the SSH allow/deny policy engine for host certificates
if sshHostPolicy, err = policy.NewSSHHostPolicyEngine(options.GetSSHOptions()); err != nil {
return nil, err
}
// Initialize the SSH allow/deny policy engine for user certificates
if sshUserPolicy, err = policy.NewSSHUserPolicyEngine(options.GetSSHOptions()); err != nil {
return nil, err
}
return &policyEngine{
x509Policy: x509Policy,
sshHostPolicy: sshHostPolicy,
sshUserPolicy: sshUserPolicy,
}, nil
}
func (p *policyEngine) GetX509() policy.X509Policy {
if p == nil {
return nil
}
return p.x509Policy
}
func (p *policyEngine) GetSSHHost() policy.HostPolicy {
if p == nil {
return nil
}
return p.sshHostPolicy
}
func (p *policyEngine) GetSSHUser() policy.UserPolicy {
if p == nil {
return nil
}
return p.sshUserPolicy
}

@ -5,8 +5,6 @@ import (
"time"
"github.com/pkg/errors"
"github.com/smallstep/certificates/authority/policy"
)
// SCEP is the SCEP provisioner type, an entity that can authorize the
@ -36,7 +34,6 @@ type SCEP struct {
ctl *Controller
secretChallengePassword string
encryptionAlgorithm int
x509Policy policy.X509Policy
}
// GetID returns the provisioner unique identifier.
@ -113,12 +110,7 @@ func (s *SCEP) Init(config Config) (err error) {
// TODO: add other, SCEP specific, options?
// Initialize the x509 allow/deny policy engine
if s.x509Policy, err = policy.NewX509PolicyEngine(s.Options.GetX509Options()); err != nil {
return err
}
s.ctl, err = NewController(s, s.Claims, config)
s.ctl, err = NewController(s, s.Claims, config, s.Options)
return
}
@ -135,7 +127,7 @@ func (s *SCEP) AuthorizeSign(ctx context.Context, token string) ([]SignOption, e
// validators
newPublicKeyMinimumLengthValidator(s.MinimumPublicKeyLength),
newValidityValidator(s.ctl.Claimer.MinTLSCertDuration(), s.ctl.Claimer.MaxTLSCertDuration()),
newX509NamePolicyValidator(s.x509Policy),
newX509NamePolicyValidator(s.ctl.GetPolicy().GetX509()),
}, nil
}

@ -8,9 +8,11 @@ import (
"time"
"github.com/pkg/errors"
"github.com/smallstep/certificates/errs"
"go.step.sm/crypto/jose"
"golang.org/x/crypto/ssh"
"go.step.sm/crypto/jose"
"github.com/smallstep/certificates/errs"
)
// sshPOPPayload extends jwt.Claims with step attributes.
@ -92,12 +94,10 @@ func (p *SSHPOP) Init(config Config) (err error) {
return errors.New("provisioner public SSH validation keys cannot be empty")
}
// TODO(hs): initialize the policy engine and add it as an SSH cert validator
p.sshPubKeys = config.SSHKeys
config.Audiences = config.Audiences.WithFragment(p.GetIDForToken())
p.ctl, err = NewController(p, p.Claims, config)
p.ctl, err = NewController(p, p.Claims, config, nil)
return
}

@ -184,7 +184,7 @@ func generateJWK() (*JWK, error) {
}
p.ctl, err = NewController(p, p.Claims, Config{
Audiences: testAudiences,
})
}, nil)
return p, err
}
@ -219,7 +219,7 @@ func generateK8sSA(inputPubKey interface{}) (*K8sSA, error) {
}
p.ctl, err = NewController(p, p.Claims, Config{
Audiences: testAudiences,
})
}, nil)
return p, err
}
@ -256,7 +256,7 @@ func generateSSHPOP() (*SSHPOP, error) {
}
p.ctl, err = NewController(p, p.Claims, Config{
Audiences: testAudiences,
})
}, nil)
return p, err
}
@ -305,7 +305,7 @@ M46l92gdOozT
}
p.ctl, err = NewController(p, p.Claims, Config{
Audiences: testAudiences,
})
}, nil)
return p, err
}
@ -343,7 +343,7 @@ func generateOIDC() (*OIDC, error) {
}
p.ctl, err = NewController(p, p.Claims, Config{
Audiences: testAudiences,
})
}, nil)
return p, err
}
@ -373,7 +373,7 @@ func generateGCP() (*GCP, error) {
}
p.ctl, err = NewController(p, p.Claims, Config{
Audiences: testAudiences.WithFragment("gcp/" + name),
})
}, nil)
return p, err
}
@ -411,7 +411,7 @@ func generateAWS() (*AWS, error) {
}
p.ctl, err = NewController(p, p.Claims, Config{
Audiences: testAudiences.WithFragment("aws/" + name),
})
}, nil)
return p, err
}
@ -518,7 +518,7 @@ func generateAWSV1Only() (*AWS, error) {
}
p.ctl, err = NewController(p, p.Claims, Config{
Audiences: testAudiences.WithFragment("aws/" + name),
})
}, nil)
return p, err
}
@ -608,7 +608,7 @@ func generateAzure() (*Azure, error) {
}
p.ctl, err = NewController(p, p.Claims, Config{
Audiences: testAudiences,
})
}, nil)
return p, err
}

@ -8,11 +8,12 @@ import (
"time"
"github.com/pkg/errors"
"github.com/smallstep/certificates/authority/policy"
"github.com/smallstep/certificates/errs"
"go.step.sm/crypto/jose"
"go.step.sm/crypto/sshutil"
"go.step.sm/crypto/x509util"
"github.com/smallstep/certificates/errs"
)
// x5cPayload extends jwt.Claims with step attributes.
@ -27,17 +28,14 @@ type x5cPayload struct {
// signature requests.
type X5C struct {
*base
ID string `json:"-"`
Type string `json:"type"`
Name string `json:"name"`
Roots []byte `json:"roots"`
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
ctl *Controller
rootPool *x509.CertPool
x509Policy policy.X509Policy
sshHostPolicy policy.HostPolicy
sshUserPolicy policy.UserPolicy
ID string `json:"-"`
Type string `json:"type"`
Name string `json:"name"`
Roots []byte `json:"roots"`
Claims *Claims `json:"claims,omitempty"`
Options *Options `json:"options,omitempty"`
ctl *Controller
rootPool *x509.CertPool
}
// GetID returns the provisioner unique identifier. The name and credential id
@ -124,23 +122,8 @@ func (p *X5C) Init(config Config) (err error) {
return errors.Errorf("no x509 certificates found in roots attribute for provisioner '%s'", p.GetName())
}
// Initialize the x509 allow/deny policy engine
if p.x509Policy, err = policy.NewX509PolicyEngine(p.Options.GetX509Options()); err != nil {
return err
}
// Initialize the SSH allow/deny policy engine for user certificates
if p.sshUserPolicy, err = policy.NewSSHUserPolicyEngine(p.Options.GetSSHOptions()); err != nil {
return err
}
// Initialize the SSH allow/deny policy engine for host certificates
if p.sshHostPolicy, err = policy.NewSSHHostPolicyEngine(p.Options.GetSSHOptions()); err != nil {
return err
}
config.Audiences = config.Audiences.WithFragment(p.GetIDForToken())
p.ctl, err = NewController(p, p.Claims, config)
p.ctl, err = NewController(p, p.Claims, config, p.Options)
return
}
@ -252,7 +235,7 @@ func (p *X5C) AuthorizeSign(ctx context.Context, token string) ([]SignOption, er
defaultSANsValidator(claims.SANs),
defaultPublicKeyValidator{},
newValidityValidator(p.ctl.Claimer.MinTLSCertDuration(), p.ctl.Claimer.MaxTLSCertDuration()),
newX509NamePolicyValidator(p.x509Policy),
newX509NamePolicyValidator(p.ctl.GetPolicy().GetX509()),
}, nil
}
@ -338,6 +321,6 @@ func (p *X5C) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption,
// Require all the fields in the SSH certificate
&sshCertDefaultValidator{},
// Ensure that all principal names are allowed
newSSHNamePolicyValidator(p.sshHostPolicy, p.sshUserPolicy),
newSSHNamePolicyValidator(p.ctl.GetPolicy().GetSSHHost(), p.ctl.GetPolicy().GetSSHUser()),
), nil
}

Loading…
Cancel
Save