Update AllowWildcardNames configuration name

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

@ -53,8 +53,9 @@ type PolicyNames struct {
// X509Policy contains ACME account level X.509 policy // X509Policy contains ACME account level X.509 policy
type X509Policy struct { type X509Policy struct {
Allowed PolicyNames `json:"allow"` Allowed PolicyNames `json:"allow"`
Denied PolicyNames `json:"deny"` Denied PolicyNames `json:"deny"`
AllowWildcardNames bool `json:"allowWildcardNames"`
} }
// Policy is an ACME Account level policy // Policy is an ACME Account level policy
@ -81,18 +82,14 @@ func (p *Policy) GetDeniedNameOptions() *policy.X509NameOptions {
} }
} }
// IsWildcardLiteralAllowed returns true by default for // AreWildcardNamesAllowed returns if wildcard names
// ACME account policies, as authorization is performed on DNS // like *.example.com are allowed to be signed.
// level. // Defaults to false.
func (p *Policy) IsWildcardLiteralAllowed() bool { func (p *Policy) AreWildcardNamesAllowed() bool {
return true if p == nil {
} return false
}
// ShouldVerifySubjectCommonName returns true by default return p.X509.AllowWildcardNames
// for ACME account policies, as this is embedded in the
// protocol.
func (p *Policy) ShouldVerifyCommonName() bool {
return true
} }
// ExternalAccountKey is an ACME External Account Binding key. // ExternalAccountKey is an ACME External Account Binding key.

@ -109,6 +109,7 @@ func eakToLinked(k *acme.ExternalAccountKey) *linkedca.EABKey {
eak.Policy.X509.Allow.Ips = k.Policy.X509.Allowed.IPRanges eak.Policy.X509.Allow.Ips = k.Policy.X509.Allowed.IPRanges
eak.Policy.X509.Deny.Dns = k.Policy.X509.Denied.DNSNames eak.Policy.X509.Deny.Dns = k.Policy.X509.Denied.DNSNames
eak.Policy.X509.Deny.Ips = k.Policy.X509.Denied.IPRanges eak.Policy.X509.Deny.Ips = k.Policy.X509.Denied.IPRanges
eak.Policy.X509.AllowWildcardNames = k.Policy.X509.AllowWildcardNames
} }
return eak return eak
@ -143,6 +144,7 @@ func linkedEAKToCertificates(k *linkedca.EABKey) *acme.ExternalAccountKey {
eak.Policy.X509.Denied.DNSNames = deny.Dns eak.Policy.X509.Denied.DNSNames = deny.Dns
eak.Policy.X509.Denied.IPRanges = deny.Ips eak.Policy.X509.Denied.IPRanges = deny.Ips
} }
eak.Policy.X509.AllowWildcardNames = x509.AllowWildcardNames
} }
} }

@ -512,6 +512,7 @@ func Test_linkedEAKToCertificates(t *testing.T) {
Dns: []string{"badhost.local"}, Dns: []string{"badhost.local"},
Ips: []string{"10.0.0.30"}, Ips: []string{"10.0.0.30"},
}, },
AllowWildcardNames: true,
}, },
}, },
}, },
@ -533,6 +534,7 @@ func Test_linkedEAKToCertificates(t *testing.T) {
DNSNames: []string{"badhost.local"}, DNSNames: []string{"badhost.local"},
IPRanges: []string{"10.0.0.30"}, IPRanges: []string{"10.0.0.30"},
}, },
AllowWildcardNames: true,
}, },
}, },
}, },

@ -311,7 +311,7 @@ func policyToCertificates(p *linkedca.Policy) *authPolicy.Options {
} }
} }
opts.X509.AllowWildcardLiteral = x509.AllowWildcardLiteral opts.X509.AllowWildcardNames = x509.GetAllowWildcardNames()
} }
// fill ssh policy configuration // fill ssh policy configuration

@ -30,7 +30,7 @@ func (o *Options) GetSSHOptions() *SSHPolicyOptions {
type X509PolicyOptionsInterface interface { type X509PolicyOptionsInterface interface {
GetAllowedNameOptions() *X509NameOptions GetAllowedNameOptions() *X509NameOptions
GetDeniedNameOptions() *X509NameOptions GetDeniedNameOptions() *X509NameOptions
IsWildcardLiteralAllowed() bool AreWildcardNamesAllowed() bool
} }
// X509PolicyOptions is a container for x509 allowed and denied // X509PolicyOptions is a container for x509 allowed and denied
@ -42,10 +42,9 @@ type X509PolicyOptions struct {
// DeniedNames contains the x509 denied names // DeniedNames contains the x509 denied names
DeniedNames *X509NameOptions `json:"deny,omitempty"` DeniedNames *X509NameOptions `json:"deny,omitempty"`
// AllowWildcardLiteral indicates if literal wildcard names // AllowWildcardNames indicates if literal wildcard names
// such as *.example.com and @example.com are allowed. Defaults // like *.example.com are allowed. Defaults to false.
// to false. AllowWildcardNames bool `json:"allowWildcardNames,omitempty"`
AllowWildcardLiteral bool `json:"allowWildcardLiteral,omitempty"`
} }
// X509NameOptions models the X509 name policy configuration. // X509NameOptions models the X509 name policy configuration.
@ -83,13 +82,13 @@ func (o *X509PolicyOptions) GetDeniedNameOptions() *X509NameOptions {
return o.DeniedNames return o.DeniedNames
} }
// IsWildcardLiteralAllowed returns whether the authority allows // AreWildcardNamesAllowed returns whether the authority allows
// literal wildcard domains and other names to be signed. // literal wildcard names to be signed.
func (o *X509PolicyOptions) IsWildcardLiteralAllowed() bool { func (o *X509PolicyOptions) AreWildcardNamesAllowed() bool {
if o == nil { if o == nil {
return true return true
} }
return o.AllowWildcardLiteral return o.AllowWildcardNames
} }
// SSHPolicyOptionsInterface is an interface for providers of // SSHPolicyOptionsInterface is an interface for providers of

@ -23,21 +23,21 @@ func TestX509PolicyOptions_IsWildcardLiteralAllowed(t *testing.T) {
{ {
name: "set-true", name: "set-true",
options: &X509PolicyOptions{ options: &X509PolicyOptions{
AllowWildcardLiteral: true, AllowWildcardNames: true,
}, },
want: true, want: true,
}, },
{ {
name: "set-false", name: "set-false",
options: &X509PolicyOptions{ options: &X509PolicyOptions{
AllowWildcardLiteral: false, AllowWildcardNames: false,
}, },
want: false, want: false,
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := tt.options.IsWildcardLiteralAllowed(); got != tt.want { if got := tt.options.AreWildcardNamesAllowed(); got != tt.want {
t.Errorf("X509PolicyOptions.IsWildcardLiteralAllowed() = %v, want %v", got, tt.want) t.Errorf("X509PolicyOptions.IsWildcardLiteralAllowed() = %v, want %v", got, tt.want)
} }
}) })

@ -52,7 +52,7 @@ func NewX509PolicyEngine(policyOptions X509PolicyOptionsInterface) (X509Policy,
return nil, nil return nil, nil
} }
if policyOptions.IsWildcardLiteralAllowed() { if policyOptions.AreWildcardNamesAllowed() {
options = append(options, policy.WithAllowLiteralWildcardNames()) options = append(options, policy.WithAllowLiteralWildcardNames())
} }

@ -218,7 +218,7 @@ func Test_policyToCertificates(t *testing.T) {
Allow: &linkedca.X509Names{ Allow: &linkedca.X509Names{
Dns: []string{"*.local"}, Dns: []string{"*.local"},
}, },
AllowWildcardLiteral: false, AllowWildcardNames: false,
}, },
}, },
want: &policy.Options{ want: &policy.Options{
@ -226,7 +226,7 @@ func Test_policyToCertificates(t *testing.T) {
AllowedNames: &policy.X509NameOptions{ AllowedNames: &policy.X509NameOptions{
DNSDomains: []string{"*.local"}, DNSDomains: []string{"*.local"},
}, },
AllowWildcardLiteral: false, AllowWildcardNames: false,
}, },
}, },
}, },
@ -248,7 +248,7 @@ func Test_policyToCertificates(t *testing.T) {
Uris: []string{"https://badhost.local"}, Uris: []string{"https://badhost.local"},
CommonNames: []string{"another name"}, CommonNames: []string{"another name"},
}, },
AllowWildcardLiteral: true, AllowWildcardNames: true,
}, },
Ssh: &linkedca.SSHPolicy{ Ssh: &linkedca.SSHPolicy{
Host: &linkedca.SSHHostPolicy{ Host: &linkedca.SSHHostPolicy{
@ -291,7 +291,7 @@ func Test_policyToCertificates(t *testing.T) {
URIDomains: []string{"https://badhost.local"}, URIDomains: []string{"https://badhost.local"},
CommonNames: []string{"another name"}, CommonNames: []string{"another name"},
}, },
AllowWildcardLiteral: true, AllowWildcardNames: true,
}, },
SSH: &policy.SSHPolicyOptions{ SSH: &policy.SSHPolicyOptions{
Host: &policy.SSHHostCertificateOptions{ Host: &policy.SSHHostCertificateOptions{
@ -369,7 +369,7 @@ func TestAuthority_reloadPolicyEngines(t *testing.T) {
DeniedNames: &policy.X509NameOptions{ DeniedNames: &policy.X509NameOptions{
DNSDomains: []string{"badhost.local"}, DNSDomains: []string{"badhost.local"},
}, },
AllowWildcardLiteral: true, AllowWildcardNames: true,
}, },
} }
@ -428,7 +428,7 @@ func TestAuthority_reloadPolicyEngines(t *testing.T) {
DeniedNames: &policy.X509NameOptions{ DeniedNames: &policy.X509NameOptions{
DNSDomains: []string{"badhost.local"}, DNSDomains: []string{"badhost.local"},
}, },
AllowWildcardLiteral: true, AllowWildcardNames: true,
}, },
SSH: &policy.SSHPolicyOptions{ SSH: &policy.SSHPolicyOptions{
Host: &policy.SSHHostCertificateOptions{ Host: &policy.SSHHostCertificateOptions{
@ -486,7 +486,7 @@ func TestAuthority_reloadPolicyEngines(t *testing.T) {
DeniedNames: &policy.X509NameOptions{ DeniedNames: &policy.X509NameOptions{
DNSDomains: []string{"badhost.local"}, DNSDomains: []string{"badhost.local"},
}, },
AllowWildcardLiteral: true, AllowWildcardNames: true,
}, },
SSH: &policy.SSHPolicyOptions{ SSH: &policy.SSHPolicyOptions{
Host: &policy.SSHHostCertificateOptions{ Host: &policy.SSHHostCertificateOptions{
@ -697,7 +697,7 @@ func TestAuthority_reloadPolicyEngines(t *testing.T) {
DeniedNames: &policy.X509NameOptions{ DeniedNames: &policy.X509NameOptions{
DNSDomains: []string{"badhost.local"}, DNSDomains: []string{"badhost.local"},
}, },
AllowWildcardLiteral: true, AllowWildcardNames: true,
}, },
}, },
}, },
@ -796,7 +796,7 @@ func TestAuthority_reloadPolicyEngines(t *testing.T) {
DeniedNames: &policy.X509NameOptions{ DeniedNames: &policy.X509NameOptions{
DNSDomains: []string{"badhost.local"}, DNSDomains: []string{"badhost.local"},
}, },
AllowWildcardLiteral: true, AllowWildcardNames: true,
}, },
SSH: &policy.SSHPolicyOptions{ SSH: &policy.SSHPolicyOptions{
Host: &policy.SSHHostCertificateOptions{ Host: &policy.SSHHostCertificateOptions{
@ -911,7 +911,7 @@ func TestAuthority_reloadPolicyEngines(t *testing.T) {
Deny: &linkedca.X509Names{ Deny: &linkedca.X509Names{
Dns: []string{"badhost.local"}, Dns: []string{"badhost.local"},
}, },
AllowWildcardLiteral: true, AllowWildcardNames: true,
}, },
Ssh: &linkedca.SSHPolicy{ Ssh: &linkedca.SSHPolicy{
Host: &linkedca.SSHHostPolicy{ Host: &linkedca.SSHHostPolicy{
@ -976,7 +976,7 @@ func TestAuthority_reloadPolicyEngines(t *testing.T) {
Deny: &linkedca.X509Names{ Deny: &linkedca.X509Names{
Dns: []string{"badhost.local"}, Dns: []string{"badhost.local"},
}, },
AllowWildcardLiteral: true, AllowWildcardNames: true,
}, },
}, nil }, nil
}, },
@ -996,11 +996,6 @@ func TestAuthority_reloadPolicyEngines(t *testing.T) {
t.Errorf("Authority.reloadPolicyEngines() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("Authority.reloadPolicyEngines() error = %v, wantErr %v", err, tt.wantErr)
} }
// TODO(hs): fix those
// assert.Equal(t, tt.expected.x509Policy, a.x509Policy)
// assert.Equal(t, tt.expected.sshHostPolicy, a.sshHostPolicy)
// assert.Equal(t, tt.expected.sshUserPolicy, a.sshUserPolicy)
assert.Equal(t, tt.expected, a.policyEngine) assert.Equal(t, tt.expected, a.policyEngine)
}) })
} }

@ -66,10 +66,9 @@ type X509Options struct {
// DeniedNames contains the SANs the provisioner is not authorized to sign // DeniedNames contains the SANs the provisioner is not authorized to sign
DeniedNames *policy.X509NameOptions `json:"-"` DeniedNames *policy.X509NameOptions `json:"-"`
// AllowWildcardLiteral indicates if literal wildcard names // AllowWildcardNames indicates if literal wildcard names
// such as *.example.com and @example.com are allowed. Defaults // like *.example.com are allowed. Defaults to false.
// to false. AllowWildcardNames bool `json:"-"`
AllowWildcardLiteral bool `json:"-"`
} }
// HasTemplate returns true if a template is defined in the provisioner options. // HasTemplate returns true if a template is defined in the provisioner options.
@ -95,11 +94,11 @@ func (o *X509Options) GetDeniedNameOptions() *policy.X509NameOptions {
return o.DeniedNames return o.DeniedNames
} }
func (o *X509Options) IsWildcardLiteralAllowed() bool { func (o *X509Options) AreWildcardNamesAllowed() bool {
if o == nil { if o == nil {
return true return true
} }
return o.AllowWildcardLiteral return o.AllowWildcardNames
} }
// TemplateOptions generates a CertificateOptions with the template and data // TemplateOptions generates a CertificateOptions with the template and data

@ -302,21 +302,21 @@ func TestX509Options_IsWildcardLiteralAllowed(t *testing.T) {
{ {
name: "set-true", name: "set-true",
options: &X509Options{ options: &X509Options{
AllowWildcardLiteral: true, AllowWildcardNames: true,
}, },
want: true, want: true,
}, },
{ {
name: "set-false", name: "set-false",
options: &X509Options{ options: &X509Options{
AllowWildcardLiteral: false, AllowWildcardNames: false,
}, },
want: false, want: false,
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := tt.options.IsWildcardLiteralAllowed(); got != tt.want { if got := tt.options.AreWildcardNamesAllowed(); got != tt.want {
t.Errorf("X509PolicyOptions.IsWildcardLiteralAllowed() = %v, want %v", got, tt.want) t.Errorf("X509PolicyOptions.IsWildcardLiteralAllowed() = %v, want %v", got, tt.want)
} }
}) })

@ -285,17 +285,6 @@ func TestNamePolicyEngine_matchEmailConstraint(t *testing.T) {
want bool want bool
wantErr bool wantErr bool
}{ }{
{
name: "fail/asterisk-prefix",
engine: &NamePolicyEngine{},
mailbox: rfc2821Mailbox{
local: "mail",
domain: "local",
},
constraint: "*@example.com",
want: false,
wantErr: true,
},
{ {
name: "fail/asterisk-label", name: "fail/asterisk-label",
engine: &NamePolicyEngine{}, engine: &NamePolicyEngine{},
@ -307,17 +296,6 @@ func TestNamePolicyEngine_matchEmailConstraint(t *testing.T) {
want: false, want: false,
wantErr: true, wantErr: true,
}, },
{
name: "fail/asterisk-inside-local",
engine: &NamePolicyEngine{},
mailbox: rfc2821Mailbox{
local: "mail",
domain: "local",
},
constraint: "m*il@local",
want: false,
wantErr: true,
},
{ {
name: "fail/asterisk-inside-domain", name: "fail/asterisk-inside-domain",
engine: &NamePolicyEngine{}, engine: &NamePolicyEngine{},
@ -358,7 +336,7 @@ func TestNamePolicyEngine_matchEmailConstraint(t *testing.T) {
local: "mail", local: "mail",
domain: "local", domain: "local",
}, },
constraint: ".local", // "wildcard" for the local domain; requires exactly 1 subdomain constraint: ".local",
want: false, want: false,
wantErr: false, wantErr: false,
}, },
@ -406,6 +384,50 @@ func TestNamePolicyEngine_matchEmailConstraint(t *testing.T) {
want: true, want: true,
wantErr: false, wantErr: false,
}, },
{
name: "ok/asterisk-prefix",
engine: &NamePolicyEngine{},
mailbox: rfc2821Mailbox{
local: "mail",
domain: "local",
},
constraint: "*@example.com",
want: false,
wantErr: false,
},
{
name: "ok/asterisk-prefix-match",
engine: &NamePolicyEngine{},
mailbox: rfc2821Mailbox{
local: "*",
domain: "example.com",
},
constraint: "*@example.com",
want: true,
wantErr: false,
},
{
name: "ok/asterisk-inside-local",
engine: &NamePolicyEngine{},
mailbox: rfc2821Mailbox{
local: "mail",
domain: "local",
},
constraint: "m*il@local",
want: false,
wantErr: false,
},
{
name: "ok/asterisk-inside-local-match",
engine: &NamePolicyEngine{},
mailbox: rfc2821Mailbox{
local: "m*il",
domain: "local",
},
constraint: "m*il@local",
want: true,
wantErr: false,
},
{ {
name: "ok/specific-mail", name: "ok/specific-mail",
engine: &NamePolicyEngine{}, engine: &NamePolicyEngine{},

@ -125,7 +125,7 @@ func (e *NamePolicyEngine) validateNames(dnsNames []string, ips []net.IP, emailA
Reason: CannotParseDomain, Reason: CannotParseDomain,
NameType: EmailNameType, NameType: EmailNameType,
Name: email, Name: email,
detail: fmt.Sprintf("cannot parse email domain %q", email), detail: fmt.Errorf("cannot parse email domain %q: %w", email, err).Error(),
} }
} }
mailbox.domain = domainASCII mailbox.domain = domainASCII
@ -577,11 +577,6 @@ func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) {
// SOURCE: https://cs.opensource.google/go/go/+/refs/tags/go1.17.5:src/crypto/x509/verify.go // SOURCE: https://cs.opensource.google/go/go/+/refs/tags/go1.17.5:src/crypto/x509/verify.go
func (e *NamePolicyEngine) matchEmailConstraint(mailbox rfc2821Mailbox, constraint string) (bool, error) { func (e *NamePolicyEngine) matchEmailConstraint(mailbox rfc2821Mailbox, constraint string) (bool, error) {
// TODO(hs): handle literal wildcard case for emails? Does that even make sense?
// If the constraint contains an @, then it specifies an exact mailbox name (currently)
if strings.Contains(constraint, "*") {
return false, fmt.Errorf("email constraint %q cannot contain asterisk", constraint)
}
if strings.Contains(constraint, "@") { if strings.Contains(constraint, "@") {
constraintMailbox, ok := parseRFC2821Mailbox(constraint) constraintMailbox, ok := parseRFC2821Mailbox(constraint)
if !ok { if !ok {
@ -617,7 +612,7 @@ func (e *NamePolicyEngine) matchURIConstraint(uri *url.URL, constraint string) (
if strings.Contains(host, ":") && !strings.HasSuffix(host, "]") { if strings.Contains(host, ":") && !strings.HasSuffix(host, "]") {
var err error var err error
host, _, err = net.SplitHostPort(uri.Host) host, _, err = net.SplitHostPort(host)
if err != nil { if err != nil {
return false, err return false, err
} }

Loading…
Cancel
Save