OpenLDAP
How to create a small OpenLDAP server in a container
In some cases where you need to spin up a small LDAP server for testing or 'temporary production' environments, the following docker-compose stack should fit the bill. This stack will utilize a bootstrap.ldif file to populate the LDAP directory. You may choose to keep this LDAP server without any state (useful for testing) by simply not mounting the data volumes. In such cases, a restart of the container will re-create all users and groups based on the bootstrap.ldif.
This docker-compose stack also includes an instance of PHPLdapAdmin, a web tool that lets you view and manage users and groups. You may remove this if desired by commenting out the lines in the docker-compose.yml file.
Create a docker-compose.yml file with the following contents. Adjust as necessary. Notice the admin LDAP account password is given as an environment variable.
version: '3.3'
services:
ldap:
image: osixia/openldap
restart: always
volumes:
- ./config:/container/service/slapd/assets/config/bootstrap/ldif/custom
# For persistent states, you may also want tot add these volumes
# - ./data:/var/lib/ldap
# - ./config:/etc/ldap/slapd.d
environment:
- "TZ=MST7MDT,M3.2.0,M11.1.0"
- LDAP_ORGANISATION=Home
- LDAP_DOMAIN=home.steamr.com
- LDAP_ADMIN_PASSWORD=super-secret-password
- LDAP_TLS="false"
- LDAP_RFC2307BIS_SCHEMA="true"
expose:
- "389"
ports:
- "10.1.1.1:389:389"
networks:
- internal
command: --copy-service
phpldapadmin:
image: osixia/phpldapadmin:latest
container_name: phpldapadmin
environment:
PHPLDAPADMIN_LDAP_HOSTS: "ldap"
PHPLDAPADMIN_HTTPS: "false"
# If you are using traefik as a reverse proxy service...
#labels:
# - traefik.enable=true ... etc
#expose:
# - "80"
# Otherwise, expose port 80.
ports:
- "10.1.1.1:80:80"
depends_on:
- ldap
networks:
- internal
networks:
internal:
Next, create your bootstrap.ldif file. This file contains all the users and groups that should be set up when the container starts up. It does not take effect if there are existing data in the /var/lib/ldap location. The admin account can be left out from this file since it will be set up by the container entrypoint script based on the environment variables.
Here's an example file where I create my account in addition to one group.
dn: ou=groups,dc=home,dc=steamr,dc=com
objectclass: organizationalUnit
objectclass: top
ou: groups
dn: cn=downloaders,ou=groups,dc=home,dc=steamr,dc=com
cn: downloaders
gidnumber: 250
objectclass: posixGroup
objectclass: top
ou=users,dc=home,dc=steamr,dc=com
dn: ou=users,dc=home,dc=steamr,dc=com
objectclass: organizationalUnit
objectclass: top
ou: users
dn: cn=leo,ou=users,dc=home,dc=steamr,dc=com
cn: leo
displayname: Leo Leung
gidnumber: 500
givenname: leo
homedirectory: /home/leo
loginshell: /bin/bash
mail: leo@example.com
objectclass: top
objectclass: inetOrgPerson
objectclass: posixAccount
sn: Leung
uid: leo
uidnumber: 500
userpassword: asdfasdf
Bring everything up with docker-compose up -d.
The container will set up an admin account directly in the root of the directory. Once everything is running, you can login to PHPLdapAdmin as cn=admin,dc=example,dc=com using the password set by the LDAP_ADMIN_PASSWORD environment variable.
Anonymous binds are not enabled by default, but you can create a readonly account using the LDAP_READONLY_USER environment variable, which will create a cn=readonly account.
Troubleshooting
If your bootstrap.ldif file isn't taking effect, it most likely has some issues that's preventing it from being loaded. In such circumstance, it is best to enter the container and manually try loading the ldif file.
# docker exec -ti <docker container> bash
# ldapadd -Z -D cn=admin,dc=example,dc=com -w password -f /container/service/slapd/assets/config/bootstrap/ldif/custom/bootstrap.ldif
Samba integration
Samba integration with LDAP simply means that the samba credentials and user properties are stored in the user's account rather than the SAM database on the local server. The steps below will go over how to set this up.
Note: Your LDAP server should have the samba schemas. If you are using the osixia OpenLDAP container, this should already be bundled.
Edit smb.conf. Add the following lines under [global]:
[global]
workgroup = MYGROUP
passdb backend = ldapsam:ldap://10.1.1.9
ldap suffix = dc=home,dc=steamr,dc=com
ldap admin dn = cn=admin,dc=home,dc=steamr,dc=com
ldap user suffix = ou=users
ldap machine suffix = ou=computers
ldap group suffix = ou=group
ldap passwd sync = yes
ldap ssl = no
Change the workgroup name and LDAP server and base DN as required. For this example, I will not be using TLS.
Restart samba. If samba fails to start, check the samba logs. I ran into some issues getting samba to start at this step which I documented in the troubleshooting below.
Get the local SID:
# net getlocalsid
SID for domain SERVER is: S-1-5-21-3808049139-2148245656-2735675580
Using this SID, import this entry into your LDAP server using ldapadd -x -D ... -x ... -f import.ldif:
dn: sambaDomainName=MYGROUP,dc=home,dc=steamr,dc=com
objectclass: sambaDomain
objectclass: sambaUnixIdPool
objectclass: top
sambaDomainName: MYGROUP
sambaSID: S-1-5-21-3808049139-2148245656-2735675580
uidNumber: 550
gidNumber: 550
Restart samba, then try to add a new user:
# smbpasswd -a leo
New SMB password:
Retype new SMB password:
Added user leo
When successful, you should see a bunch of new attributes for the user in the LDAP server.
Troubleshooting
NT_STATUS_NO_MEMORY:
[2021/07/17 23:22:03.698217, 0] ../../source3/passdb/secrets.c:364(fetch_ldap_pw)
fetch_ldap_pw: neither ldap secret retrieved!
[2021/07/17 23:22:03.698463, 0] ../../source3/passdb/pdb_ldap.c:6652(pdb_init_ldapsam_common)
pdb_init_ldapsam_common: Failed to retrieve LDAP password from secrets.tdb
[2021/07/17 23:22:03.698488, 0] ../../source3/passdb/pdb_interface.c:180(make_pdb_method_name)
pdb backend ldapsam:ldap://10.1.1.9 did not correctly init (error was NT_STATUS_NO_MEMORY)
This was caused by bad LDAP bind credentials.
NT_STATUS_CANT_ACCESS_DOMAIN_INFO:
[2021/07/17 23:53:29.901142, 0] ../../source3/lib/smbldap.c:628(smbldap_start_tls)
Failed to issue the StartTLS instruction: Protocol error
[2021/07/17 23:53:30.905981, 0] ../../source3/passdb/pdb_ldap.c:6753(pdb_ldapsam_init_common)
pdb_init_ldapsam: WARNING: Could not get domain info, nor add one to the domain. We cannot work reliably without it.
[2021/07/17 23:53:30.906196, 0] ../../source3/passdb/pdb_interface.c:180(make_pdb_method_name)
pdb backend ldapsam:ldap://10.1.1.9 did not correctly init (error was NT_STATUS_CANT_ACCESS_DOMAIN_INFO)
This was fixed after setting no ssl.
See also:
- https://access.redhat.com/articles/17303
- https://7thzero.com/blog/configure-centos-7-samba-server-use-secure-ldap-authentication