From 6396902796eee0230a9b91da117c67104e04b96c Mon Sep 17 00:00:00 2001 From: Joao Luna Date: Tue, 18 Aug 2026 11:14:23 +0100 Subject: [PATCH] docs: confidential compute KBS registries, storage, and sealed secrets Update the Confidential Compute docs for the tenant-controlled KBS features landing across chain-sdk#352, provider#427, and the upstream CoCo/Kata/Trustee PRs. The feature stays experimental; these pages describe the new SDL and provider surface. Tenant guide (learn/core-concepts/confidential-compute): - new "Confidential Registries, Storage, and Secrets" section - private registry credentials via credentials.uri (kbs:///repo/type/tag) - persistent encrypted storage via storage keyRef + persistent block class - sealed environment variables (fail-closed unseal) - KBS provider/tenant modes (params.kbs) - refreshed limitations (private registries, persistent volumes, first-mount cost) Operator guide (providers/.../kubespray/confidential-compute): - STEP 4b: provider KBS flags and confidential storage class allowlist - fix stale tee: {type: sev-snp} example -> tee: cpu Hardware compatibility: Hopper/Blackwell local GPU attestation note. SDL advanced-features: replace stale private-registry warning. --- .../akash-sdl/advanced-features/index.md | 2 +- .../confidential-compute/index.md | 122 +++++++++++++++++- .../confidential-compute-hardware/index.md | 2 + .../kubespray/confidential-compute/index.md | 54 +++++++- 4 files changed, 173 insertions(+), 7 deletions(-) diff --git a/src/content/Docs/developers/deployment/akash-sdl/advanced-features/index.md b/src/content/Docs/developers/deployment/akash-sdl/advanced-features/index.md index b0407bdb9..4939170b2 100644 --- a/src/content/Docs/developers/deployment/akash-sdl/advanced-features/index.md +++ b/src/content/Docs/developers/deployment/akash-sdl/advanced-features/index.md @@ -262,7 +262,7 @@ If the `reclamation` block is omitted, reclamation is not required and any provi Request hardware-isolated Trusted Execution Environments (TEE) to fully secure your workloads during processing. Akash supports AMD SEV-SNP and Intel TDX with optional NVIDIA GPU Confidential Computing. You specify a TEE *capability* in SDL; the provider resolves the actual hardware *platform* at deployment time. -> **Important: Private container registries are not supported yet with Confidential Compute.** TEE services can only pull images from **public** registries. The [`credentials`](#private-container-registries) field is not honored for TEE workloads, and a deployment referencing a private image will fail. Make sure every `image` in a TEE service is publicly pullable. +> **Private registries, persistent encrypted storage, and sealed secrets.** TEE services support all three through tenant-controlled Key Broker Service (KBS) references that the provider brokers but never reads. Registry credentials go in `credentials.uri` as a `kbs:///...` reference instead of inline values, persistent volumes take a signed `keyRef`, and the guest unseals any `sealed.`-prefixed value at startup. See [Confidential Registries, Storage, and Secrets](/docs/learn/core-concepts/confidential-compute#confidential-registries-storage-and-secrets). ### Basic TEE Request diff --git a/src/content/Docs/learn/core-concepts/confidential-compute/index.md b/src/content/Docs/learn/core-concepts/confidential-compute/index.md index 398d253dd..5708193ff 100644 --- a/src/content/Docs/learn/core-concepts/confidential-compute/index.md +++ b/src/content/Docs/learn/core-concepts/confidential-compute/index.md @@ -15,7 +15,7 @@ Standard cloud deployments require trusting the infrastructure operator. Confide Akash supports AMD SEV-SNP and Intel TDX. Tenants specify a TEE *capability* (`cpu` or `cpu-gpu`) in their SDL, and the provider resolves the actual hardware *platform* (`snp` or `tdx`) at deployment time based on its cluster nodes. NVIDIA GPU Confidential Computing is available with the `cpu-gpu` capability. -> **Important: Private container registries are not supported yet.** Confidential Compute workloads can only pull images from **public** registries. If your SDL references an image that requires registry credentials to pull, the deployment will fail. See [Limitations and Considerations](#limitations-and-considerations) for details. +> **New: private registries, persistent encrypted storage, and sealed secrets.** Confidential workloads can now pull private images, attach encrypted persistent volumes, and receive injected secrets, all through tenant-controlled references that the provider brokers but can never read. See [Confidential Registries, Storage, and Secrets](#confidential-registries-storage-and-secrets). --- @@ -88,7 +88,7 @@ Everything inside the VM boundary is encrypted. The provider's OS and administra Set `params.tee` to the desired capability in your service definition. The rest of the SDL remains unchanged. -> **Important: Images must come from a public registry.** Private container registries are not supported yet for Confidential Compute. Every `image` referenced by a TEE service must be publicly pullable, images requiring pull credentials will cause the deployment to fail. +> **Public images need nothing extra.** Any publicly pullable `image` works with no additional configuration. To pull from a **private** registry, provide the credentials as a KBS reference so the provider never sees them, see [Private Registry Credentials](#private-registry-credentials). ### Basic Example — CPU-only TEE @@ -192,6 +192,119 @@ The `params.tee` field accepts the following values: --- +## Confidential Registries, Storage, and Secrets + +Confidential workloads often need something that would normally be visible to whoever runs the machine: credentials to pull a private image, or an encrypted disk that survives restarts. Akash handles these through a **Key Broker Service (KBS)**. The KBS hands a secret to the guest only after the guest proves, through hardware attestation, that it is the exact TEE you deployed. The provider relays the request and never sees what comes back. + +In your SDL you only ever write a reference: an opaque `kbs:///repo/type/tag` URI, or a signed `sealed.<...>` token. The real secret lives in the KBS and never touches the SDL, the manifest, or the provider. + +### Choosing a Key Broker (`params.kbs`) + +Set `params.kbs.mode` on each confidential service to choose whose KBS releases its secrets. This block is required whenever a service uses any of the reference-based features below. + +**Provider mode** uses the KBS the provider operates. This is the simplest option and is enough for most workloads. + +```yaml +params: + tee: cpu + kbs: + mode: provider +``` + +**Tenant mode** points the workload at a KBS you run yourself, so your own attestation policy decides what gets released. + +```yaml +params: + tee: cpu + kbs: + mode: tenant + url: https://kbs.example.com:8443 + certificate: | + -----BEGIN CERTIFICATE----- + ...your KBS public certificate... + -----END CERTIFICATE----- + imageSecurityPolicyURI: kbs:///team/security-policy/sha256-<64-hex-digest> + agentPolicy: | + package agent_policy + default allow = false +``` + +**Managed Trustee (Overclock Labs).** Tenant mode does not mean you have to operate Trustee yourself. Overclock Labs, the team behind Akash, runs a managed Trustee instance you can point `url` at. You get an attestation authority that is independent of the provider, you keep your own key-release policies, and the provider still never sees your secrets, without the work of standing up and maintaining the service. This is the easiest way to use tenant mode. + +### Private Registry Credentials + +A confidential service can pull from a private registry, but you hand it the credentials **by reference, never inline**, so the provider never reads them. Put the registry login in your KBS and point `credentials.uri` at it: + +```yaml +services: + app: + image: registry.example.com/team/private-app:latest + credentials: + uri: kbs:///team/registry/app + params: + tee: cpu + kbs: + mode: provider +``` + +The URI has to be the canonical `kbs:///repo/type/tag` form. A confidential service rejects inline `username`/`password` credentials, since those would hand the secret straight to the provider. Ordinary (non-TEE) services keep using inline credentials exactly as before. + +### Persistent Encrypted Storage + +Confidential workloads can attach persistent volumes that only your guest can decrypt. The data survives restarts, and neither the provider nor the host ever holds the key. + +Mark the volume `persistent: true`, request a block storage `class` the provider has qualified for confidential storage, and give it a signed key reference: + +```yaml +services: + db: + image: postgres:16 + params: + tee: cpu + kbs: + mode: provider + storage: + data: + mount: /var/lib/postgresql/data + keyRef: sealed. +profiles: + compute: + db: + resources: + cpu: + units: 2 + memory: + size: 4Gi + storage: + - name: data + size: 10Gi + attributes: + class: beta3 + persistent: true +``` + +The guest encrypts the volume with a key the KBS releases against your `keyRef`. That `keyRef` has to be a tenant-signed sealed reference (`sealed.
..`), and it only works on a persistent volume. Not every provider offers this. You need one that advertises a block storage class qualified for confidential storage, see [Limitations and Considerations](#limitations-and-considerations). + +### Sealed Environment Variables + +The guest unseals any environment variable value that starts with `sealed.` before your container runs. If it cannot, the container fails to start rather than coming up with the raw `sealed.` string still in place, so a broken secret never leaks its encoded form into your app. + +```yaml +services: + app: + image: myorg/app:latest + env: + - API_KEY=sealed. + params: + tee: cpu + kbs: + mode: provider +``` + +Use sealed environment variables for API keys, database passwords, and other runtime secrets you don't want visible to the provider. + +--- + ## Preparing Images for Confidential Compute A TEE workload runs inside a Kata VM, and its image is pulled and unpacked **inside the encrypted guest** ("guest pull") rather than on the host. A few image properties that don't matter for a normal deployment become important here. Following these keeps you on the happy path. @@ -397,7 +510,7 @@ The attestation design enforces these properties: ## Limitations and Considerations -- **Private container registries are not supported yet.** Confidential Compute workloads can only pull images from **public** registries. Images that require authentication (pull credentials/`imagePullSecrets`) cannot be used with a TEE deployment, and the deployment will fail if it references one. Support for private registries is planned but not yet available. For now, ensure any image used in a confidential workload is publicly pullable. +- **Private registries require KBS-brokered credentials.** A confidential service can pull private images, but the registry credentials must be supplied as a `kbs:///repo/type/tag` reference under `credentials.uri`, not inline. Inline `username`/`password` credentials and `imagePullSecrets` are rejected for TEE services. See [Confidential Registries, Storage, and Secrets](#confidential-registries-storage-and-secrets). - **Provider availability**: Only providers with TEE-capable hardware can accept confidential workloads. Look for the `tee/type` attribute when selecting a provider. - **Performance**: Memory encryption adds a small overhead (~1-5%). GPU Confidential Computing may add further overhead depending on the workload. - **Sidecar resources**: The attestation sidecar consumes modest resources (10m CPU, 32-64Mi memory) which are automatically included in resource accounting. @@ -405,7 +518,8 @@ The attestation design enforces these properties: - **Distroless and scratch-based images are not supported.** Kata Containers uses a guest agent inside the VM to set up and manage the container filesystem. Images built `FROM scratch` or from `gcr.io/distroless/...` lack the minimal filesystem structure (e.g. `/dev`, `/proc`, `/sys`) that the guest agent requires to initialize the container. Use a minimal but complete base image such as `alpine` or `ubuntu` instead. - **Images must run as a numeric user, not a named one.** A named `USER` in the image (e.g. `USER appuser`) fails at container creation (`openat etc/passwd: no such file or directory`) because the host cannot resolve the name against the in-guest filesystem. Use a numeric `UID:GID` (or root). See [Preparing Images for Confidential Compute](#preparing-images-for-confidential-compute). - **Image size is bounded by guest memory.** The image is unpacked into guest RAM (there is no host-shared filesystem), so large images need a correspondingly large `memory` request and can otherwise fail to unpack (`Failed to unpack layer to destination`) or time out during creation (`context deadline exceeded`). Prefer small images and size `memory` for the *extracted* image plus your working set. -- **Ephemeral `storage` is not a real disk (and not extra RAM).** With `shared_fs` disabled, the container's writable layer lives in the guest's RAM. A `storage` request is neither turned into a disk of that size nor into that much RAM (RAM comes from `memory`); usable writable space is bounded by the VM's memory, and writing past it fails with an out-of-space error. Size `memory` for what your workload writes. See [Preparing Images for Confidential Compute](#preparing-images-for-confidential-compute). +- **Ephemeral `storage` is not a real disk (and not extra RAM).** With `shared_fs` disabled, the container's writable layer lives in the guest's RAM. A `storage` request is neither turned into a disk of that size nor into that much RAM (RAM comes from `memory`); usable writable space is bounded by the VM's memory, and writing past it fails with an out-of-space error. Size `memory` for what your workload writes. For durable data, attach a [persistent encrypted volume](#persistent-encrypted-storage) instead. See [Preparing Images for Confidential Compute](#preparing-images-for-confidential-compute). +- **Persistent confidential volumes need a qualified provider and a slow first mount.** Encrypted persistent storage is only available on providers that advertise a block storage class qualified for confidential use. The volume is read in full on first attach to establish encryption, so a large disk can take several minutes before the container starts (roughly 15+ minutes per TB); later restarts mount quickly. --- diff --git a/src/content/Docs/providers/operations/confidential-compute-hardware/index.md b/src/content/Docs/providers/operations/confidential-compute-hardware/index.md index 0c0a4d7c5..e7c2ce39c 100644 --- a/src/content/Docs/providers/operations/confidential-compute-hardware/index.md +++ b/src/content/Docs/providers/operations/confidential-compute-hardware/index.md @@ -52,6 +52,8 @@ GPU CC requires a supported GPU **and** a CC-capable CPU (SEV-SNP or TDX). Drive > Some early H100 boards shipped with vBIOS that does not support CC. Check with your vendor for a CC-enabled vBIOS update if needed. +**Attestation mode.** The provider's Trustee can verify Hopper and Blackwell GPU evidence **locally**, with no round-trip to NVIDIA's Remote Attestation Service (NRAS). It checks the GPU's signed measurements against operator-supplied reference values, taken from authenticated NVIDIA RIMs. Some data-center parts still require remote verification. + ## Compatibility Matrix | CPU | GPU | TEE Capability (SDL) | Platform | Runtime Class | diff --git a/src/content/Docs/providers/setup-and-installation/kubespray/confidential-compute/index.md b/src/content/Docs/providers/setup-and-installation/kubespray/confidential-compute/index.md index 0bb02b8cd..769e5d69c 100644 --- a/src/content/Docs/providers/setup-and-installation/kubespray/confidential-compute/index.md +++ b/src/content/Docs/providers/setup-and-installation/kubespray/confidential-compute/index.md @@ -241,6 +241,57 @@ provider-services run \ --- +## STEP 4b - Configure Confidential Secrets and Storage (optional) + +Confidential workloads can pull private images, attach encrypted persistent volumes, and receive sealed secrets. Each of these relies on a Key Broker Service (KBS), part of [Trustee](https://github.com/confidential-containers/trustee), which releases a secret to a guest only after the guest passes hardware attestation. The provider brokers the request but never sees the secret material. + +There are two ways a tenant's workload can reach a KBS: + +- **Tenant KBS mode**: the tenant runs their own Trustee/KBS and declares it in their SDL. This needs **no provider configuration**; it works as soon as attestation (STEP 4) is enabled. +- **Provider KBS mode**: the provider operates a shared Trustee/KBS and advertises it as the default. Tenants opt in with `kbs: { mode: provider }` in their SDL. Configure it with the flags below. + +> **Skip this step** if you only intend to support tenant-run KBS instances. Tenant KBS mode requires nothing here. + +### Provider KBS Flags + +Point the provider at your Trustee/KBS deployment. These values are all **public**: an HTTPS origin, a certificate chain, and content-addressed policy references. None of them carry secret material. + +> **Managed Trustee (Overclock Labs).** You don't have to run Trustee yourself to offer provider KBS mode. Overclock Labs, the team behind Akash, runs a managed Trustee instance; point `--cc-kbs-url` and the matching certificate and policy flags at it instead of standing up your own. + +| Flag | Description | +|------|-------------| +| `--cc-kbs-url` | HTTPS origin of the provider-managed Trustee KBS, used when an SDL selects provider KBS mode. | +| `--cc-kbs-cert-file` | Path to the public Trustee KBS certificate chain. | +| `--cc-image-security-policy-uri` | Content-addressed `kbs:///` image security policy URI for provider KBS mode. | +| `--cc-agent-policy-file` | Path to the measured Kata agent policy for provider KBS mode. | + +The provider folds these into a deterministic, measured Kata `initdata` bundle for each confidential pod. Because the bundle is measured, only the public configuration above may go into it, tenant keys and credentials never do. + +### Confidential Persistent Storage + +| Flag | Description | +|------|-------------| +| `--cc-persistent-storage-classes` | Comma-separated block storage classes qualified for confidential persistent storage. Empty (the default) disables the feature. | + +Only list **block-mode** storage classes here. The guest encrypts each confidential volume with LUKS and cannot fall back to a host-shared filesystem, so a class that only supports shared filesystems will not work. Tenants can request any class in this list for a persistent confidential volume. The provider rejects anything else at deploy time. + +> **Provider KBS flags are all-or-nothing.** If you set a storage allowlist or advertise provider KBS mode, you must supply a complete Trustee configuration (`--cc-kbs-url`, `--cc-kbs-cert-file`, `--cc-image-security-policy-uri`, and `--cc-agent-policy-file`). The provider fails at startup on an incomplete configuration rather than accepting deployments it cannot serve. + +### Example: CLI Flags + +```bash +provider-services run \ + --attestation-webhook-enabled \ + --attestation-sidecar-image "ghcr.io/akash-network/attestation-sidecar:latest" \ + --cc-kbs-url "https://kbs.provider.example:8443" \ + --cc-kbs-cert-file /etc/akash/cc/kbs-cert.pem \ + --cc-image-security-policy-uri "kbs:///default/security-policy/sha256-<64-hex-digest>" \ + --cc-agent-policy-file /etc/akash/cc/agent-policy.rego \ + --cc-persistent-storage-classes beta3 +``` + +--- + ## STEP 5 — Configure Provider Attributes Tenants discover TEE-capable providers through on-chain attributes. Add both `tee/platform` and `tee/type` to your `provider.yaml`: @@ -319,8 +370,7 @@ services: to: - global: true params: - tee: - type: sev-snp + tee: cpu profiles: compute: