Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ ifneq ($(shell echo '$(IMG_VERSION)' | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$$' && e
$(error IMG_VERSION '$(IMG_VERSION)' is not valid semver (expected: Major.Minor.Patch))
endif

# EXTERNAL_SECRETS_VERSION defines the external-secrets release version to fetch helm charts.
EXTERNAL_SECRETS_VERSION ?= v2.5.0
# EXTERNAL_SECRETS_VERSION defines the upstream Helm chart version (SemVer, no "v" prefix).
EXTERNAL_SECRETS_VERSION ?= 2.5.0

# CHANNELS define the bundle channels used in the bundle.
# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable")
Expand Down
12 changes: 5 additions & 7 deletions hack/govulncheck.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,18 @@ set -o errexit
# KNOWN_VULNS_UNTIL (UTC, YYYY-MM-DD): ignores are valid through this date inclusive.
# After it expires, re-run the scan, drop fixed IDs, re-justify remaining ones, and
# advance this date (typically ~2 weeks).
KNOWN_VULNS_UNTIL="2026-08-28"
KNOWN_VULNS_UNTIL="2026-09-21"
#
## Below vulnerabilities are in the kubernetes package, which impacts the server and not the operator, which is the client.
# - https://pkg.go.dev/vuln/GO-2025-3521 - Kubernetes GitRepo Volume Inadvertent Local Repository Access in k8s.io/kubernetes --
# - https://pkg.go.dev/vuln/GO-2025-3547 - Kubernetes kube-apiserver Vulnerable to Race Condition in k8s.io/kubernetes --
# - https://pkg.go.dev/vuln/GO-2025-3521 - Kubernetes GitRepo Volume Inadvertent Local Repository Access in k8s.io/kubernetes
# - https://pkg.go.dev/vuln/GO-2025-3547 - Kubernetes kube-apiserver Vulnerable to Race Condition in k8s.io/kubernetes
#
## Below vulnerabilities are in the go packages, which doesn't impact the operator code and requires the fix to be available downstream.
# - https://pkg.go.dev/vuln/GO-2026-4918 - HTTP/2 infinite loop via SETTINGS_MAX_FRAME_SIZE of 0 in net/http, golang.org/x/net --
# - https://pkg.go.dev/vuln/GO-2026-5026 - x/net/idna: ToUnicode accepts Punycode labels encoding pure ASCII labels --
# - https://pkg.go.dev/vuln/GO-2026-5970 - x/text/unicode/norm: infinite loop on invalid UTF-8 input. --
# - https://pkg.go.dev/vuln/GO-2026-5026 - x/net/idna: ToUnicode accepts Punycode labels encoding pure ASCII labels
# - https://pkg.go.dev/vuln/GO-2026-5972 - Enforce maximum recursion depth in encoding/asn1
# - https://pkg.go.dev/vuln/GO-2026-6090 - Limit handshake messages we are willing to accept post-handshake in crypto/tls
# - https://pkg.go.dev/vuln/GO-2026-6218 - Avoid quadratic complexity in resolvePath in net/url
KNOWN_VULNS_PATTERN="GO-2025-3521|GO-2025-3547|GO-2026-4918|GO-2026-5026|GO-2026-5970|GO-2026-5972|GO-2026-6090|GO-2026-6218"
KNOWN_VULNS_PATTERN="GO-2025-3521|GO-2025-3547|GO-2026-5026|GO-2026-5972|GO-2026-6090|GO-2026-6218"

GOVULNCHECK_BIN="${1:-}"
OUTPUT_DIR="${2:-}"
Expand Down
20 changes: 13 additions & 7 deletions hack/update-external-secrets-manifests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ set -o nounset
set -o pipefail
set -o errexit

EXTERNAL_SECRETS_VERSION=${1:?"missing external-secrets version. Please specify a version from https://github.com/external-secrets/external-secrets/releases"}
EXTERNAL_SECRETS_VERSION=${1:?"missing external-secrets helm chart version. See https://charts.external-secrets.io or https://github.com/external-secrets/external-secrets/releases"}
MANIFESTS_PATH=./_output/manifests
OPERAND_BINDATA=bindata/external-secrets/operand

mkdir -p ${MANIFESTS_PATH}

Expand Down Expand Up @@ -45,8 +46,16 @@ echo "---- Patching external-secrets manifests ----"
# add custom label to all CRDs
./bin/yq e 'select(.kind == "CustomResourceDefinition").metadata.labels."app" = "external-secrets"' -i ${MANIFESTS_PATH}/manifests.yaml

# regenerate all bindata
rm -rf bindata/external-secrets/resources
# refresh helm-rendered operand bindata; preserve operator-owned manifests.
mkdir -p "${OPERAND_BINDATA}"
shopt -s extglob nullglob
(
cd "${OPERAND_BINDATA}"
for manifest in !(namespace_external-secrets.yml|certificate_bitwarden-tls-certs.yml); do
rm -- "${manifest}"
done
)
shopt -u extglob nullglob
rm -f config/crd/bases/customresourcedefinition_*

# split into individual manifest files
Expand All @@ -59,11 +68,8 @@ rm -f config/crd/bases/customresourcedefinition_*
rm ${MANIFESTS_PATH}/customresourcedefinition_fakes.generators.external-secrets.io.yml

# Move resource manifests to appropriate location
mkdir -p bindata/external-secrets/resources

mv ${MANIFESTS_PATH}/customresourcedefinition_* config/crd/bases/
mv ${MANIFESTS_PATH}/*.yml bindata/external-secrets/resources
mv ${MANIFESTS_PATH}/*.yml "${OPERAND_BINDATA}"

# Clean up
rm -r ${MANIFESTS_PATH}

10 changes: 5 additions & 5 deletions harness-evals/constitution.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

The operator deploys and manages upstream **external-secrets** and the optional **bitwarden-sdk-server** plugin via **embedded manifests in `bindata/external-secrets/`**. The operator **never** reimplements upstream secret-sync logic (provider authentication, ExternalSecret reconciliation, generator behavior, Bitwarden SDK protocol). Operator packages reconcile operator CRs and deploy/configure operand workloads only.

**Evidence:** `bindata/external-secrets/resources/` — operand YAML from upstream helm; `pkg/controller/external_secrets/` installs deployments/RBAC/webhooks but contains zero provider-specific secret-fetch logic. `README.md` states the operator uses upstream helm charts.
**Evidence:** `bindata/external-secrets/operand/` — operand YAML from upstream helm; `pkg/controller/external_secrets/` installs deployments/RBAC/webhooks but contains zero provider-specific secret-fetch logic. `README.md` states the operator uses upstream helm charts.

### II. Operand Workloads — Core, Conditional TLS Helper, Plugin

Expand Down Expand Up @@ -56,7 +56,7 @@ Runtime feature toggles are defined on `ExternalSecretsManager.Spec.Features[]`

Webhook TLS uses either cert-manager `Certificate` CRs (`certProvider.certManager.mode == Enabled`) **or** the in-tree `external-secrets-cert-controller` deployment — never both. cert-controller deployment is skipped when cert-manager path is active.

**Evidence:** `pkg/controller/external_secrets/deployments.go` — `certControllerDeploymentAssetName` condition `!isCertManagerConfigEnabled(esc)`; `pkg/controller/external_secrets/certificate.go`; `bindata/external-secrets/resources/certificate_external-secrets-webhook.yml` vs `bindata/external-secrets/resources/secret_external-secrets-webhook.yml`.
**Evidence:** `pkg/controller/external_secrets/deployments.go` — `certControllerDeploymentAssetName` condition `!isCertManagerConfigEnabled(esc)`; `pkg/controller/external_secrets/certificate.go`; `bindata/external-secrets/operand/certificate_external-secrets-webhook.yml` vs `bindata/external-secrets/operand/secret_external-secrets-webhook.yml`.

### VIII. Bindata / Manifest Regeneration — Never Hand-Edit, Always `make update`

Expand All @@ -78,9 +78,9 @@ E2E (`make test-e2e`, build tag `e2e`) requires a live cluster.

### X. RBAC Least Privilege — Explicit Operator and Operand Manifests

Operator RBAC is in `config/rbac/`. Operand RBAC is embedded in `bindata/external-secrets/resources/` and applied by `pkg/controller/external_secrets/rbacs.go`. New permissions MUST be explicit ClusterRole rules in bindata or operator RBAC — not broad cluster-admin grants.
Operator RBAC is in `config/rbac/`. Operand RBAC is embedded in `bindata/external-secrets/operand/` and applied by `pkg/controller/external_secrets/rbacs.go`. New permissions MUST be explicit ClusterRole rules in bindata or operator RBAC — not broad cluster-admin grants.

**Evidence:** `config/rbac/role.yaml`; `bindata/external-secrets/resources/` — per-component RBAC YAML; `pkg/controller/external_secrets/rbacs.go`.
**Evidence:** `config/rbac/role.yaml`; `bindata/external-secrets/operand/` — per-component RBAC YAML; `pkg/controller/external_secrets/rbacs.go`.

### XI. OLM Bundle and Related Images

Expand Down Expand Up @@ -131,7 +131,7 @@ Operator runs in `external-secrets-operator` namespace. Operand runs in `externa
| **OperatorController_Agent** | `pkg/controller/external_secrets/` (incl. `pkg/controller/external_secrets/trusted_ca_bundle.go`), `pkg/controller/external_secrets_manager/`, `pkg/controller/crd_annotator/`, `pkg/operator/setup_manager.go` | Core operand reconciliation, wiring, user trusted CA |
| **ManifestsBindata_Agent** | `bindata/`, `hack/update-external-secrets-manifests.sh`, operand CRDs | Operand manifest refresh, version pins |
| **BitwardenPlugin_Agent** | `Plugins.BitwardenSecretManagerProvider`, bitwarden bindata assets | Bitwarden SDK plugin workload |
| **WebhookTLS_Agent** | `pkg/controller/external_secrets/certificate.go`, webhook deployments under `bindata/external-secrets/resources/` | Webhook TLS paths (cert-manager Certificate vs in-tree cert-controller) |
| **WebhookTLS_Agent** | `pkg/controller/external_secrets/certificate.go`, webhook deployments under `bindata/external-secrets/operand/` | Webhook TLS paths (cert-manager Certificate vs in-tree cert-controller) |
| **RBACSecurity_Agent** | `config/rbac/`, `pkg/controller/external_secrets/rbacs.go`, `pkg/controller/external_secrets/networkpolicy.go` | RBAC and network policy |
| **OLMRelease_Agent** | `bundle/`, `config/manifests/` | CSV, relatedImages |
| **Testing_Agent** | `test/e2e/`, `test/apis/` | Test authoring |
Expand Down
5 changes: 3 additions & 2 deletions harness-evals/harness-docs/ESO_DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ The `hack/update-external-secrets-manifests.sh` script:
- Renders templates (cert-manager enabled + disabled variants)
- Strips Helm labels, relabels `managed-by`
- Customizes core deployment (disables leader election, cluster-store/push-secret reconcilers)
- Splits into individual YAML files in `bindata/external-secrets/`
- Refreshes helm-rendered files under `bindata/external-secrets/operand/` (preserves `namespace_external-secrets.yml` and `certificate_bitwarden-tls-certs.yml`)
- Network policies live under `bindata/external-secrets/networkpolicies/` and are not touched by the script

### 2. Add a New Managed Resource Type

1. Add bindata YAML to `bindata/external-secrets/resources/`
1. Add bindata YAML to `bindata/external-secrets/operand/`
2. Run `make update-bindata` so `pkg/operator/assets/bindata.go` picks up the new asset
3. Add asset name constant in `pkg/controller/external_secrets/constants.go`
4. Add `Decode*ObjBytes` function in `pkg/controller/common/utils.go`
Expand Down
9 changes: 6 additions & 3 deletions harness-evals/harness-docs/architecture/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ pkg/operator/
│ ├── setup_manager.go # Controller registration, default ESM creation
│ └── assets/bindata.go # Generated — DO NOT EDIT
pkg/version/ # Build-time ldflags (commit, version, date)
bindata/external-secrets/ # Source YAML manifests for operand resources
bindata/external-secrets/
├── operand/ # Helm-rendered + operator-preserved operand YAML
└── networkpolicies/ # Operator-owned NetworkPolicy YAML
config/ # CRDs, RBAC, manager deployment, samples, console
bundle/ # OLM bundle (CRDs, metadata, console quickstarts)
hack/ # Build/update scripts
Expand Down Expand Up @@ -158,8 +160,9 @@ Operand manifests are sourced from upstream Helm charts, processed by `hack/upda
```text
upstream Helm chart → helm template (cert-manager enabled + disabled variants)
→ strip Helm labels → relabel managed-by → split into individual YAML files
→ bindata/external-secrets/ → openshift/build-machinery-go add-bindata
→ pkg/operator/assets/bindata.go (DO NOT EDIT)
→ bindata/external-secrets/operand/ (preserves operator-owned namespace + bitwarden cert)
→ bindata/external-secrets/networkpolicies/ (unchanged by update script)
→ openshift/build-machinery-go add-bindata → pkg/operator/assets/bindata.go (DO NOT EDIT)
```

Customizations applied during rendering: leader election disabled, cluster-store and push-secret reconcilers disabled in core deployment.
Expand Down
66 changes: 33 additions & 33 deletions pkg/controller/external_secrets/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,39 +183,39 @@ var (
// asset names are the files present in the root `bindata/` dir, which are then loaded to
// and made available by the pkg/operator/assets package.
const (
externalsecretsNamespaceAssetName = "external-secrets/external-secrets-namespace.yaml"
bitwardenCertificateAssetName = "external-secrets/certificate_bitwarden-tls-certs.yml"
webhookCertificateAssetName = "external-secrets/resources/certificate_external-secrets-webhook.yml"
certControllerClusterRoleAssetName = "external-secrets/resources/clusterrole_external-secrets-cert-controller.yml"
controllerClusterRoleAssetName = "external-secrets/resources/clusterrole_external-secrets-controller.yml"
controllerClusterRoleEditAssetName = "external-secrets/resources/clusterrole_external-secrets-edit.yml"
controllerClusterRoleServiceBindingsAssetName = "external-secrets/resources/clusterrole_external-secrets-servicebindings.yml"
controllerClusterRoleViewAssetName = "external-secrets/resources/clusterrole_external-secrets-view.yml"
certControllerClusterRoleBindingAssetName = "external-secrets/resources/clusterrolebinding_external-secrets-cert-controller.yml"
controllerClusterRoleBindingAssetName = "external-secrets/resources/clusterrolebinding_external-secrets-controller.yml"
bitwardenDeploymentAssetName = "external-secrets/resources/deployment_bitwarden-sdk-server.yml"
controllerDeploymentAssetName = "external-secrets/resources/deployment_external-secrets.yml"
certControllerDeploymentAssetName = "external-secrets/resources/deployment_external-secrets-cert-controller.yml"
webhookDeploymentAssetName = "external-secrets/resources/deployment_external-secrets-webhook.yml"
controllerRoleLeaderElectionAssetName = "external-secrets/resources/role_external-secrets-leaderelection.yml"
controllerRoleBindingLeaderElectionAssetName = "external-secrets/resources/rolebinding_external-secrets-leaderelection.yml"
webhookTLSSecretAssetName = "external-secrets/resources/secret_external-secrets-webhook.yml"
bitwardenServiceAssetName = "external-secrets/resources/service_bitwarden-sdk-server.yml"
webhookServiceAssetName = "external-secrets/resources/service_external-secrets-webhook.yml"
metricsServiceAssetName = "external-secrets/resources/service_external-secrets-metrics.yml"
certControllerMetricsServiceAssetName = "external-secrets/resources/service_external-secrets-cert-controller-metrics.yml"
controllerServiceAccountAssetName = "external-secrets/resources/serviceaccount_external-secrets.yml"
bitwardenServiceAccountAssetName = "external-secrets/resources/serviceaccount_bitwarden-sdk-server.yml"
certControllerServiceAccountAssetName = "external-secrets/resources/serviceaccount_external-secrets-cert-controller.yml"
webhookServiceAccountAssetName = "external-secrets/resources/serviceaccount_external-secrets-webhook.yml"
validatingWebhookExternalSecretCRDAssetName = "external-secrets/resources/validatingwebhookconfiguration_externalsecret-validate.yml"
validatingWebhookSecretStoreCRDAssetName = "external-secrets/resources/validatingwebhookconfiguration_secretstore-validate.yml"
denyAllNetworkPolicyAssetName = "external-secrets/networkpolicy_deny-all.yaml"
allowMainControllerTrafficAssetName = "external-secrets/networkpolicy_allow-api-server-egress-for-main-controller-traffic.yaml"
allowWebhookTrafficAssetName = "external-secrets/networkpolicy_allow-api-server-and-webhook-traffic.yaml"
allowCertControllerTrafficAssetName = "external-secrets/networkpolicy_allow-api-server-egress-for-cert-controller-traffic.yaml"
allowBitwardenServerTrafficAssetName = "external-secrets/networkpolicy_allow-api-server-egress-for-bitwarden-sever.yaml"
allowDNSTrafficAssetName = "external-secrets/networkpolicy_allow-dns.yaml"
externalsecretsNamespaceAssetName = "external-secrets/operand/namespace_external-secrets.yml"
bitwardenCertificateAssetName = "external-secrets/operand/certificate_bitwarden-tls-certs.yml"
webhookCertificateAssetName = "external-secrets/operand/certificate_external-secrets-webhook.yml"
certControllerClusterRoleAssetName = "external-secrets/operand/clusterrole_external-secrets-cert-controller.yml"
controllerClusterRoleAssetName = "external-secrets/operand/clusterrole_external-secrets-controller.yml"
controllerClusterRoleEditAssetName = "external-secrets/operand/clusterrole_external-secrets-edit.yml"
controllerClusterRoleServiceBindingsAssetName = "external-secrets/operand/clusterrole_external-secrets-servicebindings.yml"
controllerClusterRoleViewAssetName = "external-secrets/operand/clusterrole_external-secrets-view.yml"
certControllerClusterRoleBindingAssetName = "external-secrets/operand/clusterrolebinding_external-secrets-cert-controller.yml"
controllerClusterRoleBindingAssetName = "external-secrets/operand/clusterrolebinding_external-secrets-controller.yml"
bitwardenDeploymentAssetName = "external-secrets/operand/deployment_bitwarden-sdk-server.yml"
controllerDeploymentAssetName = "external-secrets/operand/deployment_external-secrets.yml"
certControllerDeploymentAssetName = "external-secrets/operand/deployment_external-secrets-cert-controller.yml"
webhookDeploymentAssetName = "external-secrets/operand/deployment_external-secrets-webhook.yml"
controllerRoleLeaderElectionAssetName = "external-secrets/operand/role_external-secrets-leaderelection.yml"
controllerRoleBindingLeaderElectionAssetName = "external-secrets/operand/rolebinding_external-secrets-leaderelection.yml"
webhookTLSSecretAssetName = "external-secrets/operand/secret_external-secrets-webhook.yml"
bitwardenServiceAssetName = "external-secrets/operand/service_bitwarden-sdk-server.yml"
webhookServiceAssetName = "external-secrets/operand/service_external-secrets-webhook.yml"
metricsServiceAssetName = "external-secrets/operand/service_external-secrets-metrics.yml"
certControllerMetricsServiceAssetName = "external-secrets/operand/service_external-secrets-cert-controller-metrics.yml"
controllerServiceAccountAssetName = "external-secrets/operand/serviceaccount_external-secrets.yml"
bitwardenServiceAccountAssetName = "external-secrets/operand/serviceaccount_bitwarden-sdk-server.yml"
certControllerServiceAccountAssetName = "external-secrets/operand/serviceaccount_external-secrets-cert-controller.yml"
webhookServiceAccountAssetName = "external-secrets/operand/serviceaccount_external-secrets-webhook.yml"
validatingWebhookExternalSecretCRDAssetName = "external-secrets/operand/validatingwebhookconfiguration_externalsecret-validate.yml"
validatingWebhookSecretStoreCRDAssetName = "external-secrets/operand/validatingwebhookconfiguration_secretstore-validate.yml"
denyAllNetworkPolicyAssetName = "external-secrets/networkpolicies/deny-all.yml"
allowMainControllerTrafficAssetName = "external-secrets/networkpolicies/allow-api-server-egress-for-main-controller-traffic.yml"
allowWebhookTrafficAssetName = "external-secrets/networkpolicies/allow-api-server-egress-for-webhook-traffic.yml"
allowCertControllerTrafficAssetName = "external-secrets/networkpolicies/allow-api-server-egress-for-cert-controller-traffic.yml"
allowBitwardenServerTrafficAssetName = "external-secrets/networkpolicies/allow-api-server-egress-for-bitwarden-sever.yml"
allowDNSTrafficAssetName = "external-secrets/networkpolicies/allow-dns.yml"
)

var (
Expand Down
Loading