-
Notifications
You must be signed in to change notification settings - Fork 6.9k
Description
Summary
Add $file:/path/to/secret as a new reference format in ArgoCD's $-prefixed secret substitution, allowing config values to be resolved from files on disk.
Motivation
ArgoCD's $variable substitution currently only reads from Kubernetes Secrets ($key from argocd-secret, or $secretName:key from labeled secrets). There is no way to reference a secret value from a file.
This forces users who manage secrets outside of Kubernetes Secret objects into workarounds like bypassing argocd-dex rundex entirely with wrapper scripts, or using Kustomize patches to override the dex-server command — both fragile and hard to maintain across upgrades.
A file-based reference covers a wide range of secret delivery mechanisms:
- Secrets Store CSI Driver (GCP Secret Manager, AWS Secrets Manager, Azure Key Vault, HashiCorp Vault) — mounts external secrets as files without creating K8s Secret objects in etcd
- Projected volumes — assembling secrets from multiple sources
- Init containers — fetching secrets at startup and writing to a shared volume
- Any orchestration that places a secret on the filesystem before the main container starts
Proposal
Extend ReplaceStringSecret in util/settings/settings.go to recognize a $file: prefix:
// File-based secret reference: $file:/path/to/secret
if strings.HasPrefix(val, "$file:") {
filePath := val[len("$file:"):]
data, err := os.ReadFile(filePath)
if err != nil {
log.Warnf("config referenced file '%s', but could not read: %v", filePath, err)
return val
}
return strings.TrimSpace(string(data))
}Since ReplaceStringSecret is the central substitution function used by ReplaceMapSecrets, this automatically works everywhere $ references are currently supported — dex.config, oidc.config, and any other config value.
Usage
# argocd-cm ConfigMap
dex.config: |
connectors:
- type: oidc
name: Google
config:
issuer: https://accounts.google.com
clientID: $file:/etc/dex-secrets/client-id
clientSecret: $file:/etc/dex-secrets/client-secretThe volume source is up to the user — CSI, projected volume, init container, etc. For example, with Secrets Store CSI Driver:
dex:
volumes:
- name: dex-secrets
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: gcp-dex-config
volumeMounts:
- name: dex-secrets
mountPath: /etc/dex-secrets
readOnly: trueNo wrapper scripts, no command overrides, no Kustomize patches. Standard argocd-dex rundex handles everything. Fully backwards compatible — existing $key and $secretName:key syntax unchanged