-
Notifications
You must be signed in to change notification settings - Fork 0
LDAP
Because I don't want the post-installation script to configure slapd, create a new debconf entry specifying the preference (and as such, the unconfigured slapd should not be started):
policy=/usr/sbin/policy-rc.d
printf '#!/bin/sh\nexit 101\n' > "$policy" && chmod +x "$policy"
echo 'slapd slapd/no_configuration boolean true' | debconf-set-selections
apt-get install --no-install-recommends slapd ldap-utils gosa-schema sssd-ldap libnss-sss libpam-sss
rm "$policy"
systemctl disable slapd
systemctl disable sssd # what about sssd-secrets.socket?There are two well known ways of representing users and groups: RFC 2307 and RFC 2307 bis, we'll use the later (which requires the gosa-schema package to retrieve rfc2307bis.schema).
Necessary setup:
slapd_directory=/etc/ldap/slapd.d
mdb_directory=/var/lib/ldap/lorn.space
mkdir "$slapd_directory" "$mdb_directory"Let's create a basic configuration:
slapadd -b cn=config -F "$slapd_directory" -l <(cat << EOF
# slapd settings
dn: cn=config
objectClass: olcGlobal
cn: config
olcToolThreads: 1
# check slapd-config(5) for the possible values, this will log basic usage
olcLogLevel: 0x100
# debian specific
olcPidFile: /var/run/slapd/slapd.pid
olcArgsFile: /var/run/slapd/slapd.args
# common database settings
dn: olcDatabase=frontend,cn=config
objectClass: olcDatabaseConfig
objectClass: olcFrontendConfig
olcDatabase: frontend
# maximum number of entries returned, defaults to 500
olcSizeLimit: unlimited
# allow unauthenticated read for schema & dn discovery
olcAccess: to dn.exact="" by * read
olcAccess: to dn.base="cn=Subschema" by * read
# configuration database
dn: olcDatabase=config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: config
# allow root access
olcAccess: to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break
# schemas (don't care much about inetorgperson & others)
dn: cn=schema,cn=config
objectClass: olcSchemaConfig
cn: schema
include: file:///etc/ldap/schema/core.ldif
include: file:///etc/ldap/schema/cosine.ldif
include: file:///etc/ldap/schema/gosa/rfc2307bis.ldif
# modules
dn: cn=module,cn=config
objectClass: olcModuleList
cn: module
olcModulePath: /usr/lib/ldap
olcModuleLoad: back_mdb
olcModuleLoad: memberof
# defaults for mdb backends, see slapd-mdb(5)
dn: olcBackend=mdb,cn=config
objectClass: olcBackendConfig
olcBackend: mdb
# the actual database
dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: mdb
olcSuffix: dc=lorn,dc=space
olcDbDirectory: /var/lib/ldap/lorn.space
# mdb database size, may be increased later (defaults to 1GiB, here it's 64MiB)
olcDbMaxSize: $((64 * 1024 * 1024))
# save last modification time
olcLastMod: TRUE
# indexes
olcDbIndex: objectClass eq
olcDbIndex: uid eq,sub
olcDbIndex: uidNumber,gidNumber,memberUid eq
# allow root access
olcAccess: to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break
# acl, disable writes and allow reads for everything but the userPassword field
olcAccess: to attrs=userPassword by anonymous auth by * none
olcAccess: to * by * read
# strict memberof overlay to ease maintenance
dn: olcOverlay=memberof,olcDatabase={1}mdb,cn=config
objectClass: olcMemberOf
objectClass: olcOverlayConfig
olcOverlay: memberof
olcMemberOfRefInt: TRUE
# the default is ignore
olcMemberOfDangling: error
EOF
)Ensure permissions are okay and start slapd:
chown -R openldap: "$slapd_directory" "$mdb_directory"
systemctl start slapdCreate the basic directory structure:
ldapadd -Y EXTERNAL -H ldapi:// -f <(cat << EOF
dn: dc=lorn,dc=space
objectClass: organization
objectClass: dcObject
o: lorn.space
dc: lorn
dn: ou=users,dc=lorn,dc=space
objectClass: organizationalUnit
ou: users
dn: ou=groups,dc=lorn,dc=space
objectClass: organizationalUnit
ou: groups
EOF
)Setup the first account and its primary group:
user=ether
password=$user
uid=$(ldapsearch -LLL -Y EXTERNAL -H ldapi:// -b dc=lorn,dc=space uidNumber | grep -Po '(?<=uidNumber: )\d+' | sort | tail -n 1)
uid=$((${uid:-9999}+1))
gid=$uid
ldapadd -Y EXTERNAL -H ldapi:// -f <(cat << EOF
dn: uid=$user,ou=users,dc=lorn,dc=space
objectClass: person
objectClass: posixAccount
cn: $user
sn: $user
uid: $user
uidNumber: $uid
gidNumber: $gid
homeDirectory: /home/$user
userPassword: $(slappasswd -s "$password")
dn: cn=$user,ou=groups,dc=lorn,dc=space
objectClass: posixGroup
objectClass: groupOfNames
cn: $user
gidNumber: $gid
member: uid=$user,ou=users,dc=lorn,dc=space
EOF
)Some things that should not be overlooked:
-
olcThreadsincn=config: will limit the number of concurrent connections - you may want to add
olcRootDN&olcRootPWon some databases if you want another access beside ldapi://
If everything went well, the following commands should work:
# configuration database
ldapsearch -LLL -Y EXTERNAL -H ldapi:// -b cn=config
# discovery
ldapsearch -LLL -Y EXTERNAL -H ldapi:// -b '' -s base +
ldapsearch -LLL -Y EXTERNAL -H ldapi:// -b cn=Subschema -s base +
# database
ldapsearch -LLL -Y EXTERNAL -H ldapi:// -b dc=lorn,dc=space
# memberof overlay
ldapsearch -LLL -Y EXTERNAL -H ldapi:// -b dc=lorn,dc=space "(uid=$user)" memberOf
# authenticate (cleartext)
ldapwhoami -x -D "uid=$user,ou=users,dc=lorn,dc=space" -w "$password" -H ldap://
# anonymous search
ldapsearch -LLL -x -H ldap:// -b dc=lorn,dc=spaceThe following shouldn't:
# no access to the configuration by default
ldapsearch -LLL -x -D "uid=$user,ou=users,dc=lorn,dc=space" -w "$password" -H ldap:// -b cn=config
ldapsearch -LLL -x -H ldap:// -b cn=configNote: if a self-signed certificate is good enough, playing with TLS_{CA,REQ}CERT in /etc/ldap/ldap.conf will do the trick for the ldap* commands.
Refer to the initial Let's Encrypt setup.
slapd drops its privileges before reading the SSL certificates and key, so it's a bit more involved to setup properly.
Initial setup (acme.sh leaves the file mode as 0644):
mkdir /etc/ldap/ssl
chown -R root:openldap "$_"
chmod 750 "$_"Request the certificate (you'll need to setup a public DNS record for ldap.service.lorn.space and the web server should handle it):
acme.sh --stateless --issue --domain ldap.service.lorn.space --reloadcmd 'systemctl restart slapd' --ca-file /etc/ldap/ssl/ca.cer --cert-file /etc/ldap/ssl/ldap.service.lorn.space.cer --key-file /etc/ldap/ssl/ldap.service.lorn.space.keyConfigure slapd:
ldapmodify -Y EXTERNAL -H ldapi:// -f <(cat << EOF
dn: cn=config
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ldap/ssl/ca.cer
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/ssl/ldap.service.lorn.space.key
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/ssl/ldap.service.lorn.space.cer
EOF
)It may be nice to use recommended cipher suites as shown in Let's Encrypt. Unfortunately, OpenLDAP is linked with GnuTLS which is bit less flexible but the following should give a couple of cipher suites from the recommended modern configuration:
ldapmodify -Y EXTERNAL -H ldapi:// -f <(cat << EOF
dn: cn=config
replace: olcTLSCipherSuite
olcTLSCipherSuite: NONE:+VERS-TLS1.2:+CURVE-ALL:+SIGN-ALL:+COMP-ALL:+CTYPE-ALL:+ECDHE-ECDSA:+ECDHE-RSA:+CHACHA20-POLY1305:+AES-256-GCM:+AES-128-GCM:+AES-256-CBC:+AES-128-CBC:+AEAD:+SHA384:+SHA256
EOF
)
The -ALL stuff is required to enable basic functionality, what comes after defines the list of supported cipher suites which can be seen via gnutls-cli -l --priority $priority_string.
GnuTLS will happily accept a priority list that may not be functional, verify it via gnutls-cli --debug 9999 google.com --priority $priority_string.
More information is available from GnuTLS' manual and on Mozilla's configuration generator GitHub repository's documentation.
To enable LDAPS, the URI must be added in /etc/default/slapd (else use the StartTLS extension over LDAP):
SLAPD_SERVICES="ldap:/// ldaps:/// ldapi:///"The following command should now work:
ldapwhoami -x -D "uid=$user,ou=users,dc=lorn,dc=space" -w "$password" -H ldaps://ldap.service.lorn.spaceNow that TLS properly works, it may be interesting to disable binds without TLS protection:
ldapmodify -Y EXTERNAL -H ldapi:// -f <(cat << EOF
dn: olcDatabase={1}mdb,cn=config
changetype: modify
delete: olcAccess
olcAccess: {1}to attrs=userPassword by anonymous auth by * none
-
add: olcAccess
olcAccess: {1}to attrs=userPassword by tls_ssf=128 anonymous auth by * none
EOF
)ssf or "security strength factors" is the corresponding level of protection. In the case of tls_ssf, this is the number of bits (so for example EXPORT or DES cipher suites won't be accepted).
The following command should still work:
ldapwhoami -x -D "uid=$user,ou=users,dc=lorn,dc=space" -w "$password" -H ldaps://ldap.service.lorn.spaceBut not that one anymore:
ldapwhoami -x -D "uid=$user,ou=users,dc=lorn,dc=space" -w "$password" -H ldap://ldap.service.lorn.spaceSSSD or the System Security Services Daemon may be seen as a more flexible (but more complex) alternative to the more common nslcd.
A basic /etc/sssd/sssd.conf would be (don't forget the chmod 0600 or sssd will complain):
[sssd]
config_file_version = 2
services = nss, pam
domains = LDAP
[domain/LDAP]
id_provider = ldap
auth_provider = ldap
access_provider = none
chpass_provider = none
sudo_provider = none
selinux_provider = none
subdomains_provider = none
autofs_provider = none
hostid_provider = none
ldap_schema = rfc2307bis
ldap_uri = ldaps://ldap.service.lorn.space
ldap_search_base = dc=lorn,dc=space
; those are set to false by default
; enumerate = true ; required for getent passwd
; cache_credentials = true ; would allow offline login
Debian packages installation should setup /etc/nsswitch.conf and PAM with the required entries.