config: add separate option for handling attestation parameters (#1623)

* Add attestation options to config

* Add join-config migration path for clusters with old measurement format

* Always create MAA provider for Azure SNP clusters

* Remove confidential VM option from provider in favor of attestation options

* cli: add config migrate command to handle config migration (#1678)

---------

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
Daniel Weiße 2023-05-03 11:11:53 +02:00 committed by GitHub
parent 6027b066e5
commit d7a2ddd939
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
74 changed files with 1339 additions and 1282 deletions

View file

@ -10,56 +10,27 @@ import (
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"errors"
"fmt"
"github.com/edgelesssys/constellation/v2/internal/atls"
"github.com/edgelesssys/constellation/v2/internal/attestation/choose"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/spf13/cobra"
)
// Validator validates Platform Configuration Registers (PCRs).
type Validator struct {
attestationVariant variant.Variant
pcrs measurements.M
idKeyConfig config.SNPFirmwareSignerConfig
validator atls.Validator
log debugLog
}
// NewValidator creates a new Validator.
func NewValidator(conf *config.Config, maaURL string, log debugLog) (*Validator, error) {
v := Validator{log: log}
attestVariant, err := variant.FromString(conf.AttestationVariant)
if err != nil {
return nil, fmt.Errorf("parsing attestation variant: %w", err)
}
v.attestationVariant = attestVariant // valid variant
if err := v.setPCRs(conf); err != nil {
return nil, err
}
if v.attestationVariant.Equal(variant.AzureSEVSNP{}) {
v.idKeyConfig = config.SNPFirmwareSignerConfig{
AcceptedKeyDigests: conf.Provider.Azure.IDKeyDigest,
EnforcementPolicy: conf.IDKeyDigestPolicy(),
MAAURL: maaURL,
}
}
return &v, nil
func NewValidator(cmd *cobra.Command, config config.AttestationCfg, log debugLog) (atls.Validator, error) {
return choose.Validator(config, warnLogger{cmd: cmd, log: log})
}
// UpdateInitPCRs sets the owner and cluster PCR values.
func (v *Validator) UpdateInitPCRs(ownerID, clusterID string) error {
if err := v.updatePCR(uint32(measurements.PCRIndexOwnerID), ownerID); err != nil {
func UpdateInitPCRs(config config.AttestationCfg, ownerID, clusterID string) error {
m := config.GetMeasurements()
if err := updatePCR(m, uint32(measurements.PCRIndexOwnerID), ownerID); err != nil {
return err
}
return v.updatePCR(uint32(measurements.PCRIndexClusterID), clusterID)
return updatePCR(m, uint32(measurements.PCRIndexClusterID), clusterID)
}
// updatePCR adds a new entry to the measurements of v, or removes the key if the input is an empty string.
@ -67,9 +38,9 @@ func (v *Validator) UpdateInitPCRs(ownerID, clusterID string) error {
// When adding, the input is first decoded from hex or base64.
// We then calculate the expected PCR by hashing the input using SHA256,
// appending expected PCR for initialization, and then hashing once more.
func (v *Validator) updatePCR(pcrIndex uint32, encoded string) error {
func updatePCR(m measurements.M, pcrIndex uint32, encoded string) error {
if encoded == "" {
delete(v.pcrs, pcrIndex)
delete(m, pcrIndex)
return nil
}
@ -85,42 +56,15 @@ func (v *Validator) updatePCR(pcrIndex uint32, encoded string) error {
// new_pcr_value := hash(old_pcr_value || data_to_extend)
// Since we use the TPM2_PCR_Event call to extend the PCR, data_to_extend is the hash of our input
hashedInput := sha256.Sum256(decoded)
oldExpected := v.pcrs[pcrIndex].Expected
oldExpected := m[pcrIndex].Expected
expectedPcr := sha256.Sum256(append(oldExpected[:], hashedInput[:]...))
v.pcrs[pcrIndex] = measurements.Measurement{
m[pcrIndex] = measurements.Measurement{
Expected: expectedPcr,
ValidationOpt: v.pcrs[pcrIndex].ValidationOpt,
ValidationOpt: m[pcrIndex].ValidationOpt,
}
return nil
}
func (v *Validator) setPCRs(config *config.Config) error {
measurements := config.GetMeasurements()
if len(measurements) == 0 {
return errors.New("no measurements found in config")
}
v.pcrs = measurements
return nil
}
// V returns the validator as atls.Validator.
func (v *Validator) V(cmd *cobra.Command) atls.Validator {
v.updateValidator(cmd)
return v.validator
}
// PCRS returns the validator's PCR map.
func (v *Validator) PCRS() measurements.M {
return v.pcrs
}
func (v *Validator) updateValidator(cmd *cobra.Command) {
log := warnLogger{cmd: cmd, log: v.log}
// Use of a valid variant has been check in NewValidator so we may drop the error
v.validator, _ = choose.Validator(v.attestationVariant, v.pcrs, v.idKeyConfig, log)
}
// warnLogger implements logging of warnings for validators.
type warnLogger struct {
cmd *cobra.Command