diff --git a/README.md b/README.md index 056058e2..ca3db016 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,8 @@ The configuration file is an [HCL](https://github.com/hashicorp/hcl) formatted f | `svid_bundle_file_name` | File name to be used to store the X.509 SVID Bundle in PEM format. | `"svid_bundle.pem"` | | `jwt_svids` | An array with the audience and file name to store the JWT SVIDs. File is Base64-encoded string). | `[{jwt_audience="your-audience", jwt_svid_file_name="jwt_svid.token"}]` | | `jwt_bundle_file_name` | File name to be used to store JWT Bundle in JSON format. | `"jwt_bundle.json"` | + | `include_federated_domains` | Include trust domains from federated servers in the CA bundle. | `true` | + ### Configuration example ``` diff --git a/pkg/sidecar/config.go b/pkg/sidecar/config.go index 90457493..d50907f0 100644 --- a/pkg/sidecar/config.go +++ b/pkg/sidecar/config.go @@ -31,6 +31,7 @@ type Config struct { SvidBundleFileNameDeprecated string `hcl:"svidBundleFileName"` RenewSignal string `hcl:"renew_signal"` RenewSignalDeprecated string `hcl:"renewSignal"` + IncludeFederatedDomains bool `hcl:"include_federated_domains"` // JWT configuration JwtSvids []JwtConfig `hcl:"jwt_svids"` diff --git a/pkg/sidecar/sidecar.go b/pkg/sidecar/sidecar.go index ec1530f4..7b419598 100644 --- a/pkg/sidecar/sidecar.go +++ b/pkg/sidecar/sidecar.go @@ -218,10 +218,12 @@ func (s *Sidecar) dumpBundles(svidResponse *workloadapi.X509Context) error { svidBundleFile := path.Join(s.config.CertDir, s.config.SvidBundleFileName) certs := svid.Certificates + bundleSet, found := svidResponse.Bundles.Get(svid.ID.TrustDomain()) if !found { return fmt.Errorf("no bundles found for %s trust domain", svid.ID.TrustDomain().String()) } + bundles := bundleSet.X509Authorities() privateKey, err := x509.MarshalPKCS8PrivateKey(svid.PrivateKey) if err != nil { @@ -234,6 +236,17 @@ func (s *Sidecar) dumpBundles(svidResponse *workloadapi.X509Context) error { certs = []*x509.Certificate{certs[0]} } + // If using federated domains, add them to the CA bundle + if s.config.IncludeFederatedDomains { + bundleSets := svidResponse.Bundles.Bundles() + for _, bundle := range bundleSets { + // The bundle corresponding to svid.ID.TrustDomain is already stored + if bundle.TrustDomain().Name() != svid.ID.TrustDomain().Name() { + bundles = append(bundles, bundle.X509Authorities()...) + } + } + } + if err := writeCerts(svidFile, certs); err != nil { return err } diff --git a/pkg/sidecar/sidecar_test.go b/pkg/sidecar/sidecar_test.go index 3f4edf89..4dba7dc6 100644 --- a/pkg/sidecar/sidecar_test.go +++ b/pkg/sidecar/sidecar_test.go @@ -30,6 +30,10 @@ func TestSidecar_RunDaemon(t *testing.T) { domain1Inter := domain1CA.CreateCA() domain1Bundle := domain1CA.Roots() + // Used for testing federated trust domains + domain2CA := spiffetest.NewCA(t) + domain2Bundle := domain2CA.Roots() + // Svid with intermediate spiffeIDWithIntermediate, err := spiffeid.FromString("spiffe://example.test/workloadWithIntermediate") require.NoError(t, err) @@ -62,6 +66,12 @@ func TestSidecar_RunDaemon(t *testing.T) { }, } + bundleWithFederatedDomains := domain1CA.Roots() + bundleWithFederatedDomains = append(bundleWithFederatedDomains, domain2Bundle[0:]...) + // Used to create an additional bundle when testing federated trust domains + federatedSpiffeID, err := spiffeid.FromString("spiffe://foo.test/server") + require.NoError(t, err) + tmpdir := t.TempDir() log, _ := test.NewNullLogger() @@ -90,6 +100,7 @@ func TestSidecar_RunDaemon(t *testing.T) { bundle []*x509.Certificate renewSignal string intermediateInBundle bool + federatedDomains bool }{ { name: "svid with intermediate", @@ -147,6 +158,17 @@ func TestSidecar_RunDaemon(t *testing.T) { bundle: domain1Bundle, renewSignal: "SIGHUP", }, + { + name: "svid with federated trust domains", + response: &workloadapi.X509Context{ + Bundles: x509bundle.NewSet(x509bundle.FromX509Authorities(spiffeID.TrustDomain(), domain1CA.Roots()), x509bundle.FromX509Authorities(federatedSpiffeID.TrustDomain(), domain2CA.Roots())), + SVIDs: svid, + }, + certs: svidChain, + key: svidKey, + bundle: bundleWithFederatedDomains, + federatedDomains: true, + }, } svidFile := path.Join(tmpdir, config.SvidFileName) @@ -160,6 +182,7 @@ func TestSidecar_RunDaemon(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { sidecar.config.AddIntermediatesToBundle = testCase.intermediateInBundle sidecar.config.RenewSignal = testCase.renewSignal + sidecar.config.IncludeFederatedDomains = testCase.federatedDomains // Push response to start updating process // updateMockChan <- testCase.response.ToProto(t) w.OnX509ContextUpdate(testCase.response)