Hardening Witnesses with Confidential Computing

Adit SachdeAdit Sachde
4 min read

Witnesses verify that the verifiable logs they are observing maintain their append-only property and countersign verified checkpoints. Clients can use these countersigned checkpoints to protect themselves against split-views, an attack where a log presents inconsistent checkpoints to different clients.

Detecting witness private key misuse is a much harder problem than detecting private key misuse by log. Inclusion proofs, such as signed certificate timestamps, can be cross checked against the current state of the log, but witnesses do not store a history of the checkpoints they signed. To protect against private key material leaks, the armored witness project uses custom hardware.

Confidential computing makes it possible to provide similar guarantees for witnesses running in the cloud. The confidential witness project provides an implementation for running a witness on GCP with public audit proofs. A running witness can be found at buoyant-breeze.itko.dev with audit logs found in this repository.

What is confidential computing?

Confidential computing aims to provide a guarantee to a remote client that the server is running a specific version of software, relying on support from cloud hardware and software. In our case, GCP provides the Secure Space image.

This image uses AMD’s Secure Encrypted Virtualization technology to receive a signed attestation that it is isolated from the Compute Engine hypervisor and that it has not been tampered with. Next, it launches the container specified by the operator and injects an IAM token into the container with these attestations. The operator’s software can use this token with remote services to provide the remote service with details about the currently running version of software.

Confidential computing shifts the trust boundaries of traditional applications. Instead of simply assuming that the service operator is running a correct version of software, we can rely on attestations generated by AMD and GCP to know that the service operator is running the correct version of software. We still have to trust someone, but it is likely that we trust the operational practices of AMD and GCP more than we trust those of the witness operators.

Trust flow of a confidential witness

The confidential witness software runs within the secure space without any state. The private key material is generated by and stored in GCP’s Key Management Service, ensuring that the operator does not have a copy unbound by the access policies, and other state is stored in a Cloud Storage bucket, both of which are protected with a set of IAM rules.

  attribute_condition = 
    'STABLE' in assertion.submods.confidential_space.support_attributes &&
    assertion.swname=='CONFIDENTIAL_SPACE' &&
    assertion.submods.container.image_reference=='${var.shasum}' &&
    assertion.submods.gce.project_id=='${var.project_id}' &&
    assertion.submods.container.env.WITNESS_KEY=='${local.witness_key}' &&
    assertion.submods.container.env.WITNESS_NAME=='${local.witness_name}' &&
    assertion.submods.container.env.WITNESS_AUDIENCE=='${local.witness_audience}' &&
    '${google_service_account.witness_compute_engine.email}' in assertion.google_service_accounts

One of the attributes provided in the IAM token is the hash of the container image. This attribute allows us to strongly link the image to a specific Github Actions workflow and the specific hash of the upstream confidential witness repository using Cosign. We can now audit the source code that went into building the container, providing an opportunity to ensure that there is nothing in the source that will allow the witness to maliciously sign checkpoints.

On the other side, we also need to make sure that the IAM rules for the cloud storage bucket and KMS are set up correctly to only accept requests from a container running an image with a hash that is known to be good.

Here, we rely on a Github actions workflow that calls the GCP APIs to fetch audit logs and configuration information, and then publish the data to a git repository. By using Github Actions instead of relying on the operator to publish the information, we can ensure that the data has not been tampered with prior to publishing.

Putting it all together

Let’s walk through using these tools to verify the source of the Buoyant Breeze witness.

1. Look at the audit logs to find what version of software is allowed to access the private key for the witness stored in GCP’s Key Management Service.

ghcr.io/aditsachde/confidential-witness@sha256:b634433ac01a0f43c05bbeb257044b990fee51a3128a5a5310192a5bddc9bc2d

2. Use the github cli to verify the attestation. Here, we can also specify the source commit, which can be looked up at https://github.com/aditsachde/confidential-witness/attestations.

gh attestation verify oci://ghcr.io/aditsachde/confidential-witness@sha256:b634433ac01a0f43c05bbeb257044b990fee51a3128a5a5310192a5bddc9bc2d --repo aditsachde/confidential-witness --source-digest 5b89c70e59060b51763219e8315cd9c2b4c45f1c

3. Audit the source code to ensure that this container will only sign properly verified checkpoints.

4. Use the audit logs to verify that the operator has configured everything in the project correctly and to our expectations, so that there are no other principals authorized to access private key material.

Confidential Witness

The confidential witness project provides an implementation of this concept, adapting omniwitness to run in a GCP confidential space with publicly published audit logs. The implementation is still a prototype, and not yet ready for production, but shows how these tools can be applied to the witness ecosystem. Interested in running your own witness or getting involved in the project? Join the community on the transparency.dev Slack!

0
Subscribe to my newsletter

Read articles from Adit Sachde directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Adit Sachde
Adit Sachde