openLDAP – Linux Client LDAP Integration

Linux Client LDAP Integration
This entry is part 6 of 8 in the series Openldap Tutorial

In the previous article we saw how to integrate Graylog with LDAP. In this section we will discuss about Linux client LDAP Integration.

What we will do ?

Based on our scenario, we will implement key based authentication to a linux client connected to LDAP. Like previous examples, two users will have access to the server. One of the user is an admin and will have sudo privileges. The other will be considered a Dev user, who has sudo access only to a specific application id ( appid )

 

We first need to create a separate group for managing access to servers. Let’s get our hands dirty and start doing it.

LINUX CLIENT DIT - UPDATED

 

We have already got few containers and entries created in the previous section when we integrated Graylog with LDAP.  We need to create the ones marked in dotted red boundaries in the diagram above.

 

Create a container ( ou=server ) for managing servers

Create a file named serverou.ldif with the below content,

dn: ou=server,ou=group,dc=devopsideas,dc=com
objectClass: organizationalUnit
ou: server
description: Group for managing servers

Run the below command to implement the change,

ldapadd -Z -W -D cn=admin,dc=devopsideas,dc=com -f serverou.ldif

 

Overcoming posixGroup and groupOfNames caveat

We will be creating server group objects of type posixGroup under ou=server container. The posixgroup is required to provide the translation between group id numbers and their name. We’ll be providing access to servers based on membership of the groups. posixGroup’s member attribute is called memberUID and simply lists the uid of the member. Using this alone, there’s really no solid way to identify the specific distinguished name of the group member.

The problem we have is, memberOf attribute is part of groupOfNames objectClass. We cannot use both posixGroup and groupOfNames together since both are STRUCTURAL objectClasses ( An entry can have only one STRUCTURAL object class ).

To overcome this, we need to create a custom objectClass that will be a clone of posixGroup but of type  AUXILIARY instead of STRUCTURAL. Hence we will be able to use groupOfNames along with the custom posixGroup which is almost identical to posixGroup except the class type.

The posixGroup exists in nis schema and hence we’ll make the change there.

Create a file named schema_update.ldif with the below content

dn: cn={2}nis,cn=schema,cn=config
changetype: modify
add: olcObjectClasses
olcObjectClasses: {13}( 1.3.6.1.1.1.2.13 NAME 'customposixGroup' DESC 'Abstraction of a group of accounts' AUXILIARY MUST ( cn $ gidNumber ) MAY ( userPassword $ memberUid $ description $ member ) )

{2} denotes the order. You can refer ‘/etc/ldap/slapd.d/cn\=config/cn\=schema’ to get this.

We have named the custom group as customposixGroup. This contains all the attributes that are part of posixGroup except the class type marked as ‘AUXILIARY’.

Run the below command to make the changes,

ldapmodify -W -D cn=admin,cn=config -f schema_update.ldif

 

 

Create the server group entries within ou=server container

Create a file named server_group.ldif and copy the below content.

dn: cn=server_admin,ou=server,ou=group,dc=devopsideas,dc=com
objectclass: customposixGroup
objectclass: groupOfNames
cn: server_admin
gidNumber: 5000
description: Server Admin Group
member: cn=chris.sam,ou=people,dc=devopsideas,dc=com

dn: cn=server_dev,ou=server,ou=group,dc=devopsideas,dc=com
objectclass: customposixGroup
objectclass: groupOfNames
cn: server_dev
gidNumber: 6000
description: Server Dev Group
member: cn=aron.francis,ou=people,dc=devopsideas,dc=com

 

We are using customposixGroup and groupOfNames as objectClass.   As part of creating this entry we are adding members to it. chris.sam is added as part of server_admin and aron.francis is added as part of server_dev group.

The gidNumber represents the Group id in the server. We are giving higher numbers for this to be safe from conflicting with the local gid’s in the server.

Implement the change by running the below command,

ldapadd -W -Z -D cn=admin,dc=devopsideas,dc=com -f server_group.ldif

We have now completed adding group entries inside ou=server container.

 

Service id for Linux Client binding

Create a service id cn=serverid,ou=service_ids,dc=devopsideas,dc=com, for binding LDAP clients. Since we need to specify password for this, we’ll create password hash first,

$ slappasswd -h {SHA} -s <password>
{SHA}qUqP5cyxm6YcTAhz05Hph5gvu9M=

Create a file named serverid.ldif with the below content.

dn: cn=serverid,ou=service_ids,dc=devopsideas,dc=com
cn: serverid
givenName: Server ID
sn: id
uid: serverid
objectClass: top
objectClass: inetOrgPerson
objectClass: person
userPassword: {SHA}qUqP5cyxm6YcTAhz05Hph5gvu9M=

Run the below command to import the change,

ldapadd -W -Z -D cn=admin,dc=devopsideas,dc=com -f serverid.ldif

 

If you recollect, we have set a separate password policy for service id’s and we need to apply that for this id. Create a file named serverid_ppolicy.ldif with the below content.

dn: cn=serverid,ou=service_ids,dc=devopsideas,dc=com
changetype: modify
add: pwdPolicySubentry
pwdPolicySubentry: cn=servicePasswordPolicy,ou=pwpolicies,dc=devopsideas,dc=com

Run the below command,

ldapmodify -W -Z -D cn=admin,dc=devopsideas,dc=com -f serverid_ppolicy.ldif

The serverid DN will now have ‘cn=servicePasswordPolicy,ou=pwpolicies,dc=devopsideas,dc=com’ as its password policy definition

 

Update schema to enable sshPublicKey attribute

Since we will implement key based authentication, we need an attribute that can store public key of the user. There is no attribute available by default to store the public key. Hence we need to define a schema for the same and create an attribute to store the key.

Create a file named publickey.ldif with the below content,

dn: cn=openssh-lpk,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: openssh-lpk
olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
DESC 'MANDATORY: OpenSSH Public key'
EQUALITY octetStringMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
DESC 'MANDATORY: OpenSSH LPK objectclass'
MAY ( sshPublicKey $ uid )
)

Run the below command to implement the change,

ldapadd -W -D cn=admin,cn=config -f publickey.ldif

We have created an attributed named ‘ldapPublicKey’ to store the ssh public key of the users.

 

Update user entry with posixGroup and ldapPublicKey

We already have user entries created with inetOrgPerson objectClass. We further need posixGroup & ldapPublicKey added as part of the entries to get attributes that will be used for working with Linux clients.

Create a file named usermod.ldif and copy the below content

dn: cn=chris.sam,ou=people,dc=devopsideas,dc=com
changetype: modify
add: objectClass
objectclass: posixAccount
-
add: homeDirectory
homeDirectory: /home/chris.sam
-
add: loginShell
loginShell: /bin/bash
-
add: uidNumber
uidNumber: 5000
-
add: gidNumber
gidNumber: 5000
-
add: uid
uid: chris.sam
-
add: objectClass
objectclass: ldapPublicKey
-
add: sshPublicKey
sshPublicKey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMhJyIJ66E4uEU6N309afcc2RrF3n+38AQaf4e4IItuotD7b0K/JM4XdpnbNfOUmXSqOpOaCKnBdP6d7TBQVq5ChxMOtAvvNwmOtgzIJNCIPLD7aVHekO3MNgLwqlkDGXEoO3HjcJpoZhWLpHNOopiPp2yJcfFXA6twhKf9Dqbl+1XT4mDeyF7Fg0/y1JIkBQEraCFywHzsWTuQTc5u7Ve6kQMlEOP5np13e+hQJ7lQUxsFvnO59W4Th/4Uyimp2G32nfuy3p6pF6iwZD6QuD/iIFvmaYDh1MsXGcMPrP1M8ewhknEWn4mgxJVvb/zq2R74FSB5azg5yO1VyI9lN6R

dn: cn=aron.francis,ou=people,dc=devopsideas,dc=com
changetype: modify
add: objectClass
objectclass: posixAccount
-
add: homeDirectory
homeDirectory: /home/aron.francis
-
add: loginShell
loginShell: /bin/bash
-
add: uidNumber
uidNumber: 6000
-
add: gidNumber
gidNumber: 6000
-
add: uid
uid: aron.francis
-
add: objectClass
objectclass: ldapPublicKey
-
add: sshPublicKey
sshPublicKey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDD2A/ApDfwnlHDmzJ1SefYSgd3x/BPqltQ3kO4EmpUDpE6CZJL+RVaTq19lOzpqnLOAx7qM5qS6rsfPzE2UxfTmMM4PWeBe+M5ypCMp7yQgXoJkxX90sTM5KRv5Bj9WauF56ZK+PiFqQzuE1cWnt7Owwnki4aTEvwY+vtWFcHy4KLrVzML0Y5ldsshp1l0o3Qj69smsAbCto76lEG5fXCfZ0XELXSKKQdiBqdQqz+dhi1slZDSt8n0azyQSTqWR1nXNuLd5HfveT+VGq9/HuNkriKUV94RzYjrkGJXlqsaa24vRY21tKqKgw3rGHrWml1g6yNVqg24kGrezlxVO3Hd

We have included new objectClasses to our user entries. We have also specified the required attributes of those entries. In short,

  • We have specified the homeDirectory , loginShell, uid and gid of the user
  • We have also added the user ssh keys as part of sshPublicKey attribute.

 

We have everything configured at LDAP server end and we are good to configure our Linux client now.

Configure Linux Client

Run the below commands to install the necessary packages in Linux Client.

apt-get -y install libpam-ldap nscd ldap-utils libnss-ldapd

You’ll be asked series of questions similar to those installed during LDAP server.

 

1)  First prompt relates to nlscd configuration. Provide the LDAP server domain name or IP address.

Linux Client LDAP Integration - 1

 

2) Next, enter the distinguished name of the LDAP server. dc=devopsideas,dc=com in this case.

Linux Client LDAP Integration - 2

 

3) Next configuration is for libnss-ldapd. Select the services for which LDAP lookups should be enabled. We are enabling for passwd, group and shadow service in this example.

Linux Client LDAP Integration - 3

 

4) Next, enter the LDAP URI. ( ldap://ldap.devopsideas.com)

Linux Client LDAP Integration - 4

 

5) The next configuration is for ldap-auth-config. Enter the DN of the LDAP search again ( dc=devopsideas,dc=com)

Linux Client LDAP Integration - 5

 

6) Select the LDAP version – v3

Linux Client LDAP Integration - 6

 

7) Select ‘No’ for the next option to store password locally.

Linux Client LDAP Integration - 7

 

8) Select ‘Yes’ for the next option

Linux Client LDAP Integration - 8

 

9) Provide the DN of the serverid which we created earlier,

Linux Client LDAP Integration - 9

 

10) Enter the password of the serverid

Linux Client LDAP Integration - 10

 

Install the other required packages,

apt-get -y install python-pip python-ldap
apt-get install libsasl2-dev python-dev libldap2-dev libssl-dev
pip install ssh-ldap-pubkey

 

We must configure OpenSSH to fetch the keys from OpenLDAP. Add the following lines to /etc/ssh/sshd_config:

AuthorizedKeysCommand /usr/local/bin/ssh-ldap-pubkey-wrapper
AuthorizedKeysCommandUser nobody

 

Restart ssh service,

service ssh restart

 

Configure PAM

1)  Edit /etc/pam.d/common-auth and add the following line:

account required    pam_access.so

2) Edit /etc/pam.d/common-password and remove use_authtok parameter

3)  To automatically create home directories when users log in, edit /etc/pam.d/common-session and add the following line:

session required pam_mkhomedir.so skel=/etc/skel umask=0022

 

Configure ldap client to use startTLS

1)  Copy the cacert.pem generated in the LDAP server. ( Refer Enabling and Enforcing TLS section in this article ).

mkdir /etc/ldap/certs

# Assuming you have copied the cert from LDAP server to the client in /tmp
cp /tmp/cacert.pem /etc/ldap/certs/

2) Edit /etc/ldap.conf file and make the following changes,

# Uncomment start_tls
ssl start_tls

# uncomment tls_checkpeer
tls_checkpeer yes

tls_cacertfile /etc/ldap/certs/cacert.pem

3) Edit /etc/ldap/ldap.conf and change the value of  TLS_CACERT to point to cacert.pem

TLS_CACERT      /etc/ldap/certs/cacert.pem

 

Configure nslcd

nslcd is a daemon that will do LDAP queries for local processes based on a simple configuration file.  nslcd is configured through a configuration file nslcd.conf.  We will using filter to implement access control.

Edit the nslcd configuration file /etc/nslcd.conf and it should contain the below content.

uid nslcd
gid nslcd

uri ldap://ldap.devopsideas.com/

base ou=people,dc=devopsideas,dc=com

binddn cn=serverid,ou=service_ids,dc=devopsideas,dc=com
bindpw <serverid-password>

ssl start_tls
tls_reqcert demand

tls_cacertfile /etc/ldap/certs/cacert.pem
tls_cacertdir /etc/ldap/certs

filter passwd (&(objectClass=posixAccount)(|(memberOf=cn=server_dev,ou=server,ou=group,dc=devopsideas,dc=com)(memberOf=cn=server_admin,ou=server,ou=group,dc=devopsideas,dc=com)))

base group ou=server,ou=group,dc=devopsideas,dc=com
filter group (&(objectClass=posixGroup)(cn=server*))

 

Take a look at the filter section. We are filtering users based on objectClass of type posixAccoung and they should be member of either server_dev or server_admin group

We are also filtering and importing group in order to use it locally to provide sudo access.

Do a restart of the nslcd service for the changes to take effect

service nslcd restart

 

Test your access

We have completed the Linux client and LDAP integration. Try accessing the linux client from your local where you have the keys. You should be able to access the server now.

ssh [email protected] 
chris.sam@web:~$


chris.sam@web:~$ id
uid=5000(chris.sam) gid=5000(server_admin) groups=5000(server_admin)

If you are not able to login, check the syslog of LDAP server and see if you get any errors. Try troubleshooting based on the error code.

The id command reveals that the user is part of server_admin which we created in LDAP. This gets fetched from the group filter specified in the nslcd.conf file

 

Configure sudo access

We can’t do anything much with the present configuration. The user can only login with their id’s but they cannot perform any operations like deploying new code, make configuration changes, restarting service etc.

For this example, we will consider the application is owned by an application id (appid). The Dev user should have access to switch only to this id. On the other hand the Admin user should have complete sudo access. We will achieving this by editing sudoers file and adding relevant permission to the groups that we got through the group filter in nslcd configuration

Run visudo to edit the sudoers file and add the below content

Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

# User privilege specification
root ALL=(ALL:ALL) ALL

# Access for appid for server_dev users
%server_dev ALL=(appid) ALL

# Sudo access ofr server_admin users
%server_admin ALL=(ALL:ALL) ALL

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL

 

The content highlighted in blue are the ones we have added additionally. We have specified that users belonging to server_admin will have sudo access and user part of server_dev will have access to switch only to appid 

For eg, the aron.francis belongs to server_dev group. Hence in order to switch to appid, he has to run

sudo -u appid -i

 

Well Done!! We have successfully integrated Linux client with LDAP.

Series Navigation<< OpenLDAP – Graylog LDAP IntegrationopenLDAP – Basic Authentication using LDAP >>