OS Image Build pipeline: prepare lookup tables and additional artifacts (#560)

This commit is contained in:
Malte Poll 2022-11-16 15:45:10 +01:00 committed by GitHub
parent ca4764c466
commit cdaf1fc476
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 366 additions and 55 deletions

View file

@ -36,9 +36,9 @@ outputs:
awsImagePath: awsImagePath:
description: "AWS image path" description: "AWS image path"
value: ${{ steps.aws.outputs.imagePath }} value: ${{ steps.aws.outputs.imagePath }}
awsAmiOutput: awsJsonOutput:
description: "AWS ami output path" description: "AWS ami json output path"
value: ${{ steps.aws.outputs.amiOutput }} value: ${{ steps.aws.outputs.jsonOutput }}
awsImageFilename: awsImageFilename:
description: "AWS raw image filename" description: "AWS raw image filename"
value: ${{ steps.aws.outputs.imageFilename }} value: ${{ steps.aws.outputs.imageFilename }}
@ -72,6 +72,9 @@ outputs:
azureImagePath: azureImagePath:
description: "Azure image path" description: "Azure image path"
value: ${{ steps.azure.outputs.imagePath }} value: ${{ steps.azure.outputs.imagePath }}
azureJsonOutput:
description: "Azure image json output path"
value: ${{ steps.azure.outputs.jsonOutput }}
azureSecurityType: azureSecurityType:
description: "Azure security type" description: "Azure security type"
value: ${{ steps.azure.outputs.securityType }} value: ${{ steps.azure.outputs.securityType }}
@ -108,6 +111,9 @@ outputs:
gcpImagePath: gcpImagePath:
description: "GCP image path" description: "GCP image path"
value: ${{ steps.gcp.outputs.imagePath }} value: ${{ steps.gcp.outputs.imagePath }}
gcpJsonOutput:
description: "GCP image json output path"
value: ${{ steps.gcp.outputs.jsonOutput }}
gcpImageName: gcpImageName:
description: "GCP image name" description: "GCP image name"
value: ${{ steps.gcp.outputs.imageName }} value: ${{ steps.gcp.outputs.imageName }}
@ -117,6 +123,18 @@ outputs:
gcpImageFamily: gcpImageFamily:
description: "GCP image family" description: "GCP image family"
value: ${{ steps.gcp.outputs.imageFamily }} value: ${{ steps.gcp.outputs.imageFamily }}
qemuJsonOutput:
description: "QEMU image json output path"
value: ${{ steps.qemu.outputs.jsonOutput }}
qemuBucket:
description: "QEMU S3 bucket"
value: ${{ steps.qemu.outputs.bucket }}
qemuBaseUrl:
description: "QEMU raw image base URL"
value: ${{ steps.qemu.outputs.baseUrl }}
qemuImagePath:
description: "QEMU image path"
value: ${{ steps.qemu.outputs.imagePath }}
runs: runs:
using: "composite" using: "composite"
@ -142,7 +160,7 @@ runs:
echo "bucket=constellation-images" >> $GITHUB_OUTPUT echo "bucket=constellation-images" >> $GITHUB_OUTPUT
echo "efivarsPath=${basePath}/mkosi.output.aws/fedora~36/efivars.bin" >> $GITHUB_OUTPUT echo "efivarsPath=${basePath}/mkosi.output.aws/fedora~36/efivars.bin" >> $GITHUB_OUTPUT
echo "imagePath=${basePath}/mkosi.output.aws/fedora~36/image.raw" >> $GITHUB_OUTPUT echo "imagePath=${basePath}/mkosi.output.aws/fedora~36/image.raw" >> $GITHUB_OUTPUT
echo "amiOutput=${basePath}/mkosi.output.aws/fedora~36/ami.json" >> $GITHUB_OUTPUT echo "jsonOutput=${basePath}/mkosi.output.aws/fedora~36/image-upload.json" >> $GITHUB_OUTPUT
echo "imageFilename=image-$(date +%s).raw" >> $GITHUB_OUTPUT echo "imageFilename=image-$(date +%s).raw" >> $GITHUB_OUTPUT
if [ "${imageType}" = release ] if [ "${imageType}" = release ]
then then
@ -172,6 +190,7 @@ runs:
semver: ${{ steps.version.outputs.semanticVersion }} semver: ${{ steps.version.outputs.semanticVersion }}
pseudover: ${{ steps.version.outputs.pseudoVersion }} pseudover: ${{ steps.version.outputs.pseudoVersion }}
branchName: ${{ steps.version.outputs.branchName }} branchName: ${{ steps.version.outputs.branchName }}
uploadVariant: ${{ inputs.uploadVariant }}
run: | run: |
echo "resourceGroupName=constellation-images" >> $GITHUB_OUTPUT echo "resourceGroupName=constellation-images" >> $GITHUB_OUTPUT
echo "region=northeurope" >> $GITHUB_OUTPUT echo "region=northeurope" >> $GITHUB_OUTPUT
@ -181,6 +200,7 @@ runs:
echo "publisher=edgelesssys" >> $GITHUB_OUTPUT echo "publisher=edgelesssys" >> $GITHUB_OUTPUT
echo "rawImagePath=${basePath}/mkosi.output.azure/fedora~36/image.raw" >> $GITHUB_OUTPUT echo "rawImagePath=${basePath}/mkosi.output.azure/fedora~36/image.raw" >> $GITHUB_OUTPUT
echo "imagePath=${basePath}/mkosi.output.azure/fedora~36/image.vhd" >> $GITHUB_OUTPUT echo "imagePath=${basePath}/mkosi.output.azure/fedora~36/image.vhd" >> $GITHUB_OUTPUT
echo "jsonOutput=${basePath}/mkosi.output.azure/fedora~36/image-upload${uploadVariant}.json" >> $GITHUB_OUTPUT
# TODO: set default security type to "ConfidentialVM" once replication is possible # TODO: set default security type to "ConfidentialVM" once replication is possible
securityType=${{ inputs.uploadVariant }} securityType=${{ inputs.uploadVariant }}
if [ -z "${securityType}" ]; then if [ -z "${securityType}" ]; then
@ -234,6 +254,7 @@ runs:
echo "region=europe-west3" >> $GITHUB_OUTPUT echo "region=europe-west3" >> $GITHUB_OUTPUT
echo "rawImagePath=${basePath}/mkosi.output.gcp/fedora~36/image.raw" >> $GITHUB_OUTPUT echo "rawImagePath=${basePath}/mkosi.output.gcp/fedora~36/image.raw" >> $GITHUB_OUTPUT
echo "imagePath=${basePath}/mkosi.output.gcp/fedora~36/image.tar.gz" >> $GITHUB_OUTPUT echo "imagePath=${basePath}/mkosi.output.gcp/fedora~36/image.tar.gz" >> $GITHUB_OUTPUT
echo "jsonOutput=${basePath}/mkosi.output.gcp/fedora~36/image-upload.json" >> $GITHUB_OUTPUT
if [ "${imageType}" = release ] if [ "${imageType}" = release ]
then then
echo "imageName=constellation-${imageVersion//./-}" >> $GITHUB_OUTPUT echo "imageName=constellation-${imageVersion//./-}" >> $GITHUB_OUTPUT
@ -249,3 +270,15 @@ runs:
echo "imageFilename=constellation-${timestamp}.tar.gz" >> $GITHUB_OUTPUT echo "imageFilename=constellation-${timestamp}.tar.gz" >> $GITHUB_OUTPUT
echo "imageFamily=constellation-${branchName}" >> $GITHUB_OUTPUT echo "imageFamily=constellation-${branchName}" >> $GITHUB_OUTPUT
fi fi
- name: Configure QEMU input variables
id: qemu
if: ${{ inputs.csp == 'qemu' }}
shell: bash
env:
basePath: ${{ inputs.basePath }}
run: |
echo "bucket=cdn-confidential-cloud-backend" >> $GITHUB_OUTPUT
echo "baseUrl=https://cdn.confidential.cloud" >> $GITHUB_OUTPUT
echo "imagePath=${basePath}/mkosi.output.qemu/fedora~36/image.raw" >> $GITHUB_OUTPUT
echo "jsonOutput=${basePath}/mkosi.output.qemu/fedora~36/image-upload.json" >> $GITHUB_OUTPUT

View file

@ -67,6 +67,7 @@ jobs:
outputs: outputs:
imageType: ${{ steps.image-type.outputs.imageType }} imageType: ${{ steps.image-type.outputs.imageType }}
pkiSet: ${{ steps.pki-set.outputs.pkiSet }} pkiSet: ${{ steps.pki-set.outputs.pkiSet }}
imageVersionUid: ${{ steps.image-version-uid.outputs.imageVersionUid }}
steps: steps:
- name: Checkout - name: Checkout
@ -103,6 +104,18 @@ jobs:
echo "pkiSet=pki_testing" >> "$GITHUB_OUTPUT" echo "pkiSet=pki_testing" >> "$GITHUB_OUTPUT"
fi fi
- name: Determine image version uid
id: image-version-uid
shell: bash
run: |
if [ "${{ steps.image-type.outputs.imageType }}" = "release" ]; then
echo "imageVersionUid=${{ github.event.inputs.imageVersion }}" >> "$GITHUB_OUTPUT"
elif [ "${{ steps.image-type.outputs.imageType }}" = "debug" ]; then
echo "imageVersionUid=debug-${{ steps.version.outputs.pseudoVersion }}" >> "$GITHUB_OUTPUT"
else
echo "imageVersionUid=${{ steps.version.outputs.branchName }}-${{ steps.version.outputs.pseudoVersion }}" >> "$GITHUB_OUTPUT"
fi
make-os-image: make-os-image:
name: "Build OS using mkosi" name: "Build OS using mkosi"
needs: [build-settings, build-dependencies] needs: [build-settings, build-dependencies]
@ -250,7 +263,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
csp: [aws, azure, gcp] csp: [aws, azure, gcp, qemu]
upload-variant: [""] upload-variant: [""]
include: include:
- csp: azure - csp: azure
@ -291,7 +304,10 @@ jobs:
- name: Login to AWS - name: Login to AWS
uses: aws-actions/configure-aws-credentials@67fbcbb121271f7775d2e7715933280b06314838 # tag=v1.7.0 uses: aws-actions/configure-aws-credentials@67fbcbb121271f7775d2e7715933280b06314838 # tag=v1.7.0
if: ${{ matrix.csp == 'aws' || matrix.csp == 'azure' }} # on AWS, login is required to upload the image as AMI
# on Azure, login is done to download the VMGS from S3
# on QEMU, login is done to upload the image to S3
if: ${{ matrix.csp == 'aws' || matrix.csp == 'azure' || matrix.csp == 'qemu' }}
with: with:
role-to-assume: arn:aws:iam::795746500882:role/GitHubConstellationImagePipeline role-to-assume: arn:aws:iam::795746500882:role/GitHubConstellationImagePipeline
aws-region: eu-central-1 aws-region: eu-central-1
@ -334,14 +350,14 @@ jobs:
run: | run: |
echo "::group::Upload AWS image" echo "::group::Upload AWS image"
secure-boot/aws/create_uefivars.sh "${AWS_EFIVARS_PATH}" secure-boot/aws/create_uefivars.sh "${AWS_EFIVARS_PATH}"
upload/upload_aws.sh "${AWS_AMI_OUTPUT}" upload/upload_aws.sh
echo -e "Uploaded AWS image: \`\`\`$(jq < "${AWS_AMI_OUTPUT}")\`\`\`" >> "$GITHUB_STEP_SUMMARY" echo -e "Uploaded AWS image: \n\n\`\`\`\n$(jq < "${AWS_JSON_OUTPUT}")\n\`\`\`\n" >> "$GITHUB_STEP_SUMMARY"
echo "::endgroup::" echo "::endgroup::"
working-directory: ${{ github.workspace }}/image working-directory: ${{ github.workspace }}/image
if: ${{ matrix.csp == 'aws' }} if: ${{ matrix.csp == 'aws' }}
env: env:
PKI: ${{ github.workspace }}/image/pki PKI: ${{ github.workspace }}/image/pki
AWS_AMI_OUTPUT: ${{ steps.vars.outputs.awsAmiOutput }} AWS_JSON_OUTPUT: ${{ steps.vars.outputs.awsJsonOutput }}
AWS_BUCKET: ${{ steps.vars.outputs.awsBucket }} AWS_BUCKET: ${{ steps.vars.outputs.awsBucket }}
AWS_EFIVARS_PATH: ${{ steps.vars.outputs.awsEfivarsPath }} AWS_EFIVARS_PATH: ${{ steps.vars.outputs.awsEfivarsPath }}
AWS_IMAGE_FILENAME: ${{ steps.vars.outputs.awsImageFilename }} AWS_IMAGE_FILENAME: ${{ steps.vars.outputs.awsImageFilename }}
@ -357,12 +373,13 @@ jobs:
echo "::group::Upload GCP image" echo "::group::Upload GCP image"
upload/pack.sh gcp "${GCP_RAW_IMAGE_PATH}" "${GCP_IMAGE_PATH}" upload/pack.sh gcp "${GCP_RAW_IMAGE_PATH}" "${GCP_IMAGE_PATH}"
upload/upload_gcp.sh upload/upload_gcp.sh
echo -e "Uploaded GCP image: \`projects/${GCP_PROJECT}/global/images/${GCP_IMAGE_NAME}\`" >> "$GITHUB_STEP_SUMMARY" echo -e "Uploaded GCP image: \n\n\`\`\`\n$(jq < "${GCP_JSON_OUTPUT}")\n\`\`\`\n" >> "$GITHUB_STEP_SUMMARY"
echo "::endgroup::" echo "::endgroup::"
working-directory: ${{ github.workspace }}/image working-directory: ${{ github.workspace }}/image
if: ${{ matrix.csp == 'gcp' }} if: ${{ matrix.csp == 'gcp' }}
env: env:
PKI: ${{ github.workspace }}/image/pki PKI: ${{ github.workspace }}/image/pki
GCP_JSON_OUTPUT: ${{ steps.vars.outputs.gcpJsonOutput }}
GCP_BUCKET: ${{ steps.vars.outputs.gcpBucket }} GCP_BUCKET: ${{ steps.vars.outputs.gcpBucket }}
GCP_IMAGE_FAMILY: ${{ steps.vars.outputs.gcpImageFamily }} GCP_IMAGE_FAMILY: ${{ steps.vars.outputs.gcpImageFamily }}
GCP_IMAGE_FILENAME: ${{ steps.vars.outputs.gcpImageFilename }} GCP_IMAGE_FILENAME: ${{ steps.vars.outputs.gcpImageFilename }}
@ -378,12 +395,13 @@ jobs:
echo "::group::Upload Azure image" echo "::group::Upload Azure image"
upload/pack.sh azure "${AZURE_RAW_IMAGE_PATH}" "${AZURE_IMAGE_PATH}" upload/pack.sh azure "${AZURE_RAW_IMAGE_PATH}" "${AZURE_IMAGE_PATH}"
upload/upload_azure.sh -g --disk-name "${AZURE_DISK_NAME}" "${AZURE_VMGS_PATH}" upload/upload_azure.sh -g --disk-name "${AZURE_DISK_NAME}" "${AZURE_VMGS_PATH}"
echo -e "Uploaded Azure ${AZURE_SECURITY_TYPE} image: \`/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/${AZURE_RESOURCE_GROUP_NAME^^}/providers/Microsoft.Compute/galleries/${AZURE_GALLERY_NAME}/images/${AZURE_IMAGE_DEFINITION}/versions/${AZURE_IMAGE_VERSION}\`" >> "$GITHUB_STEP_SUMMARY" echo -e "Uploaded Azure ${AZURE_SECURITY_TYPE} image: \n\n\`\`\`\n$(jq < "${AZURE_JSON_OUTPUT}")\n\`\`\`\n" >> "$GITHUB_STEP_SUMMARY"
echo "::endgroup::" echo "::endgroup::"
working-directory: ${{ github.workspace }}/image working-directory: ${{ github.workspace }}/image
if: ${{ matrix.csp == 'azure' }} if: ${{ matrix.csp == 'azure' }}
env: env:
PKI: ${{ github.workspace }}/image/pki PKI: ${{ github.workspace }}/image/pki
AZURE_JSON_OUTPUT: ${{ steps.vars.outputs.azureJsonOutput }}
AZURE_DISK_NAME: ${{ steps.vars.outputs.azureDiskName }} AZURE_DISK_NAME: ${{ steps.vars.outputs.azureDiskName }}
AZURE_GALLERY_NAME: ${{ steps.vars.outputs.azureGalleryName }} AZURE_GALLERY_NAME: ${{ steps.vars.outputs.azureGalleryName }}
AZURE_IMAGE_DEFINITION: ${{ steps.vars.outputs.azureImageDefinition }} AZURE_IMAGE_DEFINITION: ${{ steps.vars.outputs.azureImageDefinition }}
@ -400,9 +418,34 @@ jobs:
AZURE_SKU: ${{ steps.vars.outputs.azureSku }} AZURE_SKU: ${{ steps.vars.outputs.azureSku }}
AZURE_VMGS_PATH: ${{ steps.vars.outputs.azureVmgsPath }} AZURE_VMGS_PATH: ${{ steps.vars.outputs.azureVmgsPath }}
- name: Upload QEMU image
shell: bash
if: ${{ matrix.csp == 'qemu' }}
run: |
echo "::group::Upload QEMU image"
upload/upload_qemu.sh
echo -e "Uploaded QEMU image: \n\n\`\`\`\n$(jq < "${QEMU_JSON_OUTPUT}")\n\`\`\`\n" >> "$GITHUB_STEP_SUMMARY"
echo "::endgroup::"
working-directory: ${{ github.workspace }}/image
env:
QEMU_JSON_OUTPUT: ${{ steps.vars.outputs.qemuJsonOutput }}
QEMU_BUCKET: ${{ steps.vars.outputs.qemuBucket }}
QEMU_BASE_URL: ${{ steps.vars.outputs.qemuBaseUrl }}
QEMU_IMAGE_PATH: ${{ steps.vars.outputs.qemuImagePath }}
IMAGE_VERSION_UID: ${{ needs.build-settings.outputs.imageVersionUid }}
- name: Upload image lookup table as artifact
uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # tag=v3.1.1
with:
name: lookup-table
path: ${{ github.workspace }}/image/mkosi.output.*/*/image-upload*.json
calculate-pcrs: calculate-pcrs:
name: "Calculate PCRs" name: "Calculate PCRs"
needs: [make-os-image] needs: [build-settings, make-os-image]
permissions:
id-token: write
contents: read
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
strategy: strategy:
fail-fast: false fail-fast: false
@ -414,6 +457,12 @@ jobs:
with: with:
ref: ${{ github.head_ref }} ref: ${{ github.head_ref }}
- name: Login to AWS
uses: aws-actions/configure-aws-credentials@67fbcbb121271f7775d2e7715933280b06314838 # tag=v1.7.0
with:
role-to-assume: arn:aws:iam::795746500882:role/GitHubConstellationImagePipeline
aws-region: eu-central-1
- name: Download OS image artifact - name: Download OS image artifact
uses: actions/download-artifact@9782bd6a9848b53b110e712e20e42d89988822b7 # tag=v3.0.1 uses: actions/download-artifact@9782bd6a9848b53b110e712e20e42d89988822b7 # tag=v3.0.1
with: with:
@ -436,7 +485,7 @@ jobs:
./precalculate_pcr_9.sh ${{ github.workspace }}/image.raw ${{ github.workspace }}/pcr-9-${{ matrix.csp }}.json ./precalculate_pcr_9.sh ${{ github.workspace }}/image.raw ${{ github.workspace }}/pcr-9-${{ matrix.csp }}.json
} >> "$GITHUB_STEP_SUMMARY" } >> "$GITHUB_STEP_SUMMARY"
cp pcr-stable.json ${{ github.workspace }}/ cp pcr-stable.json ${{ github.workspace }}/
jq --sort-keys -s '.[0] * .[1] * .[2] * .[3]' ${{ github.workspace }}/pcr-* > ${{ github.workspace }}/pcrs-${{ matrix.csp }}.json jq -sSc '.[0] * .[1] * .[2] * .[3]' ${{ github.workspace }}/pcr-* > ${{ github.workspace }}/pcrs-${{ matrix.csp }}.json
echo "::endgroup::" echo "::endgroup::"
working-directory: ${{ github.workspace }}/image/measured-boot working-directory: ${{ github.workspace }}/image/measured-boot
@ -446,11 +495,28 @@ jobs:
name: pcrs name: pcrs
path: pcrs-${{ matrix.csp }}.json path: pcrs-${{ matrix.csp }}.json
- name: Upload expected PCRs to S3
shell: bash
run: |
aws s3 cp \
"pcrs-${{ matrix.csp }}.json" \
"s3://cdn-confidential-cloud-backend/v1/measurements/${{ needs.build-settings.outputs.imageVersionUid }}/${{ matrix.csp }}/measurements.image.json" \
--no-progress
generate-sbom: generate-sbom:
name: "Generate SBOM" name: "Generate SBOM"
needs: [build-dependencies, make-os-image] needs: [build-settings, build-dependencies, make-os-image]
permissions:
id-token: write
contents: read
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Login to AWS
uses: aws-actions/configure-aws-credentials@67fbcbb121271f7775d2e7715933280b06314838 # tag=v1.7.0
with:
role-to-assume: arn:aws:iam::795746500882:role/GitHubConstellationImagePipeline
aws-region: eu-central-1
- name: Install squashfs tools - name: Install squashfs tools
run: | run: |
echo "::group::Install squashfs tools" echo "::group::Install squashfs tools"
@ -465,6 +531,13 @@ jobs:
# since the images only differ in the ESP partition # since the images only differ in the ESP partition
name: parts-qemu name: parts-qemu
- name: Download manifest
uses: actions/download-artifact@9782bd6a9848b53b110e712e20e42d89988822b7 # tag=v3.0.1
with:
# downloading / using only the QEMU manifest is fine
# since the images only differ in the ESP partition
name: manifest-qemu
- name: Unpack squashfs - name: Unpack squashfs
run: | run: |
echo "::group::Unpack squashfs" echo "::group::Unpack squashfs"
@ -475,18 +548,21 @@ jobs:
with: with:
path: image.root.tree path: image.root.tree
artifact-name: sbom.spdx.json artifact-name: sbom.spdx.json
output-file: sbom.spdx.json
format: spdx-json format: spdx-json
- uses: anchore/sbom-action@06e109483e6aa305a2b2395eabae554e51530e1d # tag=v0.13.1 - uses: anchore/sbom-action@06e109483e6aa305a2b2395eabae554e51530e1d # tag=v0.13.1
with: with:
path: image.root.tree path: image.root.tree
artifact-name: sbom.cyclonedx.json artifact-name: sbom.cyclonedx.json
output-file: sbom.cyclonedx.json
format: cyclonedx-json format: cyclonedx-json
- uses: anchore/sbom-action@06e109483e6aa305a2b2395eabae554e51530e1d # tag=v0.13.1 - uses: anchore/sbom-action@06e109483e6aa305a2b2395eabae554e51530e1d # tag=v0.13.1
with: with:
path: image.root.tree path: image.root.tree
artifact-name: sbom.syft.json artifact-name: sbom.syft.json
output-file: sbom.syft.json
format: syft-json format: syft-json
- name: Combine hashes - name: Combine hashes
@ -529,3 +605,55 @@ jobs:
EOF EOF
cat SHA256SUMS cat SHA256SUMS
echo -e "SHA256SUMS:\n\`\`\`\n$(cat SHA256SUMS)\n\`\`\`" >> "$GITHUB_STEP_SUMMARY" echo -e "SHA256SUMS:\n\`\`\`\n$(cat SHA256SUMS)\n\`\`\`" >> "$GITHUB_STEP_SUMMARY"
- name: Upload SBOMs to S3
shell: bash
run: |
sboms='sbom.spdx.json sbom.cyclonedx.json sbom.syft.json'
manifests='image.raw.manifest image.raw.changelog'
hashes='SHA256SUMS'
for file in ${sboms} ${manifests} ${hashes}; do
aws s3 cp \
"${file}" \
"s3://cdn-confidential-cloud-backend/v1/sbom/${{ needs.build-settings.outputs.imageVersionUid }}/${file}" \
--no-progress
done
upload-image-lookup-table:
name: "Upload image lookup table"
runs-on: ubuntu-22.04
needs: [build-settings, upload-os-image]
permissions:
id-token: write
contents: read
steps:
- name: Download image lookup table
uses: actions/download-artifact@v2
with:
name: lookup-table
- name: Combine lookup tables for CSPs
shell: bash
run: |
echo '{}' > intermediate.json
for lut in mkosi.output.*/*/image-upload*.json; do
jq -scS '.[0] * .[1]' intermediate.json "${lut}" > lookup-table.json
cp lookup-table.json intermediate.json
done
rm -f intermediate.json
mv lookup-table.json "${{ needs.build-settings.outputs.imageVersionUid }}.json"
- name: Login to AWS
uses: aws-actions/configure-aws-credentials@67fbcbb121271f7775d2e7715933280b06314838 # tag=v1.7.0
with:
role-to-assume: arn:aws:iam::795746500882:role/GitHubConstellationImagePipeline
aws-region: eu-central-1
- name: Upload lookup table to S3
shell: bash
run: |
aws s3 cp \
"${{ needs.build-settings.outputs.imageVersionUid }}.json" \
"s3://cdn-confidential-cloud-backend/v1/images/${{ needs.build-settings.outputs.imageVersionUid }}.json" \
--no-progress
echo -e "- [Lookup table](https://cdn.confidential.cloud/v1/images/${{ needs.build-settings.outputs.imageVersionUid }}.json)" >> "$GITHUB_STEP_SUMMARY"

2
image/.gitignore vendored
View file

@ -3,3 +3,5 @@ mkosi.extra
pki pki
image.* image.*
mkosi.output.* mkosi.output.*
pki_*/*.key
pki_*/*.vmgs

View file

@ -5,6 +5,7 @@ BOOTSTRAPPER_BINARY ?= $(BASE_PATH)/../build/bootstrapper
DISK_MAPPER_BINARY ?= $(BASE_PATH)/../build/disk-mapper DISK_MAPPER_BINARY ?= $(BASE_PATH)/../build/disk-mapper
PKI ?= $(BASE_PATH)/pki PKI ?= $(BASE_PATH)/pki
MKOSI_EXTRA ?= $(BASE_PATH)/mkosi.extra MKOSI_EXTRA ?= $(BASE_PATH)/mkosi.extra
IMAGE_VERSION ?= v0.0.0
-include $(CURDIR)/config.mk -include $(CURDIR)/config.mk
csps := aws qemu gcp azure csps := aws qemu gcp azure
certs := $(PKI)/PK.cer $(PKI)/KEK.cer $(PKI)/db.cer certs := $(PKI)/PK.cer $(PKI)/KEK.cer $(PKI)/db.cer
@ -16,7 +17,7 @@ all: $(csps)
$(csps): %: mkosi.output.%/fedora~36/image.raw $(csps): %: mkosi.output.%/fedora~36/image.raw
mkosi.output.%/fedora~36/image.raw: mkosi.files/mkosi.%.conf inject-bins inject-certs mkosi.output.%/fedora~36/image.raw: mkosi.files/mkosi.%.conf inject-bins inject-certs
mkosi --config mkosi.files/mkosi.$*.conf build mkosi --config mkosi.files/mkosi.$*.conf --image-version=$(IMAGE_VERSION) build
secure-boot/signed-shim.sh $@ secure-boot/signed-shim.sh $@
@if [ -n $(SUDO_UID) ] && [ -n $(SUDO_GID) ]; then \ @if [ -n $(SUDO_UID) ] && [ -n $(SUDO_GID) ]; then \
chown -R $(SUDO_UID):$(SUDO_GID) mkosi.output.$*; \ chown -R $(SUDO_UID):$(SUDO_GID) mkosi.output.$*; \

View file

@ -84,7 +84,7 @@ The generated images are partially signed by Microsoft ([shim loader](https://gi
For QEMU and Azure, you can pre-generate the NVRAM variables for secure boot. This is not necessary for GCP, as you can specify secure boot parameters via the GCP API on image creation. For QEMU and Azure, you can pre-generate the NVRAM variables for secure boot. This is not necessary for GCP, as you can specify secure boot parameters via the GCP API on image creation.
<details> <details>
<summary>libvirt / QEMU / KVM</summary> <summary><a id="qemu-secure-boot">libvirt / QEMU / KVM</a></summary>
```sh ```sh
secure-boot/generate_nvram_vars.sh mkosi.output.qemu/fedora~36/image.raw secure-boot/generate_nvram_vars.sh mkosi.output.qemu/fedora~36/image.raw
@ -112,6 +112,7 @@ export AZURE_SNAPSHOT_NAME=${AZURE_DISK_NAME}
export AZURE_RAW_IMAGE_PATH=${PWD}/mkosi.output.azure/fedora~36/image.raw export AZURE_RAW_IMAGE_PATH=${PWD}/mkosi.output.azure/fedora~36/image.raw
export AZURE_IMAGE_PATH=${PWD}/mkosi.output.azure/fedora~36/image.vhd export AZURE_IMAGE_PATH=${PWD}/mkosi.output.azure/fedora~36/image.vhd
export AZURE_VMGS_FILENAME=${AZURE_SECURITY_TYPE}.vmgs export AZURE_VMGS_FILENAME=${AZURE_SECURITY_TYPE}.vmgs
export AZURE_JSON_OUTPUT=${PWD}/mkosi.output.azure/fedora~36/image-upload.json
export BLOBS_DIR=${PWD}/blobs export BLOBS_DIR=${PWD}/blobs
upload/pack.sh azure "${AZURE_RAW_IMAGE_PATH}" "${AZURE_IMAGE_PATH}" upload/pack.sh azure "${AZURE_RAW_IMAGE_PATH}" "${AZURE_IMAGE_PATH}"
upload/upload_azure.sh --disk-name "${AZURE_DISK_NAME}-setup-secure-boot" "" upload/upload_azure.sh --disk-name "${AZURE_DISK_NAME}-setup-secure-boot" ""
@ -158,9 +159,9 @@ export AWS_BUCKET=constellation-images
export AWS_EFIVARS_PATH=${PWD}/mkosi.output.aws/fedora~36/efivars.bin export AWS_EFIVARS_PATH=${PWD}/mkosi.output.aws/fedora~36/efivars.bin
export AWS_IMAGE_PATH=${PWD}/mkosi.output.aws/fedora~36/image.raw export AWS_IMAGE_PATH=${PWD}/mkosi.output.aws/fedora~36/image.raw
export AWS_IMAGE_FILENAME=image-$(date +%s).raw export AWS_IMAGE_FILENAME=image-$(date +%s).raw
export AWS_AMI_OUTPUT=${PWD}/mkosi.output.aws/fedora~36/ami.txt export AWS_JSON_OUTPUT=${PWD}/mkosi.output.aws/fedora~36/image-upload.json
secure-boot/aws/create_uefivars.sh "${AWS_EFIVARS_PATH}" secure-boot/aws/create_uefivars.sh "${AWS_EFIVARS_PATH}"
upload/upload_aws.sh "${AWS_AMI_OUTPUT}" upload/upload_aws.sh
``` ```
</details> </details>
@ -187,6 +188,7 @@ export GCP_BUCKET=constellation-images
export GCP_RAW_IMAGE_PATH=${PWD}/mkosi.output.gcp/fedora~36/image.raw export GCP_RAW_IMAGE_PATH=${PWD}/mkosi.output.gcp/fedora~36/image.raw
export GCP_IMAGE_FILENAME=$(date +%s).tar.gz export GCP_IMAGE_FILENAME=$(date +%s).tar.gz
export GCP_IMAGE_PATH=${PWD}/mkosi.output.gcp/fedora~36/image.tar.gz export GCP_IMAGE_PATH=${PWD}/mkosi.output.gcp/fedora~36/image.tar.gz
export GCP_JSON_OUTPUT=${PWD}/mkosi.output.gcp/fedora~36/image-upload.json
upload/pack.sh gcp ${GCP_RAW_IMAGE_PATH} ${GCP_IMAGE_PATH} upload/pack.sh gcp ${GCP_RAW_IMAGE_PATH} ${GCP_IMAGE_PATH}
upload/upload_gcp.sh upload/upload_gcp.sh
``` ```
@ -228,8 +230,27 @@ export AZURE_PUBLISHER=edgelesssys
export AZURE_DISK_NAME=constellation-$(date +%s) export AZURE_DISK_NAME=constellation-$(date +%s)
export AZURE_RAW_IMAGE_PATH=${PWD}/mkosi.output.azure/fedora~36/image.raw export AZURE_RAW_IMAGE_PATH=${PWD}/mkosi.output.azure/fedora~36/image.raw
export AZURE_IMAGE_PATH=${PWD}/mkosi.output.azure/fedora~36/image.vhd export AZURE_IMAGE_PATH=${PWD}/mkosi.output.azure/fedora~36/image.vhd
export AZURE_JSON_OUTPUT=${PWD}/mkosi.output.azure/fedora~36/image-upload.json
upload/pack.sh azure "${AZURE_RAW_IMAGE_PATH}" "${AZURE_IMAGE_PATH}" upload/pack.sh azure "${AZURE_RAW_IMAGE_PATH}" "${AZURE_IMAGE_PATH}"
upload/upload_azure.sh -g --disk-name "${AZURE_DISK_NAME}" "${AZURE_VMGS_PATH}" upload/upload_azure.sh -g --disk-name "${AZURE_DISK_NAME}" "${AZURE_VMGS_PATH}"
``` ```
</details> </details>
<details>
<summary>QEMU</summary>
- Install `aws` cli (see [here](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html))
- Login to AWS (see [here](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-quickstart.html))
```sh
# set these variables
export IMAGE_VERSION_UID= # e.g. "test123" or "v2.1.0"
export QEMU_BUCKET=cdn-confidential-cloud-backend
export QEMU_BASE_URL="https://cdn.confidential.cloud"
export QEMU_IMAGE_PATH=${PWD}/mkosi.output.qemu/fedora~36/image.raw
export QEMU_JSON_OUTPUT=${PWD}/mkosi.output.qemu/fedora~36/image-upload.json
upload/upload_qemu.sh
```
</details>

View file

@ -1,6 +1,8 @@
{ {
"pcr11": "0000000000000000000000000000000000000000000000000000000000000000", "measurements": {
"pcr12": "0000000000000000000000000000000000000000000000000000000000000000", "11": "0000000000000000000000000000000000000000000000000000000000000000",
"pcr13": "0000000000000000000000000000000000000000000000000000000000000000", "12": "0000000000000000000000000000000000000000000000000000000000000000",
"pcr15": "0000000000000000000000000000000000000000000000000000000000000000" "13": "0000000000000000000000000000000000000000000000000000000000000000",
"15": "0000000000000000000000000000000000000000000000000000000000000000"
}
} }

View file

@ -22,7 +22,9 @@ write_output() {
local out="$1" local out="$1"
cat > "${out}" << EOF cat > "${out}" << EOF
{ {
"pcr4": "${expected_pcr_4}", "measurements": {
"4": "${expected_pcr_4}"
},
"efistages": [ "efistages": [
{ {
"name": "shim", "name": "shim",

View file

@ -7,7 +7,7 @@
# PCR[8] contains the hash of the kernel command line and is measured by systemd-boot. # PCR[8] contains the hash of the kernel command line and is measured by systemd-boot.
# This value is deprecated and will be moved to PCR[12] in the future. # This value is deprecated and will be moved to PCR[12] in the future.
# This script may produce wrong results after 2023 (when the kernel command line is only measured in PCR[12]). # This script may produce wrong results after 2023 (when the kernel command line is only measured in PCR[12]).
# Usage: precalculate_pcr_8.sh <path to image> <path to output file> # Usage: precalculate_pcr_8.sh <path to image> <path to output file> <csp>
set -euo pipefail set -euo pipefail
shopt -s inherit_errexit shopt -s inherit_errexit
@ -34,8 +34,11 @@ write_output() {
local out="$1" local out="$1"
cat > "${out}" << EOF cat > "${out}" << EOF
{ {
"pcr8": "${expected_pcr_8}", "measurements": {
"cmdline": "${cmdline}" "8": "${expected_pcr_8}"
},
"cmdline": "${cmdline}",
"cmdline-sha256": "${cmdline_hash}"
} }
EOF EOF
} }

View file

@ -27,8 +27,10 @@ write_output() {
local out="$1" local out="$1"
cat > "${out}" << EOF cat > "${out}" << EOF
{ {
"pcr9": "${expected_pcr_9}", "measurements": {
"initrd": "${initrd_hash}" "9": "${expected_pcr_9}"
},
"initrd-sha256": "${initrd_hash}"
} }
EOF EOF
} }

View file

@ -17,6 +17,8 @@ SecureBootKey=pki/db.key
SecureBootCertificate=pki/db.crt SecureBootCertificate=pki/db.crt
# TODO: Wait for systemd 252 to bring systemd-measure # TODO: Wait for systemd 252 to bring systemd-measure
# Measure=yes # Measure=yes
ImageId=constellation
Output=image.raw
[Host] [Host]
QemuHeadless=yes QemuHeadless=yes

View file

@ -20,3 +20,7 @@ mkdir -p /etc/{cni,kubernetes}
mv /etc/issue.d /usr/lib/issue.d || true mv /etc/issue.d /usr/lib/issue.d || true
rm -f /etc/issue rm -f /etc/issue
rm -f /etc/issue.net rm -f /etc/issue.net
# update /etc/os-release
echo "IMAGE_ID=\"${IMAGE_ID}\"" >> /etc/os-release
echo "IMAGE_VERSION=\"${IMAGE_VERSION}\"" >> /etc/os-release

View file

@ -13,7 +13,6 @@ fi
CONTAINERS_JSON=$(mktemp /tmp/containers-XXXXXXXXXXXXXX.json) CONTAINERS_JSON=$(mktemp /tmp/containers-XXXXXXXXXXXXXX.json)
declare -A AMI_FOR_REGION declare -A AMI_FOR_REGION
AMI_OUTPUT=$1
import_status() { import_status() {
local import_task_id=$1 local import_task_id=$1
@ -160,8 +159,17 @@ for region in ${AWS_REPLICATION_REGIONS}; do
tag_ami_with_backing_snapshot "${AMI_FOR_REGION[${region}]}" "${region}" tag_ami_with_backing_snapshot "${AMI_FOR_REGION[${region}]}" "${region}"
make_ami_public "${AMI_FOR_REGION[${region}]}" "${region}" make_ami_public "${AMI_FOR_REGION[${region}]}" "${region}"
done done
echo -n "{\"${AWS_REGION}\": \"${AMI_FOR_REGION[${AWS_REGION}]}\"" > "${AMI_OUTPUT}"
json=$(jq -ncS \
--arg region "${AWS_REGION}" \
--arg ami "${AMI_FOR_REGION[${AWS_REGION}]}" \
'{"aws":{($region): $ami}}')
for region in ${AWS_REPLICATION_REGIONS}; do for region in ${AWS_REPLICATION_REGIONS}; do
echo -n ", \"${region}\": \"${AMI_FOR_REGION[${region}]}\"" >> "${AMI_OUTPUT}" json=$(jq -ncS \
--argjson json "${json}" \
--arg region "${region}" \
--arg ami "${AMI_FOR_REGION[${region}]}" \
'$json * {"aws": {($region): $ami}}')
done done
echo "}" >> "${AMI_OUTPUT}"
echo "${json}" > "${AWS_JSON_OUTPUT}"

View file

@ -41,10 +41,13 @@ set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
if [[ ${AZURE_SECURITY_TYPE} == "ConfidentialVM" ]]; then if [[ ${AZURE_SECURITY_TYPE} == "ConfidentialVM" ]]; then
AZURE_DISK_SECURITY_TYPE=ConfidentialVM_VMGuestStateOnlyEncryptedWithPlatformKey AZURE_DISK_SECURITY_TYPE=ConfidentialVM_VMGuestStateOnlyEncryptedWithPlatformKey
AZURE_SIG_VERSION_ENCRYPTION_TYPE=EncryptedVMGuestStateOnlyWithPmk AZURE_SIG_VERSION_ENCRYPTION_TYPE=EncryptedVMGuestStateOnlyWithPmk
security_type_short_name="cvm"
elif [[ ${AZURE_SECURITY_TYPE} == "ConfidentialVMSupported" ]]; then elif [[ ${AZURE_SECURITY_TYPE} == "ConfidentialVMSupported" ]]; then
AZURE_DISK_SECURITY_TYPE="" AZURE_DISK_SECURITY_TYPE=""
security_type_short_name="cvm"
elif [[ ${AZURE_SECURITY_TYPE} == "TrustedLaunch" ]]; then elif [[ ${AZURE_SECURITY_TYPE} == "TrustedLaunch" ]]; then
AZURE_DISK_SECURITY_TYPE=TrustedLaunch AZURE_DISK_SECURITY_TYPE=TrustedLaunch
security_type_short_name="trustedlaunch"
else else
echo "Unknown security type: ${AZURE_SECURITY_TYPE}" echo "Unknown security type: ${AZURE_SECURITY_TYPE}"
exit 1 exit 1
@ -188,6 +191,43 @@ create_sig_version() {
${SOURCE} ${SOURCE}
} }
get_image_version_reference() {
local is_community_gallery
is_community_gallery=$(az sig show --gallery-name "${AZURE_GALLERY_NAME}" \
--resource-group "${AZURE_RESOURCE_GROUP_NAME}" \
--query 'sharingProfile.communityGalleryInfo.communityGalleryEnabled' \
-o tsv)
if [[ ${is_community_gallery} == "true" ]]; then
get_community_image_version_reference
return
fi
get_unshared_image_version_reference
}
get_community_image_version_reference() {
local communityGalleryName
communityGalleryName=$(az sig show --gallery-name "${AZURE_GALLERY_NAME}" \
--resource-group "${AZURE_RESOURCE_GROUP_NAME}" \
--query 'sharingProfile.communityGalleryInfo.publicNames[0]' \
-o tsv)
az sig image-version show-community \
--public-gallery-name "${communityGalleryName}" \
--gallery-image-definition "${AZURE_IMAGE_DEFINITION}" \
--gallery-image-version "${AZURE_IMAGE_VERSION}" \
--location "${AZURE_REGION}" \
--query 'uniqueId' \
-o tsv
}
get_unshared_image_version_reference() {
az sig image-version show \
--resource-group "${AZURE_RESOURCE_GROUP_NAME}" \
--gallery-name "${AZURE_GALLERY_NAME}" \
--gallery-image-definition "${AZURE_IMAGE_DEFINITION}" \
--gallery-image-version "${AZURE_IMAGE_VERSION}" \
--query id --output tsv
}
create_disk create_disk
if [[ ${CREATE_SIG_VERSION} == "YES" ]]; then if [[ ${CREATE_SIG_VERSION} == "YES" ]]; then
@ -196,3 +236,10 @@ if [[ ${CREATE_SIG_VERSION} == "YES" ]]; then
delete_image delete_image
delete_disk delete_disk
fi fi
image_reference=$(get_image_version_reference)
json=$(jq -ncS \
--arg security_type "${security_type_short_name}" \
--arg image_reference "${image_reference}" \
'{"azure": {($security_type): $image_reference}}')
echo -n "${json}" > "${AZURE_JSON_OUTPUT}"

View file

@ -31,3 +31,11 @@ gcloud compute images add-iam-policy-binding "${GCP_IMAGE_NAME}" \
--member='allAuthenticatedUsers' \ --member='allAuthenticatedUsers' \
--role='roles/compute.imageUser' --role='roles/compute.imageUser'
gsutil rm "gs://${GCP_BUCKET}/${GCP_IMAGE_FILENAME}" gsutil rm "gs://${GCP_BUCKET}/${GCP_IMAGE_FILENAME}"
image_reference=$(gcloud compute images describe "${GCP_IMAGE_NAME}" \
--project "${GCP_PROJECT}" \
'--format=value(selfLink.scope(v1))')
json=$(jq -ncS \
--arg image_reference "${image_reference}" \
'{"gcp": {"sev-es": $image_reference}}')
echo -n "${json}" > "${GCP_JSON_OUTPUT}"

21
image/upload/upload_qemu.sh Executable file
View file

@ -0,0 +1,21 @@
#!/usr/bin/env bash
# Copyright (c) Edgeless Systems GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
set -euo pipefail
shopt -s inherit_errexit
if [[ -z ${CONFIG_FILE-} ]] && [[ -f ${CONFIG_FILE-} ]]; then
# shellcheck source=/dev/null
. "${CONFIG_FILE}"
fi
aws s3 cp "${QEMU_IMAGE_PATH}" "s3://${QEMU_BUCKET}/v1/raw/${IMAGE_VERSION_UID}/qemu/image.raw" --no-progress
image_url="${QEMU_BASE_URL}/v1/raw/${IMAGE_VERSION_UID}/qemu/image.raw"
json=$(jq -ncS \
--arg image_url "${image_url}" \
'{"qemu": {"default": $image_url}}')
echo -n "${json}" > "${QEMU_JSON_OUTPUT}"

View file

@ -42,12 +42,13 @@ The build pipeline takes as inputs:
- a version number that is one of - a version number that is one of
- a release version number (e.g. `v2.2.0`) for release images - a release version number (e.g. `v2.2.0`) for release images
- a pseudo-version number (e.g. `v2.3.0-pre-debug`) for development images - a pseudo-version number (e.g. `debug-v2.3.0-pre.0.`) for development images
- a pseudo-version number (e.g. `v2.3.0-pre-branch-name`) for branch images - a pseudo-version number (e.g. `branch-name-v2.3.0-pre.0.`) for branch images
- a commit hash of the Constellation monorepo that is used to build the images (e.g. `cc0de5c68d41f31dd0b284d574f137e0b0ad106b`) - a commit hash of the Constellation monorepo that is used to build the images (e.g. `cc0de5c68d41f31dd0b284d574f137e0b0ad106b`)
- a commit timestamp of the Constellation monorepo that is used to build the images (e.g. `20221115082220`)
To identify images belonging to one invocation of the build pipeline, the pipeline uses a unique identifier for the set of images, referred to as `image version uid`. To identify images belonging to one invocation of the build pipeline, the pipeline uses a unique identifier for the set of images, referred to as `image version uid`.
This is either the release version number (e.g. `v2.2.0`) or a pseudo version that combines the version number and the commit hash (e.g. `v2.3.0-pre-debug-cc0de5c68d41f31dd0b284d574f137e0b0ad106b`). This is either the release version number (e.g. `v2.2.0`) or a pseudo version that combines the version number, commit timestamp and the commit hash (e.g. `debug-v2.3.0-pre.0.20221115082220-cc0de5c68d41f31dd0b284d574f137e0b0ad106b`).
The build pipeline produces as outputs: The build pipeline produces as outputs:
@ -59,12 +60,34 @@ The build pipeline produces as outputs:
The lookup table is uploaded to S3 and is used to identify the images that belong to a given `image version uid`. The lookup table is uploaded to S3 and is used to identify the images that belong to a given `image version uid`.
Measurements are uploaded to S3 and can be looked up for each cloud service provider and `image version uid`. Measurements are uploaded to S3 and can be looked up for each cloud service provider and `image version uid`.
## Image API
The build pipeline produces artifacts that are uploaded to S3 and can be accessed via HTTP.
The artifacts are organized in a directory structure that allows to look up the artifacts for a given `image version uid`.
Where applicable, the API uses the following CSP names:
- `aws` for Amazon Web Services
- `azure` for Microsoft Azure
- `gcp` for Google Cloud Platform
- `qemu` for QEMU
The following HTTP endpoints are available:
- `GET /v1/images/<image version uid>.json` returns the lookup table for the given `image version uid`.
- `GET /v1/measurements/<image version uid>/<csp>/` contains files with measurements and signatures for the given `image version uid` and CSP.
- `measurements.json` contains the final measurements for the given `image version uid` and CSP.
- `measurements.json.sig` returns the signature of the measurements file.
- `measurements.image.json` returns the measurements generated statically from the image.
- `GET /v1/raw/<image version uid>/<csp>/image.raw` returns the raw image for the given `image version uid` and CSP.
- `GET /v1/sbom/<image version uid>/` contains SBOM files for the given `image version uid`. The exact formats and file names are TBD.
## Image lookup table ## Image lookup table
The image lookup table is a JSON file that maps the `image version uid` to the CSP-specific image references. It uses the `image version uid` as file name. The image lookup table is a JSON file that maps the `image version uid` to the CSP-specific image references. It uses the `image version uid` as file name.
``` ```
s3://<BUCKET-NAME>/images/<IMAGE-VERSION-UID>.json s3://<BUCKET-NAME>/v1/images/<IMAGE-VERSION-UID>.json
``` ```
```json ```json
@ -80,8 +103,10 @@ s3://<BUCKET-NAME>/images/<IMAGE-VERSION-UID>.json
}, },
"gcp": { "gcp": {
"sev-es": "gcp-image-123" "sev-es": "gcp-image-123"
},
"qemu": {
"default": "https://cdn.confidential.cloud/v1/raw/v2.2.0/qemu/image.raw"
} }
"qemu": "https://cdn.edgeless.systems/.../qemu.raw"
} }
``` ```
@ -101,8 +126,9 @@ The format of the image measurements is described in the [secure software distri
The image measurements are stored in a folder structure in S3 that is organized by CSP and `image version uid`. The image measurements are stored in a folder structure in S3 that is organized by CSP and `image version uid`.
``` ```
s3://<BUCKET-NAME>/measurements/<CSP>/<IMAGE-VERSION-UID>/measurements.yaml s3://<BUCKET-NAME>/v1/measurements/<CSP>/<IMAGE-VERSION-UID>/measurements.json
s3://<BUCKET-NAME>/measurements/<CSP>/<IMAGE-VERSION-UID>/measurements.yaml.sig s3://<BUCKET-NAME>/v1/measurements/<CSP>/<IMAGE-VERSION-UID>/measurements.json.sig
s3://<BUCKET-NAME>/v1/measurements/<CSP>/<IMAGE-VERSION-UID>/measurements.image.json
``` ```
## CLI image discovery ## CLI image discovery
@ -117,11 +143,12 @@ The `image` field is independent of the CSP and is a used to discover the CSP-sp
The CLI can find a CSP- and region specific image reference by looking up the `image version uid` in the following order: The CLI can find a CSP- and region specific image reference by looking up the `image version uid` in the following order:
- if a local file `<IMAGE-VERSION-UID>.json` exists, use the lookup table in that file - if a local file `<IMAGE-VERSION-UID>.json` exists, use the lookup table in that file
- otherwise, load the image lookup table from a well known URL (e.g. `https://cdn.confidential.cloud/images/<IMAGE-VERSION-UID>.json`) and use the lookup table in that file - otherwise, load the image lookup table from a well known URL (e.g. `https://cdn.confidential.cloud/v1/images/<IMAGE-VERSION-UID>.json`) and use the lookup table in that file
- choose the CSP-specific image reference for the current region and security type: - choose the CSP-specific image reference for the current region and security type:
- On AWS, use the AMI ID for the current region (e.g. `.aws.us-east-1`) - On AWS, use the AMI ID for the current region (e.g. `.aws.us-east-1`)
- On Azure, use the image ID for the security type (CVM or Trusted Launch) (e.g. `.azure.cvm`) - On Azure, use the image ID for the security type (CVM or Trusted Launch) (e.g. `.azure.cvm`)
- On GCP, use the only image ID (e.g. `.gcp`) - On GCP, use the only image ID (e.g. `.gcp.sev-es`)
- On QEMU, use the only image ID (e.g. `.qemu.default`)
This allows customers to upload images to their own cloud subscription and use them with the CLI by providing the image lookup table as a local file. This allows customers to upload images to their own cloud subscription and use them with the CLI by providing the image lookup table as a local file.