Fetching secrets using the Anjuna Policy Manager

In this guide, you will learn how to securely deliver secrets to an Anjuna Confidential Container using the Anjuna Policy Manager.

For example, an application running as an Anjuna Confidential Container might need a private key and a certificate to prove its identity to client applications. The Anjuna Confidential Container will authenticate itself to the Anjuna Policy Manager using its unique and unforgeable attestation report, and then fetch secrets and inject them into the application as environment variables or files.

Prerequisites

You will need a running instance of the Anjuna Policy Manager (APM).

Follow the quickstart documentation here, including deploying the APM Server and configuring the CLI: Anjuna Policy Manager: Deploy Quickstart.

Configuring the Anjuna Confidential Container

To configure an Anjuna Confidential Container to fetch secrets from the APM, add the following to your enclave configuration file:

apmConfig:
  url: https://apm.anjuna.com:8200  # Replace with your APM server's IP address
  caCert: |
    -----BEGIN CERTIFICATE-----
    ... APM's certificate content ...
    -----END CERTIFICATE-----
  envs:
  - apmPath: credentials/example_api_key_path
    engine: anjuna
    name: EXAMPLE_API_KEY

With this configuration, the Anjuna Confidential Container will generate an attestation report, authenticate to the Anjuna Policy Manager, and fetch the secret located at credentials/example_api_key_path. The secret will be made available to the container application as the environment variable EXAMPLE_API_KEY.

A similar configuration is possible to support secret files. The following configuration makes a file available to the container at the path .ssh/authorized_keys.

apmConfig:
  url: https://apm.anjuna.com:8200  # Replace with your APM server's IP address
  caCert: |
    -----BEGIN CERTIFICATE-----
    ... APM's certificate content ...
    -----END CERTIFICATE-----
  files:
  - apmPath: credentials/example_path
    engine: anjuna
    path:  .ssh/authorized_keys
See Configuration reference: apmConfig for reference material on the apmConfig block, including TLS configuration.

Once you have added the apmConfig block to your configuration file, you can build a new Anjuna Confidential Container image using anjuna-azure-cli disk create --config <file>.

Configuring the Anjuna Policy Manager secrets and policies

Full example

This section assumes you have completed deploying the APM following Anjuna Policy Manager: Deploy Quickstart.

It also assumes you have completed the Quickstart guide for the Anjuna Confidential Container and have the necessary cloud resources to upload a disk and run an instance.

Configuring the CLI

First, set local environment variables so that you can reach the APM.

$ export ANJUNA_ADDR="https://<anjuna policy manager server hostname or IP address>:8200"
$ export ANJUNA_TOKEN="<anjuna policy manager token>"
$ export ANJUNA_CACERT="<path to ca cert file, PEM-encoded>"
$ export APM_GROUP_NAME="<resource group name of APM>"
In the apm-secure-deployments scripts, these variables are automatically exported by client_env.sh. The manual steps above are only necessary if you deploy the APM in a different way.

Building an Anjuna Confidential Container to fetch secrets from the APM

Create the file config.yaml, which will store the enclave configuration:

version: 1.7

apmConfig:
  url: https://apm.anjuna.com:8200  # Replace with your APM server's IP address
  caCert: |
    -----BEGIN CERTIFICATE-----
    ... APM's certificate content ...
    -----END CERTIFICATE-----
  envs:
  - apmPath: credentials/example_api_key_path
    engine: anjuna
    name: EXAMPLE_API_KEY

command: ["printenv"]

Now you can build and upload a disk image for the Anjuna Confidential Container. This is a basic container which prints its environment variables and exits.

$ anjuna-azure-cli disk create  \
  --docker-uri=debian:buster-slim  \
  --disk-size 1G  \
  --config=config.yaml \
  --save-measurements measurements.json

$ anjuna-azure-cli disk upload \
  --disk disk.vhd \
  --image-name apm-quickstart-client-disk.vhd \
  --storage-account ${STORAGE_ACCOUNT_NAME} \
  --storage-container mystoragecontainer \
  --resource-group myResourceGroup \
  --image-gallery myGallery \
  --image-definition myFirstDefinition \
  --image-version 0.1.1 \
  --location eastus \
  --subscription-id ${MY_AZURE_SUBSCRIPTION}

The output will include the Enclave ID and Signer ID measurements, which are 64-digit hexadecimal strings. You will use these measurements to set policies later.

Adding a secret

Then, you can create a secret using the APM CLI:

$ anjuna-policy-manager secret create \
    credentials/example_api_key_path  \
    --value "my-secret-api-key-136d4813"

See Creating secrets for instructions on providing secret content via a file, or having the APM generate a random secret.

Configuring an access policy

Using the measurements you got in the disk create output, you can authorize the Anjuna Confidential Container to have access to the secret you just created.

$ export SIGNER_ID="$(jq -r .SignerID measurements.json)"
$ export ENCLAVE_ID="$(jq -r .EnclaveID measurements.json)"
$ anjuna-policy-manager authorize enclave \
      --signer "${SIGNER_ID#0x}" \
      --enclave "${ENCLAVE_ID#0x}" \
      credentials/example_api_key_path

See Defining access policies for more details on restricting access to secrets.

Running the Anjuna Confidential Container

Now you can configure an access rule to allow your enclave to reach APM and run the instance with:

$ export CLIENT_PUBLIC_IP="$(az network public-ip show -n myPublicIP -g myResourceGroup | jq -r .ipAddress)"
$ az network nsg rule create \
  --resource-group ${APM_GROUP_NAME} \
  --nsg-name apm-nsg-${APM_GROUP_NAME#"apm-"} \
  --name allow-client \
  --protocol Tcp \
  --direction Inbound \
  --priority 1001 \
  --source-address-prefix "${CLIENT_PUBLIC_IP}" \
  --source-port-range '*' \
  --destination-address-prefix '*' \
  --destination-port-range 8200 \
  --access Allow

$ anjuna-azure-cli instance create \
  --name anjuna-azure-apm-quickstart-client-instance \
  --location eastus \
  --image-gallery myGallery \
  --image-definition myFirstDefinition \
  --image-version 0.1.1 \
  --resource-group myResourceGroup \
  --storage-account ${STORAGE_ACCOUNT_NAME} \
  --nics myNic

Once the instance is running, you should be able to view its logs using the Anjuna CLI:

$ anjuna-azure-cli instance log --tail  \
  --name anjuna-azure-apm-quickstart-client-instance  \
  --resource-group myResourceGroup
Checking if the resource group myResourceGroup exists...
Tailing boot log, press CTRL-C to exit..

...

ANJ-ENCLAVE: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ANJ-ENCLAVE: HOME=/root
ANJ-ENCLAVE: EXAMPLE_API_KEY=my-secret-api-key-136d4813

You should see the secret value in the output, available to the application as an environment variable.