-
Tested OS:
- Debian: 12 (Bookworm), 13 (Trixie)
- Ubuntu: 22.04 (Jammy Jellyfish), 24.04 (Noble)
This HOWTO uses example.org to provide this guide with example values.
Please remember to replace all occurencences of the example.org domain name with the domain name of your institution.
-
Simple Bash script useful to convert a Domain Name into a Distinguished Name of LDAP: domain2dn.sh
-
Apache Directory Studio: https://directory.apache.org/studio/downloads.html
-
System Update:
sudo apt update ; sudo apt upgrade
-
Automate SLAPD installation (Change all "_CHANGEME" values):
-
sudo apt install debconf-utils -
sudo vim /root/debconf-slapd.confslapd slapd/password1 password <LDAP-ROOT-PW_CHANGEME> slapd slapd/password2 password <LDAP-ROOT-PW_CHANGEME> slapd slapd/move_old_database boolean true slapd slapd/domain string <INSTITUTE-DOMAIN_CHANGEME> slapd shared/organization string <ORGANIZATION-NAME_CHANGEME> slapd slapd/no_configuration boolean false slapd slapd/purge_database boolean false slapd slapd/allow_ldap_v2 boolean false slapd slapd/backend select MDB
-
sudo cat /root/debconf-slapd.conf | sudo debconf-set-selections
NOTES: The HOWTO considers the following values that have to be changed as your needs:
<LDAP-ROOT-PW_CHANGEME>==>ciaoldap<INSTITUTE-DOMAIN_CHANGEME>==>example.org<ORGANIZATION-NAME_CHANGEME>==>Example Org
-
-
Install required package:
sudo apt install slapd ldap-utils ldapscripts rsyslog
-
Check
/etc/hoststo be sure to have the correct FQDN for OpenLDAP server -
Create Certificate/Key (This HOWTO will use Self Signed Certificate for LDAP):
-
Self Signed (4096 bit - 3 years before expiration):
-
sudo openssl req -newkey rsa:4096 -x509 -nodes -out /etc/ldap/$(hostname -f).crt -keyout /etc/ldap/$(hostname -f).key -days 1095 -subj "/CN=$(hostname -f)"
-
sudo chown openldap:openldap /etc/ldap/$(hostname -f).crt /etc/ldap/$(hostname -f).key
-
-
Signed (Do not use if you are not a NREN GARR Member):
-
Add CA Cert into
/etc/ssl/certs-
If you use GARR TCS or GEANT TCS:
wget -O /etc/ssl/certs/GEANT_TLS_RSA_1.pem https://crt.sh/?d=16099180997 -
If you use ACME (Let's Encrypt):
sudo ln -s /etc/letsencrypt/live/<SERVER_FQDN>/chain.pem /etc/ssl/certs/ACME-CA.pem
-
-
Generate CSR(Certificate Signing Request) and the KEY:
sudo openssl req -new -newkey rsa:4096 -nodes -out /etc/ssl/certs/$(hostname -f).csr -keyout /etc/ssl/private/$(hostname -f).key -subj "/C=IT/ST=/L=Rome/O=Consortium GARR/CN=$(hostname -f)"
-
Once obtained the SSL Certificate, copy it and the key into openldap directory:
sudo cp /etc/ssl/certs/$(hostname -f).crt /etc/ldap/$(hostname -f).crt sudo cp /etc/ssl/private/$(hostname -f).key /etc/ldap/$(hostname -f).key sudo chown openldap:openldap /etc/ldap/$(hostname -f).crt /etc/ldap/$(hostname -f).key
-
-
-
Enable SSL for LDAP:
sudo sed -i "s/TLS_CACERT.*/TLS_CACERT\t\/etc\/ldap\/$(hostname -f).crt/g" /etc/ldap/ldap.conf sudo chown openldap:openldap /etc/ldap/ldap.conf -
Restart OpenLDAP:
sudo service slapd restart
-
Create
scratchdirectory:sudo mkdir /etc/ldap/scratch -
Configure LDAP for StartTLS/SSL:
sudo bash -c 'cat > /etc/ldap/scratch/olcTLS.ldif <<EOF dn: cn=config changetype: modify replace: olcTLSCACertificateFile olcTLSCACertificateFile: /etc/ldap/$(hostname -f).crt - replace: olcTLSCertificateFile olcTLSCertificateFile: /etc/ldap/$(hostname -f).crt - replace: olcTLSCertificateKeyFile olcTLSCertificateKeyFile: /etc/ldap/$(hostname -f).key EOF'
-
Apply with:
sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f /etc/ldap/scratch/olcTLS.ldif
-
Create the 3 main Organizational Unit (OU),
people,groupsandsystem.Example: if the domain name is
example.orgthan the distinguish name will bedc=example,dc=org:Be carefull! Replace
dc=example,dc=orgwith distinguish name (DN) of your domain name and<LDAP-ROOT-PW_CHANGEME>with the LDAP ROOT password!-
sudo bash -c 'cat > /etc/ldap/scratch/add_ou.ldif <<EOF dn: ou=people,dc=example,dc=org objectClass: organizationalUnit objectClass: top ou: people dn: ou=groups,dc=example,dc=org objectClass: organizationalUnit objectClass: top ou: groups dn: ou=system,dc=example,dc=org objectClass: organizationalUnit objectClass: top ou: system EOF'
-
Apply with:
sudo ldapadd -x -D 'cn=admin,dc=example,dc=org' -w '<LDAP-ROOT-PW_CHANGEME>' -H ldapi:/// -f /etc/ldap/scratch/add_ou.ldif
-
Verify with:
sudo ldapsearch -x -b 'dc=example,dc=org'
-
-
Create the
idpuserneeded to perform Bind and Search operations:Be carefull! Replace
dc=example,dc=orgwith distinguish name (DN) of your domain name,<LDAP-ROOT-PW_CHANGEME>with the LDAP ROOT password and<INSERT-HERE-IDPUSER-PW>with password for theidpuseruser!-
sudo bash -c 'cat > /etc/ldap/scratch/add_idpuser.ldif <<EOF dn: cn=idpuser,ou=system,dc=example,dc=org objectClass: inetOrgPerson cn: idpuser sn: idpuser givenName: idpuser userPassword: <INSERT-HERE-IDPUSER-PW> EOF'
-
Apply with:
sudo ldapadd -x -D 'cn=admin,dc=example,dc=org' -w '<LDAP-ROOT-PW_CHANGEME>' -H ldapi:/// -f /etc/ldap/scratch/add_idpuser.ldif
-
-
Configure OpenLDAP ACL to allow
idpuserto perform search operation on the directory:Be carefull! Replace
dc=example,dc=orgwith distinguish name (DN) of your domain name!-
Check which configuration your directory has:
sudo ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config 'olcDatabase={1}mdb'
-
Configure ACL for
idpuserwith:sudo bash -c 'cat > /etc/ldap/scratch/olcAcl.ldif <<EOF dn: olcDatabase={1}mdb,cn=config changeType: modify replace: olcAccess olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break olcAccess: {1}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=example,dc=org" write by * none olcAccess: {2}to dn.base="" by anonymous auth by * read olcAccess: {3}to dn.base="cn=Subschema" by * read olcAccess: {4}to * by dn.exact="cn=idpuser,ou=system,dc=example,dc=org" read by self read by anonymous auth by * none EOF'
-
Apply with:
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/scratch/olcAcl.ldif
-
-
Check that
idpusercan search other users (when users exist):Be carefull! Replace
dc=example,dc=orgwith distinguish name (DN) of your domain name!sudo ldapsearch -x -D 'cn=idpuser,ou=system,dc=example,dc=org' -w '<INSERT-HERE-IDPUSER-PW>' -b 'ou=people,dc=example,dc=org'
-
Install needed schemas (eduPerson, SCHAC):
sudo wget https://raw.githubusercontent.com/REFEDS/eduperson/master/schema/openldap/eduperson.ldif -O /etc/ldap/schema/eduperson.ldif sudo wget https://raw.githubusercontent.com/REFEDS/SCHAC/main/schema/openldap.ldif -O /etc/ldap/schema/schac.ldif sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/eduperson.ldif sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/schac.ldif
and verify presence of the new
schacandeduPersonschemas with:sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b 'cn=schema,cn=config' dn -
Add MemberOf Configuration:
-
Create
add_memberof.ldif:sudo bash -c 'cat > /etc/ldap/scratch/add_memberof.ldif <<EOF dn: cn=module,cn=config cn: module objectClass: olcModuleList olcModuleLoad: memberof olcModulePath: /usr/lib/ldap dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config objectClass: olcConfig objectClass: olcMemberOf objectClass: olcOverlayConfig objectClass: top olcOverlay: memberof olcMemberOfDangling: ignore olcMemberOfRefInt: TRUE olcMemberOfGroupOC: groupOfNames olcMemberOfMemberAD: member olcMemberOfMemberOfAD: memberOf EOF'
-
Add it to the Directory:
sudo ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/ldap/scratch/add_memberof.ldif
-
-
Improve performance:
-
Create
olcDbIndex.ldif:sudo bash -c 'cat > /etc/ldap/scratch/olcDbIndex.ldif <<EOF dn: olcDatabase={1}mdb,cn=config changetype: modify replace: olcDbIndex # UID Bind olcDbIndex: uid eq,sub # Groups olcDbIndex: member eq olcDbIndex: memberUid eq # SAML Attributes olcDbIndex: cn,sn,givenName pres,eq,sub olcDbIndex: mail eq,sub olcDbIndex: eduPersonAffiliation,eduPersonEntitlement eq # STRUCTURE olcDbIndex: ou pres,eq,sub EOF'
-
Add it to the Directory:
sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f /etc/ldap/scratch/olcDbIndex.ldif
-
-
Configure Logging:
sudo mkdir /var/log/slapd sudo chown syslog /var/log/slapd sudo bash -c 'cat > /etc/rsyslog.d/99-slapd.conf <<EOF local4.* /var/log/slapd/slapd.log EOF' sudo bash -c 'cat > /etc/ldap/scratch/olcLogLevelStats.ldif <<EOF dn: cn=config changeType: modify replace: olcLogLevel olcLogLevel: stats EOF' sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f /etc/ldap/scratch/olcLogLevelStats.ldif sudo service rsyslog restart sudo service slapd restart
-
Configure openLDAP olcSizeLimit:
sudo bash -c 'cat > /etc/ldap/scratch/olcSizeLimit.ldif <<EOF dn: cn=config changetype: modify replace: olcSizeLimit olcSizeLimit: unlimited dn: olcDatabase={-1}frontend,cn=config changetype: modify replace: olcSizeLimit olcSizeLimit: unlimited EOF' sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f /etc/ldap/scratch/olcSizeLimit.ldif
-
Add the first user:
Be carefull! Replace
dc=example,dc=orgwith distinguish name (DN) of your domain name!-
Configure
user1.ldif:sudo bash -c 'cat > /etc/ldap/scratch/user1.ldif <<EOF # USERNAME: user1 , PASSWORD: hello-world-12 dn: uid=user1,ou=people,dc=aai-test,dc=garr,dc=it changetype: add objectClass: inetOrgPerson objectClass: eduPerson uid: user1 sn: User1 givenName: Test cn: Test User1 displayName: Test User1 preferredLanguage: it userPassword: hello-world-12 mail: test.user1@institute-domain.it eduPersonAffiliation: student eduPersonAffiliation: staff eduPersonAffiliation: member eduPersonEntitlement: urn:mace:dir:entitlement:common-lib-terms eduPersonEntitlement: urn:mace:terena.org:tcs:personal-user EOF'
-
Apply with:
sudo ldapadd -x -D 'cn=admin,dc=example,dc=org' -w '<LDAP-ROOT-PW_CHANGEME>' -H ldapi:/// -f /etc/ldap/scratch/user1.ldif
-
-
Check that
idpusercan finduser1:Be carefull! Replace
dc=example,dc=orgwith distinguish name (DN) of your domain name!sudo ldapsearch -x -D 'cn=idpuser,ou=system,dc=example,dc=org' -w '<INSERT-HERE-IDPUSER-PW>' -b 'uid=user1,ou=people,dc=example,dc=org'
-
Check that LDAP has TLS ('anonymous' MUST BE returned):
sudo ldapwhoami -H ldap:// -x -ZZ -
Make sure that
mail,eduPersonPrincipalNameandschacPersonalUniqueIDare unique:-
Load
uniquemodule:sudo bash -c 'cat > /etc/ldap/scratch/loadUniqueModule.ldif <<EOF dn: cn=module{0},cn=config changetype: modify add: olcModuleLoad olcModuleload: unique EOF' sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f /etc/ldap/scratch/loadUniqueModule.ldif
-
Configure mail, eduPersonPrincipalName and schacPersonalUniqueID as unique:
sudo bash -c 'cat > /etc/ldap/scratch/mail_ePPN_sPUI_unique.ldif <<EOF dn: olcOverlay=unique,olcDatabase={1}mdb,cn=config objectClass: olcOverlayConfig objectClass: olcUniqueConfig olcOverlay: unique olcUniqueAttribute: mail olcUniqueAttribute: schacPersonalUniqueID olcUniqueAttribute: eduPersonPrincipalName EOF' sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/scratch/mail_ePPN_sPUI_unique.ldif
-
-
Disable Anonymous bind:
sudo bash -c 'cat > /etc/ldap/scratch/disableAnonymoysBind.ldif <<EOF dn: cn=config changetype: modify add: olcDisallows olcDisallows: bind_anon dn: olcDatabase={-1}frontend,cn=config changetype: modify add: olcRequires olcRequires: authc EOF' sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f /etc/ldap/scratch/disableAnonymoysBind.ldif
-
Load Password Policy module:
sudo bash -c 'cat > /etc/ldap/scratch/load-ppolicy-mod.ldif <<EOF dn: cn=module{0},cn=config changetype: modify add: olcModuleLoad olcModuleLoad: ppolicy.so EOF' sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/scratch/load-ppolicy-mod.ldif
-
Create Password Policies OU Container:
Be carefull! Replace
dc=example,dc=orgwith distinguish name (DN) of your domain name!sudo bash -c 'cat > /etc/ldap/scratch/policies-ou.ldif <<EOF dn: ou=policies,dc=example,dc=org objectClass: organizationalUnit objectClass: top ou: policies EOF' sudo ldapadd -x -D 'cn=admin,dc=example,dc=org' -w '<LDAP-ROOT-PW_CHANGEME>' -H ldapi:/// -f /etc/ldap/scratch/policies-ou.ldif
-
Create OpenLDAP Password Policy Overlay DN:
Be carefull! Replace
dc=example,dc=orgwith distinguish name (DN) of your domain name!sudo bash -c 'cat > /etc/ldap/scratch/ppolicy-overlay.ldif <<EOF dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config objectClass: olcOverlayConfig objectClass: olcPPolicyConfig olcOverlay: ppolicy olcPPolicyDefault: cn=default,ou=policies,dc=example,dc=org olcPPolicyHashCleartext: TRUE EOF' sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/scratch/ppolicy-overlay.ldif
-
Create the Default Password Policy:
Be carefull! Replace
dc=example,dc=orgwith distinguish name (DN) of your domain name!sudo bash -c 'cat > /etc/ldap/scratch/default-ppolicy.ldif <<EOF dn: cn=default,ou=policies,dc=example,dc=org objectClass: pwdPolicy objectClass: device objectClass: top cn: default # Applies policy to userPassword attribute pwdAttribute: userPassword # Enables account lockout after failures pwdLockout: TRUE # Maximum failed login attempts before lockout pwdMaxFailure: 5 # Lockout duration in seconds (15 minutes) pwdLockoutDuration: 900 # Password maximum age in seconds (0 = never expires) pwdMaxAge: 0 # Minimum password length in characters pwdMinLength: 12 # Number of old passwords stored (no reuse) pwdInHistory: 5 # 0=off, 1=low, 2=strict quality check pwdCheckQuality: 2 # Users can change their own password pwdAllowUserChange: TRUE EOF' sudo ldapadd -x -D 'cn=admin,dc=example,dc=org' -w '<LDAP-ROOT-PW_CHANGEME>' -H ldapi:/// -f /etc/ldap/scratch/policies-ou.ldif
Marco Malavolti (mailto:marco.malavolti@garr.it)
