package tlsreload import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" "crypto/x509/pkix" "encoding/pem" "math/big" "net/url" "os" "path/filepath" "testing" "time" ) func TestResolveSPIFFEIdentityUsesExactRoleSpecificURI(t *testing.T) { certificatePath, keyPath := writeWorkloadCertificate(t, "gateway-a", "spiffe://proxy-pool.local/production/worker/gateway-a") identity, err := ResolveSPIFFEIdentity(certificatePath, keyPath, "proxy-pool.local", "production", "worker") if err != nil || identity != "gateway-a" { t.Fatalf("ResolveSPIFFEIdentity() = (%q, %v), want (gateway-a, nil)", identity, err) } if _, err := ResolveSPIFFEIdentity(certificatePath, keyPath, "proxy-pool.local", "production", "checker"); err == nil { t.Fatal("ResolveSPIFFEIdentity(checker) error = nil") } } func TestResolveSPIFFEIdentityRejectsMultipleMatchingURIs(t *testing.T) { certificatePath, keyPath := writeWorkloadCertificate(t, "gateway-a", "spiffe://proxy-pool.local/production/worker/gateway-a", "spiffe://proxy-pool.local/production/worker/gateway-b", ) if _, err := ResolveSPIFFEIdentity(certificatePath, keyPath, "proxy-pool.local", "production", "worker"); err == nil { t.Fatal("ResolveSPIFFEIdentity(multiple identities) error = nil") } } func TestResolveSPIFFEIdentityRejectsMultipleURISANsAcrossRoles(t *testing.T) { certificatePath, keyPath := writeWorkloadCertificate(t, "gateway-a", "spiffe://proxy-pool.local/production/worker/gateway-a", "spiffe://proxy-pool.local/production/checker/checker-a", ) if _, err := ResolveSPIFFEIdentity(certificatePath, keyPath, "proxy-pool.local", "production", "worker"); err == nil { t.Fatal("ResolveSPIFFEIdentity(multiple URI SANs) error = nil") } } func writeWorkloadCertificate(t *testing.T, commonName string, identityURIs ...string) (string, string) { t.Helper() directory := t.TempDir() certificatePath := filepath.Join(directory, "tls.crt") keyPath := filepath.Join(directory, "tls.key") privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { t.Fatalf("generate workload key: %v", err) } identities := make([]*url.URL, 0, len(identityURIs)) for _, raw := range identityURIs { identity, parseErr := url.Parse(raw) if parseErr != nil { t.Fatalf("parse workload identity: %v", parseErr) } identities = append(identities, identity) } now := time.Now() template := &x509.Certificate{ SerialNumber: big.NewInt(now.UnixNano()), Subject: pkix.Name{CommonName: commonName}, URIs: identities, NotBefore: now.Add(-time.Minute), NotAfter: now.Add(time.Hour), KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, } der, err := x509.CreateCertificate(rand.Reader, template, template, &privateKey.PublicKey, privateKey) if err != nil { t.Fatalf("create workload certificate: %v", err) } certificate := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}) privateDER, err := x509.MarshalPKCS8PrivateKey(privateKey) if err != nil { t.Fatalf("marshal workload key: %v", err) } key := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privateDER}) if err := os.WriteFile(certificatePath, certificate, 0o600); err != nil { t.Fatalf("write workload certificate: %v", err) } if err := os.WriteFile(keyPath, key, 0o600); err != nil { t.Fatalf("write workload key: %v", err) } return certificatePath, keyPath }