Add additional policy options

This commit is contained in:
Herman Slatman 2022-04-19 10:24:52 +02:00
parent def9438ad6
commit 7f9034d22a
No known key found for this signature in database
GPG key ID: F4D8A44EA0A75A4F
6 changed files with 112 additions and 23 deletions

View file

@ -81,6 +81,20 @@ func (p *Policy) GetDeniedNameOptions() *policy.X509NameOptions {
}
}
// IsWildcardLiteralAllowed returns true by default for
// ACME account policies, as authorization is performed on DNS
// level.
func (p *Policy) IsWildcardLiteralAllowed() bool {
return true
}
// ShouldVerifySubjectCommonName returns true by default
// for ACME account policies, as this is embedded in the
// protocol.
func (p *Policy) ShouldVerifySubjectCommonName() bool {
return true
}
// ExternalAccountKey is an ACME External Account Binding key.
type ExternalAccountKey struct {
ID string `json:"id"`

View file

@ -2,9 +2,11 @@ package api
import (
"errors"
"fmt"
"net/http"
"go.step.sm/linkedca"
"google.golang.org/protobuf/types/known/wrapperspb"
"github.com/smallstep/certificates/acme"
"github.com/smallstep/certificates/api/read"
@ -85,6 +87,10 @@ func (par *PolicyAdminResponder) CreateAuthorityPolicy(w http.ResponseWriter, r
return
}
fmt.Println("before: ", newPolicy)
applyDefaults(newPolicy)
fmt.Println("after: ", newPolicy)
adm := linkedca.AdminFromContext(ctx)
var createdPolicy *linkedca.Policy
@ -202,6 +208,8 @@ func (par *PolicyAdminResponder) CreateProvisionerPolicy(w http.ResponseWriter,
return
}
applyDefaults(newPolicy)
prov.Policy = newPolicy
if err := par.auth.UpdateProvisioner(ctx, prov); err != nil {
@ -366,3 +374,13 @@ func (par *PolicyAdminResponder) DeleteACMEAccountPolicy(w http.ResponseWriter,
render.JSONStatus(w, DeleteResponse{Status: "ok"}, http.StatusOK)
}
func applyDefaults(p *linkedca.Policy) {
if p.GetX509() == nil {
return
}
if p.GetX509().VerifySubjectCommonName == nil {
p.X509.VerifySubjectCommonName = &wrapperspb.BoolValue{Value: true}
}
return
}

View file

@ -30,6 +30,8 @@ func (o *Options) GetSSHOptions() *SSHPolicyOptions {
type X509PolicyOptionsInterface interface {
GetAllowedNameOptions() *X509NameOptions
GetDeniedNameOptions() *X509NameOptions
IsWildcardLiteralAllowed() bool
ShouldVerifySubjectCommonName() bool
}
// X509PolicyOptions is a container for x509 allowed and denied
@ -39,6 +41,13 @@ type X509PolicyOptions struct {
AllowedNames *X509NameOptions `json:"allow,omitempty"`
// DeniedNames contains the x509 denied names
DeniedNames *X509NameOptions `json:"deny,omitempty"`
// AllowWildcardLiteral indicates if literal wildcard names
// such as *.example.com and @example.com are allowed. Defaults
// to false.
AllowWildcardLiteral *bool `json:"allow_wildcard_literal,omitempty"`
// VerifySubjectCommonName indicates if the Subject Common Name
// is verified in addition to the SANs. Defaults to true.
VerifySubjectCommonName *bool `json:"verify_subject_common_name,omitempty"`
}
// X509NameOptions models the X509 name policy configuration.
@ -58,6 +67,43 @@ func (o *X509NameOptions) HasNames() bool {
len(o.URIDomains) > 0
}
// GetDeniedNameOptions returns the x509 denied name policy configuration
func (o *X509PolicyOptions) GetDeniedNameOptions() *X509NameOptions {
if o == nil {
return nil
}
return o.DeniedNames
}
// GetAllowedUserNameOptions returns the SSH allowed user name policy
// configuration.
func (o *SSHPolicyOptions) GetAllowedUserNameOptions() *SSHNameOptions {
if o == nil {
return nil
}
if o.User == nil {
return nil
}
return o.User.AllowedNames
}
func (o *X509PolicyOptions) IsWildcardLiteralAllowed() bool {
if o == nil {
return true
}
return o.AllowWildcardLiteral != nil && *o.AllowWildcardLiteral
}
func (o *X509PolicyOptions) ShouldVerifySubjectCommonName() bool {
if o == nil {
return false
}
if o.VerifySubjectCommonName == nil {
return true
}
return *o.VerifySubjectCommonName
}
// SSHPolicyOptionsInterface is an interface for providers of
// SSH user and host name policy configuration.
type SSHPolicyOptionsInterface interface {
@ -84,26 +130,6 @@ func (o *X509PolicyOptions) GetAllowedNameOptions() *X509NameOptions {
return o.AllowedNames
}
// GetDeniedNameOptions returns the x509 denied name policy configuration
func (o *X509PolicyOptions) GetDeniedNameOptions() *X509NameOptions {
if o == nil {
return nil
}
return o.DeniedNames
}
// GetAllowedUserNameOptions returns the SSH allowed user name policy
// configuration.
func (o *SSHPolicyOptions) GetAllowedUserNameOptions() *SSHNameOptions {
if o == nil {
return nil
}
if o.User == nil {
return nil
}
return o.User.AllowedNames
}
// GetDeniedUserNameOptions returns the SSH denied user name policy
// configuration.
func (o *SSHPolicyOptions) GetDeniedUserNameOptions() *SSHNameOptions {

View file

@ -50,8 +50,13 @@ func NewX509PolicyEngine(policyOptions X509PolicyOptionsInterface) (X509Policy,
return nil, nil
}
// enable x509 Subject Common Name validation by default
if policyOptions.ShouldVerifySubjectCommonName() {
options = append(options, policy.WithSubjectCommonNameVerification())
}
if policyOptions.IsWildcardLiteralAllowed() {
options = append(options, policy.WithAllowLiteralWildcardNames())
}
return policy.New(options...)
}

View file

@ -65,6 +65,14 @@ type X509Options struct {
// DeniedNames contains the SANs the provisioner is not authorized to sign
DeniedNames *policy.X509NameOptions `json:"-"`
// AllowWildcardLiteral indicates if literal wildcard names
// such as *.example.com and @example.com are allowed. Defaults
// to false.
AllowWildcardLiteral *bool `json:"-"`
// VerifySubjectCommonName indicates if the Subject Common Name
// is verified in addition to the SANs. Defaults to true.
VerifySubjectCommonName *bool `json:"-"`
}
// HasTemplate returns true if a template is defined in the provisioner options.
@ -90,6 +98,23 @@ func (o *X509Options) GetDeniedNameOptions() *policy.X509NameOptions {
return o.DeniedNames
}
func (o *X509Options) IsWildcardLiteralAllowed() bool {
if o == nil {
return true
}
return o.AllowWildcardLiteral != nil && *o.AllowWildcardLiteral
}
func (o *X509Options) ShouldVerifySubjectCommonName() bool {
if o == nil {
return false
}
if o.VerifySubjectCommonName == nil {
return true
}
return *o.VerifySubjectCommonName
}
// TemplateOptions generates a CertificateOptions with the template and data
// defined in the ProvisionerOptions, the provisioner generated data, and the
// user data provided in the request. If no template has been provided,

3
go.mod
View file

@ -20,6 +20,7 @@ require (
github.com/go-kit/kit v0.10.0 // indirect
github.com/go-piv/piv-go v1.7.0
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.2
github.com/google/go-cmp v0.5.7
github.com/google/uuid v1.3.0
github.com/googleapis/gax-go/v2 v2.1.1
@ -52,4 +53,4 @@ require (
// replace github.com/smallstep/nosql => ../nosql
// replace go.step.sm/crypto => ../crypto
// replace go.step.sm/cli-utils => ../cli-utils
// replace go.step.sm/linkedca => ../linkedca
replace go.step.sm/linkedca => ../linkedca