Using Hashicorp Vault ¶
This documentation provides details for using Hashicorp Vault and secrets with Ping Identity DevOps images.
Note: the PingIdentity DevOps images and Helm chart only support version 2 of the KV secrets engine API for Vault secrets. PingDirectory itself currently only supports KV version 1 for password storage schemes. Learn more in the Vault KV secrets engine documentation.
Before you begin ¶
You must:
- Complete Get Started to set up your DevOps environment and run a test deployment of the products.
- Have a running Hashicorp Vault instance.
About this task ¶
The following examples explain and show:
- How to use HashiCorp Vault Secrets in native PingIdentity DevOps images
- How to use HashiCorp Vault Injector in Kubernetes deployments
Kubernetes - HashiCorp Vault Injector ¶
If you are using Kubernetes to deploy your containers, it's highly recommended to use the HashiCorp Vault Injector. The following provides details on how to use secrets in a non-Kubernetes deployment, such as Docker-compose.
If the HashiCorp Vault Injector Agent is installed, annotations can be added to the .yaml
file of a
Pod, Deployment, StatefulSet resource to pull in the secrets. The snippet below provides an example set
of annotations (placed in to the metadata of the container) to pull in a pf.jwk
secret into a container.
Helm Chart Stateful Set
This is an StatefulSet example created using the PingIdentity DevOps Helm Chart.
apiVersion: apps/v1
kind: StatefulSet
spec:
template:
metadata:
annotations:
vault.hashicorp.com/agent-init-first: "true"
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/agent-inject-secret-devops-secret.env.json: secret/.../devops-secret.env
vault.hashicorp.com/agent-inject-template-devops-secret.env.json: |
{{ with secret "secret/.../devops-secret.env" -}}
{{ .Data.data | toJSONPretty }}
{{- end }}
vault.hashicorp.com/agent-inject-secret-devops-secret.env.json: secret/.../passwords
vault.hashicorp.com/agent-inject-template-passwords.json: |
{{ with secret "secret/.../passwords" -}}
{{ .Data.data | toJSONPretty }}
{{- end }}
vault.hashicorp.com/agent-pre-populate-only: "true"
vault.hashicorp.com/log-level: info
vault.hashicorp.com/preserve-secret-case: "true"
vault.hashicorp.com/role: k8s-default
vault.hashicorp.com/secret-volume-path: /run/secrets
Secrets - Variables ¶
Using the previous example, the value for secret secret/.../devops-secret.env
JSON will be pulled into the container as /run/secrets/devops-secret.env.json
.
Because this secret ends in the value of .env
, it will further be turned into a property file
with NAME=VALUE pairs and is available to the container environment on start up.
Example of devops-secret.env transformed into files
{
"PING_IDENTITY_DEVOPS_USER": "jsmith@example.com",
"PING_IDENTITY_DEVOPS_KEY": "xxxxx-xxxx-xxxxx-xxxxx-xxxx"
}
File: /run/secrets/devops-secret.env
Contents: PING_IDENTITY_DEVOPS_USER="jsmith@example.com"
PING_IDENTITY_DEVOPS_KEY="xxxxx-xxxx-xxxxx-xxxxx-xxxx"
Secret - Files ¶
Using the previous example, the value for secret secret/.../passwords
JSON will be pulled into the container as /run/secrets/passwords.json
and for every key/value
in that secret, a file will be created with the name of the key
and contents of value
.
Example of /run/secrets/passwords.json transformed into files
{
"root-user-password": "secret-root-password",
"admin-password": "secret-admin-password"
}
File: /run/secrets/secret-root-password
Contents: secret-root-password
File: /run/secrets/secret-admin-password
Contents: secret-admin-password
Native DevOps HashiCorp Support ¶
Vault secrets can also be used in native PingIdentity DevOps images regardless of the environment they are deployed in, for example, Kubernetes, Docker, and Docker-compose. In these cases, there is no injector agent required.
This does require some type of AuthN to your vault, such as USERNAME/PASSWORD or TOKEN. HashiCorp Injector method is recommended.
The following image depicts the components and steps for pulling secrets into a container at start-up.
You can use the following variables to deploy images that will pull secrets from the Vault.
Variable | Example | Description |
---|---|---|
SECRETS_DIR | /run/secrets | Location for storing secrets. See section below on using a tmpfs mounted filesystem to store secrets in a memory location. |
VAULT_TYPE | hashicorp | Type of vault used. Currently supporting hashicorp. |
VAULT_ADDR | https://vault.example.com:8200 | URL for the vault with secrets |
VAULT_TOKEN | s.gvC3vd5aFz......JovV0b0A | Active token used to authticate/authorize container to vault. Optional if VAULT_AUTH_USERNAME/VAULT_AUTH_PASSWORD are provided. |
VAULT_AUTH_USERNAME | demo | Username of internal vault identity. Optional if VAULT_TOKEN is provided. |
VAULT_AUTH_PASSWORD | 2FederateM0re | Password of internal vault identity. Optional if VAULT_TOKEN is provided. |
VAULT_SECRETS | /pingfederate/encryption-keys | A list of secrets to pull into the container. Must be the full secret path used in vault. |
The following example shows how these would be used in a docker-compose.yaml file. This example provides two secrets, as denoted by the VAULT_SECRETS setting.
services:
pingfederate:
image: pingidentity/pingfederate:edge
environment:
...
################################################
# Vault Info
################################################
- VAULT_TYPE=hashicorp
- VAULT_ADDR=https://vault.ping-devops.com:8200
- VAULT_AUTH_USERNAME=demo
- VAULT_AUTH_PASSWORD=2FederateM0re
- VAULT_SECRETS=/demo/passwords
/demo/getting-started/pingfederated/pf-keys
The secret types (Variables/Files) are processed the same way as with the HashiCorp Injector Method above.
Secrets - Base64 ¶
Often, there are secrets that might be of a binary format, such as certificates.
Special key name suffixes can be used to perform certain processing on the keys when the file is created. The following table provides examples of how keys with special suffixes.
Key Suffix | Description |
---|---|
.b64 or .base64 | Specifies that the value is base64 encoded and the resulting file should be decoded when written, without the suffix. |
There is a message that is base64 encoded and stored in the vault as secret /demo/b64-demo
and key hello.b64
Secret: /demo/b64-demo
KEY VALUE
--- -----
hello.b64 SGVsbG8gV29ybGQhCg==
would result in the following file:
/run/secrets/hello
CONTENTS
--------
Hello World!
Using tmpfs for Secrets ¶
It's best practice to place secrets in a volume that won't be persisted to storage with the possibility that it might be improperly accessed at any point in the future, such as backups and environment variables.
Kubernetes automatically provides the default SECRETS_DIR
of /run/secrets
for this.
If using Docker, you should create a tmpfs
type volume and size it to 32m
and mount it to a path of /run/secrets
.
Docker-compose version > 2.4
Requires Docker-compose version 2.4 or later, due to the options provided to the tmpfs volumes definition
Creates a /run/secrets
volume under tmpfs
version: "2.4"
services:
pingfederate:
image: pingidentity/pingfederate:edge
environment:
...
tmpfs: /run/secrets
---- or -----
volumes:
- type: tmpfs
target: /run/secrets
tmpfs:
size: 32m
See this mount by exec'ing into the container and running:
> df -k /run/secrets
Filesystem 1K-blocks Used Available Use% Mounted on
tmpfs 16384 0 16384 0% /run/secrets