diff --git a/builtin/credential/cert/backend_test.go b/builtin/credential/cert/backend_test.go index e12fca70baa3..095e42389f67 100644 --- a/builtin/credential/cert/backend_test.go +++ b/builtin/credential/cert/backend_test.go @@ -844,9 +844,9 @@ func TestBackend_CertWrites(t *testing.T) { tc := logicaltest.TestCase{ Backend: testFactory(t), Steps: []logicaltest.TestStep{ - testAccStepCert(t, "aaa", ca1, "foo", "", "", false), - testAccStepCert(t, "bbb", ca2, "foo", "", "", false), - testAccStepCert(t, "ccc", ca3, "foo", "", "", true), + testAccStepCert(t, "aaa", ca1, "foo", "", "", "", false), + testAccStepCert(t, "bbb", ca2, "foo", "", "", "", false), + testAccStepCert(t, "ccc", ca3, "foo", "", "", "", true), }, } tc.Steps = append(tc.Steps, testAccStepListCerts(t, []string{"aaa", "bbb"})...) @@ -867,7 +867,7 @@ func TestBackend_basic_CA(t *testing.T) { logicaltest.Test(t, logicaltest.TestCase{ Backend: testFactory(t), Steps: []logicaltest.TestStep{ - testAccStepCert(t, "web", ca, "foo", "", "", false), + testAccStepCert(t, "web", ca, "foo", "", "", "", false), testAccStepLogin(t, connState), testAccStepCertLease(t, "web", ca, "foo"), testAccStepCertTTL(t, "web", ca, "foo"), @@ -876,9 +876,9 @@ func TestBackend_basic_CA(t *testing.T) { testAccStepLogin(t, connState), testAccStepCertNoLease(t, "web", ca, "foo"), testAccStepLoginDefaultLease(t, connState), - testAccStepCert(t, "web", ca, "foo", "*.example.com", "", false), + testAccStepCert(t, "web", ca, "foo", "*.example.com", "", "", false), testAccStepLogin(t, connState), - testAccStepCert(t, "web", ca, "foo", "*.invalid.com", "", false), + testAccStepCert(t, "web", ca, "foo", "*.invalid.com", "", "", false), testAccStepLoginInvalid(t, connState), }, }) @@ -927,13 +927,13 @@ func TestBackend_basic_singleCert(t *testing.T) { logicaltest.Test(t, logicaltest.TestCase{ Backend: testFactory(t), Steps: []logicaltest.TestStep{ - testAccStepCert(t, "web", ca, "foo", "", "", false), + testAccStepCert(t, "web", ca, "foo", "", "", "", false), testAccStepLogin(t, connState), - testAccStepCert(t, "web", ca, "foo", "example.com", "", false), + testAccStepCert(t, "web", ca, "foo", "example.com", "", "", false), testAccStepLogin(t, connState), - testAccStepCert(t, "web", ca, "foo", "invalid", "", false), + testAccStepCert(t, "web", ca, "foo", "invalid", "", "", false), testAccStepLoginInvalid(t, connState), - testAccStepCert(t, "web", ca, "foo", "", "1.2.3.4:invalid", false), + testAccStepCert(t, "web", ca, "foo", "", "", "1.2.3.4:invalid", false), testAccStepLoginInvalid(t, connState), }, }) @@ -956,39 +956,70 @@ func TestBackend_extensions_singleCert(t *testing.T) { logicaltest.Test(t, logicaltest.TestCase{ Backend: testFactory(t), Steps: []logicaltest.TestStep{ - testAccStepCert(t, "web", ca, "foo", "", "2.1.1.1:A UTF8String Extension", false), + testAccStepCert(t, "web", ca, "foo", "", "", "2.1.1.1:A UTF8String Extension", false), testAccStepLogin(t, connState), - testAccStepCert(t, "web", ca, "foo", "", "2.1.1.1:*,2.1.1.2:A UTF8*", false), + testAccStepCert(t, "web", ca, "foo", "", "", "2.1.1.1:*,2.1.1.2:A UTF8*", false), testAccStepLogin(t, connState), - testAccStepCert(t, "web", ca, "foo", "", "1.2.3.45:*", false), + testAccStepCert(t, "web", ca, "foo", "", "", "1.2.3.45:*", false), testAccStepLoginInvalid(t, connState), - testAccStepCert(t, "web", ca, "foo", "", "2.1.1.1:The Wrong Value", false), + testAccStepCert(t, "web", ca, "foo", "", "", "2.1.1.1:The Wrong Value", false), testAccStepLoginInvalid(t, connState), - testAccStepCert(t, "web", ca, "foo", "", "2.1.1.1:*,2.1.1.2:The Wrong Value", false), + testAccStepCert(t, "web", ca, "foo", "", "", "2.1.1.1:*,2.1.1.2:The Wrong Value", false), testAccStepLoginInvalid(t, connState), - testAccStepCert(t, "web", ca, "foo", "", "2.1.1.1:", false), + testAccStepCert(t, "web", ca, "foo", "", "", "2.1.1.1:", false), testAccStepLoginInvalid(t, connState), - testAccStepCert(t, "web", ca, "foo", "", "2.1.1.1:,2.1.1.2:*", false), + testAccStepCert(t, "web", ca, "foo", "", "", "2.1.1.1:,2.1.1.2:*", false), testAccStepLoginInvalid(t, connState), - testAccStepCert(t, "web", ca, "foo", "example.com", "2.1.1.1:A UTF8String Extension", false), + testAccStepCert(t, "web", ca, "foo", "example.com", "", "2.1.1.1:A UTF8String Extension", false), testAccStepLogin(t, connState), - testAccStepCert(t, "web", ca, "foo", "example.com", "2.1.1.1:*,2.1.1.2:A UTF8*", false), + testAccStepCert(t, "web", ca, "foo", "example.com", "", "2.1.1.1:*,2.1.1.2:A UTF8*", false), testAccStepLogin(t, connState), - testAccStepCert(t, "web", ca, "foo", "example.com", "1.2.3.45:*", false), + testAccStepCert(t, "web", ca, "foo", "example.com", "", "1.2.3.45:*", false), testAccStepLoginInvalid(t, connState), - testAccStepCert(t, "web", ca, "foo", "example.com", "2.1.1.1:The Wrong Value", false), + testAccStepCert(t, "web", ca, "foo", "example.com", "", "2.1.1.1:The Wrong Value", false), testAccStepLoginInvalid(t, connState), - testAccStepCert(t, "web", ca, "foo", "example.com", "2.1.1.1:*,2.1.1.2:The Wrong Value", false), + testAccStepCert(t, "web", ca, "foo", "example.com", "", "2.1.1.1:*,2.1.1.2:The Wrong Value", false), testAccStepLoginInvalid(t, connState), - testAccStepCert(t, "web", ca, "foo", "invalid", "2.1.1.1:A UTF8String Extension", false), + testAccStepCert(t, "web", ca, "foo", "invalid", "", "2.1.1.1:A UTF8String Extension", false), testAccStepLoginInvalid(t, connState), - testAccStepCert(t, "web", ca, "foo", "invalid", "2.1.1.1:*,2.1.1.2:A UTF8*", false), + testAccStepCert(t, "web", ca, "foo", "invalid", "", "2.1.1.1:*,2.1.1.2:A UTF8*", false), testAccStepLoginInvalid(t, connState), - testAccStepCert(t, "web", ca, "foo", "invalid", "1.2.3.45:*", false), + testAccStepCert(t, "web", ca, "foo", "invalid", "", "1.2.3.45:*", false), testAccStepLoginInvalid(t, connState), - testAccStepCert(t, "web", ca, "foo", "invalid", "2.1.1.1:The Wrong Value", false), + testAccStepCert(t, "web", ca, "foo", "invalid", "", "2.1.1.1:The Wrong Value", false), testAccStepLoginInvalid(t, connState), - testAccStepCert(t, "web", ca, "foo", "invalid", "2.1.1.1:*,2.1.1.2:The Wrong Value", false), + testAccStepCert(t, "web", ca, "foo", "invalid", "", "2.1.1.1:*,2.1.1.2:The Wrong Value", false), + testAccStepLoginInvalid(t, connState), + }, + }) +} + +// Test a self-signed client with URI alt names (root CA) that is trusted +func TestBackend_URI_singleCert(t *testing.T) { + connState, err := testConnState( + "test-fixtures/root/rootcawuricert.pem", + "test-fixtures/root/rootcawurikey.pem", + "test-fixtures/root/rootcacert.pem", + ) + if err != nil { + t.Fatalf("error testing connection state: %v", err) + } + ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem") + if err != nil { + t.Fatalf("err: %v", err) + } + logicaltest.Test(t, logicaltest.TestCase{ + Backend: testFactory(t), + Steps: []logicaltest.TestStep{ + testAccStepCert(t, "web", ca, "foo", "", "spiffe://example.com/*", "", false), + testAccStepLogin(t, connState), + testAccStepCert(t, "web", ca, "foo", "", "spiffe://example.com/host", "", false), + testAccStepLogin(t, connState), + testAccStepCert(t, "web", ca, "foo", "", "spiffe://example.com/invalid", "", false), + testAccStepLoginInvalid(t, connState), + testAccStepCert(t, "web", ca, "foo", "", "abc", "", false), + testAccStepLoginInvalid(t, connState), + testAccStepCert(t, "web", ca, "foo", "", "http://www.google.com", "", false), testAccStepLoginInvalid(t, connState), }, }) @@ -1008,9 +1039,9 @@ func TestBackend_mixed_constraints(t *testing.T) { logicaltest.Test(t, logicaltest.TestCase{ Backend: testFactory(t), Steps: []logicaltest.TestStep{ - testAccStepCert(t, "1unconstrained", ca, "foo", "", "", false), - testAccStepCert(t, "2matching", ca, "foo", "*.example.com,whatever", "", false), - testAccStepCert(t, "3invalid", ca, "foo", "invalid", "", false), + testAccStepCert(t, "1unconstrained", ca, "foo", "", "", "", false), + testAccStepCert(t, "2matching", ca, "foo", "*.example.com,whatever", "", "", false), + testAccStepCert(t, "3invalid", ca, "foo", "invalid", "", "", false), testAccStepLogin(t, connState), // Assumes CertEntries are processed in alphabetical order (due to store.List), so we only match 2matching if 1unconstrained doesn't match testAccStepLoginWithName(t, connState, "2matching"), @@ -1190,7 +1221,7 @@ func testAccStepListCerts( } func testAccStepCert( - t *testing.T, name string, cert []byte, policies string, allowedNames string, requiredExtensions string, expectError bool) logicaltest.TestStep { + t *testing.T, name string, cert []byte, policies, allowedNames, allowedURIs, requiredExtensions string, expectError bool) logicaltest.TestStep { return logicaltest.TestStep{ Operation: logical.UpdateOperation, Path: "certs/" + name, @@ -1200,6 +1231,7 @@ func testAccStepCert( "policies": policies, "display_name": name, "allowed_names": allowedNames, + "allowed_uris": allowedURIs, "required_extensions": requiredExtensions, "lease": 1000, }, diff --git a/builtin/credential/cert/path_certs.go b/builtin/credential/cert/path_certs.go index 511b240c489f..7dc660a9eee4 100644 --- a/builtin/credential/cert/path_certs.go +++ b/builtin/credential/cert/path_certs.go @@ -46,6 +46,12 @@ Must be x509 PEM encoded.`, At least one must exist in either the Common Name or SANs. Supports globbing.`, }, + "allowed_uris": &framework.FieldSchema{ + Type: framework.TypeCommaStringSlice, + Description: `A comma-separated list of URIs. +At least one must exist in the SANs. Supports globbing.`, + }, + "required_extensions": &framework.FieldSchema{ Type: framework.TypeCommaStringSlice, Description: `A comma-separated string or array of extensions @@ -75,12 +81,14 @@ seconds. Defaults to system/backend default TTL.`, Description: `TTL for tokens issued by this backend. Defaults to system/backend default TTL time.`, }, + "max_ttl": &framework.FieldSchema{ Type: framework.TypeDurationSecond, Description: `Duration in either an integer number of seconds (3600) or an integer time unit (60m) after which the issued token can no longer be renewed.`, }, + "period": &framework.FieldSchema{ Type: framework.TypeDurationSecond, Description: `If set, indicates that the token generated using this role @@ -144,13 +152,15 @@ func (b *backend) pathCertRead(ctx context.Context, req *logical.Request, d *fra return &logical.Response{ Data: map[string]interface{}{ - "certificate": cert.Certificate, - "display_name": cert.DisplayName, - "policies": cert.Policies, - "ttl": cert.TTL / time.Second, - "max_ttl": cert.MaxTTL / time.Second, - "period": cert.Period / time.Second, - "allowed_names": cert.AllowedNames, + "certificate": cert.Certificate, + "display_name": cert.DisplayName, + "policies": cert.Policies, + "ttl": cert.TTL / time.Second, + "max_ttl": cert.MaxTTL / time.Second, + "period": cert.Period / time.Second, + "allowed_names": cert.AllowedNames, + "allowed_uris": cert.AllowedURIs, + "required_extensions": cert.RequiredExtensions, }, }, nil } @@ -161,6 +171,7 @@ func (b *backend) pathCertWrite(ctx context.Context, req *logical.Request, d *fr displayName := d.Get("display_name").(string) policies := policyutil.ParsePolicies(d.Get("policies")) allowedNames := d.Get("allowed_names").([]string) + allowedURIs := d.Get("allowed_uris").([]string) requiredExtensions := d.Get("required_extensions").([]string) var resp logical.Response @@ -234,6 +245,7 @@ func (b *backend) pathCertWrite(ctx context.Context, req *logical.Request, d *fr DisplayName: displayName, Policies: policies, AllowedNames: allowedNames, + AllowedURIs: allowedURIs, RequiredExtensions: requiredExtensions, TTL: ttl, MaxTTL: maxTTL, @@ -265,6 +277,7 @@ type CertEntry struct { MaxTTL time.Duration Period time.Duration AllowedNames []string + AllowedURIs []string RequiredExtensions []string } diff --git a/builtin/credential/cert/path_login.go b/builtin/credential/cert/path_login.go index fce012bced02..d1497e514cb5 100644 --- a/builtin/credential/cert/path_login.go +++ b/builtin/credential/cert/path_login.go @@ -266,6 +266,7 @@ func (b *backend) verifyCredentials(ctx context.Context, req *logical.Request, d func (b *backend) matchesConstraints(clientCert *x509.Certificate, trustedChain []*x509.Certificate, config *ParsedCert) bool { return !b.checkForChainInCRLs(trustedChain) && b.matchesNames(clientCert, config) && + b.matchesURIs(clientCert, config) && b.matchesCertificateExtensions(clientCert, config) } @@ -293,7 +294,27 @@ func (b *backend) matchesNames(clientCert *x509.Certificate, config *ParsedCert) return true } } + + } + return false +} + +// matchesURIs verifies that the certificate matches at least one configured +// allowed uri +func (b *backend) matchesURIs(clientCert *x509.Certificate, config *ParsedCert) bool { + // Default behavior (no names) is to allow all names + if len(config.Entry.AllowedURIs) == 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 _, name := range clientCert.URIs { + if glob.Glob(allowedURI, name.String()) { + return true + } + } + } + return false } diff --git a/builtin/credential/cert/test-fixtures/root/rootcacert.srl b/builtin/credential/cert/test-fixtures/root/rootcacert.srl index 219a6be4b13b..282f3267bb3e 100644 --- a/builtin/credential/cert/test-fixtures/root/rootcacert.srl +++ b/builtin/credential/cert/test-fixtures/root/rootcacert.srl @@ -1 +1 @@ -92223EAFBBEE17A3 +92223EAFBBEE17A4 diff --git a/builtin/credential/cert/test-fixtures/root/rootcawuri.cnf b/builtin/credential/cert/test-fixtures/root/rootcawuri.cnf new file mode 100644 index 000000000000..bb15540ca7e4 --- /dev/null +++ b/builtin/credential/cert/test-fixtures/root/rootcawuri.cnf @@ -0,0 +1,18 @@ +[ req ] +default_bits = 2048 +encrypt_key = no +prompt = no +default_md = sha256 +req_extensions = req_v3 +distinguished_name = dn + +[ dn ] +CN = example.com + +[ req_v3 ] +subjectAltName = @alt_names + +[ alt_names ] +DNS.1 = example.com +IP.1 = 127.0.0.1 +URI.1 = spiffe://example.com/host diff --git a/builtin/credential/cert/test-fixtures/root/rootcawuri.csr b/builtin/credential/cert/test-fixtures/root/rootcawuri.csr new file mode 100644 index 000000000000..0ababe1ce027 --- /dev/null +++ b/builtin/credential/cert/test-fixtures/root/rootcawuri.csr @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICpTCCAY0CAQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDEtoz6THzA8RFNJ+wu40Pa30Inyprv3xRGYA71 +0T3yLrWUA0xaS8i7HHXDaEVmtHi7I+dFRqGwCgtDLY3sXN1C1t/U6V6xhhQ1hRW7 +PJhbGfsfi8uBx83amWiSMlmEBYPryQzPS+8mmRErBi6EdmgbdGWV5IcovMddDxE1 +Npc1vwmTxDUOe6mRSa8UkaR9nwFl8LTz9clIkGlOJLHWD2oX15PVr7SKYco+MrIh +HLKkYMgATFJ05EKLyRxO/lQWD6ibUYJuGhFeNyjk34swl3uoWQBGndxcs2BQP4OL +EfnsoXVDrHwjZ1FWSu/Bf6TfKvwo5It1IZLnm+cCTqxCnaLRAgMBAAGgSjBIBgkq +hkiG9w0BCQ4xOzA5MDcGA1UdEQQwMC6CC2V4YW1wbGUuY29thwR/AAABhhlzcGlm +ZmU6Ly9leGFtcGxlLmNvbS9ob3N0MA0GCSqGSIb3DQEBCwUAA4IBAQBw2y7bPrLk +B7DrZRvO/s8yj/Mi2iS/q3KEACEUxHTXH9GrqnQJ1n00WjaEu5JgXW8F08738nj/ +QhO5IM9ZMBtFyt9/GguZzGWnGUGUvtfM/ps/qzF6lAnjxYnFfqJeDWhg4SQsW6ZW +eFZ3S1kx0iQjy+Y7oWZNObbgDhszdJa6swN1WJBB8BZuiDJYXMBzfWdR6aZStJ0Z +lUHyaQbILXRc+meuDY7KeILJhldlE8oU/NENO1w1WXcsseXg8790pPYg+uR/uXg0 +0iWPtqgjO+55eAvkZ5nY0N/kABV1oaCB8bVs6/2HPqquPX6c+xkcUI/HY8SJgWzk +AHCG7VIB4W94 +-----END CERTIFICATE REQUEST----- diff --git a/builtin/credential/cert/test-fixtures/root/rootcawuricert.pem b/builtin/credential/cert/test-fixtures/root/rootcawuricert.pem new file mode 100644 index 000000000000..171f4de004ea --- /dev/null +++ b/builtin/credential/cert/test-fixtures/root/rootcawuricert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC6jCCAdKgAwIBAgIJAJIiPq+77hekMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV +BAMTC2V4YW1wbGUuY29tMB4XDTE4MDMzMTE2MTE0NVoXDTE5MDMzMTE2MTE0NVow +FjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDEtoz6THzA8RFNJ+wu40Pa30Inyprv3xRGYA710T3yLrWUA0xaS8i7 +HHXDaEVmtHi7I+dFRqGwCgtDLY3sXN1C1t/U6V6xhhQ1hRW7PJhbGfsfi8uBx83a +mWiSMlmEBYPryQzPS+8mmRErBi6EdmgbdGWV5IcovMddDxE1Npc1vwmTxDUOe6mR +Sa8UkaR9nwFl8LTz9clIkGlOJLHWD2oX15PVr7SKYco+MrIhHLKkYMgATFJ05EKL +yRxO/lQWD6ibUYJuGhFeNyjk34swl3uoWQBGndxcs2BQP4OLEfnsoXVDrHwjZ1FW +Su/Bf6TfKvwo5It1IZLnm+cCTqxCnaLRAgMBAAGjOzA5MDcGA1UdEQQwMC6CC2V4 +YW1wbGUuY29thwR/AAABhhlzcGlmZmU6Ly9leGFtcGxlLmNvbS9ob3N0MA0GCSqG +SIb3DQEBBQUAA4IBAQDhR59hSpL4k4wbK3bA17YoNwFBsDpDcoU2iB9NDUTj+j+T +Rgumt+VHtgxuGRDFPQ+0D2hmJJHNCHKulgeDKVLtY/c5dCEsk8epLQwoCd/pQsNR +Lj102g83rCrU0pfTFjAUoecmHBFt7GDxVyWDsJgGItMatPQuWyZXTzO8JdhCfpMP +m7z65VYZjIPgevpSR5NVJDU8u2jRCkRQBFqOXotJS6EObu4P8aly4YhwiMf1B0L8 +60XHbBksOQSZOky37uFhaab78bAu5nd2kN1K4qSObTJshCZAwRYk0XdCjDrMcZRJ +Fp+yygib+K8e7o71Co0zUdSU0yxOKGsWvjz1BUVl +-----END CERTIFICATE----- diff --git a/builtin/credential/cert/test-fixtures/root/rootcawurikey.pem b/builtin/credential/cert/test-fixtures/root/rootcawurikey.pem new file mode 100644 index 000000000000..81ac978291d7 --- /dev/null +++ b/builtin/credential/cert/test-fixtures/root/rootcawurikey.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDEtoz6THzA8RFN +J+wu40Pa30Inyprv3xRGYA710T3yLrWUA0xaS8i7HHXDaEVmtHi7I+dFRqGwCgtD +LY3sXN1C1t/U6V6xhhQ1hRW7PJhbGfsfi8uBx83amWiSMlmEBYPryQzPS+8mmREr +Bi6EdmgbdGWV5IcovMddDxE1Npc1vwmTxDUOe6mRSa8UkaR9nwFl8LTz9clIkGlO +JLHWD2oX15PVr7SKYco+MrIhHLKkYMgATFJ05EKLyRxO/lQWD6ibUYJuGhFeNyjk +34swl3uoWQBGndxcs2BQP4OLEfnsoXVDrHwjZ1FWSu/Bf6TfKvwo5It1IZLnm+cC +TqxCnaLRAgMBAAECggEAYLdYbR/6HmroFMVSLGN000H9ps7IirNlpoxIDrhH+rDY +eeN9QNAN62E8zUyRAsQsr+YhKUBm8sSdcPQO2W13JAu9lVMAScwgV4gNfTd3uSL3 +AzWaYz63iYjvjyHOPUjw6Za6A5nUBWgwtrSdXmdRHF6IK8Bma7MVWj20OjOS+MsM +ScXk+yMTzpQYZ+AhP6rgcccn6djtk+Mqrpa7yW5cTDkQ0+/MF0KR7tYUbakRSimI +Ph6e+zFt4infOWP5fDr0oSpMXA2chh0INTtxbltnJzvaaPF8LSzyihWTZszABc84 +Ckgrvmt5DViYbmfKHk0csS/xF/wdygfkkJHML8l/IQKBgQD9CMaDgfpM78uH8Kgm +Ja/ANu4Te5zO/n5E96PHdvCN+m7pCMgYuXuKgXDADgD1O6MItzDnEpkubluffARf +1eJyw9ner0tTAs8bZgtKdLQvaghq5Afk1+m8XDTskJsVLVGrozvJLuabPqnZrkRH +AxLdZjiAh6z2csFVYTQnMQSfhQKBgQDHBMjapcDx9y/jUq/yoFvwkdT3THQO9JgK +XC5NOHGVhyT3695wpqi/ANA4b8P9MmAzcUkT8a3jcqV87OIQmK3Y1oGvjHQCKS60 +OYE9TadpxwW2uzxS5T7YegXf5L3uHinoWHlLklN+Q9pvJStw4QrDzhd8rtcZA+FN +KBmjzYdJ3QKBgQDYutl97qi7mXEVgPYlpoYA94u4OFq5mZYB8LLhuGiW03iINbNe +KhE9M12lwtjjNC+S2YYThgSaln/3/LuqcoLBlitY54B3G6LVbvQg1BE5w3JuS97P +Dnjvk3LpZXrQCr83altdGMUBGA1XnEJzKJjR9ipTPOLTPLuIK/gF0aCKGQKBgQCm +ZFitfZGge4M9Mt/KIcpciwCcNf5+ln8bglBv3XYRhykgYsLaOmyxLLPpy3/4DAsk +V1263//7PtofZUnoiE4pEcbhh7NiLx5OLhngsDD9Hhmn2kkoIWR2xyZsN6mYEP4G +tRnMVi2aTo6tCE2WlYBTjtZSNze9QWI4CQPO0MKAvQKBgQCzpJAJXl04zQv9S5uW +pH3xShmd0Zjv9tNyOVNqWUeg47IFzNC2w/6FqYkhd9C4DCAibzPx7WkVjYAR+ivY +NQv1usVhV3maJX5rw+C4Zck8kAmiqMbLacUVdy/5E2Mbk7xqjAvu+qrMFdSk/2GR +raR1xOEvE0cKWIwr8c8wIva4wA== +-----END PRIVATE KEY----- diff --git a/website/source/api/auth/cert/index.html.md b/website/source/api/auth/cert/index.html.md index 9d94aef3dd23..adf8efcfda4c 100644 --- a/website/source/api/auth/cert/index.html.md +++ b/website/source/api/auth/cert/index.html.md @@ -34,6 +34,11 @@ 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. +- `allowed_uris` `(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 + matching at least one pattern. If not set, defaults to allowing all URIs. - `required_extensions` `(string: "" or array:[])` - Require specific Custom Extension OIDs to exist and match the pattern. Value is a comma separated string or array of `oid:value`. Expects the extension value to be some type