-
Notifications
You must be signed in to change notification settings - Fork 3
End-to-end demo on Azure (no attestation yet) #53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 88 commits
1a5744e
6331e29
281a443
5264ac2
c59f3e4
ac1bdfd
d09bb94
e6e0d74
b41526b
838f6b6
3691570
b32af82
15e747d
573fc88
a033a90
ccd871a
bfae8d2
841c105
9fbb5a1
f692166
41e45e8
d8cbae5
2015bd7
ee369b1
8b0e1e4
5687058
f21a657
c2ef7b4
69d2ce8
09c38d9
0421723
d8e6329
b58e472
9c85d2b
a3d919c
700b9f6
d14c26d
33a9ec7
91aedbb
91eca6a
5ba6e0b
f0f62ed
835bcb6
7382339
9451c5a
7e537e3
29f4226
9833491
2ae8eb9
e6e6920
6cfff52
a689ddb
0258fe1
be7cc68
3071a14
2dd2981
114113c
a6d60f6
f08f7bf
a660086
a22c982
9ec30de
02c5356
24a8f52
0874e93
cea8cee
21a0919
7ba15d8
44dc4ae
ae15c25
51838a2
4849b2f
b3a8e5f
71eaa26
d44ec4f
902d98e
2dd473a
55d77a9
42ac094
45af771
5d293cc
96685c6
376b103
17c5e9c
c444515
c476dda
b3d08bd
7a3389b
8941a45
e2a611a
b383aee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
| name: Test for BuildEnv L1 container build | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| push: | ||
| branches: | ||
| - main | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,26 +4,50 @@ This is a proof-of-concept for the OpenSSF SLSA draft | |
| [Attested Build Environments (BuildEnv) track](https://github.com/slsa-framework/slsa/issues/975). | ||
|
|
||
| The CLI in this repo implements vTPM-based attestation and | ||
| integrity checking of a Linux VM image. This repo also provides | ||
| integrity checking of a Linux VM image running in Azure. This repo also provides | ||
| demo GHA workflows showcasing how to meet SLSA BuildEnv L1 and L2 (WIP). | ||
|
|
||
| This Demo uses 2 VMs - `ImageVM` and `HasherVM`. | ||
| - `ImageVM` is used to build the target image, it could be populated with all the tools and data needed | ||
| - `HasherVM` is a "worker" VM whose sole purpose is to compute Verity tree over the ImageVM root FS. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This makes me think that the HasherVM is "more trusted" than the ImageVM. We may want to note a basic trust model for these VMs here.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think they are about the same from the trust perspective. But that seems to unnecessarily complicate things from the distribution perspective because now image provider would have to distribute two images. I will mention trust relationships in the doc
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added text about trusting VMs. @marcelamelara the challenging part is L3. If BuildProvider has BuildEnv L3 level then it should be running ImageVM and HasherVM as confidential VMs encrypting the disk. However, the image itself should not be encrypted. And then the question is how do we generate Verity hashes for the encrypted disk like if it was not encrypted? One solution that comes into my mind is that
In other words we need to operate with a logical disk on the encrypted physical disk. |
||
|
|
||
| ```mermaid | ||
| graph LR; | ||
| ImageVM-- root FS disk -->ImageDisk; | ||
| HasherVM-- computes hashes -->ImageDisk; | ||
| ``` | ||
|
|
||
| Once `HasherVM` completes setting up `ImageDisk` it could be snapshotted to create clones of the `ImageVM`. | ||
|
|
||
| ## Image configuration | ||
|
|
||
| Image has 3 notable partitions - `boot`, `root file system` and `verity tree`. Verity tree contains hashes for the root file system. Verity configuration data (e.g., root hash) is passed in a well-known configuration file within the boot partition. This file is processed by `initrd` to properly initialize (i.e. open) Verity device. Root hash is measured into TPM and hence is present in the remote attestation quote. | ||
|
|
||
| Initrd sets up OverlayFS for the root file system using local ephemeral disk as a storage device. Build environments are ephemeral at `Build L3` and intermediate data is not expected to be preserved upon the termination of the environment. To achieve `BuildEnv L3` temporary storage must be encrypted, which could be done with an ephemeral key generated in Initrd upon booting the environment. `BuildEnv L2` does not require encryption. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to enforce in the demo that the storage must be encrypted at L3? I thought we took that out of the specification.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It has to be encrypted at L3. Because otherwise host-based malware may tamper with the temporary data (and all build artifacts will be there). I do not think it's a big deal to encrypt temporary drive because it's ephemeral and so there is no need in managing keys. And confidential VM will make sure that keys in memory are protected from the malicious host. |
||
|
|
||
| GRUB environment block is disabled to prevent unintended modificaton of the root file system upon booting. | ||
|
|
||
| ## How To Use | ||
|
|
||
| ### Generate the initramfs | ||
| ### Configure Azure account | ||
|
|
||
| From a fresh Ubuntu 20+ VM, install the initramfs scripts: | ||
| ``` | ||
| sudo initramfs/install.sh | ||
| ``` | ||
| _You need to have Azure account to run this demo_ | ||
|
|
||
| Generate the initramfs: | ||
| ``` | ||
| sudo mkinitramfs -o image-attestation.img | ||
| ``` | ||
| Few configuration settings need to be defined in [Actions secrets](https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets). None of these are secrets per se but they are treated as secrets to reduce visibility of private resources in public Actions workflow logs: | ||
| - `AZURE_SUBSCRIPTION_ID` - Azure subscription id that you have `Owner` access to | ||
| - `AZURE_RESOURCE_GROUP` - resource group name where VM and all associated resources are provisioned | ||
| - `AZURE_TENANT_ID` - Azure Entra tenant id where App is located | ||
| - `AZURE_CLIENT_ID` - Azure app id for accessing subscription from the Actions workflow (**MUST** have `Contributor` access to the subscription) | ||
| - `AZURE_LOCATION` - location where VM is provisioned (e.g. `eastus`) | ||
| - `AZURE_VM_NAME` - Name to be used for the VM | ||
|
|
||
| You need to configure OIDC credentials for the app to let Actions workflow acquire access token for this app ([doc link](https://docs.github.com/en/actions/how-tos/secure-your-work/security-harden-deployments/oidc-in-azure)). | ||
|
|
||
| ### Dispath the workflow | ||
|
|
||
| ### Update GRUB | ||
| Dispatch `Image Build` workflow to run this demo. Workflow will build a VM and give you access to this VM by adding GitHub actor public keys into the authorized keys for the `azureuser`. Keys are downloaded from `https://github.com/<your alias>.keys` | ||
|
|
||
| TODO | ||
| After the VM is built you will be able to SSH to the VM with `ssh azureuser@<ip address>` and poke around. | ||
|
|
||
| ### CLI | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| #!/bin/bash | ||
|
|
||
| set -e | ||
|
|
||
| echo "Attesting VM..." | ||
| #TODO |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| #!/bin/bash | ||
|
|
||
| set -e | ||
|
|
||
| VM_NAME=$1 | ||
| VM_USER=${AZURE_VM_USER:-azureuser} | ||
|
|
||
| if ! [ -f ~/.ssh/id_rsa ]; then | ||
| ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -N "" | ||
| fi | ||
|
|
||
| az vm create --resource-group $AZURE_RESOURCE_GROUP \ | ||
| --name $VM_NAME \ | ||
| --image "Canonical:0001-com-ubuntu-server-jammy:22_04-lts-gen2:latest" \ | ||
| --admin-username $VM_USER \ | ||
| --ssh-key-value ~/.ssh/id_rsa.pub \ | ||
| --size Standard_D4ds_v5 \ | ||
| --security-type TrustedLaunch \ | ||
| --nic-delete-option delete \ | ||
| --os-disk-delete-option delete \ | ||
| --patch-mode ImageDefault | ||
|
|
||
| az vm boot-diagnostics enable --resource-group $AZURE_RESOURCE_GROUP \ | ||
| --name $VM_NAME |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| #!/bin/bash | ||
|
|
||
| set -e | ||
|
|
||
| VM_RESOURCE=$1 | ||
|
|
||
| NIC_RESOURCE=$(az vm show --id $VM_RESOURCE | jq -r ".networkProfile.networkInterfaces[0].id") | ||
| IP_RESOURCE=$(az network nic show --id $NIC_RESOURCE | jq -r ".ipConfigurations[0].publicIPAddress.id") | ||
| IP_ADDR=$(az network public-ip show --id $IP_RESOURCE | jq -r ".ipAddress") | ||
|
|
||
| echo $IP_ADDR |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| #!/bin/bash | ||
|
|
||
| set -e | ||
|
|
||
| IP_ADDR=$1 | ||
| VM_USER="${AZURE_VM_USER:-azureuser}" | ||
|
|
||
| echo "Making sure we can connect to the VM using IP $IP_ADDR..." | ||
| MAX_RETRIES=10 | ||
| RETRY_DELAY=10 | ||
| count=0 | ||
| while [ $count -lt $MAX_RETRIES ]; do | ||
| ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa "${VM_USER}@${IP_ADDR}" "uname -a" && break | ||
| count=$((count + 1)) | ||
| echo "Retry $count/$MAX_RETRIES failed. Waiting $RETRY_DELAY seconds before next attempt..." | ||
| sleep $RETRY_DELAY | ||
| done | ||
|
|
||
| if [ $count -eq $MAX_RETRIES ]; then | ||
| echo "All $MAX_RETRIES attempts failed." | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "$IP_ADDR is reachable for SSH!" |
Uh oh!
There was an error while loading. Please reload this page.