Set up required cloud resources

This guide will proceed step by step, with conceptual explanations for each step. For a single script containing all the commands, see Appendix: full scripts.

Set environment variables

There are several settings that are defined using environment variables. These values determine the names of GCP resources and must be unique for the GCP account, project, or VPC (depending on the resource).

Some GCP resource names persist even when deleted, such as KMS keyring and key names. For this reason, change the value of the following PREFIX environment variable to be unique among executions of this deployment guide. The default value anjuna can be used only once per GCP account.

Run the following command to set the PREFIX environment variable used by additional environment variable settings below. Be sure to change this value to a new, unique value for subsequent executions of this guide.

# If you change this value, it should be alphanumeric only,
# with no spaces, dashes, underscores, or other characters
$ export PREFIX="anjuna"

Next, define the GCP project name, region, and zone that you are using for deployment. Set the following:

  • GCP_PROJECT environment variable to the name of your project

  • GCP_REGION to the region

  • GCP_ZONE to the zone

The following example commands set the project to the PREFIX defined in the previous step followed by -apm-project, the region to us-central1, and the zone to us-central1-a:

$ export GCP_PROJECT="${PREFIX}-apm-project"
$ export GCP_REGION="us-central1"
$ export GCP_ZONE="us-central1-a"

The following commands define additional values used for the names of various resources that will be created in the subsequent sections of this guide. You may change them according to your preferences.

$ export NETWORK_NAME="${PREFIX}-apm-network"
$ export SUBNET_NAME="${NETWORK_NAME}-subnet"

$ export SERVICE_ACCOUNT_NAME="${PREFIX}-apm-sa"
$ export SERVICE_ACCOUNT_DESCR="Anjuna Policy Manager Server"
$ export SERVICE_ACCOUNT_EMAIL="${SERVICE_ACCOUNT_NAME}@${GCP_PROJECT}.iam.gserviceaccount.com"

$ export ATTESTATION_ROLE_NAME="${PREFIX}_attestation_role"

$ export KMS_LOCATION="global"
$ export KMS_KEYRING="${PREFIX}-apm-keyring"
$ export KMS_KEY="${PREFIX}-apm-key"

$ export APM_SERVER_BUCKET="${PREFIX}-apm-server"
$ export APM_SERVER_IMAGE="${PREFIX}-apm-server-image"
$ export APM_SERVER_INSTANCE="${PREFIX}-apm-server-instance"
$ export APM_SERVER_STORAGE="${PREFIX}-apm-storage"
$ export APM_SERVER_TLS_KEY_SECRET="${PREFIX}-apm-tls-key"
$ export APM_SERVER_TLS_CERT_SECRET="${PREFIX}-apm-tls-cert"

Virtual Private Cloud network

Instances must be deployed in a Virtual Private Cloud (VPC) network. In this tutorial, you will create a new VPC network. If you have an existing one, you may use it as well.

To create a VPC network, run the following commands:

$ gcloud compute networks create \
    "${NETWORK_NAME}" \
    --subnet-mode "custom"
$ gcloud compute networks subnets create \
    "${SUBNET_NAME}" \
    --network ${NETWORK_NAME} \
    --range "10.128.0.0/20" \
    --region ${GCP_REGION}

Then, create firewall rules to allow default access between instances on the network.

# Allow any TCP and ICMP within the VPC
$ gcloud compute firewall-rules create \
    "${NETWORK_NAME}-allow-internal" \
    --network "${NETWORK_NAME}" \
    --allow tcp,icmp \
    --source-ranges "10.128.0.0/20"

# Allow TCP port 8200 from anywhere
$ gcloud compute firewall-rules create \
    "${NETWORK_NAME}-firewall-apm" \
    --network "${NETWORK_NAME}" \
    --allow tcp:8200 \
    --source-ranges "0.0.0.0/0"

Service account for the Anjuna Policy Manager

The Anjuna Policy Manager (APM) will access various GCP services. Authorization requires a service account, which will be associated with the APM Server instance.

Run the following command to create the service account:

$ gcloud iam service-accounts create \
    "${SERVICE_ACCOUNT_NAME}" \
    --description "${SERVICE_ACCOUNT_DESCR}"
Anyone with access to the service account will be able to access sensitive data used by the APM, including secrets and the TLS key and certificate. See Google Cloud’s Best practices for using service accounts to restrict usage.

Logging

Using Google Cloud Logging for improved performance and more granular access control is recommended. For more information, see Controlling log access with service accounts.

Run the following command to grant write access for logging:

$ gcloud projects add-iam-policy-binding \
    "${GCP_PROJECT}" \
    --member="serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
    --role="roles/logging.logWriter"

Attestation

In order to verify attestation reports from client enclaves, the APM needs access to the GCP API call getShieldedInstanceIdentity.

To grant access to this API call, create an IAM role and bind it to the service account with the following commands:

$ gcloud iam roles create \
    "${ATTESTATION_ROLE_NAME}" \
    --project "${GCP_PROJECT}" \
    --title "Anjuna Attestation Role" \
    --permissions "compute.instances.getShieldedInstanceIdentity"
$ gcloud projects add-iam-policy-binding \
    "${GCP_PROJECT}" \
    --member "serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
    --role "projects/${GCP_PROJECT}/roles/${ATTESTATION_ROLE_NAME}"

Cloud Storage Bucket for persistent storage

The APM uses Google Cloud Storage as a persistent storage backend. This ensures that secrets are not lost if the APM instance is deleted.

Data stored in Google Cloud Storage is encrypted in-transit and at-rest, but anyone with Google Cloud access to the KMS key and bucket will be able to decrypt and read it. So, only grant read and write permissions for the APM service account to access the bucket.

The following commands create a storage bucket for the APM storage backend and grant access to the service account:

$ gcloud storage buckets create \
    "gs://${APM_SERVER_STORAGE}" \
    --location "${GCP_REGION}"
$ gcloud storage buckets add-iam-policy-binding \
    "gs://${APM_SERVER_STORAGE}" \
    --member "serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
    --role=roles/storage.objectAdmin

TLS configuration

A TLS certificate is used so that clients can verify the authenticity of the APM. The certificate and certificate private key are stored in the Google Cloud Secret Manager for access by the APM Server.

Server hostname

The hostname is a part of the TLS certificate. This means that clients must access the APM using the same hostname, or the TLS certificate verification will fail. Clients of the APM include the administration computer and any client enclaves.

If you have obtained a fully-qualified domain name (FQDN) for your APM Server like anjuna-policy-manager.example.com, run the following command replacing <fully-qualified domain name> with the full domain name of the server:

export APM_SERVER_HOST="<fully-qualified domain name>"

If you do not have a fully-qualified domain name, then you can use the Internal DNS feature of GCP. When a VM instance is created, it is automatically assigned a local DNS host name based on the instance name, GCP zone, and project.

The internal DNS name of the APM server is automatically available to clients only within the same GCP VPC Network. Therefore, when using this feature, client enclaves should be deployed on the same VPC network.

To use the Internal DNS name, run the following command instead:

$ export APM_SERVER_HOST="${APM_SERVER_INSTANCE}.${GCP_ZONE}.c.${GCP_PROJECT}.internal"

TLS key and certificate

Create a TLS certificate and private key, and sign the certificate with your organization’s certificate authority (CA) for production. You should use the value of the APM_SERVER_HOST environment variable that you assigned in the Server hostname section. To view the value of this variable, run the following command:

$ echo "${APM_SERVER_HOST}"
If you do not have a TLS certificate already, you can generate a self-signed certificate for development purposes. However, this is not recommended in production environments. See Generate a self-signed certificate for instructions.

Upload TLS key and certificate to Google Cloud Secret Manager

The following commands will store the private key and certificate in Google Cloud Secret Manager and grant access to the APM service account. These commands assume that the TLS key and certificate are named tls-key.pem and tls-cert.pem respectively:

$ gcloud secrets create \
    "${APM_SERVER_TLS_KEY_SECRET}" \
    --data-file "tls-key.pem"
$ gcloud secrets create \
    "${APM_SERVER_TLS_CERT_SECRET}" \
    --data-file "tls-cert.pem"
$ gcloud secrets add-iam-policy-binding \
    "${APM_SERVER_TLS_KEY_SECRET}" \
    --member "serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
    --role "roles/secretmanager.secretAccessor"
$ gcloud secrets add-iam-policy-binding \
    "${APM_SERVER_TLS_CERT_SECRET}" \
    --member "serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
    --role="roles/secretmanager.secretAccessor"

Auto-unseal

The APM Server provides a way to auto-unseal the encrypted storage backend using a GCP KMS key bound to the service account of the APM. With this feature, the server is accessible upon enclave boot without having to manually unseal the encrypted storage.

The following commands create a KMS keyring and key for auto-unsealing and grant required permissions to the service account:

$ gcloud kms keyrings create \
    ${KMS_KEYRING} \
    --location "${KMS_LOCATION}"
$ gcloud kms keys create \
    ${KMS_KEY} \
    --keyring "${KMS_KEYRING}" \
    --location "${KMS_LOCATION}" \
    --purpose "encryption"
$ gcloud kms keys add-iam-policy-binding \
    ${KMS_KEY} \
    --keyring "${KMS_KEYRING}" \
    --location "${KMS_LOCATION}" \
    --member "serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
    --role "roles/cloudkms.cryptoKeyEncrypterDecrypter"