api: for Azure attestationconfigapi use TCB values from SNP report instead of MAA token (#2429)

This commit is contained in:
Adrian Stobbe 2023-10-17 17:36:50 +02:00 committed by GitHub
parent 0c89f57ac5
commit 5819a11d25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 211 additions and 110 deletions

View File

@ -66,18 +66,14 @@ runs:
forwarderPID=$! forwarderPID=$!
sleep 5 sleep 5
verifyOut=$(constellation verify --cluster-id "${clusterID}" --force --node-endpoint localhost:9090) if [[ ${{ inputs.cloudProvider }} == "azure" ]]; then
echo "Extracting Azure TCB versions for API update"
kill $forwarderPID constellation verify --cluster-id "${clusterID}" --force --node-endpoint localhost:9090 -o json > "snp-report-${node}.json"
else
if [[ ${{ inputs.cloudProvider }} != "azure" ]]; then constellation verify --cluster-id "${clusterID}" --force --node-endpoint localhost:9090
continue
fi fi
echo "Extracting TCB versions for API update" kill $forwarderPID
startMAAToken="Microsoft Azure Attestation Token:"
endMAAToken="Verification OK"
sed -n "/${startMAAToken}/,/${endMAAToken}/ { /${startMAAToken}/d; /${endMAAToken}/d; p }" <<< "${verifyOut}" > "maa-claims-${node}.json"
done done
- name: Login to AWS - name: Login to AWS
@ -94,8 +90,8 @@ runs:
COSIGN_PASSWORD: ${{ inputs.cosignPassword }} COSIGN_PASSWORD: ${{ inputs.cosignPassword }}
COSIGN_PRIVATE_KEY: ${{ inputs.cosignPrivateKey }} COSIGN_PRIVATE_KEY: ${{ inputs.cosignPrivateKey }}
run: | run: |
for file in $(ls maa-claims-*.json); do for file in $(ls snp-report-*.json); do
path=$(realpath "${file}") path=$(realpath "${file}")
cat "${path}" cat "${path}"
bazel run //internal/api/attestationconfigapi/cli -- --maa-claims-path "${path}" bazel run //internal/api/attestationconfigapi/cli -- --snp-report-path "${path}"
done done

View File

@ -2480,8 +2480,9 @@ def go_dependencies():
build_file_generation = "on", build_file_generation = "on",
build_file_proto_mode = "disable_global", build_file_proto_mode = "disable_global",
importpath = "github.com/google/go-sev-guest", importpath = "github.com/google/go-sev-guest",
sum = "h1:XlvpFmmyMGvXmCIBTScYt7AX3ClvW8gfFN3SBCRVuKY=", replace = "github.com/google/go-sev-guest",
version = "v0.9.1", sum = "h1:6o4Z/vQqNUH+cEagfx1Ez5ElK70iZulEXZwmLnRo44I=",
version = "v0.0.0-20230928233922-2dcbba0a4b9d",
) )
go_repository( go_repository(
name = "com_github_google_go_tdx_guest", name = "com_github_google_go_tdx_guest",

View File

@ -712,8 +712,12 @@ func newCertificates(certTypeName string, cert []byte, log debugLog) (certs []ve
if err != nil { if err != nil {
return certs, fmt.Errorf("parsing VCEK certificate extensions: %w", err) return certs, fmt.Errorf("parsing VCEK certificate extensions: %w", err)
} }
certPEM := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: cert.Raw,
})
certs = append(certs, verify.Certificate{ certs = append(certs, verify.Certificate{
Certificate: cert, CertificatePEM: string(certPEM),
CertTypeName: certTypeName, CertTypeName: certTypeName,
StructVersion: vcekExts.StructVersion, StructVersion: vcekExts.StructVersion,
ProductName: vcekExts.ProductName, ProductName: vcekExts.ProductName,
@ -721,8 +725,12 @@ func newCertificates(certTypeName string, cert []byte, log debugLog) (certs []ve
HardwareID: vcekExts.HWID, HardwareID: vcekExts.HWID,
}) })
} else { } else {
certPEM := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: cert.Raw,
})
certs = append(certs, verify.Certificate{ certs = append(certs, verify.Certificate{
Certificate: cert, CertificatePEM: string(certPEM),
CertTypeName: certTypeName, CertTypeName: certTypeName,
}) })
} }
@ -783,7 +791,7 @@ func newSNPReport(reportBytes []byte) (res verify.SNPReport, err error) {
SignerInfo: verify.SignerInfo{ SignerInfo: verify.SignerInfo{
AuthorKey: signerInfo.AuthorKeyEn, AuthorKey: signerInfo.AuthorKeyEn,
MaskChipKey: signerInfo.MaskChipKey, MaskChipKey: signerInfo.MaskChipKey,
SigningKey: signerInfo.SigningKey, SigningKey: signerInfo.SigningKey.String(),
}, },
ReportData: report.ReportData, ReportData: report.ReportData,
Measurement: report.Measurement, Measurement: report.Measurement,

1
go.mod
View File

@ -33,6 +33,7 @@ replace (
replace ( replace (
github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/api => ./operators/constellation-node-operator/api github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/api => ./operators/constellation-node-operator/api
github.com/google/go-sev-guest => github.com/google/go-sev-guest v0.0.0-20230928233922-2dcbba0a4b9d
github.com/google/go-tpm => github.com/thomasten/go-tpm v0.0.0-20230629092004-f43f8e2a59eb github.com/google/go-tpm => github.com/thomasten/go-tpm v0.0.0-20230629092004-f43f8e2a59eb
github.com/google/go-tpm-tools => github.com/msanft/go-tpm-tools v0.0.0-20231009082622-266280269413 github.com/google/go-tpm-tools => github.com/msanft/go-tpm-tools v0.0.0-20231009082622-266280269413
github.com/martinjungblut/go-cryptsetup => github.com/daniel-weisse/go-cryptsetup v0.0.0-20230705150314-d8c07bd1723c github.com/martinjungblut/go-cryptsetup => github.com/daniel-weisse/go-cryptsetup v0.0.0-20230705150314-d8c07bd1723c

4
go.sum
View File

@ -574,8 +574,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.15.2 h1:MMkSh+tjSdnmJZO7ljvEqV1DjfekB6VUEAZgy3a+TQE= github.com/google/go-containerregistry v0.15.2 h1:MMkSh+tjSdnmJZO7ljvEqV1DjfekB6VUEAZgy3a+TQE=
github.com/google/go-containerregistry v0.15.2/go.mod h1:wWK+LnOv4jXMM23IT/F1wdYftGWGr47Is8CG+pmHK1Q= github.com/google/go-containerregistry v0.15.2/go.mod h1:wWK+LnOv4jXMM23IT/F1wdYftGWGr47Is8CG+pmHK1Q=
github.com/google/go-sev-guest v0.9.1 h1:XlvpFmmyMGvXmCIBTScYt7AX3ClvW8gfFN3SBCRVuKY= github.com/google/go-sev-guest v0.0.0-20230928233922-2dcbba0a4b9d h1:6o4Z/vQqNUH+cEagfx1Ez5ElK70iZulEXZwmLnRo44I=
github.com/google/go-sev-guest v0.9.1/go.mod h1:hc1R4R6f8+NcJwITs0L90fYWTsBpd1Ix+Gur15sqHDs= github.com/google/go-sev-guest v0.0.0-20230928233922-2dcbba0a4b9d/go.mod h1:hc1R4R6f8+NcJwITs0L90fYWTsBpd1Ix+Gur15sqHDs=
github.com/google/go-tdx-guest v0.2.2 h1:MgHcWLCEHVpqR0LXxtgJq2uG0oNNszV8+5XYtKs7+Yg= github.com/google/go-tdx-guest v0.2.2 h1:MgHcWLCEHVpqR0LXxtgJq2uG0oNNszV8+5XYtKs7+Yg=
github.com/google/go-tdx-guest v0.2.2/go.mod h1:a8EIh1l5x7jmIrrOuH//xWn6y4Sk4yupwmMcJE006RI= github.com/google/go-tdx-guest v0.2.2/go.mod h1:a8EIh1l5x7jmIrrOuH//xWn6y4Sk4yupwmMcJE006RI=
github.com/google/go-tspi v0.3.0 h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus= github.com/google/go-tspi v0.3.0 h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus=

View File

@ -19,11 +19,14 @@ go_library(
deps = [ deps = [
"//internal/api/attestationconfigapi", "//internal/api/attestationconfigapi",
"//internal/constants", "//internal/constants",
"//internal/file",
"//internal/logger", "//internal/logger",
"//internal/staticupload", "//internal/staticupload",
"//internal/verify",
"@com_github_aws_aws_sdk_go//aws", "@com_github_aws_aws_sdk_go//aws",
"@com_github_aws_aws_sdk_go_v2_service_s3//:s3", "@com_github_aws_aws_sdk_go_v2_service_s3//:s3",
"@com_github_aws_aws_sdk_go_v2_service_s3//types", "@com_github_aws_aws_sdk_go_v2_service_s3//types",
"@com_github_spf13_afero//:afero",
"@com_github_spf13_cobra//:cobra", "@com_github_spf13_cobra//:cobra",
"@org_uber_go_zap//:zap", "@org_uber_go_zap//:zap",
], ],
@ -31,9 +34,13 @@ go_library(
go_test( go_test(
name = "cli_test", name = "cli_test",
srcs = ["delete_test.go"], srcs = [
"delete_test.go",
"main_test.go",
],
embed = [":cli_lib"], embed = [":cli_lib"],
deps = [ deps = [
"//internal/verify",
"@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require", "@com_github_stretchr_testify//require",
], ],

View File

@ -73,12 +73,12 @@ func runDelete(cmd *cobra.Command, _ []string) (retErr error) {
if err != nil { if err != nil {
return fmt.Errorf("getting testing flag: %w", err) return fmt.Errorf("getting testing flag: %w", err)
} }
_, distribution := getEnvironment(testing) apiCfg := getAPIEnvironment(testing)
cfg := staticupload.Config{ cfg := staticupload.Config{
Bucket: bucket, Bucket: bucket,
Region: region, Region: region,
DistributionID: distribution, DistributionID: apiCfg.distribution,
} }
client, clientClose, err := attestationconfigapi.NewClient(cmd.Context(), cfg, client, clientClose, err := attestationconfigapi.NewClient(cmd.Context(), cfg,
[]byte(cosignPwd), []byte(privateKey), false, 1, log) []byte(cosignPwd), []byte(privateKey), false, 1, log)
@ -113,13 +113,13 @@ func runRecursiveDelete(cmd *cobra.Command, _ []string) (retErr error) {
if err != nil { if err != nil {
return fmt.Errorf("getting testing flag: %w", err) return fmt.Errorf("getting testing flag: %w", err)
} }
_, distribution := getEnvironment(testing) apiCfg := getAPIEnvironment(testing)
log := logger.New(logger.PlainLog, zap.DebugLevel).Named("attestationconfigapi") log := logger.New(logger.PlainLog, zap.DebugLevel).Named("attestationconfigapi")
client, closeFn, err := staticupload.New(cmd.Context(), staticupload.Config{ client, closeFn, err := staticupload.New(cmd.Context(), staticupload.Config{
Bucket: bucket, Bucket: bucket,
Region: region, Region: region,
DistributionID: distribution, DistributionID: apiCfg.distribution,
}, log) }, log)
if err != nil { if err != nil {
return fmt.Errorf("create static upload client: %w", err) return fmt.Errorf("create static upload client: %w", err)

View File

@ -31,53 +31,95 @@ registerExitHandler "rm -rf $tmpdir"
${configapi_cli} delete recursive --region "$region" --bucket "$bucket" ${configapi_cli} delete recursive --region "$region" --bucket "$bucket"
# the high version numbers ensure that it's newer than the current latest value # the high version numbers ensure that it's newer than the current latest value
readonly current_claim_path="$tmpdir/currentMaaClaim.json" readonly current_report_path="$tmpdir/currentSnpReport.json"
cat << EOF > "$current_claim_path" cat << EOF > "$current_report_path"
{ {
"x-ms-isolation-tee": { "snp_report": {
"x-ms-sevsnpvm-tee-svn": 1, "reported_tcb": {
"x-ms-sevsnpvm-snpfw-svn": 1, "bootloader": 1,
"x-ms-sevsnpvm-microcode-svn": 1, "tee": 1,
"x-ms-sevsnpvm-bootloader-svn": 1 "snp": 1,
"microcode": 1
},
"committed_tcb": {
"bootloader": 1,
"tee": 1,
"snp": 1,
"microcode": 1
},
"launch_tcb": {
"bootloader": 1,
"tee": 1,
"snp": 1,
"microcode": 1
}
} }
} }
EOF EOF
# upload a fake latest version for the fetcher # upload a fake latest version for the fetcher
${configapi_cli} --force --maa-claims-path "$current_claim_path" --upload-date "2000-01-01-01-01" --region "$region" --bucket "$bucket" ${configapi_cli} --force --snp-report-path "$current_report_path" --upload-date "2000-01-01-01-01" --region "$region" --bucket "$bucket"
# the high version numbers ensure that it's newer than the current latest value # the high version numbers ensure that it's newer than the current latest value
readonly claim_path="$tmpdir/maaClaim.json" readonly report_path="$tmpdir/snpReport.json"
cat << EOF > "$claim_path" cat << EOF > "$report_path"
{ {
"x-ms-isolation-tee": { "snp_report": {
"x-ms-sevsnpvm-tee-svn": 255, "reported_tcb": {
"x-ms-sevsnpvm-snpfw-svn": 255, "bootloader": 255,
"x-ms-sevsnpvm-microcode-svn": 255, "tee": 255,
"x-ms-sevsnpvm-bootloader-svn": 255 "snp": 255,
"microcode": 255
},
"committed_tcb": {
"bootloader": 255,
"tee": 255,
"snp": 255,
"microcode": 255
},
"launch_tcb": {
"bootloader": 255,
"tee": 255,
"snp": 255,
"microcode": 255
}
} }
} }
EOF EOF
# has an older version # has an older version
readonly older_claim_path="$tmpdir/maaClaimOld.json" readonly older_report_path="$tmpdir/snpReportOld.json"
cat << EOF > "$older_claim_path" cat << EOF > "$older_report_path"
{ {
"x-ms-isolation-tee": { "snp_report": {
"x-ms-sevsnpvm-tee-svn": 255, "reported_tcb": {
"x-ms-sevsnpvm-snpfw-svn": 255, "bootloader": 255,
"x-ms-sevsnpvm-microcode-svn": 254, "tee": 255,
"x-ms-sevsnpvm-bootloader-svn": 255 "snp": 255,
"microcode": 254
},
"committed_tcb": {
"bootloader": 255,
"tee": 255,
"snp": 255,
"microcode": 254
},
"launch_tcb": {
"bootloader": 255,
"tee": 255,
"snp": 255,
"microcode": 254
}
} }
} }
EOF EOF
# report 3 versions with different dates to fill the reporter cache # report 3 versions with different dates to fill the reporter cache
readonly date_oldest="2023-02-01-03-04" readonly date_oldest="2023-02-01-03-04"
${configapi_cli} --maa-claims-path "$older_claim_path" --upload-date "$date_oldest" --region "$region" --bucket "$bucket" --cache-window-size 3 ${configapi_cli} --snp-report-path "$older_report_path" --upload-date "$date_oldest" --region "$region" --bucket "$bucket" --cache-window-size 3
readonly date_older="2023-02-02-03-04" readonly date_older="2023-02-02-03-04"
${configapi_cli} --maa-claims-path "$older_claim_path" --upload-date "$date_older" --region "$region" --bucket "$bucket" --cache-window-size 3 ${configapi_cli} --snp-report-path "$older_report_path" --upload-date "$date_older" --region "$region" --bucket "$bucket" --cache-window-size 3
readonly date="2023-02-03-03-04" readonly date="2023-02-03-03-04"
${configapi_cli} --maa-claims-path "$claim_path" --upload-date "$date" --region "$region" --bucket "$bucket" --cache-window-size 3 ${configapi_cli} --snp-report-path "$report_path" --upload-date "$date" --region "$region" --bucket "$bucket" --cache-window-size 3
# expect that $date_oldest is served as latest version # expect that $date_oldest is served as latest version
baseurl="https://d33dzgxuwsgbpw.cloudfront.net/constellation/v1/attestation/azure-sev-snp" baseurl="https://d33dzgxuwsgbpw.cloudfront.net/constellation/v1/attestation/azure-sev-snp"

View File

@ -15,7 +15,6 @@ Any version update is then pushed to the API.
package main package main
import ( import (
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"os" "os"
@ -23,11 +22,13 @@ import (
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/staticupload" "github.com/edgelesssys/constellation/v2/internal/staticupload"
"go.uber.org/zap" "github.com/edgelesssys/constellation/v2/internal/verify"
"github.com/spf13/afero"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"go.uber.org/zap"
) )
const ( const (
@ -67,7 +68,7 @@ func newRootCmd() *cobra.Command {
PreRunE: envCheck, PreRunE: envCheck,
RunE: runCmd, RunE: runCmd,
} }
rootCmd.Flags().StringP("maa-claims-path", "t", "", "File path to a json file containing the MAA claims.") rootCmd.Flags().StringP("snp-report-path", "t", "", "File path to a file containing the Constellation verify output.")
rootCmd.Flags().StringP("upload-date", "d", "", "upload a version with this date as version name.") rootCmd.Flags().StringP("upload-date", "d", "", "upload a version with this date as version name.")
rootCmd.Flags().BoolP("force", "f", false, "Use force to manually push a new latest version."+ rootCmd.Flags().BoolP("force", "f", false, "Use force to manually push a new latest version."+
" The version gets saved to the cache but the version selection logic is skipped.") " The version gets saved to the cache but the version selection logic is skipped.")
@ -75,7 +76,7 @@ func newRootCmd() *cobra.Command {
rootCmd.PersistentFlags().StringP("region", "r", awsRegion, "region of the targeted bucket.") rootCmd.PersistentFlags().StringP("region", "r", awsRegion, "region of the targeted bucket.")
rootCmd.PersistentFlags().StringP("bucket", "b", awsBucket, "bucket targeted by all operations.") rootCmd.PersistentFlags().StringP("bucket", "b", awsBucket, "bucket targeted by all operations.")
rootCmd.PersistentFlags().Bool("testing", false, "upload to S3 test bucket.") rootCmd.PersistentFlags().Bool("testing", false, "upload to S3 test bucket.")
must(rootCmd.MarkFlagRequired("maa-claims-path")) must(rootCmd.MarkFlagRequired("snp-report-path"))
rootCmd.AddCommand(newDeleteCmd()) rootCmd.AddCommand(newDeleteCmd())
return rootCmd return rootCmd
} }
@ -104,17 +105,20 @@ func runCmd(cmd *cobra.Command, _ []string) (retErr error) {
DistributionID: flags.distribution, DistributionID: flags.distribution,
} }
log.Infof("Reading MAA claims from file: %s", flags.maaFilePath) log.Infof("Reading SNP report from file: %s", flags.snpReportPath)
maaClaimsBytes, err := os.ReadFile(flags.maaFilePath)
if err != nil { fs := file.NewHandler(afero.NewOsFs())
return fmt.Errorf("reading MAA claims file: %w", err) var report verify.Report
if err := fs.ReadJSON(flags.snpReportPath, &report); err != nil {
return fmt.Errorf("reading snp report: %w", err)
} }
var maaTCB maaTokenTCBClaims snpReport := report.SNPReport
if err = json.Unmarshal(maaClaimsBytes, &maaTCB); err != nil { if !allEqual(snpReport.LaunchTCB, snpReport.CommittedTCB, snpReport.ReportedTCB) {
return fmt.Errorf("unmarshalling MAA claims file: %w", err) return fmt.Errorf("TCB versions are not equal: \nLaunchTCB:%+v\nCommitted TCB:%+v\nReportedTCB:%+v",
snpReport.LaunchTCB, snpReport.CommittedTCB, snpReport.ReportedTCB)
} }
inputVersion := maaTCB.ToAzureSEVSNPVersion() inputVersion := convertTCBVersionToAzureVersion(snpReport.LaunchTCB)
log.Infof("Input version: %+v", inputVersion) log.Infof("Input report: %+v", inputVersion)
client, clientClose, err := attestationconfigapi.NewClient(ctx, cfg, client, clientClose, err := attestationconfigapi.NewClient(ctx, cfg,
[]byte(cosignPwd), []byte(privateKey), false, flags.cacheWindowSize, log) []byte(cosignPwd), []byte(privateKey), false, flags.cacheWindowSize, log)
@ -129,7 +133,7 @@ func runCmd(cmd *cobra.Command, _ []string) (retErr error) {
return fmt.Errorf("creating client: %w", err) return fmt.Errorf("creating client: %w", err)
} }
latestAPIVersionAPI, err := attestationconfigapi.NewFetcherWithCustomCDNAndCosignKey(flags.url, constants.CosignPublicKeyDev).FetchAzureSEVSNPVersionLatest(ctx) latestAPIVersionAPI, err := attestationconfigapi.NewFetcherWithCustomCDNAndCosignKey(flags.url, flags.cosignPublicKey).FetchAzureSEVSNPVersionLatest(ctx)
if err != nil { if err != nil {
if errors.Is(err, attestationconfigapi.ErrNoVersionsFound) { if errors.Is(err, attestationconfigapi.ErrNoVersionsFound) {
log.Infof("No versions found in API, but assuming that we are uploading the first version.") log.Infof("No versions found in API, but assuming that we are uploading the first version.")
@ -148,9 +152,34 @@ func runCmd(cmd *cobra.Command, _ []string) (retErr error) {
return nil return nil
} }
func allEqual(args ...verify.TCBVersion) bool {
if len(args) < 2 {
return true
}
firstArg := args[0]
for _, arg := range args[1:] {
if arg != firstArg {
return false
}
}
return true
}
func convertTCBVersionToAzureVersion(tcb verify.TCBVersion) attestationconfigapi.AzureSEVSNPVersion {
return attestationconfigapi.AzureSEVSNPVersion{
Bootloader: tcb.Bootloader,
TEE: tcb.TEE,
SNP: tcb.SNP,
Microcode: tcb.Microcode,
}
}
type config struct { type config struct {
maaFilePath string snpReportPath string
uploadDate time.Time uploadDate time.Time
cosignPublicKey string
region string region string
bucket string bucket string
distribution string distribution string
@ -160,7 +189,7 @@ type config struct {
} }
func parseCliFlags(cmd *cobra.Command) (config, error) { func parseCliFlags(cmd *cobra.Command) (config, error) {
maaFilePath, err := cmd.Flags().GetString("maa-claims-path") snpReportFilePath, err := cmd.Flags().GetString("snp-report-path")
if err != nil { if err != nil {
return config{}, fmt.Errorf("getting maa claims path: %w", err) return config{}, fmt.Errorf("getting maa claims path: %w", err)
} }
@ -191,7 +220,7 @@ func parseCliFlags(cmd *cobra.Command) (config, error) {
if err != nil { if err != nil {
return config{}, fmt.Errorf("getting testing flag: %w", err) return config{}, fmt.Errorf("getting testing flag: %w", err)
} }
url, distribution := getEnvironment(testing) apiCfg := getAPIEnvironment(testing)
force, err := cmd.Flags().GetBool("force") force, err := cmd.Flags().GetBool("force")
if err != nil { if err != nil {
@ -203,41 +232,29 @@ func parseCliFlags(cmd *cobra.Command) (config, error) {
return config{}, fmt.Errorf("getting cache window size: %w", err) return config{}, fmt.Errorf("getting cache window size: %w", err)
} }
return config{ return config{
maaFilePath: maaFilePath, snpReportPath: snpReportFilePath,
uploadDate: uploadDate, uploadDate: uploadDate,
cosignPublicKey: apiCfg.cosignPublicKey,
region: region, region: region,
bucket: bucket, bucket: bucket,
url: url, url: apiCfg.url,
distribution: distribution, distribution: apiCfg.distribution,
force: force, force: force,
cacheWindowSize: cacheWindowSize, cacheWindowSize: cacheWindowSize,
}, nil }, nil
} }
func getEnvironment(testing bool) (url string, distributionID string) { type apiConfig struct {
url string
distribution string
cosignPublicKey string
}
func getAPIEnvironment(testing bool) apiConfig {
if testing { if testing {
return "https://d33dzgxuwsgbpw.cloudfront.net", "ETZGUP1CWRC2P" return apiConfig{url: "https://d33dzgxuwsgbpw.cloudfront.net", distribution: "ETZGUP1CWRC2P", cosignPublicKey: constants.CosignPublicKeyDev}
}
return constants.CDNRepositoryURL, constants.CDNDefaultDistributionID
}
// maaTokenTCBClaims describes the TCB information in a MAA token.
type maaTokenTCBClaims struct {
IsolationTEE struct {
TEESvn uint8 `json:"x-ms-sevsnpvm-tee-svn"`
SNPFwSvn uint8 `json:"x-ms-sevsnpvm-snpfw-svn"`
MicrocodeSvn uint8 `json:"x-ms-sevsnpvm-microcode-svn"`
BootloaderSvn uint8 `json:"x-ms-sevsnpvm-bootloader-svn"`
} `json:"x-ms-isolation-tee"`
}
func (c maaTokenTCBClaims) ToAzureSEVSNPVersion() attestationconfigapi.AzureSEVSNPVersion {
return attestationconfigapi.AzureSEVSNPVersion{
TEE: c.IsolationTEE.TEESvn,
SNP: c.IsolationTEE.SNPFwSvn,
Microcode: c.IsolationTEE.MicrocodeSvn,
Bootloader: c.IsolationTEE.BootloaderSvn,
} }
return apiConfig{url: constants.CDNRepositoryURL, distribution: constants.CDNDefaultDistributionID, cosignPublicKey: constants.CosignPublicKeyReleases}
} }
func must(err error) { func must(err error) {

View File

@ -0,0 +1,32 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package main
import (
"testing"
"github.com/edgelesssys/constellation/v2/internal/verify"
"github.com/stretchr/testify/assert"
)
func TestAllEqual(t *testing.T) {
// Test case 1: One input arg
assert.True(t, allEqual(verify.TCBVersion{Bootloader: 1, Microcode: 2, SNP: 3, TEE: 4}), "Expected allEqual to return true for one input arg, but got false")
// Test case 2: Three input args that are equal
assert.True(t, allEqual(
verify.TCBVersion{Bootloader: 1, Microcode: 2, SNP: 3, TEE: 4},
verify.TCBVersion{Bootloader: 1, Microcode: 2, SNP: 3, TEE: 4},
verify.TCBVersion{Bootloader: 1, Microcode: 2, SNP: 3, TEE: 4},
), "Expected allEqual to return true for three equal input args, but got false")
// Test case 3: Three input args where second and third element are different
assert.False(t, allEqual(
verify.TCBVersion{Bootloader: 2, Microcode: 2, SNP: 3, TEE: 4},
verify.TCBVersion{Bootloader: 2, Microcode: 2, SNP: 3, TEE: 4},
verify.TCBVersion{Bootloader: 2, Microcode: 3, SNP: 3, TEE: 4},
), "Expected allEqual to return false for three input args with different second and third elements, but got true")
}

View File

@ -13,9 +13,6 @@ the attestationconfigapi upload tool through JSON serialization.
package verify package verify
import ( import (
"crypto/x509"
"fmt"
"github.com/golang-jwt/jwt/v5" "github.com/golang-jwt/jwt/v5"
) )
@ -29,7 +26,7 @@ type Report struct {
// Certificate contains the certificate data and additional information. // Certificate contains the certificate data and additional information.
type Certificate struct { type Certificate struct {
*x509.Certificate `json:"certificate"` CertificatePEM string `json:"certificate"`
CertTypeName string `json:"cert_type_name"` CertTypeName string `json:"cert_type_name"`
StructVersion uint8 `json:"struct_version"` StructVersion uint8 `json:"struct_version"`
ProductName string `json:"product_name"` ProductName string `json:"product_name"`
@ -59,7 +56,7 @@ type PlatformInfo struct {
type SignerInfo struct { type SignerInfo struct {
AuthorKey bool `json:"author_key_en"` AuthorKey bool `json:"author_key_en"`
MaskChipKey bool `json:"mask_chip_key"` MaskChipKey bool `json:"mask_chip_key"`
SigningKey fmt.Stringer `json:"signing_key"` SigningKey string `json:"signing_key"`
} }
// SNPReport contains the SNP report data. // SNPReport contains the SNP report data.