Deploy an App to Google Cloud
Platform:
So you’ve seen the demo app in action on your local workstation. That’s great, but to truly experience the value of secrets management you’ll want to actually deploy something.
After doing so, you should be able to apply these concepts in the real world and add automatic secrets provisioning to your own production applications.
Let’s see what’s necessary to take it to the next level:
- Install binary on the host
- Create a service account
- Set access rules
- Pick a mechanism for loading secrets
- T-minus 3, 2, 1… 🚀
Step 1: Install binary on the host
To get the secrets, your app has to be able to authenticate to the SecretHub server and decrypt the requested secrets.
Because we don’t want you to modify all your application code for this, we’ve made sure that your codebase doesn’t need to know anything about SecretHub. Instead, you’ll use the CLI to load the secrets for you.
Install the CLI on the host that is running the app. It’s the same piece of software you’ve installed already on your workstation!
Docker
If you’re using Docker, you can just add the SecretHub CLI to the Docker image. This way, your apps don’t have to rely on orchestrator-level injection mechanisms and they run consistently from dev to prod, regardless of the ecosystem they’re launched in.
Furthermore, your secrets are no longer visible with kubectl describe
and docker inspect
.
In your Dockerfile, you can put any of the installation commands as a RUN
statement.
Kubernetes / GKE
If you’re on Kubernetes and prefer to not include the CLI in your image, you can also use the SecretHub Mutating Webhook to automatically mount the binary onto a volume.
Linux
You can install the CLI from our Alpine repository using this one-liner:
apk add --repository https://alpine.secrethub.io/alpine/edge/main --allow-untrusted secrethub-cli
To install the CLI with apt-get
, add the SecretHub repository to your sources.list
:
echo "deb [trusted=yes] https://apt.secrethub.io stable main" > /etc/apt/sources.list.d/secrethub.sources.list && apt-get update
Then, use apt-get install
to install the CLI:
apt-get install -y secrethub-cli
Shorthand
You can also use this one-liner instead:
curl https://apt.secrethub.io | bash
To install the CLI using yum
, first add the SecretHub repo to your /etc/yum/repos.d
:
curl https://yum.secrethub.io/secrethub.repo -o /etc/yum/repos.d/secrethub.repo --create-dirs
Then, install the CLI like any other yum
package:
yum install secrethub-cli
Shorthand
You can also use this one-liner instead:
curl https://yum.secrethub.io | bash
Or you can link to the GitHub release directly, but you won’t be able to automatically yum update
later on:
yum install https://github.com/secrethub/secrethub-cli/releases/download/v0.41.2/secrethub-v0.41.2-linux-amd64.rpm
To install the CLI on Debian/Ubuntu, download the latest Debian amd64
release and install it with dpkg
:
curl -sLJO https://deb.secrethub.io/amd64
dpkg -i secrethub-cli-amd64.deb
rm secrethub-cli-amd64.deb
To update the CLI, you can just re-run this command.
For other architectures or earlier versions, see the complete list of CLI releases.
Windows Server
On Windows, you can install the CLI using a standard Windows installer.
Download the latest amd64 .msi
file and follow the installation wizard.
For other architectures, see the complete list of CLI releases.
To install the CLI using Scoop, first add the SecretHub bucket:
scoop bucket add secrethub https://github.com/secrethub/scoop-secrethub
Afterwards, run this to actually install the CLI:
scoop install secrethub-cli
To download and install the secrethub
CLI, run the following in Powershell as an Administrator:
iwr https://get.secrethub.io/windows | iex
And you’re done.
Note: this works for Windows Server 2012 R2, Windows 8, and upwards. For older operating systems (e.g. Windows Server 2008 R2), use the equivalent more verbose command:
(New-Object System.Net.WebClient).DownloadString("https://get.secrethub.io/windows") | iex
Other
To install the CLI with NPM, run:
npm install -g @secrethub/cli
You can also include the CLI as a dev dependency to your project:
npm install --save-dev @secrethub/cli
Global install as root
To do a global install as root
, you have to run NPM with the unsafe-perm
setting.
You can do this by using the --unsafe-perm
flag:
npm install -g --unsafe-perm @secrethub/cli
Or by updating your NPM config:
npm config set unsafe-perm true
npm install -g @secrethub/cli
Step 2: Create a service account
Bringing you end-to-end encrypted secrets management does mean that the application-end also needs to do decryption. So it needs a key.
Technically, you could re-use your personal keyfile for every app you deploy, but you’d be missing out on some core (security) features if you did.
If instead every app gets its own account, you can set app-specific access rules, see the app’s activity on the audit log, and revoke it when its confidentiality cannot be not guaranteed anymore.
For GCP, we’ve built a special type of service account that hides the SecretHub key for you. Instead, it gets its identity from Cloud IAM and uses Cloud KMS as the last turtle, making your apps ‘keyless’.
As long as your app takes on a Google Service Account, it can load the secrets it needs. To set it up, create a KMS key and give your app’s Service Account decryption rights. Then, create the SecretHub service account:
Run the following command and you’ll be prompted for the email of your Google Service Account and the resource id of the Cloud KMS key:
secrethub service gcp init your-username/demo
To see the service accounts tied to a repo, run:
secrethub service ls your-username/demo
Every service gets an ID assigned (e.g. s-a1b2c3d4e5
), that you can use to set access rules or to delete the account.
resource "secrethub_service_gcp" "demo_app" {
repo = "your-username/demo"
service_account_email = google_service_account.demo_app.email
kms_key_id = google_kms_crypto_key.demo_app.id
}
Full Example
resource "google_service_account" "demo_app" {
account_id = "demo-app"
description = "SecretHub demo app"
}
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}",
]
}
resource "secrethub_service_gcp" "demo_app" {
repo = "your-username/demo"
service_account_email = google_service_account.demo_app.email
kms_key_id = google_kms_crypto_key.demo_app.id
}
For a complete, start-to-finish walkthrough of deploying the demo app, follow these guides:
Step 3: Set access rules
Creating a service account alone doesn’t grant it access to anything. To do that, you need to set access rules.
To allow the service to read every secret under your-username/demo
:
You first need the ID (e.g. s-a1b2c3d4e5
) of the service account, which can be obtained by listing all service accounts for your repo:
secrethub service ls your-username/demo
This ID can then be used to create a new access rule that gives the service account read access to the repo:
secrethub acl set your-username/demo s-a1b2c3d4e5 read
resource "secrethub_access_rule" "your_app" {
account_name = secrethub_service.your_app.id
dir = "your-username/demo"
permission = "read"
}
Step 4: Pick a mechanism for loading secrets
With a service account set up and the SecretHub CLI in place on the host, the last thing to do is to make your app load the secrets.
Your application code doesn’t have to change for this, it can just get the secret values from environment variables, config files, or key files:
The recommended way to load your secrets is through environment variables. As covered earlier, you can reference the secrets in your environment, instead of hardcoding them:
export DEMO_USERNAME=secrethub://your-username/demo/username
export DEMO_PASSWORD=secrethub://your-username/demo/password
Then, wrap the app launch command in secrethub run
:
secrethub run -- ./start-your-app
When you stop your app (either gracefully or forcefully), all local copies of secrets are gone. The next time you launch your app, they’ll have to be fetched and decrypted again, adding a new read entry to the audit log.
Docker
In your Dockerfile, you can set secrethub run
as the ENTRYPOINT
and your app start command as the CMD
:
ENTRYPOINT ["secrethub", "run", "--"]
CMD ["./start-your-app"]
If your app prefers config files, that’s fine too. Replace the secret values in the config with path references:
postgres:
host: localhost
port: 5432
user: {{ your-username/demo/username }}
password: {{ your-username/demo/password }}
Then, right before your app starts, inject the secret values into the config template:
secrethub inject -i config.yml.tpl -o config.yml
Keep in mind however that you have to make sure that the config file that contains the plaintext secrets gets deleted when your app stops.
If your app needs .crt
, .pem
, or other key files, we’ve got you covered as well.
For example, to write a TLS certificate key stored on SecretHub at your-username/demo/tls/example.com.key
to a local file called example.com.key
, run:
secrethub read -o example.com.key --filemode 0600 your-username/demo/tls/example.com.key
Keep in mind however that you have to make sure that the secret files get deleted when your app stops.
Whichever method you choose, make sure you set --identity-provider
or SECRETHUB_IDENTITY_PROVIDER
to gcp
, so the app knows where to look for the key.
T-minus 3, 2, 1… 🚀
You’re all set up now, so let’s deploy the app!
After deploying, check the audit log again and you’ll see some new entries logged.