Skip to content

Example: Reading and Updating a SCONE Policy

A SCONE policy defines

  • criteria to attest a service: e.g., the hash value of the service, the file system state, and the hosts that are permitted to execute the service.
  • secrets: types of secrets and how the values of the secrets are generated / retrieved.
  • secret release: the way how a secret is released to a service.

Deploy the CLI

We show how to create, read, and update a policy using the SCONE CLI. The SCONE CLI is deployed as part of a docker image:

export SCONE_CLI_IMAGE="registry.scontain.com:5050/sconecuratedimages/sconecli:alpine3.10"
docker pull $SCONE_CLI_IMAGE
docker run -it $SCONE_CLI_IMAGE

Attesting SCONE CAS

SCONE CAS attests services on startup and also provisions secrets to attested services. Before uploading a policy to a CAS instance, we need to attest this CAS instance runs inside of an enclave, runs the expected code, and the server running the CAS has an up-to-date firmware and microcode.

This attestation can be performed via the SCONE CLI. In this example, we use one of our public CAS instances. This public CAS instance runs in debug mode. Hence, attestation will fail - unless we set a few options to indicate that we are ok that we communicate with a CAS that executes in debug mode.

Command scone cas attest performs the attestation of the CAS:

export SCONE_CAS_ADDR=scone-cas.cf
scone cas attest "$SCONE_CAS_ADDR" --only_for_testing-debug  --only_for_testing-ignore-signer --only_for_testing-trust-any

Creating a SCONE policy

We create a policy, read the policy back, and then update the policy. Typically, sconify_image would create the namespace as well as the initial policy of a service. In some cases, we might need to change the namespace and/or the policy at some later point.

Let's first create a unique namespace for our example. We ensure that only we have access to this namespace and that only we can create policies in this namespace. Authorization is enforced with the help of a (random) public/private key pair. This key pair is referred to as CREATOR. This keypair is stored in file $HOME/.cas/config.json. If the public/private key pair does not exist, it is automatically generated by the SCONE CLI.

Let us create a policy for creating a new namespace. We use a random file namespace name by append a random number:

export SESSION_LANG_VERSION="0.3"
export NAMESPACE="MyNameSpace-$RANDOM"
cat > my_namespace.yml <<EOF
name: $NAMESPACE
version: "$SESSION_LANG_VERSION"

access_policy:
  read:
   - CREATOR
  update:
   - CREATOR
  create_sessions:
   - CREATOR
EOF

We can now create this namespace with command scone session create:

scone session create --cas "$SCONE_CAS_ADDR" --only_for_testing-disable-attestation-verification --use-env my_namespace.yml

Determining the ID of an existing policy

This policy is associated with a unique ID. The ID could be viewed similar to a git commit time stamp. This ID is needed when we want to update a session. The ID is printed when the policy / namespace is created. When this namespace/policy was created by sconify_image, we might not remember this ID.

To recover the ID of a policy, we can perform the following steps. First, we read and store the current policy that describes this namespace as follows (see scone session read):

scone session read  --cas "$SCONE_CAS_ADDR" $NAMESPACE  --only_for_testing-disable-attestation-verification > my_namespace_from_cas.yml

The session that we read, might be slightly different from the policy that we created. For example, it contains the public key of the creator. Given the current policy, we can determine the ID as follows (see scone session verify):

scone session verify  --cas "$SCONE_CAS_ADDR" -n $NAMESPACE  --only_for_testing-disable-attestation-verification my_namespace_from_cas.yml > namespace_id
export ID=$(cat namespace_id)

Updating the policy

When updating a policy, we need to set the predecessor field, i.e., we need to say which policy version to update (to ensure a linear history of policy updates). The policy that we read from CAS contains a field creator, this is the public key of the creator. We cannot change the creator's public key and hence, we replace that field. Technically, we can update the namespace / policy as follows:

sed "s/predecessor:.*/predecessor: $ID /; s/creator: .*/ /" my_namespace_from_cas.yml > new_namespace_policy.yml
cat >> new_namespace_policy.yml <<EOF

secrets:
    - name: my_generated_ascii_secret
      kind: ascii
      size: 12
EOF

The new namespace policy might look as follows:

---
version: "0.3"
name: MyNameSpace-26322
predecessor: 33f0d91c71e7dd582042565b7d1f2e71bf7c13a7ef08866e3e71274ab16cecfe 
access_policy:
  read:
    - CREATOR
  update:
    - CREATOR
  create_sessions:
    - CREATOR

secrets:
    - name: my_generated_ascii_secret
      kind: ascii
      size: 12

Linear History

Note that the field predecessor ensures that we do not overwrite any concurrent updates. In case of an concurrent update, the predecessor ID would be wrong and the update would fail. In this case, we would need to read the newest policy, determine the ID, and then update the policy.

Uploading the new policy

We can now upload the modified as follows (see scone session verify):

scone session update  --cas "$SCONE_CAS_ADDR"  --only_for_testing-disable-attestation-verification new_namespace_policy.yml

On success, the session update command will print the new ID of the updated policy.