Skip to content

External Secrets Operator

Red Hat Documentation

The External Secrets Operator integrates external secret management systems (AWS Secrets Manager, HashiCorp Vault, Azure Key Vault, Google Secret Manager, IBM Cloud Secrets Manager) with OpenShift. It fetches secrets from external providers and provisions them as native Kubernetes Secret resources.

Warning

Do not run more than one External Secrets Operator in a cluster. If you have the community operator installed, uninstall it first.

Install the Operator via WebUI

  1. Go to Ecosystem -> Software Catalog -> filter for "External Secrets" -> click the "External Secrets Operator" tile (the Red Hat one, not community)
  2. Click Install
  3. Leave all the defaults and click Install
  4. Wait for the Operator to install
Install the Operator via YAML (click to expand)
apiVersion: v1
kind: Namespace
metadata:
  name: external-secrets-operator
---
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
  name: openshift-external-secrets-operator
  namespace: external-secrets-operator
spec:
  targetNamespaces: []
---
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: openshift-external-secrets-operator
  namespace: external-secrets-operator
spec:
  channel: stable-v1
  name: openshift-external-secrets-operator
  source: redhat-operators
  sourceNamespace: openshift-marketplace
  installPlanApproval: Automatic
oc apply -f external-secrets-operator.yaml

Wait for the operator:

oc get csv -n external-secrets-operator -w

Deploy the Operand

The operator does not deploy the external-secrets pods automatically. Create an ExternalSecretsConfig resource:

  1. Go to Ecosystem -> Installed Operators -> External Secrets Operator
  2. Click on the "ExternalSecretsConfig" tab
  3. Click "Create ExternalSecretsConfig"
  4. Leave defaults, then switch to YAML view and ensure an egress NetworkPolicy is present if your cluster uses default-deny policies (see the YAML example below) — click Create

Or via YAML:

apiVersion: operator.openshift.io/v1alpha1
kind: ExternalSecretsConfig
metadata:
  name: cluster
spec:
  controllerConfig:
    networkPolicies:
      - componentName: ExternalSecretsCoreController
        egress:
          - {}
        name: allow-external-secrets-egress

Why the networkPolicies block?

The External Secrets controller pod must make outbound HTTPS calls to reach your external vault (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, etc.). The egress: [{}] rule creates a NetworkPolicy that allows all outbound traffic from the controller. Without it, clusters with default-deny network policies will block the controller from fetching secrets. In production, restrict the egress rule to the specific vault endpoint IP/port.

oc apply -f external-secrets-config.yaml

Verify the operand pods are running:

oc get pods -n external-secrets

Configure a SecretStore

Example: HashiCorp Vault

oc create secret generic vault-token \
  --from-literal=token={{ vault_token }} \
  -n my-namespace
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: vault-store
  namespace: my-namespace
spec:
  provider:
    vault:
      server: "https://vault.example.com"
      path: "secret"
      version: "v2"
      auth:
        tokenSecretRef:
          name: vault-token
          key: token

Example: AWS Secrets Manager

oc create secret generic aws-credentials \
  --from-literal=access-key={{ access_key_id }} \
  --from-literal=secret-access-key={{ secret_access_key }} \
  -n my-namespace
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: aws-store
  namespace: my-namespace
spec:
  provider:
    aws:
      service: SecretsManager
      region: us-east-1
      auth:
        secretRef:
          accessKeyIDSecretRef:
            name: aws-credentials
            key: access-key
          secretAccessKeySecretRef:
            name: aws-credentials
            key: secret-access-key

Create an ExternalSecret

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: my-secret
  namespace: my-namespace
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-store
    kind: SecretStore
  target:
    name: my-k8s-secret
    creationPolicy: Owner
  data:
    - secretKey: password
      remoteRef:
        key: path/to/secret
        property: password

Verify

oc get secret my-k8s-secret -n my-namespace
oc get externalsecret my-secret -n my-namespace

The STATUS should show SecretSynced.