forked from TrueCloudLab/certificates
Contain policy engines inside provisioner Controller
This commit is contained in:
parent
ef110a94df
commit
c40a4d2694
16 changed files with 232 additions and 228 deletions
|
@ -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,8 +229,11 @@ func (a *Authority) reloadPolicyEngines(ctx context.Context) error {
|
|||
|
||||
linkedPolicy, err := a.adminDB.GetAuthorityPolicy(ctx)
|
||||
if err != nil {
|
||||
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 {
|
||||
policyOptions = a.config.AuthorityConfig.Policy
|
||||
|
|
|
@ -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
|
||||
|
@ -29,7 +27,6 @@ type ACME struct {
|
|||
Options *Options `json:"options,omitempty"`
|
||||
|
||||
ctl *Controller
|
||||
x509Policy policy.X509Policy
|
||||
}
|
||||
|
||||
// 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
|
||||
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"
|
||||
)
|
||||
|
||||
|
@ -39,9 +38,6 @@ type JWK struct {
|
|||
Claims *Claims `json:"claims,omitempty"`
|
||||
Options *Options `json:"options,omitempty"`
|
||||
ctl *Controller
|
||||
x509Policy policy.X509Policy
|
||||
sshHostPolicy policy.HostPolicy
|
||||
sshUserPolicy policy.UserPolicy
|
||||
}
|
||||
|
||||
// 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"
|
||||
)
|
||||
|
||||
|
@ -54,9 +53,6 @@ type K8sSA struct {
|
|||
//kauthn kauthn.AuthenticationV1Interface
|
||||
pubKeys []interface{}
|
||||
ctl *Controller
|
||||
x509Policy policy.X509Policy
|
||||
sshHostPolicy policy.HostPolicy
|
||||
sshUserPolicy policy.UserPolicy
|
||||
}
|
||||
|
||||
// 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 (
|
||||
|
@ -43,8 +44,6 @@ type Nebula struct {
|
|||
Options *Options `json:"options,omitempty"`
|
||||
caPool *nebula.NebulaCAPool
|
||||
ctl *Controller
|
||||
x509Policy policy.X509Policy
|
||||
sshHostPolicy policy.HostPolicy
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
|
|
65
authority/provisioner/policy.go
Normal file
65
authority/provisioner/policy.go
Normal file
|
@ -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.
|
||||
|
@ -35,9 +36,6 @@ type X5C struct {
|
|||
Options *Options `json:"options,omitempty"`
|
||||
ctl *Controller
|
||||
rootPool *x509.CertPool
|
||||
x509Policy policy.X509Policy
|
||||
sshHostPolicy policy.HostPolicy
|
||||
sshUserPolicy policy.UserPolicy
|
||||
}
|
||||
|
||||
// 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…
Reference in a new issue