Secret injection in GitOps applications
Use Harness secrets and expressions directly in Argo CD manifests via the Config Management Plugin. No Delegate required.
The Harness Argo CD Config Management Plugin resolves secret expressions in your manifests during Argo CD's rendering phase, before anything is applied to the cluster. No Harness Delegate required.
What you will learn from this topic
How the plugin intercepts and resolves secret expressions during manifest rendering
How to set up and use secret injection in three steps
What secret sources are supported (Harness, Vault, external managers)
What the security model is and how to harden your setup
What limitations exist with the plugin
How to troubleshoot common secret resolution issues
Before you begin
Before using secret injection, ensure you have:
GitOps Agent: Agent with the plugin enabled. Go to Harness expressions in GitOps manifests for installation steps.
Secrets configured: Secrets in Harness Secret Manager, Vault, or another integrated secret manager. Go to Harness Secret Manager to create secrets.
Kubernetes manifests: A Git repository containing Kubernetes manifests where you want to inject secrets.
Manifest rendering with the Config Management Plugin
Argo CD normally controls manifest rendering end-to-end. The Config Management Plugin (CMP) intercepts that phase and hands it to Harness, which:
Scans manifests for
<+secrets.getValue("ref")>expressionsResolves secret references against Harness Secret Manager (or Vault/external managers)
Injects actual values into the manifest
Returns the rendered manifest to Argo CD for deployment
Because resolution happens at render time, you do not need to manually sync after adding expressions; Argo CD re-renders on the next sync and the values are there.
Delegate Requirements
The GitOps agent handles secret resolution directly via the CMP sidecar. This makes it viable for pure GitOps setups where you want only the Argo CD stack, without running a Delegate alongside it.
Configure Harness secrets in GitOps
Prerequisites: Plugin enabled on your agent (see setup guide) · Secret exists in Harness.
Step 1. Create a secret in Harness
Go to your project → Secrets → New Secret → Text secret. Note the identifier (e.g., prodDbPassword).
Step 2. Reference it in a kind: Secret manifest
Or using a service variable of type Secret:
Step 3. Commit, push, sync
The plugin resolves the expression at render time. The deployed Secret in the cluster contains the actual value (base64-encoded as Kubernetes expects).
Verify:
Supported secret sources
Harness Secret Manager
Built-in. Create a Text secret, reference by identifier.
HashiCorp Vault
Configure Vault connector in Harness; reference secrets via Harness secret entity pointing to Vault path
Other external managers
Any secret manager with a Harness connector
Reference syntax
Project
<+secrets.getValue("secretIdentifier")>
Account
<+secrets.getValue("account.secretIdentifier")>
Org
<+secrets.getValue("org.secretIdentifier")>
Using service/environment variables (two-stage resolution)
When a Harness variable is defined as type Secret, it resolves in two stages:
Manifest generation
<+serviceVariables.name> → <+secrets.getValue("account.ref")>
Deployment time
<+secrets.getValue(...)> → actual secret value injected
Security model
Secret Visibility and Access
ARGO CD CACHES RENDERED MANIFESTS, INCLUDING INJECTED SECRET VALUES, IN REDIS
The rendered manifests (with real secret values) are stored in Argo CD's Redis instance and also exposed via the repo-server gRPC API. Anyone with access to either can read the resolved values.
Argo CD Redis
Cached rendered manifests with injected values
Argo CD repo-server API
Same cached manifests via gRPC
Harness UI
Secret values are masked
Kubernetes cluster
Secrets stored base64-encoded; requires cluster RBAC to read
Hardening checklist
Network policies: block direct access to Argo CD's Redis and repo-server from workloads that do not need it. Verify your cluster enforces these policies.
Dedicated Argo CD cluster: run Argo CD on a cluster with no other tenant workloads; minimizes lateral movement risk.
RBAC: restrict who can read Kubernetes
Secretresources and who can access Argo CD components.Audit logs: monitor access to Argo CD components for unauthorized reads.
For more, see Argo CD secret management: mitigating risks of injection plugins.
Best practices
Define secrets in Harness before referencing them in manifests
Test in non-production environments before relying on secret injection in production
Use RBAC to control who can modify secret expressions in
ApplicationmanifestsAvoid
HELM_ARGS: it passes unsanitized strings to the shell. See HELM_ARGS warning
Limitations
Application source type is reported as Plugin
When the CMP is active, Argo CD reports source type as Plugin instead of Helm/Directory. Features that rely on source type detection (Helm chart path listing, auto-type detection) do not work. Go to the upstream issue for details.
Workaround: Specify application source paths manually instead of relying on Argo CD's path discovery UI.
Kustomize secretGenerator is unverified
Secret injection into kind: Secret objects produced by Kustomize's secretGenerator has not been verified. secretGenerator output is already base64-encoded before the plugin sees it, and the plugin does not re-encode substituted values. Use plain Secret manifests (not secretGenerator) until this is confirmed.
Troubleshooting
Secret not found
Confirm the secret exists in Harness (correct scope: project, org, or account).
Check the identifier in the expression matches exactly (case-sensitive, no extra spaces).
Confirm you have permission to read the secret at that scope.
Expression not replaced
<+secrets.getValue("ref")> appears literally in the deployed pod:
Verify the plugin is installed:
kubectl get pods -n <agent-namespace>should showargocd-harness-pluginas a running container on the repo-server pod.Check sidecar logs:
kubectl logs -n <agent-namespace> <repo-server-pod> -c argocd-harness-pluginConfirm expression syntax:
<+secrets.getValue("identifier")>with double quotes.
Secret resolves to empty
Secret exists but has no value; check in Harness Secrets.
Access denied; verify RBAC permissions for the GitOps agent service account.
Next steps
Harness expressions in GitOps manifests: Tool detection, non-secret expressions, and agent setup
External Secrets integration: Integrate External Secrets Operator with Harness GitOps
SOPS integration: Use Mozilla SOPS for encrypted secrets in Git
Create a GitOps application: Set up your first ArgoCD application in Harness
Last updated
Was this helpful?