Security — ArgoCD
The tdp-argo chart supports LDAP authentication through Dex. LDAP is disabled by default; enable it explicitly by editing values.yaml and setting tdp-argo.dex.enabled: true.
When enabled, LDAP uses bind credentials in argocd-secret (keys dex.ldap.bindDN and dex.ldap.bindPW), dex.config in tdp-argo.configs.cm, and RBAC in tdp-argo.rbacConfig.
Prerequisites
- LDAP server reachable from the Kubernetes cluster.
- LDAP bind credentials for Dex.
argocd-secretcreated manually withkubectl create secretbefore the deploy, with thedex.ldap.bindDNanddex.ldap.bindPWkeys.- Dex explicitly enabled with
tdp-argo.dex.enabled: true. tdp-argo.configs.cm.dex.configpopulated with the LDAP host andbaseDN.
Credentials and Secrets
Create the argocd-secret before installing the chart, so Dex reads the bind credentials via references $dex.ldap.bindDN / $dex.ldap.bindPW and Helm does not try to manage it:
kubectl create namespace <NAMESPACE>
kubectl create secret generic argocd-secret \
--from-literal=dex.ldap.bindDN="uid=<LDAP_BIND_USER>,cn=users,cn=accounts,dc=<LDAP_DOMAIN>,dc=com" \
--from-literal=dex.ldap.bindPW="<LDAP_BIND_PASSWORD>" \
-n <NAMESPACE>
Then, keep createSecret: false in the values file so Helm does not manage the Secret:
tdp-argo:
configs:
secret:
createSecret: false
Do not commit passwords. Use private values files, secure CI, or external secret management.
LDAP configuration
tdp-argo:
configs:
cm:
url: https://<ARGOCD_HOST>
dex.config: |
connectors:
- type: ldap
id: ldap
name: LDAP
config:
host: "<LDAP_HOST>:389"
insecureNoSSL: true
insecureSkipVerify: true
bindDN: "$dex.ldap.bindDN"
bindPW: "$dex.ldap.bindPW"
userSearch:
baseDN: "cn=users,cn=accounts,dc=example,dc=com"
filter: "(objectClass=person)"
username: uid
idAttr: uid
emailAttr: mail
nameAttr: givenName
secret:
createSecret: false
dex:
enabled: true
Adjust host, baseDN and SSL flags according to your directory. When createSecret: false, create and maintain argocd-secret by another means, with the keys referenced in dex.config.
The default values.yaml keeps Dex disabled and leaves dex.config empty. In this state, the login page does not show the LDAP/SSO button.
The example above uses plaintext LDAP (<LDAP_HOST>:389 with insecureNoSSL: true and insecureSkipVerify: true), suitable only for test environments. In production, use LDAPS (port 636): set insecureNoSSL: false and insecureSkipVerify: false, change host to <LDAP_HOST>:636, and make the LDAP server CA available to Dex.
Authorization and policies
tdp-argo:
rbacConfig:
policy.default: role:readonly
policy.csv: |
g:devops-admins, role:admin
g:data-platform, role:admin
g:data-read, role:readonly
p, role:ldap-user, applications, *, default/<NAMESPACE>, get
p, role:ldap-user, applications, *, default/<NAMESPACE>, sync
p, role:ldap-user, applications, *, default/<NAMESPACE>, override
p, role:ldap-user, clusters, *, *, get
g, *, role:ldap-user
This block is already active by default in the chart, even without LDAP/Dex enabled.
The groups devops-admins, data-platform, and data-read, and <NAMESPACE>, are example values: replace them with the real groups from your LDAP directory and your project's namespace, otherwise these rules won't apply to any user.
The rbacConfig.policy.csv block combines three rule types:
- Group mappings: lines such as
g:devops-admins, role:adminmap LDAP groups to built-in Argo CD roles. - Custom role permissions:
p, role:ldap-user, ...lines define what theldap-userrole can do. - Default assignment:
g, *, role:ldap-userassigns authenticated users to theldap-userrole by default.
NetworkPolicy
By default, the chart does not create NetworkPolicies (tdp-argo.global.networkPolicy.create: false), keeping traffic open (allow-all).
To enable the upstream allow-all policies:
tdp-argo:
global:
networkPolicy:
create: true
defaultDenyIngress: false
The upstream templates do not allow customizing the rules via Helm values. For a real restriction, apply your own NetworkPolicy — for example, allowing ingress to the Argo CD pods only from a trusted namespace (<NAMESPACE> is the namespace where Argo CD runs; <TRUSTED_NAMESPACE>, the authorized source namespace):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: argocd-restrict-ingress
namespace: <NAMESPACE>
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: In
values:
- <TRUSTED_NAMESPACE>
Installation or update
helm upgrade --install <RELEASE_NAME> \
oci://registry.tecnisys.com.br/tdp/charts/tdp-argo \
-n <NAMESPACE> --create-namespace
After deploy or upgrade, confirm that Dex is running:
kubectl get pods -n <NAMESPACE> | grep dex
kubectl get svc -n <NAMESPACE> | grep dex
Also confirm the RBAC resources created by the chart:
kubectl get serviceaccount -n <NAMESPACE> | grep argo
kubectl get role -n <NAMESPACE> | grep argo
kubectl get rolebinding -n <NAMESPACE> | grep argo
Login
- UI: access
https://<ARGOCD_HOST>and use "LOG IN VIA LDAP" (local login/password is only for local accounts). - CLI:
argocd login <ARGOCD_HOST> --sso
Troubleshooting
Initial checks
Check Argo CD server logs for LDAP connection errors and RBAC evaluation:
kubectl logs -n <NAMESPACE> deployment/<DEPLOYMENT_NAME> -f
Test LDAP from the Dex pod (example with ldapsearch):
kubectl exec -n <NAMESPACE> deployment/<DEPLOYMENT_NAME> -- \
ldapsearch -x -H ldap://<LDAP_HOST>:389 \
-D "<LDAP_BIND_DN>" \
-w "<PASSWORD>" \
-b "<LDAP_USER_BASE_DN>" \
"(uid=<USERNAME>)"
Replace deployment names with actual resources (kubectl get deploy -n <NAMESPACE>).
Common issues
| Problem | Probable cause | What to check |
|---|---|---|
no such host for argocd-dex-server | Dex is disabled or the Dex Service was not created | Set tdp-argo.dex.enabled: true and confirm `kubectl get pods,svc -n <NAMESPACE> |
config referenced key does not exist in secret | dex.config references keys that do not exist in argocd-secret | Confirm the argocd-secret Secret exists and contains dex.ldap.bindDN and dex.ldap.bindPW |
Invalid username or password or invalid LDAP | Connectivity failure, incorrect bind DN/password, or incorrect user search | Validate LDAP server access from the cluster, check bindDN/password, userSearch.baseDN, filter, and LDAP server logs |
| Authenticated user has no permissions | LDAP user/group is not mapped to an Argo CD role | Review tdp-argo.rbacConfig.policy.csv, confirm LDAP group names, and check RBAC evaluation messages in Argo CD logs |