ldaprbacargocdgitops

ArgoCD LDAP : RBAC using LDAP is not working (Not assigning the policies)


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


Solution

  • 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).