diff --git a/builtin/credential/cert/backend_test.go b/builtin/credential/cert/backend_test.go index c783a70f7000..4e4edb730c97 100644 --- a/builtin/credential/cert/backend_test.go +++ b/builtin/credential/cert/backend_test.go @@ -1037,6 +1037,8 @@ func TestBackend_dns_singleCert(t *testing.T) { Steps: []logicaltest.TestStep{ testAccStepCert(t, "web", ca, "foo", allowed{dns: "example.com"}, false), testAccStepLogin(t, connState), + testAccStepCert(t, "web", ca, "foo", allowed{dns: "*ample.com"}, false), + testAccStepLogin(t, connState), testAccStepCert(t, "web", ca, "foo", allowed{dns: "notincert.com"}, false), testAccStepLoginInvalid(t, connState), testAccStepCert(t, "web", ca, "foo", allowed{dns: "abc"}, false), @@ -1066,6 +1068,8 @@ func TestBackend_email_singleCert(t *testing.T) { Steps: []logicaltest.TestStep{ testAccStepCert(t, "web", ca, "foo", allowed{emails: "valid@example.com"}, false), testAccStepLogin(t, connState), + testAccStepCert(t, "web", ca, "foo", allowed{emails: "*@example.com"}, false), + testAccStepLogin(t, connState), testAccStepCert(t, "web", ca, "foo", allowed{emails: "invalid@notincert.com"}, false), testAccStepLoginInvalid(t, connState), testAccStepCert(t, "web", ca, "foo", allowed{emails: "abc"}, false), @@ -1305,9 +1309,9 @@ func testAccStepListCerts( type allowed struct { names string // allowed names in the certificate, looks at common, name, dns, email [depricated] common_names string // allowed common names in the certificate - dns string // allowed dns names in the certificate - emails string // allowed email names in the certificate - uris string // allowed uris in SAN section of the certificate + dns string // allowed dns names in the SAN extension of the certificate + emails string // allowed email names in SAN extension of the certificate + uris string // allowed uris in SAN extension of the certificate ext string // required extensions in the certificate } @@ -1323,9 +1327,9 @@ func testAccStepCert( "display_name": name, "allowed_names": testData.names, "allowed_common_names": testData.common_names, - "allowed_dns": testData.dns, - "allowed_emails": testData.emails, - "allowed_uris": testData.uris, + "allowed_dns_sans": testData.dns, + "allowed_email_sans": testData.emails, + "allowed_uri_sans": testData.uris, "required_extensions": testData.ext, "lease": 1000, }, diff --git a/builtin/credential/cert/path_certs.go b/builtin/credential/cert/path_certs.go index 6b75e71bcffd..676e574c847d 100644 --- a/builtin/credential/cert/path_certs.go +++ b/builtin/credential/cert/path_certs.go @@ -44,8 +44,8 @@ Must be x509 PEM encoded.`, Type: framework.TypeCommaStringSlice, Description: `A comma-separated list of names. At least one must exist in either the Common Name or SANs. Supports globbing. -This parameter is deprecated, please use allowed_common_names, allowed_dns, -allowed_email, allowed_uris.`, +This parameter is deprecated, please use allowed_common_names, allowed_dns_sans, +allowed_email_sans, allowed_uri_sans.`, }, "allowed_common_names": &framework.FieldSchema{ @@ -54,19 +54,19 @@ allowed_email, allowed_uris.`, At least one must exist in the Common Name. Supports globbing.`, }, - "allowed_dns": &framework.FieldSchema{ + "allowed_dns_sans": &framework.FieldSchema{ Type: framework.TypeCommaStringSlice, Description: `A comma-separated list of DNS names. At least one must exist in the SANs. Supports globbing.`, }, - "allowed_emails": &framework.FieldSchema{ + "allowed_email_sans": &framework.FieldSchema{ Type: framework.TypeCommaStringSlice, Description: `A comma-separated list of Email Addresses. At least one must exist in the SANs. Supports globbing.`, }, - "allowed_uris": &framework.FieldSchema{ + "allowed_uri_sans": &framework.FieldSchema{ Type: framework.TypeCommaStringSlice, Description: `A comma-separated list of URIs. At least one must exist in the SANs. Supports globbing.`, @@ -180,9 +180,9 @@ func (b *backend) pathCertRead(ctx context.Context, req *logical.Request, d *fra "period": cert.Period / time.Second, "allowed_names": cert.AllowedNames, "allowed_common_names": cert.AllowedCommonNames, - "allowed_dns": cert.AllowedDNS, - "allowed_emails": cert.AllowedEmails, - "allowed_uris": cert.AllowedURIs, + "allowed_dns_sans": cert.AllowedDNSSans, + "allowed_email_sans": cert.AllowedEmailSans, + "allowed_uri_sans": cert.AllowedURISans, "required_extensions": cert.RequiredExtensions, }, }, nil @@ -195,9 +195,9 @@ func (b *backend) pathCertWrite(ctx context.Context, req *logical.Request, d *fr policies := policyutil.ParsePolicies(d.Get("policies")) allowedNames := d.Get("allowed_names").([]string) allowedCommonNames := d.Get("allowed_common_names").([]string) - allowedDNS := d.Get("allowed_dns").([]string) - allowedEmails := d.Get("allowed_emails").([]string) - allowedURIs := d.Get("allowed_uris").([]string) + allowedDNSSans := d.Get("allowed_dns_sans").([]string) + allowedEmailSans := d.Get("allowed_email_sans").([]string) + allowedURISans := d.Get("allowed_uri_sans").([]string) requiredExtensions := d.Get("required_extensions").([]string) var resp logical.Response @@ -272,9 +272,9 @@ func (b *backend) pathCertWrite(ctx context.Context, req *logical.Request, d *fr Policies: policies, AllowedNames: allowedNames, AllowedCommonNames: allowedCommonNames, - AllowedDNS: allowedDNS, - AllowedEmails: allowedEmails, - AllowedURIs: allowedURIs, + AllowedDNSSans: allowedDNSSans, + AllowedEmailSans: allowedEmailSans, + AllowedURISans: allowedURISans, RequiredExtensions: requiredExtensions, TTL: ttl, MaxTTL: maxTTL, @@ -307,9 +307,9 @@ type CertEntry struct { Period time.Duration AllowedNames []string AllowedCommonNames []string - AllowedDNS []string - AllowedEmails []string - AllowedURIs []string + AllowedDNSSans []string + AllowedEmailSans []string + AllowedURISans []string RequiredExtensions []string } diff --git a/builtin/credential/cert/path_login.go b/builtin/credential/cert/path_login.go index 2e14c86abd60..9c42fba7cc71 100644 --- a/builtin/credential/cert/path_login.go +++ b/builtin/credential/cert/path_login.go @@ -267,9 +267,9 @@ func (b *backend) matchesConstraints(clientCert *x509.Certificate, trustedChain return !b.checkForChainInCRLs(trustedChain) && b.matchesNames(clientCert, config) && b.matchesCommonName(clientCert, config) && - b.matchesDNSName(clientCert, config) && - b.matchesEmail(clientCert, config) && - b.matchesURIs(clientCert, config) && + b.matchesDNSSans(clientCert, config) && + b.matchesEmailSans(clientCert, config) && + b.matchesURISans(clientCert, config) && b.matchesCertificateExtensions(clientCert, config) } @@ -319,15 +319,15 @@ func (b *backend) matchesCommonName(clientCert *x509.Certificate, config *Parsed return false } -// matchesDNSName verifies that the certificate matches at least one configured -// allowed dns name -func (b *backend) matchesDNSName(clientCert *x509.Certificate, config *ParsedCert) bool { +// matchesDNSSans verifies that the certificate matches at least one configured +// allowed dns entry in the subject alternate name extension +func (b *backend) matchesDNSSans(clientCert *x509.Certificate, config *ParsedCert) bool { // Default behavior (no names) is to allow all names - if len(config.Entry.AllowedDNS) == 0 { + if len(config.Entry.AllowedDNSSans) == 0 { return true } // At least one pattern must match at least one name if any patterns are specified - for _, allowedDNS := range config.Entry.AllowedDNS { + for _, allowedDNS := range config.Entry.AllowedDNSSans { for _, name := range clientCert.DNSNames { if glob.Glob(allowedDNS, name) { return true @@ -338,15 +338,15 @@ func (b *backend) matchesDNSName(clientCert *x509.Certificate, config *ParsedCer return false } -// matchesDNSName verifies that the certificate matches at least one configured -// allowed dns name -func (b *backend) matchesEmail(clientCert *x509.Certificate, config *ParsedCert) bool { +// matchesEmailSans verifies that the certificate matches at least one configured +// allowed email in the subject alternate name extension +func (b *backend) matchesEmailSans(clientCert *x509.Certificate, config *ParsedCert) bool { // Default behavior (no names) is to allow all names - if len(config.Entry.AllowedEmails) == 0 { + if len(config.Entry.AllowedEmailSans) == 0 { return true } // At least one pattern must match at least one name if any patterns are specified - for _, allowedEmail := range config.Entry.AllowedEmails { + for _, allowedEmail := range config.Entry.AllowedEmailSans { for _, email := range clientCert.EmailAddresses { if glob.Glob(allowedEmail, email) { return true @@ -357,15 +357,15 @@ func (b *backend) matchesEmail(clientCert *x509.Certificate, config *ParsedCert) return false } -// matchesURIs verifies that the certificate matches at least one configured -// allowed uri -func (b *backend) matchesURIs(clientCert *x509.Certificate, config *ParsedCert) bool { +// matchesURISans verifies that the certificate matches at least one configured +// allowed uri in the subject alternate name extension +func (b *backend) matchesURISans(clientCert *x509.Certificate, config *ParsedCert) bool { // Default behavior (no names) is to allow all names - if len(config.Entry.AllowedURIs) == 0 { + if len(config.Entry.AllowedURISans) == 0 { return true } // At least one pattern must match at least one name if any patterns are specified - for _, allowedURI := range config.Entry.AllowedURIs { + for _, allowedURI := range config.Entry.AllowedURISans { for _, name := range clientCert.URIs { if glob.Glob(allowedURI, name.String()) { return true diff --git a/website/source/api/auth/cert/index.html.md b/website/source/api/auth/cert/index.html.md index c4bf5e3d66b5..be75e5aaeda0 100644 --- a/website/source/api/auth/cert/index.html.md +++ b/website/source/api/auth/cert/index.html.md @@ -34,24 +34,25 @@ Sets a CA cert and associated parameters in a role name. (https://github.com/ryanuber/go-glob/blob/master/README.md#example). Value is a comma-separated list of patterns. Authentication requires at least one Name matching at least one pattern. If not set, defaults to allowing all names. - Note: This parameter is deprecated please use allowed_uris, allowed_common_names, - allowed_dns, allowed_emails, allowed_uris, required_extensions + Note: This parameter is deprecated please use individual parameters + allowed_common_names, allowed_dns_sans, allowed_email_sans, allowed_uri_sans, + required_extensions - `allowed_common_names` `(string: "")` - Constrain the Common Names in the client certificate with a [globbed pattern] (https://github.com/ryanuber/go-glob/blob/master/README.md#example). Value is a comma-separated list of patterns. Authentication requires at least one Name matching at least one pattern. If not set, defaults to allowing all names. -- `allowed_dns` `(string: "")` - Constrain the Alternative Names in +- `allowed_dns_sans` `(string: "")` - Constrain the Alternative Names in the client certificate with a [globbed pattern] (https://github.com/ryanuber/go-glob/blob/master/README.md#example). Value is a comma-separated list of patterns. Authentication requires at least one DNS matching at least one pattern. If not set, defaults to allowing all dns. -- `allowed_email` `(string: "")` - Constrain the Alternative Names in +- `allowed_email_sans` `(string: "")` - Constrain the Alternative Names in the client certificate with a [globbed pattern] (https://github.com/ryanuber/go-glob/blob/master/README.md#example). Value is a comma-separated list of patterns. Authentication requires at least one Email matching at least one pattern. If not set, defaults to allowing all emails. -- `allowed_uris` `(string: "")` - Constrain the Alternative Names in +- `allowed_uri_sans` `(string: "")` - Constrain the Alternative Names in the client certificate with a [globbed pattern] (https://github.com/ryanuber/go-glob/blob/master/README.md#example). Value is a comma-separated list of URI patterns. Authentication requires at least one URI