From 622491a338b4a8d5486f790a1989721c60cd83fd Mon Sep 17 00:00:00 2001 From: Mark Goddard Date: Mon, 9 Dec 2024 10:11:45 +0000 Subject: [PATCH] Add support for bundle endpoint profile in trust zones This is an enum in the TrustZone message, and the https_web and https_spiffe profiles are currently supported. The default continues to be https_spiffe, but plugins may choose to change this. Fixes: #71 --- cmd/cofidectl/cmd/trustzone/trustzone.go | 16 ++++--- go.mod | 2 +- go.sum | 4 +- internal/pkg/config/schema.cue | 3 ++ internal/pkg/config/testdata/config/full.yaml | 2 + internal/pkg/federation/federation.go | 38 ++++++++++----- internal/pkg/test/fixtures/fixtures.go | 11 +++-- pkg/provider/helm/values.go | 5 +- pkg/provider/helm/values_test.go | 46 +++++++++++++++++-- 9 files changed, 98 insertions(+), 29 deletions(-) diff --git a/cmd/cofidectl/cmd/trustzone/trustzone.go b/cmd/cofidectl/cmd/trustzone/trustzone.go index 41a4dbf..90fb2c1 100644 --- a/cmd/cofidectl/cmd/trustzone/trustzone.go +++ b/cmd/cofidectl/cmd/trustzone/trustzone.go @@ -11,8 +11,8 @@ import ( "slices" "strconv" - cmdcontext "github.com/cofide/cofidectl/pkg/cmd/context" "github.com/cofide/cofidectl/cmd/cofidectl/cmd/trustzone/helm" + cmdcontext "github.com/cofide/cofidectl/pkg/cmd/context" "github.com/manifoldco/promptui" trust_provider_proto "github.com/cofide/cofide-api-sdk/gen/go/proto/trust_provider/v1alpha1" @@ -140,13 +140,15 @@ func (c *TrustZoneCommand) GetAddCommand() *cobra.Command { return err } + bundleEndpointProfile := trust_zone_proto.BundleEndpointProfile_BUNDLE_ENDPOINT_PROFILE_HTTPS_SPIFFE newTrustZone := &trust_zone_proto.TrustZone{ - Name: opts.name, - TrustDomain: opts.trustDomain, - KubernetesCluster: &opts.kubernetesCluster, - KubernetesContext: &opts.context, - TrustProvider: &trust_provider_proto.TrustProvider{Kind: &opts.profile}, - JwtIssuer: &opts.jwtIssuer, + Name: opts.name, + TrustDomain: opts.trustDomain, + KubernetesCluster: &opts.kubernetesCluster, + KubernetesContext: &opts.context, + TrustProvider: &trust_provider_proto.TrustProvider{Kind: &opts.profile}, + JwtIssuer: &opts.jwtIssuer, + BundleEndpointProfile: &bundleEndpointProfile, } _, err = ds.AddTrustZone(newTrustZone) diff --git a/go.mod b/go.mod index 82cb8ce..8b48707 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.22.7 require ( buf.build/go/protoyaml v0.2.0 cuelang.org/go v0.10.1 - github.com/cofide/cofide-api-sdk v0.3.1-0.20241206100419-25af9d3bc0c5 + github.com/cofide/cofide-api-sdk v0.3.1-0.20241209124727-c60451a4ba77 github.com/fatih/color v1.18.0 github.com/gofrs/flock v0.12.1 github.com/google/go-cmp v0.6.0 diff --git a/go.sum b/go.sum index 4fc06da..e87ce2a 100644 --- a/go.sum +++ b/go.sum @@ -84,8 +84,8 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= -github.com/cofide/cofide-api-sdk v0.3.1-0.20241206100419-25af9d3bc0c5 h1:o0xy1hnXWVEoHyqrLm+sU5lXyw/Rcm3A+1w884v8vqI= -github.com/cofide/cofide-api-sdk v0.3.1-0.20241206100419-25af9d3bc0c5/go.mod h1:yKMfhL3qCIVJcKvgZsPZC1o60/8co6/0NsCaJtrUoFY= +github.com/cofide/cofide-api-sdk v0.3.1-0.20241209124727-c60451a4ba77 h1:Uq2GS7GLwqjGWnnEEi/dfoc0+D9/yhmjEwNqLd7e8J0= +github.com/cofide/cofide-api-sdk v0.3.1-0.20241209124727-c60451a4ba77/go.mod h1:yKMfhL3qCIVJcKvgZsPZC1o60/8co6/0NsCaJtrUoFY= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/containerd v1.7.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZGBNYOOwQ= diff --git a/internal/pkg/config/schema.cue b/internal/pkg/config/schema.cue index 6edddf6..f58a86c 100644 --- a/internal/pkg/config/schema.cue +++ b/internal/pkg/config/schema.cue @@ -12,6 +12,7 @@ attestation_policies: [...#APBinding] jwt_issuer?: string extra_helm_values?: #HelmValues + bundle_endpoint_profile?: #BundleEndpointProfile } #TrustProvider: { @@ -58,6 +59,8 @@ [string]: _ } +#BundleEndpointProfile: string & =~"BUNDLE_ENDPOINT_PROFILE_.*" + #PluginConfig: { [string]: _ } diff --git a/internal/pkg/config/testdata/config/full.yaml b/internal/pkg/config/testdata/config/full.yaml index 39ae113..baee7ad 100644 --- a/internal/pkg/config/testdata/config/full.yaml +++ b/internal/pkg/config/testdata/config/full.yaml @@ -23,6 +23,7 @@ trust_zones: create: true spire-server: logLevel: INFO + bundle_endpoint_profile: BUNDLE_ENDPOINT_PROFILE_HTTPS_SPIFFE - name: tz2 trust_domain: td2 kubernetes_cluster: local2 @@ -39,6 +40,7 @@ trust_zones: federates_with: - tz1 jwt_issuer: https://tz2.example.com + bundle_endpoint_profile: BUNDLE_ENDPOINT_PROFILE_HTTPS_WEB attestation_policies: - name: ap1 kubernetes: diff --git a/internal/pkg/federation/federation.go b/internal/pkg/federation/federation.go index bb1fe43..e1e05a7 100644 --- a/internal/pkg/federation/federation.go +++ b/internal/pkg/federation/federation.go @@ -9,6 +9,11 @@ import ( trust_zone_proto "github.com/cofide/cofide-api-sdk/gen/go/proto/trust_zone/v1alpha1" ) +const ( + bundleEndpointProfileHTTPSWeb = "https_web" + bundleEndpointProfileHTTPSSPIFFE = "https_spiffe" +) + type Federation struct { destTrustZone *trust_zone_proto.TrustZone } @@ -19,16 +24,27 @@ func NewFederation(trustZone *trust_zone_proto.TrustZone) *Federation { } } -func (fed *Federation) GetHelmConfig() map[string]interface{} { - clusterFederatedTrustDomain := map[string]interface{}{ - "bundleEndpointURL": fed.destTrustZone.GetBundleEndpointUrl(), - "bundleEndpointProfile": map[string]interface{}{ - "type": "https_spiffe", - "endpointSPIFFEID": fmt.Sprintf("spiffe://%s/spire/server", fed.destTrustZone.TrustDomain), - }, - "trustDomain": fed.destTrustZone.TrustDomain, - "trustDomainBundle": fed.destTrustZone.GetBundle(), +func (fed *Federation) GetHelmConfig() (map[string]interface{}, error) { + switch fed.destTrustZone.GetBundleEndpointProfile() { + case trust_zone_proto.BundleEndpointProfile_BUNDLE_ENDPOINT_PROFILE_HTTPS_SPIFFE: + return map[string]interface{}{ + "bundleEndpointURL": fed.destTrustZone.GetBundleEndpointUrl(), + "bundleEndpointProfile": map[string]interface{}{ + "type": bundleEndpointProfileHTTPSSPIFFE, + "endpointSPIFFEID": fmt.Sprintf("spiffe://%s/spire/server", fed.destTrustZone.TrustDomain), + }, + "trustDomain": fed.destTrustZone.TrustDomain, + "trustDomainBundle": fed.destTrustZone.GetBundle(), + }, nil + case trust_zone_proto.BundleEndpointProfile_BUNDLE_ENDPOINT_PROFILE_HTTPS_WEB: + return map[string]interface{}{ + "bundleEndpointURL": fed.destTrustZone.GetBundleEndpointUrl(), + "bundleEndpointProfile": map[string]interface{}{ + "type": bundleEndpointProfileHTTPSWeb, + }, + "trustDomain": fed.destTrustZone.TrustDomain, + }, nil + default: + return nil, fmt.Errorf("unexpected bundle endpoint profile %d", fed.destTrustZone.GetBundleEndpointProfile()) } - - return clusterFederatedTrustDomain } diff --git a/internal/pkg/test/fixtures/fixtures.go b/internal/pkg/test/fixtures/fixtures.go index c88f007..2d44aee 100644 --- a/internal/pkg/test/fixtures/fixtures.go +++ b/internal/pkg/test/fixtures/fixtures.go @@ -59,6 +59,7 @@ var trustZoneFixtures map[string]*trust_zone_proto.TrustZone = map[string]*trust } return value }(), + BundleEndpointProfile: trust_zone_proto.BundleEndpointProfile_BUNDLE_ENDPOINT_PROFILE_HTTPS_SPIFFE.Enum(), }, "tz2": { Name: "tz2", @@ -82,7 +83,8 @@ var trustZoneFixtures map[string]*trust_zone_proto.TrustZone = map[string]*trust FederatesWith: []string{"tz1"}, }, }, - JwtIssuer: StringPtr("https://tz2.example.com"), + JwtIssuer: StringPtr("https://tz2.example.com"), + BundleEndpointProfile: trust_zone_proto.BundleEndpointProfile_BUNDLE_ENDPOINT_PROFILE_HTTPS_WEB.Enum(), }, // tz3 has no federations or bound attestation policies. "tz3": { @@ -93,9 +95,10 @@ var trustZoneFixtures map[string]*trust_zone_proto.TrustZone = map[string]*trust TrustProvider: &trust_provider_proto.TrustProvider{ Kind: StringPtr("kubernetes"), }, - BundleEndpointUrl: StringPtr("127.0.0.3"), - Federations: []*federation_proto.Federation{}, - AttestationPolicies: []*ap_binding_proto.APBinding{}, + BundleEndpointUrl: StringPtr("127.0.0.3"), + Federations: []*federation_proto.Federation{}, + AttestationPolicies: []*ap_binding_proto.APBinding{}, + BundleEndpointProfile: trust_zone_proto.BundleEndpointProfile_BUNDLE_ENDPOINT_PROFILE_HTTPS_SPIFFE.Enum(), }, } diff --git a/pkg/provider/helm/values.go b/pkg/provider/helm/values.go index 3e9a624..158b546 100644 --- a/pkg/provider/helm/values.go +++ b/pkg/provider/helm/values.go @@ -183,7 +183,10 @@ func (g *HelmValuesGenerator) GenerateValues() (map[string]any, error) { return nil, fmt.Errorf("failed to get clusterFederatedTrustDomains map from identities: %w", err) } - cftd[fed.To] = federation.NewFederation(tz).GetHelmConfig() + cftd[fed.To], err = federation.NewFederation(tz).GetHelmConfig() + if err != nil { + return nil, err + } } } } diff --git a/pkg/provider/helm/values_test.go b/pkg/provider/helm/values_test.go index fdc2c52..45d26f4 100644 --- a/pkg/provider/helm/values_test.go +++ b/pkg/provider/helm/values_test.go @@ -173,12 +173,10 @@ func TestHelmValuesGenerator_GenerateValues_success(t *testing.T) { "clusterFederatedTrustDomains": Values{ "tz2": Values{ "bundleEndpointProfile": Values{ - "endpointSPIFFEID": "spiffe://td2/spire/server", - "type": "https_spiffe", + "type": "https_web", }, "bundleEndpointURL": "127.0.0.2", "trustDomain": "td2", - "trustDomainBundle": "", }, }, "clusterSPIFFEIDs": Values{ @@ -440,6 +438,48 @@ func TestHelmValuesGenerator_GenerateValues_failure(t *testing.T) { } } +func TestHelmValuesGenerator_GenerateValues_federationFailure(t *testing.T) { + tests := []struct { + name string + destTrustZone *trust_zone_proto.TrustZone + wantErrString string + }{ + { + name: "nil bundle endpoint profile", + destTrustZone: func() *trust_zone_proto.TrustZone { + tz := fixtures.TrustZone("tz2") + tz.BundleEndpointProfile = nil + return tz + }(), + wantErrString: "unexpected bundle endpoint profile 0", + }, + { + name: "unspecified bundle endpoint profile", + destTrustZone: func() *trust_zone_proto.TrustZone { + tz := fixtures.TrustZone("tz2") + tz.BundleEndpointProfile = trust_zone_proto.BundleEndpointProfile_BUNDLE_ENDPOINT_PROFILE_UNSPECIFIED.Enum() + return tz + }(), + wantErrString: "unexpected bundle endpoint profile 0", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg := defaultConfig() + cfg.TrustZones[1] = tt.destTrustZone + source := newFakeDataSource(t, cfg) + g := &HelmValuesGenerator{ + source: source, + trustZone: cfg.TrustZones[0], + values: nil, + } + _, err := g.GenerateValues() + require.Error(t, err) + assert.ErrorContains(t, err, tt.wantErrString) + }) + } +} + func TestGetOrCreateNestedMap(t *testing.T) { tests := []struct { name string