open-consul/agent/consul/server_connect.go
Freddy 6ef38eaea7
Configure upstream TLS context with peer root certs (#13321)
For mTLS to work between two proxies in peered clusters with different root CAs,
proxies need to configure their outbound listener to use different root certificates
for validation.

Up until peering was introduced proxies would only ever use one set of root certificates
to validate all mesh traffic, both inbound and outbound. Now an upstream proxy
may have a leaf certificate signed by a CA that's different from the dialing proxy's.

This PR makes changes to proxycfg and xds so that the upstream TLS validation
uses different root certificates depending on which cluster is being dialed.
2022-06-01 15:53:52 -06:00

77 lines
2.2 KiB
Go

package consul
import (
"fmt"
"github.com/hashicorp/go-memdb"
"github.com/hashicorp/consul/agent/connect"
"github.com/hashicorp/consul/agent/consul/state"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/lib"
)
func (s *Server) getCARoots(ws memdb.WatchSet, state *state.Store) (*structs.IndexedCARoots, error) {
index, roots, config, err := state.CARootsAndConfig(ws)
if err != nil {
return nil, err
}
if config == nil || config.ClusterID == "" {
return nil, fmt.Errorf("CA has not finished initializing")
}
indexedRoots := &structs.IndexedCARoots{}
// Build TrustDomain based on the ClusterID stored.
signingID := connect.SpiffeIDSigningForCluster(config.ClusterID)
if signingID == nil {
// If CA is bootstrapped at all then this should never happen but be
// defensive.
return nil, fmt.Errorf("no cluster trust domain setup")
}
indexedRoots.TrustDomain = signingID.Host()
indexedRoots.Index, indexedRoots.Roots = index, roots
if indexedRoots.Roots == nil {
indexedRoots.Roots = make(structs.CARoots, 0)
}
// The response should not contain all fields as there are sensitive
// data such as key material stored within the struct. So here we
// pull out some of the fields and copy them into
for i, r := range indexedRoots.Roots {
var intermediates []string
if r.IntermediateCerts != nil {
intermediates = make([]string, len(r.IntermediateCerts))
for i, intermediate := range r.IntermediateCerts {
intermediates[i] = intermediate
}
}
// IMPORTANT: r must NEVER be modified, since it is a pointer
// directly to the structure in the memdb store.
indexedRoots.Roots[i] = &structs.CARoot{
ID: r.ID,
Name: r.Name,
SerialNumber: r.SerialNumber,
SigningKeyID: r.SigningKeyID,
ExternalTrustDomain: r.ExternalTrustDomain,
NotBefore: r.NotBefore,
NotAfter: r.NotAfter,
RootCert: lib.EnsureTrailingNewline(r.RootCert),
IntermediateCerts: intermediates,
RaftIndex: r.RaftIndex,
Active: r.Active,
PrivateKeyType: r.PrivateKeyType,
PrivateKeyBits: r.PrivateKeyBits,
}
if r.Active {
indexedRoots.ActiveRootID = r.ID
}
}
return indexedRoots, nil
}