diff --git a/agent/cache-types/connect_ca_leaf.go b/agent/cache-types/connect_ca_leaf.go index 8f98080adb..ce98955c6e 100644 --- a/agent/cache-types/connect_ca_leaf.go +++ b/agent/cache-types/connect_ca_leaf.go @@ -540,7 +540,9 @@ func (c *ConnectCALeaf) generateNewLeaf(req *ConnectCALeafRequest, var id connect.CertURI var dnsNames []string var ipAddresses []net.IP - if req.Service != "" { + + switch { + case req.Service != "": id = &connect.SpiffeIDService{ Host: roots.TrustDomain, Datacenter: req.Datacenter, @@ -549,7 +551,8 @@ func (c *ConnectCALeaf) generateNewLeaf(req *ConnectCALeafRequest, Service: req.Service, } dnsNames = append(dnsNames, req.DNSSAN...) - } else if req.Agent != "" { + + case req.Agent != "": id = &connect.SpiffeIDAgent{ Host: roots.TrustDomain, Datacenter: req.Datacenter, @@ -558,19 +561,30 @@ func (c *ConnectCALeaf) generateNewLeaf(req *ConnectCALeafRequest, } dnsNames = append([]string{"localhost"}, req.DNSSAN...) ipAddresses = append([]net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")}, req.IPSAN...) - } else if req.Kind != "" { - if req.Kind != structs.ServiceKindMeshGateway { - return result, fmt.Errorf("unsupported kind: %s", req.Kind) - } + case req.Kind == structs.ServiceKindMeshGateway: id = &connect.SpiffeIDMeshGateway{ Host: roots.TrustDomain, Datacenter: req.Datacenter, Partition: req.TargetPartition(), } dnsNames = append(dnsNames, req.DNSSAN...) - } else { - return result, errors.New("URI must be either service, agent, or kind") + + case req.Kind != "": + return result, fmt.Errorf("unsupported kind: %s", req.Kind) + + case req.Server: + if req.Datacenter == "" { + return result, errors.New("datacenter name must be specified") + } + id = &connect.SpiffeIDServer{ + Host: roots.TrustDomain, + Datacenter: req.Datacenter, + } + dnsNames = append(dnsNames, connect.PeeringServerSAN(req.Datacenter, roots.TrustDomain)) + + default: + return result, errors.New("URI must be either service, agent, server, or kind") } // Create a new private key @@ -679,6 +693,7 @@ type ConnectCALeafRequest struct { Service string // Service name, not ID Agent string // Agent name, not ID Kind structs.ServiceKind // only mesh-gateway for now + Server bool DNSSAN []string IPSAN []net.IP MinQueryIndex uint64 @@ -711,6 +726,14 @@ func (r *ConnectCALeafRequest) Key() string { } case r.Kind != "": // this is not valid + case r.Server: + v, err := hashstructure.Hash([]interface{}{ + "server", + r.Datacenter, + }, nil) + if err == nil { + return fmt.Sprintf("server:%d", v) + } default: v, err := hashstructure.Hash([]interface{}{ r.Service, diff --git a/agent/cache-types/connect_ca_leaf_test.go b/agent/cache-types/connect_ca_leaf_test.go index dc709f56a5..04fe805cb0 100644 --- a/agent/cache-types/connect_ca_leaf_test.go +++ b/agent/cache-types/connect_ca_leaf_test.go @@ -1164,4 +1164,11 @@ func TestConnectCALeaf_Key(t *testing.T) { }) }) }) + t.Run("server", func(t *testing.T) { + r1 := key(ConnectCALeafRequest{ + Server: true, + Datacenter: "us-east", + }) + require.True(t, strings.HasPrefix(r1, "server:"), "Key %s does not start with server:", r1) + }) } diff --git a/agent/connect/uri_server.go b/agent/connect/uri_server.go index 3d120b5b9b..e6d7110514 100644 --- a/agent/connect/uri_server.go +++ b/agent/connect/uri_server.go @@ -18,3 +18,9 @@ func (id SpiffeIDServer) URI() *url.URL { result.Path = fmt.Sprintf("/agent/server/dc/%s", id.Datacenter) return &result } + +// PeeringServerSAN returns the DNS SAN to attach to server certificates +// for control-plane peering traffic. +func PeeringServerSAN(dc, trustDomain string) string { + return fmt.Sprintf("server.%s.peering.%s", dc, trustDomain) +} diff --git a/agent/connect/uri_test.go b/agent/connect/uri_test.go index 1cc3f7a1f6..b57f3ffe84 100644 --- a/agent/connect/uri_test.go +++ b/agent/connect/uri_test.go @@ -157,3 +157,9 @@ func TestSpiffeIDServer_URI(t *testing.T) { require.Equal(t, "spiffe://1234.consul/agent/server/dc/dc1", srv.URI().String()) } + +func TestServerSAN(t *testing.T) { + san := PeeringServerSAN("dc1", TestTrustDomain) + expect := "server.dc1.peering." + TestTrustDomain + require.Equal(t, expect, san) +}