Skip to content

Commit

Permalink
feat: Add an --external-server flag to the `cofidectl trust-zone ad…
Browse files Browse the repository at this point in the history
…d` command (#94)
  • Loading branch information
nialdaly authored Dec 19, 2024
1 parent 4ae7e8e commit b03222b
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 2 deletions.
3 changes: 3 additions & 0 deletions cmd/cofidectl/cmd/trustzone/trustzone.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ type addOpts struct {
context string
profile string
jwtIssuer string
externalServer bool
}

func (c *TrustZoneCommand) GetAddCommand() *cobra.Command {
Expand Down Expand Up @@ -156,6 +157,7 @@ func (c *TrustZoneCommand) GetAddCommand() *cobra.Command {
Profile: &opts.profile,
JwtIssuer: &opts.jwtIssuer,
BundleEndpointProfile: &bundleEndpointProfile,
ExternalServer: &opts.externalServer,
}

_, err = ds.AddTrustZone(newTrustZone)
Expand All @@ -173,6 +175,7 @@ func (c *TrustZoneCommand) GetAddCommand() *cobra.Command {
f.StringVar(&opts.context, "kubernetes-context", "", "Kubernetes context to use for this trust zone")
f.StringVar(&opts.profile, "profile", "kubernetes", "Cofide profile used in the installation (e.g. kubernetes, istio)")
f.StringVar(&opts.jwtIssuer, "jwt-issuer", "", "JWT issuer to use for this trust zone")
f.BoolVar(&opts.externalServer, "external-server", false, "If the SPIRE server runs externally")

cobra.CheckErr(cmd.MarkFlagRequired("trust-domain"))
cobra.CheckErr(cmd.MarkFlagRequired("kubernetes-cluster"))
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ toolchain go1.23.4
require (
buf.build/go/protoyaml v0.3.0
cuelang.org/go v0.10.1
github.com/cofide/cofide-api-sdk v0.4.1-0.20241213113045-864bfb581c91
github.com/cofide/cofide-api-sdk v0.4.1-0.20241218164200-fd9d4ce5088c
github.com/fatih/color v1.18.0
github.com/gofrs/flock v0.12.1
github.com/google/go-cmp v0.6.0
Expand All @@ -25,7 +25,7 @@ require (

require (
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20241127180247-a33202765966.1 // indirect
cel.dev/expr v0.18.0 // indirect
cel.dev/expr v0.18.0 // indirect
dario.cat/mergo v1.0.1 // indirect
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEa
github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc=
github.com/cofide/cofide-api-sdk v0.4.1-0.20241213113045-864bfb581c91 h1:We5sn+o74dce2gkO63ola8RFSD92jsud3pAIwVbzAq8=
github.com/cofide/cofide-api-sdk v0.4.1-0.20241213113045-864bfb581c91/go.mod h1:u2iATR4IbZm9ruIBN734UjVuO3XQKPAFViIY3Xr6kTA=
github.com/cofide/cofide-api-sdk v0.4.1-0.20241218164200-fd9d4ce5088c h1:nEdnzITNrjaBjP6VRCEsCyFF5nUI5M0nBDB98JZrZEI=
github.com/cofide/cofide-api-sdk v0.4.1-0.20241218164200-fd9d4ce5088c/go.mod h1:uChrsD6JvNDSCsAxXil3gGqTHxee0VJ1MbCT7xFZg6g=
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=
Expand Down
1 change: 1 addition & 0 deletions internal/pkg/config/schema.cue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
jwt_issuer?: string
extra_helm_values?: #HelmValues
bundle_endpoint_profile?: #BundleEndpointProfile
external_server?: bool
}

#TrustProvider: {
Expand Down
2 changes: 2 additions & 0 deletions internal/pkg/config/testdata/config/full.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ trust_zones:
logLevel: INFO
bundle_endpoint_profile: BUNDLE_ENDPOINT_PROFILE_HTTPS_SPIFFE
profile: kubernetes
external_server: false
- name: tz2
trust_domain: td2
kubernetes_cluster: local2
Expand All @@ -42,6 +43,7 @@ trust_zones:
jwt_issuer: https://tz2.example.com
bundle_endpoint_profile: BUNDLE_ENDPOINT_PROFILE_HTTPS_WEB
profile: kubernetes
external_server: false
attestation_policies:
- name: ap1
kubernetes:
Expand Down
21 changes: 21 additions & 0 deletions internal/pkg/test/fixtures/fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,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(),
ExternalServer: BoolPtr(false),
},
"tz2": {
Name: "tz2",
Expand All @@ -88,6 +89,7 @@ var trustZoneFixtures map[string]*trust_zone_proto.TrustZone = map[string]*trust
},
JwtIssuer: StringPtr("https://tz2.example.com"),
BundleEndpointProfile: trust_zone_proto.BundleEndpointProfile_BUNDLE_ENDPOINT_PROFILE_HTTPS_WEB.Enum(),
ExternalServer: BoolPtr(false),
},
// tz3 has no federations or bound attestation policies.
"tz3": {
Expand Down Expand Up @@ -118,6 +120,21 @@ var trustZoneFixtures map[string]*trust_zone_proto.TrustZone = map[string]*trust
Federations: []*federation_proto.Federation{},
AttestationPolicies: []*ap_binding_proto.APBinding{},
},
// tz5 has no federations or bound attestation policies and has an external SPIRE server.
"tz5": {
Name: "tz5",
TrustDomain: "td5",
KubernetesCluster: StringPtr("local5"),
KubernetesContext: StringPtr("kind-local5"),
TrustProvider: &trust_provider_proto.TrustProvider{
Kind: StringPtr("kubernetes"),
},
Profile: StringPtr("kubernetes"),
BundleEndpointUrl: StringPtr("127.0.0.5"),
Federations: []*federation_proto.Federation{},
AttestationPolicies: []*ap_binding_proto.APBinding{},
ExternalServer: BoolPtr(true),
},
}

var attestationPolicyFixtures map[string]*attestation_policy_proto.AttestationPolicy = map[string]*attestation_policy_proto.AttestationPolicy{
Expand Down Expand Up @@ -275,3 +292,7 @@ func Plugins(name string) *pluginspb.Plugins {
func StringPtr(s string) *string {
return &s
}

func BoolPtr(b bool) *bool {
return &b
}
7 changes: 7 additions & 0 deletions pkg/plugin/provision/spirehelm/spirehelm.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,17 @@ func (h *SpireHelm) InstallSPIREStack(ctx context.Context, ds datasource.DataSou
func (h *SpireHelm) WatchAndConfigure(ctx context.Context, ds datasource.DataSource, trustZones []*trust_zone_proto.TrustZone, kubeCfgFile string, statusCh chan<- *provisionpb.Status) error {
// Wait for SPIRE servers to be available and update status before applying federation(s)
for _, trustZone := range trustZones {
if trustZone.GetExternalServer() {
sb := provision.NewStatusBuilder(trustZone.Name, trustZone.GetKubernetesCluster())
statusCh <- sb.Done("Ready", "Skipped waiting for external SPIRE server pod and service")
continue
}

if err := h.GetBundleAndEndpoint(ctx, statusCh, ds, trustZone, kubeCfgFile); err != nil {
return err
}
}

return nil
}

Expand Down
30 changes: 30 additions & 0 deletions pkg/plugin/provision/spirehelm/spirehelm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,36 @@ func TestSpireHelm_Deploy(t *testing.T) {
assert.EqualExportedValues(t, want, statuses)
}

func TestSpireHelm_Deploy_ExternalServer(t *testing.T) {
providerFactory := newFakeHelmSPIREProviderFactory()
spireHelm := NewSpireHelm(providerFactory)

config := &config.Config{
TrustZones: []*trust_zone_proto.TrustZone{
fixtures.TrustZone("tz5"),
},
AttestationPolicies: []*attestation_policy_proto.AttestationPolicy{},
Plugins: fixtures.Plugins("plugins1"),
}

ds := newFakeDataSource(t, config)

statusCh, err := spireHelm.Deploy(context.Background(), ds, "fake-kube.cfg")
require.NoError(t, err, err)

statuses := collectStatuses(statusCh)
want := []*provisionpb.Status{
provision.StatusOk("Preparing", "Adding SPIRE Helm repo"),
provision.StatusDone("Prepared", "Added SPIRE Helm repo"),
provision.StatusOk("Installing", "Installing SPIRE CRDs for local5 in tz5"),
provision.StatusOk("Installing", "Installing SPIRE chart for local5 in tz5"),
provision.StatusDone("Installed", "Installation completed for local5 in tz5"),
provision.StatusDone("Ready", "Skipped waiting for external SPIRE server pod and service for local5 in tz5"),
provision.StatusDone("Ready", "Skipped waiting for external SPIRE server pod and service for local5 in tz5"),
}
assert.EqualExportedValues(t, want, statuses)
}

func TestSpireHelm_TearDown(t *testing.T) {
providerFactory := newFakeHelmSPIREProviderFactory()
spireHelm := NewSpireHelm(providerFactory)
Expand Down
13 changes: 13 additions & 0 deletions pkg/provider/helm/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type spireServerValues struct {
caKeyType string
caTTL string
controllerManagerEnabled bool
enabled bool
fullnameOverride string
logLevel string
serverConfig trustprovider.TrustProviderServerConfig
Expand Down Expand Up @@ -101,10 +102,13 @@ func (g *HelmValuesGenerator) GenerateValues() (map[string]any, error) {
return nil, err
}

spireServerEnabled := !g.trustZone.GetExternalServer()

ssv := spireServerValues{
caKeyType: "rsa-2048",
caTTL: "12h",
controllerManagerEnabled: true,
enabled: spireServerEnabled,
fullnameOverride: "spire-server",
logLevel: "DEBUG",
serverConfig: tp.ServerConfig,
Expand Down Expand Up @@ -330,6 +334,14 @@ func (s *spireAgentValues) generateValues() (map[string]any, error) {

// generateValues generates the spire-server Helm values map.
func (s *spireServerValues) generateValues() (map[string]any, error) {
if !s.enabled {
return map[string]any{
"spire-server": map[string]any{
"enabled": s.enabled,
},
}, nil
}

if s.caKeyType == "" {
return nil, fmt.Errorf("caKeyType value is empty")
}
Expand Down Expand Up @@ -364,6 +376,7 @@ func (s *spireServerValues) generateValues() (map[string]any, error) {

return map[string]any{
"spire-server": map[string]any{
"enabled": s.enabled,
"caKeyType": s.caKeyType,
"caTTL": s.caTTL,
"controllerManager": map[string]any{
Expand Down
22 changes: 22 additions & 0 deletions pkg/provider/helm/values_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ func TestHelmValuesGenerator_GenerateValues_success(t *testing.T) {
},
},
},
"enabled": true,
"fullnameOverride": "spire-server",
"logLevel": "DEBUG",
"nodeAttestor": Values{
Expand Down Expand Up @@ -209,6 +210,7 @@ func TestHelmValuesGenerator_GenerateValues_success(t *testing.T) {
},
},
},
"enabled": true,
"federation": Values{
"enabled": true,
},
Expand Down Expand Up @@ -298,6 +300,7 @@ func TestHelmValuesGenerator_GenerateValues_success(t *testing.T) {
},
},
},
"enabled": true,
"fullnameOverride": "spire-server",
"logLevel": "DEBUG",
"nodeAttestor": Values{
Expand Down Expand Up @@ -444,6 +447,7 @@ func TestHelmValuesGenerator_GenerateValues_AdditionalValues(t *testing.T) {
},
},
},
"enabled": true,
"fullnameOverride": "spire-server",
"logLevel": "DEBUG",
"nodeAttestor": Values{
Expand Down Expand Up @@ -840,6 +844,7 @@ func TestMergeMaps(t *testing.T) {
},
},
},
"enabled": true,
},
},
want: map[string]any{
Expand All @@ -864,6 +869,7 @@ func TestMergeMaps(t *testing.T) {
},
},
},
"enabled": true,
},
},
},
Expand Down Expand Up @@ -1286,6 +1292,7 @@ func TestSpireServerValues_GenerateValues(t *testing.T) {
caKeyType: "rsa-2048",
caTTL: "12h",
controllerManagerEnabled: true,
enabled: true,
fullnameOverride: "spire-server",
logLevel: "DEBUG",
serverConfig: trustprovider.TrustProviderServerConfig{
Expand All @@ -1308,6 +1315,7 @@ func TestSpireServerValues_GenerateValues(t *testing.T) {
"controllerManager": map[string]any{
"enabled": true,
},
"enabled": true,
"fullnameOverride": "spire-server",
"logLevel": "DEBUG",
"nodeAttestor": Values{
Expand All @@ -1330,12 +1338,25 @@ func TestSpireServerValues_GenerateValues(t *testing.T) {
},
wantErr: false,
},
{
name: "valid SPIRE server values, enabled set to false",
input: spireServerValues{
enabled: false,
},
want: map[string]any{
"spire-server": map[string]any{
"enabled": false,
},
},
wantErr: false,
},
{
name: "invalid SPIRE server values, empty serviceType value",
input: spireServerValues{
caKeyType: "rsa-2048",
caTTL: "12h",
controllerManagerEnabled: true,
enabled: true,
fullnameOverride: "spire-server",
logLevel: "DEBUG",
serverConfig: trustprovider.TrustProviderServerConfig{
Expand All @@ -1361,6 +1382,7 @@ func TestSpireServerValues_GenerateValues(t *testing.T) {
caKeyType: "rsa-2048",
caTTL: "12h",
controllerManagerEnabled: true,
enabled: true,
fullnameOverride: "spire-server",
logLevel: "DEBUG",
serverConfig: trustprovider.TrustProviderServerConfig{
Expand Down

0 comments on commit b03222b

Please sign in to comment.