From 7be442ee637151ffa71ebe878a239412244fd286 Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Mon, 14 Nov 2022 10:27:03 -0800 Subject: [PATCH] connect: strip port from DNS SANs for ingress gateway leaf cert (#15320) * connect: strip port from DNS SANs for ingress gateway leaf cert * connect: format DNS SANs in CreateCSR * connect: Test wildcard case when formatting SANs --- .changelog/15320.txt | 3 +++ agent/connect/csr.go | 20 +++++++++++++++++++- agent/connect/csr_test.go | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 .changelog/15320.txt create mode 100644 agent/connect/csr_test.go diff --git a/.changelog/15320.txt b/.changelog/15320.txt new file mode 100644 index 000000000..b38b554d2 --- /dev/null +++ b/.changelog/15320.txt @@ -0,0 +1,3 @@ +```release-note:bug +connect: strip port from DNS SANs for ingress gateway leaf certificate to avoid an invalid hostname error when using the Vault provider. +``` diff --git a/agent/connect/csr.go b/agent/connect/csr.go index f699a5879..63ba59476 100644 --- a/agent/connect/csr.go +++ b/agent/connect/csr.go @@ -12,6 +12,7 @@ import ( "fmt" "net" "net/url" + "strings" ) // SigAlgoForKey returns the preferred x509.SignatureAlgorithm for a given key @@ -47,11 +48,28 @@ func SigAlgoForKeyType(keyType string) x509.SignatureAlgorithm { // along with the PEM-encoded private key for this certificate. func CreateCSR(uri CertURI, privateKey crypto.Signer, dnsNames []string, ipAddresses []net.IP, extensions ...pkix.Extension) (string, error) { + + // Drop everything after the ':' from the name when constructing the DNS SANs. + uniqueNames := make(map[string]struct{}) + formattedDNSNames := make([]string, 0) + for _, host := range dnsNames { + hostSegments := strings.Split(host, ":") + if len(hostSegments) == 0 || hostSegments[0] == "" { + continue + } + + formattedHost := hostSegments[0] + if _, ok := uniqueNames[formattedHost]; !ok { + formattedDNSNames = append(formattedDNSNames, formattedHost) + uniqueNames[formattedHost] = struct{}{} + } + } + template := &x509.CertificateRequest{ URIs: []*url.URL{uri.URI()}, SignatureAlgorithm: SigAlgoForKey(privateKey), ExtraExtensions: extensions, - DNSNames: dnsNames, + DNSNames: formattedDNSNames, IPAddresses: ipAddresses, } HackSANExtensionForCSR(template) diff --git a/agent/connect/csr_test.go b/agent/connect/csr_test.go new file mode 100644 index 000000000..322585840 --- /dev/null +++ b/agent/connect/csr_test.go @@ -0,0 +1,36 @@ +package connect + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestCreateCSR_FormatDNSSANs(t *testing.T) { + pk, _, err := GeneratePrivateKey() + require.NoError(t, err) + spiffeID := &SpiffeIDService{ + Host: "7528f42f-92e5-4db4-b84c-3405c3ca91e6", + Service: "srv1", + Datacenter: "dc1", + } + csr, err := CreateCSR(spiffeID, pk, []string{ + "foo.example.com", + "foo.example.com:8080", + "bar.example.com", + "*.example.com", + ":8080", + "", + }, nil) + require.NoError(t, err) + + req, err := ParseCSR(csr) + require.NoError(t, err) + require.Len(t, req.URIs, 1) + require.Equal(t, spiffeID.URI(), req.URIs[0]) + require.Equal(t, []string{ + "foo.example.com", + "bar.example.com", + "*.example.com", + }, req.DNSNames) +}