cli: remove helm management from join-config (#2251)

* Replace UpdateAttestationConfig with ApplyJoinConfig

* Dont set up join-config over Helm, it is now only managed by our CLI directly during init and upgrade

* Remove measurementSalt and attestationConfig parsing from helm, they were only needed for the JoinConfig

* Add migration step to remove join-config from Helm management

* Update attestation config trouble shooting tip

---------

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
Daniel Weiße 2023-08-23 08:14:39 +02:00 committed by GitHub
parent c42e81bf23
commit 053aa60e47
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 326 additions and 196 deletions

View file

@ -226,7 +226,6 @@ go_library(
"charts/edgeless/constellation-services/charts/join-service/Chart.yaml",
"charts/edgeless/constellation-services/charts/join-service/templates/clusterrole.yaml",
"charts/edgeless/constellation-services/charts/join-service/templates/clusterrolebinding.yaml",
"charts/edgeless/constellation-services/charts/join-service/templates/configmap.yaml",
"charts/edgeless/constellation-services/charts/join-service/templates/daemonset.yaml",
"charts/edgeless/constellation-services/charts/join-service/templates/service.yaml",
"charts/edgeless/constellation-services/charts/join-service/templates/serviceaccount.yaml",
@ -468,7 +467,6 @@ go_test(
deps = [
"//cli/internal/clusterid",
"//cli/internal/terraform",
"//internal/attestation/idkeydigest",
"//internal/attestation/measurements",
"//internal/cloud/azureshared",
"//internal/cloud/cloudprovider",

View file

@ -1,10 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: join-config
namespace: {{ .Release.Namespace }}
data:
{{/* mustToJson is required so the json-strings passed from go are of type string in the rendered yaml. */}}
attestationConfig: {{ .Values.attestationConfig | mustToJson }}
binaryData:
measurementSalt: {{ .Values.measurementSalt }}

View file

@ -3,33 +3,33 @@
"properties": {
"csp": {
"description": "CSP to which the chart is deployed.",
"enum": ["AWS", "Azure", "GCP", "OpenStack", "QEMU"]
},
"attestationConfig": {
"description": "JSON-string to describe the config to use for attestation validation.",
"type": "string",
"examples": ["{'measurements':{'1':{'expected':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA','warnOnly':true},'15':{'expected':'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=','warnOnly':true}}}"]
"enum": [
"AWS",
"Azure",
"GCP",
"OpenStack",
"QEMU"
]
},
"image": {
"description": "Container image to use for the spawned pods.",
"type": "string",
"examples": ["ghcr.io/edgelesssys/constellation/join-service:latest"]
},
"measurementSalt": {
"description": "Salt used to generate node measurements",
"type": "string",
"examples": ["AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"]
"examples": [
"ghcr.io/edgelesssys/constellation/join-service:latest"
]
},
"attestationVariant": {
"description": "Attestation variant to use for aTLS connections.",
"type": "string",
"examples": ["azure-sev-snp", "azure-trusted-launch", "gcp-sev-es"]
"examples": [
"azure-sev-snp",
"azure-trusted-launch",
"gcp-sev-es"
]
}
},
"required": [
"csp",
"attestationConfig",
"measurementSalt",
"image",
"attestationVariant"
],

View file

@ -1,5 +1,4 @@
csp: "gcp"
attestationVariant: ""
measurementSalt: ""
joinServicePort: 9090
joinServiceNodePort: 30090

View file

@ -134,10 +134,7 @@ func (i *ChartLoader) LoadReleases(
return nil, fmt.Errorf("loading constellation-services: %w", err)
}
if idFile.MeasurementSalt == nil {
return nil, errors.New("missing measurement salt in idFile")
}
svcVals, err := extraConstellationServicesValues(config, masterSecret, idFile.MeasurementSalt, idFile.UID, serviceAccURI, output)
svcVals, err := extraConstellationServicesValues(config, masterSecret, idFile.UID, serviceAccURI, output)
if err != nil {
return nil, fmt.Errorf("extending constellation-services values: %w", err)
}

View file

@ -7,7 +7,6 @@ SPDX-License-Identifier: AGPL-3.0-only
package helm
import (
"bytes"
"fmt"
"io/fs"
"os"
@ -25,7 +24,6 @@ import (
"github.com/edgelesssys/constellation/v2/cli/internal/clusterid"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/azureshared"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
@ -71,7 +69,7 @@ func TestLoadReleases(t *testing.T) {
helmReleases, err := chartLoader.LoadReleases(
config, true, WaitModeAtomic,
uri.MasterSecret{Key: []byte("secret"), Salt: []byte("masterSalt")},
fakeServiceAccURI(cloudprovider.GCP), clusterid.File{UID: "testuid", MeasurementSalt: []byte("measurementSalt")}, terraform.ApplyOutput{GCP: &terraform.GCPApplyOutput{}},
fakeServiceAccURI(cloudprovider.GCP), clusterid.File{UID: "testuid"}, terraform.ApplyOutput{GCP: &terraform.GCPApplyOutput{}},
)
require.NoError(err)
chart := helmReleases.ConstellationServices.Chart
@ -113,18 +111,7 @@ func TestConstellationServices(t *testing.T) {
Provider: config.ProviderConfig{Azure: &config.AzureConfig{
DeployCSIDriver: toPtr(true),
}},
Attestation: config.AttestationConfig{AzureSEVSNP: &config.AzureSEVSNP{
Measurements: measurements.M{1: measurements.WithAllBytes(0xAA, measurements.Enforce, measurements.PCRMeasurementLength)},
FirmwareSignerConfig: config.SNPFirmwareSignerConfig{
AcceptedKeyDigests: idkeydigest.List{bytes.Repeat([]byte{0xAA}, 32)},
EnforcementPolicy: idkeydigest.MAAFallback,
MAAURL: "https://192.0.2.1:8080/maa",
},
BootloaderVersion: config.AttestationVersion{Value: 1, WantLatest: true},
TEEVersion: config.AttestationVersion{Value: 2, WantLatest: true},
SNPVersion: config.AttestationVersion{Value: 3, WantLatest: true},
MicrocodeVersion: config.AttestationVersion{Value: 4, WantLatest: true},
}},
Attestation: config.AttestationConfig{AzureSEVSNP: &config.AzureSEVSNP{}},
},
enforceIDKeyDigest: true,
ccmImage: "ccmImageForAzure",
@ -135,27 +122,21 @@ func TestConstellationServices(t *testing.T) {
Provider: config.ProviderConfig{GCP: &config.GCPConfig{
DeployCSIDriver: toPtr(true),
}},
Attestation: config.AttestationConfig{GCPSEVES: &config.GCPSEVES{
Measurements: measurements.M{1: measurements.WithAllBytes(0xAA, measurements.Enforce, measurements.PCRMeasurementLength)},
}},
Attestation: config.AttestationConfig{GCPSEVES: &config.GCPSEVES{}},
},
ccmImage: "ccmImageForGCP",
},
"OpenStack": {
config: &config.Config{
Provider: config.ProviderConfig{OpenStack: &config.OpenStackConfig{}},
Attestation: config.AttestationConfig{QEMUVTPM: &config.QEMUVTPM{
Measurements: measurements.M{1: measurements.WithAllBytes(0xAA, measurements.Enforce, measurements.PCRMeasurementLength)},
}},
Provider: config.ProviderConfig{OpenStack: &config.OpenStackConfig{}},
Attestation: config.AttestationConfig{QEMUVTPM: &config.QEMUVTPM{}},
},
ccmImage: "ccmImageForOpenStack",
},
"QEMU": {
config: &config.Config{
Provider: config.ProviderConfig{QEMU: &config.QEMUConfig{}},
Attestation: config.AttestationConfig{QEMUVTPM: &config.QEMUVTPM{
Measurements: measurements.M{1: measurements.WithAllBytes(0xAA, measurements.Enforce, measurements.PCRMeasurementLength)},
}},
Provider: config.ProviderConfig{QEMU: &config.QEMUConfig{}},
Attestation: config.AttestationConfig{QEMUVTPM: &config.QEMUVTPM{}},
},
},
}
@ -186,7 +167,6 @@ func TestConstellationServices(t *testing.T) {
Key: []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
Salt: []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
},
[]byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
"uid", serviceAccURI, terraform.ApplyOutput{
Azure: &terraform.AzureApplyOutput{},
GCP: &terraform.GCPApplyOutput{},
@ -381,13 +361,6 @@ func buildTestdataMap(csp string, expectedData map[string]string, require *requi
// addInClusterValues adds values that are only known after the cluster is created.
func addInClusterValues(values map[string]any, csp cloudprovider.Provider) error {
joinVals, ok := values["join-service"].(map[string]any)
if !ok {
return errors.New("missing 'join-service' key")
}
joinVals["measurementSalt"] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
verificationVals, ok := values["verification-service"].(map[string]any)
if !ok {
return fmt.Errorf("missing 'verification-service' key %v", values)

View file

@ -54,17 +54,11 @@ func extraCiliumValues(provider cloudprovider.Provider, conformanceMode bool, ou
// extraConstellationServicesValues extends the given values map by some values depending on user input.
// Values set inside this function are only applied during init, not during upgrade.
func extraConstellationServicesValues(
cfg *config.Config, masterSecret uri.MasterSecret, measurementSalt []byte, uid, serviceAccURI string, output terraform.ApplyOutput,
cfg *config.Config, masterSecret uri.MasterSecret, uid, serviceAccURI string, output terraform.ApplyOutput,
) (map[string]any, error) {
attestationConfigJSON, err := json.Marshal(cfg.GetAttestationConfig())
if err != nil {
return nil, fmt.Errorf("marshalling measurements: %w", err)
}
extraVals := map[string]any{}
extraVals["join-service"] = map[string]any{
"measurementSalt": base64.StdEncoding.EncodeToString(measurementSalt),
"attestationVariant": cfg.GetAttestationConfig().GetVariant().String(),
"attestationConfig": string(attestationConfigJSON),
}
extraVals["verification-service"] = map[string]any{
"attestationVariant": cfg.GetAttestationConfig().GetVariant().String(),

View file

@ -1,9 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: join-config
namespace: testNamespace
data:
attestationConfig: "{\"measurements\":{\"1\":{\"expected\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"warnOnly\":false}}}"
binaryData:
measurementSalt: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

View file

@ -1,9 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: join-config
namespace: testNamespace
data:
attestationConfig: "{\"measurements\":{\"1\":{\"expected\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"warnOnly\":false}},\"bootloaderVersion\":1,\"teeVersion\":2,\"snpVersion\":3,\"microcodeVersion\":4,\"firmwareSignerConfig\":{\"acceptedKeyDigests\":[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"],\"enforcementPolicy\":\"MAAFallback\",\"maaURL\":\"https://192.0.2.1:8080/maa\"},\"amdRootKey\":\"-----BEGIN CERTIFICATE-----\\n-----END CERTIFICATE-----\\n\"}"
binaryData:
measurementSalt: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

View file

@ -1,9 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: join-config
namespace: testNamespace
data:
attestationConfig: "{\"measurements\":{\"1\":{\"expected\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"warnOnly\":false}}}"
binaryData:
measurementSalt: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

View file

@ -1,9 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: join-config
namespace: testNamespace
data:
attestationConfig: "{\"measurements\":{\"1\":{\"expected\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"warnOnly\":false}}}"
binaryData:
measurementSalt: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

View file

@ -1,9 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: join-config
namespace: testNamespace
data:
attestationConfig: "{\"measurements\":{\"1\":{\"expected\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"warnOnly\":false}}}"
binaryData:
measurementSalt: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA