beyondtrustworkloadcredentials.md 10 KB

BeyondTrust Workload Credentials

External Secrets Operator integrates with BeyondTrust Workload Credentials for secret management.

The provider supports static key-value secrets stored in folders. For dynamic secret generation (e.g., temporary AWS credentials), refer to the BeyondTrust Workload Credentials Generator.

For complete BeyondTrust Workload Credentials API documentation, see: https://docs.beyondtrust.com/bt-docs/docs/secrets-api

Example

First, create a SecretStore with a BeyondTrust Workload Credentials backend. You'll need an API token and the server configuration:

{% include 'beyondtrustworkloadcredentials-secret-store.yaml' %}

Create the API token secret:

kubectl create secret generic api-token \
  --from-literal=token=<YOUR_API_TOKEN> \
  -n external-secrets

If using self-signed certificates, create a CA bundle secret:

kubectl create secret generic my-ca-bundle \
  --from-file=ca.crt="/path/to/root.crt" \
  -n external-secrets

Now create an ExternalSecret that uses the above SecretStore:

{% include 'beyondtrustworkloadcredentials-external-secret.yaml' %}

This will automatically create a Kubernetes Secret with the synced data.

Fetching Secret Properties

Single Property Retrieval

You can fetch a specific property from a secret by specifying the property field:

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: postgres-credentials
  namespace: external-secrets
spec:
  refreshInterval: 1m
  secretStoreRef:
    name: beyondtrustworkloadcredentials-ss
    kind: SecretStore
  target:
    name: postgres-creds
  data:
    - secretKey: username
      remoteRef:
        key: postgresCreds
        property: username
    - secretKey: password
      remoteRef:
        key: postgresCreds
        property: password

This creates a secret with individual keys for username and password.

Fetching All Properties as JSON

If you omit the property field, you'll get all key-value pairs as a single JSON string:

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: postgres-credentials-json
  namespace: external-secrets
spec:
  refreshInterval: 1m
  secretStoreRef:
    name: beyondtrustworkloadcredentials-ss
    kind: SecretStore
  target:
    name: postgres-creds-json
  data:
    - secretKey: credentials
      remoteRef:
        key: postgresCreds

This returns: {"username":"user","password":"pass"} as the value of credentials.

Extracting All Properties as Separate Keys

To sync all properties of a secret as individual keys in the target Kubernetes secret, use dataFrom with extract:

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: postgres-credentials-extracted
  namespace: external-secrets
spec:
  refreshInterval: 1m
  secretStoreRef:
    name: beyondtrustworkloadcredentials-ss
    kind: SecretStore
  target:
    name: postgres-creds-extracted
  dataFrom:
    - extract:
        key: postgresCreds

This creates a secret with:

data:
  username: dXNlcg==     # base64("user")
  password: cGFzcw==     # base64("pass")

Getting Multiple Secrets

You can extract multiple secrets from a folder by using dataFrom.find.

Given a folder eso/static with these secrets:

  • anotherSecret: {"someKey": "value1"}
  • mySecret: {"myKey": "value2", "someKey": "value3"}
  • postgresCreds: {"username": "user", "password": "pass"}

Fetch All Secrets in Folder

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: all-secrets
  namespace: external-secrets
spec:
  refreshInterval: 1m
  secretStoreRef:
    name: beyondtrustworkloadcredentials-ss
    kind: SecretStore
  target:
    name: all-folder-secrets
  dataFrom:
    - find:
        name:
          regexp: ".*"

This merges all key-value pairs from all secrets in the folder into a single Kubernetes secret.

Regex Pattern Filtering

To sync only secrets matching a specific pattern:

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: filtered-secrets
  namespace: external-secrets
spec:
  refreshInterval: 1m
  secretStoreRef:
    name: beyondtrustworkloadcredentials-ss
    kind: SecretStore
  target:
    name: filtered-folder-secrets
  dataFrom:
    - find:
        name:
          regexp: "Secret$"

This will only sync secrets whose names end with "Secret" (e.g., anotherSecret, mySecret).

Specifying a Different Folder

By default, find uses the folderPath from the SecretStore. To search a different folder, use the path field:

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: subfolder-secrets
  namespace: external-secrets
spec:
  refreshInterval: 1m
  secretStoreRef:
    name: beyondtrustworkloadcredentials-ss
    kind: SecretStore
  target:
    name: subfolder-data
  dataFrom:
    - find:
        path: "eso/production"  # Override folder path
        name:
          regexp: ".*"           # Get all secrets in this folder

This will list all secrets in the eso/production folder, regardless of the folderPath configured in the SecretStore.

Note: The path field specifies a folder path, not a path to a specific secret. To fetch a single secret, use data with extract or individual remoteRef entries.

Handling Source Secret Deletion

By default, when a source secret is deleted from BeyondTrust Workload Credentials, the managed Kubernetes secret is retained. You can change this behavior using deletionPolicy:

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: secret-with-deletion
  namespace: external-secrets
spec:
  refreshInterval: 1m
  secretStoreRef:
    name: beyondtrustworkloadcredentials-ss
    kind: SecretStore
  target:
    name: managed-secret
    deletionPolicy: Delete  # Delete the Kubernetes secret when source is removed
  data:
    - secretKey: myKey
      remoteRef:
        key: mySecret

Valid values:

  • Retain (default): Keep the Kubernetes secret even if the source is deleted
  • Delete: Remove the Kubernetes secret when the source is deleted

Authentication

BeyondTrust Workload Credentials uses API key authentication. The API key is stored in a Kubernetes Secret and referenced in the SecretStore:

apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: beyondtrustworkloadcredentials-ss
  namespace: external-secrets
spec:
  provider:
    beyondtrustworkloadcredentials:
      auth:
        apikey:
          token:
            name: api-token  # Name of the Kubernetes Secret
            key: token            # Key within the Secret
      server:
        apiUrl: "https://api.beyondtrust.io/site"
        siteId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
      folderPath: "eso/static"
auth:
  apikey:
    token:
      name: api-token
      key: token

Server Configuration

The server configuration consists of:

  • apiUrl: The base URL of your BeyondTrust Workload Credentials API
  • siteId: Your BeyondTrust site identifier (UUID format)

The provider automatically constructs the full API endpoint as: {apiUrl}/{siteId}/secrets

Certificate Trust

BeyondTrust Workload Credentials typically uses certificates signed by public CAs, requiring no additional configuration.

If using self-signed certificates, configure trust using either caBundle or caProvider:

Using caProvider (Recommended)

spec:
  provider:
    beyondtrustworkloadcredentials:
      # ... other config ...
      caProvider:
        type: Secret
        name: my-ca-bundle
        key: ca.crt
        namespace: external-secrets  # Required for ClusterSecretStore

First create the CA bundle secret:

kubectl create secret generic my-ca-bundle \
  --from-file=ca.crt="/path/to/ca.crt" \
  -n external-secrets

Using caBundle

Alternatively, embed the base64-encoded PEM certificate directly:

spec:
  provider:
    beyondtrustworkloadcredentials:
      # ... other config ...
      server:
        apiUrl: "https://api.beyondtrust.io/site"
        siteId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
      caBundle: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0t..."  # base64-encoded PEM

To generate the base64 string:

cat /path/to/ca.crt | base64 -w 0

Folder Path

The folderPath specifies the default folder containing your secrets. This should be a folder path, not the full path to a specific secret.

For example, if your secrets are stored at:

  • eso/static/secret1
  • eso/static/secret2
  • eso/static/secret3

Set folderPath: "eso/static" in your SecretStore.

When using data or dataFrom.extract, secret names are relative to this folder. When using dataFrom.find, this folder is searched by default (unless overridden with the path field).

Refresh Interval

The refreshInterval controls how often the ExternalSecret checks for updates:

spec:
  refreshInterval: 5m  # Check every 5 minutes

Supported units: s (seconds), m (minutes), h (hours).

Best Practice: Balance between keeping secrets up-to-date and minimizing API calls. For most use cases, 1m to 15m is appropriate.

ClusterSecretStore

To use a ClusterSecretStore (accessible across all namespaces):

apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
  name: beyondtrustworkloadcredentials-css
spec:
  provider:
    beyondtrustworkloadcredentials:
      auth:
        apikey:
          token:
            name: api-token
            key: token
            namespace: external-secrets  # Required: specify where the token secret lives
      server:
        apiUrl: "https://api.beyondtrust.io/site"
        siteId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
      folderPath: "eso/static"

Reference it in an ExternalSecret:

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: my-secret
  namespace: my-app
spec:
  secretStoreRef:
    name: beyondtrustworkloadcredentials-css
    kind: ClusterSecretStore  # Specify ClusterSecretStore
  # ... rest of spec