diff --git a/.github/actions/e2e_attestationconfigapi/action.yml b/.github/actions/e2e_attestationconfigapi/action.yml index a98b54670fe..02ec2808475 100644 --- a/.github/actions/e2e_attestationconfigapi/action.yml +++ b/.github/actions/e2e_attestationconfigapi/action.yml @@ -2,9 +2,9 @@ name: E2E Attestationconfig API Test description: "Test the attestationconfig CLI is functional." inputs: - csp: - description: "Cloud provider to run tests against" - default: "azure" + attestationVariant: + description: "attestation variant to run tests against" + default: "azure-sev-snp" cosignPrivateKey: description: "Cosign private key" required: true @@ -30,4 +30,4 @@ runs: COSIGN_PRIVATE_KEY: ${{ inputs.cosignPrivateKey }} COSIGN_PASSWORD: ${{ inputs.cosignPassword }} run: | - bazel run //internal/api/attestationconfigapi/cli:cli_e2e_test -- ${{ inputs.csp }} + bazel run //internal/api/attestationconfigapi/cli:cli_e2e_test -- ${{ inputs.attestationVariant }} diff --git a/.github/actions/e2e_verify/action.yml b/.github/actions/e2e_verify/action.yml index f330751f563..61cefeef0ab 100644 --- a/.github/actions/e2e_verify/action.yml +++ b/.github/actions/e2e_verify/action.yml @@ -68,9 +68,9 @@ runs: case "${{ inputs.attestationVariant }}" in - "azure-sev-snp"|"aws-sev-snp"|"gcp-sev-snp") + "azure-sev-snp"|"azure-tdx"|"aws-sev-snp"|"gcp-sev-snp") echo "Extracting TCB versions for API update" - constellation verify --cluster-id "${clusterID}" --node-endpoint localhost:9090 -o json > "snp-report-${node}.json" + constellation verify --cluster-id "${clusterID}" --node-endpoint localhost:9090 -o json > "attestation-report-${node}.json" ;; *) constellation verify --cluster-id "${clusterID}" --node-endpoint localhost:9090 @@ -88,22 +88,19 @@ runs: aws-region: eu-central-1 - name: Upload extracted TCBs - if: github.ref_name == 'main' && (inputs.attestationVariant == 'azure-sev-snp' || inputs.attestationVariant == 'aws-sev-snp' || inputs.attestationVariant == 'gcp-sev-snp') + if: github.ref_name == 'main' && (inputs.attestationVariant == 'azure-sev-snp' || inputs.attestationVariant == 'azure-tdx' || inputs.attestationVariant == 'aws-sev-snp' || inputs.attestationVariant == 'gcp-sev-snp') shell: bash env: COSIGN_PASSWORD: ${{ inputs.cosignPassword }} COSIGN_PRIVATE_KEY: ${{ inputs.cosignPrivateKey }} run: | - reports=(snp-report-*.json) + reports=(attestation-report-*.json) if [ -z ${#reports[@]} ]; then exit 1 fi - attestationVariant=${{ inputs.attestationVariant }} - cloudProvider=${attestationVariant%%-*} - for file in "${reports[@]}"; do path=$(realpath "${file}") cat "${path}" - bazel run //internal/api/attestationconfigapi/cli -- upload "${cloudProvider}" snp-report "${path}" + bazel run //internal/api/attestationconfigapi/cli -- upload {{ inputs.attestationVariant }} attestation-report "${path}" done diff --git a/.github/workflows/e2e-attestationconfigapi.yml b/.github/workflows/e2e-attestationconfigapi.yml index f00ae908d5a..145e7b52dd9 100644 --- a/.github/workflows/e2e-attestationconfigapi.yml +++ b/.github/workflows/e2e-attestationconfigapi.yml @@ -17,7 +17,7 @@ jobs: fail-fast: false max-parallel: 1 matrix: - csp: ["azure", "aws", "gcp"] + attestationVariant: ["azure-sev-snp", "azure-tdx", "aws-sev-snp", "gcp-sev-snp"] runs-on: ubuntu-22.04 permissions: id-token: write @@ -36,4 +36,4 @@ jobs: with: cosignPrivateKey: ${{ secrets.COSIGN_DEV_PRIVATE_KEY }} cosignPassword: ${{ secrets.COSIGN_DEV_PASSWORD }} - csp: ${{ matrix.csp }} + attestationVariant: ${{ matrix.attestationVariant }} diff --git a/internal/api/attestationconfigapi/cli/client/reportersnp.go b/internal/api/attestationconfigapi/cli/client/reportersnp.go index 3462558c0b1..f197dac4d4f 100644 --- a/internal/api/attestationconfigapi/cli/client/reportersnp.go +++ b/internal/api/attestationconfigapi/cli/client/reportersnp.go @@ -65,8 +65,8 @@ func (c Client) UploadSEVSNPVersionLatest( } c.s3Client.Logger.Info(fmt.Sprintf("Found minimal version: %+v with date: %s", minVersion, minDate)) - if isInputNewerThanOtherVersion(minVersion, latestVersionInAPI) { - c.s3Client.Logger.Info(fmt.Sprintf("Input version: %+v is not newer than latest API version: %+v", minVersion, latestVersionInAPI)) + if !isInputNewerThanOtherVersion(minVersion, latestVersionInAPI) { + c.s3Client.Logger.Info(fmt.Sprintf("Input version: %+v is not newer than latest API version: %+v. Skipping list update", minVersion, latestVersionInAPI)) return ErrNoNewerVersion } @@ -107,9 +107,9 @@ func (c Client) cacheSEVSNPVersion(ctx context.Context, variant variant.Variant, return res.Execute(ctx, c.s3Client) } -// findMinSEVSNPVersion finds the minimal version of the given version dates among the latest cached values in the version window size. +// findMinSEVSNPVersion finds the minimal version (the version with the lowest SVNs) of the given version dates among the latest cached values in the version window size. func (c Client) findMinSEVSNPVersion(ctx context.Context, attestationVariant variant.Variant, versionDates []string) (attestationconfigapi.SEVSNPVersion, string, error) { - var minimalVersion attestationconfigapi.SEVSNPVersion + var minimalVersion *attestationconfigapi.SEVSNPVersion var minimalDate string sort.Sort(sort.Reverse(sort.StringSlice(versionDates))) // sort in reverse order to slice the latest versions versionDates = versionDates[:c.cacheWindowSize] @@ -123,14 +123,21 @@ func (c Client) findMinSEVSNPVersion(ctx context.Context, attestationVariant var // Need to set this explicitly as the variant is not part of the marshalled JSON. obj.variant = attestationVariant - // If the version we fetched has higher SVNs than the current minimal version, update the minimal version. - if isInputNewerThanOtherVersion(obj.SEVSNPVersion, minimalVersion) { - minimalVersion = obj.SEVSNPVersion + if minimalVersion == nil { + minimalVersion = &obj.SEVSNPVersion + minimalDate = date + continue + } + + // If the current minimal version has newer versions than the one we just fetched, + // update the minimal version to the older version. + if isInputNewerThanOtherVersion(*minimalVersion, obj.SEVSNPVersion) { + minimalVersion = &obj.SEVSNPVersion minimalDate = date } } - return minimalVersion, minimalDate, nil + return *minimalVersion, minimalDate, nil } // isInputNewerThanOtherVersion compares all version fields and returns true if any input field is newer. diff --git a/internal/api/attestationconfigapi/cli/client/reportertdx.go b/internal/api/attestationconfigapi/cli/client/reportertdx.go index a36498f9e6f..9500829e630 100644 --- a/internal/api/attestationconfigapi/cli/client/reportertdx.go +++ b/internal/api/attestationconfigapi/cli/client/reportertdx.go @@ -55,7 +55,7 @@ func (c Client) UploadTDXVersionLatest( c.s3Client.Logger.Info(fmt.Sprintf("Found minimal version: %+v with date: %s", minVersion, minDate)) if !isInputNewerThanOtherTDXVersion(minVersion, latestVersionInAPI) { - c.s3Client.Logger.Info(fmt.Sprintf("Input version: %+v is not newer than latest API version: %+v", minVersion, latestVersionInAPI)) + c.s3Client.Logger.Info(fmt.Sprintf("Input version: %+v is not newer than latest API version: %+v. Skipping list update", minVersion, latestVersionInAPI)) return ErrNoNewerVersion } @@ -95,7 +95,7 @@ func (c Client) cacheTDXVersion(ctx context.Context, variant variant.Variant, ve } func (c Client) findMinTDXVersion(ctx context.Context, attestationVariant variant.Variant, versionDates []string) (attestationconfigapi.TDXVersion, string, error) { - var minimalVersion attestationconfigapi.TDXVersion + var minimalVersion *attestationconfigapi.TDXVersion var minimalDate string sort.Sort(sort.Reverse(sort.StringSlice(versionDates))) versionDates = versionDates[:c.cacheWindowSize] @@ -108,14 +108,21 @@ func (c Client) findMinTDXVersion(ctx context.Context, attestationVariant varian } obj.variant = attestationVariant - // If the version we fetched has higher SVNs than the current minimal version, update the minimal version. - if isInputNewerThanOtherTDXVersion(obj.TDXVersion, minimalVersion) { - minimalVersion = obj.TDXVersion + if minimalVersion == nil { + minimalVersion = &obj.TDXVersion + minimalDate = date + continue + } + + // If the current minimal version has newer versions than the one we just fetched, + // update the minimal version to the older version. + if isInputNewerThanOtherTDXVersion(*minimalVersion, obj.TDXVersion) { + minimalVersion = &obj.TDXVersion minimalDate = date } } - return minimalVersion, minimalDate, nil + return *minimalVersion, minimalDate, nil } func isInputNewerThanOtherTDXVersion(input, other attestationconfigapi.TDXVersion) bool { @@ -125,12 +132,6 @@ func isInputNewerThanOtherTDXVersion(input, other attestationconfigapi.TDXVersio if input.QESVN < other.QESVN { return false } - if bytes.Equal(input.QEVendorID[:], other.QEVendorID[:]) { - return false - } - if bytes.Equal(input.XFAM[:], other.XFAM[:]) { - return false - } // Validate component-wise security version numbers for idx, inputVersion := range input.TEETCBSVN { @@ -139,5 +140,9 @@ func isInputNewerThanOtherTDXVersion(input, other attestationconfigapi.TDXVersio } } + if bytes.Equal(input.QEVendorID[:], other.QEVendorID[:]) && bytes.Equal(input.XFAM[:], other.XFAM[:]) { + return false + } + return true } diff --git a/internal/api/attestationconfigapi/cli/delete.go b/internal/api/attestationconfigapi/cli/delete.go index 69dbeccb2c8..013c69481dc 100644 --- a/internal/api/attestationconfigapi/cli/delete.go +++ b/internal/api/attestationconfigapi/cli/delete.go @@ -29,7 +29,7 @@ func newDeleteCmd() *cobra.Command { Use: "delete {aws-sev-snp|azure-sev-snp|azure-tdx|gcp-sev-snp} {attestation-report|guest-firmware} ", Short: "Delete an object from the attestationconfig API", Long: "Delete a specific object version from the config api. is the name of the object to delete (without .json suffix)", - Example: "COSIGN_PASSWORD=$CPW COSIGN_PRIVATE_KEY=$CKEY cli delete azure snp-report 1.0.0", + Example: "COSIGN_PASSWORD=$CPW COSIGN_PRIVATE_KEY=$CKEY cli delete azure-sev-snp attestation-report 1.0.0", Args: cobra.MatchAll(cobra.ExactArgs(3), isAttestationVariant(0), isValidKind(1)), PreRunE: envCheck, RunE: runDelete, @@ -39,7 +39,7 @@ func newDeleteCmd() *cobra.Command { Use: "recursive {aws-sev-snp|azure-sev-snp|azure-tdx|gcp-sev-snp}", Short: "delete all objects from the API path constellation/v1/attestation/", Long: "Delete all objects from the API path constellation/v1/attestation/", - Example: "COSIGN_PASSWORD=$CPW COSIGN_PRIVATE_KEY=$CKEY cli delete recursive azure", + Example: "COSIGN_PASSWORD=$CPW COSIGN_PRIVATE_KEY=$CKEY cli delete recursive azure-sev-snp", Args: cobra.MatchAll(cobra.ExactArgs(1), isAttestationVariant(0)), RunE: runRecursiveDelete, } diff --git a/internal/api/attestationconfigapi/cli/e2e/test.sh.in b/internal/api/attestationconfigapi/cli/e2e/test.sh.in index 5fb23f06f7a..88f349d065e 100755 --- a/internal/api/attestationconfigapi/cli/e2e/test.sh.in +++ b/internal/api/attestationconfigapi/cli/e2e/test.sh.in @@ -19,39 +19,72 @@ configapi_cli=$(realpath @@CONFIGAPI_CLI@@) stat "${configapi_cli}" >> /dev/null configapi_cli="${configapi_cli} --testing" ###### script body ###### -function variant() { - if [[ $1 == "aws" ]]; then - echo "aws-sev-snp" - return 0 - elif [[ $1 == "azure" ]]; then - echo "azure-sev-snp" - return 0 - elif [[ $1 == "gcp" ]]; then - echo "gcp-sev-snp" - return 0 - else - echo "Unknown CSP: $1" - exit 1 - fi -} - -csp=$1 -readonly csp -attestationType=$(variant "$csp") +attestationVariant=$1 +readonly attestationVariant readonly region="eu-west-1" readonly bucket="resource-api-testing" tmpdir=$(mktemp -d) readonly tmpdir -registerExitHandler "rm -rf $tmpdir" +registerExitHandler "rm -rf ${tmpdir}" # empty the bucket version state -${configapi_cli} delete recursive "$csp" --region "$region" --bucket "$bucket" +${configapi_cli} delete recursive "${attestationVariant}" --region "${region}" --bucket "${bucket}" + + +readonly current_report_path="${tmpdir}/attestationReportCurrent.json" +readonly report_path="${tmpdir}/attestationReport.json" +readonly older_report_path="${tmpdir}/attestationReportOld.json" +if [[ ${attestationVariant} == *-tdx ]] +then +# the high version numbers ensure that it's newer than the current latest value +cat << EOF > "${current_report_path}" +{ + "header": { + "qe_svn": "AAA=", + "pce_svn": "AAA=", + "qe_vendor_id": "k5pyM/ecTKmUCg2zlX8GBw==" + }, + "td_quote_body": { + "tee_tcb_svn": "AAAAAAAAAAAAAAAAAAAAAA==", + "xfam": "AAAAAAAAAAA=" + } +} +EOF +# the high version numbers ensure that it's newer than the current latest value +cat << EOF > "${report_path}" +{ + "header": { + "qe_svn": "//8=", + "pce_svn": "//8=", + "qe_vendor_id": "k5pyM/ecTKmUCg2zlX8GBw==" + }, + "td_quote_body": { + "tee_tcb_svn": "BAEHAAAAAAAAAAAAAAAAAA==", + "xfam": "5xgGAAAAAAA=" + } +} +EOF +# has an older version +cat << EOF > "${older_report_path}" +{ + "header": { + "qe_svn": "//8=", + "pce_svn": "/v8=", + "qe_vendor_id": "k5pyM/ecTKmUCg2zlX8GBw==" + }, + "td_quote_body": { + "tee_tcb_svn": "BAEHAAAAAAAAAAAAAAAAAA==", + "xfam": "5xgGAAAAAAA=" + } +} +EOF +elif [[ ${attestationVariant} == *-sev-snp ]] +then # the high version numbers ensure that it's newer than the current latest value -readonly current_report_path="$tmpdir/currentSnpReport.json" -cat << EOF > "$current_report_path" +cat << EOF > "${current_report_path}" { "snp_report": { "reported_tcb": { @@ -75,12 +108,8 @@ cat << EOF > "$current_report_path" } } EOF -# upload a fake latest version for the fetcher -${configapi_cli} upload "$csp" snp-report "$current_report_path" --force --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 -readonly report_path="$tmpdir/snpReport.json" -cat << EOF > "$report_path" +cat << EOF > "${report_path}" { "snp_report": { "reported_tcb": { @@ -104,10 +133,8 @@ cat << EOF > "$report_path" } } EOF - # has an older version -readonly older_report_path="$tmpdir/snpReportOld.json" -cat << EOF > "$older_report_path" +cat << EOF > "${older_report_path}" { "snp_report": { "reported_tcb": { @@ -131,19 +158,26 @@ cat << EOF > "$older_report_path" } } EOF +else + echo "Unknown attestation variant: ${attestationVariant}" + exit 1 +fi + +# upload a fake latest version for the fetcher +${configapi_cli} upload "${attestationVariant}" attestation-report "${current_report_path}" --force --upload-date "2000-01-01-01-01" --region "${region}" --bucket "${bucket}" # report 3 versions with different dates to fill the reporter cache readonly date_oldest="2023-02-01-03-04" -${configapi_cli} upload "$csp" snp-report "$older_report_path" --upload-date "$date_oldest" --region "$region" --bucket "$bucket" --cache-window-size 3 +${configapi_cli} upload "${attestationVariant}" attestation-report "${older_report_path}" --upload-date "${date_oldest}" --region "${region}" --bucket "${bucket}" --cache-window-size 3 readonly date_older="2023-02-02-03-04" -${configapi_cli} upload "$csp" snp-report "$older_report_path" --upload-date "$date_older" --region "$region" --bucket "$bucket" --cache-window-size 3 +${configapi_cli} upload "${attestationVariant}" attestation-report "${older_report_path}" --upload-date "${date_older}" --region "${region}" --bucket "${bucket}" --cache-window-size 3 readonly date="2023-02-03-03-04" -${configapi_cli} upload "$csp" snp-report "$report_path" --upload-date "$date" --region "$region" --bucket "$bucket" --cache-window-size 3 +${configapi_cli} upload "${attestationVariant}" attestation-report "${report_path}" --upload-date "${date}" --region "${region}" --bucket "${bucket}" --cache-window-size 3 # expect that $date_oldest is served as latest version -basepath="constellation/v1/attestation/${attestationType}" +basepath="constellation/v1/attestation/${attestationVariant}" baseurl="https://d33dzgxuwsgbpw.cloudfront.net/${basepath}" -if ! curl -fsSL "${baseurl}"/${date_oldest}.json > version.json; then +if ! curl -fsSL "${baseurl}/${date_oldest}.json" > version.json; then echo "Checking for uploaded version file ${basepath}/${date_oldest}.json: request returned ${?}" exit 1 fi @@ -155,7 +189,7 @@ if ! cmp -s <(echo -n '{"bootloader":255,"tee":255,"snp":255,"microcode":254}') echo '{"bootloader":255,"tee":255,"snp":255,"microcode":254}' exit 1 fi -if ! curl -fsSL "${baseurl}"/${date_oldest}.json.sig > /dev/null; then +if ! curl -fsSL "${baseurl}/${date_oldest}.json.sig" > /dev/null; then echo "Checking for uploaded version signature file ${basepath}/${date_oldest}.json.sig: request returned ${?}" exit 1 fi @@ -174,28 +208,28 @@ if ! cmp -s <(echo -n '["2023-02-01-03-04.json","2000-01-01-01-01.json"]') list. fi # check that the other versions are not uploaded -http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}"/${date_older}.json) -if [[ $http_code -ne 404 ]]; then +http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}/${date_older}.json") +if [[ ${http_code} -ne 404 ]]; then echo "Expected HTTP code 404 for: ${basepath}/${date_older}.json, but got ${http_code}" exit 1 fi -http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}"/${date}.json.sig) -if [[ $http_code -ne 404 ]]; then +http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}/${date}.json.sig") +if [[ ${http_code} -ne 404 ]]; then echo "Expected HTTP code 404 for: ${basepath}/${date}.json, but got ${http_code}" exit 1 fi -${configapi_cli} delete "$csp" snp-report "$date_oldest" --region "$region" --bucket "$bucket" +${configapi_cli} delete "${attestationVariant}" attestation-report "${date_oldest}" --region "${region}" --bucket "${bucket}" # Omit -f to check for 404. We want to check that a file was deleted, therefore we expect the query to fail. -http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}"/${date_oldest}.json) -if [[ $http_code -ne 404 ]]; then +http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}/${date_oldest}.json") +if [[ ${http_code} -ne 404 ]]; then echo "Expected HTTP code 404 for: ${basepath}/${date_oldest}.json, but got ${http_code}" exit 1 fi # Omit -f to check for 404. We want to check that a file was deleted, therefore we expect the query to fail. -http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}"/${date_oldest}.json.sig) -if [[ $http_code -ne 404 ]]; then +http_code=$(curl -sSL -w '%{http_code}\n' -o /dev/null "${baseurl}/${date_oldest}.json.sig") +if [[ ${http_code} -ne 404 ]]; then echo "Expected HTTP code 404 for: ${basepath}/${date_oldest}.json, but got ${http_code}" exit 1 fi diff --git a/internal/api/attestationconfigapi/cli/upload.go b/internal/api/attestationconfigapi/cli/upload.go index 75b13b58572..5943c0ad266 100644 --- a/internal/api/attestationconfigapi/cli/upload.go +++ b/internal/api/attestationconfigapi/cli/upload.go @@ -32,14 +32,14 @@ func newUploadCmd() *cobra.Command { Use: "upload {aws-sev-snp|azure-sev-snp|azure-tdx|gcp-sev-snp} {attestation-report|guest-firmware} ", Short: "Upload an object to the attestationconfig API", - Long: fmt.Sprintf("Upload a new object to the attestationconfig API. For snp-reports the new object is added to a cache folder first."+ + Long: fmt.Sprintf("Upload a new object to the attestationconfig API. For snp-reports the new object is added to a cache folder first.\n"+ "The CLI then determines the lowest version within the cache-window present in the cache and writes that value to the config api if necessary. "+ - "For guest-firmware objects the object is added to the API directly. "+ - "Please authenticate with AWS through your preferred method (e.g. environment variables, CLI)"+ + "For guest-firmware objects the object is added to the API directly.\n"+ + "Please authenticate with AWS through your preferred method (e.g. environment variables, CLI) "+ "to be able to upload to S3. Set the %s and %s environment variables to authenticate with cosign.", envCosignPrivateKey, envCosignPwd, ), - Example: "COSIGN_PASSWORD=$CPW COSIGN_PRIVATE_KEY=$CKEY cli upload azure snp-report /some/path/report.json", + Example: "COSIGN_PASSWORD=$CPW COSIGN_PRIVATE_KEY=$CKEY cli upload azure-sev-snp attestation-report /some/path/report.json", Args: cobra.MatchAll(cobra.ExactArgs(3), isAttestationVariant(0), isValidKind(1)), PreRunE: envCheck, @@ -125,12 +125,12 @@ func uploadReport( newVersion := convertTCBVersionToSNPVersion(report.SNPReport.LaunchTCB) log.Info(fmt.Sprintf("Input SNP report: %+v", newVersion)) - if err := apiClient.UploadSEVSNPVersionLatest(ctx, cfg.variant, newVersion, latestVersionInAPI.SEVSNPVersion, cfg.uploadDate, cfg.force); err != nil { - if errors.Is(err, client.ErrNoNewerVersion) { - log.Info(fmt.Sprintf("Input version: %+v is not newer than latest API version: %+v", newVersion, latestVersionInAPI)) - } + if err := apiClient.UploadSEVSNPVersionLatest( + ctx, cfg.variant, newVersion, latestVersionInAPI.SEVSNPVersion, cfg.uploadDate, cfg.force, + ); err != nil && !errors.Is(err, client.ErrNoNewerVersion) { return fmt.Errorf("updating latest version: %w", err) } + case variant.AzureTDX{}: log.Info(fmt.Sprintf("Reading TDX report from file: %s", cfg.path)) var report *tdx.QuoteV4 @@ -141,10 +141,9 @@ func uploadReport( newVersion := convertQuoteToTDXVersion(report) log.Info(fmt.Sprintf("Input TDX report: %+v", newVersion)) - if err := apiClient.UploadTDXVersionLatest(ctx, cfg.variant, newVersion, latestVersionInAPI.TDXVersion, cfg.uploadDate, cfg.force); err != nil { - if errors.Is(err, client.ErrNoNewerVersion) { - log.Info(fmt.Sprintf("Input version: %+v is not newer than latest API version: %+v", newVersion, latestVersionInAPI)) - } + if err := apiClient.UploadTDXVersionLatest( + ctx, cfg.variant, newVersion, latestVersionInAPI.TDXVersion, cfg.uploadDate, cfg.force, + ); err != nil && !errors.Is(err, client.ErrNoNewerVersion) { return fmt.Errorf("updating latest version: %w", err) } diff --git a/internal/config/config.go b/internal/config/config.go index 24849b02113..b6533022b4b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1165,7 +1165,7 @@ type AzureTDX struct { // Expected 48 byte hex-encoded MR_SEAM value. MRSeam encoding.HexBytes `json:"mrSeam,omitempty" yaml:"mrSeam,omitempty"` // description: | - // Expected 8 byte hex-encoded XFAM field. + // Expected 8 byte hex-encoded eXtended Features Available Mask (XFAM) field. Defaults to the latest available XFAM on Azure VMs. Unset to disable validation. XFAM AttestationVersion[encoding.HexBytes] `json:"xfam" yaml:"xfam"` // description: | // Intel Root Key certificate used to verify the TDX certificate chain.