Kubernetes Secrets-Agent
Overview
The Kubernetes (K8S) Secrets-Agent integration for Password Safe enables the injection of secrets from Password Safe into K8S pods.
Pods can be configured to retrieve secrets from Password Safe before being applied to their primary application. The application consuming the secrets does not need to have any knowledge of Password Safe to use the secret at run time.
Permissions for access to secrets in Password Safe can be granted to specific accounts within BeyondInsight.
Note
This secrets-agent version only works with Password Safe version 23.1.0 and later releases.
Applications can opt in to Password Safe secret retrieval by adding the secrets-agent to their Kubernetes manifests as an initContainer, or a sidecar container. The secrets-agent retrieves secrets and makes them available to the target consumer without requiring that the consumer be aware of Password Safe.
To support this feature, your BeyondInsight instance must be configured with an API registration.
At run time, secrets are retrieved from Password Safe by Kubernetes pods, pictured in the figure below:
- On startup, the initContainer authenticates to Password Safe.
- Secrets-agent retrieves secrets from Password Safe and writes them to a shared volume.
- The end-user application reads the secrets from the shared volume.

Retrieve secrets from Password Safe by Kubernetes pod
Configuring an Application for Secret Retrieval
For an application to opt in to Password Safe secret retrieval, each of the following must be in place:
- A Password Safe API registration must be configured.
- The application's manifest must add the secrets-agent container and a Shared Volume.
This section first presents a guide to setting up the required authorization to allow a Pod's secrets-agent to retrieve secrets, and then shows the pod manifest modifications necessary to add the secret-retrieval behavior to the Pod at runtime.
Permissions - Authorize access to the target secret
The secrets-agent must be provided an API key and a user account in order to access its target secrets in PasswordSafe. This is accomplished by the following steps:
Setup
- Create an API registration in BeyondInsight (does not require a user password).
- Create or use an existing Secrets Safe group.
- Create or use an existing BeyondInsight user.
- Add API registration to the group.
- Add the user to the group.
- Add the Secrets Safe Feature to the group.
Managed Accounts Setup
- Create or use an existing Access Policy that has view password auto approve set.
- Add the All Managed Accounts Smart Group to the BeyondInsight group.
- Add the Access Policy to the All Managed Accounts Smart Group, and ensure that both requestor and approver are set.
- Create or use an existing managed system.
- Create or use an existing managed account associated with the managed system.
- Configure the managed account with API Enabled and Max Concurrent Requests Unlimited.
Update target application's manifest
The final step in injecting secrets into pods is to modify the manifest of the target application to include the resources that retrieve secrets and write them to the pod filesystem.
Below is an example manifest for a deployment that retrieves the secrets at paths rootFolder/childFolder1/secretTitle and rootFolder/ from a Password Safe instance. The secret retrieval initContainer runs prior to the main application starting, retrieves the target secrets, and writes their contents to files on the shared volume at /usr/src/app/secrets_files:
apiVersion: v1
kind: Pod
metadata:
name: passwordsafe-integration
spec:
volumes:
- name: secrets
emptyDir:
medium: Memory
initContainers:
- name: secrets-agent
image: secrets-agent:latest
# securityContext is optional, if not set, container will run as root user
securityContext:
runAsUser: 1000 # specifies that for any Containers in the Pod, all processes run with user ID 1000
runAsNonRoot: true
allowPrivilegeEscalation: false
volumeMounts:
- name: secrets
mountPath: /usr/src/app/secrets_files
ports:
- containerPort: 8000
name: secrets-agent
imagePullPolicy: Never
resources:
limits:
memory: "400Mi"
env:
- name: SECRETS_PATH
value: "/usr/src/app/secrets_files"
- name: BT_API_URL
value: "https://example.com:443/Beyondtrust/api/public/v3"
- name: BT_API_VERSION
value: "3.1"
- name: BT_API_KEY
value: "<API-KEY>;runas=username;"
- name: SECRETS_LIST
value: "rootFolder/childFolder1/secretTitle,rootFolder/childFolder2/secretTitle"
- name: FOLDER_LIST
value: "rootFolder/childFolder3/,rootFolder/childFolder4/"
- name: MANAGED_ACCOUNTS_LIST
value: "Server2016Standard/serveruser1"
- name: BT_VERIFY_CA
value: "True"
Below is an example manifest for a deployment that retrieves the secrets at paths rootFolder/childFolder1/secretTitle and rootFolder/ from a Password Safe instance. The secret retrieval sidecar runs alongside the main application, retrieves the target secrets, and writes their contents to files on the shared volume at /usr/src/app/secrets_files:
apiVersion: v1
kind: Pod
metadata:
name: passwordsafe-integration
spec:
volumes:
- name: secrets
emptyDir:
medium: Memory
containers:
- name: secrets-agent-sidecar
image: secrets-agent:latest
# securityContext is optional, if not set, container will run as root user
securityContext:
runAsUser: 1000 # specifies that for any Containers in the Pod, all processes run with user ID 1000
runAsNonRoot: true
allowPrivilegeEscalation: false
volumeMounts:
- name: secrets
mountPath: /usr/src/app/secrets_files
ports:
- containerPort: 8000
name: secrets-agent
imagePullPolicy: Never
resources:
limits:
memory: "400Mi"
env:
- name: SECRETS_PATH
value: "/usr/src/app/secrets_files"
- name: BT_API_URL
value: "https://example.com:443/Beyondtrust/api/public/v3"
- name: BT_API_KEY
value: "<API-KEY>;runas=apiuser;"
- name: BT_API_VERSION
value: "3.1"
- name: SECRETS_LIST
value: "rootFolder/childFolder1/secretTitle,rootFolder/childFolder2/secretTitle"
- name: FOLDER_LIST
value: "rootFolder/childFolder3/,rootFolder/childFolder4/"
- name: MANAGED_ACCOUNTS_LIST
value: "Server2016Standard/serveruser1"
- name: POLLING_WAIT_BETWEEN_REQUESTS_MINUTES
value: "20"
- name: BT_VERIFY_CA
value: "True"
After saving the above pod manifest to a .yaml file named secret-retrieval-example.yaml, apply it to the cluster using kubectl apply -f secret-retrieval-example.yaml. This creates the pod on the cluster.
Observe the initContainer image pulled using kubectl describe for the pod. Verify that the target secret contents are injected into the directory at /usr/src/app/secrets_files using kubectl exec -it sh to start an interactive shell session inside the running pod. From there, navigate to the /usr/src/app/secrets_files directory and inspect the contents of the files in the secrets_files folder.
Kubernetes Secrets-Agent Usage
Usage for the secrets-agent is controlled using environment variables. Add the following environment variables to your K8s yaml file:
Environment variables
- SECRETS_PATH
- Optional sidecar or initContainer environment variable.
- Defaults to: /usr/src/app/secrets_files
- The name and path of the folder on the volume to store secrets and their metadata in.
- Example usage:
SECRETS_PATH="/usr/src/app/secrets_files"
- BT_API_URL
- Mandatory sidecar or initContainer environment variable.
- The URL for retrieving secrets.
- Example usage:
BT_API_URL=https://example.com:443/Beyondtrust/api/public/v3
- BT_API_VERSION
- Optional sidecar or initContainer environment variable.
- The recommended version is 3.1. If no version is specified, the default API version 3.0 will be use.
- Example usage:
BT_API_VERSION="3.1"
- BT_API_KEY
- Optional sidecar or initContainer environment variable.
- The registered API key, if not set, then Client Credentials would be used (CLIENT_ID, CLIENT_SECRET).
- Example usage:
BT_API_KEY="<API-KEY>;runas=username;"
- CLIENT_ID
- Optional sidecar or initContainer environment variable.
- The registered Client ID, if using OAuth Client Credentials.
- Example usage:
CLIENT_ID=<CLIENT_ID>
- CLIENT_SECRET
- Optional, sidecar or initContainer environment variable.
- The registered Client Secret, if using OAuth Client Credentials..
- Example Usage:
CLIENT_SECRET=<CLIENT_SECRET>
- SECRET_LIST
- Optional sidecar or initContainer environment variable.
- By default a comma-delimited list of Secrets Safe paths.
- Example usage:
rootFolder/childFolder1/secretTitle,rootFolder/childFolder2/secretTitle
- FOLDER_LIST
- Optional sidecar or initContainer environment variable.
- By default a comma-delimited list of Secrets Safe folder paths.
Note
Only secrets at the level specified are shown. Usage of this variable does not traverse subfolders for secrets.
- Example usage:
rootFolder/childFolder3/,rootFolder/childFolder4/
- MANAGED_ACCOUNTS_LIST
- Optional sidecar or initContainer environment variable.
- By default a comma-delimited list of managed account paths.
- Example usage:
MANAGED_ACCOUNTS=server2019/accountName1,server2019/accountName2
- BT_VERIFY_CA
- Optional sidecar or initContainer environment variable.
- Instructs the secrets-agent to not verify the Password Safe certificate authority. If the environment variable is not specified or BT_VERIFY_CA=False, the CA will not be verified.
- Example Usage:
BT_VERIFY_CA=True
- POLLING_WAIT_BETWEEN_REQUESTS_MINUTES
- Mandatory sidecar-only environment variable.
- When running secrets-agent as a sidecar, you can specify how long to wait between subsequent secrets requests. The recommended wait time is 20 minutes. The minimum wait is 5 minutes.
- If not specified or POLLING_WAIT_BETWEEN_REQUESTS_MINUTES=0, there is no polling.
Note
If this variable is used for your initContainer configuration, the initContainer will never complete.
- Example usage:
POLLING_WAIT_BETWEEN_REQUESTS_MINUTES=20
- BT_CLIENT_CERTIFICATE_PATH
- Optional sidecar or initContainer environment variable.
- The path to a persistent volume with the client certificate file. If a path is empty, a client certificate is not used.
- Example usage:
BT_CLIENT_CERTIFICATE_PATH="/usr/src/app/certificate/certificate.pfx"
- BT_CLIENT_CERTIFICATE_PASSWORD
- Optional sidecar or initContainer environment variable.
- The client certificate password.
- Example Usage:
BT_CLIENT_CERTIFICATE_PASSWORD=password
- LIST_DELIMITER
- Optional sidecar or initContainer environment variable. Default to using a comma if not specified.
- Used to change the default delimiter for the SECRETS_LIST, FOLDER_LIST and MANAGED_ACCOUNTS_LIST variables.
- Example Usage:
LIST_DELIMITER=";"
The initContainer environment variable list from the manifest example above can be expanded to include these options for a client certificate file:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv
spec:
storageClassName: standard
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
hostPath:
path: "/home/docker/"
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 200Mi
storageClassName: standard
volumeName: pv
apiVersion: v1
kind: Pod
metadata:
name: passwordsafe-integration
spec:
volumes:
- name: secrets
emptyDir:
medium: Memory
- name: certificate
persistentVolumeClaim:
claimName: pvc
containers:
- name: secrets-agent-sidecar
image: secrets-agent:latest
volumeMounts:
- name: secrets
mountPath: /usr/src/app/secrets_files
- name: certificate
mountPath: /usr/src/app/certificate
ports:
- containerPort: 8000
name: secrets-agent
imagePullPolicy: Never
resources:
limits:
memory: "400Mi"
env:
- name: SECRETS_PATH
value: "/usr/src/app/secrets_files"
- name: BT_API_URL
value: "https://example.com:443/Beyondtrust/api/public/v3"
- name: BT_API_VERSION
value: "3.1"
- name: BT_API_KEY
value: "<API-KEY>;runas=apiuser;"
- name: SECRETS_LIST
value: "rootFolder/childFolder1/secretTitle,rootFolder/childFolder2/secretTitle"
- name: FOLDER_LIST
value: "rootFolder/childFolder3/,rootFolder/childFolder4/"
- name: MANAGED_ACCOUNTS_LIST
value: "Server2016Standard/serveruser1"
- name: POLLING_WAIT_BETWEEN_REQUESTS_MINUTES
value: "20"
- name: BT_VERIFY_CA
value: "True"
- name: BT_CLIENT_CERTIFICATE_PATH
value: "/usr/src/app/certificate/certificate.pfx"
- name: BT_CLIENT_CERTIFICATE_PASSWORD
value: "***************"
Updated about 1 month ago