Passa al contenuto principale

OpenLDAP

This app provides LDAP authentication for other applications. It also has a web interface that allows users to change or recover their password. For each user it basically keeps a username, password and email address. However it is possible to customize it in order to store other fields as well (for each user), according to the needs of applications.

1. Installation

  1. Get the scripts and initialize a directory:

    ds pull openldap
    ds init openldap @ldap.user1.fs.al
    cd /var/ds/ldap.user1.fs.al
  2. Customize and build the container:

    nano settings.sh
    ds make

    Let's comment out (or delete) PORTS, since we don't want it to be accessed from the internet (it will be used only internally). Let's also change LDAP_ADMIN_PASSWORD, SMTP_HOST and MAIL_FROM.

  3. Check the container:

    ls
    ds shell
    hostname
    ps ax
    systemctl status slapd
    slapcat
    apt install less
    slapcat -n0 | less
    ds exit

2. Usage

2.1 Organization units (OU)

Organizational units are like subdirectories (or main branches) from the root.

Add organizational units (under the root of DIT):

ds ou
ds ou add users
ds ou add groups
ds ou add apps
ds ou ls

2.2 Manage users

ds user
ds user add \
users \
test1 \
test1@user1.fs.al \
pass123

ds user add \
users \
test2 \
test2@user1.fs.al \
# no password
ds set-passwd \
pass234 \
uid=test2,ou=users,dc=user1,dc=fs,dc=al

ds user ls

ds user del users test1
ds user ls
note

The users that are created with ds user add have a minimal data structure, as seen on the examples above. This is usually sufficient for authentication purposes. But if we have to customize it, we can make a local copy of cmd/user.sh and modify it as needed.

informazioni

The users can change or recover their password with a web interface: https://ldap.user1.fs.al/

2.3 App credentials

ds app
ds app add test1 pass123
ds app add mail1 pass234
ds app add nc1 pass345

ds app ls
ds app del test1
ds app ls

These app credentials look like cn=test1,ou=apps,dc=user1,dc=fs,dc=al and they have read-only access to the data. On the other hand, the normal users can authenticate with their own password, and change their own password, and nothing else.

Let's check that we are able to read data from the LDAP server, using the credetials of cn=mail1,ou=apps,dc=user1,dc=fs,dc=al:

apt install ldap-utils

ds app ls
ds user ls

ldapsearch -xLLL \
-H ldap://ldap.user1.fs.al/ \
-D cn=mail1,ou=apps,dc=user1,dc=fs,dc=al \
-w pass234 \
-b ou=users,dc=user1,dc=fs,dc=al \
"(uid=test2)"
  • The option -H specifies the LDAP host (and protocol: ldap/ldaps).
  • The option -D is like a username or an app ID (it is called "bind dn").
  • The option -w is like a password or secret token (called "bind password").
  • The option -b is the branch of the directory where the searching starts (called "base dn" or "search base").
  • The last argument is the LDAP filter used for searching.
suggerimento
ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)

If you get an error message like this, then uncomment PORTS="389:389" on settings.sh and remake the container with ds make.

Try the same command with -D cn=mail2,ou=apps,dc=user1,dc=fs,dc=al (where app mail2 does not exist), and with a filter "(uid=test1)" (where uid test1 does not exist).

With the option -ZZ we can request a TLS connection, which is better than a plain text connection for security reasons:

ldapsearch -xLLL -ZZ \
-H ldap://ldap.user1.fs.al/ \
-D cn=mail1,ou=apps,dc=user1,dc=fs,dc=al \
-w pass234 \
-b ou=users,dc=user1,dc=fs,dc=al \
"(uid=test2)" \
uid mail

The arguments after the filter (uid and email) are the list of attributes to show.

suggerimento

If there is any problem, add the option -d9 for debugging.

2.4 Modify

Let's say that we want to make some modifications to the data. For example change the email of a user. There is no special command for this case (like ds ou, ds user and ds app), but we can use the generic command cmd/modify.sh:

ds modify --help

cat <<EOF > modify-test2-email.ldif
dn: uid=test2,ou=users,dc=user1,dc=fs,dc=al
changetype: modify
replace: mail
mail: xyz@user1.fs.al
EOF

nano modify-test2-email.ldif
ds user ls
ds modify modify-test2-email.ldif
ds user ls

Let's restore back the email:

nano modify-test2-email.ldif
cat modify-test2-email.ldif
cat modify-test2-email.ldif | ds modify

cat <<EOF | ds modify
dn: uid=test2,ou=users,dc=user1,dc=fs,dc=al
changetype: modify
replace: mail
mail: test2@user1.fs.al
EOF

ds user ls

The format of input is LDIF, and it can be used for all kinds of modifications in the database.

note

By the way, the commands ds ou, ds user and ds app, under the hood use ds modify.

ds user add users test1 test1@user1.fs.al pass123
ds user ls

ds search | less
ds search "(uid=test*)"
ds search "(uid=test*)" dn
ds search "(uid=test*)" cn mail
ds search "(mail=*@user1.fs.al)" mail
ds search "(mail=*.fs.al)" mail | grep 'mail:'

ds search "(objectClass=inetOrgPerson)"
ds search "(&(objectClass=inetOrgPerson)(uid=test2))"
ds search "(objectClass=organizationalUnit)"
ds search "(objectClass=organizationalRole)"

The first argument is an LDAP filter.

2.6 Backup and restore

ds backup
tar tvfz backup-*.tgz
ds restore backup-*.tgz

3. Customize

The command ds user add assumes a very basic (minimalist) data structure for each user, with a uid, mail, and userPassword, which looks like this:

dn: uid=test1,ou=users,dc=user1,dc=fs,dc=al
uid: test1
objectClass: top
objectClass: inetOrgPerson
sn: test1
cn: test1
mail: test1@user1.fs.al
userPassword:: e1NTSEF9T2NlUExtSUIvQjF6SE51cVQ3WlFCaTNISFEvanJhUSs=

This is usually sufficient for authentication purposes (for example using uid or mail as username).

Sometimes we may need to store more data for each user. For example, let's say that we want to store the first name of the user in the cn: attribute, and store the last name on the sn: attribute.

In this case, we can modify the behavior of the command ds user by creating a local copy of cmd/user.sh, which will override the app copy:

cd /var/ds/ldap.user1.fs.al/
mkdir -p cmd/
cp /opt/docker-scripts/openldap/cmd/user.sh cmd/

nano cmd/user.sh
cmd/user.sh

For storing the first name and last name, the modified local copy of the script might look like this:

cmd_user_help() {
cat <<_EOF
user add <ou> <uid> <mail> <first-name> <last-name> [<passwd>]
user del <ou> <uid>
user (list | ls) [...]

_EOF
}

cmd_user() {
local cmd=$1 ; shift
case $cmd in
add|del)
_user$cmd "$@"
;;
list|ls)
_user_ls "$@"
;;
)
fail "Usage:\n$(cmd_user_help)\n"
;;
esac
}

_user_add() {
local ou=$1 uid=$2 mail=$3 first_name=$4 last_name=$5 passwd=$6
[[ -n $ou && -n $uid && -n $mail && -n $first_name && -n $last_name ]] \
|| fail "Usage:\n$(cmd_user_help)\n"

cat <<EOF | ds modify
dn: uid=$uid,ou=$ou,$(get_root_of_dit)
changetype: add
uid: $uid
objectClass: top
objectClass: inetOrgPerson
sn: $last_name
cn: $first_name
mail: $mail
EOF

[[ -n $passwd ]] && \
ds set-passwd $passwd "uid=$uid,ou=$ou,$(get_root_of_dit)"
}

_user_del() {
local ou=$1 uid=$2
[[ -n $ou && -n $uid ]] \
|| fail "Usage:\n$(cmd_user_help)\n"

cat <<EOF | ds modify
dn: uid=$uid,ou=$ou,$(get_root_of_dit)
changetype: delete
EOF
}

_user_ls() {
ds search "(uid=)" "$@"
}