Skip to main content
This document collects the reference Kubernetes manifests for External Secrets Operator (ESO) security in Astro Private Cloud (APC): the backend credentials secret, the secret store options for the shared-identity modes, the Mode 2 hardened cluster RBAC, and the Mode 3 per-namespace RBAC.
The backend-credentials secret and the ClusterSecretStore (Mode 1) apply to APC 2.0 and later. The ESO controller ServiceAccount, the Mode 2 cluster RBAC, the Mode 3 per-namespace RBAC, and the leader-election RBAC require APC 2.1 or later.
Use it alongside External Secrets Operator security, which explains the modes and how to choose, and Configure External Secrets Operator security, the step-by-step setup that applies these manifests. All examples use AWS Secrets Manager. GCP Secret Manager and Hashicorp Vault (Kubernetes auth) use the same object shapes with a different provider block; for the Vault provider block and Vault-side setup, see Configure Hashicorp Vault for data plane failover. The manifests use two placeholders: <release-name> is the Helm release name you install the Astronomer chart with (for example astronomer), and <pool-namespace> is one of your pre-created namespace pool namespaces.
These manifests assume the platform is installed in the astronomer namespace. If you installed it into a different namespace, replace astronomer in the manifests and the chart values accordingly.

Install the ESO CRDs yourself

By default the APC chart installs the External Secrets Operator CRDs (external-secrets.crd.create: true). If you set external-secrets.crd.create: false — for example, when a separate infrastructure team owns CRD installation — install the CRDs yourself before you install or upgrade the platform. The CRDs are published by the external-secrets project as a single CRD bundle. Apply the bundle whose tag matches the ESO version the APC chart ships, currently v2.7.0:
Match the bundle tag to the ESO version your APC chart ships — applying CRDs from a different version can break ESO reconciliation. Apply the bundle before the platform install so the CRDs exist when ESO starts.

Backend credentials secret (Modes 1 and 2)

Create the backend credentials in the platform (astronomer) namespace. Skip this if you authenticate with workload identity instead of a credential pair.

ESO controller ServiceAccount (Modes 2 and 3)

In Modes 2 and 3, you create the ESO controller ServiceAccount yourself and disable the chart’s ServiceAccount creation, so the ServiceAccount and its RBAC exist before ESO starts. In Configure External Secrets Operator security, you set external-secrets.serviceAccount.create: false and external-secrets.serviceAccount.name to this ServiceAccount. Create it in the astronomer namespace:
For workload identity, annotate this ServiceAccount for your provider (eks.amazonaws.com/role-arn for AWS, iam.gke.io/gcp-service-account for GCP).

Secret store manifests (Modes 1 and 2)

Option A — cluster-scoped ClusterSecretStore (Modes 1 and 2)

The manifest above authenticates with static credentials. To use workload identity instead, reference the ESO controller ServiceAccount from the store’s auth block. AWS IRSA is shown. GCP and Vault use their provider’s equivalent auth:
The ESO controller ServiceAccount (<release-name>-external-secrets) is created during ESO setup — by the chart in Mode 1, or by you in Modes 2 and 3 (see ESO controller ServiceAccount). For workload identity, annotate it for your provider (eks.amazonaws.com/role-arn for AWS, iam.gke.io/gcp-service-account for GCP) — in Mode 1 through the chart’s external-secrets.serviceAccount.annotations value, or in Modes 2 and 3 directly on the ServiceAccount you create.

Option B — namespaced SecretStore synced by the platform (Mode 2 only)

Both the credentials secret and the SecretStore carry the astronomer.io/commander-sync annotation, which tells the platform to sync them into every Deployment namespace.
Static credentials onlyThis synced-SecretStore option supports static credentials only. The platform copies the credentials Secret and the SecretStore into each Deployment namespace, so it can’t carry per-namespace workload-identity references. To use workload identity (AWS IRSA, GKE Workload Identity, or Vault Kubernetes auth) in Mode 2, use the cluster-scoped ClusterSecretStore (Option A) instead.

Force-delete secrets in AWS Secrets Manager

AWS Secrets Manager soft-deletes secrets by default, keeping them recoverable for a 30-day window during which the secret name stays reserved. If the platform then tries to create a secret with the same name, the create conflicts with the still-recoverable secret. This can happen when you use custom release names and reuse a release name for a new Deployment after deleting the previous one. To make ESO hard-delete secrets instead, set forceDeleteWithoutRecovery on the AWS provider in your SecretStore or ClusterSecretStore:
With this set, deleted secrets are removed immediately with no recovery window, so a new Deployment can reuse the name right away. If you use custom release names, set this, because reusing a release name after deleting a Deployment is exactly when the name collision occurs. The trade-off is that deleted secrets can’t be restored, since there is no recovery window. This option applies to AWS Secrets Manager only. Add it to whichever store your mode uses — the shared ClusterSecretStore or SecretStore in Modes 1 and 2, or the per-namespace SecretStore in Mode 3. The ESO GCP Secret Manager and Azure Key Vault providers don’t expose an equivalent option: GCP Secret Manager deletes secrets immediately, so the conflict doesn’t arise, and Azure Key Vault’s soft-delete can’t be overridden from the store — on Azure you purge a deleted secret through Azure itself.

Mode 2: hardened ESO cluster RBAC

In Mode 2, you disable the ESO sub-chart’s default RBAC (external-secrets.rbac.create: false), then apply the ClusterRole and ClusterRoleBinding below. They grant ESO the same reconcile rules as the Mode 3 per-namespace Role, but cluster-scoped, and pin ServiceAccount token creation with resourceNames to ESO’s own ServiceAccount in the astronomer namespace. That pinned token-create serves the same purpose as in Mode 3: ESO assumes the shared identity by minting its own ServiceAccount’s token (the serviceAccountRef path) — required for Vault, and used by AWS or GCP workload identity through serviceAccountRef. It goes unused if you authenticate with static credentials.
In Mode 2 you apply this ClusterRole and ClusterRoleBinding yourself. The chart doesn’t ship them, since external-secrets.rbac.create: false. The rules mirror the external-secrets Role, expressed as a cluster-scoped role with token creation pinned to the ESO ServiceAccount.
The clustersecretstores rules let ESO read the cluster-scoped store; include them when Mode 2 uses a ClusterSecretStore. If you use only the synced SecretStore (Option B), you can omit them.

config-syncer RBAC (Option B synced SecretStore)

The platform’s config-syncer component performs the Option B sync: it copies the commander-sync-annotated credentials Secret and SecretStore from the astronomer namespace into each Deployment namespace, so it needs write access to secrets and secretstores in every target namespace. Mode 3 doesn’t use this component — there, each namespace has its own pre-provisioned SecretStore and nothing is synced. The chart creates this RBAC automatically in a standard install. Provision the Role and RoleBinding below yourself only if you run with cluster-scoped roles disabled, so config-syncer isn’t otherwise granted namespace access. Create them in each Deployment namespace, binding the <release-name>-config-syncer ServiceAccount in astronomer.

Mode 3: per-namespace RBAC

In Mode 3 (customer-managed isolated identity), each Deployment gets its own backend identity, and you pre-provision per-namespace RBAC for every platform component that operates in the pool namespaces. This document covers the ESO and Commander RBAC. The remaining platform components — kube-state-metrics, the Houston DB bootstrapper hook, Prometheus, and NGINX — are covered in Component RBAC for restricted mode. Create these objects in the astronomer namespace and in each pool namespace, in addition to the standard namespace pools setup, and replicate them with matching namespace names on every cluster a Deployment can fail over to. Each RoleBinding names the component’s ServiceAccount in the astronomer namespace as a cross-namespace subject. The chart installs those ServiceAccounts release-prefixed: <release-name>-external-secrets and <release-name>-commander. Rather than hand-writing every object, you can generate the full set with the provided script. See Generate the platform RBAC. The manifests below are the reference for what that script produces.

Per-namespace ServiceAccount and SecretStore (isolated identity)

For isolated backend identity, pre-provision a ServiceAccount and a namespaced SecretStore that authenticates as it through workload identity in each pool namespace. In namespace pools you provision this chain when the namespaces are created, before any Deployment exists, so name the ServiceAccount after the pre-created pool namespace (shown here as <pool-namespace>-eso) rather than a Deployment ID, which isn’t yet known. Each pool namespace hosts one Deployment at a time, so a per-namespace identity is effectively per-Deployment. Annotate the ServiceAccount for your provider. Omit the annotation for Vault Kubernetes auth.
Name the SecretStore the same in every pool namespace — the value of global.dataPlaneFailover.externalSecretManagerName (shown here as astronomer-secret-store). The name must be identical across namespaces. The provider block and identity can differ per namespace.

ESO Role and RoleBinding

Grants the ESO controller ServiceAccount the reconcile verbs it needs inside the namespace. Create it in the astronomer namespace and in each pool namespace.

Token-creation Role and RoleBinding

Required in Mode 3, for any backend: the per-namespace SecretStore authenticates as the per-namespace ServiceAccount (auth.jwt.serviceAccountRef), so ESO must mint that ServiceAccount’s token to assume its identity — whether the backend is AWS (IRSA), GCP (Workload Identity), or Vault (Kubernetes auth). More broadly, ESO needs ServiceAccount-token creation whenever a store authenticates through a serviceAccountRef: always for Vault, and for AWS or GCP only when you authenticate with a ServiceAccount token (workload identity) rather than static credentials or the ESO controller’s own IRSA or GKE Workload Identity. The RoleBinding subject is the ESO controller ServiceAccount (<release-name>-external-secrets in astronomer), because the controller is the process that calls the Kubernetes TokenRequest API. The rule’s resourceNames pins which ServiceAccount the controller may mint a token for — the per-namespace SA <pool-namespace>-eso — so it can assume that one identity and nothing else. Create the Role and RoleBinding alongside the ESO Role in each pool namespace.

Commander Role and RoleBinding

Create in the astronomer namespace and in each pool namespace, binding the <release-name>-commander ServiceAccount.

Generate the platform RBAC (Mode 3)

Mode 3 needs RBAC for every platform component that runs in the pool namespaces, not just ESO. Rather than hand-writing each object, generate the complete set with the provided script. It emits a single bundle that covers both the ESO-specific RBAC in this document and the namespace pools platform-component RBAC in Component RBAC for restricted mode:
  • ESO — the reconcile Role and RoleBinding and the resourceNames-pinned token-creation Role and RoleBinding.
  • Commander — the per-namespace Role and RoleBinding.
  • kube-state-metrics — the per-namespace Role and RoleBinding.
  • Houston DB bootstrapper hook — a Role and RoleBinding created in the astronomer namespace only.
  • Prometheus — a cluster-scoped ClusterRole and ClusterRoleBinding for scrape access.
  • NGINX — a cluster-scoped ClusterRole and ClusterRoleBinding, plus its namespaced config Role and RoleBinding.
Generate and apply the full set across the platform and pool namespaces:
The options are:
  • --release-name — the Helm release name of the platform. The script uses it to prefix every generated ServiceAccount, Role, and ClusterRole (for example <release-name>-commander and <release-name>-external-secrets).
  • --release-namespace — the platform namespace (astronomer), where the component ServiceAccounts live. Every generated RoleBinding names them here as a cross-namespace subject.
  • --namespaces — a comma-separated list of the namespaces to emit per-namespace RBAC for. Include the platform namespace and every pool namespace.
To generate only the limited-privilege installer identity used to run the platform install, rather than the full component set, pass --installer-user instead:
The per-namespace ESO ServiceAccount and SecretStore carry provider-specific identity, so the script doesn’t generate them — create those as shown in Per-namespace ServiceAccount and SecretStore (isolated identity).

Leader-election RBAC (optional ESO high availability)

To run the ESO controller with more than one replica for resiliency, enable leader election so only one replica reconciles secrets at a time. See Run ESO with multiple replicas. In Modes 2 and 3, where you manage ESO’s RBAC, create the leader-election Role and RoleBinding in the astronomer namespace, binding the ESO ServiceAccount: