From b2fd4ad7c764416f832b260e69ea315716b7249d Mon Sep 17 00:00:00 2001 From: ZhenLian Date: Tue, 6 Oct 2020 13:33:26 -0700 Subject: [PATCH] add SPIFFE ID in the verification func parameters --- internal/credentials/spiffe.go | 37 +++++- security/advancedtls/advancedtls.go | 8 +- .../advancedtls_integration_test.go | 74 ++++++++++- security/advancedtls/testdata/README.md | 10 +- .../testdata/client_cert_spiffe_1.pem | 125 ++++++++++++++++++ .../testdata/client_key_spiffe_1.pem | 51 +++++++ .../testdata/server_cert_spiffe_1.pem | 125 ++++++++++++++++++ .../testdata/server_key_spiffe_1.pem | 51 +++++++ 8 files changed, 469 insertions(+), 12 deletions(-) create mode 100644 security/advancedtls/testdata/client_cert_spiffe_1.pem create mode 100644 security/advancedtls/testdata/client_key_spiffe_1.pem create mode 100644 security/advancedtls/testdata/server_cert_spiffe_1.pem create mode 100644 security/advancedtls/testdata/server_key_spiffe_1.pem diff --git a/internal/credentials/spiffe.go b/internal/credentials/spiffe.go index b66e3dbb5ac..f762e4de6cc 100644 --- a/internal/credentials/spiffe.go +++ b/internal/credentials/spiffe.go @@ -25,6 +25,7 @@ package credentials import ( "crypto/tls" + "crypto/x509" "net/url" "google.golang.org/grpc/grpclog" @@ -48,7 +49,7 @@ func SPIFFEIDFromState(state tls.ConnectionState) *url.URL { logger.Warning("invalid SPIFFE ID: total ID length larger than 2048 bytes") return nil } - if len(uri.Host) == 0 || len(uri.RawPath) == 0 || len(uri.Path) == 0 { + if len(uri.Host) == 0 || len(uri.Path) == 0 { logger.Warning("invalid SPIFFE ID: domain or workload ID is empty") return nil } @@ -65,3 +66,37 @@ func SPIFFEIDFromState(state tls.ConnectionState) *url.URL { } return spiffeID } + +// SPIFFEIDFromState parses the SPIFFE ID from x509.Certificate. If the SPIFFE +// ID format is invalid, return nil with warning. +func SPIFFEIDFromCert(cert *x509.Certificate) *url.URL { + if cert == nil { + return nil + } + var spiffeID *url.URL + for _, uri := range cert.URIs { + if uri == nil || uri.Scheme != "spiffe" || uri.Opaque != "" || (uri.User != nil && uri.User.Username() != "") { + continue + } + // From this point, we assume the uri is intended for a SPIFFE ID. + if len(uri.String()) > 2048 { + logger.Warning("invalid SPIFFE ID: total ID length larger than 2048 bytes") + return nil + } + if len(uri.Host) == 0 || len(uri.Path) == 0 { + logger.Warning("invalid SPIFFE ID: domain or workload ID is empty") + return nil + } + if len(uri.Host) > 255 { + logger.Warning("invalid SPIFFE ID: domain length larger than 255 characters") + return nil + } + // A valid SPIFFE certificate can only have exactly one URI SAN field. + if len(cert.URIs) > 1 { + logger.Warning("invalid SPIFFE ID: multiple URI SANs") + return nil + } + spiffeID = uri + } + return spiffeID +} diff --git a/security/advancedtls/advancedtls.go b/security/advancedtls/advancedtls.go index 74564632660..eae7d1fc6e4 100644 --- a/security/advancedtls/advancedtls.go +++ b/security/advancedtls/advancedtls.go @@ -27,6 +27,7 @@ import ( "crypto/x509" "fmt" "net" + "net/url" "reflect" "syscall" "time" @@ -53,6 +54,10 @@ type VerificationFuncParams struct { // certificate(s) and that verification passed. This field would be nil if // either user chose not to verify or the verification failed. Leaf *x509.Certificate + // The connection information stored during the verification. + RawConn net.Conn + // The SPIFFE ID stored in |State|. + SPIFFEID *url.URL } // VerificationResults contains the information about results of @@ -502,13 +507,14 @@ func buildVerifyFunc(c *advancedTLSCreds, } leafCert = certs[0] } - // Perform custom verification check if specified. if c.verifyFunc != nil { _, err := c.verifyFunc(&VerificationFuncParams{ ServerName: serverName, RawCerts: rawCerts, VerifiedChains: chains, Leaf: leafCert, + RawConn: rawConn, + SPIFFEID: credinternal.SPIFFEIDFromCert(leafCert), }) return err } diff --git a/security/advancedtls/advancedtls_integration_test.go b/security/advancedtls/advancedtls_integration_test.go index a95fa56a6d6..4449445301f 100644 --- a/security/advancedtls/advancedtls_integration_test.go +++ b/security/advancedtls/advancedtls_integration_test.go @@ -80,11 +80,19 @@ type certStore struct { serverPeer1 tls.Certificate // serverPeer2 is the certificate sent by server to prove its identity. // It is trusted by clientTrust2. - serverPeer2 tls.Certificate - clientTrust1 *x509.CertPool - clientTrust2 *x509.CertPool - serverTrust1 *x509.CertPool - serverTrust2 *x509.CertPool + serverPeer2 tls.Certificate + // clientPeerSPIFFE1 is the certificate with the SPIFFE ID + // "spiffe://foo.bar.com/client/workload/1" sent by client to prove identity. + // It is trusted by serverTrust1. + clientPeerSPIFFE1 tls.Certificate + // serverPeerSPIFFE1 is the certificate with the SPIFFE ID + // "spiffe://foo.bar.com/client/workload/1" sent by client to prove identity. + // It is trusted by serverTrust1. + serverPeerSPIFFE1 tls.Certificate + clientTrust1 *x509.CertPool + clientTrust2 *x509.CertPool + serverTrust1 *x509.CertPool + serverTrust2 *x509.CertPool } // loadCerts function is used to load test certificates at the beginning of @@ -111,6 +119,16 @@ func (cs *certStore) loadCerts() error { if err != nil { return err } + cs.clientPeerSPIFFE1, err = tls.LoadX509KeyPair(testdata.Path("client_cert_spiffe_1.pem"), + testdata.Path("client_key_spiffe_1.pem")) + if err != nil { + return err + } + cs.serverPeerSPIFFE1, err = tls.LoadX509KeyPair(testdata.Path("server_cert_spiffe_1.pem"), + testdata.Path("server_key_spiffe_1.pem")) + if err != nil { + return err + } cs.clientTrust1, err = readTrustCert(testdata.Path("client_trust_cert_1.pem")) if err != nil { return err @@ -384,6 +402,52 @@ func (s) TestEnd2End(t *testing.T) { }, serverVType: CertVerification, }, + // Test if the SPIFFE ID is plumbed to VerificationFuncParams while + // performing the custom authorization. + // At initialization(stage = 0), client will be initialized with cert + // clientPeerSPIFFE1 and clientTrust1, server with serverPeerSPIFFE1 and + // serverTrust1. + // The mutual authentication works at the beginning, since clientPeerSPIFFE1 + // trusted by serverTrust1, serverPeerSPIFFE1 trusted by clientTrust1. + // Besides, the client custom verification check allows the SPIFFE + // ID shown on serverPeerSPIFFE1, and server verification allows SPIFFE ID + // on clientPeerSPIFFE1. + // At stage 1, server disallows the the connections by setting custom + // verification check. The following calls should fail. Previous + // connections should not be affected. + // At stage 2, server allows the SPIFFE ID shown on the clientPeerSPIFFE1. + // Authentications should go back to normal. + { + desc: "TestSPIFFEIDIsPlumbed", + clientCert: []tls.Certificate{cs.clientPeerSPIFFE1}, + clientRoot: cs.clientTrust1, + clientVerifyFunc: func(params *VerificationFuncParams) (*VerificationResults, error) { + if params.SPIFFEID == nil || params.SPIFFEID.Scheme != "spiffe" || + params.SPIFFEID.Host != "foo.bar.com" || params.SPIFFEID.Path != "/server/workload/1" { + return nil, fmt.Errorf("custom authz check fails") + } + return &VerificationResults{}, nil + + }, + clientVType: CertVerification, + serverCert: []tls.Certificate{cs.serverPeerSPIFFE1}, + serverRoot: cs.serverTrust1, + serverVerifyFunc: func(params *VerificationFuncParams) (*VerificationResults, error) { + switch stage.read() { + case 0, 2: + if params.SPIFFEID == nil || params.SPIFFEID.Scheme != "spiffe" || + params.SPIFFEID.Host != "foo.bar.com" || params.SPIFFEID.Path != "/client/workload/1" { + return nil, fmt.Errorf("custom authz check fails") + } + return &VerificationResults{}, nil + case 1: + return nil, fmt.Errorf("custom authz check fails") + default: + return nil, fmt.Errorf("custom authz check fails") + } + }, + serverVType: CertVerification, + }, } { test := test t.Run(test.desc, func(t *testing.T) { diff --git a/security/advancedtls/testdata/README.md b/security/advancedtls/testdata/README.md index 48a1c135c44..d8ccededeb8 100644 --- a/security/advancedtls/testdata/README.md +++ b/security/advancedtls/testdata/README.md @@ -14,16 +14,16 @@ commands we run: $ openssl req -x509 -newkey rsa:4096 -keyout ca_key.pem -out ca_cert.pem -nodes -days $DURATION_DAYS ``` -2. Generate a CSR `csr.pem` using `subject_key.pem`: - +2. Generate a private key `subject_key.pem` for the subject: + ``` - $ openssl req -new -key subject_key.pem -out csr.pem + $ openssl genrsa -out subject_key.pem 4096 ``` -3. Generate a private key `subject_key.pem` for the subject: +3. Generate a CSR `csr.pem` using `subject_key.pem`: ``` - $ openssl genrsa -out subject_key.pem 4096 + $ openssl req -new -key subject_key.pem -out csr.pem ``` 4. Use `ca_key.pem` and `ca_cert.pem` to sign `csr.pem`, and get a certificate, `subject_cert.pem`, for the subject: diff --git a/security/advancedtls/testdata/client_cert_spiffe_1.pem b/security/advancedtls/testdata/client_cert_spiffe_1.pem new file mode 100644 index 00000000000..4d62d671d39 --- /dev/null +++ b/security/advancedtls/testdata/client_cert_spiffe_1.pem @@ -0,0 +1,125 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=VA, O=Internet Widgits Pty Ltd, CN=foo.bar.hoo.ca.com + Validity + Not Before: Oct 5 20:11:06 2020 GMT + Not After : May 27 20:11:06 2045 GMT + Subject: C=US, ST=CA, L=Sunnyvale, O=XX, OU=XXX, CN=foo.bar.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (4096 bit) + Modulus: + 00:bb:ee:3e:6d:79:0b:3c:33:b5:cb:ef:56:f7:a4: + 15:42:d4:94:05:c8:59:37:d1:d8:7c:44:40:dd:cd: + 9f:64:e1:c6:6d:c8:8d:a1:3a:85:df:34:3e:5b:23: + 1d:16:d1:c3:67:94:c9:35:21:cd:8f:80:46:a6:a2: + 78:c1:f6:c7:45:c3:f2:0a:9d:ad:2c:64:72:f6:5b: + 7b:79:dd:33:d7:5c:c0:9f:97:9e:45:8e:c9:30:33: + 6d:0e:24:b4:62:85:ab:ce:43:b3:25:98:31:39:f4: + d2:fe:ce:10:bf:53:e7:92:a5:b7:8d:a4:5b:e3:37: + ec:c5:06:8e:94:ee:10:d0:6e:dc:6b:90:08:c9:06: + 6d:01:79:ba:94:df:0b:20:3d:ae:a2:cc:7f:30:53: + 07:cb:8a:ca:77:80:d5:94:12:1a:2a:36:b3:f3:5e: + d7:51:02:00:2a:1e:f1:bd:89:0b:37:4f:dc:58:af: + 0f:74:14:01:21:20:8e:69:b6:e9:0d:da:52:21:ea: + 71:2b:64:69:a9:c9:fb:f8:7e:55:d7:8f:a0:c7:98: + cb:a7:e5:16:44:2f:39:d2:9b:ad:e7:4a:de:f8:3b: + 1b:65:a0:c9:50:ce:0a:6c:32:29:38:78:4a:f5:11: + 28:53:a9:c6:c1:85:2b:10:09:79:5a:54:9c:9f:1b: + b7:f7:16:66:3e:be:cb:2f:3b:e6:27:3e:d2:d1:c6: + f5:2b:d7:46:e7:22:6a:42:17:0c:cc:46:1d:12:e0: + 81:f8:6d:cc:58:2c:1c:0a:21:8d:0d:af:d5:a9:31: + 35:1f:99:14:3b:2c:32:c2:b2:8b:9d:39:cd:ee:40: + 22:7b:4e:a8:4a:f1:15:b2:51:4d:82:3c:0e:35:e7: + d1:79:d7:b9:0e:f9:9d:ba:d0:bf:17:fb:e2:df:55: + ac:f8:8e:e5:dc:f2:dc:50:1b:cc:a5:a2:2a:84:8a: + 75:16:a8:95:b2:6c:bc:21:d9:89:6f:c9:83:6d:f8: + 0f:26:26:de:f1:1a:ad:4e:8b:54:dd:43:e9:ef:04: + 92:71:75:bb:7f:3c:82:e9:1f:4e:c2:04:73:fd:c1: + 73:df:0a:ae:2d:c5:9a:5d:08:cf:28:ea:2e:1f:ee: + d7:8e:21:01:55:a1:8e:90:79:43:86:ac:6f:ec:58: + ca:e5:04:b2:a0:75:35:89:0e:09:d0:7c:03:b3:25: + e1:ff:42:ec:8e:b7:43:1f:9e:b3:71:51:a7:b5:42: + c8:27:f1:6d:9f:ae:4e:2c:d2:8b:0c:f9:90:7a:5c: + 93:ed:4a:8d:14:06:06:36:f0:a5:1b:6c:8e:85:46: + 9b:14:3f:b7:23:69:a1:d2:48:32:27:67:20:49:c8: + ce:a6:c1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + FD:25:82:CC:12:B6:0D:19:F6:94:A5:00:A7:E2:20:A0:C8:1B:05:FA + X509v3 Authority Key Identifier: + keyid:B4:19:08:1C:FC:10:23:C5:30:86:22:BC:CB:B1:5F:AD:EA:7A:5D:F1 + + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Key Encipherment + X509v3 Subject Alternative Name: + URI:spiffe://foo.bar.com/client/workload/1 + Signature Algorithm: sha256WithRSAEncryption + 4f:21:c8:46:e0:f7:04:a0:98:a5:02:b9:c1:6b:9b:29:26:26: + 9e:29:c1:42:8f:5c:71:4a:cc:5c:ff:d0:0c:02:6e:13:9f:89: + 8e:24:f9:92:6c:4f:97:25:fd:d3:03:6f:aa:8d:69:fa:b0:df: + 84:da:f6:47:af:3f:f3:17:5a:96:08:20:2d:df:78:a7:99:4f: + 5a:9b:5c:06:7c:e9:89:f0:04:47:75:b0:da:20:d2:3f:88:9e: + a2:79:59:23:54:8e:13:05:be:26:d4:b6:e2:70:78:3f:41:56: + 53:dc:ff:b7:22:04:12:38:75:c2:ec:da:b6:b3:3e:d0:1f:bc: + 80:78:b8:b4:4d:de:b8:34:b3:a9:30:9b:1d:af:2a:53:df:2c: + 7d:fe:c8:4c:93:a6:ad:3f:1b:73:31:56:4d:3b:3c:4f:b3:be: + 40:78:08:b7:65:fd:08:37:62:6e:bb:bc:22:7e:dd:d5:3a:ad: + 07:e1:31:24:c0:20:bf:0c:cc:85:60:b5:2c:34:e1:5f:f4:26: + f4:b2:8d:76:ae:de:0c:ca:17:2d:cb:ec:1d:66:b4:9b:9f:0b: + 2e:1a:64:ea:fa:52:4b:bb:bd:33:73:8d:bc:9f:8b:a6:24:ea: + 12:62:6b:60:23:f3:cb:e8:b9:f2:b3:ca:d2:0b:ea:76:3f:4c: + cf:cc:eb:4f:0e:5a:a6:66:96:7f:46:6f:15:e4:28:a3:dd:ea: + 93:24:c3:b3:99:3f:bc:b7:71:dc:24:28:5c:4c:21:b3:ca:6a: + 67:b0:a8:f4:00:c5:75:5e:6e:65:07:95:39:c2:2c:a6:bd:dc: + 78:61:19:29:9d:dd:1e:54:5e:3e:6f:fb:79:37:ff:06:8c:f5: + 50:cc:f2:4a:3b:03:e3:6e:7c:65:ad:c3:80:0e:79:d3:28:fd: + bf:4b:6a:b6:56:a6:2f:d0:a0:19:96:85:7e:69:46:b1:8c:4c: + c3:eb:43:86:15:06:e9:9e:90:d4:3d:85:28:3a:cf:6f:c4:e7: + d7:7d:61:29:ae:7a:99:2a:c7:26:48:84:01:43:98:97:b4:69: + 5a:47:eb:f5:33:bb:f8:a5:8d:6f:56:9e:01:58:f7:0d:8c:1b: + e3:8b:a9:e2:58:20:bf:27:f2:7b:7d:e4:a5:35:61:8e:12:57: + 4e:b7:31:09:73:13:0b:f9:b7:26:f9:d5:bb:c5:5d:f3:e4:d5: + b6:17:14:e5:99:39:36:e8:a9:a8:88:ca:da:79:45:cd:c8:66: + 5e:ad:78:b2:52:52:fb:06:b7:a3:4d:50:16:7e:af:d8:0e:6f: + 8f:48:40:57:97:6e:c3:19:cf:fb:bc:e4:3f:33:61:80:af:15: + 1b:d7:b3:20:3f:ed:ff:7d +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/security/advancedtls/testdata/client_key_spiffe_1.pem b/security/advancedtls/testdata/client_key_spiffe_1.pem new file mode 100644 index 00000000000..7f6e202345f --- /dev/null +++ b/security/advancedtls/testdata/client_key_spiffe_1.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/security/advancedtls/testdata/server_cert_spiffe_1.pem b/security/advancedtls/testdata/server_cert_spiffe_1.pem new file mode 100644 index 00000000000..e14a36f73b5 --- /dev/null +++ b/security/advancedtls/testdata/server_cert_spiffe_1.pem @@ -0,0 +1,125 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4 (0x4) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=CA, L=SVL, O=Internet Widgits Pty Ltd + Validity + Not Before: Oct 5 22:59:52 2020 GMT + Not After : May 27 22:59:52 2045 GMT + Subject: C=US, ST=CA, L=Sunnyvale, O=Internet Widgits Pty Ltd, OU=X, CN=XX + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (4096 bit) + Modulus: + 00:be:ab:c4:0b:d6:57:f2:22:62:8f:31:0d:7a:ac: + 70:d6:0a:b8:65:18:26:de:8e:00:18:34:62:6c:ed: + f7:6f:ed:68:14:31:de:6a:8f:f0:dd:74:1d:16:06: + fe:c4:20:b4:80:39:5d:19:8f:29:dd:e4:31:e8:c3: + 39:92:60:72:ad:1c:5e:0f:b1:f9:52:23:9f:42:1d: + f0:41:bb:a2:3b:4d:65:eb:03:ef:c9:86:27:34:e2: + 78:6f:31:44:f8:c7:c4:57:ad:59:3f:a2:8f:bc:87: + 5f:29:bc:76:0e:39:cd:68:a4:b1:64:5d:97:c6:c7: + c8:72:98:21:19:6e:57:11:b8:50:fc:be:02:b5:1d: + 51:15:65:0c:42:d9:30:d1:ff:68:8e:6f:e9:c5:52: + cf:5a:9f:b7:8a:b7:f6:a3:17:5a:7f:29:a1:32:fb: + f6:59:29:a1:81:34:39:20:21:f4:fb:64:79:76:57: + 73:87:3a:fc:9c:5d:f2:44:e4:be:8b:ed:c9:67:1d: + e1:57:d6:5f:32:b1:14:90:79:68:dc:f6:0a:5a:bf: + 92:18:56:e4:62:59:1c:56:5d:0c:aa:8a:92:14:b6: + 9e:3a:61:5c:86:b1:29:2d:67:11:d3:6d:62:bb:2b: + 65:79:a6:17:8c:b2:c4:ab:d1:4c:57:e2:d6:5d:20: + 39:11:2f:8c:79:3c:f4:ab:94:17:c1:97:21:c6:0f: + ee:d7:9c:0b:cd:0c:a5:98:34:45:51:d0:c7:53:73: + bd:f7:f6:0f:cc:21:58:be:ca:6d:14:b7:47:5f:62: + 29:b9:dc:e9:b5:a6:10:3b:50:67:26:df:1f:0a:e2: + aa:f6:4b:e3:71:93:57:a4:17:46:7d:fc:78:6c:6e: + 9d:34:11:84:24:ca:5b:16:c1:a9:ae:d3:96:d8:a9: + 4f:35:22:5e:43:54:1d:3d:dd:63:d5:e1:a3:0f:46: + dd:fa:43:96:8f:2b:67:55:6a:7e:b3:52:ae:52:56: + 4c:30:3a:5b:c0:43:77:f0:60:55:c9:1e:1b:5a:94: + d5:f9:2c:8f:61:e6:a4:74:20:db:6e:f8:11:41:00: + 25:e2:62:43:7a:51:f9:fa:83:95:85:c6:d3:c4:e5: + 28:11:35:43:84:05:b1:53:95:68:20:b4:85:9c:df: + 77:aa:1e:d3:7d:08:13:29:d7:82:53:bb:5a:36:ab: + 52:06:c4:95:aa:ac:9a:9e:25:a9:09:89:7c:48:16: + 8c:8e:4b:c4:9c:d2:a4:f5:3a:07:f3:00:22:60:f9: + 6c:00:5e:5a:ad:08:1d:5b:26:3b:5f:fc:51:20:98: + 97:1a:f1:39:15:ae:85:81:26:fb:77:a1:9c:a8:5c: + 9e:0e:c1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 59:2B:55:82:7F:3E:7C:09:B5:32:F2:F8:6A:88:17:13:46:90:17:54 + X509v3 Authority Key Identifier: + keyid:5A:A5:DA:B1:99:D4:E5:0E:E6:1E:94:EA:FF:FC:62:E2:ED:09:F1:06 + + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Key Encipherment + X509v3 Subject Alternative Name: + URI:spiffe://foo.bar.com/server/workload/1 + Signature Algorithm: sha256WithRSAEncryption + 74:bb:61:80:e7:24:5b:d0:33:88:db:bd:26:95:7f:c7:75:57: + 21:6a:8f:a3:a2:f4:d0:54:e9:76:7e:d9:a3:7b:60:bf:18:40: + 29:9b:ff:b9:b7:5b:b9:63:eb:ea:db:03:fe:90:55:f0:08:66: + 9d:f3:c0:25:24:ba:02:8f:dd:93:65:58:08:5c:30:ed:06:5b: + 0a:03:fc:9a:eb:f2:41:8e:e5:3e:ac:7a:d7:70:93:88:8b:75: + 68:49:dc:d0:b3:75:6b:66:44:a2:7c:fa:40:14:a1:d6:39:f3: + af:f0:3a:0c:9e:63:01:dc:2c:3c:f4:18:a7:f0:96:5a:3f:94: + 76:47:7b:65:24:0e:1d:2e:8e:8d:7c:70:c9:2f:73:de:9c:ba: + 1d:f5:24:0c:30:59:f5:83:f6:ad:3b:b2:c2:b3:7e:cd:ab:00: + 40:6b:79:8c:54:21:30:be:19:89:4c:3e:4a:3b:7f:41:92:ea: + b7:49:78:4f:d9:dd:bc:c0:35:8c:f6:3f:2f:27:db:b3:a9:25: + ce:99:a0:69:4e:72:1c:ed:59:12:10:02:90:63:11:51:23:83: + 20:92:62:df:e4:ce:20:cf:89:5b:66:a2:70:85:90:f5:a5:0b: + 92:c7:00:0b:90:05:58:a2:f0:ae:bd:81:3f:c8:cb:11:3f:b8: + 66:75:79:27:e0:a3:b7:bf:00:ae:b6:7e:b2:16:5c:8e:1d:ef: + 57:7e:13:7e:45:c6:68:03:28:72:85:06:69:c0:4d:08:c9:59: + 8e:56:5f:8e:82:6f:13:6c:f3:6e:7b:63:81:ff:8f:91:fc:32: + 64:b5:84:bb:ee:5f:a7:5c:70:b6:52:58:c4:6e:b9:db:20:44: + 70:be:31:ba:f4:3b:b8:50:47:f3:ca:1b:f1:41:62:4e:f5:6a: + 73:c2:79:a9:f7:ce:79:0f:0b:b0:ed:11:16:d3:4b:45:77:77: + 9e:75:95:50:a0:39:fe:b8:ae:73:f4:9b:17:e1:3e:89:a2:06: + 5c:1c:85:76:ba:24:90:1a:d8:02:91:f0:b3:98:d4:53:ba:fd: + 5b:77:ca:74:fb:45:b2:f8:58:60:23:bf:d3:bb:c2:9a:04:20: + f2:34:f5:52:4d:e1:6a:d9:c4:ff:b5:f0:be:bd:9a:01:46:7a: + d4:96:0c:2b:2a:6c:dd:a9:66:dc:e9:4c:f0:06:6d:89:88:c8: + 33:96:d9:32:44:2e:83:3e:17:75:3d:1d:f0:30:9f:57:72:77: + 40:9b:59:f6:d8:fc:48:ca:22:ed:bc:93:b8:f7:fd:07:69:67: + 29:b9:b8:8b:cd:15:4f:8c:be:dd:ce:aa:e2:ea:fa:9a:f6:30: + f6:a0:2b:f2:85:2d:94:62 +-----BEGIN CERTIFICATE----- +MIIFvzCCA6egAwIBAgIBBDANBgkqhkiG9w0BAQsFADBLMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExDDAKBgNVBAcMA1NWTDEhMB8GA1UECgwYSW50ZXJuZXQgV2lk +Z2l0cyBQdHkgTHRkMB4XDTIwMTAwNTIyNTk1MloXDTQ1MDUyNzIyNTk1MlowajEL +MAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxITAf +BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEKMAgGA1UECwwBWDELMAkG +A1UEAwwCWFgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC+q8QL1lfy +ImKPMQ16rHDWCrhlGCbejgAYNGJs7fdv7WgUMd5qj/DddB0WBv7EILSAOV0Zjynd +5DHowzmSYHKtHF4PsflSI59CHfBBu6I7TWXrA+/Jhic04nhvMUT4x8RXrVk/oo+8 +h18pvHYOOc1opLFkXZfGx8hymCEZblcRuFD8vgK1HVEVZQxC2TDR/2iOb+nFUs9a +n7eKt/ajF1p/KaEy+/ZZKaGBNDkgIfT7ZHl2V3OHOvycXfJE5L6L7clnHeFX1l8y +sRSQeWjc9gpav5IYVuRiWRxWXQyqipIUtp46YVyGsSktZxHTbWK7K2V5pheMssSr +0UxX4tZdIDkRL4x5PPSrlBfBlyHGD+7XnAvNDKWYNEVR0MdTc7339g/MIVi+ym0U +t0dfYim53Om1phA7UGcm3x8K4qr2S+Nxk1ekF0Z9/Hhsbp00EYQkylsWwamu05bY +qU81Il5DVB093WPV4aMPRt36Q5aPK2dVan6zUq5SVkwwOlvAQ3fwYFXJHhtalNX5 +LI9h5qR0INtu+BFBACXiYkN6Ufn6g5WFxtPE5SgRNUOEBbFTlWggtIWc33eqHtN9 +CBMp14JTu1o2q1IGxJWqrJqeJakJiXxIFoyOS8Sc0qT1OgfzACJg+WwAXlqtCB1b +Jjtf/FEgmJca8TkVroWBJvt3oZyoXJ4OwQIDAQABo4GOMIGLMB0GA1UdDgQWBBRZ +K1WCfz58CbUy8vhqiBcTRpAXVDAfBgNVHSMEGDAWgBRapdqxmdTlDuYelOr//GLi +7QnxBjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDAxBgNVHREEKjAohiZzcGlmZmU6 +Ly9mb28uYmFyLmNvbS9zZXJ2ZXIvd29ya2xvYWQvMTANBgkqhkiG9w0BAQsFAAOC +AgEAdLthgOckW9AziNu9JpV/x3VXIWqPo6L00FTpdn7Zo3tgvxhAKZv/ubdbuWPr +6tsD/pBV8AhmnfPAJSS6Ao/dk2VYCFww7QZbCgP8muvyQY7lPqx613CTiIt1aEnc +0LN1a2ZEonz6QBSh1jnzr/A6DJ5jAdwsPPQYp/CWWj+Udkd7ZSQOHS6OjXxwyS9z +3py6HfUkDDBZ9YP2rTuywrN+zasAQGt5jFQhML4ZiUw+Sjt/QZLqt0l4T9ndvMA1 +jPY/Lyfbs6klzpmgaU5yHO1ZEhACkGMRUSODIJJi3+TOIM+JW2aicIWQ9aULkscA +C5AFWKLwrr2BP8jLET+4ZnV5J+Cjt78ArrZ+shZcjh3vV34TfkXGaAMocoUGacBN +CMlZjlZfjoJvE2zzbntjgf+PkfwyZLWEu+5fp1xwtlJYxG652yBEcL4xuvQ7uFBH +88ob8UFiTvVqc8J5qffOeQ8LsO0RFtNLRXd3nnWVUKA5/riuc/SbF+E+iaIGXByF +drokkBrYApHws5jUU7r9W3fKdPtFsvhYYCO/07vCmgQg8jT1Uk3hatnE/7Xwvr2a +AUZ61JYMKyps3alm3OlM8AZtiYjIM5bZMkQugz4XdT0d8DCfV3J3QJtZ9tj8SMoi +7byTuPf9B2lnKbm4i80VT4y+3c6q4ur6mvYw9qAr8oUtlGI= +-----END CERTIFICATE----- diff --git a/security/advancedtls/testdata/server_key_spiffe_1.pem b/security/advancedtls/testdata/server_key_spiffe_1.pem new file mode 100644 index 00000000000..48c84412a87 --- /dev/null +++ b/security/advancedtls/testdata/server_key_spiffe_1.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY-----