LDAP access to your kubernetes cluster can be confusing to configure.
This guide should assist you with troubleshooting some common issues and misconfigurations. You can use our official documentation here as a base.
However, we can't provide a comprehensive configuration guide as every LDAP environment is different. Your LDAP server might be linux based, or Microsoft ActiveDirectory, or one of the many web based LDAP solutions. Regardless of how your LDAP server is configured you should be able to use this guide to successfully configure LDAP or identify any blocking issues preventing you from doing so.
1. Using ldapsearch
ldapsearch is a commandline utilty which we will use to determine what values are available for us to configure, as well as to determine if our ldap accounts have the correct permissions. Install ldapsearch on any computer that has access to both the kubernetes cluster and the ldap server, such as a bastion, bootstrap or worker node.
sudo yum install openldap-clients
LDAP queries we will use in this guide will all use the following format:
ldapsearch -x -W \ -D "" \ -b "" \ -H ldap://:389 \ ''
The -W flag specifies to prompt the user for a password so that it does not need to be used in plaintext as part of the query
DN or Distinguished Name is the full name of an LDAP object.
Bind DN is the DN (user account) that we use to authenticate with the ldap server. We will use the same Bind DN for all ldap queries.
Base DN specifies the top level for our query. It is important to narrow your search results as much as possible so that you only return information that is relevant to your query.
Some values are case sensitive so please use the exact values your LDAP server queries output as it is difficult to troubleshoot this later.
2. Add an ldap connector account
Dex needs to know what account it should use to query for users and groups, we must verify this account is valid before any further configuration can be done. For this example, I am using the LDAP account ldapReader
The DN for ldapReader is: cn=ldapReader,ou=users,dc=daclusta
Let's confirm that the ldapReader account can search for itself. Our search filter will just be the cn (common name) of the ldapReader account because we currently don't know anything else about it besides its DN.
ldapsearch -x -W -D "cn=ldapReader,ou=users,dc=daclusta" -b "ou=users,dc=daclusta" -H ldap://10.4.6.2:389 '(cn=ldapReader)'
This search should output the following:
dn: cn=ldapReader,ou=users,dc=daclusta sn: ldapReader cn:: IGxkYXBSZWFkZXI= uid: ldapreader userPassword:: Y2F0 uidNumber: 1001 gidNumber: 504 homeDirectory: /home/users/ldapreader objectClass: inetOrgPerson objectClass: posixAccount objectClass: top loginShell: /bin/bash
This tells us all of the properties of this user. Once your query is able to return something like the above, you've confirmed the values needed for your ldap connector account!
Using the example yaml from the documentation as a base, fill in the values so they match the object properties returned by our ldap query. We need to fill in the following values:
password: the password you are queried for in your above ldap search.
host: the ldap server address. By default it will use port 389, manually specify port to override this.
bindDN: in our example it will be cn=ldapReader,ou=users,dc=daclusta as that is the DN for our ldap connector account.
3. Define a userSearch configuration
userSearch allows ldap to query specific users mapped to individual roleBindings:
userSearch: baseDN: BaseDN to start the search from. filter: Optional filter to apply when searching the directory. username: Username attribute used for comparing user entries. idAttr: String representation of the user. emailAttr: Required. Attribute to map to Email.
To start, lets query a user that we want to enable for full cluster admin access:
ldapsearch -x -W -D "cn=ldapReader,ou=users,dc=daclusta" -b "ou=users,dc=daclusta" -H ldap://10.4.6.2:389 '(cn=Michael Scott)'
dn: cn=Michael Scott,ou=users,dc=daclusta givenName: Michael sn: Scott cn: Michael Scott uid: mscott uidNumber: 1002 gidNumber: 501 homeDirectory: /home/users/mscott loginShell: /bin/sh objectClass: inetOrgPerson objectClass: posixAccount objectClass: top
Given the above output, we can fill in the fields that correlate to this user's properties:
userSearch: baseDN: ou=users,dc=daclusta filter: "(objectClass=inetOrgPerson)" username: uid idAttr: uid emailAttr: uid
Our ldap user account does not store email information, but it is required by the dex ldap yaml file. You may not be able to or desire to configure your LDAP server with email information but you can substitute some other identifying value of the user account, such as the uid.
4. Define a groupSearch configuration
groupSearch: baseDN: BaseDN to start the search from. filter: Optional filter to apply when searching the directory. userAttr: Value that uniquely identifies a user, Must exactly match a value in the Group's member list. groupAttr: Value used to list members of this group. Must exactly match a value in the User's object nameAttr: Represents group name.
In order to define a groupSearch we first need to have information about a user in the group, otherwise we wont be able to match the userAttr to the groupAttr. We'll use the query for the user Micahel Scott above. The next step is to query information about a group that Michael Scott belongs to. For this example we have added Michel Scott to the clusterAdministrators group. We query it the same way we would a user:
ldapsearch -x -W -D "cn=ldapReader,ou=users,dc=daclusta" -b "ou=employees,dc=daclusta" -H ldap://10.4.6.2:389 '(cn=clusterAdministrators)'
dn: cn=clusterAdministrators,ou=employees,dc=daclusta gidNumber: 501 objectClass: posixGroup objectClass: top cn: clusterAdministrators memberUid: mscott memberUid: tflenderson
Note that the clusterAdministrators group is not in the users OU (organizational unit) but the employees OU.
baseDN: ou=employees,dc=daclusta
We can see that the only objectClass available is posixGroup, so we will specify that as our filter
filter: "(objectClass=posixGroup)"
The next values to configure are userAttr and groupAttr. Start with the groupAttr as there is only one correct variable that we can use here. We notice in the clusterAdministrators object that there are multiple users listed via memberUid:
memberUid: mscott memberUid: tflenderson
We need to match the value of memberUid to the value of an attribute of the Michael Scott user so that when the user tries to log in, Dex will correctly find that he is a member of the right group and allow access. The only value in the user object that matches the memberUid attriute for Michael Scott is the uid with a value of mscott, so we will use that. Together, our two values will look like this:
userAttr: uid groupAttr: memberUid
The last value to add is the groups name, and the attribute of the clusterAdministrators object that correlates to that is the cn (Common Name)
nameAttr: cn
All together our groupSearch looks like:
groupSearch: baseDN: ou=employees,dc=daclusta filter: "(objectClass=posixGroup)" userAttr: uid groupAttr: memberUid nameAttr: cn
The next step is to create some roleBindings for our users and groups in a file called bindings.yaml. The --- separator indicates that these are two different objects in the same yaml file.
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mscott-admin roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: mscott --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: clusterAdminGroup roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - apiGroup: rbac.authorization.k8s.io kind: Group name: oidc:clusterAdministrators
5. Applying and Testing Configuration
After we have created the rolebindings, we must then create these objects in kubernetes by applying them:
kubectl apply -f ldap.yaml secret/ldap-password created connector.dex.mesosphere.io/ldap created
kubectl apply -f bindings.yaml clusterrolebinding.rbac.authorization.k8s.io/mscott-admin created clusterrolebinding.rbac.authorization.k8s.io/clusterAdminGroup created
We can see that the objects have been created and we can modify them or check them by referring to the names listed above. Next, lets check if the user mscott in the group clusterAdministrator is properly authenticated:
kubectl auth can-i get pods --namespace kube-system --as mscott --as-group oidc:clusterAdministrators --as-group system:authenticated
This will either return yes or no depending on if your authentication was successful. The next step is to attempt generating a user token and attempt logging into the ops-portal. You can navigate to the cluster and attempt to generate a token via the url: https:///token. If it was successful, you should see the following output:
{ "iss": "https://10.4.6.60/dex", "sub": "CgZtc2NvdHQSE2RleC1jb250cm9sbGVyLWxkYXA", "aud": "kube-apiserver", "exp": 1616633273, "iat": 1616546873, "at_hash": "q5EaCZV9369uKghdiEDF_w", "email": "mscott", "email_verified": true, "groups": [ "clusterAdministrators" ] }
If you do not see any groups populated, then your groupSearch is misconfigured and you will need to identify any typos or errors before continuing. Your login may appear successful even though the group is not added, so ensure that everything appears correct. The last test is to attempt to log into the ops-portal via:
./konvoy get ops-portal Navigate to the URL below to access various services running in the cluster. https://10.4.6.60/ops/landing
If your user is not in an authorized group, or your rolebinding for that user or group does not have the proper permissions, you will only see:
Not Authorized
To troubleshoot issues logging in with LDAP credentials, check the dex-kubeaddons pod:
kubectl logs dex-kubeaddons-86ddd8455d-v5dh6 -n kubeaddons time="2021-03-24T00:47:52Z" level=info msg="performing ldap search ou=users,dc=daclusta sub (&(objectClass=inetOrgPerson)(uid=mscott))" time="2021-03-24T00:47:52Z" level=info msg="username \"mscott\" mapped to entry cn=Michael Scott,ou=users,dc=daclusta" time="2021-03-24T00:47:52Z" level=info msg="performing ldap search ou=employees,dc=daclusta sub (&(objectClass=posixGroup)(memberUid=mscott))" time="2021-03-24T00:47:53Z" level=info msg="login successful: connector \"dex-controller-ldap\", username=\"\", preferred_username=\"\", email=\"mscott\", groups=[\"clusterAdministrators\"]"
This guide should help to facilitate your LDAP configuration with Konvoy. If you still have issues, please open a ticket with our support team for further guidance. Be sure to include a ./konvoy diagnose bundle as well as details about the users/groups you are attempting to log in with.