Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 185 additions & 0 deletions attestation-service/docs/amd-offline-certificate-cache.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# Offline AMD VCEK Caching Guide

This document describes the process to pre-load VCEKs (Versioned Chip
Endorsement Keys) into the trustee environment to allow normal attestation
without connection to the AMD KDS. This guide mainly targets air-gapped
environments.

> [!Note]
> Currently this guide shows a method that builds on using
> [docker](https://confidentialcontainers.org/docs/attestation/installation/docker/)
> to manage kbs services. Additional deployment methods will be covered in future releases.

## Enabling Offline VCEK Store in Attestation Service

### 1. Set VCEK Sources Configuration Option

Update the attestation configuration file to use a predefined vcek store:

`kbs/config/as-config.json`:

```json
{
// ... other fields ...
"verifier_config": {
"snp_verifier": {
// Configure VCEK sources to try, in order. Defaults to [KDS].
"vcek_sources": [
{
"type": "OfflineStore",
},
// Optionally add a fallback to KDS. Leave out if KDS will not
// be reachable.
//{
// "type": "KDS",
//}
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this is now a default option, so maybe this comment should change a little bit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworked wording about it - trying to convey the ordering rules (add KDS if you want a fallback, otherwise KDS will never be attempted).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless nothing is specified, then the KDS will be used, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct

}
}
}
```

With the `OfflineStore` configuration specified, Trustee will inspect the
configured directory for VCEK values following the following format:

```
/opt/confidential-containers/attestation-service/kds-store/vcek/{hwid}/vcek.der
```

Where `{hwid}` is the hardware ID of the AMD EPYC server in lowercase hexadecimal.

### 2. Create and Populate VCEK directory

Create a `vcek` directory populated with the following structure:

```
vcek/
├── <Hex hardware ID>/ (ID must be lowercase)
│ └── vcek.der (cert pre-downloaded from kdsintf.amd.com)
├── <Hex hardware ID>/
│ └── vcek.der
├── <Hex hardware ID>/
└── vcek.der
```

Trustee requires one unique certificate per physical AMD EPYC server that the
KBS will be servicing. The server's hardware ID and certificate's URL can be
fetched using the [snphost tool](https://github.com/virtee/snphost).

On each AMD SNP host, with root/admin access run:
```
sudo snphost show vcek-url
```

You should get a URL of the form:
```
https://kdsintf.amd.com/vcek/{version}/{machine}/{product_name}/{hwid}?{params}
```

You may download it from a browser by pasting that URL, or you can run
the following command on any server with network access to AMD's KDS.
```
sudo snphost fetch vcek der .
```

> [!IMPORTANT]
> - Note that the VCEK URL is specific to the hardware AMD firmware of the
> machine. If the firmware is updated, the VCEK URL will change. See the
> [AMD VCEK documentation](https://docs.amd.com/api/khub/documents/dWGhwYpo1Wv51rJN4d~47g/content)
> for more information about the VCEK URL format.

### 3. Install `vcek` directory into trustee deployment

- **Install in running trustee deployment**

Use docker commands to copy your `vcek` folder into the configured directory:
```
sudo docker exec -it trustee-as-1 mkdir -p /opt/confidential-containers/attestation-service/kds-store/
sudo docker cp ./vcek/ trustee-as-1:/opt/confidential-containers/attestation-service/kds-store/vcek/
```

- **Mount shared directory**

You may also mount a shared directory from the host into the container by
updating `docker-compose.yml` with a specified directory mapping:

```yaml
as:
... <existing configuration>
volumes:
... <existing volumes>
- ./vcek:/opt/confidential-containers/attestation-service/kds-store/vcek:rw
```

### Example:

For some number of AMD EPYC servers you wish for trustee to service:
```
ssh privileged-user@epyc-host "sudo snphost show vcek-url" >> urls.txt
```

On a system with network access to AMD KDS:
```bash

# Create the vcek folder that will be copied to trustee
mkdir vcek

# Fetch certificates using the above URLs file
# There should be one line for each EPYC host that kds will service
cat urls.txt | while read line; do
hwid="$(echo "$line" | cut -d/ -f7 | cut -d'?' -f1 | tr '[:upper:]' '[:lower:]')"
mkdir vcek/$hwid
cd vcek/$hwid
sudo snphost fetch vcek der .
cd ../..
done

# Copy the archive to your air-gapped trustee attestation-service deployment
scp -r vcek user@target-host:/path/to/trustee
```

On the air-gapped trustee attestation-service host:
```bash
# Update as-config.json to enable Disk Caching
cd /path/to/trustee
vi kbs/config/as-config.json
# Update the verifier_config section to:
# "verifier_config": {
# "snp_verifier": {
# "vcek_sources": [
# {
# "type": "OfflineStore",
# }
# ]
# }
# }

# Start trustee
docker compose up -d

# Copy the vcek store into the running attestation service container
sudo docker exec -it trustee-as-1 mkdir -p /opt/confidential-containers/attestation-service/kds-store/
sudo docker cp ./vcek/ trustee-as-1:/opt/confidential-containers/attestation-service/kds-store/vcek/

# Alternative to docker copy would be to add the following shared mount to
# docker-compose.yml under as.volumes section:
# - ./vcek:/opt/confidential-containers/attestation-service/kds-store/vcek:rw
```

## Limitations

VCEK stores must be updated/rebuilt in the following events:
- AMD EPYC host added to serviced cluster
- AMD EPYC host firmware components updated
- VCEK certificate revoked by CA

## Troubleshooting

Enable debug and check logs for `vcek` keyword. Ensure configured sources match
expected values.

```
echo "RUST_LOG=debug" > debug.env
docker compose --env-file debug.env up -d
docker logs trustee-as-1 | grep -i vcek
```
7 changes: 5 additions & 2 deletions deps/verifier/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ pub struct VerifierConfig {

#[cfg(feature = "tpm-verifier")]
tpm_verifier: Option<tpm::config::TpmVerifierConfig>,

#[cfg(feature = "snp-verifier")]
snp_verifier: Option<snp::SnpVerifierConfig>,
}

pub async fn to_verifier(
Expand Down Expand Up @@ -95,8 +98,8 @@ pub async fn to_verifier(
Tee::Snp => {
cfg_if::cfg_if! {
if #[cfg(feature = "snp-verifier")] {
let verifier = snp::Snp::default();
Ok(Box::new(verifier) as Box<dyn Verifier + Send + Sync>)
let snp_config = _config.map(|c| c.snp_verifier).unwrap_or(None);
Ok(Box::<snp::Snp>::new(snp::Snp::new(snp_config).await?) as Box<dyn Verifier + Send + Sync>)
} else {
bail!("feature `snp-verifier` is not enabled for `verifier` crate.")
}
Expand Down
Loading
Loading