Skip to content

Commit

Permalink
Enable attestationconfigapi CLI e2e test for azure-tdx
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Weiße <[email protected]>
  • Loading branch information
daniel-weisse committed Jun 13, 2024
1 parent 6fadbaf commit 424451b
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 81 deletions.
8 changes: 4 additions & 4 deletions .github/actions/e2e_attestationconfigapi/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 }}
13 changes: 5 additions & 8 deletions .github/actions/e2e_verify/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
4 changes: 2 additions & 2 deletions .github/workflows/e2e-attestationconfigapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -36,4 +36,4 @@ jobs:
with:
cosignPrivateKey: ${{ secrets.COSIGN_DEV_PRIVATE_KEY }}
cosignPassword: ${{ secrets.COSIGN_DEV_PASSWORD }}
csp: ${{ matrix.csp }}
attestationVariant: ${{ matrix.attestationVariant }}
21 changes: 14 additions & 7 deletions internal/api/attestationconfigapi/cli/client/reportersnp.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func (c Client) UploadSEVSNPVersionLatest(
}
c.s3Client.Logger.Info(fmt.Sprintf("Found minimal version: %+v with date: %s", minVersion, minDate))

if isInputNewerThanOtherVersion(minVersion, latestVersionInAPI) {
if !isInputNewerThanOtherVersion(minVersion, latestVersionInAPI) {
c.s3Client.Logger.Info(fmt.Sprintf("Input version: %+v is not newer than latest API version: %+v", minVersion, latestVersionInAPI))
return ErrNoNewerVersion
}
Expand Down Expand Up @@ -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]
Expand All @@ -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.
Expand Down
17 changes: 12 additions & 5 deletions internal/api/attestationconfigapi/cli/client/reportertdx.go
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions internal/api/attestationconfigapi/cli/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -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} <version>",
Short: "Delete an object from the attestationconfig API",
Long: "Delete a specific object version from the config api. <version> 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,
Expand All @@ -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/<csp>",
Long: "Delete all objects from the API path constellation/v1/attestation/<csp>",
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,
}
Expand Down
126 changes: 80 additions & 46 deletions internal/api/attestationconfigapi/cli/e2e/test.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand All @@ -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": {
Expand All @@ -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": {
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Loading

0 comments on commit 424451b

Please sign in to comment.