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
18 changes: 9 additions & 9 deletions content/en/blog/2024/building-trust-into-os-images-for-coco.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ This option is appealing for certain CoCo deployments. If we have a Trusted Exec

An expected SEV-SNP launch measurement for Linux direct boot with Qemu can be calculated using trusted artifacts (firmware, kernel & initrd) and a few platform parameters. Please note that the respective kernel/fw components and tools are still being actively developed. The [AMDESE/AMDSEV](https://github.com/AMDESE/AMDSEV/tree/snp-latest) repository provides instructions and pointers to a working set of revisions.

```bash
```console
$ sev-snp-measure \
--mode snp \
--vcpus=1 \
Expand All @@ -49,7 +49,7 @@ A rootfs can comfortably host the infrastructure components and we can still pac

DM-Verity volumes feature a hash tree and a root hash in addition to the actual data. The hash tree can be stored on disk next to the verity volume or as a local file. We'll store the hash-tree as file for brevity and write a string `CoCo` into a file `/coco` on the formatted volume:

```bash
```console
$ dd if=/dev/zero of=rootfs.raw bs=1M count=100
$ DEVICE="$(sudo losetup --show -f rootfs.raw)"
$ sudo cfdisk "$DEVICE"
Expand Down Expand Up @@ -77,7 +77,7 @@ $ export ROOT_HASH=ad86ff8492be2ee204cb54d70c84412c2dc89cefd34e263184f4e00295a41

Now we toggle a bit on the raw image (`CoCo` => `DoCo` in `/coco`). If the image is attached as a block device via dm-verity, there will be IO errors and respective entries in the kernel log, once we attempt to read the file.

```bash
```console
$ hexdump -C rootfs.raw | grep CoCo
06000000 43 6f 43 6f 0a 00 00 00 00 00 00 00 00 00 00 00 |CoCo............|
$ printf '\x44' | dd of=rootfs.raw bs=1 seek="$((16#06000000))" count=1 conv=notrunc
Expand Down Expand Up @@ -113,7 +113,7 @@ To retrieve the expected measurements, for a dm-verity protected OS image, we ca
In a TEE the vTPM would have to be isolated from both the Host and the Guest OS. We use `swtpm` to retrieve reference values here.
{{% /alert %}}

```bash
```console
$ swtpm socket \
--tpmstate dir=/tmp/vtpm \
--ctrl type=unixio,path=/tmp/vtpm/swtpm.sock \
Expand All @@ -123,8 +123,8 @@ $ swtpm socket \

We retrieve VM firmware from debian's repository and attach the vTPM socket as character device:

```bash
# retrieve vm firmware from debian's repo
```console
$ # retrieve vm firmware from debian's repo
$ wget http://security.debian.org/debian-security/pool/updates/main/e/edk2/ovmf_2022.11-6+deb12u1_all.deb
$ mkdir fw
$ dpkg-deb -x ovmf_2022.11-6+deb12u1_all.deb fw/
Expand All @@ -146,7 +146,7 @@ $ qemu-system-x86_64 \

Once logged into the VM we can retrieve the relevant measurements in the form of PCRs (the package `tpm2_tools` needs to be available):

```bash
```console
$ tpm2_pcrread sha256:0,1,2,3,4,5,6,7,8,9,10,11
sha256:
0 : 0x61E3B90D0862D052BF6C802E0FD2A44A671A37FE2EB67368D89CB56E5D23014E
Expand All @@ -165,7 +165,7 @@ $ tpm2_pcrread sha256:0,1,2,3,4,5,6,7,8,9,10,11

If we boot the same image on a Confidential VM in Azure's cloud, we'll see different measurements. This is expected since the early boot stack does not match our reference setup:

```bash
```console
$ tpm2_pcrread sha256:0,1,2,3,4,5,6,7,8,9,10,11
sha256:
0 : 0x782B20B10F55CC46E2142CC2145D548698073E5BEB82752C8D7F9279F0D8A273
Expand All @@ -184,7 +184,7 @@ $ tpm2_pcrread sha256:0,1,2,3,4,5,6,7,8,9,10,11

We can identify the common PCRs between the measurements in a cloud VM and those that we gathered in our reference setup. Those are good candidates to include them as [reference values](https://confidentialcontainers.org/docs/attestation/reference-values/) in a relying party against which a TEE's evidence can be verified.

```bash
```console
$ grep -F -x -f pcr_reference.txt pcr_cloud.txt
3 : 0x3D458CFE55CC03EA1F443F1562BEEC8DF51C75E14A9FCF9A7234A13F198E7969
8 : 0x0000000000000000000000000000000000000000000000000000000000000000
Expand Down
104 changes: 52 additions & 52 deletions content/en/blog/2024/coco-without-confidential-hardware.md

Large diffs are not rendered by default.

55 changes: 27 additions & 28 deletions content/en/blog/2024/policing-a-sandbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ For the implementers of such a solution, this choice comes with a few challenges

This would be the sequence of RPC calls that are issued to a Kata agent in the Guest VM (for brevity we'll refer to it as _Agent_ in the text below), if we launch a simple Nginx Pod. There are 2 containers being launched, because a Pod includes the implicit `pause` container:

```
```text
create_sandbox
get_guest_details
copy_file
Expand Down Expand Up @@ -62,7 +62,6 @@ In order to preserve the integrity of a Confidential Pod, we need to observe clo
Kata-Containers currently features an implementation of a policy engine using the popular [Rego](https://www.openpolicyagent.org/docs/latest/policy-language) language. Convenience tooling can assist and automate aspects of authoring a policy for a workload. The following would be an example policy (hand-crafted for brevity, real policy bodies would be larger) in which we allow the launch of specific OCI images, the execution of certain commands, Kata management endpoints, but disallow pretty much everything else during runtime:

```rego
"""
package agent_policy

import future.keywords.in
Expand All @@ -85,13 +84,13 @@ default ExecProcessRequest := false

CreateContainerRequest if {
every storage in input.storages {
some allowed_image in policy_data.allowed_images
storage.source == allowed_image
}
some allowed_image in policy_data.allowed_images
storage.source == allowed_image
}
}

ExecProcessRequest if {
input_command = concat(" ", input.process.Args)
input_command = concat(" ", input.process.Args)
some allowed_command in policy_data.allowed_commands
input_command == allowed_command
}
Expand Down Expand Up @@ -180,8 +179,8 @@ Host-Data is a field in a TEE’s evidence that is passed into a confidential Gu

Example: Producing a SHA256 digest of the Init-Data file

```bash
openssl dgst -sha256 --binary init-data.toml | xxd -p -c32
```console
$ openssl dgst -sha256 --binary init-data.toml | xxd -p -c32
bdc9a7390bb371258fb7fb8be5a8de5ced6a07dd077d1ce04ec26e06eaf68f60
```

Expand All @@ -191,10 +190,10 @@ Instead of seeding the Init-Data hash into a Host-Data field at launch, we can a

Example: Extending an empty SHA256 runtime measurement register with the digest of an Init-Data file

```bash
dd if=/dev/zero of=zeroes bs=32 count=1
openssl dgst -sha256 --binary init-data.toml > init-data.digest
openssl dgst -sha256 --binary <(cat zeroes init-data.digest) | xxd -p -c32
```console
$ dd if=/dev/zero of=zeroes bs=32 count=1
$ openssl dgst -sha256 --binary init-data.toml > init-data.digest
$ openssl dgst -sha256 --binary <(cat zeroes init-data.digest) | xxd -p -c32
7aaf19294adabd752bf095e1f076baed85d4b088fa990cb575ad0f3e0569f292
```

Expand Down Expand Up @@ -231,46 +230,46 @@ cat nginx-cc.yaml | jq \

If the Pod came up successfully, it passed the initial policy check for the image already.

```bash
kubectl get pod
```console
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-cc-694cc48b65-lklj7 1/1 Running 0 83s
```

According to the policy only certain commands are allowed to be executed in the container. Executing `whoami` should be fine, while `ls` should be rejected:

```bash
kubectl exec -it deploy/nginx-cc -- whoami
```console
$ kubectl exec -it deploy/nginx-cc -- whoami
root
```

```bash
kubectl exec -it deploy/nginx-cc -- ls
```console
$ kubectl exec -it deploy/nginx-cc -- ls
error: Internal error occurred: error executing command in container: failed to
exec in container: failed to start exec "e2d8bad68b64d6918e6bda08a43f457196b5f30d6616baa94a0be0f443238980": cannot enter container 914c589fe74d1fcac834d0dcfa3b6a45562996661278b4a8de5511366d6a4609, with err rpc error: code = PermissionDenied desc = "ExecProcessRequest is blocked by policy: ": unknown
```

In our example we tie the Init-Data measurement to the TEE evidence using a Runtime Measurement into PCR8 of a vTPM. Assuming a 0-initalized SHA256 register, we can calculate the expected value by extend the zeroes with the SHA256 digest of the Init-Data file:
In our example we tie the Init-Data measurement to the TEE evidence using a Runtime Measurement into PCR8 of a vTPM. Assuming a 0-initialized SHA256 register, we can calculate the expected value by extend the zeroes with the SHA256 digest of the Init-Data file:

```bash
dd if=/dev/zero of=zeroes bs=32 count=1
openssl dgst -sha256 --binary init-data.toml > init-data.digest
openssl dgst -sha256 --binary <(cat zeroes init-data.digest) | xxd -p -c32
```console
$ dd if=/dev/zero of=zeroes bs=32 count=1
$ openssl dgst -sha256 --binary init-data.toml > init-data.digest
$ openssl dgst -sha256 --binary <(cat zeroes init-data.digest) | xxd -p -c32
765156eda5fe806552610f2b6e828509a8b898ad014c76ad8600261eb7c5e63f
```

As part of the policy we also allow-listed a specific command that can request a KBS token using an endpoint that is exposed to a container by a [specific Guest Component](https://github.com/confidential-containers/guest-components/tree/41ad96d4b2e5e9dc205c6d41f7b550629cea677f/api-server-rest). Note: This is not something a user would want to typically enable, since this token is used to retrieve confidential secrets and we would not want it to leak outside the Guest. We are using it here to illustrate that we _could_ retrieve a secret in the container, since we passed remote attestation including the verification of the Init-Data digest.


```bash
kubectl exec deploy/nginx-cc -- curl -s http://127.0.0.1:8006/aa/token\?token_type=kbs | jq -c 'keys'
```console
$ kubectl exec deploy/nginx-cc -- curl -s http://127.0.0.1:8006/aa/token\?token_type=kbs | jq -c 'keys'
["tee_keypair","token"]
```

Since this has been successful we can inspect the logs of the Attestation Service (bundled into a KBS here) to confirm it has been considered in the appraisal. The first text block shows the claims from the (successfully verified) TEE evidence, the second block is displaying the acceptable reference values for a PCR8 measurement:

```bash
kubectl logs deploy/kbs -n coco-tenant | grep -C 2 765156eda5fe806552610f2b6e828509a8b898ad014c76ad8600261eb7c5e63f
```console
$ kubectl logs deploy/kbs -n coco-tenant | grep -C 2 765156eda5fe806552610f2b6e828509a8b898ad014c76ad8600261eb7c5e63f
...
"aztdxvtpm.tpm.pcr06": String("65f0a56c41416fa82d573df151746dc1d6af7bd8d4a503b2ab07664305d01e59"),
"aztdxvtpm.tpm.pcr07": String("124daf47b4d67179a77dc3c1bcca198ae1ee1d094a2a879974842e44ab98bb06"),
Expand All @@ -282,7 +281,7 @@ kubectl logs deploy/kbs -n coco-tenant | grep -C 2 765156eda5fe806552610f2b6e828
"7aaf19294adabd752bf095e1f076baed85d4b088fa990cb575ad0f3e0569f292",
"765156eda5fe806552610f2b6e828509a8b898ad014c76ad8600261eb7c5e63f",
],
"aztdxvtpm.tpm.pcr10": [],
"aztdxvtpm.tpm.pcr10": [],
```

### Size Limitations
Expand Down
18 changes: 9 additions & 9 deletions content/en/blog/2025/coco-and-slsa.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Following is the current state of provenance generation of the CoCo projects:

Formerly exclusively a place to host layers for container images, OCI registries today can serve a multitude of use cases, such as Helm Charts or Attestation data. A registry is a content-addressable store, which means that it is named after a digest of its content.

```sh
```console
$ DIGEST="84ec2a70279219a45d327ec1f2f112d019bc9dcdd0e19f1ba7689b646c2de0c2"
$ oras manifest fetch "quay.io/curl/curl@sha256:${DIGEST}" | sha256sum
84ec2a70279219a45d327ec1f2f112d019bc9dcdd0e19f1ba7689b646c2de0c2 -
Expand All @@ -99,23 +99,23 @@ $ oras manifest fetch "quay.io/curl/curl@sha256:${DIGEST}" | sha256sum
We also use OCI registries to distribute and cache artifacts in the CoCo project.
There is a convention of specifying upstream dependencies in a `versions.yaml` file this:

```sh
```yaml
oci:
...
# ...
kata-containers:
registry: ghcr.io/kata-containers/cached-artefacts
reference: 3.13.0
registry: ghcr.io/kata-containers/cached-artefacts
reference: 3.13.0
guest-components:
registry: ghcr.io/confidential-containers/guest-components
reference: 3df6c412059f29127715c3fdbac9fa41f56cfce4
registry: ghcr.io/confidential-containers/guest-components
reference: 3df6c412059f29127715c3fdbac9fa41f56cfce4
```

Note that the `reference` in this case is a tag, sometimes a version, and sometimes a reference to the digest of a given git commit, not the digest of the OCI artefact. What do we express from this specification, and what do we want to verify?
We might want to resolve a tag to a git digest first, so tag 3.13.0 resolves to the digest `2777b13db748f9ba785c7d2be4fcb6ac9c9af265`. Knowing the git digest, we now want to verify that official repository runners built the artefact from the main branch using the source code and build workflows from that above digest.
This is what the SLSA attestation that we created during the artefact's build can substantiate.
It wouldn't make sense to attest against an artifact using an OCI tag alias (those are not immutable, and one can move it to point to something else); the attestations are tied to an OCI artifact referenced by its digest and conveniently stored alongside this in the same repo. We can find it manually if we search for referrers of our OCI artifact.

```sh
```console
$ GIT_DGST="2777b13db748f9ba785c7d2be4fcb6ac9c9af265"
$ oras resolve "ghcr.io/kata-containers/cached-artefacts/agent:${GIT_DGST}-x86_64"
sha256:c127db93af2fcefddebbe98013e359a7c30b9130317a96aab50093af0dbe8464
Expand All @@ -132,7 +132,7 @@ As mentioned previously, Github provides a command line option to verify the [pr

The following snippet from the cloud-api-adaptor project's [Makefile](https://github.com/confidential-containers/cloud-api-adaptor/blob/main/src/cloud-api-adaptor/podvm/Makefile.inc) shows an example usage:

```sh
```bash
define pull_agent_artifact
$(eval $(call generate_tag,tag,$(KATA_REF),$(ARCH)))
$(eval OCI_IMAGE := $(KATA_REGISTRY)/agent)
Expand Down
30 changes: 15 additions & 15 deletions content/en/blog/2026/trustee-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ kubectl get csv -n operators

We should expect something like:

```bash
```text
NAME DISPLAY VERSION REPLACES PHASE
trustee-operator.v0.17.0 Trustee Operator 0.17.0 trustee-operator.v0.5.0 Succeeded
```
Expand Down Expand Up @@ -178,7 +178,7 @@ EOF
<summary>Permissive Mode</summary>
TrusteeConfig CR creation:

```bash
```yaml
apiVersion: confidentialcontainers.org/v1alpha1
kind: TrusteeConfig
metadata:
Expand Down Expand Up @@ -308,18 +308,18 @@ kubectl config set-context --current --namespace=operators

### Check if the PODs are running

```bash
kubectl get pods -n operators
```console
$ kubectl get pods -n operators
NAME READY STATUS RESTARTS AGE
trustee-deployment-7bdc6858d7-bdncx 1/1 Running 0 69s
trustee-operator-controller-manager-6c584fc969-8dz2d 1/1 Running 0 4h7m
```

Also, the log should report something like:

```bash
POD_NAME=$(kubectl get pods -l app=kbs -o jsonpath='{.items[0].metadata.name}' -n operators)
kubectl logs -n operators $POD_NAME
```console
$ export POD_NAME=$(kubectl get pods -l app=kbs -o jsonpath='{.items[0].metadata.name}' -n operators)
$ kubectl logs -n operators $POD_NAME
[2026-02-10T15:21:47Z INFO kbs] Using config file /etc/kbs-config/kbs-config.toml
[2026-02-10T15:21:47Z INFO tracing::span] Initialize RVPS;
[2026-02-10T15:21:47Z INFO attestation_service::rvps] launch a built-in RVPS.
Expand Down Expand Up @@ -362,16 +362,16 @@ Finally we are able to test the entire attestation protocol, when fetching one o
Note: Make sure the resource-policy is permissive for testing purposes.
For example:

```
package policy
default allow = true
```rego
package policy
default allow = true
```


```bash
kubectl get secret trustee-tls-cert -n operators -o json | jq -r '.data."tls.crt"' | base64 --decode > https.crt
kubectl cp -n operators https.crt kbs-client:/
kubectl exec -it -n operators kbs-client -- kbs-client --cert-file https.crt --url https://kbs-service:8080 get-resource --path default/kbsres1/key1
```console
$ kubectl get secret trustee-tls-cert -n operators -o json | jq -r '.data."tls.crt"' | base64 --decode > https.crt
$ kubectl cp -n operators https.crt kbs-client:/
$ kubectl exec -it -n operators kbs-client -- kbs-client --cert-file https.crt --url https://kbs-service:8080 get-resource --path default/kbsres1/key1
cmVzMXZhbDE=
```

Expand All @@ -385,4 +385,4 @@ We’ll get *res1val1*, the secret we created before.

## Summary

In this blog we have shown how to use the Trustee operator for deploying Trustee and run the attestation workflow with a sample attester.
In this blog we have shown how to use the Trustee operator for deploying Trustee and run the attestation workflow with a sample attester.
2 changes: 1 addition & 1 deletion content/en/docs/attestation/client-tool/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ git clone https://github.com/confidential-containers/trustee.git
```

Build the client
```
```bash
cd kbs
make CLI_FEATURES=sample_only cli
sudo make install-cli
Expand Down
2 changes: 1 addition & 1 deletion content/en/docs/attestation/coco-setup/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ If you are using Trustee with Confidential Containers, you'll need to point
your CoCo workload to your Trustee.

In your pod definition, add the following annotation.
```bash
```yaml
io.katacontainers.config.hypervisor.kernel_params: "agent.aa_kbc_params=cc_kbc::http://<kbs-ip>:<kbs-port>"
```

Expand Down
4 changes: 2 additions & 2 deletions content/en/docs/attestation/installation/kubernetes.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ kubectl get pods -n operators --watch
```

The operator controller should be running.
```bash
```text
NAME READY STATUS RESTARTS AGE
trustee-operator-controller-manager-77cb448dc-7vxck 1/1 Running 0 11m
```
Expand Down Expand Up @@ -57,7 +57,7 @@ kubectl get pods -n operators --selector=app=kbs
```

The Trustee deployment should be running.
```bash
```text
NAME READY STATUS RESTARTS AGE
trustee-deployment-f97fb74d6-w5qsm 1/1 Running 0 25m
```
Expand Down
Loading