This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Attestation

Trusted Components for Attestation and Secret Management

Trustee contains tools and components for attesting confidential guests and providing secrets to them. Collectively, these components are known as Trustee. Trustee typically operates on behalf of the “workload provider” / “data owner” and interacts remotely with guest components.

Trustee is developed for the Confidential Containers project, but can be used with a wide variety of applications and hardware platforms.

Architecture

Trustee is flexible and can be deployed in several different configurations. This figure shows one common way to deploy these components in conjunction with certain guest components.

flowchart LR
    AA -- attests guest ----> KBS
    CDH -- requests resource --> KBS
    subgraph Guest
        CDH <.-> AA
    end
    subgraph Trustee
        KBS -- validates evidence --> AS
        RVPS -- provides reference values--> AS
    end
    client-tool -- configures --> KBS

Legend

  • CDH: Confidential Data Hub
  • AA: Attestation Agent
  • KBS: Key Broker Service
  • RVPS: Reference Value Provider Service
  • AS: Attestation Service

1 - Key Broker Service (KBS)

This service facilitates remote attestation and secret delivery

The Confidential Containers Key Broker Service (KBS) facilitates remote attestation and secret delivery. The KBS is an implementation of a Relying Party from the Remote ATtestation ProcedureS (RATS) Architecture. The KBS itself does not validate attestation evidence. Instead, it relies on the Attestation-Service (AS) to verify TEE evidence.

In conjunction with the AS or Intel Trust Authority (ITA), the KBS supports the following TEEs:

  • AMD SEV-SNP
  • AMD SEV-SNP on Azure with vTPM
  • Intel TDX
  • Intel TDX on Azure with vTPM
  • Intel SGX
  • ARM CCA
  • Hygon CSV

Deployment Configurations

The KBS can be deployed in several different environments, including as part of a docker compose cluster, part of a Kubernetes cluster or without any containerization. Additionally, the KBS can interact with other attestation components in different ways. This section focuses on the different ways the KBS can interact with other components.

Background Check Mode

Background check mode is a more straightforward and simple way to configure the Key Broker Service (KBS) and Attestation-Service (AS). The term “Background Check” is from the RATS architecture. In background check mode, the KBS directly forwards the hardware evidence of a confidential guest to the AS to validate. Once the validation passes, the KBS will release secrets to the confidential guest.

flowchart LR
    AA -- attests guest --> KBS
    CDH -- requests resource ----> KBS
    subgraph Guest
        AA <.-> CDH
    end
    subgraph Trustee
        KBS -- validates evidence --> AS
    end

In background check mode, the KBS is the relying party and the AS is the verifier.

Passport Mode

Passport mode decouples the provisioning of resources from the validation of evidence. In background check mode these tasks are already handled by separate components, but in passport mode they are decoupled even more. The term “Passport” is from the RATS architecture.

In passport mode, there are two Key Broker Services (KBSes), one that uses a KBS to verify the evidence and a second to provision resources.

flowchart LR
    CDH -- requests resource ----> KBS2
    AA -- attests guest --> KBS1
    subgraph Guest
        CDH <.-> AA
    end
    subgraph Trustee 1
        KBS1 -- validates evidence --> AS
    end
    subgraph Trustee 2
        KBS2
    end

In the RATS passport model the client typically connects directly to the verifier to get an attestation token (a passport). In CoCo we do not support direct connections to the AS, so KBS1 serves as an intermediary. Together KBS1 and the AS represent the verifier. KBS2 is the relying party.

Passport mode is good for use cases when resource provisioning and attestation are handled by separate entities.

1.1 - KBS backed by AKV

This documentation describes how to mount secrets stored in Azure Key Vault into a KBS deployment

Premise

AKS

We assume an AKS cluster configured with Workload Identity and Key Vault Secrets Provider. The former provides a KBS pod with the privileges to access an Azure Key Vault (AKV) instance. The latter is an implementation of Kubernetes’ Secret Store CSI Driver, mapping secrets from external key vaults into pods. The guides below provide instructions on how to configure a cluster accordingly:

AKV

There should be an AKV instance that has been configured with role based access control (RBAC), containing two secrets named coco_one coco_two for the purpose of the example. Find out how to configure your instance for RBAC in the guide below.

Provide access to Key Vault keys, certificates, and secrets with an Azure role-based access control

Note: You might have to toggle between Access Policy and RBAC modes to create your secrets on the CLI or via the Portal if your user doesn’t have the necessary role assignments.

CoCo

While the steps describe a deployment of KBS, the configuration of a Confidential Containers environment is out of scope for this document. CoCo should be configured with KBS as a Key Broker Client (KBC) and the resulting KBS deployment should be available and configured for confidential pods.

Azure environment

Configure your Resource group, Subscription and AKS cluster name. Adjust accordingly:

export SUBSCRIPTION_ID="$(az account show --query id -o tsv)"
export RESOURCE_GROUP=my-group
export KEYVAULT_NAME=kbs-secrets
export CLUSTER_NAME=coco

Instructions

Create Identity

Create a User managed identity for KBS:

az identity create --name kbs -g "$RESOURCE_GROUP"
export KBS_CLIENT_ID="$(az identity show -g "$RESOURCE_GROUP" --name kbs --query clientId -o tsv)"
export KBS_TENANT_ID=$(az aks show --name "$CLUSTER_NAME" --resource-group "$RESOURCE_GROUP" --query identity.tenantId -o tsv)

Assign a role to access secrets:

export KEYVAULT_SCOPE=$(az keyvault show --name "$KEYVAULT_NAME" --query id -o tsv)
az role assignment create --role "Key Vault Administrator" --assignee "$KBS_CLIENT_ID" --scope "$KEYVAULT_SCOPE"

Namespace

By default KBS is deployed into a coco-tenant Namespace:

export NAMESPACE=coco-tenant
kubectl create namespace $NAMESPACE

KBS identity and Service Account

Workload Identity provides individual pods with IAM privileges to access Azure infrastructure resources. An azure identity is bridged to a Service Account using OIDC and Federated Credentials. Those are scoped to a Namespace, we assume we deploy the Service Account and KBS into the default Namespace, adjust accordingly if necessary.

export AKS_OIDC_ISSUER="$(az aks show --resource-group "$RESOURCE_GROUP" --name "$CLUSTER_NAME" --query "oidcIssuerProfile.issuerUrl" -o tsv)"
az identity federated-credential create \
 --name kbsfederatedidentity \
 --identity-name kbs \
 --resource-group "$RESOURCE_GROUP" \
 --issuer "$AKS_OIDC_ISSUER" \
 --subject "system:serviceaccount:${NAMESPACE}:kbs"

Create a Service Account object and annotate it with the identity’s client id.

cat <<EOF> service-account.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    azure.workload.identity/client-id: ${KBS_CLIENT_ID}
  name: kbs
  namespace: ${NAMESPACE}
EOF
kubectl apply -f service-account.yaml

Secret Provider Class

A Secret Provider Class specifies a set of secrets that should be made available to k8s workloads.

cat <<EOF> secret-provider-class.yaml
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: ${KEYVAULT_NAME}
  namespace: ${NAMESPACE}
spec:
  provider: azure
  parameters:
    usePodIdentity: "false"
    clientID: ${KBS_CLIENT_ID}
    keyvaultName: ${KEYVAULT_NAME}
    objects: |
      array:
      - |
        objectName: coco_one
        objectType: secret
      - |
        objectName: coco_two
        objectType: secret
    tenantId: ${KBS_TENANT_ID}
EOF
kubectl create -f secret-provider-class.yaml

Deploy KBS

The default KBS deployment needs to be extended with label annotations and CSI volume. The secrets are mounted into the storage hierarchy default/akv.

git clone https://github.com/confidential-containers/kbs.git
cd kbs
git checkout v0.8.2
cd kbs/config/kubernetes
mkdir akv
cat <<EOF> akv/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: coco-tenant

resources:
- ../base

patches:
- path: patch.yaml
  target:
    group: apps
    kind: Deployment
    name: kbs
    version: v1
EOF
cat <<EOF> akv/patch.yaml
- op: add
  path: /spec/template/metadata/labels/azure.workload.identity~1use
  value: "true"
- op: add
  path: /spec/template/spec/serviceAccountName
  value: kbs
- op: add
  path: /spec/template/spec/containers/0/volumeMounts/-
  value:
    name: secrets
    mountPath: /opt/confidential-containers/kbs/repository/default/akv
    readOnly: true
- op: add
  path: /spec/template/spec/volumes/-
  value:
    name: secrets
    csi:
      driver: secrets-store.csi.k8s.io
      readOnly: true
      volumeAttributes:
        secretProviderClass: ${KEYVAULT_NAME}
EOF
kubectl apply -k akv/

Test

The KBS pod should be running, the pod events should give indication of possible errors. From a confidential pod the AKV secrets should be retrievable via Confidential Data Hub:

$ kubectl exec -it deploy/nginx-coco -- curl http://127.0.0.1:8006/cdh/resource/default/akv/coco_one
a secret

2 - Attestation Service (AS)

This service verifies TEE evidence

The Attestation Service (AS or CoCo-AS) verifies hardware evidence. The AS was designed to be used with the Key Broker Service (KBS) for Confidential Containers, but it can be used in a wide variety of situations. The AS can be used anytime TEE evidence needs to be validated.

Today, the AS can validate evidence from the following TEEs:

  • Intel TDX
  • Intel SGX
  • AMD SEV-SNP
  • ARM CCA
  • Hygon CSV
  • Intel TDX with vTPM on Azure
  • AMD SEV-SNP with vTPM on Azure

Overview

                                                                                                   
                                                                                                   
                                         ┌───────────────────────────────────┐                     
   ┌───────────────────────┐ Evidence    │  Attestation Service              │                     
   │                       ├────────────►│                                   │                     
   │ Verification Demander │             │ ┌───────────┐┌──────────────────┐ │                     
   │    (Such as KBS)      │             │ │┌────────┐ ││ Reference Value  │◄┼────Reference Value  
   │                       │◄────────────┤ ││ Policy │ ││ Provider Service │ │                     
   └───────────────────────┘ Attestation │ ││ Engine │ │└──────────────────┘ │                     
                           Results Token │ │└────────┘ │                     │                     
                                         │ │Attestation│                     │                     
                                         │ │   Token   │  ┌────────────────┐ │                     
                                         │ │  Broker   │  │Verifier Drivers│ │                     
                                         │ └───────────┘  └────────────────┘ │                     
                                         └───────────────────────────────────┘                     

The Attestation Service (AS) has a simple API. It receives attestation evidence and returns an attestation token containing the results of a two-step verification process. The AS can be consumed directly as a Rust crate (library) or built as a standalone service, exposing a REST or gRPC API. In Confidential Containers, the client of the AS is the Key Broker Service (KBS), but the evidence originates from the Attestation Agent inside the guest.

The AS has a two-step verification process.

  1. Verify the format and provenance of evidence itself (e.g. check the signature of the evidence).
  2. Appraise the claims presented in the evidence (e.g. check that measurements match reference values).

The first step is accomplished by one of the platform-specific Verifier Drivers. The second step is driven by the Attestation Token Broker with help from the Reference Value Provider Service (RVPS).

2.1 - Quick Start

Quick Start to deploy the Attestation Service

For the latest deployment document, please refer to the CoCoAS github page.

The CoCoAS supports different APIs. Now we have gRPC version and RESTful version.

gRPC CoCo AS

Quick Start and Test

Users can use a community version of gRPC CoCoAS image to deploy quickly.

# run gRPC CoCoAS server locally
docker run -d \
  -v <path-to-attestation-service>/docs/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf \ # this qcnl config is used when verifying SGX/TDX quotes
  -p 50004:50004 \
  ghcr.io/confidential-containers/staged-images/coco-as-grpc:latest \
  grpc-as

The sgx_default_qcnl.conf configures the PCS (Provisioning Certification Service) / PCCS (Provisioning Certification Cache Service) of Intel platforms. If you want to verify SGX/TDX quotes, please refer to the Intel Platform Configuration section.

We can use a sample grpc client to test the gRPC API using the following test request body.

{
    "tee": "snp",
    "evidence": "eyJhdHRlc3RhdGlvbl9yZXBvcnQiOnsidmVyc2lvbiI6MiwiZ3Vlc3Rfc3ZuIjo0LCJwb2xpY3kiOjE5NjYzOSwiZmFtaWx5X2lkIjpbMSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sImltYWdlX2lkIjpbMiwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sInZtcGwiOjAsInNpZ19hbGdvIjoxLCJjdXJyZW50X3RjYiI6eyJib290bG9hZGVyIjozLCJ0ZWUiOjAsIl9yZXNlcnZlZCI6WzAsMCwwLDBdLCJzbnAiOjgsIm1pY3JvY29kZSI6MjA2fSwicGxhdF9pbmZvIjoxLCJfYXV0aG9yX2tleV9lbiI6MCwiX3Jlc2VydmVkXzAiOjAsInJlcG9ydF9kYXRhIjpbMjM2LDEwOCw4MiwyMTUsODMsNjAsMTk0LDE5NiwyNDQsOTEsMjMxLDEzMiwxNTYsMjQxLDE4LDE3MSwxMzAsMTc4LDAsMTU5LDIzMSwxODksNjcsMjMxLDMwLDIwOCwxNDAsMjAsNjQsMTAsMjE1LDIyNiwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJtZWFzdXJlbWVudCI6WzE2MSwyNDMsMTQ3LDQsMTksMzYsMTIzLDE3OSwxNDAsMjUyLDIzLDIxLDEyMSwyMzQsNjAsMTgsMjEzLDI1NCw3MywxLDI0MCwxOTksMTQ2LDI0Niw2MywyMTUsOTMsMTUyLDI0MSwyMzksMTMwLDEyNCwzNSw4MCw2LDY4LDIyNCwyMzAsMTQ2LDIzMCwxOTAsMTQ1LDEyNywxNDQsODAsMjExLDIxMSwxNDBdLCJob3N0X2RhdGEiOlswLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJpZF9rZXlfZGlnZXN0IjpbMyw4NiwzMyw4OCwxMzAsMTY4LDM3LDM5LDE1NCwxMzMsMTc5LDAsMTc2LDE4Myw2NiwxNDcsMjksMTcsNTksMjQ3LDIyNyw0NSwyMjIsNDYsODAsMjU1LDIyMiwxMjYsMTk5LDY3LDIwMiw3MywzMCwyMDUsMjE1LDI0Myw1NCwyMjAsNDAsMTY2LDIyNCwxNzgsMTg3LDg3LDE3NSwxMjIsNjgsMTYzXSwiYXV0aG9yX2tleV9kaWdlc3QiOlswLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sInJlcG9ydF9pZCI6WzU2LDk0LDE4NiwxMjksMzMsMTA5LDIyOCwxMTksMTAxLDcyLDI1MiwxODQsMTExLDE0MiwxNzMsMywxOTMsMjM1LDIwMSw0Myw5OCw3LDI0MywzMywxMywxNTYsMjA2LDE4NywxMzcsMjAxLDE0NCw1XSwicmVwb3J0X2lkX21hIjpbMjU1LDI1NSwyNTUsMjU1LDI1NSwyNTUsMjU1LDI1NSwyNTUsMjU1LDI1NSwyNTUsMjU1LDI1NSwyNTUsMjU1LDI1NSwyNTUsMjU1LDI1NSwyNTUsMjU1LDI1NSwyNTUsMjU1LDI1NSwyNTUsMjU1LDI1NSwyNTUsMjU1LDI1NV0sInJlcG9ydGVkX3RjYiI6eyJib290bG9hZGVyIjozLCJ0ZWUiOjAsIl9yZXNlcnZlZCI6WzAsMCwwLDBdLCJzbnAiOjgsIm1pY3JvY29kZSI6MTE1fSwiX3Jlc2VydmVkXzEiOlswLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sImNoaXBfaWQiOlsxOTUsMTMyLDM5LDE2MywxMyw3NiwxMjIsMjQ5LDIxNywxMTEsMTIyLDIxLDE4NSwxMTQsMTA1LDEzMCw5MCwxMDAsMjAzLDExOCwxNjIsNTMsNDcsMjUzLDkzLDI0LDE3LDkzLDEzNywxNzMsNzEsNjMsMTQyLDE0MCwxMSwyMDUsMTU0LDkzLDE0NiwxMzQsOTcsNDMsMTczLDc0LDE3MywyNTEsNjgsMzgsMzIsOTAsNTksMTU4LDc5LDIzNCwxMzAsNDgsMTcsNTMsMTYxLDExMiwyMjgsMTE5LDgyLDc4XSwiY29tbWl0dGVkX3RjYiI6eyJib290bG9hZGVyIjozLCJ0ZWUiOjAsIl9yZXNlcnZlZCI6WzAsMCwwLDBdLCJzbnAiOjgsIm1pY3JvY29kZSI6MTE1fSwiY3VycmVudF9idWlsZCI6NCwiY3VycmVudF9taW5vciI6NTIsImN1cnJlbnRfbWFqb3IiOjEsIl9yZXNlcnZlZF8yIjowLCJjb21taXR0ZWRfYnVpbGQiOjQsImNvbW1pdHRlZF9taW5vciI6NTIsImNvbW1pdHRlZF9tYWpvciI6MSwiX3Jlc2VydmVkXzMiOjAsImxhdW5jaF90Y2IiOnsiYm9vdGxvYWRlciI6MywidGVlIjowLCJfcmVzZXJ2ZWQiOlswLDAsMCwwXSwic25wIjo4LCJtaWNyb2NvZGUiOjExNX0sIl9yZXNlcnZlZF80IjpbMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJzaWduYXR1cmUiOnsiciI6WzYsMjM1LDIyMCw3OSw3OCw2NSw2NywyMDQsOTgsMjU0LDIxLDE4NSwyNDIsMjA5LDIzNiw0NSw4NCwyMTIsMTcxLDIzLDEwMiwxNTgsODEsNDAsMzQsMjIsMjIsOTQsMTc5LDI3LDk1LDg5LDIyNSw5OCwxLDE3MCwyMjAsMTY0LDI1MSwyMjAsMjE3LDY1LDI0MSw1MCwxMDQsNTcsOCw4MCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sInMiOls2NCw5OSwxMjAsMjEyLDI2LDM4LDk4LDYwLDkxLDE3MywxNTQsMTg0LDIwNiwxNTIsMjE0LDIwNSw0OSw2NywxNDQsNDMsMTQ1LDEwNywxOTksMTYzLDUyLDE4OCwyMDksMTA2LDEyOSwyMTQsMTk5LDIwLDE2MSw0OCw4NiwxNjcsMTQ2LDIwLDE4MSwxODgsODUsMTEyLDI0OSwxODEsMjAsOTMsMjA3LDIyOCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sIl9yZXNlcnZlZCI6WzAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF19fSwiY2VydF9jaGFpbiI6W3siY2VydF90eXBlIjoiVkNFSyIsImRhdGEiOls0OCwxMzAsNSw3Niw0OCwxMzAsMiwyNTEsMTYwLDMsMiwxLDIsMiwxLDAsNDgsNzAsNiw5LDQyLDEzNCw3MiwxMzQsMjQ3LDEzLDEsMSwxMCw0OCw1NywxNjAsMTUsNDgsMTMsNiw5LDk2LDEzNCw3MiwxLDEwMSwzLDQsMiwyLDUsMCwxNjEsMjgsNDgsMjYsNiw5LDQyLDEzNCw3MiwxMzQsMjQ3LDEzLDEsMSw4LDQ4LDEzLDYsOSw5NiwxMzQsNzIsMSwxMDEsMyw0LDIsMiw1LDAsMTYyLDMsMiwxLDQ4LDE2MywzLDIsMSwxLDQ4LDEyMyw0OSwyMCw0OCwxOCw2LDMsODUsNCwxMSwxMiwxMSw2OSwxMTAsMTAzLDEwNSwxMTAsMTAxLDEwMSwxMTQsMTA1LDExMCwxMDMsNDksMTEsNDgsOSw2LDMsODUsNCw2LDE5LDIsODUsODMsNDksMjAsNDgsMTgsNiwzLDg1LDQsNywxMiwxMSw4Myw5NywxMTAsMTE2LDk3LDMyLDY3LDEwOCw5NywxMTQsOTcsNDksMTEsNDgsOSw2LDMsODUsNCw4LDEyLDIsNjcsNjUsNDksMzEsNDgsMjksNiwzLDg1LDQsMTAsMTIsMjIsNjUsMTAwLDExOCw5NywxMTAsOTksMTAxLDEwMCwzMiw3NywxMDUsOTksMTE0LDExMSwzMiw2OCwxMDEsMTE4LDEwNSw5OSwxMDEsMTE1LDQ5LDE4LDQ4LDE2LDYsMyw4NSw0LDMsMTIsOSw4Myw2OSw4Niw0NSw3NywxMDUsMTA4LDk3LDExMCw0OCwzMCwyMywxMyw1MCw1MSw0OCw0OSw1MCw1Miw0OSw1NSw1Myw1Niw1MCw1NCw5MCwyMywxMyw1MSw0OCw0OCw0OSw1MCw1Miw0OSw1NSw1Myw1Niw1MCw1NCw5MCw0OCwxMjIsNDksMjAsNDgsMTgsNiwzLDg1LDQsMTEsMTIsMTEsNjksMTEwLDEwMywxMDUsMTEwLDEwMSwxMDEsMTE0LDEwNSwxMTAsMTAzLDQ5LDExLDQ4LDksNiwzLDg1LDQsNiwxOSwyLDg1LDgzLDQ5LDIwLDQ4LDE4LDYsMyw4NSw0LDcsMTIsMTEsODMsOTcsMTEwLDExNiw5NywzMiw2NywxMDgsOTcsMTE0LDk3LDQ5LDExLDQ4LDksNiwzLDg1LDQsOCwxMiwyLDY3LDY1LDQ5LDMxLDQ4LDI5LDYsMyw4NSw0LDEwLDEyLDIyLDY1LDEwMCwxMTgsOTcsMTEwLDk5LDEwMSwxMDAsMzIsNzcsMTA1LDk5LDExNCwxMTEsMzIsNjgsMTAxLDExOCwxMDUsOTksMTAxLDExNSw0OSwxNyw0OCwxNSw2LDMsODUsNCwzLDEyLDgsODMsNjksODYsNDUsODYsNjcsNjksNzUsNDgsMTE4LDQ4LDE2LDYsNyw0MiwxMzQsNzIsMjA2LDYxLDIsMSw2LDUsNDMsMTI5LDQsMCwzNCwzLDk4LDAsNCwxOTgsOTcsMTgxLDEwMSwxODcsMTY4LDEsMiwxODksMjIxLDY4LDE0NSwyMDEsMTQ4LDI4LDE3OSw0MiwyNywxMjUsMTgyLDEyOCwxOCwxMzAsMTMyLDE2LDE4MywyNTUsMTQwLDE3MywyNTMsMTEyLDIyOSw3MywxODMsOTEsMTIwLDE3OSwyMDUsMjE0LDkyLDIwNSwyMzUsMTY4LDEzNCwyMTAsMjM4LDE2MSwyMTIsMjksMTIsNjMsMjAsMTA4LDE0MiwxODksMjE0LDEzMiw4MiwyMDYsMTI2LDE5NSwxMiwxMDUsOSwxMDMsMTk1LDE1OCw5OCw3NiwxLDE1LDE1NiwxODIsNiwxMDYsMTI4LDQ5LDEwLDEzNSw4MywxMDYsMTQ4LDIzNSwxNzQsNDEsMTk0LDE3MCwyMTcsMTI4LDIyLDE5LDE1MSwxOSwzMSwxODcsNywxNjMsMTMwLDEsMjIsNDgsMTMwLDEsMTgsNDgsMTYsNiw5LDQzLDYsMSw0LDEsMTU2LDEyMCwxLDEsNCwzLDIsMSwwLDQ4LDIzLDYsOSw0Myw2LDEsNCwxLDE1NiwxMjAsMSwyLDQsMTAsMjIsOCw3NywxMDUsMTA4LDk3LDExMCw0NSw2Niw0OCw0OCwxNyw2LDEwLDQzLDYsMSw0LDEsMTU2LDEyMCwxLDMsMSw0LDMsMiwxLDMsNDgsMTcsNiwxMCw0Myw2LDEsNCwxLDE1NiwxMjAsMSwzLDIsNCwzLDIsMSwwLDQ4LDE3LDYsMTAsNDMsNiwxLDQsMSwxNTYsMTIwLDEsMyw0LDQsMywyLDEsMCw0OCwxNyw2LDEwLDQzLDYsMSw0LDEsMTU2LDEyMCwxLDMsNSw0LDMsMiwxLDAsNDgsMTcsNiwxMCw0Myw2LDEsNCwxLDE1NiwxMjAsMSwzLDYsNCwzLDIsMSwwLDQ4LDE3LDYsMTAsNDMsNiwxLDQsMSwxNTYsMTIwLDEsMyw3LDQsMywyLDEsMCw0OCwxNyw2LDEwLDQzLDYsMSw0LDEsMTU2LDEyMCwxLDMsMyw0LDMsMiwxLDgsNDgsMTcsNiwxMCw0Myw2LDEsNCwxLDE1NiwxMjAsMSwzLDgsNCwzLDIsMSwxMTUsNDgsNzcsNiw5LDQzLDYsMSw0LDEsMTU2LDEyMCwxLDQsNCw2NCwxOTUsMTMyLDM5LDE2MywxMyw3NiwxMjIsMjQ5LDIxNywxMTEsMTIyLDIxLDE4NSwxMTQsMTA1LDEzMCw5MCwxMDAsMjAzLDExOCwxNjIsNTMsNDcsMjUzLDkzLDI0LDE3LDkzLDEzNywxNzMsNzEsNjMsMTQyLDE0MCwxMSwyMDUsMTU0LDkzLDE0NiwxMzQsOTcsNDMsMTczLDc0LDE3MywyNTEsNjgsMzgsMzIsOTAsNTksMTU4LDc5LDIzNCwxMzAsNDgsMTcsNTMsMTYxLDExMiwyMjgsMTE5LDgyLDc4LDQ4LDcwLDYsOSw0MiwxMzQsNzIsMTM0LDI0NywxMywxLDEsMTAsNDgsNTcsMTYwLDE1LDQ4LDEzLDYsOSw5NiwxMzQsNzIsMSwxMDEsMyw0LDIsMiw1LDAsMTYxLDI4LDQ4LDI2LDYsOSw0MiwxMzQsNzIsMTM0LDI0NywxMywxLDEsOCw0OCwxMyw2LDksOTYsMTM0LDcyLDEsMTAxLDMsNCwyLDIsNSwwLDE2MiwzLDIsMSw0OCwxNjMsMywyLDEsMSwzLDEzMCwyLDEsMCwyLDEyOCwzOCwxNjIsMjQ3LDMxLDMsMSwxMDgsMjE1LDI1NSw5OCwzMCwxNDgsMjEzLDE2NiwxMzgsMjE5LDEzMiw1LDQwLDE3MCwyNDQsNDcsOTQsMTQsMTEyLDY4LDExNCw2OCwyNCwxMzgsNjQsMzMsNjEsMTcxLDMxLDEwNiw5LDIzMiw4OCw4MCw0NSw0MiwyMzksMjE3LDg5LDUwLDEzNSwxMzksMjI0LDc2LDExMCwxOCwxNzYsMTc5LDAsODIsMjQxLDEwOSw2LDIxNSw0NCwzNCwxMTMsNjksMTM0LDE1MSw1NiwxNjAsMzUsMTM5LDkzLDE5OSwyMywyNDUsOTYsMTgsMTE0LDEwLDEzMiwyMTAsNTQsMjAzLDE4LDEwOCwxNjksMTM2LDEzNSwxNTIsMjIyLDE1MiwyMywyMzUsMTg4LDEyOCwxMDQsMjE1LDMzLDI5LDI0OSwyMzgsMTIyLDEwMCwxNDcsMjksMTMyLDIyMywzMCwyNTEsMjEsMTQ4LDExMCwyNTAsNDcsODAsNDUsMTkxLDIzNiw1NywxMjMsMjMzLDI1MiwxOTIsMTA0LDAsMTM5LDc0LDEzOCwyMTcsODIsMjU0LDg3LDYwLDE1NiwxMCw5NSwxLDE0LDMwLDE0MiwxOTcsMzMsMTk2LDY4LDE0MiwxMzQsMTAzLDI0OSwyNDIsMTYzLDM3LDU3LDIzMCwxMTcsMTE5LDMwLDIwOCwxNzYsMjUwLDI0NSwxNywyMzUsMjUwLDE5MSwxNTYsMTIzLDMzLDU5LDI0Niw5LDEzOCwyMjMsODYsMjAwLDI0NCw1NCwzNCwzOCwxMzAsMjQ4LDQ1LDIyNSwxNTcsOTMsMTU3LDIyNCw0OCwyMjksNjcsNzEsODMsMTY3LDE0LDEzOSw1NywxNDgsMjI0LDkyLDg3LDIzNCwxNzQsMzksMTYyLDExMCwxNDIsMTUyLDcsMTE5LDIxNiw1NSw3MywxNzQsMTk1LDE4NywxODYsMTEwLDE3Niw2Myw2OSwxMTcsMTcwLDEyNSwyNDIsMTM1LDI1LDE3OCw4NCw5NSwyMiw0OSw5OCwyNTUsMjUzLDE1MiwxMTcsODMsNTYsNDgsMTY2LDIzNCwyMzIsMTQwLDQxLDk2LDIwOCwxMjYsMjE2LDI0MCwxMzIsNDAsMjA4LDE4Nyw3MywyNDYsMjA2LDU0LDYsODgsMzgsMjI3LDIxNywxNTYsMjA3LDI0MCw4NiwzMywxOCwyNTMsMTk1LDI1MSw0OSwxNDcsNzMsMjEyLDE2NSwxMCw0LDE0MywxMTQsMTM1LDE2NCwyMzAsMTQ5LDQzLDI1LDEwMCwyMzEsMzcsMjQsMTU1LDIzNSw1OCwxOTIsODksMTM4LDEwMCwyMTUsMTY0LDQsMjI3LDExNiwyMTEsNDUsMTE0LDkxLDEzOCwxOTQsMTYwLDIwLDgzLDU0LDE2LDE1Myw3OCwyMTksMTI3LDEwMCwyMDQsMTE2LDIyOSwyNDIsMywyMTYsMTM1LDIzMSwyLDQxLDE0Myw4OSwyMiwyNCw3Nyw4NSwxODQsODAsMyw3NiwxNjIsMTEsMTQ1LDU1LDU4LDQ3LDUwLDI0Myw1Nyw5NiwxNjgsMTI0LDE4OCw5NSwxNjIsMTIwLDgzLDE4MSwzMiwyMzcsMjA0LDEzOSwyNTUsMTg1LDIzMywxMjEsMjI3LDE3NywxNTMsMTcwLDE3NSwxNzEsODUsMjcsMjMwLDM0LDM5LDEzMiwxODQsNzUsMTk1LDE3LDYwLDQ2LDE2MiwxMzcsMzEsODcsMTcwLDE3NCwyMjAsNjMsMjUzLDQyLDIyOCwxNzEsMjQ3LDI0LDE3OSwxNTgsOTcsMzIsMTk5LDQxLDIzOCwxMTksMjQ3LDI0OSwyMTksMTUyLDIzMywxNjQsMTQ3LDI4LDE1LDI1MCwzMSwxMDksMTIsODQsMTAyLDIyNSwxMzgsMTg5LDE4OSwyMjMsMjIzLDYwLDE5MCwxMDQsMTg4LDEwNiwxMzcsMjE4LDIzLDIzOCw3LDI2LDIxNywxMTksMTI1LDE0MywzNyw1MCwyMjksMTQzLDI1MiwyMjMsMjMwLDc3LDExMSw2MiwxNSwxMDMsMzEsNTMsODAsMTU2LDIxNSw4NCwxNDMsNjQsNCw3MiwxMjQsMjU1LDI0LDE2NSwxLDU2LDExNywxMDMsMTksMTU4LDYxLDQ4LDczLDE0MCwyMjIsMjI5LDEzMCwxODksMzcsOTQsMjEwLDE1MiwxNDEsOTUsMjQ4LDIyMyw0NCwxNzcsMTI5LDcwLDQzLDkyLDIxNCw4MiwxNjAsMTgwLDEzNCwyMTcsMjEwLDE5NCw0MywyMTcsMTYzLDE0MiwxODIsMTQzLDE0MSwxNzEsMTgzLDIyNV19XX0",
    "policy_ids": []
}

and the protobuf definition file declared in API section

# Use the following cmdline to install grpcurl
# go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest

REQ=$(cat <path-to-request>)
grpcurl \
  -plaintext \
  -import-path <path-to-parent-directory-of-proto-file> \
  -proto <path-to-proto-file> \
  -d @ 127.0.0.1:50004 attestation.AttestationService/AttestationEvaluate <<EOF
$REQ
EOF

Then you can see a token looking like the following

{
  "attestationToken": "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJjdXN0b21pemVkX2NsYWltcyI6eyJ0ZXN0X2tleSI6InRlc3RfdmFsdWUifSwiZXZhbHVhdGlvbi1yZXBvcnRzIjpbeyJldmFsdWF0aW9uLXJlc3VsdCI6IntcImFsbG93XCI6dHJ1ZX0iLCJwb2xpY3ktaGFzaCI6ImMwZTc5Mjk2NzFmYjY3ODAzODdmNTQ3NjBkODRkNjVkMmNlOTYwOTNkZmIzM2VmZGEyMWY1ZWIwNWFmY2RhNzdiYmE0NDRjMDJjZDE3N2IyM2E1ZDM1MDcxNjcyNjE1NyIsInBvbGljeS1pZCI6ImRlZmF1bHQifV0sImV4cCI6MTcwMTY3Mjk2NSwiaXNzIjoiQ29Dby1BdHRlc3RhdGlvbi1TZXJ2aWNlIiwiandrIjp7ImFsZyI6IlJTMzg0IiwiZSI6IkFRQUIiLCJrdHkiOiJSU0EiLCJuIjoiMGhGUHdHNmdTSmJKV1NaTFR6SzRfVThHSWo5WVdYc3FZbDFjbUhveHlhQ05oQ3JCYVVUcW5KdHlPRVpMLVBDcWJBS2VXNGFCWnY1M3Zycm13OU41S2lHMHNOTVJOMUc1V2V2RTFNSEEzQU1qNlNlSWtwT1hzT01DNzJBNUZrZFIzRG1hM3dMaW5tZUVHYk9xZE5rN2IzMHdtWkRhVG13QTJJSjdnNVhPZk8zNTl6YWFLaDFRZDdPUXRkT2RfaV8tQlEzQlpEYnZ4R1ctWmRsdHVwWXBjRVQwWUZLSlE1NTdPSGtsOGMxT3BVdFc5ODlEQjM3d1BGTlRxM25oU3ZveDBwYWdDd3FwZ3JCYXVVUDBlOGlkX1VhSGFVZWlPd2tXc2UxdkdYQW55cFZqUlhhdERhS2dzbzZ5QjdGQ3pMUmRwM3JzWW1kd1lMaTdtMms3TkNPaE9RIn0sIm5iZiI6MTcwMTY3MjY2NSwidGNiLXN0YXR1cyI6eyJzZ3guYm9keS5hdHRyaWJ1dGVzLmZsYWdzIjoiMDcwMDAwMDAwMDAwMDAwMCIsInNneC5ib2R5LmF0dHJpYnV0ZXMueGZybSI6ImU3MDAwMDAwMDAwMDAwMDAiLCJzZ3guYm9keS5jb25maWdfaWQiOiIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCIsInNneC5ib2R5LmNvbmZpZ19zdm4iOiIwMDAwIiwic2d4LmJvZHkuY3B1X3N2biI6IjA2MDYwYzBjZmZmZjAwMDAwMDAwMDAwMDAwMDAwMDAwIiwic2d4LmJvZHkuaXN2X2V4dF9wcm9kX2lkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJzZ3guYm9keS5pc3ZfZmFtaWx5X2lkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJzZ3guYm9keS5pc3ZfcHJvZF9pZCI6IjAwMDAiLCJzZ3guYm9keS5pc3Zfc3ZuIjoiMDAwMCIsInNneC5ib2R5Lm1pc2Nfc2VsZWN0IjoiMDEwMDAwMDAiLCJzZ3guYm9keS5tcl9lbmNsYXZlIjoiOGYxNzNlNDYxM2ZmMDVjNTJhYWYwNDE2MmQyMzRlZGFlOGM5OTc3ZWFlNDdlYjIyOTlhZTE2YTU1MzAxMWM2OCIsInNneC5ib2R5Lm1yX3NpZ25lciI6IjgzZDcxOWU3N2RlYWNhMTQ3MGY2YmFmNjJhNGQ3NzQzMDNjODk5ZGI2OTAyMGY5YzcwZWUxZGZjMDhjN2NlOWUiLCJzZ3guYm9keS5yZXBvcnRfZGF0YSI6Ijc0NjU3Mzc0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwic2d4LmJvZHkucmVzZXJ2ZWQxIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwic2d4LmJvZHkucmVzZXJ2ZWQyIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCIsInNneC5ib2R5LnJlc2VydmVkMyI6IjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJzZ3guYm9keS5yZXNlcnZlZDQiOiIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJzZ3guaGVhZGVyLmF0dF9rZXlfZGF0YV8wIjoiMDAwMDAwMDAiLCJzZ3guaGVhZGVyLmF0dF9rZXlfdHlwZSI6IjAyMDAiLCJzZ3guaGVhZGVyLnBjZV9zdm4iOiIwZDAwIiwic2d4LmhlYWRlci5xZV9zdm4iOiIwODAwIiwic2d4LmhlYWRlci51c2VyX2RhdGEiOiJkY2NkZTliMzFjZTg4NjA1NDgxNzNiYjRhMmE1N2ExNjAwMDAwMDAwIiwic2d4LmhlYWRlci52ZW5kb3JfaWQiOiI5MzlhNzIzM2Y3OWM0Y2E5OTQwYTBkYjM5NTdmMDYwNyIsInNneC5oZWFkZXIudmVyc2lvbiI6IjAzMDAifX0.SG7TUxm0E3yZs7rozijScMJIZTY8WVPZN3Yxu2CsW8HFE6lDLymdTzc1XTVrYb97PpGc6oCLwuLax786XHLN250SY_IW5GmR5WKRcYSGSQtOnYfsY7AMX3hvpV3rHGjP0QWZo_ezUp9yIbnJNwSprmFTzcNZkr2YNr1KmwWU-LhGSVCyviQwgtnqnhmQGwH-nHCcmgk0F3su_hdoFXImCggSHStXECAJ0cNjpAuTCsSQvrB4g3lM-dMii-D6a58uB_TGuOVf8Yqj9Gi6PrdxvIJZc1LSDDgo9uYuavNzunU3S3TkA2ZLDK4HIB0zDWfOnS2ZTrjyRdu5ZkzoGVK_YQ"
}

API

The API of gRPC CoCo-AS is defined by the following proto file

syntax = "proto3";

package attestation;

message AttestationRequest {
    // TEE enum. Specify the evidence type
    string tee = 1;

    // Base64 encoded evidence. The alphabet is URL_SAFE_NO_PAD.
    // defined in https://datatracker.ietf.org/doc/html/rfc4648#section-5
    string evidence = 2;

    // Runtime Data used to check the binding relationship with report data in
    // Evidence
    oneof runtime_data {
        // Base64 encoded runtime data slice. The whole string will be base64
        // decoded. The result one will then be accumulated into a digest which
        // is used as the expected runtime data to check against the one inside
        // evidence.
        //
        // The alphabet is URL_SAFE_NO_PAD.
        // defined in https://datatracker.ietf.org/doc/html/rfc4648#section-5
        string raw_runtime_data = 3;

        // Runtime data in a JSON map. CoCoAS will rearrange each layer of the
        // data JSON object in dictionary order by key, then serialize and output
        // it into a compact string, and perform hash calculation on the whole
        // to check against the one inside evidence.
        //
        // After the verification, the structured runtime data field will be included
        // inside the token claims.
        string structured_runtime_data = 4;
    }

    // Init Data used to check the binding relationship with init data in
    // Evidence
    oneof init_data {
        // Base64 encoded init data slice. The whole string will be base64
        // decoded. The result one will then be accumulated into a digest which
        // is used as the expected init data to check against the one inside
        // evidence.
        //
        // The alphabet is URL_SAFE_NO_PAD.
        // defined in https://datatracker.ietf.org/doc/html/rfc4648#section-5
        string raw_init_data = 5;

        // Init data in a JSON map. CoCoAS will rearrange each layer of the
        // data JSON object in dictionary order by key, then serialize and output
        // it into a compact string, and perform hash calculation on the whole
        // to check against the one inside evidence.
        // 
        // After the verification, the structured init data field will be included
        // inside the token claims.
        string structured_init_data = 6;
    }

    // Hash algorithm used to calculate runtime data. Currently can be "sha256",
    // "sha384" or "sha512". If not specified, "sha384" will be selected.
    string runtime_data_hash_algorithm = 7;

    // Hash algorithm used to calculate init data. Currently can be "sha256",
    // "sha384" or "sha512". If not specified, "sha384" will be selected.
    string init_data_hash_algorithm = 8;

    // List of IDs of the policy used to check evidence. If not provided,
    // a "default" one will be used.
    repeated string policy_ids = 9;
}

message AttestationResponse {
    string attestation_token = 1;
}

message SetPolicyRequest {
    string policy_id = 1;
    string policy = 2;
}
message SetPolicyResponse {}

message ChallengeRequest {
    // ChallengeRequest uses HashMap to pass variables like:
    // tee, tee_params etc
    map<string, string> inner = 1;
}
message ChallengeResponse {
    string attestation_challenge = 1;
}

service AttestationService {
    rpc AttestationEvaluate(AttestationRequest) returns (AttestationResponse) {};
    rpc SetAttestationPolicy(SetPolicyRequest) returns (SetPolicyResponse) {};
    rpc GetAttestationChallenge(ChallengeRequest) returns (ChallengeResponse) {};
    // Get the GetPolicyRequest.user and GetPolicyRequest.tee specified Policy(.rego)
}

RESTful CoCoAS

Quick Start and Test

Users can use a community version of restful CoCoAS image to verify attestation reports.

# run restful CoCoAS server locally
docker run -d \
  -v <path-to-attestation-service>/docs/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf \ # this qcnl config is used when verifying SGX/TDX quotes
  -p 8080:8080 \
  ghcr.io/confidential-containers/staged-images/coco-as-restful:latest \
  restful-as

The sgx_default_qcnl.conf configures the PCS (Provisioning Certification Service) / PCCS (Provisioning Certification Cache Service) of Intel platforms. If you want to verify SGX/TDX quotes, please refer to the Intel Platform Configuration section.

We can use curl to test the RESTful API using the same request body declared in the gRPC part.

cd <path-to-attestation-service>
curl -k -X POST http://127.0.0.1:8080/attestation \
     -i \
     -H 'Content-Type: application/json' \
     -d @tests/coco-as/request.json

Then, a token will be retrieved as HTTP response body like

eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJjdXN0b21pemVkX2NsYWltcyI6eyJ0ZXN0X2tleSI6InRlc3RfdmFsdWUifSwiZXZhbHVhdGlvbi1yZXBvcnRzIjpbeyJldmFsdWF0aW9uLXJlc3VsdCI6IntcImFsbG93XCI6dHJ1ZX0iLCJwb2xpY3ktaGFzaCI6ImMwZTc5Mjk2NzFmYjY3ODAzODdmNTQ3NjBkODRkNjVkMmNlOTYwOTNkZmIzM2VmZGEyMWY1ZWIwNWFmY2RhNzdiYmE0NDRjMDJjZDE3N2IyM2E1ZDM1MDcxNjcyNjE1NyIsInBvbGljeS1pZCI6ImRlZmF1bHQifV0sImV4cCI6MTcwMTY3Mjk2NSwiaXNzIjoiQ29Dby1BdHRlc3RhdGlvbi1TZXJ2aWNlIiwiandrIjp7ImFsZyI6IlJTMzg0IiwiZSI6IkFRQUIiLCJrdHkiOiJSU0EiLCJuIjoiMGhGUHdHNmdTSmJKV1NaTFR6SzRfVThHSWo5WVdYc3FZbDFjbUhveHlhQ05oQ3JCYVVUcW5KdHlPRVpMLVBDcWJBS2VXNGFCWnY1M3Zycm13OU41S2lHMHNOTVJOMUc1V2V2RTFNSEEzQU1qNlNlSWtwT1hzT01DNzJBNUZrZFIzRG1hM3dMaW5tZUVHYk9xZE5rN2IzMHdtWkRhVG13QTJJSjdnNVhPZk8zNTl6YWFLaDFRZDdPUXRkT2RfaV8tQlEzQlpEYnZ4R1ctWmRsdHVwWXBjRVQwWUZLSlE1NTdPSGtsOGMxT3BVdFc5ODlEQjM3d1BGTlRxM25oU3ZveDBwYWdDd3FwZ3JCYXVVUDBlOGlkX1VhSGFVZWlPd2tXc2UxdkdYQW55cFZqUlhhdERhS2dzbzZ5QjdGQ3pMUmRwM3JzWW1kd1lMaTdtMms3TkNPaE9RIn0sIm5iZiI6MTcwMTY3MjY2NSwidGNiLXN0YXR1cyI6eyJzZ3guYm9keS5hdHRyaWJ1dGVzLmZsYWdzIjoiMDcwMDAwMDAwMDAwMDAwMCIsInNneC5ib2R5LmF0dHJpYnV0ZXMueGZybSI6ImU3MDAwMDAwMDAwMDAwMDAiLCJzZ3guYm9keS5jb25maWdfaWQiOiIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCIsInNneC5ib2R5LmNvbmZpZ19zdm4iOiIwMDAwIiwic2d4LmJvZHkuY3B1X3N2biI6IjA2MDYwYzBjZmZmZjAwMDAwMDAwMDAwMDAwMDAwMDAwIiwic2d4LmJvZHkuaXN2X2V4dF9wcm9kX2lkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJzZ3guYm9keS5pc3ZfZmFtaWx5X2lkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJzZ3guYm9keS5pc3ZfcHJvZF9pZCI6IjAwMDAiLCJzZ3guYm9keS5pc3Zfc3ZuIjoiMDAwMCIsInNneC5ib2R5Lm1pc2Nfc2VsZWN0IjoiMDEwMDAwMDAiLCJzZ3guYm9keS5tcl9lbmNsYXZlIjoiOGYxNzNlNDYxM2ZmMDVjNTJhYWYwNDE2MmQyMzRlZGFlOGM5OTc3ZWFlNDdlYjIyOTlhZTE2YTU1MzAxMWM2OCIsInNneC5ib2R5Lm1yX3NpZ25lciI6IjgzZDcxOWU3N2RlYWNhMTQ3MGY2YmFmNjJhNGQ3NzQzMDNjODk5ZGI2OTAyMGY5YzcwZWUxZGZjMDhjN2NlOWUiLCJzZ3guYm9keS5yZXBvcnRfZGF0YSI6Ijc0NjU3Mzc0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwic2d4LmJvZHkucmVzZXJ2ZWQxIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwic2d4LmJvZHkucmVzZXJ2ZWQyIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCIsInNneC5ib2R5LnJlc2VydmVkMyI6IjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJzZ3guYm9keS5yZXNlcnZlZDQiOiIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLCJzZ3guaGVhZGVyLmF0dF9rZXlfZGF0YV8wIjoiMDAwMDAwMDAiLCJzZ3guaGVhZGVyLmF0dF9rZXlfdHlwZSI6IjAyMDAiLCJzZ3guaGVhZGVyLnBjZV9zdm4iOiIwZDAwIiwic2d4LmhlYWRlci5xZV9zdm4iOiIwODAwIiwic2d4LmhlYWRlci51c2VyX2RhdGEiOiJkY2NkZTliMzFjZTg4NjA1NDgxNzNiYjRhMmE1N2ExNjAwMDAwMDAwIiwic2d4LmhlYWRlci52ZW5kb3JfaWQiOiI5MzlhNzIzM2Y3OWM0Y2E5OTQwYTBkYjM5NTdmMDYwNyIsInNneC5oZWFkZXIudmVyc2lvbiI6IjAzMDAifX0.SG7TUxm0E3yZs7rozijScMJIZTY8WVPZN3Yxu2CsW8HFE6lDLymdTzc1XTVrYb97PpGc6oCLwuLax786XHLN250SY_IW5GmR5WKRcYSGSQtOnYfsY7AMX3hvpV3rHGjP0QWZo_ezUp9yIbnJNwSprmFTzcNZkr2YNr1KmwWU-LhGSVCyviQwgtnqnhmQGwH-nHCcmgk0F3su_hdoFXImCggSHStXECAJ0cNjpAuTCsSQvrB4g3lM-dMii-D6a58uB_TGuOVf8Yqj9Gi6PrdxvIJZc1LSDDgo9uYuavNzunU3S3TkA2ZLDK4HIB0zDWfOnS2ZTrjyRdu5ZkzoGVK_YQ

API

RESTful CoCo-AS’s endpoints are as following:

  • /attestation: receives evidence verification request. The request POST payload is like
{
    "tee": "sgx", // tee type.
    "evidence": "YWFhCg==...", // base64 encoded evidence in URL SAFE NO PAD,
    "runtime_data": {           // `runtime_data` is optional. If given, the runtime data binding will
                                // be checked.
                                // The field `raw` and `structured` are exclusive.
        "raw": "YWFhCg==...",   // Base64 encoded runtime data slice. The whole string will be base64
                                // decoded. The result one will then be accumulated into a digest which
                                // is used as the expected runtime data to check against the one inside
                                // evidence.
                                //
                                // The alphabet is URL_SAFE_NO_PAD.
                                // defined in https://datatracker.ietf.org/doc/html/rfc4648#section-5
                                
        "structured": {}        // Runtime data in a JSON map. CoCoAS will rearrange each layer of the
                                // data JSON object in dictionary order by key, then serialize and output
                                // it into a compact string, and perform hash calculation on the whole
                                // to check against the one inside evidence. The hash algorithm is defined
                                // by `runtime_data_hash_algorithm`.
                                //
                                // After the verification, the structured runtime data field will be included
                                // inside the token claims.
    }, 
    "init_data": {              // `init_data` is optional. If given, the init data binding will
                                // be checked.
                                // The field `raw` and `structured` are exclusive.
        "raw": "YWFhCg==...",   // Base64 encoded init data slice. The whole string will be base64
                                // decoded. The result one will then be accumulated into a digest which
                                // is used as the expected init data to check against the one inside
                                // evidence. The hash algorithm is defined by `init_data_hash_algorithm`.
                                //
                                // The alphabet is URL_SAFE_NO_PAD.
                                // defined in https://datatracker.ietf.org/doc/html/rfc4648#section-5
                                
        "structured": {}        // Init data in a JSON map. CoCoAS will rearrange each layer of the
                                // data JSON object in dictionary order by key, then serialize and output
                                // it into a compact string, and perform hash calculation on the whole
                                // to check against the one inside evidence.
                                //
                                // After the verification, the structured init data field will be included
                                // inside the token claims.
    }, 
    "runtime_data_hash_algorithm": "sha384",// Hash algorithm used to calculate runtime data. Currently can be 
                                            // "sha256", "sha384" or "sha512". If not specified, "sha384" will be selected.
    "init_data_hash_algorithm": "sha384",   // Hash algorithm used to calculate init data. Currently can be 
                                            // "sha256", "sha384" or "sha512". If not specified, "sha384" will be selected.
    "policy_ids": ["default", "policy-1"]           // List of IDs of the policy used to check evidence. If
                                                    // not provided, a "default" one will be used.
}
  • /policy: receives policy setting request. The request POST payload is like
{
    "type": "rego",         // policy type
    "policy_id": "yyyyy",   // raw string of policy id
    "policy": "xxxxx"       // base64 encoded policy content
}

Launch Configuration

For both gRPC and RESTful version CoCoAS, you can use the -c parameter to specify the path of the configuration file.

The configuration file is a JSON file.

The following properties can be set globally, i.e. not under any configuration section:

Property Type Description Required Default
work_dir String The location for Attestation Service to store data. False Firstly try to read from ENV AS_WORK_DIR. If not any, use /opt/confidential-containers/attestation-service
rvps_config RVPSConfiguration RVPS configuration False -
attestation_token_broker AttestationTokeBroker Attestation result token configuration. False -

AttestationTokenBroker

Property Type Description Required Default
type String Type of token to issue (Ear or Simple) No Ear

When type field is set to Ear, the following extra properties can be set:

Property Type Description Required Default
duration_min Integer Duration of the attestation result token in minutes. No 5
issuer_name String Issure name of the attestation result token. No CoCo-Attestation-Service
developer_name String The developer name to be used as part of the Verifier ID in the EAR No https://confidentialcontainers.org
build_name String The build name to be used as part of the Verifier ID in the EAR No Automatically generated from Cargo package and AS version
profile_name String The Profile that describes the EAR token No tag:github.com,2024:confidential-containers/Trustee`
policy_dir String The path to the work directory that contains policies to provision the tokens. No /opt/confidential-containers/attestation-service/token/ear/policies
signer TokenSignerConfig Signing material of the attestation result token. No None

When type field is set to Simple, the following extra properties can be set:

Property Type Description Required Default
duration_min Integer Duration of the attestation result token in minutes. No 5
issuer_name String Issure name of the attestation result token. No CoCo-Attestation-Service
policy_dir String The path to the work directory that contains policies to provision the tokens. No /opt/confidential-containers/attestation-service/token//simple/policies
signer TokenSignerConfig Signing material of the attestation result token. No None
TokenSignerConfig

This section is optional. When omitted, a new RSA key pair is generated and used.

Property Type Description Required Default
key_path String RSA Key Pair file (PEM format) path. Yes -
cert_url String RSA Public Key certificate chain (PEM format) URL. No -
cert_path String RSA Public Key certificate chain (PEM format) file path. No -

RVPS Configuration

Property Type Description Required Default
type String It can be either BuiltIn (Built-In RVPS) or GrpcRemote (connect to a remote gRPC RVPS) No BuiltIn
BuiltIn RVPS

If type is set to BuiltIn, the following extra properties can be set

Property Type Description Required Default
store_type String The underlying storage type of RVPS. (LocalFs or LocalJson) No LocalFs
store_config JSON Map The optional configurations to the underlying storage. No Null

Different store_type will have different store_config items.

For LocalFs, the following properties can be set

Property Type Description Required Default
file_path String The path to the directory storing reference values No /opt/confidential-containers/attestation-service/reference_values

For LocalJson, the following properties can be set

Property Type Description Required Default
file_path String The path to the file that storing reference values No /opt/confidential-containers/attestation-service/reference_values.json
Remote RVPS

If type is set to GrpcRemote, the following extra properties can be set

Property Type Description Required Default
address String Remote address of the RVPS server No 127.0.0.1:50003

Configuration Examples

Running with a built-in RVPS:

{
    "work_dir": "/var/lib/attestation-service/",
    "policy_engine": "opa",
    "rvps_config": {
        "type": "BuiltIn",
        "store_type": "LocalFs",
        "store_config": {
            "file_path": "/var/lib/attestation-service/reference-values"
        }
    },
    "attestation_token_broker": {
        "type": "Ear",
        "duration_min": 5
    }
}

Running with a remote RVPS:

{
    "work_dir": "/var/lib/attestation-service/",
    "policy_engine": "opa",
    "rvps_config": {
        "type": "GrpcRemote",
        "address": "127.0.0.1:50003"
    },
    "attestation_token_broker": {
	"type": "Ear",
        "duration_min": 5
    }
}

Configurations for token signer

{
    "work_dir": "/var/lib/attestation-service/",
    "policy_engine": "opa",
    "rvps_config": {
        "type": "GrpcRemote",
        "address": "127.0.0.1:50003"
    },
    "attestation_token_broker": {
	"type": "Ear",
        "duration_min": 5,
        "issuer_name": "some-body",
        "signer": {
            "key_path": "/etc/coco-as/signer.key",
            "cert_url": "https://example.io/coco-as-certchain",
            "cert_path": "/etc/coco-as/signer.pub"
        }
    }
}

Backups

Intel Platform Configuration

A workable file which will directly connect to Intel’s PCS without caching is given.

{"collateral_service": "https://api.trustedservices.intel.com/sgx/certification/v4/"}

This can be used for test. Users are expected to set the file to connect to another available PCCS which keeps cache. PCCS are usually supported by cloud providers, you can find the steps to configure /etc/sgx_default_qcnl.conf for

3 - Reference Value Provider Service (RVPS)

This service manages reference values used to verify TEE evidence

Reference Value Provider Service (RVPS) is a component to receive software supply chain provenances / metadata, verify them and extract the reference values. All the reference values are stored inside RVPS. When Attestation Service (AS) queries specific software claims, RVPS will response with related reference values.

Architecture

RVPS contains the following components:

  • Pre-Processor: Pre-Processor contains a set of *wares (like middleware). These wares can process the input Message and then deliver it to the Extractors.

  • Extractors: Extractors has sub-modules to process different type of provenance. Each sub-module will consume the input Message, and then generate an output Reference Value.

  • Store: Store is a trait object, which can provide key-value like API. All verified reference values will be stored in the Store. When requested by Attestation Service (AS), related reference value will be provided.

Message Flow

The message flow of RVPS is like the following figure:

Message

A protocol helps to distribute provenance of binaries. It will be received and processed by RVPS, then RVPS will generate Reference Value if working correctly.

{
    "version": <VERSION-NUMBER-STRING>,
    "type": <TYPE-OF-THE-PROVENANCE-STRING>,
    "provenance": #provenance,
}
  • "version": This field is the version of this message, making extensibility possible.
  • "type": This field specifies the concrete type of the provenance the message carries.
  • "provenance": This field is the main content passed to RVPS. This field contains the payload to be decrypted by RVPS. The meaning of the provenance depends on the type and concrete Extractor which process this.

Trust Digests

It is the reference values really requested and used by Attestation Service to compare with the gathered evidence generated from HW TEE. They are usually digests. To avoid ambiguity, they are named trust digests rather than reference values.

4 - KBS Client Tool

Simple tool to test or configure Key Broker Service and Attestation Service

This is a simple client for the Key Broker Client (KBS) that facilitates testing of the KBS and other basic attestation flows.

You can run this tool inside of a TEE to make a request with real attestation evidence. You can also provide pre-existing evidence or use the sample attester as a fallback.

The client tool can also be used to provision the KBS/AS with resources and policies.