beyondtrustworkloadcredentials.md 8.8 KB

The BeyondtrustWorkloadCredentialsDynamicSecret Generator provides an interface to BeyondTrust Workload Credentials's dynamic secret generation capabilities. This enables obtaining temporary, short-lived credentials.

Dynamic secret definitions must be created in BeyondTrust Workload Credentials before they can be referenced by the generator. The generator calls the generation endpoint to produce fresh credentials each time it is invoked.

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

Any authentication method supported by the BeyondTrust Workload Credentials provider can be used here (provider block of the spec).

Example manifest

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

Example ExternalSecret that references the BeyondTrust Workload Credentials generator:

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

Configuration

Folder Path

The folderPath in the generator spec uses the format {folder}/{secretName}:

  • folder: The folder containing the dynamic secret definition (e.g., eso)
  • secretName: The name of the dynamic secret definition (e.g., dynamic)

For example, if your dynamic secret is stored at path my/dynamic in BeyondTrust Workload Credentials:

spec:
  provider:
    folderPath: "my/dynamic"

Generated Secret Fields

The generator returns different fields depending on the type of dynamic secret:

AWS Dynamic Secrets

stringData:
  accessKeyId: ASIAIOSFODNN7EXAMPLE
  secretAccessKey: wJal...YEKY
  sessionToken: IQoJ...Ek8=
  leaseId: 84038398-ec0f-417d-9a0f-02494fd7d22c
  expiration: 2025-12-29T22:35:29Z

All fields are automatically populated in the target Kubernetes secret.

Credential Refresh and Expiration

Important: External Secrets Operator does NOT automatically handle credential expiration/TTL from BeyondTrust Workload Credentials. The refresh is controlled solely by the refreshInterval specified in the ExternalSecret spec.

Setting Refresh Interval

You should set refreshInterval to less than the credential lifetime to ensure credentials are refreshed before expiration:

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: aws-credentials
spec:
  refreshInterval: 45m  # If credentials expire in 1 hour
  target:
    name: aws-temp-creds
  dataFrom:
    - sourceRef:
        generatorRef:
          apiVersion: generators.external-secrets.io/v1alpha1
          kind: BeyondtrustWorkloadCredentialsDynamicSecret
          name: beyondtrustworkloadcredentials-ds

What happens if refreshInterval > credential expiration?

Credentials will expire before being refreshed. Users will see:

  • ExternalSecret status: SecretSyncError
  • Logs/events: Authorization errors when the application tries to use expired credentials
  • The application will fail to authenticate with the target service

What happens if refreshInterval << credential expiration?

For example, if credentials expire in 1 hour but refreshInterval: 1m:

  • New credentials are generated every minute
  • Old credentials remain valid until their expiration time
  • Multiple valid credential sets may exist simultaneously
  • These credentials expire automatically at their TTL in AWS (for AssumeRole credentials).

Recommendation: Set refreshInterval to 75-80% of the credential lifetime. For example:

  • 1-hour credentials → refreshInterval: 45m
  • 12-hour credentials → refreshInterval: 9h
  • 24-hour credentials → refreshInterval: 18h

Generator Reusability

Generators are reusable Custom Resources. You can reference the same generator from multiple ExternalSecrets:

---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: app-1-aws-creds
spec:
  refreshInterval: 45m
  target:
    name: app-1-aws-credentials
  dataFrom:
    - sourceRef:
        generatorRef:
          kind: BeyondtrustWorkloadCredentialsDynamicSecret
          name: beyondtrustworkloadcredentials-ds
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: app-2-aws-creds
spec:
  refreshInterval: 45m
  target:
    name: app-2-aws-credentials
  dataFrom:
    - sourceRef:
        generatorRef:
          kind: BeyondtrustWorkloadCredentialsDynamicSecret
          name: beyondtrustworkloadcredentials-ds

Important: Each reference triggers a new credential generation. In the example above, app-1 and app-2 will receive different, independent sets of credentials.

Authentication

The generator uses the same authentication mechanism as the BeyondTrust Workload Credentials provider (API key authentication):

apiVersion: generators.external-secrets.io/v1alpha1
kind: BeyondtrustWorkloadCredentialsDynamicSecret
metadata:
  name: beyondtrustworkloadcredentials-ds
  namespace: external-secrets
spec:
  provider:
    auth:
      apikey:
        token:
          name: api-token
          key: token

Create the API token secret:

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

Certificate Trust

If using self-signed certificates, configure trust using caProvider:

spec:
  provider:
    # ... other config ...
    caProvider:
      type: Secret
      name: my-ca-bundle
      key: ca.crt

Create the CA bundle secret:

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

Server Configuration

Configure the BeyondTrust Workload Credentials API endpoint:

spec:
  provider:
    server:
      apiUrl: "https://api.beyondtrust.io/site"
      siteId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  • apiUrl: The base URL of your BeyondTrust Workload Credentials API
  • siteId: Your BeyondTrust site identifier (UUID format)

Complete Example

Here's a complete example for AWS dynamic credentials:

  1. Create the API token and CA bundle secrets:

    kubectl create secret generic api-token \
    --from-literal=token=<YOUR_API_TOKEN> \
    -n external-secrets
    kubectl create secret generic my-ca-bundle \
    --from-file=ca.crt="/path/to/ca.crt" \
    -n external-secrets
    
  2. Create the generator:

    apiVersion: generators.external-secrets.io/v1alpha1
    kind: BeyondtrustWorkloadCredentialsDynamicSecret
    metadata:
    name: aws-dynamic-generator
    namespace: external-secrets
    spec:
    provider:
    auth:
      apikey:
        token:
          name: api-token
          key: token
    server:
      apiUrl: "https://api.beyondtrust.io/site"
      siteId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
    folderPath: "production/aws-temp"
    
  3. Create an ExternalSecret that uses the generator:

    apiVersion: external-secrets.io/v1
    kind: ExternalSecret
    metadata:
    name: app-aws-credentials
    namespace: external-secrets
    spec:
    refreshInterval: 45m  # Refresh before 1-hour expiration
    target:
    name: aws-temp-credentials
    creationPolicy: Owner
    dataFrom:
    - sourceRef:
        generatorRef:
          apiVersion: generators.external-secrets.io/v1alpha1
          kind: BeyondtrustWorkloadCredentialsDynamicSecret
          name: aws-dynamic-generator
    
  4. The resulting Kubernetes secret will contain:

    apiVersion: v1
    kind: Secret
    metadata:
    name: aws-temp-credentials
    namespace: external-secrets
    data:
    accessKeyId: QVNJ...R04=
    secretAccessKey: Z3dk...WFk=
    sessionToken: SVFv...Ek8=
    leaseId: NTdk...Nm1j
    expiration: MjAy...OVo=
    

Troubleshooting

Empty Credential Fields

If the generated secret has empty values:

  1. Verify the dynamic secret exists in BeyondTrust Workload Credentials at the specified path
  2. Check the API token has permissions to generate credentials
  3. Verify the folderPath format is correct (folder/secretName)
  4. Check controller logs: kubectl logs -l app.kubernetes.io/name=external-secrets -n external-secrets

Authentication Errors

If you see 403/401 errors:

  1. Verify the API token is valid and not expired
  2. Check the token has generate permissions for the dynamic secret
  3. Ensure the caProvider or caBundle is configured correctly if using self-signed certificates

Timeout Errors

If credential generation times out:

  1. Check network connectivity from the cluster to BeyondTrust Workload Credentials API
  2. Verify the API endpoint is responsive
  3. Check if there are firewall rules blocking the connection

Credential Expiration Issues

If applications report authentication failures:

  1. Check if refreshInterval is greater than credential lifetime
  2. Review the expiration field in the secret to see when credentials expire
  3. Adjust refreshInterval to be 75-80% of the credential lifetime
  4. Check ExternalSecret status: kubectl describe externalsecret <name> -n <namespace>