Hello. I want to integrate LDAP with ArgoCD, using Dex.
The problem is, the LDAP user that I login with, doesn't get the necessary policies that I've specified in argocd-rbac-cm
in policy.csv
;
But the confusing thing is it SUCCESSFULY gets the policy.default to whatever role I set to !
To Reproduce
These are the necessary configs that I have set.
argocd-cm
:
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
labels:
app.kubernetes.io/component: server
app.kubernetes.io/instance: argocd
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
app.kubernetes.io/version: v2.10.6
helm.sh/chart: argo-cd-6.7.11
k8slens-edit-resource-version: v1
annotations:
meta.helm.sh/release-name: argocd
meta.helm.sh/release-namespace: argocd
data:
admin.enabled: 'true'
application.instanceLabelKey: argocd.argoproj.io/instance
dex.config: |-
logger:
level: debug
connectors:
- type: ldap
name: My Company
id: ad
config:
# Ldap server address
host: "ldap.mycompany.com:389"
insecureNoSSL: true
insecureSkipVerify: true
# Variable name stores ldap bindDN in argocd-secret
bindDN: 'CN=DevOps Local Cluster Service Account,OU=Other,OU=Service Accounts,OU=_Special,OU=Users,OU=My Company Accounts,DC=mycompany,DC=com'
# Variable name stores ldap bind password in argocd-secret
bindPW: 'password'
usernamePrompt: "Username"
# Ldap user serch attributes
userSearch:
baseDN: "OU=Users,OU=My Company Accounts,DC=mycompany,DC=com"
username: mail
idAttr: mail
nameAttr: displayName
emailAttr: mail
exec.enabled: 'false'
server.rbac.log.enforce.enable: 'true'
timeout.hard.reconciliation: 0s
timeout.reconciliation: 180s
url: https://argo.mycompany.com
argocd-rbac-cm
:
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
labels:
app.kubernetes.io/component: server
app.kubernetes.io/instance: argocd
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: argocd-rbac-cm
app.kubernetes.io/part-of: argocd
app.kubernetes.io/version: v2.10.6
helm.sh/chart: argo-cd-6.7.11
k8slens-edit-resource-version: v1
annotations:
meta.helm.sh/release-name: argocd
meta.helm.sh/release-namespace: argocd
data:
policy.csv: |+
p, role:Testrole, applications, create, test/*, allow
p, role:Testrole, applications, delete, test/*, allow
p, role:Testrole, applications, get, test/*, allow
p, role:Testrole, applications, override, test/*, allow
p, role:Testrole, applications, sync, test/*, allow
p, role:Testrole, applications, update, test/*, allow
p, role:Testrole, logs, get, test/*, allow
p, role:Testrole, exec, create, test/*, allow
p, role:Testrole, projects, get, test, allow
g, behnia.f@mycompany.com, role:admin
policy.default: role:Testrole
policy.matchMode: glob
scopes: '[groups]'
Expected behavior
I expect that when I login with LDAP user behnia.f@mycompany.com
, it gets the policy of g, behnia.f@mycompany.com, role:admin
which is admin ; But it gets the default policy, which is policy.default: role:Testrole
.
Screenshots
For example, when I want to see the list of clusters, I get this error (something that admin
policy is capable of):
Version
argocd@argocd-server-7db5c6b77-2nzpf:~$ argocd version
argocd: v2.10.6+d504d2b
BuildDate: 2024-04-05T00:27:47Z
GitCommit: d504d2b1d92f0cf831a124a5fd1a96ee29fa7679
GitTreeState: clean
GoVersion: go1.21.3
Compiler: gc
Platform: linux/amd64
Logs
argocd-server
logs (debug mode) when I try to create a create a project called TestForGithub:
time="2024-04-20T10:55:52Z" level=info msg="ArgoCD API Server is starting" built="2024-04-05T00:27:47Z" commit=d504d2b1d92f0cf831a124a5fd1a96ee29fa7679 namespace=argocd port=8080 version=v2.10.6+d504d2b
time="2024-04-20T10:55:52Z" level=info msg="Starting configmap/secret informers"
time="2024-04-20T10:55:52Z" level=info msg="Configmap/secret informer synced"
time="2024-04-20T10:55:52Z" level=info msg="invalidated cache for resource in namespace: argocd with the name: argocd-notifications-cm"
time="2024-04-20T10:55:52Z" level=info msg="invalidated cache for resource in namespace: argocd with the name: argocd-notifications-secret"
time="2024-04-20T10:55:52Z" level=info msg="Creating client app (argo-cd)"
time="2024-04-20T10:55:52Z" level=info msg="argocd v2.10.6+d504d2b serving on port 8080 (url: https://argo.mycompany.com, tls: false, namespace: argocd, sso: true)"
time="2024-04-20T10:55:52Z" level=info msg="Enabled application namespace patterns: argocd"
time="2024-04-20T10:55:52Z" level=info msg="0xc0017408a0 subscribed to settings updates"
time="2024-04-20T10:55:52Z" level=info msg="Starting rbac config informer"
time="2024-04-20T10:55:52Z" level=info msg="RBAC ConfigMap 'argocd-rbac-cm' added"
time="2024-04-20T10:56:10Z" level=info msg="Initializing OIDC provider (issuer: https://argo.mycompany.com/api/dex)"
time="2024-04-20T10:56:10Z" level=info msg="OIDC supported scopes: [openid email groups profile offline_access]"
time="2024-04-20T10:56:10Z" level=info msg="received unary call /project.ProjectService/List" grpc.method=List grpc.request.claims="{\"at_hash\":\"Z-mWH5Z9XXwWAaGleL5JSA\",\"aud\":\"argo-cd\",\"c_hash\":\"lNVuQ7fISUG2rYqUaV5t_g\",\"email\":\"behnia.f@mycompany.com\",\"email_verified\":true,\"exp\":1713695788,\"iat\":1713609388,\"iss\":\"https://argo.mycompany.com/api/dex\",\"name\":\"Behnia Farahbod [ My Company - ITS ]\",\"sub\":\"ChdiZWhuaWEuZkBtdG5pcmFuY2VsbC5pchICYWQ\"}" grpc.request.content= grpc.service=project.ProjectService grpc.start_time="2024-04-20T10:56:10Z" span.kind=server system=grpc
time="2024-04-20T10:56:10Z" level=debug msg="enforce failed" claims="map[at_hash:Z-mWH5Z9XXwWAaGleL5JSA aud:argo-cd c_hash:lNVuQ7fISUG2rYqUaV5t_g email:behnia.f@mycompany.com email_verified:true exp:1.713695788e+09 iat:1.713609388e+09 iss:https://argo.mycompany.com/api/dex name:Behnia Farahbod [ My Company - ITS ] sub:ChdiZWhuaWEuZkBtdG5pcmFuY2VsbC5pchICYWQ]" groups="[]" project=default rval="[map[at_hash:Z-mWH5Z9XXwWAaGleL5JSA aud:argo-cd c_hash:lNVuQ7fISUG2rYqUaV5t_g email:behnia.f@mycompany.com email_verified:true exp:1.713695788e+09 iat:1.713609388e+09 iss:https://argo.mycompany.com/api/dex name:Behnia Farahbod [ My Company - ITS ] sub:ChdiZWhuaWEuZkBtdG5pcmFuY2VsbC5pchICYWQ] projects get default]" scopes="[groups]" subject=ChdiZWhuaWEuZkBtdG5pcmFuY2VsbC5pchICYWQ
time="2024-04-20T10:56:10Z" level=info msg="finished unary call with code OK" grpc.code=OK grpc.method=List grpc.service=project.ProjectService grpc.start_time="2024-04-20T10:56:10Z" grpc.time_ms=16.151 span.kind=server system=grpc
time="2024-04-20T10:56:11Z" level=info msg="received unary call /session.SessionService/GetUserInfo" grpc.method=GetUserInfo grpc.request.claims="{\"at_hash\":\"Z-mWH5Z9XXwWAaGleL5JSA\",\"aud\":\"argo-cd\",\"c_hash\":\"lNVuQ7fISUG2rYqUaV5t_g\",\"email\":\"behnia.f@mycompany.com\",\"email_verified\":true,\"exp\":1713695788,\"iat\":1713609388,\"iss\":\"https://argo.mycompany.com/api/dex\",\"name\":\"Behnia Farahbod [ My Company - ITS ]\",\"sub\":\"ChdiZWhuaWEuZkBtdG5pcmFuY2VsbC5pchICYWQ\"}" grpc.request.content= grpc.service=session.SessionService grpc.start_time="2024-04-20T10:56:11Z" span.kind=server system=grpc
time="2024-04-20T10:56:11Z" level=info msg="finished unary call with code OK" grpc.code=OK grpc.method=GetUserInfo grpc.service=session.SessionService grpc.start_time="2024-04-20T10:56:11Z" grpc.time_ms=1.069 span.kind=server system=grpc
2024/04/20 10:56:19 proto: tag has too few fields: "-"
2024/04/20 10:56:19 proto: tag has unknown wire type: "int64,1,opt,name=iat"
2024/04/20 10:56:19 proto: tag has unknown wire type: "int64,2,opt,name=exp"
time="2024-04-20T10:56:19Z" level=info msg="received unary call /project.ProjectService/Create" grpc.method=Create grpc.request.claims="{\"at_hash\":\"Z-mWH5Z9XXwWAaGleL5JSA\",\"aud\":\"argo-cd\",\"c_hash\":\"lNVuQ7fISUG2rYqUaV5t_g\",\"email\":\"behnia.f@mycompany.com\",\"email_verified\":true,\"exp\":1713695788,\"iat\":1713609388,\"iss\":\"https://argo.mycompany.com/api/dex\",\"name\":\"Behnia Farahbod [ My Company - ITS ]\",\"sub\":\"ChdiZWhuaWEuZkBtdG5pcmFuY2VsbC5pchICYWQ\"}" grpc.request.content="project:<TypeMeta:<kind:\"\" apiVersion:\"\" > metadata:<name:\"TestForGithub\" generateName:\"\" namespace:\"\" selfLink:\"\" uid:\"\" resourceVersion:\"\" generation:0 creationTimestamp:<0001-01-01T00:00:00Z> > spec:<description:\"\" permitOnlyProjectScopedClusters:false > status:<> > " grpc.service=project.ProjectService grpc.start_time="2024-04-20T10:56:19Z" span.kind=server system=grpc
time="2024-04-20T10:56:19Z" level=debug msg="enforce failed" claims="map[at_hash:Z-mWH5Z9XXwWAaGleL5JSA aud:argo-cd c_hash:lNVuQ7fISUG2rYqUaV5t_g email:behnia.f@mycompany.com email_verified:true exp:1.713695788e+09 iat:1.713609388e+09 iss:https://argo.mycompany.com/api/dex name:Behnia Farahbod [ My Company - ITS ] sub:ChdiZWhuaWEuZkBtdG5pcmFuY2VsbC5pchICYWQ]" groups="[]" project= rval="[map[at_hash:Z-mWH5Z9XXwWAaGleL5JSA aud:argo-cd c_hash:lNVuQ7fISUG2rYqUaV5t_g email:behnia.f@mycompany.com email_verified:true exp:1.713695788e+09 iat:1.713609388e+09 iss:https://argo.mycompany.com/api/dex name:Behnia Farahbod [ My Company - ITS ] sub:ChdiZWhuaWEuZkBtdG5pcmFuY2VsbC5pchICYWQ] projects create TestForGithub]" scopes="[groups]" subject=ChdiZWhuaWEuZkBtdG5pcmFuY2VsbC5pchICYWQ
time="2024-04-20T10:56:19Z" level=warning msg="finished unary call with code PermissionDenied" error="rpc error: code = PermissionDenied desc = permission denied: projects, create, TestForGithub, sub: ChdiZWhuaWEuZkBtdG5pcmFuY2VsbC5pchICYWQ, iat: 2024-04-20T10:36:28Z" grpc.code=PermissionDenied grpc.method=Create grpc.service=project.ProjectService grpc.start_time="2024-04-20T10:56:19Z" grpc.time_ms=1.448 span.kind=server system=grpc
The problem was due to the lack of a groupSearch
section in my dex.config. It is necessary (although it's not mentioned in ArgoCD documentations).
So the correct dex.config
would be something like this:
dex.config: |-
logger:
level: debug
connectors:
- type: ldap
name: My Company
id: ad
config:
# Ldap server address
host: "ldap.mycompany.com:389"
insecureNoSSL: true
insecureSkipVerify: true
# Variable name stores ldap bindDN in argocd-secret
bindDN: 'CN=DevOps Local Cluster Service Account,OU=Other,OU=Service Accounts,OU=_Special,OU=Users,OU=My Company Accounts,DC=mycompany,DC=com'
# Variable name stores ldap bind password in argocd-secret
bindPW: 'password'
usernamePrompt: "Username"
# Ldap user serch attributes
userSearch:
baseDN: "OU=Users,OU=My Company Accounts,DC=mycompany,DC=com"
username: mail
idAttr: mail
nameAttr: displayName
emailAttr: mail
# Ldap group serch attributes - Necessary
groupSearch:
baseDN: "OU=Users,OU=My Company Accounts,DC=mycompany,DC=com"
filter: "(objectClass=person)"
userMatchers:
- userAttr: dn
groupAttr: distinguishedName
nameAttr: sAMAccountName
Also take a look of the userMatchers
that I used:
userMatchers:
- userAttr: dn
groupAttr: distinguishedName
This will match a user(identified by it's dn
) with the groups that the user is in. I used distinguishedName
(which is same as dn
), to NOT list the groups of the user. Because I just wanted the user itself; so the result would be a group which only contains the user(I will post an screenshot of the ArgoCD panel here soon).