GCE logo

How to use SecretHub on GCE

This guide will show you how to provision an application running on Google Compute Engine with the secrets it needs.

Using the SecretHub GCP Identity Provider in combination, your app will be able to load secrets simply by taking on a GCP service account without having to deal with another key.

To make life easy, you can use the demo app from the Getting Started guide, but you can also follow along with your own app.

Before you begin

Before you start using SecretHub with GCE, make sure you have completed the following steps:

  1. Set up SecretHub on your workstation.
  2. Install gcloud with application credentials configured.

Depending on whether you’re following allong with Terraform or the CLI, set up the following:

Export your GCP project ID to your shell, so you can just copy-paste the commands in this guide later on:

export GCP_PROJECT_ID="demo-project-1234567890"

To follow this guide using Terraform, you need to declare the following variables:

variable "gcp_project_id" {
  description = "GCP project ID"
}

variable "gcp_zone" {
  description = "GCP zone to run Compute instance in"
}

variable "secrethub_repo" {
  description = "SecretHub repo that contains the demo `username` and `password` secrets"
}

Then, configure the following providers:

provider "google" {
  project = var.gcp_project_id
}

provider "secrethub" {
  credential = file("~/.secrethub/credential")
}

Step 1: Create a GCP service account

Start out by creating a GCP Service Account to attach to your Compute instance:

gcloud iam service-accounts create demo-app \
  --display-name="SecretHub demo app"

Take note of the service account email it generates, e.g. demo-app@demo-project-1234567890.iam.gserviceaccount.com:

gcloud iam service-accounts list \
  --filter="name:demo-app" \
  --format="value(email)"

Export the value to your shell, e.g.:

export GCP_SERVICE_ACCOUNT_EMAIL="demo-app@demo-project-1234567890.iam.gserviceaccount.com"
resource "google_service_account" "demo_app" {
  account_id  = "demo-app"
  description = "SecretHub demo app"
}

Step 2: Create a Cloud KMS key

For encryption and decryption of your secrets, you need to create a Cloud KMS key.

Start by creating a keyring:

gcloud kms keyrings create secrethub \
  --location="global"

Then, create a KMS key for your app:

gcloud kms keys create demo-app \
  --location="global" \
  --keyring="secrethub" \
  --purpose="encryption"

Lastly, make sure the GCP service account you created earlier has decryption rights on the KMS key:

gcloud kms keys add-iam-policy-binding demo-app \
  --location="global" \
  --keyring="secrethub" \
  --member="serviceAccount:${GCP_SERVICE_ACCOUNT_EMAIL}" \
  --role="roles/cloudkms.cryptoKeyDecrypter"
resource "google_kms_key_ring" "secrethub" {
  name     = "secrethub"
  location = "global"
}

resource "google_kms_crypto_key" "demo_app" {
  name     = "demo-app"
  key_ring = google_kms_key_ring.secrethub.id
}

resource "google_kms_crypto_key_iam_binding" "crypto_key" {
  crypto_key_id = google_kms_crypto_key.demo_app.id
  role          = "roles/cloudkms.cryptoKeyDecrypter"

  members = [
    "serviceAccount:${google_service_account.demo_app.email}",
  ]
}

Step 3: Create a SecretHub service account

With the KMS key and the GCP service account in place, you can now create a SecretHub service account:

secrethub service gcp init your-username/demo \
  --description demo-app \
  --service-account-email ${GCP_SERVICE_ACCOUNT_EMAIL} \
  --kms-key "projects/${GCP_PROJECT_ID}/locations/global/keyRings/secrethub/cryptoKeys/demo-app" \
  --permission read

The (optional) --permission read flag will grant the service read access to every secret in the repo. For more granular access, see the acl set command.

resource "secrethub_service_gcp" "demo_app" {
  repo                  = var.secrethub_repo
  service_account_email = google_service_account.demo_app.email
  kms_key_id            = google_kms_crypto_key.demo_app.id
}

resource "secrethub_access_rule" "demo_app" {
  account_name = secrethub_service_gcp.demo_app.id
  dir          = var.secrethub_repo
  permission   = "read"
}

Do note that to be able to run this, you need to have GCP credentials present with encryption rights on the KMS key you pass in.

After running it, you may have noticed that unlike the usual SecretHub service accounts, the SecretHub GCP service account does not output a credential.

That’s because apps running on GCP don’t need it anymore: as long they take on the specified service account on GCP, they can automatically load their secrets from SecretHub.


Step 4: Launch Compute instance

Now that everything is set up, it’s time to launch a Compute instance:

gcloud compute instances create secrethub-demo \
  --service-account="${GCP_SERVICE_ACCOUNT_EMAIL}" \
  --scopes="https://www.googleapis.com/auth/cloudkms"

Then, add a firewall rule to allow port 8080:

gcloud compute firewall-rules create allow-demo-app \
  --allow="tcp:8080" \
  --target-service-accounts="${GCP_SERVICE_ACCOUNT_EMAIL}"
resource "google_compute_instance" "demo_app" {
  name         = "secrethub-demo"
  machine_type = "n1-standard-1"
  zone         = var.gcp_zone

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-9"
    }
  }

  network_interface {
    network = google_compute_firewall.demo_app.network

    access_config {
      // Auto-assign IP
    }
  }

  service_account {
    email = google_service_account.demo_app.email
    scopes = ["https://www.googleapis.com/auth/cloudkms"]
  }

  depends_on = [
    secrethub_access_rule.demo_app,
  ]
}

resource "google_compute_firewall" "demo_app" {
  name    = "allow-demo-app"
  network = "default"

  allow {
    protocol = "tcp"
    ports    = ["8080"]
  }
}

output "public_ip" {
  value = google_compute_instance.demo_app.network_interface[0].access_config[0].nat_ip
}

Take note of the public IP to later see the end result. Your Compute instance should come online shortly.


Step 5: Run application on EC2

When the Compute Instance is up and running, connect to it:

gcloud compute ssh secrethub-demo

On the machine, install the SecretHub CLI for the appropriate OS.

By default, Compute instances run Debian, so you can use apt-get:

echo "deb [trusted=yes] https://apt.secrethub.io stable main" | sudo tee /etc/apt/sources.list.d/secrethub.sources.list && sudo apt-get update
sudo apt-get install -y secrethub-cli

Next, provision the app with secrets by referencing them in environment variables. They’ll automatically get replaced with the secret value when starting the app.

export DEMO_USERNAME=secrethub://your-username/demo/username
export DEMO_PASSWORD=secrethub://your-username/demo/password

Now, all that’s left is to run the app. Wrap the app start command in secrethub run:

secrethub run --identity-provider=gcp -- secrethub demo serve --host 0.0.0.0 --port 8080

And that’s it! As you can see, there’s no keyfile that needs to be deployed onto the Compute instance. Just set the --identity-provider flag to gcp.

CLI flags are configurable using environment variables as well, so setting SECRETHUB_IDENTITY_PROVIDER to gcp will also do the trick.

See if it all works by visiting http://<COMPUTE-INSTANCE-IP>:8080.

Screenshot of the demo app running
Demo app running

See also