top of page
Search

Setting up an LDAP System in an AWS Cluster

  • Writer: Joseph
    Joseph
  • 3 days ago
  • 8 min read

Updated: 22 hours ago

This is the sixth part of an eight- part series  on how to set up an HPC cluster on AWS. This document explains how to setup LDAP in the cluster



The cluster has seven virtual machines (VMs)

  • One head / control node (node1)

  • One login node (node2)

  • Three compute nodes (node3, node4, node 5)

  • Two storage nodes (node6, node7)

  • All the VMs will have the OS Rocky Linux 9.6 (Blue Onyx)


Lightweight Directory Access Protocol (LDAP) is a protocol used for accessing and managing directory services over a network. It is commonly used for centralised authentication and authorisation in enterprise environments. By integrating LDAP with a PBS cluster, user authentication and management can be centralised, making it easier to handle user accounts and permissions across multiple nodes in the cluster.


LDAP has two types of nodes

  • LDAP server - Head node (node1)

  • LDAP clients - Login node (node2)

To avoid this discrepancy when installing packages, follow the steps outlined in the second part of this series. That document also explains how to disable SELinux. Also, make sure passwordless SSH access between all the nodes in the cluster is set up. Check out the third part of this series on how to do this.


LDAP Server Configuration

On the head node (node1), install OpenLDAP packages.

sudo dnf install openldap-servers openldap-clients

You can now start the srever

sudo systemctl start slapd
sudo systemctl enable slapd
sudo systemctl status slapd


The slappasswd command is a utility in OpenLDAP used to generate encrypted (hashed) passwords that can be safely stored in the LDAP directory. It’s not for changing passwords directly inside LDAP — rather, it creates a secure password hash that you can then manually add or update in an LDAP entry (for example, in olcRootPW or userPassword attributes). One thing to note is that slappasswd generates different hashes for the same password each time because it uses a salted hashing algorithm. In the next step, find the hash of the password you want to use as the LDAP admin password.

slappasswd

In this setup, we are using the password ldappassword. Let us assume the hash generated for password ldappassword is {SSHA}UNHjdYvrkQIhD9vRlShjlADjmJF/hhcm. Now we use this hash in the following LDIF file to set the LDAP admin password.  In LDAP (Lightweight Directory Access Protocol), an LDIF (LDAP Data Interchange Format) file is a plain-text file used to represent directory data and configuration in a standard, portable format. So we use the following LDIF file (changerootpass.ldif) to set the admin password for LDAP.

dn: olcDatabase={0}config,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}UNHjdYvrkQIhD9vRlShjlADjmJF/hhcm

Line

Meaning

dn: olcDatabase={0}config,cn=config

This specifies the Distinguished Name (DN) of the LDAP entry being modified — in this case, it’s the configuration database itself. {0}config is the internal configuration backend used by slapd (the LDAP daemon).

changetype: modify

Tells LDAP you’re performing a modification (not adding or deleting an entire entry).

add: olcRootPW

You’re adding a new attribute named olcRootPW to this configuration entry.

olcRootPW: {SSHA}UNHjdYvrkQIhD9vRlShjlADjmJF/hhcm

This is the hashed password (generated using slappasswd) that becomes the root bind password for this configuration database.


Now we run the command

sudo ldapadd -Y EXTERNAL -H ldapi:/// -f changerootpass.ldif

This command applies configuration changes from changerootpass.ldif to the local LDAP server. It connects via the local UNIX socket (`ldapi:///`) and authenticates as the system user using SASL EXTERNAL. SASL (Simple Authentication and Security Layer) is a framework that allows LDAP to use different authentication methods. The EXTERNAL mechanism means the authentication is done outside of LDAP, using the identity provided by the connection itself (root).

The next step is to add the necessary LDAP schemas. In LDAP schema defines the structure, rules, and types of data that can be stored in the directory. Schemas specify which object classes and attributes are allowed and how they relate to each other. Without loading the necessary schemas, LDAP wouldn’t know how to handle common entries like users, groups, or email addresses.

In this case, we are loading three schemas:

  • cosine.ldif: Provides general-purpose internet-related attributes and object classes for users and groups.

  • nis.ldif: Adds UNIX/Linux account and group attributes for system integration.

  • inetorgperson.ldif: Defines detailed human user attributes for directories and identity management.


To add the schemas to LDAP, use the commands.

sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif

sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif

sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif

Then restart the LDAP service

sudo systemctl restart slapd

The next step is to set the domain and configure the LDAP database. Create a file named setdomain.ldif with the following content:

# Give local root (UID 0) and Manager read access to the monitor database
dn: olcDatabase={1}monitor,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to *
	by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read
	by dn.base="cn=Manager,dc=cluster,dc=lan" read
	by * none

# Set the LDAP database suffix (your domain)
dn: olcDatabase={2}mdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=cluster,dc=lan

# Define the root DN (admin user for LDAP)

dn: olcDatabase={2}mdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=Manager,dc=cluster,dc=lan

# Add root password (replace with your own SSHA hash)
dn: olcDatabase={2}mdb,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}UNHjdYvrkQIhD9vRlShjlADjmJF/hhcm

# Set access control rules for users and the admin

dn: olcDatabase={2}mdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {0}to attrs=userPassword,shadowLastChange
	by dn="cn=Manager,dc=cluster,dc=lan" write
	by anonymous auth
	by self write
	by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to *
	by dn="cn=Manager,dc=cluster,dc=lan" write
	by * read

Let us break down the different aspects of the LDIF file.

dn: olcDatabase={1}monitor,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to *
	by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read
	by dn.base="cn=Manager,dc=cluster,dc=lan" read
	by * none

This secures the monitor database so that only trusted users (local root or LDAP admin) can read it. Protects sensitive runtime information from unauthorised users. In the above In OpenLDAP, a database (different from a SQL database) is a storage backend for LDAP entries. Each backend can have its own configuration, root DN, access controls, and data.

dn: olcDatabase={2}mdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=cluster,dc=lan

This sets the LDAP domain for the main database. It defines the LDAP root for the main database and establishes the domain name under which all directory entries (users, groups, organisational units) are stored. Changing this is effectively changing the LDAP domain (cluster.lan).


Main LDAP Database (olcDatabase={2}mdb)

├─ Suffix / LDAP Domain: dc=cluster,dc=lan

├─ Root DN: cn=Manager,dc=cluster,dc=lan

├─ Purpose: Store actual directory data (users, groups, OUs)

├─ Access: Controlled by olcAccess rules

├─ Contains:

│ ├─ Admin user:

│ │ └─ cn=Manager,dc=cluster,dc=lan

│ ├─ Users:

│ │ ├─ uid=user1,dc=cluster,dc=lan

│ │ └─ uid=user2,dc=cluster,dc=lan

│ ├─ Groups:

│ │ ├─ cn=admins,dc=cluster,dc=lan

│ │ └─ cn=users,dc=cluster,dc=lan

│ └─ Organizational Units:

│ ├─ ou=People,dc=cluster,dc=lan

│ └─ ou=Groups,dc=cluster,dc=lan



dn: olcDatabase={2}mdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=Manager,dc=cluster,dc=lan

This modifies another existing database ({2}mdb) in LDAP, and it changes the admin account for that database. The root user (administrator) for that database is now cn=Manager,dc=cluster,dc=lan.


In an OpenLDAP server, the {2}mdb and {1}monitor databases serve distinctly different purposes. The {2}mdb database is the primary directory backend, storing all real LDAP entries such as users, groups, and organizational units under the domain defined by its suffix (e.g., `dc=cluster,dc=lan`). It has a defined root DN (`cn=Manager`) with full administrative privileges and supports read and write operations controlled by access control rules. In contrast, the {1}monitor database is a special read-only system database that provides internal monitoring information about the LDAP server, such as active connections, operations per second, and cache statistics.


Access to {1}monitor is strictly limited to the local root user or the LDAP admin for security purposes, and it does not contain or manage actual directory entries. While {2}mdb is essential for the functioning of the directory and user management, {1}monitor exists solely for server monitoring and operational insight.


dn: olcDatabase={2}mdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {0}to attrs=userPassword,shadowLastChange
	by dn="cn=Manager,dc=cluster,dc=lan" write
	by anonymous auth
	by self write
	by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to *
	by dn="cn=Manager,dc=cluster,dc=lan" write
	by * read

This snippet defines access control rules (ACLs) for the main LDAP database ({2}mdb) to control who can read or write entries and attributes.


Main LDAP Database (olcDatabase={2}mdb)

├─ Sensitive Attributes: userPassword, shadowLastChange

│ ├─ Admin (cn=Manager) → write

│ ├─ Self (the user owning the entry) → write

│ ├─ Anonymous → auth only

│ └─ Everyone else → none

├─ Root of Database: dn.base=""

│ └─ Everyone → read

├─ All Entries (*)

│ ├─ Admin (cn=Manager) → write

│ └─ Everyone else → read


In summary, the above configuration sets the LDAP domain to cluster.lan, defines the admin user, sets the databases, and establishes access control rules. Now apply the configuration using the following commands:

sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f setdomain.ldif

Verify the naming contexts to ensure the domain is set correctly:

 sudo ldapsearch -H ldap:// -x -s base -b "" -LLL "namingContexts"

The next step is to add organizational units (OUs) to the LDAP directory. For this, create a file named addou.ldif with the following content:

dn: dc=cluster,dc=lan
objectClass: top
objectClass: dcObject
objectClass: organization
o: Cluster Organisation
dc: cluster

dn: cn=Manager,dc=cluster,dc=lan
objectClass: organizationalRole
cn: Manager
description: OpenLDAP Manager

dn: ou=People,dc=cluster,dc=lan
objectClass: organizationalUnit
ou: People

dn: ou=Group,dc=cluster,dc=lan
objectClass: organizationalUnit
ou: Group

Let us break down the ldif file:

dn: dc=cluster,dc=lan
objectClass: top
objectClass: dcObject
objectClass: organization
o: Cluster Organisation
dc: cluster

This entry creates the root of your LDAP directory tree for the domain cluster.lan, serving as the parent for all other entries such as users, groups, and organisational units, while also providing organisational information for the directory.


dn: cn=Manager,dc=cluster,dc=lan
objectClass: organizationalRole
cn: Manager
description: OpenLDAP Manager

This entry creates the Manager role in LDAP, which acts as the administrative user (Root DN) for the database. It is used to perform all privileged operations, such as adding or modifying users, groups, and organisational units.


dn: ou=People,dc=cluster,dc=lan
objectClass: organizationalUnit
ou: People

dn: ou=Group,dc=cluster,dc=lan
objectClass: organizationalUnit
ou: Group

These entries create two organisational units under the LDAP root:

  1. ou=People: container for user accounts.

  2. ou=Group: container for group entries.

Using OUs keeps the LDAP directory structured and manageable, allowing hierarchical organisation of users and groups.


LDAP Directory Tree

└─ dc=cluster,dc=lan (Root Entry)

├─ ou=People,dc=cluster,dc=lan → Organizational Unit for users

│ ├─ uid=user1,ou=People,dc=cluster,dc=lan

│ └─ uid=user2,ou=People,dc=cluster,dc=lan

└─ ou=Group,dc=cluster,dc=lan → Organizational Unit for groups

├─ cn=admins,ou=Group,dc=cluster,dc=lan

└─ cn=users,ou=Group,dc=cluster,dc=lan


Apply the changes using the following command:

sudo ldapadd -x -D cn=Manager,dc=cluster,dc=lan -W -f addou.ldif

Finally we add a user calles testuser1 to the LDAP directory. First, generate a password hash for the user using slappasswd.

slappasswd

In this setup, we use the password testuser. Let's assume the hash generated is {SSHA}yJcv+xLWUvgAWu+fdNN/K6V4cdS4PC5E. Then create a file named user1.ldif with the following content:

dn: uid=testuser1,ou=People,dc=cluster,dc=lan
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
cn: testuser1
sn: user
userPassword: {SSHA}yJcv+xLWUvgAWu+fdNN/K6V4cdS4PC5E
loginShell: /bin/bash
uidNumber: 2001
gidNumber: 2001
homeDirectory: /scratch/userhome/testuser1
shadowLastChange: 0
shadowMax: 0
shadowWarning: 0

dn: cn=testuser1,ou=Group,dc=cluster,dc=lan
objectClass: posixGroup
cn: testuser1
gidNumber: 2001
memberUid: testuser1

This LDIF file creates the user testuser1 belongs to the group testuser1 (gidNumber=2001). This setup is typical for LDAP-based UNIX/Linux accounts, where each user has a private group.  Add the user using the following command:

sudo ldapadd -x -D cn=Manager,dc=cluster,dc=lan -W -f user1.ldif

Verify that the user has been added successfully:

sudo ldapsearch -x -b "ou=People,dc=cluster,dc=lan"

Next we will enable TLS for secure LDAP communication. First, generate a self-signed TLS

certificate:

sudo openssl req -x509 -nodes -days 365   -newkey rsa:2048   -keyout /etc/pki/tls/ldapserver.key   -out /etc/pki/tls/ldapserver.crt

sudo chown ldap:ldap /etc/pki/tls/{ldapserver.crt,ldapserver.key}

Then create a file named tls.ldif with the following content:

dn: cn=config
changetype: modify
replace: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/pki/tls/ldapserver.crt
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/pki/tls/ldapserver.crt
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/pki/tls/ldapserver.key

The ldif file specifies the paths to the TLS certificate and key files. Next apply the TLS

configuration using the command:

sudo ldapadd -Y EXTERNAL -H ldapi:/// -f tls.ldif

Then make sure the /etc/openldap/ldap.conf file is configured to use TLS:

TLS_CACERT      /etc/pki/tls/cert.pem
TLS_REQCERT never

LDAP Client Configuration


Now that the LDAP server is set up and running , we can setup the LDAP client. Ideally, an HPC system should have a file system to manage user home directories. In our case, we will host all the user home directories under the /scratch file system. In the /scratch directory, create a directory userhome to be used as the base home

directory for LDAP users:

sudo mkdir -p /scratch/userhome
sudo chown root:root /scratch/userhome
sudo chmod 755 /scratch/userhome

On the client nodes, install and configure the LDAP client:

    sudo dnf install openldap-clients sssd sssd-ldap oddjob-mkhomedir -y
sudo authselect select sssd with-mkhomedir --force

Enable and start the oddjobd service to support home directory creation:

sudo systemctl enable --now oddjobd.service
sudo systemctl status oddjobd.service

Then configure the LDAP client by editing the /etc/openldap/ldap.conf file:

URI ldap://node1/
BASE dc=cluster,dc=lan

After this, configure SSSD by editing the /etc/sssd/sssd.conf file:

[domain/default]
id_provider = ldap
autofs_provider = ldap
auth_provider = ldap
chpass_provider = ldap

ldap_uri = ldap://node1/
ldap_search_base = dc=cluster,dc=lan
ldap_id_use_start_tls = True

ldap_tls_cacertdir = /etc/openldap/certs
cache_credentials = True
ldap_tls_reqcert = allow

[sssd]

services = nss, pam, autofs
domains = default

nss]
homedir_substring = /scratch/userhome/%u

Once the configuration is done, set the appropriate permissions for the /etc/sssd/sssd.conf file and start the service:

sudo chmod 0600 /etc/sssd/sssd.conf
sudo systemctl start sssd

sudo systemctl enable sssd
sudo systemctl status sssd
sudo sss_cache -E

Then verify that LDAP user created on the LDAP serever (node1) can be resolved from the LDAP client (node2):

getent passwd testuser1

Then try to log in to the client node using the LDAP user:

su - testuser1

If SELinux is not disabled, it can interfere with LDAP authentication.  Especially the home directory creation. Now, you should be able to log in using the LDAP user credentials. Try logging in via SSH (from the local system):

ssh testuser1@<ip of the login node>

The next part outlines the steps to set up a Prometheus and Grafana in the AWS cluster. The main GitHub repo is available here.


Reference

 
 
 

Recent Posts

See All
Setting up Prometheus and Grafana in an AWS Cluster

This is the seventh part of an eight-part series  on how to setup an HPC cluster on AWS. This document explains how to set up an OpenPBS job scheduler in an AWS cluster. The cluster has seven virtual

 
 
 
Setting up a PBS Scheduler in an AWS Cluster

This is the fifth part of an eight-part series  on how to setup an HPC cluster on AWS. This document explains how to set up an OpenPBS job scheduler in an AWS cluster. The cluster has seven virtual m

 
 
 

Comments


bottom of page