diff --git a/credentials/tls/certprovider/pemfile/builder.go b/credentials/tls/certprovider/pemfile/builder.go index ad4207892b7e..58c7c434877f 100644 --- a/credentials/tls/certprovider/pemfile/builder.go +++ b/credentials/tls/certprovider/pemfile/builder.go @@ -63,19 +63,21 @@ func pluginConfigFromJSON(jd json.RawMessage) (Options, error) { // is that the refresh_interval is represented here as a duration proto, // while in the latter a time.Duration is used. cfg := &struct { - CertificateFile string `json:"certificate_file,omitempty"` - PrivateKeyFile string `json:"private_key_file,omitempty"` - CACertificateFile string `json:"ca_certificate_file,omitempty"` - RefreshInterval json.RawMessage `json:"refresh_interval,omitempty"` + CertificateFile string `json:"certificate_file,omitempty"` + PrivateKeyFile string `json:"private_key_file,omitempty"` + CACertificateFile string `json:"ca_certificate_file,omitempty"` + SPIFFETrustBundleMapFile string `json:"spiffe_trust_bundle_map_file,omitempty"` + RefreshInterval json.RawMessage `json:"refresh_interval,omitempty"` }{} if err := json.Unmarshal(jd, cfg); err != nil { return Options{}, fmt.Errorf("pemfile: json.Unmarshal(%s) failed: %v", string(jd), err) } opts := Options{ - CertFile: cfg.CertificateFile, - KeyFile: cfg.PrivateKeyFile, - RootFile: cfg.CACertificateFile, + CertFile: cfg.CertificateFile, + KeyFile: cfg.PrivateKeyFile, + RootFile: cfg.CACertificateFile, + SPIFFEBundleMapFile: cfg.SPIFFETrustBundleMapFile, // Refresh interval is the only field in the configuration for which we // support a default value. We cannot possibly have valid defaults for // file paths to watch. Also, it is valid to specify an empty path for diff --git a/credentials/tls/certprovider/pemfile/watcher.go b/credentials/tls/certprovider/pemfile/watcher.go index d7b5e1f1270e..bc9c545a7bf4 100644 --- a/credentials/tls/certprovider/pemfile/watcher.go +++ b/credentials/tls/certprovider/pemfile/watcher.go @@ -115,7 +115,7 @@ func newProvider(o Options) certprovider.Provider { if o.CertFile != "" && o.KeyFile != "" { provider.identityDistributor = newDistributor() } - if o.RootFile != "" { + if o.RootFile != "" || o.SPIFFEBundleMapFile != "" { provider.rootDistributor = newDistributor() } diff --git a/internal/credentials/spiffe/spiffe.go b/internal/credentials/spiffe/spiffe.go index e8a9cef8b227..7be008a19853 100644 --- a/internal/credentials/spiffe/spiffe.go +++ b/internal/credentials/spiffe/spiffe.go @@ -22,6 +22,7 @@ package spiffe import ( + "crypto/x509" "encoding/json" "fmt" @@ -61,3 +62,46 @@ func BundleMapFromBytes(bundleMapBytes []byte) (map[string]*spiffebundle.Bundle, } return bundleMap, nil } + +// GetRootsFromSPIFFEBundleMap returns the root trust certificates from the +// SPIFFE bundle map for the given trust domain from the leaf certificate. +func GetRootsFromSPIFFEBundleMap(bundleMap map[string]*spiffebundle.Bundle, leafCert *x509.Certificate) (*x509.CertPool, error) { + // 1. Upon receiving a peer certificate, verify that it is a well-formed SPIFFE + // leaf certificate. In particular, it must have a single URI SAN containing + // a well-formed SPIFFE ID ([SPIFFE ID format]). + spiffeID, err := idFromCert(leafCert) + if err != nil { + return nil, fmt.Errorf("spiffe: could not get spiffe ID from peer leaf cert but verification with spiffe trust map was configured: %v", err) + } + + // 2. Use the trust domain in the peer certificate's SPIFFE ID to lookup + // the SPIFFE trust bundle. If the trust domain is not contained in the + // configured trust map, reject the certificate. + spiffeBundle, ok := bundleMap[spiffeID.TrustDomain().Name()] + if !ok { + return nil, fmt.Errorf("spiffe: no bundle found for peer certificates trust domain %q but verification with a SPIFFE trust map was configured", spiffeID.TrustDomain().Name()) + } + roots := spiffeBundle.X509Authorities() + rootPool := x509.NewCertPool() + for _, root := range roots { + rootPool.AddCert(root) + } + return rootPool, nil +} + +// idFromCert parses the SPIFFE ID from the x509.Certificate. If the certificate +// does not have a valid SPIFFE ID, returns an error. +func idFromCert(cert *x509.Certificate) (*spiffeid.ID, error) { + if cert == nil { + return nil, fmt.Errorf("input cert is nil") + } + // A valid SPIFFE Certificate should have exactly one URI. + if len(cert.URIs) != 1 { + return nil, fmt.Errorf("input cert has %v URIs but should have 1", len(cert.URIs)) + } + id, err := spiffeid.FromURI(cert.URIs[0]) + if err != nil { + return nil, fmt.Errorf("invalid spiffeid: %v", err) + } + return &id, nil +} diff --git a/internal/credentials/spiffe/spiffe_test.go b/internal/credentials/spiffe/spiffe_test.go index c4ad015d72d1..fe1c3ae66bd5 100644 --- a/internal/credentials/spiffe/spiffe_test.go +++ b/internal/credentials/spiffe/spiffe_test.go @@ -22,51 +22,49 @@ import ( "crypto/x509" "encoding/pem" "io" + "net/url" "os" + "strings" "testing" - "github.com/spiffe/go-spiffe/v2/bundle/spiffebundle" "google.golang.org/grpc/testdata" ) -// loadSPIFFEBundleMap loads a SPIFFE Bundle Map from a file. See the SPIFFE -// Bundle Map spec for more detail - -// https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE_Trust_Domain_and_Bundle.md#4-spiffe-bundle-format -// If duplicate keys are encountered in the JSON parsing, Go's default unmarshal -// behavior occurs which causes the last processed entry to be the entry in the -// parsed map. -func loadSPIFFEBundleMap(filePath string) (map[string]*spiffebundle.Bundle, error) { - bundleMapRaw, err := os.ReadFile(filePath) +const wantURI = "spiffe://foo.bar.com/client/workload/1" + +func loadFileBytes(t *testing.T, filePath string) []byte { + bytes, err := os.ReadFile(filePath) if err != nil { - return nil, err + t.Fatalf("Error reading file: %v", err) } - return BundleMapFromBytes(bundleMapRaw) + return bytes } func TestKnownSPIFFEBundle(t *testing.T) { spiffeBundleFile := testdata.Path("spiffe/spiffebundle.json") - bundles, err := loadSPIFFEBundleMap(spiffeBundleFile) + spiffeBundleBytes := loadFileBytes(t, spiffeBundleFile) + bundles, err := BundleMapFromBytes(spiffeBundleBytes) if err != nil { - t.Fatalf("LoadSPIFFEBundleMap(%v) Error during parsing: %v", spiffeBundleFile, err) + t.Fatalf("BundleMapFromBytes(%v) error during parsing: %v", spiffeBundleFile, err) } - wantBundleSize := 2 + const wantBundleSize = 2 if len(bundles) != wantBundleSize { - t.Fatalf("LoadSPIFFEBundleMap(%v) did not parse correct bundle length. got %v want %v", spiffeBundleFile, len(bundles), wantBundleSize) + t.Fatalf("BundleMapFromBytes(%v) did not parse correct bundle length. got %v want %v", spiffeBundleFile, len(bundles), wantBundleSize) } if bundles["example.com"] == nil { - t.Fatalf("LoadSPIFFEBundleMap(%v) got no bundle for example.com", spiffeBundleFile) + t.Fatalf("BundleMapFromBytes(%v) got no bundle for example.com", spiffeBundleFile) } if bundles["test.example.com"] == nil { - t.Fatalf("LoadSPIFFEBundleMap(%v) got no bundle for test.example.com", spiffeBundleFile) + t.Fatalf("BundleMapFromBytes(%v) got no bundle for test.example.com", spiffeBundleFile) } - expectedExampleComCert := loadX509Cert(t, testdata.Path("spiffe/spiffe_cert.pem")) - expectedTestExampleComCert := loadX509Cert(t, testdata.Path("spiffe/server1_spiffe.pem")) - if !bundles["example.com"].X509Authorities()[0].Equal(expectedExampleComCert) { - t.Fatalf("LoadSPIFFEBundleMap(%v) parsed wrong cert for example.com.", spiffeBundleFile) + wantExampleComCert := loadX509Cert(t, testdata.Path("spiffe/spiffe_cert.pem")) + wantTestExampleComCert := loadX509Cert(t, testdata.Path("spiffe/server1_spiffe.pem")) + if !bundles["example.com"].X509Authorities()[0].Equal(wantExampleComCert) { + t.Errorf("BundleMapFromBytes(%v) parsed wrong cert for example.com.", spiffeBundleFile) } - if !bundles["test.example.com"].X509Authorities()[0].Equal(expectedTestExampleComCert) { - t.Fatalf("LoadSPIFFEBundleMap(%v) parsed wrong cert for test.example.com", spiffeBundleFile) + if !bundles["test.example.com"].X509Authorities()[0].Equal(wantTestExampleComCert) { + t.Errorf("BundleMapFromBytes(%v) parsed wrong cert for test.example.com", spiffeBundleFile) } } @@ -86,7 +84,7 @@ func loadX509Cert(t *testing.T, filePath string) *x509.Certificate { return cert } -func TestLoadSPIFFEBundleMapFailures(t *testing.T) { +func TestSPIFFEBundleMapFailures(t *testing.T) { filePaths := []string{ testdata.Path("spiffe/spiffebundle_corrupted_cert.json"), testdata.Path("spiffe/spiffebundle_malformed.json"), @@ -95,28 +93,154 @@ func TestLoadSPIFFEBundleMapFailures(t *testing.T) { testdata.Path("spiffe/spiffebundle_wrong_multi_certs.json"), testdata.Path("spiffe/spiffebundle_wrong_root.json"), testdata.Path("spiffe/spiffebundle_wrong_seq_type.json"), - testdata.Path("NOT_A_REAL_FILE"), testdata.Path("spiffe/spiffebundle_invalid_trustdomain.json"), + testdata.Path("spiffe/spiffebundle_empty_string_key.json"), + testdata.Path("spiffe/spiffebundle_empty_keys.json"), } for _, path := range filePaths { t.Run(path, func(t *testing.T) { - if _, err := loadSPIFFEBundleMap(path); err == nil { - t.Fatalf("LoadSPIFFEBundleMap(%v) did not fail but should have.", path) + bundleBytes := loadFileBytes(t, path) + if _, err := BundleMapFromBytes(bundleBytes); err == nil { + t.Fatalf("BundleMapFromBytes(%v) did not fail but should have", path) } }) } } -func TestLoadSPIFFEBundleMapX509Failures(t *testing.T) { +func TestSPIFFEBundleMapX509Failures(t *testing.T) { // SPIFFE Bundles only support a use of x509-svid and jwt-svid. If a // use other than this is specified, the parser does not fail, it // just doesn't add an x509 authority or jwt authority to the bundle filePath := testdata.Path("spiffe/spiffebundle_wrong_use.json") - bundle, err := loadSPIFFEBundleMap(filePath) + bundleBytes := loadFileBytes(t, filePath) + bundle, err := BundleMapFromBytes(bundleBytes) if err != nil { - t.Fatalf("LoadSPIFFEBundleMap(%v) failed with error: %v", filePath, err) + t.Fatalf("BundleMapFromBytes(%v) failed with error: %v", filePath, err) } if len(bundle["example.com"].X509Authorities()) != 0 { - t.Fatalf("LoadSPIFFEBundleMap(%v) did not have empty bundle but should have.", filePath) + t.Fatalf("BundleMapFromBytes(%v) did not have empty bundle but should have", filePath) + } +} + +func TestGetRootsFromSPIFFEBundleMapSuccess(t *testing.T) { + bundleMapFile := testdata.Path("spiffe/spiffebundle_match_client_spiffe.json") + bundleBytes := loadFileBytes(t, bundleMapFile) + bundle, err := BundleMapFromBytes(bundleBytes) + if err != nil { + t.Fatalf("BundleMapFromBytes(%v) failed with error: %v", bundleMapFile, err) + } + + cert := loadX509Cert(t, testdata.Path("spiffe/client_spiffe.pem")) + gotRoots, err := GetRootsFromSPIFFEBundleMap(bundle, cert) + if err != nil { + t.Fatalf("GetRootsFromSPIFFEBundleMap() failed with err %v", err) + } + wantRoot := loadX509Cert(t, testdata.Path("spiffe/spiffe_cert.pem")) + wantRoots := x509.NewCertPool() + wantRoots.AddCert(wantRoot) + if !gotRoots.Equal(wantRoots) { + t.Fatalf("GetRootsFromSPIFFEBundleMap() got %v want %v", gotRoots, wantRoots) + } +} + +func TestGetRootsFromSPIFFEBundleMapFailures(t *testing.T) { + bundleMapFile := testdata.Path("spiffe/spiffebundle.json") + bundleBytes := loadFileBytes(t, bundleMapFile) + bundle, err := BundleMapFromBytes(bundleBytes) + certWithTwoURIs := loadX509Cert(t, testdata.Path("spiffe/client_spiffe.pem")) + certWithTwoURIs.URIs = append(certWithTwoURIs.URIs, certWithTwoURIs.URIs[0]) + certWithNoURIs := loadX509Cert(t, testdata.Path("spiffe/client_spiffe.pem")) + certWithNoURIs.URIs = nil + if err != nil { + t.Fatalf("BundleMapFromBytes(%v) failed with error: %v", bundleMapFile, err) + } + tests := []struct { + name string + bundleMapFile string + leafCert *x509.Certificate + wantErr string + }{ + { + name: "no bundle for peer cert spiffeID", + leafCert: loadX509Cert(t, testdata.Path("spiffe/client_spiffe.pem")), + wantErr: "no bundle found for peer certificates", + }, + { + name: "cert has invalid SPIFFE id", + leafCert: loadX509Cert(t, testdata.Path("ca.pem")), + wantErr: "could not get spiffe ID from peer leaf cert", + }, + { + name: "nil cert", + leafCert: nil, + wantErr: "input cert is nil", + }, + { + name: "cert has multiple URIs", + leafCert: certWithTwoURIs, + wantErr: "input cert has 2 URIs but should have 1", + }, + { + name: "cert has no URIs", + leafCert: certWithNoURIs, + wantErr: "input cert has 0 URIs but should have 1", + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + _, err = GetRootsFromSPIFFEBundleMap(bundle, tc.leafCert) + if err == nil { + t.Fatalf("GetRootsFromSPIFFEBundleMap() got no error but want error containing %v.", tc.wantErr) + } + if !strings.Contains(err.Error(), tc.wantErr) { + t.Fatalf("GetRootsFromSPIFFEBundleMap() got error: %v. want error to contain %v", err, tc.wantErr) + } + }) + } +} + +func TestIDFromCert(t *testing.T) { + cert := loadX509Cert(t, testdata.Path("x509/spiffe_cert.pem")) + uri, err := idFromCert(cert) + if err != nil { + t.Fatalf("idFromCert() failed with err: %v", err) + } + if uri != nil && uri.String() != wantURI { + t.Fatalf("ID not expected, got %s, want %s", uri.String(), wantURI) + } +} + +func TestIDFromCertFileFailures(t *testing.T) { + certWithNoURIs := loadX509Cert(t, testdata.Path("spiffe/client_spiffe.pem")) + certWithNoURIs.URIs = nil + certWithInvalidSPIFFEID := loadX509Cert(t, testdata.Path("spiffe/client_spiffe.pem")) + certWithInvalidSPIFFEID.URIs = []*url.URL{{Path: "non-spiffe.bad"}} + tests := []struct { + name string + cert *x509.Certificate + }{ + { + name: "certificate with multiple URIs", + cert: loadX509Cert(t, testdata.Path("x509/multiple_uri_cert.pem")), + }, + { + name: "certificate with invalidSPIFFE ID", + cert: certWithInvalidSPIFFEID, + }, + { + name: "nil cert", + cert: nil, + }, + { + name: "cert with no URIs", + cert: certWithNoURIs, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if _, err := idFromCert(tt.cert); err == nil { + t.Fatalf("idFromCert() succeeded but want error") + } + }) } } diff --git a/internal/testutils/tls_creds.go b/internal/testutils/tls_creds.go index d93151380c16..680f688d635a 100644 --- a/internal/testutils/tls_creds.go +++ b/internal/testutils/tls_creds.go @@ -74,3 +74,83 @@ func CreateServerTLSCredentials(t *testing.T, clientAuth tls.ClientAuthType) cre ClientCAs: ca, }) } + +// CreateServerTLSCredentialsCompatibleWithSPIFFE creates server-side TLS +// transport credentials using certificate and key files from the +// testdata/spiffe_end2end directory. These credentials are compatible with the +// SPIFFE trust bundles used on the client side. +func CreateServerTLSCredentialsCompatibleWithSPIFFE(t *testing.T, clientAuth tls.ClientAuthType) credentials.TransportCredentials { + t.Helper() + + cert, err := tls.LoadX509KeyPair(testdata.Path("spiffe_end2end/server_spiffe.pem"), testdata.Path("spiffe_end2end/server.key")) + if err != nil { + t.Fatalf("tls.LoadX509KeyPair(spiffe_end2end/server_spiffe.pem, spiffe_end2end/server.key) failed: %v", err) + } + b, err := os.ReadFile(testdata.Path("spiffe_end2end/ca.pem")) + if err != nil { + t.Fatalf("os.ReadFile(spiffe_end2end/ca.pem) failed: %v", err) + } + ca := x509.NewCertPool() + if !ca.AppendCertsFromPEM(b) { + t.Fatal("Failed to append certificates") + } + return credentials.NewTLS(&tls.Config{ + ClientAuth: clientAuth, + Certificates: []tls.Certificate{cert}, + ClientCAs: ca, + }) +} + +// CreateServerTLSCredentialsCompatibleWithSPIFFEChain creates server-side TLS +// transport credentials using a certificate chain and key files from the +// testdata/spiffe_end2end directory. These credentials are compatible with the +// SPIFFE trust bundles used on the client side. +func CreateServerTLSCredentialsCompatibleWithSPIFFEChain(t *testing.T, clientAuth tls.ClientAuthType) credentials.TransportCredentials { + t.Helper() + + certs, err := tls.LoadX509KeyPair(testdata.Path("spiffe_end2end/leaf_and_intermediate_chain.pem"), testdata.Path("spiffe_end2end/leaf_signed_by_intermediate.key")) + if err != nil { + t.Fatalf("tls.LoadX509KeyPair(spiffe_end2end/leaf_and_intermediate_chain.pem, spiffe_end2end/leaf_signed_by_intermediate.key) failed: %v", err) + } + b, err := os.ReadFile(testdata.Path("spiffe_end2end/ca.pem")) + if err != nil { + t.Fatalf("os.ReadFile(spiffe_end2end/ca.pem) failed: %v", err) + } + ca := x509.NewCertPool() + if !ca.AppendCertsFromPEM(b) { + t.Fatal("Failed to append certificates") + } + return credentials.NewTLS(&tls.Config{ + ClientAuth: clientAuth, + Certificates: []tls.Certificate{certs}, + ClientCAs: ca, + }) +} + +// CreateServerTLSCredentialsValidSPIFFEButWrongCA creates server-side TLS +// transport credentials using certificate and key files from the +// testdata/spiffe directory rather than the testdata/spiffe_end2end directory. +// These credentials have the expected trust domains and SPIFFE IDs that are +// compatible with testdata/spiffe_end2end client files, but they are signed by +// a different CA and will thus fail the connection. +func CreateServerTLSCredentialsValidSPIFFEButWrongCA(t *testing.T, clientAuth tls.ClientAuthType) credentials.TransportCredentials { + t.Helper() + + cert, err := tls.LoadX509KeyPair(testdata.Path("spiffe/server1_spiffe.pem"), testdata.Path("server1.key")) + if err != nil { + t.Fatalf("tls.LoadX509KeyPair(spiffe/server1_spiffe.pem, spiffe/server.key) failed: %v", err) + } + b, err := os.ReadFile(testdata.Path("spiffe_end2end/ca.pem")) + if err != nil { + t.Fatalf("os.ReadFile(spiffe_end2end/ca.pem) failed: %v", err) + } + ca := x509.NewCertPool() + if !ca.AppendCertsFromPEM(b) { + t.Fatal("Failed to append certificates") + } + return credentials.NewTLS(&tls.Config{ + ClientAuth: clientAuth, + Certificates: []tls.Certificate{cert}, + ClientCAs: ca, + }) +} diff --git a/internal/xds/bootstrap/tlscreds/bundle.go b/internal/xds/bootstrap/tlscreds/bundle.go index ed90720b581f..7b9631adeeb4 100644 --- a/internal/xds/bootstrap/tlscreds/bundle.go +++ b/internal/xds/bootstrap/tlscreds/bundle.go @@ -23,15 +23,19 @@ package tlscreds import ( "context" "crypto/tls" + "crypto/x509" "encoding/json" "errors" "fmt" "net" "sync" + "time" + "github.com/spiffe/go-spiffe/v2/bundle/spiffebundle" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/tls/certprovider" "google.golang.org/grpc/credentials/tls/certprovider/pemfile" + "google.golang.org/grpc/internal/credentials/spiffe" ) // bundle is an implementation of credentials.Bundle which implements mTLS @@ -48,9 +52,10 @@ type bundle struct { // See gRFC A65: github.com/grpc/proposal/blob/master/A65-xds-mtls-creds-in-bootstrap.md func NewBundle(jd json.RawMessage) (credentials.Bundle, func(), error) { cfg := &struct { - CertificateFile string `json:"certificate_file"` - CACertificateFile string `json:"ca_certificate_file"` - PrivateKeyFile string `json:"private_key_file"` + CertificateFile string `json:"certificate_file"` + CACertificateFile string `json:"ca_certificate_file"` + PrivateKeyFile string `json:"private_key_file"` + SPIFFETrustBundleMapFile string `json:"spiffe_trust_bundle_map_file"` }{} if jd != nil { @@ -59,7 +64,7 @@ func NewBundle(jd json.RawMessage) (credentials.Bundle, func(), error) { } } // Else the config field is absent. Treat it as an empty config. - if cfg.CACertificateFile == "" && cfg.CertificateFile == "" && cfg.PrivateKeyFile == "" { + if cfg.CACertificateFile == "" && cfg.CertificateFile == "" && cfg.PrivateKeyFile == "" && cfg.SPIFFETrustBundleMapFile == "" { // We cannot use (and do not need) a file_watcher provider in this case, // and can simply directly use the TLS transport credentials. // Quoting A65: @@ -69,6 +74,8 @@ func NewBundle(jd json.RawMessage) (credentials.Bundle, func(), error) { // > provider, at least one of the "certificate_file" or // > "ca_certificate_file" fields must be specified, whereas in this // > configuration, it is acceptable to specify neither one. + // Further, with the introduction of SPIFFE Trust Map support, we also + // check for this value. return &bundle{transportCredentials: credentials.NewTLS(&tls.Config{})}, func() {}, nil } // Otherwise we need to use a file_watcher provider to watch the CA, @@ -114,9 +121,18 @@ func (c *reloadingCreds) ClientHandshake(ctx context.Context, authority string, if err != nil { return nil, nil, err } - config := &tls.Config{ - RootCAs: km.Roots, - Certificates: km.Certs, + var config *tls.Config + if km.SPIFFEBundleMap != nil { + config = &tls.Config{ + InsecureSkipVerify: true, + VerifyPeerCertificate: buildSPIFFEVerifyFunc(km.SPIFFEBundleMap), + Certificates: km.Certs, + } + } else { + config = &tls.Config{ + RootCAs: km.Roots, + Certificates: km.Certs, + } } return credentials.NewTLS(config).ClientHandshake(ctx, authority, rawConn) } @@ -136,3 +152,39 @@ func (c *reloadingCreds) OverrideServerName(string) error { func (c *reloadingCreds) ServerHandshake(net.Conn) (net.Conn, credentials.AuthInfo, error) { return nil, nil, errors.New("server handshake is not supported by xDS client TLS credentials") } + +func buildSPIFFEVerifyFunc(spiffeBundleMap map[string]*spiffebundle.Bundle) func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { + return func(rawCerts [][]byte, _ [][]*x509.Certificate) error { + rawCertList := make([]*x509.Certificate, len(rawCerts)) + for i, asn1Data := range rawCerts { + cert, err := x509.ParseCertificate(asn1Data) + if err != nil { + return fmt.Errorf("spiffe: verify function could not parse input certificate: %v", err) + } + rawCertList[i] = cert + } + if len(rawCertList) == 0 { + return fmt.Errorf("spiffe: verify function has no valid input certificates") + } + leafCert := rawCertList[0] + roots, err := spiffe.GetRootsFromSPIFFEBundleMap(spiffeBundleMap, leafCert) + if err != nil { + return err + } + + opts := x509.VerifyOptions{ + Roots: roots, + CurrentTime: time.Now(), + Intermediates: x509.NewCertPool(), + } + + for _, cert := range rawCertList[1:] { + opts.Intermediates.AddCert(cert) + } + // The verified chain is (surprisingly) unused. + if _, err = rawCertList[0].Verify(opts); err != nil { + return fmt.Errorf("spiffe: x509 certificate Verify failed: %v", err) + } + return nil + } +} diff --git a/internal/xds/bootstrap/tlscreds/bundle_ext_test.go b/internal/xds/bootstrap/tlscreds/bundle_ext_test.go index ec1cc3f224f2..7cefffba432d 100644 --- a/internal/xds/bootstrap/tlscreds/bundle_ext_test.go +++ b/internal/xds/bootstrap/tlscreds/bundle_ext_test.go @@ -58,6 +58,7 @@ func (s) TestValidTlsBuilder(t *testing.T) { caCert := testdata.Path("x509/server_ca_cert.pem") clientCert := testdata.Path("x509/client1_cert.pem") clientKey := testdata.Path("x509/client1_key.pem") + clientSpiffeBundle := testdata.Path("spiffe_end2end/client_spiffe.json") tests := []struct { name string jd string @@ -97,6 +98,10 @@ func (s) TestValidTlsBuilder(t *testing.T) { name: "Refresh interval, CA chain, private key and certificate chain", jd: fmt.Sprintf(`{"refresh_interval": "1s","ca_certificate_file":"%s","certificate_file":"%s","private_key_file":"%s"}`, caCert, clientCert, clientKey), }, + { + name: "Refresh interval, CA chain, private key, certificate chain, spiffe bundle", + jd: fmt.Sprintf(`{"refresh_interval": "1s","ca_certificate_file":"%s","certificate_file":"%s","private_key_file":"%s","spiffe_trust_bundle_map_file":"%s"}`, caCert, clientCert, clientKey, clientSpiffeBundle), + }, { name: "Unknown field", jd: `{"unknown_field": "foo"}`, @@ -198,7 +203,6 @@ func (s) TestCaReloading(t *testing.T) { if err != nil { t.Fatalf("Failed to write test CA cert: %v", err) } - for ; ctx.Err() == nil; <-time.After(10 * time.Millisecond) { ss := stubserver.StubServer{ Address: server.Address, @@ -224,6 +228,101 @@ func (s) TestCaReloading(t *testing.T) { } } +// Test_SPIFFE_Reloading sets up a client and server. The client is configured +// to use a SPIFFE bundle map, and the server is configured to use TLS creds +// compatible with this bundle. A handshake is performed and connection is +// expected to be successful. Then we change the client's SPIFFE Bundle Map file +// on disk to one that should fail with the server's credentials. This change +// should be picked up by the client via our file reloading. Another handshake +// is performed and checked for failure, ensuring that gRPC is correctly using +// the changed-on-disk bundle map. +func (s) Test_SPIFFE_Reloading(t *testing.T) { + clientSPIFFEBundle, err := os.ReadFile(testdata.Path("spiffe_end2end/client_spiffebundle.json")) + if err != nil { + t.Fatalf("Failed to read test SPIFFE bundle: %v", err) + } + + // Write CA certs to a temporary file so that we can modify it later. + spiffePath := t.TempDir() + "/client_spiffe.json" + if err = os.WriteFile(spiffePath, clientSPIFFEBundle, 0644); err != nil { + t.Fatalf("Failed to write test SPIFFE Bundle %v: %v", clientSPIFFEBundle, err) + } + cfg := fmt.Sprintf(`{ + "spiffe_trust_bundle_map_file": "%s", + "refresh_interval": ".01s" + }`, spiffePath) + tlsBundle, stop, err := tlscreds.NewBundle([]byte(cfg)) + if err != nil { + t.Fatalf("Failed to create TLS bundle: %v", err) + } + defer stop() + + l, err := testutils.LocalTCPListener() + if err != nil { + t.Fatalf("testutils.LocalTCPListener() failed: %v", err) + } + lis := testutils.NewRestartableListener(l) + defer lis.Close() + ss := stubserver.StubServer{ + Listener: lis, + EmptyCallF: func(context.Context, *testpb.Empty) (*testpb.Empty, error) { return &testpb.Empty{}, nil }, + } + + serverCredentials := grpc.Creds(testutils.CreateServerTLSCredentialsCompatibleWithSPIFFE(t, tls.NoClientCert)) + server := stubserver.StartTestService(t, &ss, serverCredentials) + + defer server.Stop() + + conn, err := grpc.NewClient( + server.Address, + grpc.WithCredentialsBundle(tlsBundle), + grpc.WithAuthority("x.test.example.com"), + ) + if err != nil { + t.Fatalf("grpc.NewClient(%q) failed: %v", server.Address, err) + } + defer conn.Close() + + ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) + defer cancel() + + client := testgrpc.NewTestServiceClient(conn) + if _, err = client.EmptyCall(ctx, &testpb.Empty{}); err != nil { + t.Errorf("Error calling EmptyCall: %v", err) + } + + // Setup the wrong bundle to be reloaded + wrongBundle, err := os.ReadFile(testdata.Path("spiffe_end2end/server_spiffebundle.json")) + if err != nil { + t.Fatalf("Failed to read test spiffe bundle %v: %v", "spiffe_end2end/server_spiffebundle.json", err) + } + // Write the bundle that will fail to the tmp file path to be reloaded + err = os.WriteFile(spiffePath, wrongBundle, 0644) + if err != nil { + t.Fatalf("Failed to write test spiffe bundle %v: %v", "spiffe_end2end/server_spiffebundle.json", err) + } + + for ; ctx.Err() == nil; <-time.After(10 * time.Millisecond) { + // Stop and restart the listener to force new handshakes + lis.Stop() + lis.Restart() + // Client handshake should eventually fail because the client CA was + // reloaded, and thus the server cert is signed by an unknown CA. + t.Log(server) + _, err = client.EmptyCall(ctx, &testpb.Empty{}) + const wantErr = "no bundle found for peer certificates trust domain" + if status.Code(err) == codes.Unavailable && strings.Contains(err.Error(), wantErr) { + // Certs have reloaded. + server.Stop() + break + } + t.Logf("EmptyCall() got err: %s, want code: %s, want err: %s", err, codes.Unavailable, wantErr) + } + if ctx.Err() != nil { + t.Errorf("Timed out waiting for CA certs reloading") + } +} + func (s) TestMTLS(t *testing.T) { s := stubserver.StartTestService(t, nil, grpc.Creds(testutils.CreateServerTLSCredentials(t, tls.RequireAndVerifyClientCert))) defer s.Stop() @@ -253,3 +352,129 @@ func (s) TestMTLS(t *testing.T) { t.Errorf("EmptyCall(): got error %v when expected to succeed", err) } } + +// Test_MTLS_SPIFFE configures a client and server. The server has a certificate +// chain that is compatible with the client's configured SPIFFE bundle map. An +// MTLS connection is attempted between the two and checked for success. +func (s) Test_MTLS_SPIFFE(t *testing.T) { + tests := []struct { + name string + serverOption grpc.ServerOption + }{ + { + name: "MTLS SPIFFE", + serverOption: grpc.Creds(testutils.CreateServerTLSCredentialsCompatibleWithSPIFFE(t, tls.RequireAndVerifyClientCert)), + }, + { + name: "MTLS SPIFFE Chain", + serverOption: grpc.Creds(testutils.CreateServerTLSCredentialsCompatibleWithSPIFFEChain(t, tls.RequireAndVerifyClientCert)), + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + s := stubserver.StartTestService(t, nil, grpc.Creds(testutils.CreateServerTLSCredentialsCompatibleWithSPIFFE(t, tls.RequireAndVerifyClientCert))) + defer s.Stop() + + cfg := fmt.Sprintf(`{ + "certificate_file": "%s", + "private_key_file": "%s", + "spiffe_trust_bundle_map_file": "%s" +}`, + testdata.Path("spiffe_end2end/client_spiffe.pem"), + testdata.Path("spiffe_end2end/client.key"), + testdata.Path("spiffe_end2end/client_spiffebundle.json")) + tlsBundle, stop, err := tlscreds.NewBundle([]byte(cfg)) + if err != nil { + t.Fatalf("Failed to create TLS bundle: %v", err) + } + defer stop() + conn, err := grpc.NewClient(s.Address, grpc.WithCredentialsBundle(tlsBundle), grpc.WithAuthority("x.test.example.com")) + if err != nil { + t.Fatalf("Error dialing: %v", err) + } + defer conn.Close() + client := testgrpc.NewTestServiceClient(conn) + ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) + defer cancel() + if _, err = client.EmptyCall(ctx, &testpb.Empty{}); err != nil { + t.Errorf("EmptyCall(): got error %v when expected to succeed", err) + } + }) + } +} + +func (s) Test_MTLS_SPIFFE_Failure(t *testing.T) { + tests := []struct { + name string + certFile string + keyFile string + spiffeBundleFile string + serverOption grpc.ServerOption + wantErrContains string + wantErrCode codes.Code + }{ + { + name: "No matching trust domain in bundle", + certFile: "spiffe_end2end/client_spiffe.pem", + keyFile: "spiffe_end2end/client.key", + spiffeBundleFile: "spiffe_end2end/server_spiffebundle.json", + serverOption: grpc.Creds(testutils.CreateServerTLSCredentialsCompatibleWithSPIFFE(t, tls.RequireAndVerifyClientCert)), + wantErrContains: "spiffe: no bundle found for peer certificates", + wantErrCode: codes.Unavailable, + }, + { + name: "Server cert has no valid SPIFFE URIs", + certFile: "spiffe_end2end/client_spiffe.pem", + keyFile: "spiffe_end2end/client.key", + spiffeBundleFile: "spiffe_end2end/client_spiffebundle.json", + serverOption: grpc.Creds(testutils.CreateServerTLSCredentials(t, tls.RequireAndVerifyClientCert)), + wantErrContains: "spiffe: could not get spiffe ID from peer leaf cert", + wantErrCode: codes.Unavailable, + }, + { + name: "Server cert has valid spiffe ID but doesn't chain to the root CA", + certFile: "spiffe_end2end/client_spiffe.pem", + keyFile: "spiffe_end2end/client.key", + spiffeBundleFile: "spiffe_end2end/client_spiffebundle.json", + serverOption: grpc.Creds(testutils.CreateServerTLSCredentialsValidSPIFFEButWrongCA(t, tls.RequireAndVerifyClientCert)), + wantErrContains: "spiffe: x509 certificate Verify failed: x509: certificate signed by unknown authority", + wantErrCode: codes.Unavailable, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + s := stubserver.StartTestService(t, nil, tc.serverOption) + defer s.Stop() + cfg := fmt.Sprintf(`{ +"certificate_file": "%s", +"private_key_file": "%s", +"spiffe_trust_bundle_map_file": "%s" +}`, + testdata.Path(tc.certFile), + testdata.Path(tc.keyFile), + testdata.Path(tc.spiffeBundleFile)) + tlsBundle, stop, err := tlscreds.NewBundle([]byte(cfg)) + if err != nil { + t.Fatalf("Failed to create TLS bundle: %v", err) + } + defer stop() + conn, err := grpc.NewClient(s.Address, grpc.WithCredentialsBundle(tlsBundle), grpc.WithAuthority("x.test.example.com")) + if err != nil { + t.Fatalf("grpc.NewClient(%q) failed: %v", s.Address, err) + } + defer conn.Close() + client := testgrpc.NewTestServiceClient(conn) + ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) + defer cancel() + if _, err = client.EmptyCall(ctx, &testpb.Empty{}); err == nil { + t.Errorf("EmptyCall(): got success. want failure") + } + if status.Code(err) != tc.wantErrCode { + t.Errorf("EmptyCall(): failed with wrong error. got code %v. want code: %v", status.Code(err), tc.wantErrCode) + } + if !strings.Contains(err.Error(), tc.wantErrContains) { + t.Errorf("EmptyCall(): failed with wrong error. got %v. want contains: %v", err, tc.wantErrContains) + } + }) + } +} diff --git a/internal/xds/bootstrap/tlscreds/bundle_test.go b/internal/xds/bootstrap/tlscreds/bundle_test.go index 5f99dd9e0b00..9e2e449e9246 100644 --- a/internal/xds/bootstrap/tlscreds/bundle_test.go +++ b/internal/xds/bootstrap/tlscreds/bundle_test.go @@ -21,14 +21,18 @@ package tlscreds import ( "context" "crypto/tls" + "crypto/x509" + "encoding/pem" "errors" "fmt" + "os" "strings" "testing" "time" "google.golang.org/grpc" "google.golang.org/grpc/credentials/tls/certprovider" + "google.golang.org/grpc/internal/credentials/spiffe" "google.golang.org/grpc/internal/grpctest" "google.golang.org/grpc/internal/stubserver" "google.golang.org/grpc/internal/testutils" @@ -63,11 +67,13 @@ func (s) TestFailingProvider(t *testing.T) { cfg := fmt.Sprintf(`{ "ca_certificate_file": "%s", "certificate_file": "%s", - "private_key_file": "%s" + "private_key_file": "%s", + "spiffe_trust_bundle_map_file": "%s" }`, testdata.Path("x509/server_ca_cert.pem"), testdata.Path("x509/client1_cert.pem"), - testdata.Path("x509/client1_key.pem")) + testdata.Path("x509/client1_key.pem"), + testdata.Path("spiffe_end2end/client_spiffebundle.json")) tlsBundle, stop, err := NewBundle([]byte(cfg)) if err != nil { t.Fatalf("Failed to create TLS bundle: %v", err) @@ -96,3 +102,61 @@ func (s) TestFailingProvider(t *testing.T) { t.Errorf("EmptyCall() got err: %s, want err to contain: %s", err, wantErr) } } + +func rawCertsFromFile(t *testing.T, filePath string) [][]byte { + t.Helper() + rawCert, err := os.ReadFile(testdata.Path(filePath)) + if err != nil { + t.Fatalf("Reading certificate file failed: %v", err) + } + block, _ := pem.Decode(rawCert) + if block == nil || block.Type != "CERTIFICATE" { + t.Fatalf("pem.Decode() failed to decode certificate in file %q", "spiffe/server1_spiffe.pem") + } + return [][]byte{block.Bytes} +} + +func (s) TestSPIFFEVerifyFuncMismatchedCert(t *testing.T) { + spiffeBundleBytes, err := os.ReadFile(testdata.Path("spiffe_end2end/client_spiffebundle.json")) + if err != nil { + t.Fatalf("Reading spiffebundle file failed: %v", err) + } + spiffeBundle, err := spiffe.BundleMapFromBytes(spiffeBundleBytes) + if err != nil { + t.Fatalf("spiffe.BundleMapFromBytes() failed: %v", err) + } + verifyFunc := buildSPIFFEVerifyFunc(spiffeBundle) + verifiedChains := [][]*x509.Certificate{} + tests := []struct { + name string + rawCerts [][]byte + wantErrContains string + }{ + { + name: "mismathed cert", + rawCerts: rawCertsFromFile(t, "spiffe/server1_spiffe.pem"), + wantErrContains: "spiffe: x509 certificate Verify failed", + }, + { + name: "bad input cert", + rawCerts: [][]byte{[]byte("NOT_GOOD_DATA")}, + wantErrContains: "spiffe: verify function could not parse input certificate", + }, + { + name: "no input bytes", + rawCerts: nil, + wantErrContains: "no valid input certificates", + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err = verifyFunc(tc.rawCerts, verifiedChains) + if err == nil { + t.Fatalf("buildSPIFFEVerifyFunc call succeeded. want failure") + } + if !strings.Contains(err.Error(), tc.wantErrContains) { + t.Fatalf("buildSPIFFEVerifyFunc got err %v want err to contain %v", err, tc.wantErrContains) + } + }) + } +} diff --git a/testdata/spiffe/README.md b/testdata/spiffe/README.md index eb834f032116..99dfa90b3083 100644 --- a/testdata/spiffe/README.md +++ b/testdata/spiffe/README.md @@ -12,9 +12,14 @@ It is just the `example.com` trust domain from spiffebundle.json. * spiffebundle_corrupted_cert.json - manually modifies the `x5c` field and removes a character to create an invalid certificate +* spiffebundle_empty_keys.json - the `keys` field is an empty array +* spiffebundle_empty_string_keys.json - the `keys` field contains an entry +* with an empty string key * spiffebundle_invalid_trustdomain - uses a `#` in the trust domain which is a disallowed character per the spec * spiffebundle_malformed.json - a fully wrong json +* spiffebundle_match_client_spiffe.json - a valid spiffe bundle with a trust + domain matching the SPIFFE ID in spiffe_cert.pem * spiffebundle_wrong_kid.json - has the `kid` field instead of the `kty` field * spiffebundle_wrong_kty.json - Uses `EC` instead of `RSA` in the `kty` field * spiffebundle_wrong_multi_certs.json - place 2 certificates in the `x5c` diff --git a/testdata/spiffe/spiffebundle_empty_keys.json b/testdata/spiffe/spiffebundle_empty_keys.json new file mode 100644 index 000000000000..f12b20366a79 --- /dev/null +++ b/testdata/spiffe/spiffebundle_empty_keys.json @@ -0,0 +1,9 @@ +{ + "trust_domains": { + "": { + "spiffe_sequence": 12035488, + "keys": [ + ] + } + } +} diff --git a/testdata/spiffe/spiffebundle_empty_string_key.json b/testdata/spiffe/spiffebundle_empty_string_key.json new file mode 100644 index 000000000000..f213f6196327 --- /dev/null +++ b/testdata/spiffe/spiffebundle_empty_string_key.json @@ -0,0 +1,18 @@ +{ + "trust_domains": { + "": { + "spiffe_sequence": 12035488, + "keys": [ + { + "kty": "RSA", + "use": "x509-svid", + "x5c": [ + "MIIFsjCCA5qgAwIBAgIURygVMMzdr+Q7rsUaz189JozyHMwwDQYJKoZIhvcNAQELBQAwTjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTVkwxDTALBgNVBAoMBGdSUEMxFTATBgNVBAMMDHRlc3QtY2xpZW50MTAeFw0yMTEyMjMxODQyNTJaFw0zMTEyMjExODQyNTJaME4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU1ZMMQ0wCwYDVQQKDARnUlBDMRUwEwYDVQQDDAx0ZXN0LWNsaWVudDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ4AqpGetyVSqGUuBJLVFla+7bEfca7UYzfVSSZLZ/X+JDmWIVN8UIPuFib5jhMEc3XaUnFXUmM7zEtz/ZG5hapwLwOb2C3ZxOP6PQjYCJxbkLie+b43UQrFu1xxd3vMhVJgcj/AIxEpmszuqOa6kUrkYifjJADQ+64kZgl66bsTdXMCzpxyFl9xUfff59L8OX+HUfAcoZz3emjg3ZJPYURQEmjdZTOau1EjFilwHgd989Jt7NKgx30NXoHmw7nusVBIY94fL2VKN3f1XVm0dHu5NI279Q6zr0ZBU7k5T3IeHnzsUesQS4NGlklDWoVTKk73Uv9Pna8yQsSW757PEbHOGp9Knu4bnoGPOlsG81yIPipO6hTgGFK24pF97M9kpGbWqYX4+2vLlrCAfcmsHqaUPmQlYeRVTT6vw7ctYo2kyUYGtnODXk76LqewRBVvkzx75QUhfjAyb740YcDmIenc56Tq6gebJHjhEmVSehR6xIpXP7SVeurTyhPsEQnpJHtgs4dcwWOZp7BvPNzHXmJqfr7vsshie3vS5kQ0u1e1yqAqXgyDjqKXOkx+dpgUTehSJHhPNHvTc5LXRsvvXKYz6FrwR/DZ8t7BNEvPeLjFgxpH7QVJFLCvCbXs5K6yYbsnLfxFIBPRnrbJkIsK+sQwnRdnsiUdPsTkG5B2lQfQIDAQABo4GHMIGEMB0GA1UdDgQWBBQ2lBp0PiRHHvQ5IRURm8aHsj4RETAfBgNVHSMEGDAWgBQ2lBp0PiRHHvQ5IRURm8aHsj4RETAPBgNVHRMBAf8EBTADAQH/MDEGA1UdEQQqMCiGJnNwaWZmZTovL2Zvby5iYXIuY29tL2NsaWVudC93b3JrbG9hZC8xMA0GCSqGSIb3DQEBCwUAA4ICAQA1mSkgRclAl+E/aS9zJ7t8+Y4n3T24nOKKveSIjxXm/zjhWqVsLYBI6kglWtih2+PELvU8JdPqNZK34Kl0Q6FWpVSGDdWN1i6NyORt2ocggL3ke3iXxRk3UpUKJmqwz81VhA2KUHnMlyE0IufFfZNwNWWHBv13uJfRbjeQpKPhU+yf4DeXrsWcvrZlGvAET+mcplafUzCp7Iv+PcISJtUerbxbVtuHVeZCLlgDXWkLAWJN8rf0dIG4x060LJ+j6j9uRVhb9sZn1HJV+j4XdIYm1VKilluhOtNwP2d3Ox/JuTBxf7hFHXZPfMagQE5k5PzmxRaCAEMJ1l2DvUbZw+shJfSNoWcBo2qadnUaWT3BmmJRBDh7ZReib/RQ1Rd4ygOyzP3E0vkV4/gqyjLdApXh5PZP8KLQZ+1JN/sdWt7VfIt9wYOpkIqujdll51ESHzwQeAK9WVCB4UvVz6zdhItB9CRbXPreWC+wCB1xDovIzFKOVsLs5+Gqs1m7VinG2LxbDqaKyo/FB0Hxx0acBNzezLWoDwXYQrN0T0S4pnqhKD1CYPpdArBkNezUYAjS725FkApuK+mnBX3U0msBffEaUEOkcyar1EW2m/33vpetD/k3eQQkmvQf4Hbiu9AF+9cNDm/hMuXEw5EXGA91fn0891b5eEW8BJHXX0jri0aN8g==" + ], + "n": "yeAKqRnrclUqhlLgSS1RZWvu2xH3Gu1GM31UkmS2f1_iQ5liFTfFCD7hYm-Y4TBHN12lJxV1JjO8xLc_2RuYWqcC8Dm9gt2cTj-j0I2AicW5C4nvm-N1EKxbtccXd7zIVSYHI_wCMRKZrM7qjmupFK5GIn4yQA0PuuJGYJeum7E3VzAs6cchZfcVH33-fS_Dl_h1HwHKGc93po4N2ST2FEUBJo3WUzmrtRIxYpcB4HffPSbezSoMd9DV6B5sO57rFQSGPeHy9lSjd39V1ZtHR7uTSNu_UOs69GQVO5OU9yHh587FHrEEuDRpZJQ1qFUypO91L_T52vMkLElu-ezxGxzhqfSp7uG56BjzpbBvNciD4qTuoU4BhStuKRfezPZKRm1qmF-Ptry5awgH3JrB6mlD5kJWHkVU0-r8O3LWKNpMlGBrZzg15O-i6nsEQVb5M8e-UFIX4wMm--NGHA5iHp3Oek6uoHmyR44RJlUnoUesSKVz-0lXrq08oT7BEJ6SR7YLOHXMFjmaewbzzcx15ian6-77LIYnt70uZENLtXtcqgKl4Mg46ilzpMfnaYFE3oUiR4TzR703OS10bL71ymM-ha8Efw2fLewTRLz3i4xYMaR-0FSRSwrwm17OSusmG7Jy38RSAT0Z62yZCLCvrEMJ0XZ7IlHT7E5BuQdpUH0", + "e": "AQAB" + } + ] + } + } +} diff --git a/testdata/spiffe/spiffebundle_match_client_spiffe.json b/testdata/spiffe/spiffebundle_match_client_spiffe.json new file mode 100644 index 000000000000..114943624a5d --- /dev/null +++ b/testdata/spiffe/spiffebundle_match_client_spiffe.json @@ -0,0 +1,31 @@ +{ + "trust_domains": { + "foo.bar.com": { + "spiffe_sequence": 12035488, + "keys": [ + { + "kty": "RSA", + "use": "x509-svid", + "x5c": [ + "MIIFsjCCA5qgAwIBAgIURygVMMzdr+Q7rsUaz189JozyHMwwDQYJKoZIhvcNAQELBQAwTjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTVkwxDTALBgNVBAoMBGdSUEMxFTATBgNVBAMMDHRlc3QtY2xpZW50MTAeFw0yMTEyMjMxODQyNTJaFw0zMTEyMjExODQyNTJaME4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU1ZMMQ0wCwYDVQQKDARnUlBDMRUwEwYDVQQDDAx0ZXN0LWNsaWVudDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ4AqpGetyVSqGUuBJLVFla+7bEfca7UYzfVSSZLZ/X+JDmWIVN8UIPuFib5jhMEc3XaUnFXUmM7zEtz/ZG5hapwLwOb2C3ZxOP6PQjYCJxbkLie+b43UQrFu1xxd3vMhVJgcj/AIxEpmszuqOa6kUrkYifjJADQ+64kZgl66bsTdXMCzpxyFl9xUfff59L8OX+HUfAcoZz3emjg3ZJPYURQEmjdZTOau1EjFilwHgd989Jt7NKgx30NXoHmw7nusVBIY94fL2VKN3f1XVm0dHu5NI279Q6zr0ZBU7k5T3IeHnzsUesQS4NGlklDWoVTKk73Uv9Pna8yQsSW757PEbHOGp9Knu4bnoGPOlsG81yIPipO6hTgGFK24pF97M9kpGbWqYX4+2vLlrCAfcmsHqaUPmQlYeRVTT6vw7ctYo2kyUYGtnODXk76LqewRBVvkzx75QUhfjAyb740YcDmIenc56Tq6gebJHjhEmVSehR6xIpXP7SVeurTyhPsEQnpJHtgs4dcwWOZp7BvPNzHXmJqfr7vsshie3vS5kQ0u1e1yqAqXgyDjqKXOkx+dpgUTehSJHhPNHvTc5LXRsvvXKYz6FrwR/DZ8t7BNEvPeLjFgxpH7QVJFLCvCbXs5K6yYbsnLfxFIBPRnrbJkIsK+sQwnRdnsiUdPsTkG5B2lQfQIDAQABo4GHMIGEMB0GA1UdDgQWBBQ2lBp0PiRHHvQ5IRURm8aHsj4RETAfBgNVHSMEGDAWgBQ2lBp0PiRHHvQ5IRURm8aHsj4RETAPBgNVHRMBAf8EBTADAQH/MDEGA1UdEQQqMCiGJnNwaWZmZTovL2Zvby5iYXIuY29tL2NsaWVudC93b3JrbG9hZC8xMA0GCSqGSIb3DQEBCwUAA4ICAQA1mSkgRclAl+E/aS9zJ7t8+Y4n3T24nOKKveSIjxXm/zjhWqVsLYBI6kglWtih2+PELvU8JdPqNZK34Kl0Q6FWpVSGDdWN1i6NyORt2ocggL3ke3iXxRk3UpUKJmqwz81VhA2KUHnMlyE0IufFfZNwNWWHBv13uJfRbjeQpKPhU+yf4DeXrsWcvrZlGvAET+mcplafUzCp7Iv+PcISJtUerbxbVtuHVeZCLlgDXWkLAWJN8rf0dIG4x060LJ+j6j9uRVhb9sZn1HJV+j4XdIYm1VKilluhOtNwP2d3Ox/JuTBxf7hFHXZPfMagQE5k5PzmxRaCAEMJ1l2DvUbZw+shJfSNoWcBo2qadnUaWT3BmmJRBDh7ZReib/RQ1Rd4ygOyzP3E0vkV4/gqyjLdApXh5PZP8KLQZ+1JN/sdWt7VfIt9wYOpkIqujdll51ESHzwQeAK9WVCB4UvVz6zdhItB9CRbXPreWC+wCB1xDovIzFKOVsLs5+Gqs1m7VinG2LxbDqaKyo/FB0Hxx0acBNzezLWoDwXYQrN0T0S4pnqhKD1CYPpdArBkNezUYAjS725FkApuK+mnBX3U0msBffEaUEOkcyar1EW2m/33vpetD/k3eQQkmvQf4Hbiu9AF+9cNDm/hMuXEw5EXGA91fn0891b5eEW8BJHXX0jri0aN8g==" + ], + "n": "yeAKqRnrclUqhlLgSS1RZWvu2xH3Gu1GM31UkmS2f1_iQ5liFTfFCD7hYm-Y4TBHN12lJxV1JjO8xLc_2RuYWqcC8Dm9gt2cTj-j0I2AicW5C4nvm-N1EKxbtccXd7zIVSYHI_wCMRKZrM7qjmupFK5GIn4yQA0PuuJGYJeum7E3VzAs6cchZfcVH33-fS_Dl_h1HwHKGc93po4N2ST2FEUBJo3WUzmrtRIxYpcB4HffPSbezSoMd9DV6B5sO57rFQSGPeHy9lSjd39V1ZtHR7uTSNu_UOs69GQVO5OU9yHh587FHrEEuDRpZJQ1qFUypO91L_T52vMkLElu-ezxGxzhqfSp7uG56BjzpbBvNciD4qTuoU4BhStuKRfezPZKRm1qmF-Ptry5awgH3JrB6mlD5kJWHkVU0-r8O3LWKNpMlGBrZzg15O-i6nsEQVb5M8e-UFIX4wMm--NGHA5iHp3Oek6uoHmyR44RJlUnoUesSKVz-0lXrq08oT7BEJ6SR7YLOHXMFjmaewbzzcx15ian6-77LIYnt70uZENLtXtcqgKl4Mg46ilzpMfnaYFE3oUiR4TzR703OS10bL71ymM-ha8Efw2fLewTRLz3i4xYMaR-0FSRSwrwm17OSusmG7Jy38RSAT0Z62yZCLCvrEMJ0XZ7IlHT7E5BuQdpUH0", + "e": "AQAB" + } + ] + }, + "test.example.com": { + "keys": [ + { + "kty": "RSA", + "use": "x509-svid", + "x5c": [ + "MIIEZDCCA0ygAwIBAgIUVXGlXjNENtOZbI12epjgIhMaShMwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEPMA0GA1UEAwwGdGVzdGNhMB4XDTI0MTAyMTAyMTQxNVoXDTM0MTAxOTAyMTQxNVowZTELMAkGA1UEBhMCVVMxETAPBgNVBAgMCElsbGlub2lzMRAwDgYDVQQHDAdDaGljYWdvMRUwEwYDVQQKDAxFeGFtcGxlLCBDby4xGjAYBgNVBAMMESoudGVzdC5nb29nbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5xOONxJJ8b8Qauvob5/7dPYZfIcd+uhAWL2ZlTPzQvu4oF0QI4iYgP5iGgry9zEtCM+YQS8UhiAlPlqa6ANxgiBSEyMHH/xE8lo/+caYGeACqy640Jpl/JocFGo3xd1L8DCawjlaj6eu7T7T/tpAV2qq13b5710eNRbCAfFe8yALiGQemx0IYhlZXNbIGWLBNhBhvVjJh7UvOqpADk4xtl8o5j0xgMIRg6WJGK6c6ffSIg4eP1XmovNYZ9LLEJG68tF0Q/yIN43B4dt1oq4jzSdCbG4F1EiykT2TmwPVYDi8tml6DfOCDGnit8svnMEmBv/fcPd31GSbXjF8M+KGGQIDAQABo4IBGTCCARUwdwYDVR0RBHAwboIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQOGJnNwaWZmZTovL2V4YW1wbGUuY29tL3dvcmtsb2FkLzllZWJjY2QyMB0GA1UdDgQWBBRvRpAYHQYP6dFPf5V7/MyCftnNjTB7BgNVHSMEdDByoVqkWDBWMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2GCFFqz9Fbx3Mviz+lLmDbYi/YAYQ+aMA0GCSqGSIb3DQEBCwUAA4IBAQBJ1bnbBHa1n15vvhpGIzokuiJ+9q/zim63UuVDnkhrQM2N+RQbStGTTis2tNse1bh460dJFm6ArgHWogzx6fQZzgaDeCOAXvrAe4jM9IHr9K7lkq/33CZSBDV+jCmm2sRsqSMkKUcX6JhyqWGFHuTDAKJzsEV2MlcswleKlGHDkeelAaxlLzpzRHOSQd0N9xAs18lzx95SQEx90PtrBOmvIDDiI5o5z9Oz12Iy1toiksFl4jmknkDD5VF3AyCRgN8NPW0uNC8D2vo4L+tgj9U6NPlmMOrjRsEH257LJ1wopAGr+yezkIIdQQodGSVm5cOuw/K7Ma4nBDjVJkjcdY3t" + ], + "n": "5xOONxJJ8b8Qauvob5_7dPYZfIcd-uhAWL2ZlTPzQvu4oF0QI4iYgP5iGgry9zEtCM-YQS8UhiAlPlqa6ANxgiBSEyMHH_xE8lo_-caYGeACqy640Jpl_JocFGo3xd1L8DCawjlaj6eu7T7T_tpAV2qq13b5710eNRbCAfFe8yALiGQemx0IYhlZXNbIGWLBNhBhvVjJh7UvOqpADk4xtl8o5j0xgMIRg6WJGK6c6ffSIg4eP1XmovNYZ9LLEJG68tF0Q_yIN43B4dt1oq4jzSdCbG4F1EiykT2TmwPVYDi8tml6DfOCDGnit8svnMEmBv_fcPd31GSbXjF8M-KGGQ", + "e": "AQAB" + } + ] + } + } +} diff --git a/testdata/spiffe_end2end/README.md b/testdata/spiffe_end2end/README.md new file mode 100644 index 000000000000..9bb52b4c2fde --- /dev/null +++ b/testdata/spiffe_end2end/README.md @@ -0,0 +1,38 @@ +All of the following files in this directory except `server_spiffebundle.json` +and `client_spiffebundle.json` are generated with the `generate.sh` and +`generate_intermediate.sh` script in this directory. + +These comprise a root trust certificate authority (CA) that signs two +certificates - `client_spiffe.pem` and `server_spiffe.pem`. These are valid SPIFFE +certificates (via the configuration in `spiffe-openssl.cnf`), and the +`*_spiffebundle.json` files are SPIFFE Bundle Maps for the client and server +respectively. + +The SPIFFE trust bundle map files (`*_spiffebundle.json`) are manually created for +end to end testing. The `server_spiffebundle.json` contains the `foo.bar.com` +trust domain (only this entry is used in e2e tests) matching URI SAN of +`client_spiffe.pem`, and the CA certificate is `ca.pem`. The client +`spiffebundle.json` file contains `example.com` trust domain matching the URI SAN +of `server_spiffe.pem`, and the CA certificate there is also `ca.pem`. + +`leaf_and_intermediate_chain.pem` is a certificate chain whose leaf is a valid +SPIFFE cert that is signed by an intermediate CA (`intermediate_ca.pem`). The +intermediate CA is signed by the root CA (`ca.pem`). Thus, this setup yields a +valid chain to the root of trust `ca.pem`. + +If updating these files, the `x5c` field in the json is the raw PEM CA +certificate and can be copy pasted from the certificate file `ca.pem`. `n` and +`e` are values from the public key attached to this certificate. `e` should +*probably* be `AQAB` as it is the exponent. `n` can be fetched from the +certificate by getting the RSA key from the cert and extracting the value. This +can be done in golang with the following codeblock: + +``` +func(GetBase64ModulusFromPublicKey(key *rsa.PublicKey) string { + return base64.RawURLEncoding.EncodeToString(key.N.Bytes()) +} + +block, _ := pem.Decode(rawPemCert) cert, _ := x509.ParseCertificate(block.Bytes) +publicKey := cert.PublicKey.(*rsa.PublicKey) +fmt.Println(GetBase64ModulusFromPublicKey(publicKey)) +``` diff --git a/testdata/spiffe_end2end/ca.key b/testdata/spiffe_end2end/ca.key new file mode 100644 index 000000000000..bb60bf90fb7b --- /dev/null +++ b/testdata/spiffe_end2end/ca.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQC19PImArmxbwgq +o2QG2si8BU6E69Bvyqxz8Je3swxBIGwZ9uIobMSBLeTCYyXuf+o90Zf0kMwzmrAK +eLEeky5W/j07zGXAtgUBPA7L1Uk0TxOdJXBCUvEm5Oc4GxubfO7F+pdJKZ+XkRVq +bnStGe5qX6KNs5rcJfFUhewbtM0snGEIf2yhaA0mNNuGtlIm4VB7jmiyHNU5YTow +ByVCVrV3/t2RI9+T4ya0AlkW93rU0M0qQauJ35LkJIXifbzrnLxmztEyb+mnVUB+ +GJgz01E4teWo/PJb1aNJ/ojf/UONsQ5IFRdza6RhaQB7C+Dxlnt/SJ3MMaxHgVyc +YuJeVtJQuncGRSuQ2YrmW9b36HVnxa0xBDeSluUjv48hMRlLNaXaH4yuK6oc8TNJ +ie++/ir6Kb4H+0RjcKMGqxZYfotU1obxa+5N3wzGSjUDUrhofzlfvqbp+NCwdFH+ +qczM4IZPL8YMMh6goKr9BRN9/xRIieotyH6rfKNcnkUgDp750U0cZ7P2eRUpldyc +9hZS5AlF4cKQXgLIrv1LrZHkiIietetInUEBAa/PF2YHRLXUyI1PCSBKBu7wdwAU +15J9dVFC9jkmOLYhoRdPfrobpWhs5+FfPJumSoiusdGXd7x4l313xi2V02YXz5mR +GbT2lCb6aJPweuziiEBZn+5KV++DkQIDAQABAoICAADWyAO4mVHKyGYpOdNT36do +4HZZAir2+CCTv9z8wLnrF2cF36+xvNp+an5PoYdjoxL+HP5EVT4fFWLQ22VQw5N5 +uEKAoZDGBXUpNJ/UKO1rFWA8U+iHFmDYsxlzX7lrjSkBk4fOw1rJ12HcFZo1580V +J/GO1TmVcf0Z2jLX9Q6+TD2xTzsWFIMWp/PPMP5FqokXeBQij3LluW4Wsbf2qEBu +/a2g5HjL6QhBgxqci6eX7b3b7sbHjLp66G+kM6n4JIFE4+Z1+sypdVBYoUESRjlB +9qIF5Gb53QTgLYgn93AKD/hGtJ7jUcrESliAoCgWbdkYDm/vkStkX6vWdXmX01fl +hfv6c1eYTkDhOboVZL0p0DxZwHU4Ci6UF0PflrHmospKo12bLoa2dea+5LfQVgB0 +icijZ1ZF4oePzFOtIdDYmNDfTkBe7q52HKNIPbLytXTFv9gHj/XpRdDUDgNzS7TO +wXP1k4zY96H9YEgXNr/Ze7IQt711/Szj/bIPfuCyJTSMRh40wPW+1TzGkdQepBDO +lHk1uVs185lJd3TryUGhfXu9X49hXOpvq1nhOy3UW/FoDPLGckOoQGe9PikP3zQC +6poTttdmfmTy7D3vniZUjDmbztyml3twM50+KGhGJTbjEKDqs9dASbn5B69LbnOA +kq3SzgJOGgTiTT8EFwjzAoIBAQD8LjTqiEB8TY9qQjihtcidDWBA7TcBjIQ/Wm4p +3ff0NdGPa6/qaCPX7769wBW5/fJfoJu9ZhebWfLLYacK2Dz1BYn5EqoAf4mF4C9S +ZDY4NO3tl8t902bjlQs+ehojyzOOVHxuATZ4mBrCFUYuFn1YPXR0qIvvXsvhRM4k +LCf9lGl1ldUpWNbdxTxUl7NZVuZKevwBvfsGB9SPgnvDCgg0Mh4pBGUDP0WZqwaS +frvB2iP4hVH5e/lUl2XxtlJIil8Eb1rGH2O6CmbvkSc6Sceg67/E0N6u4w9i+g1G +uu+FFdPQSve3jUrOrhQjO7tqjh6p8J858H7CvoJo7Uojk8yjAoIBAQC4tnUCvlns +VJQ9SVqabVuIWPJvgDf/EVHncVFwJZtdsFRchs+QFtUWyJRD6mRtHtBdyIpsQCBb +YxPYbMoQClpEC7VNC9Y6RDKVxRM+A1cQ1JiP4PQTyzYIVfoU/RbWuixXHOvGOYsb +LwjGZ7WQtaG8Pyqt8P97OIqZzeuQK5y+ZuixDZpBsy3xhYyQcC1oowLLgf7ip1QU +ueEF/fi3OZCd7oIbZX10EYr/QINnlyYstRxnHz2AOO4kilQEt4Yq2YKxo/GiXVp+ +HlDD53xl/1HfT1sV9BnnoRQksmt61LO3qz6hI7TgQtFt4+Z3TsXB4siWoFtmfGRo +njuShRAdjt47AoIBADo2EFDzEq+e17QXhSsO4zgdllJmb4QUA5L8NOHFMy9UHQOW +QA1D7MIzvTvf0yQT0pbwZALcRia+JKV97Sk7sRZ+KNMt08A5sG0Oyt2h9EIVNbba +i0aIPf/ar7XESbRpe4UnS3G5JfHAaqzSbFjHKDfuN6uWHHcs0rM1RsBi0PhgAdf6 +tjHNKAwZM0vzmJrOzGn06acdS4yg0hgubpMfBbXGu9+L/CU7vb0zFVlLl9uvlw4O ++FU2oN8983JQO74y8qv7aGDDbinLrOcwAnYaAdLLmIC+FikYkLywK9Bf5lo6J6K1 +K2lbXCFJXaykZSa7l6hyus6NDTW29DN0UuDThTECggEBAIlRU0G74zv3UNETBGFD +pUWC4pCT4I0mAh6uNp3Jx2vqF31F127GGpo6eUbYLNqWis79tDJvpd5qlKlTjxBH +sf1eOuVRRGzCoFyJSxnR/9sKQXTNBobkjoG58RXDZUQy2Z3VaU5PHyQRXlOpa+ht +rxQ0XXU8caHYUemvlUzzry45cQmXFDN9kk04PFxwmMFuVjiWprc3MCHMYgZDXbBR +Ajr2whC97XrpQ80o18eeLYoVBk1/gwgcyqWtlHKBQSP/2dJYD93lys1xmhdZszhc +jDAYXZ2/f7acIE57ub1x/T0w+HlxAxmpcupf/8h4bjoKb5bTFb/l//tqjt0JQQbI +XFsCggEBALd+S5rIRYz3YpXCnt+uT6ELbD7RfDtoGdWtLavm3vQb3yZCXGwlHesP +ud1xXZ5w1Ky3GSqvXJ4F+UiVd+DLEoq6u0Y8adkKmNpwElJffG7+/9ZgDgAUQDhr +i4yqH5wYHs2tSdc0hHEqmLjn0uylX+y4pWojHD1l0w7KrepUzj9SNVrOyzl8D7D2 +xXFNb+rSY4B9ZwPofYqxGxM6GGo47GFFOGqFsCtwp8lcbSMgzx0j36Ibg9uPmoeM +53ea7Fbqv+fWVzhu+6r7BE7mp0rYBWPMRg/euciYl2X3FBRjhqt1/GENDwejYkFS +qLeaSJiKSNSUyCl91Qu0eb4FbE5qLwI= +-----END PRIVATE KEY----- diff --git a/testdata/spiffe_end2end/ca.pem b/testdata/spiffe_end2end/ca.pem new file mode 100644 index 000000000000..c086690f0651 --- /dev/null +++ b/testdata/spiffe_end2end/ca.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFlTCCA32gAwIBAgIUCD73sHXu5IURolSTiJ127a/xUO4wDQYJKoZIhvcNAQEL +BQAwWjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMSEwHwYDVQQKDBhJbnRlcm5l +dCBXaWRnaXRzIFB0eSBMdGQxGzAZBgNVBAMMEmZvby5iYXIuaG9vLmNhLmNvbTAe +Fw0yNTAzMDcxOTM0NDZaFw0yNjAzMDcxOTM0NDZaMFoxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJWQTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRsw +GQYDVQQDDBJmb28uYmFyLmhvby5jYS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQC19PImArmxbwgqo2QG2si8BU6E69Bvyqxz8Je3swxBIGwZ9uIo +bMSBLeTCYyXuf+o90Zf0kMwzmrAKeLEeky5W/j07zGXAtgUBPA7L1Uk0TxOdJXBC +UvEm5Oc4GxubfO7F+pdJKZ+XkRVqbnStGe5qX6KNs5rcJfFUhewbtM0snGEIf2yh +aA0mNNuGtlIm4VB7jmiyHNU5YTowByVCVrV3/t2RI9+T4ya0AlkW93rU0M0qQauJ +35LkJIXifbzrnLxmztEyb+mnVUB+GJgz01E4teWo/PJb1aNJ/ojf/UONsQ5IFRdz +a6RhaQB7C+Dxlnt/SJ3MMaxHgVycYuJeVtJQuncGRSuQ2YrmW9b36HVnxa0xBDeS +luUjv48hMRlLNaXaH4yuK6oc8TNJie++/ir6Kb4H+0RjcKMGqxZYfotU1obxa+5N +3wzGSjUDUrhofzlfvqbp+NCwdFH+qczM4IZPL8YMMh6goKr9BRN9/xRIieotyH6r +fKNcnkUgDp750U0cZ7P2eRUpldyc9hZS5AlF4cKQXgLIrv1LrZHkiIietetInUEB +Aa/PF2YHRLXUyI1PCSBKBu7wdwAU15J9dVFC9jkmOLYhoRdPfrobpWhs5+FfPJum +SoiusdGXd7x4l313xi2V02YXz5mRGbT2lCb6aJPweuziiEBZn+5KV++DkQIDAQAB +o1MwUTAdBgNVHQ4EFgQUL/YTEXKZRjbOv82CwGMuBeNwErIwHwYDVR0jBBgwFoAU +L/YTEXKZRjbOv82CwGMuBeNwErIwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B +AQsFAAOCAgEAIYtNERVMj4dS/KgoXD3a6mF6KD+IuxDTlVbVTwDJMzdNW5UPB2qC +iDKbirK8Eedh90r3qxKzBiQPE5AHDZrbWSBAxDhlpQqCXgx8Z+nCB38K9i8hbKM/ +ablm9DkeHiHohoP1kJEN2HtPz1K6OabbKbPtVGt8y+QTIlZDodPPzKPmQ6dUTm9t +WlU1oIxl4pPVR6WXDr0qAmNRvdW7+8/Ai+gMDi6fKQJCe/r/meVrI9lSrnn8VQyO +4xXvyolHEROTUiomlJ1QE9IWAM9LNFOuWFwQjayo2d6O+zHqjGUtbzBHFb8/BLJc +QzogWYT0/+rEboJhR+/OGe0ntPPkudmLL0HTx0Q1aajnChMVlaOd2wucePZSa6Gq +GEVA+lCqwbteqwJCnL7deVHo+UlORFgQwYir2CQbyN9Yd4MtQT7VZuDiVC6tlGbj +1ogrpOnW8n49jXrNPWuPz2hcPQb2gzYFGI9WRKIX4SjvvS3QcHUyigQkjAQ12Ldj +5CXBYTjSmjcgsa2QfUY5qrXsHLz7e4uXD9XYnB/XEEfxQfQTFEy5CtzTrTxnT+cw +RuBooIr6InjqdbdJ+UbkWcIY6w+c7ndFT849pUgtrojbVpm9ZzsmHhAahR/+iHYH ++LGeHYIpq71o/YDgM4vV9z3sWic7u1YE9JULBdlaDw8Xik82zjvw4IA= +-----END CERTIFICATE----- diff --git a/testdata/spiffe_end2end/client.key b/testdata/spiffe_end2end/client.key new file mode 100644 index 000000000000..d3f694ad1ccd --- /dev/null +++ b/testdata/spiffe_end2end/client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC/Y4KWLto/B3f3 +YRlwJXn2l+hlre80L36k0dNmyvZW6nY0zZfXGJBHV3UlIT3YB+vIsePu3KtpfJak +xjBuyL65LtZphxkR+1mfL6ucVqgroI6b7WFt/Zo6vjElTbJGMaNcprItlLNjBxKw +d0elYWS4q/TkhUw9cPfywE+FCNy3OPLPbI677lD1C29AlI8ToTHfjY1PqJ+9dS2j +xg7qAskWUsOTjfXO8SiQbF15DkD2hZDg9I2/BBC9YhB5xUOCywb5U9Ucomp7Q9aH +J3OkvsN1n0Un7GHkEn1iyXaa61vh94uk7M1e/ewvBdmC+JUgLaU0tKdg7dFIgc4g +KF4ewvITAgMBAAECggEAGNHb1oQe83uReDhUZzHE/lC257DFy5u5LcC0TKlXhvAD +AlgDL/bUhxv1aipEbeahEjbXm1tss1Jf6uB02XkZGsTTM348pxNUjQtOkwi96GJ6 +/Aet0ejIfoO5td+8ldPMHrDTfIvDM71wFAhz9yOJP1W1fYk32OP0k7uS1GrQzMXQ +6y5pA+Mvn1lXb9zsufkrvyp4F+QGUiXnPNEPXC+9u5pNqY0OkNvudn3cfU6t2jJO +lUies9xiX5GatWQ4kp/i26HoTGvefuM3mnNmm37dSt/5zalfrECC9e3mKkba1StY +XPavOtXkjA1X51w5MqVL1wEBYQCQTlr+KSATR44y2QKBgQD98MID26fNYSrNuTxN +I9YHGqFmwB3qe2jOec9dqmOtdh8ji+UEX1z10Sm6Vrdk75LwwCp066LBxyYVTJo2 +PgN6Dn0ARHEF0j4GgJiYWKhOJk+mwVHDENuQFSpGgP+mLXGGyo8irCz/HP6g5uww +70h+QDPtNEccDHLAUaaA92DdfQKBgQDA8OEtKPtgWZBdTEvcKQbn49m1aihqjV/q +kr8Nn28Y39i90vyGoO67muTuSAvDNgW6ne/W2Ic5VhSicIVyVHV0p3cUB2NGwdnp +RvT+7wd22pVUMW9Lys4hAg1O4TtoO5Th/lRDXf28IAmxQPz7jc3alr2AEgaawrEH +t/gyph5izwKBgAm/uHMVd7e2x0Hmnp4Hhiv3pcKgFYXu/vMOUhuycukx47glosEs +OBFn2kZBFgFWATok5nxen3z4/ElNC46RiuigrcPY3M3waFkvjqwqmyuE5QHt4gmv +F/7METdrtGTY0cbu99fI7GFO56edteubBBl0tYmhvCkjgTRI7i99T8axAoGADvGZ +PzoxXiERwWgrZ/31fvhy4E48myQgDbcX/SIgJLkRvIIe9P55/yXcHWiPIKuKfg3F +icpzjslQB9TXQSexgTuHSZHY6p4RFrRcPXKeDWKYtlCt4hzvIjdaeIWRaF1VBrwA +Iseg43VHyubRsVomW4vZWZYL1OjHdWWWX7XmHJkCgYEA2LUeWNkdqABJ9Yta7kKu +02gkOsjnQyyYIeFCteGSM9oejE4zDM+WSCpVCLzq8DcRK8M/xBhCIf+mVZRroHAz +g5YpFrg5a7kuuTgQJv/6ju+Mbd+DGpsul/N2zIPFzy6T27gIzL8+QExUK0y1XkL/ +7yGUwV4OO2kuwh8YT+TiCts= +-----END PRIVATE KEY----- diff --git a/testdata/spiffe_end2end/client_spiffe.pem b/testdata/spiffe_end2end/client_spiffe.pem new file mode 100644 index 000000000000..475b49093a5e --- /dev/null +++ b/testdata/spiffe_end2end/client_spiffe.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvjCCAqagAwIBAgIUBoJ396S7DO0kRqDUn4TB6zKKIIkwDQYJKoZIhvcNAQEL +BQAwWjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMSEwHwYDVQQKDBhJbnRlcm5l +dCBXaWRnaXRzIFB0eSBMdGQxGzAZBgNVBAMMEmZvby5iYXIuaG9vLmNhLmNvbTAe +Fw0yNTAzMDcxOTM0NDZaFw0zNTAzMDUxOTM0NDZaMEwxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEMMAoGA1UEBwwDU1ZMMQ0wCwYDVQQKDARnUlBDMRMwEQYDVQQD +DAp0ZXN0Y2xpZW50MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2OC +li7aPwd392EZcCV59pfoZa3vNC9+pNHTZsr2Vup2NM2X1xiQR1d1JSE92AfryLHj +7tyraXyWpMYwbsi+uS7WaYcZEftZny+rnFaoK6COm+1hbf2aOr4xJU2yRjGjXKay +LZSzYwcSsHdHpWFkuKv05IVMPXD38sBPhQjctzjyz2yOu+5Q9QtvQJSPE6Ex342N +T6ifvXUto8YO6gLJFlLDk431zvEokGxdeQ5A9oWQ4PSNvwQQvWIQecVDgssG+VPV +HKJqe0PWhydzpL7DdZ9FJ+xh5BJ9Ysl2mutb4feLpOzNXv3sLwXZgviVIC2lNLSn +YO3RSIHOICheHsLyEwIDAQABo4GJMIGGMEQGA1UdEQQ9MDuGOXNwaWZmZTovL2Zv +by5iYXIuY29tLzllZWJjY2QyLTEyYmYtNDBhNi1iMjYyLTY1ZmUwNDg3ZDQ1MzAd +BgNVHQ4EFgQUVHpZYzO6JCGBTQwzWbj/CVC6sTAwHwYDVR0jBBgwFoAUL/YTEXKZ +RjbOv82CwGMuBeNwErIwDQYJKoZIhvcNAQELBQADggIBACa1C7Zn0rXXIXC9SI8G +MPSTyebo2s/OZCQ2sKQEK90yL33Ae97beiBVgFlt2TTXeEW91iZMZMfn9BlRDYkZ +j8qdcNbG1QQEco2ZT3Ti13psVoSIgX2yMbds5DFkalJhXCx21xxNHLVUtd1xRDhu +JvFm+V4TNFi1ka0U5fNcxRAGeVkR7tzpvUy8La+aNHOOAEaOX4oCQKueDXhGJGcL +EXMz6N/KyLq4otaKGO67D2q5or6hH1afgrIcdZV0Gb7Cf+nR18QNWvH0Nm1cXdkT +OL/iKlDqbhLGznGazz6T1EWlbynGjupFWdXDIPjsgN0xrAJS7NWjkUSgWcA94J7Z +JwtIsjgP0DWg7fQsYa4cR9rxS+gYtkiKZuRTONSGYxQLAxJEb5NCCXE6fBC6jfHZ +xtsY1ExlA6f6t+E7mS0OkRqbb6KZqTFGgSyx99jDL46FUH3zqA4IOs8Q4loo/Zkh +LNjeG/3MoO7RvyY9g58y+yf3ZOp92zoyKMSqCBsvdTMRP0hWGq4BqoW/3Sn3ujf1 +uf5KEE+peuYzEqK1mtuZQHe/+1Vm7h88/TlER7mijMN3/MFZzmor890vBbzqf7KQ +Q2QCRwIISj3a0puskpZM13Jt0r8cM+npkk1evfgmpBjNLrOinIQgWy30Qlxt5fIh +jYaOBLHtSFI01OHnivQ1dFWG +-----END CERTIFICATE----- diff --git a/testdata/spiffe_end2end/client_spiffebundle.json b/testdata/spiffe_end2end/client_spiffebundle.json new file mode 100644 index 000000000000..18f81dafe6ef --- /dev/null +++ b/testdata/spiffe_end2end/client_spiffebundle.json @@ -0,0 +1,18 @@ +{ + "trust_domains": { + "example.com": { + "spiffe_sequence": 12035488, + "keys": [ + { + "kty": "RSA", + "use": "x509-svid", + "x5c": [ + "MIIFlTCCA32gAwIBAgIUCD73sHXu5IURolSTiJ127a/xUO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxGzAZBgNVBAMMEmZvby5iYXIuaG9vLmNhLmNvbTAeFw0yNTAzMDcxOTM0NDZaFw0yNjAzMDcxOTM0NDZaMFoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRswGQYDVQQDDBJmb28uYmFyLmhvby5jYS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC19PImArmxbwgqo2QG2si8BU6E69Bvyqxz8Je3swxBIGwZ9uIobMSBLeTCYyXuf+o90Zf0kMwzmrAKeLEeky5W/j07zGXAtgUBPA7L1Uk0TxOdJXBCUvEm5Oc4GxubfO7F+pdJKZ+XkRVqbnStGe5qX6KNs5rcJfFUhewbtM0snGEIf2yhaA0mNNuGtlIm4VB7jmiyHNU5YTowByVCVrV3/t2RI9+T4ya0AlkW93rU0M0qQauJ35LkJIXifbzrnLxmztEyb+mnVUB+GJgz01E4teWo/PJb1aNJ/ojf/UONsQ5IFRdza6RhaQB7C+Dxlnt/SJ3MMaxHgVycYuJeVtJQuncGRSuQ2YrmW9b36HVnxa0xBDeSluUjv48hMRlLNaXaH4yuK6oc8TNJie++/ir6Kb4H+0RjcKMGqxZYfotU1obxa+5N3wzGSjUDUrhofzlfvqbp+NCwdFH+qczM4IZPL8YMMh6goKr9BRN9/xRIieotyH6rfKNcnkUgDp750U0cZ7P2eRUpldyc9hZS5AlF4cKQXgLIrv1LrZHkiIietetInUEBAa/PF2YHRLXUyI1PCSBKBu7wdwAU15J9dVFC9jkmOLYhoRdPfrobpWhs5+FfPJumSoiusdGXd7x4l313xi2V02YXz5mRGbT2lCb6aJPweuziiEBZn+5KV++DkQIDAQABo1MwUTAdBgNVHQ4EFgQUL/YTEXKZRjbOv82CwGMuBeNwErIwHwYDVR0jBBgwFoAUL/YTEXKZRjbOv82CwGMuBeNwErIwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAIYtNERVMj4dS/KgoXD3a6mF6KD+IuxDTlVbVTwDJMzdNW5UPB2qCiDKbirK8Eedh90r3qxKzBiQPE5AHDZrbWSBAxDhlpQqCXgx8Z+nCB38K9i8hbKM/ablm9DkeHiHohoP1kJEN2HtPz1K6OabbKbPtVGt8y+QTIlZDodPPzKPmQ6dUTm9tWlU1oIxl4pPVR6WXDr0qAmNRvdW7+8/Ai+gMDi6fKQJCe/r/meVrI9lSrnn8VQyO4xXvyolHEROTUiomlJ1QE9IWAM9LNFOuWFwQjayo2d6O+zHqjGUtbzBHFb8/BLJcQzogWYT0/+rEboJhR+/OGe0ntPPkudmLL0HTx0Q1aajnChMVlaOd2wucePZSa6GqGEVA+lCqwbteqwJCnL7deVHo+UlORFgQwYir2CQbyN9Yd4MtQT7VZuDiVC6tlGbj1ogrpOnW8n49jXrNPWuPz2hcPQb2gzYFGI9WRKIX4SjvvS3QcHUyigQkjAQ12Ldj5CXBYTjSmjcgsa2QfUY5qrXsHLz7e4uXD9XYnB/XEEfxQfQTFEy5CtzTrTxnT+cwRuBooIr6InjqdbdJ+UbkWcIY6w+c7ndFT849pUgtrojbVpm9ZzsmHhAahR/+iHYH+LGeHYIpq71o/YDgM4vV9z3sWic7u1YE9JULBdlaDw8Xik82zjvw4IA=" + ], + "n": "tfTyJgK5sW8IKqNkBtrIvAVOhOvQb8qsc_CXt7MMQSBsGfbiKGzEgS3kwmMl7n_qPdGX9JDMM5qwCnixHpMuVv49O8xlwLYFATwOy9VJNE8TnSVwQlLxJuTnOBsbm3zuxfqXSSmfl5EVam50rRnual-ijbOa3CXxVIXsG7TNLJxhCH9soWgNJjTbhrZSJuFQe45oshzVOWE6MAclQla1d_7dkSPfk-MmtAJZFvd61NDNKkGrid-S5CSF4n2865y8Zs7RMm_pp1VAfhiYM9NROLXlqPzyW9WjSf6I3_1DjbEOSBUXc2ukYWkAewvg8ZZ7f0idzDGsR4FcnGLiXlbSULp3BkUrkNmK5lvW9-h1Z8WtMQQ3kpblI7-PITEZSzWl2h-MriuqHPEzSYnvvv4q-im-B_tEY3CjBqsWWH6LVNaG8WvuTd8Mxko1A1K4aH85X76m6fjQsHRR_qnMzOCGTy_GDDIeoKCq_QUTff8USInqLch-q3yjXJ5FIA6e-dFNHGez9nkVKZXcnPYWUuQJReHCkF4CyK79S62R5IiInrXrSJ1BAQGvzxdmB0S11MiNTwkgSgbu8HcAFNeSfXVRQvY5Jji2IaEXT366G6VobOfhXzybpkqIrrHRl3e8eJd9d8YtldNmF8-ZkRm09pQm-miT8Hrs4ohAWZ_uSlfvg5E", + "e": "AQAB" + } + ] + } + } +} diff --git a/testdata/spiffe_end2end/generate.sh b/testdata/spiffe_end2end/generate.sh new file mode 100755 index 000000000000..9ba3388f0525 --- /dev/null +++ b/testdata/spiffe_end2end/generate.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Generate client/server self signed CAs and certs. +openssl req -x509 -newkey rsa:4096 -keyout ca.key -out ca.pem -days 365 -nodes -subj "/C=US/ST=VA/O=Internet Widgits Pty Ltd/CN=foo.bar.hoo.ca.com" + +# The SPIFFE related extensions are listed in spiffe-openssl.cnf config. Both +# client_spiffe.pem and server_spiffe.pem are generated in the same way with +# original client.pem and server.pem but with using that config. Here are the +# exact commands (we pass "-subj" as argument in this case): +openssl genrsa -out client.key.rsa 2048 +openssl pkcs8 -topk8 -in client.key.rsa -out client.key -nocrypt +openssl req -new -key client.key -out spiffe-cert.csr \ + -subj /C=US/ST=CA/L=SVL/O=gRPC/CN=testclient/ \ + -config spiffe-openssl.cnf -reqexts spiffe_client_e2e +openssl x509 -req -CA ca.pem -CAkey ca.key -CAcreateserial \ + -in spiffe-cert.csr -out client_spiffe.pem -extensions spiffe_client_e2e \ + -extfile spiffe-openssl.cnf -days 3650 -sha256 + +openssl genrsa -out server.key.rsa 2048 +openssl pkcs8 -topk8 -in server.key.rsa -out server.key -nocrypt +openssl req -new -key server.key -out spiffe-cert.csr \ + -subj "/C=US/ST=CA/L=SVL/O=gRPC/CN=*.test.google.com/" \ + -config spiffe-openssl.cnf -reqexts spiffe_server_e2e +openssl x509 -req -CA ca.pem -CAkey ca.key -CAcreateserial \ + -in spiffe-cert.csr -out server_spiffe.pem -extensions spiffe_server_e2e \ + -extfile spiffe-openssl.cnf -days 3650 -sha256 + +rm *.rsa +rm *.csr +rm *.srl diff --git a/testdata/spiffe_end2end/intermediate.cnf b/testdata/spiffe_end2end/intermediate.cnf new file mode 100644 index 000000000000..eeeb3af6bca9 --- /dev/null +++ b/testdata/spiffe_end2end/intermediate.cnf @@ -0,0 +1,38 @@ +[ca] +default_ca = CA_intermediate + +[CA_intermediate] +dir = . +certs = $dir/certs +crl_dir = $dir/crl +new_certs_dir = $dir/newcerts +database = $dir/index.txt +serial = $dir/serial +RANDFILE = $dir/private/.rand +private_key = $dir/intermediate_ca.key +certificate = $dir/intermediate_ca.pem +crl = $dir/intermediate.crl + +# For certificate revocation lists. +crlnumber = $dir/crlnumber +crl = $dir/crl/intermediate.crl +crl_extensions = crl_ext +default_crl_days = 3650 + +default_md = sha256 + +[req] +distinguished_name = req_distinguished_name +req_extensions = v3_req +prompt = no + +[req_distinguished_name] +CN = intermediatecert.example.com + +[crl_ext] +authorityKeyIdentifier=keyid:always + +[v3_req] +keyUsage = critical, digitalSignature, keyEncipherment, keyCertSign, cRLSign +extendedKeyUsage = clientAuth, serverAuth +basicConstraints = critical, CA:true diff --git a/testdata/spiffe_end2end/intermediate_ca.key b/testdata/spiffe_end2end/intermediate_ca.key new file mode 100644 index 000000000000..3e5fe818bb89 --- /dev/null +++ b/testdata/spiffe_end2end/intermediate_ca.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC7XOGe2r5KNdo7 +ELwJ7GRAIVqxAkT9bB6+7rUyDhJnxWeI7E9vr+I4clDRYREoxnuXq6oGTICKlWiv +vrxBASSdA0PpjLsMNnNU1n9XHXEBEa3YM7w85UBvf/8IdlpiyHgPkg+1DdvuToOa +0Xhejnq/aCcNyErjjNN26k/06joO3+feYvsn1tToXomif4HUU+SE5xIGiuPHcDwJ +tjk/Iugh+pNPdltOguxq2E7m8upQvwShe2A6azD1wV9HiyFtkf7tlp4f900MmRyb +kHb7zXfgXBwlf7waa2RP3UDZbJAZZZkOFQmPcujNvkAz/ghaf0Uf2Ix/P0Zh69LU +notPVa35AgMBAAECggEADMnb740UMHoJBX+Qqie7twHf0BWs0lRjK9qcvQgnWvRn +KvogOOobKYmp+QSkWHFlxbY2onvtySfGD7rX3CMBFgN/Su1rZfvAdwG2CuLsT+ue +P1PWrRxjv8iPhosXg8cVpNBuKIhD4vnycyqJigC1IaPxCHiLngkCdQssvnWPVWz2 +nXp0SKcDKJu/sU8Mp0UW490DIUi8iSQHkjbpXu+RExAPAjhe+vvEuExZFs8dN0Rp +g3oj8l6pLkfJ/M4tfib7WiQxxtZWEEuEYsz3JDpxySFWR59SRZ2tYKv4k9TNbQXA +qX8jqVGT+YubWKY4HtRxd2L3yy443ERQdwQecLsYIQKBgQDgPpRts1pz9UnrXnr8 +ee8nO4SSxsJxge4OX5/yX7Lm/JwOPyk6/nCH3LKqxOWMOZpOpgI3ithA1Qvb1JuM +vDQo13z4Xi5RMJm8h3B5O0f9brw3L2h+hrImJfYuozj0icyFSbT/PjO1pGB/QAAF +ie6G3JQLRlBFF0dclcqb4tpEEQKBgQDV5UAYKGz+sdDpzgarTmsyd0YVTRitdBMv +S7eddG/gCBMaISXXXksYXX+Y74zbs2LCfkLz+i4j8BDoRFPfPlK/daCOMOriJ++Z +LNBClmkBiwqlZXs9d1dEWmJis5GbJEiAneoNskAy6UspFMCLu4QJJHfB5aZsAphm +4509tRqTaQKBgF8gDOTwVWmlXyMaZD+gFiRlahq9eBSgknTEedxeXk0AUc71Wi8t +al0n8R7iAaJXeS7t2zjmjFAMUEiDyyyLVfERYHEXurw0SrMgHUVAMYy/odYjJUev +Kflm1yT3lpydrAXKu54fK95dCZZRdvDijy3kemTCAiEc++e5n0Y7mG2RAoGAeMtN +5ha2byPWeqOqaoYPzeFEB/WRMSuzRet514cRQzDsML51k2oh+LGcxK7MGqr05CfQ +Ad7QveTud21W/GVC7/Mq6AJCM9Qf4J5JQsGUrZVrPrrP3YePFgABPgJxAW99Ln1/ +15pJ3TaZBqs8je0pBMy+gRcDZE4W6Uwz2cx0JLkCgYAn6/C71GXvLkjDdmRHS2zA +K+gOTCb4YdGDCnv5Cez64pega6mUy+EIznJYpI3KwHbAsUFkYgNJ7VvUtVIu2z9U +UHSBHilN/cMWRCgN3KXyYOHr50g0P+gei0bhiWddIh8+tC1J/627g2r2Jwowuarn +1JLr0ZYgh3SXglOkgyvIKA== +-----END PRIVATE KEY----- diff --git a/testdata/spiffe_end2end/intermediate_ca.pem b/testdata/spiffe_end2end/intermediate_ca.pem new file mode 100644 index 000000000000..84cabe6aa59c --- /dev/null +++ b/testdata/spiffe_end2end/intermediate_ca.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEkzCCAnugAwIBAgIUa4ZkytupQZ5OwDMPw/vRY8deFc4wDQYJKoZIhvcNAQEL +BQAwWjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMSEwHwYDVQQKDBhJbnRlcm5l +dCBXaWRnaXRzIFB0eSBMdGQxGzAZBgNVBAMMEmZvby5iYXIuaG9vLmNhLmNvbTAe +Fw0yNTAzMTgxNjE4NTFaFw0zNTAzMTYxNjE4NTFaMCcxJTAjBgNVBAMMHGludGVy +bWVkaWF0ZWNlcnQuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQC7XOGe2r5KNdo7ELwJ7GRAIVqxAkT9bB6+7rUyDhJnxWeI7E9vr+I4 +clDRYREoxnuXq6oGTICKlWivvrxBASSdA0PpjLsMNnNU1n9XHXEBEa3YM7w85UBv +f/8IdlpiyHgPkg+1DdvuToOa0Xhejnq/aCcNyErjjNN26k/06joO3+feYvsn1tTo +Xomif4HUU+SE5xIGiuPHcDwJtjk/Iugh+pNPdltOguxq2E7m8upQvwShe2A6azD1 +wV9HiyFtkf7tlp4f900MmRybkHb7zXfgXBwlf7waa2RP3UDZbJAZZZkOFQmPcujN +vkAz/ghaf0Uf2Ix/P0Zh69LUnotPVa35AgMBAAGjgYMwgYAwDgYDVR0PAQH/BAQD +AgGmMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBTozd97no7w/qAJQZxNFwSYq6ydVjAfBgNVHSMEGDAWgBQv +9hMRcplGNs6/zYLAYy4F43ASsjANBgkqhkiG9w0BAQsFAAOCAgEApXU0I4IWvGYo +qpU0EdDcja7qAV3MaXQRk5hgViaSd+iAd3I04EMDeWomTVb3ZFSPBR2cwPy3vJ6Y +cLx1gxRCH2gJNj85EjwQ44Fj4/gbSnx2rNVeTmzjyQ4bt6dzdaorGW6ydZgqfX3f +n++wx9an7Q56NuBOLihInTMHOocVnizHrse5zXN3dXMZxBOU1EHCgKi9xAGMZRmR +r+AYYXcWB6PRxxwCX7VG4STGYz+GRb4rx0hEl/oQatMqxatN1nAvXCwBASWp47UX +3n3Tl0/jq0c7DSbL5i+VQridDaifRozBbOkDowS+JDbV1BzYQ/oo9C3kzjraRCXI +ZJrO9pMNTyLHOXwC9LdlN/30Pe1j40jVo1CR29uONeqmUeJKHfPFBtucVE7ohqHu +ESHuxZWb0VP7uVWaVIOQ9l8XZcLXtnmSQpHW+4aYbE4q9L0abZ312yRAtyOM/NSH +wdJn8436jJnu1t8Va85M6lzQHY1E0gxuT9cw02PuS65odFseW7H9gGtlqlOzfVV2 +/psCLlAjVSRQ78zIH6y8DvWGMqabyznIAgZf/PVj9cydPA1he9We6V//Kdcv/Bb8 +RQyryujLBalUTyA9AtDGijp+NWkb1h1uyX0vhiIjJubEu6KKQ5YrZkLXjz+E4I20 +E5GmOYoJhLGkeoUjoTC2wuNFsLFJJHs= +-----END CERTIFICATE----- diff --git a/testdata/spiffe_end2end/intermediate_gen.sh b/testdata/spiffe_end2end/intermediate_gen.sh new file mode 100644 index 000000000000..6fa8698aa4ad --- /dev/null +++ b/testdata/spiffe_end2end/intermediate_gen.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright 2025 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +# Meant to be run from testdata/spiffe_end2end/ +# Sets up an intermediate ca, generates certificates, then copies then up and deletes unnecessary files + +rm -rf intermediate_ca +mkdir intermediate_ca +cp intermediate.cnf intermediate_ca/ +cp spiffe-openssl.cnf intermediate_ca/ +pushd intermediate_ca + +# Generating the intermediate CA +openssl genrsa -out temp.rsa 2048 +openssl pkcs8 -topk8 -in temp.rsa -out intermediate_ca.key -nocrypt +rm temp.rsa +openssl req -key intermediate_ca.key -new -out temp.csr -config intermediate.cnf +openssl x509 -req -days 3650 -in temp.csr -CA "../ca.pem" -CAkey "../ca.key" -CAcreateserial -out intermediate_ca.pem -extfile intermediate.cnf -extensions 'v3_req' + +# Generating the leaf and chain +openssl genrsa -out temp.rsa 2048 +openssl pkcs8 -topk8 -in temp.rsa -out leaf_signed_by_intermediate.key -nocrypt +openssl req -new -key leaf_signed_by_intermediate.key -out spiffe-cert.csr \ + -subj /C=US/ST=CA/L=SVL/O=gRPC/CN=testserver/ \ + -config spiffe-openssl.cnf -reqexts spiffe_server_e2e +openssl x509 -req -CA intermediate_ca.pem -CAkey intermediate_ca.key -CAcreateserial \ + -in spiffe-cert.csr -out leaf_signed_by_intermediate.pem -extensions spiffe_server_e2e \ + -extfile spiffe-openssl.cnf -days 3650 -sha256 +cat leaf_signed_by_intermediate.pem intermediate_ca.pem > leaf_and_intermediate_chain.pem + +popd + +# Copy files up to the higher directory +cp "./intermediate_ca/leaf_signed_by_intermediate.key" ./ +cp "./intermediate_ca/leaf_signed_by_intermediate.pem" ./ +cp "./intermediate_ca/leaf_and_intermediate_chain.pem" ./ +cp "./intermediate_ca/intermediate_ca.key" ./ +cp "./intermediate_ca/intermediate_ca.pem" ./ + +rm ca.srl +rm -rf intermediate_ca diff --git a/testdata/spiffe_end2end/leaf_and_intermediate_chain.pem b/testdata/spiffe_end2end/leaf_and_intermediate_chain.pem new file mode 100644 index 000000000000..a1cd9010a479 --- /dev/null +++ b/testdata/spiffe_end2end/leaf_and_intermediate_chain.pem @@ -0,0 +1,50 @@ +-----BEGIN CERTIFICATE----- +MIIDvjCCAqagAwIBAgIUSuuNuIcMCQ1UZrOtCL689eeZx9EwDQYJKoZIhvcNAQEL +BQAwJzElMCMGA1UEAwwcaW50ZXJtZWRpYXRlY2VydC5leGFtcGxlLmNvbTAeFw0y +NTAzMTgxNjE4NTFaFw0zNTAzMTYxNjE4NTFaMEwxCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEMMAoGA1UEBwwDU1ZMMQ0wCwYDVQQKDARnUlBDMRMwEQYDVQQDDAp0 +ZXN0c2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAue2BY6B4 +JNz5SnYr0b4IUsXfpSxqXzpx3CymRzNiPL+ZYERQd+5PPbwyj/K0ZUPNcdGtgj0i +jCSpKl6fGNx11vY/Z5BS7DN9Z6Fqf8/sBr5BIko33UafdqB/s1avrIzFNRD1n6Fu +X1EwlQpXwjiTMLswuf6X6mJVJ2VhA/xtyO4S6fTeK2jUlFn4MYHVczJBDTiMCUPX +1Z/9SXkcwZbQTbRaWvd6c0OEWZKSWxSzWG6d4qOmq9C0Tse39cmjuDpeBvtiGik4 +pYrTmmswiQ8lgLbOY1/YGjvOD+qlxXkX9Y/cYjdygrQoY7mqnjMcUFvWK/OW0XCB +CJ1jeSflrYUd4QIDAQABo4G8MIG5MHcGA1UdEQRwMG6CECoudGVzdC5nb29nbGUu +ZnKCGHdhdGVyem9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29t +hwTAqAEDhiZzcGlmZmU6Ly9leGFtcGxlLmNvbS93b3JrbG9hZC85ZWViY2NkMjAd +BgNVHQ4EFgQUsMpVfuYdrW5+i5mFW/hCaOZiKKcwHwYDVR0jBBgwFoAU6M3fe56O +8P6gCUGcTRcEmKusnVYwDQYJKoZIhvcNAQELBQADggEBABReEQ2cIaZv5wZKOjFS +5b5QfpkbR29JTQQxrkiqdXcnonX+Q/dCH+tnzUp9LCCIsVjp6is4pdKTvPNg1ZPT +WB0KEFpVG9LAOmfcgu9pwIsKUCS384PeVhffMKXsKWfgfRGP1E7XeEIdSgpwPKzK +Defa7kwTG276xre/36WOAu9RZ32s0ltXyvHtTi0pfaGuOmryX+XeHtVpxQSjhdDB +tpLvolS+7cRsvKNKIL5X/789IKbdShMgpwPDDe6Z3riBjGPBydnA40IofRc8y3jL +0TKiBiKYOz8nj6DLAiVPqQ2vo5NzihNoqgu/HpkhSG26OAJq2NDYurMsT+Myiuq4 +YkE= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEkzCCAnugAwIBAgIUa4ZkytupQZ5OwDMPw/vRY8deFc4wDQYJKoZIhvcNAQEL +BQAwWjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMSEwHwYDVQQKDBhJbnRlcm5l +dCBXaWRnaXRzIFB0eSBMdGQxGzAZBgNVBAMMEmZvby5iYXIuaG9vLmNhLmNvbTAe +Fw0yNTAzMTgxNjE4NTFaFw0zNTAzMTYxNjE4NTFaMCcxJTAjBgNVBAMMHGludGVy +bWVkaWF0ZWNlcnQuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQC7XOGe2r5KNdo7ELwJ7GRAIVqxAkT9bB6+7rUyDhJnxWeI7E9vr+I4 +clDRYREoxnuXq6oGTICKlWivvrxBASSdA0PpjLsMNnNU1n9XHXEBEa3YM7w85UBv +f/8IdlpiyHgPkg+1DdvuToOa0Xhejnq/aCcNyErjjNN26k/06joO3+feYvsn1tTo +Xomif4HUU+SE5xIGiuPHcDwJtjk/Iugh+pNPdltOguxq2E7m8upQvwShe2A6azD1 +wV9HiyFtkf7tlp4f900MmRybkHb7zXfgXBwlf7waa2RP3UDZbJAZZZkOFQmPcujN +vkAz/ghaf0Uf2Ix/P0Zh69LUnotPVa35AgMBAAGjgYMwgYAwDgYDVR0PAQH/BAQD +AgGmMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBTozd97no7w/qAJQZxNFwSYq6ydVjAfBgNVHSMEGDAWgBQv +9hMRcplGNs6/zYLAYy4F43ASsjANBgkqhkiG9w0BAQsFAAOCAgEApXU0I4IWvGYo +qpU0EdDcja7qAV3MaXQRk5hgViaSd+iAd3I04EMDeWomTVb3ZFSPBR2cwPy3vJ6Y +cLx1gxRCH2gJNj85EjwQ44Fj4/gbSnx2rNVeTmzjyQ4bt6dzdaorGW6ydZgqfX3f +n++wx9an7Q56NuBOLihInTMHOocVnizHrse5zXN3dXMZxBOU1EHCgKi9xAGMZRmR +r+AYYXcWB6PRxxwCX7VG4STGYz+GRb4rx0hEl/oQatMqxatN1nAvXCwBASWp47UX +3n3Tl0/jq0c7DSbL5i+VQridDaifRozBbOkDowS+JDbV1BzYQ/oo9C3kzjraRCXI +ZJrO9pMNTyLHOXwC9LdlN/30Pe1j40jVo1CR29uONeqmUeJKHfPFBtucVE7ohqHu +ESHuxZWb0VP7uVWaVIOQ9l8XZcLXtnmSQpHW+4aYbE4q9L0abZ312yRAtyOM/NSH +wdJn8436jJnu1t8Va85M6lzQHY1E0gxuT9cw02PuS65odFseW7H9gGtlqlOzfVV2 +/psCLlAjVSRQ78zIH6y8DvWGMqabyznIAgZf/PVj9cydPA1he9We6V//Kdcv/Bb8 +RQyryujLBalUTyA9AtDGijp+NWkb1h1uyX0vhiIjJubEu6KKQ5YrZkLXjz+E4I20 +E5GmOYoJhLGkeoUjoTC2wuNFsLFJJHs= +-----END CERTIFICATE----- diff --git a/testdata/spiffe_end2end/leaf_signed_by_intermediate.key b/testdata/spiffe_end2end/leaf_signed_by_intermediate.key new file mode 100644 index 000000000000..23c07a777ca0 --- /dev/null +++ b/testdata/spiffe_end2end/leaf_signed_by_intermediate.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC57YFjoHgk3PlK +divRvghSxd+lLGpfOnHcLKZHM2I8v5lgRFB37k89vDKP8rRlQ81x0a2CPSKMJKkq +Xp8Y3HXW9j9nkFLsM31noWp/z+wGvkEiSjfdRp92oH+zVq+sjMU1EPWfoW5fUTCV +ClfCOJMwuzC5/pfqYlUnZWED/G3I7hLp9N4raNSUWfgxgdVzMkENOIwJQ9fVn/1J +eRzBltBNtFpa93pzQ4RZkpJbFLNYbp3io6ar0LROx7f1yaO4Ol4G+2IaKTilitOa +azCJDyWAts5jX9gaO84P6qXFeRf1j9xiN3KCtChjuaqeMxxQW9Yr85bRcIEInWN5 +J+WthR3hAgMBAAECggEACGVwarbpIAyK1TUQkeVnl7HUAX/3yoa/lDBfvq7ESp8i +KnPRULYuRcjfPWsJ4JoTD7cW418WhZ7E9SruWzt+9pL6nmcZCI3DdbPnVN/nTi9m +rnlMrCljm4JAXBFfx+54PCcQuYmLLAKlC5D60TR3+KsWZmrX8kuoIeohC0KZtFlw +xHC1fz6k9qbStDW8UBWUY8I1N2Zh9U5kYGNG9j5rLYzs7zJ23xWmiGOwywGlLSii +2i9vC+XwQATFmgFyVM9F9W4P//ElOADDXDhBU8R3UXXoK5+s+Bx12gyTeBfSLgy1 +I5/ee2rFJdlGUsOvEO39npHDCeFDKe0MjeJY8FcSUQKBgQDcXJYnxM6ULY3T9jrf +rSiVi4S7Rewq7KdFDKo32Lqr85VJ3+nqOtLjdyTnHpsRYQSBDbMluMjImfcWxLym +e/3ldNdRR4W6YSdL8kvnKvxsCYR/XC5wihfgKLY3yU7iydrJjFdQZlmFLbCAom7U +P26OJXo8STCD9BURFKlzm24W0QKBgQDX/0lBWuWNhF8h65WK7Lp8zj2LzZFfNOB2 +YysKKteYxDmyV7dKZogG9KDDbDpiylDhg58i8c949/73diCGbZHRMCFFeTO6SOjx ++2Z0iLgMs1IxqLCLhv/H/nfyNii+/G80JDHKR0d0xFQRfAzIVbBaxjL6JiI9aJdl +Y+yJYHZ6EQKBgQCTtPftVk1GI7bSolTaQ35VpzxkLz1blF+WuCOM5ZhS1CZ4az+n +AqEDWYSB6xD0ODzFqIIxwcfMNu/Z8iulyKzqVkRRtghcYuztSk84d6bVYBfRKt/y +DY5tcbyabjSTbcxalticCs7spzCNONPjL1WSsGpb6I89k6lfVqMy27eSUQKBgQCG +rFdidmg2Klieb6LX8e38ryLUriF7uR5S8lX9iuTODVrkBaj0rKUXoSMzdaGZwwdW +9JgeU6LGi+nfJTn2Vw7Z3SaBiKZl+du0NMmW0z/eO1h+Oe2JsWx9p/3leTtCiWZU +nlSlCHhXJ6o7FJtrtXG1x2o1ad1jaHks8Hak2Q5F4QKBgQCQpMwv662qJai06bpQ +Q1A3rzn/LbDIPZmkadRE9+Lv1KDHp3uhkxX53DK7K560adwUYurzfsyp3VV763h4 +73Lk/z6wOTjmXNO3b/+asKx9z063XZc0vUxct7Del5+C28s026XfUOy30IMaIQqr +ei17qa7SQn3GwetSxblr+IQKHg== +-----END PRIVATE KEY----- diff --git a/testdata/spiffe_end2end/leaf_signed_by_intermediate.pem b/testdata/spiffe_end2end/leaf_signed_by_intermediate.pem new file mode 100644 index 000000000000..e9c9f064a4d5 --- /dev/null +++ b/testdata/spiffe_end2end/leaf_signed_by_intermediate.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDvjCCAqagAwIBAgIUSuuNuIcMCQ1UZrOtCL689eeZx9EwDQYJKoZIhvcNAQEL +BQAwJzElMCMGA1UEAwwcaW50ZXJtZWRpYXRlY2VydC5leGFtcGxlLmNvbTAeFw0y +NTAzMTgxNjE4NTFaFw0zNTAzMTYxNjE4NTFaMEwxCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEMMAoGA1UEBwwDU1ZMMQ0wCwYDVQQKDARnUlBDMRMwEQYDVQQDDAp0 +ZXN0c2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAue2BY6B4 +JNz5SnYr0b4IUsXfpSxqXzpx3CymRzNiPL+ZYERQd+5PPbwyj/K0ZUPNcdGtgj0i +jCSpKl6fGNx11vY/Z5BS7DN9Z6Fqf8/sBr5BIko33UafdqB/s1avrIzFNRD1n6Fu +X1EwlQpXwjiTMLswuf6X6mJVJ2VhA/xtyO4S6fTeK2jUlFn4MYHVczJBDTiMCUPX +1Z/9SXkcwZbQTbRaWvd6c0OEWZKSWxSzWG6d4qOmq9C0Tse39cmjuDpeBvtiGik4 +pYrTmmswiQ8lgLbOY1/YGjvOD+qlxXkX9Y/cYjdygrQoY7mqnjMcUFvWK/OW0XCB +CJ1jeSflrYUd4QIDAQABo4G8MIG5MHcGA1UdEQRwMG6CECoudGVzdC5nb29nbGUu +ZnKCGHdhdGVyem9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29t +hwTAqAEDhiZzcGlmZmU6Ly9leGFtcGxlLmNvbS93b3JrbG9hZC85ZWViY2NkMjAd +BgNVHQ4EFgQUsMpVfuYdrW5+i5mFW/hCaOZiKKcwHwYDVR0jBBgwFoAU6M3fe56O +8P6gCUGcTRcEmKusnVYwDQYJKoZIhvcNAQELBQADggEBABReEQ2cIaZv5wZKOjFS +5b5QfpkbR29JTQQxrkiqdXcnonX+Q/dCH+tnzUp9LCCIsVjp6is4pdKTvPNg1ZPT +WB0KEFpVG9LAOmfcgu9pwIsKUCS384PeVhffMKXsKWfgfRGP1E7XeEIdSgpwPKzK +Defa7kwTG276xre/36WOAu9RZ32s0ltXyvHtTi0pfaGuOmryX+XeHtVpxQSjhdDB +tpLvolS+7cRsvKNKIL5X/789IKbdShMgpwPDDe6Z3riBjGPBydnA40IofRc8y3jL +0TKiBiKYOz8nj6DLAiVPqQ2vo5NzihNoqgu/HpkhSG26OAJq2NDYurMsT+Myiuq4 +YkE= +-----END CERTIFICATE----- diff --git a/testdata/spiffe_end2end/server.key b/testdata/spiffe_end2end/server.key new file mode 100644 index 000000000000..6bc006ce5971 --- /dev/null +++ b/testdata/spiffe_end2end/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCpfq2SvTp7uxmk +ux2D9fM3yBOum3YjRx3HLplC0GkBOHCwvsvw03ipQk8DJOSz0enun6SaLEhOZJ3Z +9Y24qEeMEeWfm2rWrCzULmf2qH9lmJ1fYdj3V/v8x+ulgUWiSRB9LiwJzSFt0uTK +L+PZZLjfkze8SFB6Zn6NBnTKzWbLs/ZxjiJcin8YLMoAnS5FfEVMfaDwE3RO9kED +Jt0YG8bf6p8Tv773aOrDW2WszxWSUwoVMe2ByHajf6vC7/oyh1lrq0QIUy0AnXst +3DKPolenY+Qt+17XP9HZf52cLVolzuhjw+yjEKMxbwHtXewayMHkoV5ySck5VrC9 +iF34jyTfAgMBAAECggEABxYYw63NqCamZ9C65y19QbPHvuEZC1iJ0i4MklKMUVS+ +wWT4udTdkpYHH6aHOU1pbmSWSSvYyg5C2z388t92PlDxPL8OtHL2XNij2BgrW2AK +FFbO72hqTKM/IuhItQRBADrR9IbzAthyYFGoQQqJAC/zgJe1ZairWdIPR/tWdOW7 +1+ctVWIMCKpTpomuoI1oK7PJos6ciIQ5yCWPhMVyQ4EInG4YHF4r2agxWyaF5MLT +gu/qH7tKvkCgo+jjofEntCrw7QYqW8HSFLGm5wxus4/vxoyrwRAgwSotm13tpbg8 +ODleK3u8S50zXuVk/+smskHv1QMGVAxuVFi7ZpPHAQKBgQDU6KpvYOZPR5+XdQNn +BBGbkgaw0qQ7E+1w3pbcaEpglcLQRQn2fjwUOc7YWV8SpMXIneqfhvGLPJXKExXK +coCdjyPAy77zAt7HOVJwAfYaLaoyxnAxnFIgTCLUOchvysWuvauYOkBF5d1GCbXK +v5XUqbLiWnQoLPESubm/IJEEfwKBgQDLzJ/wmEn8vCZk6saEJoFkfG43oJaGrDOT +kKE5pgLSNOtBB6ML4xliU1rwbHz+gpmQKBpb1zQedSyB9rd5G+NzPFQ14RoTsR10 +71S6o8jacIJxo6vZWrS3yOJSBcEhU2K8yFRGgI3cy53JtT5gZIckyINnovdTZpR7 +7vdhPngvoQKBgQC4FH4flGEsVJnIYrRRYjQzFLtSMJ0sMxuNBfbblBQSlAl+9uIZ +S6V4O076wbKwtOQIg3iy+wJmRzifIYcqpXtMPtFDxSVQiL/C8m2zSA7XLXpFMksY +qbZcFFfctCT3exMV9QmisWKWzJpXDtgt9x19ZEe0604Y2lqIvSm69VZM0wKBgHHG +I8gijLOOqnSOaRMfl/7sRG/DtCUs/4IzLP7NAiguKOPeCpU5TFOLK2qrdkBz0p0a +9lQtWUhjq9xGSvlOq3UKygxmRbOWnlZIwmmLxDbGttwQPoESVW+As3CNC9u5/JZd +1EajwA7ykX0pNNCFbrkHQ+zYmvCxhNWHfA2K3XfhAoGAUtwFJFNRCYIGiFVrQ19n +nwCt4+3zYT8wTL1EbyWa0pKhADFSwnwdhJ1ZNev1hKu663+iQO5KdlBeoicicpOA +hNkrw5Al4pvJBp+WV6pqCLtMbuJUBYAWOpUipGnnJsEYTC9SxDnIqh+6Qc7tsEYv +xDykqFvrNxQXLahWavYW8Lg= +-----END PRIVATE KEY----- diff --git a/testdata/spiffe_end2end/server_spiffe.pem b/testdata/spiffe_end2end/server_spiffe.pem new file mode 100644 index 000000000000..f607d7c848d2 --- /dev/null +++ b/testdata/spiffe_end2end/server_spiffe.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE+DCCAuCgAwIBAgIUBoJ396S7DO0kRqDUn4TB6zKKIIowDQYJKoZIhvcNAQEL +BQAwWjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMSEwHwYDVQQKDBhJbnRlcm5l +dCBXaWRnaXRzIFB0eSBMdGQxGzAZBgNVBAMMEmZvby5iYXIuaG9vLmNhLmNvbTAe +Fw0yNTAzMDcxOTM0NDZaFw0zNTAzMDUxOTM0NDZaMFMxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEMMAoGA1UEBwwDU1ZMMQ0wCwYDVQQKDARnUlBDMRowGAYDVQQD +DBEqLnRlc3QuZ29vZ2xlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAKl+rZK9Onu7GaS7HYP18zfIE66bdiNHHccumULQaQE4cLC+y/DTeKlCTwMk +5LPR6e6fpJosSE5kndn1jbioR4wR5Z+batasLNQuZ/aof2WYnV9h2PdX+/zH66WB +RaJJEH0uLAnNIW3S5Mov49lkuN+TN7xIUHpmfo0GdMrNZsuz9nGOIlyKfxgsygCd +LkV8RUx9oPATdE72QQMm3Rgbxt/qnxO/vvdo6sNbZazPFZJTChUx7YHIdqN/q8Lv ++jKHWWurRAhTLQCdey3cMo+iV6dj5C37Xtc/0dl/nZwtWiXO6GPD7KMQozFvAe1d +7BrIweShXnJJyTlWsL2IXfiPJN8CAwEAAaOBvDCBuTB3BgNVHREEcDBughAqLnRl +c3QuZ29vZ2xlLmZyghh3YXRlcnpvb2kudGVzdC5nb29nbGUuYmWCEioudGVzdC55 +b3V0dWJlLmNvbYcEwKgBA4Ymc3BpZmZlOi8vZXhhbXBsZS5jb20vd29ya2xvYWQv +OWVlYmNjZDIwHQYDVR0OBBYEFDJn3wGxfbvBrS/dTLOScNtTMi9EMB8GA1UdIwQY +MBaAFC/2ExFymUY2zr/NgsBjLgXjcBKyMA0GCSqGSIb3DQEBCwUAA4ICAQCaWp4p +qmG5il353PrAedmk7kk5+YigeX/uUBYCdOm/j/M4IpJpsmkfFStYIhJAq3H2KViQ +x7MNRLd15Z2fcdx9qWJ7aHq9fp9W7L1dINbiFD0KTp9c9oD2HpXnldy8r1EIDDaQ +VxIlJDd3rUsebLT4oPZ13HQDp5clJ44WdcybqFgbvcJoxhXYMlBXOKwsLlm+abDO +0XWEfubO/irsrsByUmaoGc/0Adf2O+wgDo9xSB4d2b601K02dYpl71NNelRvBrB5 +FubExuAef+4xgha/eMn+qcRBhH2jv7Fjc1HuKH8srukcRJHblQy96reJj2bcDhp/ +bPJ2xBzc13UZ2do9A209qGRCHONd5VH5NY++484XlFf12jJUEQiUCT7jOReFbUbR +FkiHbyapVEmqnI8RifPbRIov/XzCqkaCZuMW+64cr6eBpuoi8YV+xV37zHYhT2bf +Wpk83uyuvw6qZApQPLc2MQ6MpRv3740S/0+lKjNoG5xi2loNCMTGCgtt7EQT93cZ +z/picgGigC1qIPonukQsdf+cCD3eC0Kd45VEj8bon4MxmjbROUdVzVwG4wmptF7l +jB3GjnqHfEJl1RuDsLFEtBSqjESQTeeOuNMcPKSfNVbePLf4CxuRmIXumpwAxicw +aeSaOwEPybd7LBd8qJHSRgfKMMgKnpZgzV4SZQ== +-----END CERTIFICATE----- diff --git a/testdata/spiffe_end2end/server_spiffebundle.json b/testdata/spiffe_end2end/server_spiffebundle.json new file mode 100644 index 000000000000..928d15b35cce --- /dev/null +++ b/testdata/spiffe_end2end/server_spiffebundle.json @@ -0,0 +1,18 @@ +{ + "trust_domains": { + "foo.bar.com": { + "spiffe_sequence": 12035488, + "keys": [ + { + "kty": "RSA", + "use": "x509-svid", + "x5c": [ + "MIIFlTCCA32gAwIBAgIUCD73sHXu5IURolSTiJ127a/xUO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxGzAZBgNVBAMMEmZvby5iYXIuaG9vLmNhLmNvbTAeFw0yNTAzMDcxOTM0NDZaFw0yNjAzMDcxOTM0NDZaMFoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRswGQYDVQQDDBJmb28uYmFyLmhvby5jYS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC19PImArmxbwgqo2QG2si8BU6E69Bvyqxz8Je3swxBIGwZ9uIobMSBLeTCYyXuf+o90Zf0kMwzmrAKeLEeky5W/j07zGXAtgUBPA7L1Uk0TxOdJXBCUvEm5Oc4GxubfO7F+pdJKZ+XkRVqbnStGe5qX6KNs5rcJfFUhewbtM0snGEIf2yhaA0mNNuGtlIm4VB7jmiyHNU5YTowByVCVrV3/t2RI9+T4ya0AlkW93rU0M0qQauJ35LkJIXifbzrnLxmztEyb+mnVUB+GJgz01E4teWo/PJb1aNJ/ojf/UONsQ5IFRdza6RhaQB7C+Dxlnt/SJ3MMaxHgVycYuJeVtJQuncGRSuQ2YrmW9b36HVnxa0xBDeSluUjv48hMRlLNaXaH4yuK6oc8TNJie++/ir6Kb4H+0RjcKMGqxZYfotU1obxa+5N3wzGSjUDUrhofzlfvqbp+NCwdFH+qczM4IZPL8YMMh6goKr9BRN9/xRIieotyH6rfKNcnkUgDp750U0cZ7P2eRUpldyc9hZS5AlF4cKQXgLIrv1LrZHkiIietetInUEBAa/PF2YHRLXUyI1PCSBKBu7wdwAU15J9dVFC9jkmOLYhoRdPfrobpWhs5+FfPJumSoiusdGXd7x4l313xi2V02YXz5mRGbT2lCb6aJPweuziiEBZn+5KV++DkQIDAQABo1MwUTAdBgNVHQ4EFgQUL/YTEXKZRjbOv82CwGMuBeNwErIwHwYDVR0jBBgwFoAUL/YTEXKZRjbOv82CwGMuBeNwErIwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAIYtNERVMj4dS/KgoXD3a6mF6KD+IuxDTlVbVTwDJMzdNW5UPB2qCiDKbirK8Eedh90r3qxKzBiQPE5AHDZrbWSBAxDhlpQqCXgx8Z+nCB38K9i8hbKM/ablm9DkeHiHohoP1kJEN2HtPz1K6OabbKbPtVGt8y+QTIlZDodPPzKPmQ6dUTm9tWlU1oIxl4pPVR6WXDr0qAmNRvdW7+8/Ai+gMDi6fKQJCe/r/meVrI9lSrnn8VQyO4xXvyolHEROTUiomlJ1QE9IWAM9LNFOuWFwQjayo2d6O+zHqjGUtbzBHFb8/BLJcQzogWYT0/+rEboJhR+/OGe0ntPPkudmLL0HTx0Q1aajnChMVlaOd2wucePZSa6GqGEVA+lCqwbteqwJCnL7deVHo+UlORFgQwYir2CQbyN9Yd4MtQT7VZuDiVC6tlGbj1ogrpOnW8n49jXrNPWuPz2hcPQb2gzYFGI9WRKIX4SjvvS3QcHUyigQkjAQ12Ldj5CXBYTjSmjcgsa2QfUY5qrXsHLz7e4uXD9XYnB/XEEfxQfQTFEy5CtzTrTxnT+cwRuBooIr6InjqdbdJ+UbkWcIY6w+c7ndFT849pUgtrojbVpm9ZzsmHhAahR/+iHYH+LGeHYIpq71o/YDgM4vV9z3sWic7u1YE9JULBdlaDw8Xik82zjvw4IA=" + ], + "n": "tfTyJgK5sW8IKqNkBtrIvAVOhOvQb8qsc_CXt7MMQSBsGfbiKGzEgS3kwmMl7n_qPdGX9JDMM5qwCnixHpMuVv49O8xlwLYFATwOy9VJNE8TnSVwQlLxJuTnOBsbm3zuxfqXSSmfl5EVam50rRnual-ijbOa3CXxVIXsG7TNLJxhCH9soWgNJjTbhrZSJuFQe45oshzVOWE6MAclQla1d_7dkSPfk-MmtAJZFvd61NDNKkGrid-S5CSF4n2865y8Zs7RMm_pp1VAfhiYM9NROLXlqPzyW9WjSf6I3_1DjbEOSBUXc2ukYWkAewvg8ZZ7f0idzDGsR4FcnGLiXlbSULp3BkUrkNmK5lvW9-h1Z8WtMQQ3kpblI7-PITEZSzWl2h-MriuqHPEzSYnvvv4q-im-B_tEY3CjBqsWWH6LVNaG8WvuTd8Mxko1A1K4aH85X76m6fjQsHRR_qnMzOCGTy_GDDIeoKCq_QUTff8USInqLch-q3yjXJ5FIA6e-dFNHGez9nkVKZXcnPYWUuQJReHCkF4CyK79S62R5IiInrXrSJ1BAQGvzxdmB0S11MiNTwkgSgbu8HcAFNeSfXVRQvY5Jji2IaEXT366G6VobOfhXzybpkqIrrHRl3e8eJd9d8YtldNmF8-ZkRm09pQm-miT8Hrs4ohAWZ_uSlfvg5E", + "e": "AQAB" + } + ] + } + } +} diff --git a/testdata/spiffe_end2end/spiffe-openssl.cnf b/testdata/spiffe_end2end/spiffe-openssl.cnf new file mode 100644 index 000000000000..0092743a2eed --- /dev/null +++ b/testdata/spiffe_end2end/spiffe-openssl.cnf @@ -0,0 +1,28 @@ +[spiffe_client] +subjectAltName = @alt_names + +[spiffe_client_multi] +subjectAltName = @alt_names_multi + +[spiffe_server_e2e] +subjectAltName = @alt_names_server_e2e + +[spiffe_client_e2e] +subjectAltName = @alt_names_client_e2e + +[alt_names] +URI = spiffe://foo.bar.com/client/workload/1 + +[alt_names_multi] +URI.1 = spiffe://foo.bar.com/client/workload/1 +URI.2 = spiffe://foo.bar.com/client/workload/2 + +[alt_names_server_e2e] +DNS.1 = *.test.google.fr +DNS.2 = waterzooi.test.google.be +DNS.3 = *.test.youtube.com +IP.1 = "192.168.1.3" +URI = spiffe://example.com/workload/9eebccd2 + +[alt_names_client_e2e] +URI = spiffe://foo.bar.com/9eebccd2-12bf-40a6-b262-65fe0487d453