---
title: Using Hashicorp Vault
description: This documentation provides details for using Hashicorp Vault and secrets with Ping Identity DevOps images.
component: devops
page_id: devops::how-to/usingVault
canonical_url: https://developer.pingidentity.com/devops/how-to/usingVault.html
section_ids:
  devops-before-you-begin: Before you begin
  devops-about-this-task: About this task
  devops-kubernetes-hashicorp-vault-injector: Kubernetes - HashiCorp Vault Injector
  devops-secrets-variables: Secrets - Variables
  devops-secret-files: Secret - Files
  devops-native-devops-hashicorp-support: Native DevOps HashiCorp Support
  devops-secrets-base64: Secrets - Base64
  devops-using-tmpfs-for-secrets: Using tmpfs for Secrets
---

# 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](https://developer.hashicorp.com/vault/api-docs/secret/kv).

## Before you begin

You must:

* Complete [Get Started](../get-started/introduction.html) 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.

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | This is an StatefulSet example created using the PingIdentity DevOps Helm Chart.```text
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.

|   |                                                                                                                                                                                                                                                                                                                         |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | ```json
{
  "PING_IDENTITY_DEVOPS_USER": "jsmith@example.com",
  "PING_IDENTITY_DEVOPS_KEY": "xxxxx-xxxx-xxxxx-xxxxx-xxxx"
}
```creates the files```
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`.

|   |                                                                                                                                                                                                                                                                                      |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|   | ```json
{
  "root-user-password": "secret-root-password",
  "admin-password": "secret-admin-password"
}
```creates the files```
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 authentication to your Vault, such as USERNAME/PASSWORD or TOKEN. The HashiCorp Injector method is recommended.** |

The following image depicts the components and steps for pulling secrets into a container at start-up.

![Using Vault](../_images/usingVault-1.png)

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 authenticate/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.

```yaml
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. |

|   |                                                                                                                                                                                                                      |
| - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | ```text
Secret: /demo/b64-demo

  KEY         VALUE
  ---         -----
  hello.b64   SGVsbG8gV29ybGQhCg==
```would result in the following file:```text
/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.

|   |                                                                                                            |
| - | ---------------------------------------------------------------------------------------------------------- |
|   | Requires Docker-compose version 2.4 or later, due to the options provided to the tmpfs volumes definition. |

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | ```yaml
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:```bash
> df -k /run/secrets
Filesystem           1K-blocks      Used Available Use% Mounted on
tmpfs                    16384         0     16384   0% /run/secrets
``` |
