sssd
has established itself as the most common way to provision system accounts via LDAP or Active Directory on linux servers across all linux distributions. However, working with it can be tricky!
TL;DR;
We show an example of using sssd
to contact an LDAP server that is listening on port 389 (in plaintext / no TLS). This is NOT a good idea in any production environment. However, it can be important and helpful in playgrounds, learning, or other experiments. The magic configuration is ldap_auth_disable_tls_never_use_in_production = true
.
Why
It is quite straightforward to stand up an LDAP server listening in plaintext. My favorite mechanism is using the openldap
container, although there are other options.
docker run -it --rm -p 389:389 osixia/openldap:latest
However, if you have a toy linux container running sssd
, this is unfortunately not an obvious option! Why, you ask? This is all just a dev playground!? Right. Well the sssd
maintainers want to be very careful about not creating security vulnerabilities or letting their users get hacked. This means you have to work hard to open yourself up to this type of vulnerability in your playground.
Specifically, we will use the ldap_auth_disable_tls_never_use_in_production
setting.
NOTE: Do not use this setting in any "real" environment with "real" users, passwords, sensitive data, etc.
Give it a Shot
Create Users
First, we need to create and populate our LDAP server. Let's go ahead and do that. It is easiest if we create a file with users first. For a more advanced LDIF file, check out the repository associated with this post:
users.ldif
version: 1
## Entry 1: dc=angl,dc=dev
#dn: dc=angl,dc=dev
#dc: angl
#o: Angl Dev
#objectclass: top
#objectclass: dcObject
#objectclass: organization
#
## Entry 2: cn=admin,dc=angl,dc=dev
#dn: cn=admin,dc=angl,dc=dev
#cn: admin
#description: LDAP administrator
#objectclass: simpleSecurityObject
#objectclass: organizationalRole
#userpassword: {SSHA}+FquX8RcwTtBPo7mu2pgSvjaQYX9HpCL
#
#
# Entry 3: cn=engineering_group,dc=angl,dc=dev
dn: cn=engineering_group,dc=angl,dc=dev
cn: engineering_group
gidnumber: 500
memberuid: joe
memberuid: julie
objectclass: posixGroup
objectclass: top
# Entry 4: dc=engineering,dc=angl,dc=dev
dn: dc=engineering,dc=angl,dc=dev
dc: engineering
description: The Engineering Department
o: Engineering
objectclass: dcObject
objectclass: organization
objectclass: top
# Entry 5: cn=joe,dc=engineering,dc=angl,dc=dev
dn: cn=joe,dc=engineering,dc=angl,dc=dev
cn: joe
gidnumber: 500
givenname: Joe
homedirectory: /home/joe
loginshell: /bin/sh
mail: joe@angl.dev
objectclass: inetOrgPerson
objectclass: posixAccount
objectclass: top
sn: Golly
uid: joe
uidnumber: 1000
userpassword: {MD5}j/MkifkvM0FmlL6P3C1MIg==
# Entry 9: cn=julie,dc=engineering,dc=angl,dc=dev
dn: cn=julie,dc=engineering,dc=angl,dc=dev
cn: julie
gidnumber: 500
givenname: Julie
homedirectory: /home/julie
loginshell: /bin/sh
mail: julie@angl.dev
objectclass: inetOrgPerson
objectclass: posixAccount
objectclass: top
sn: Jolly
uid: julie
uidnumber: 1001
userpassword: {MD5}FvEvXoN54ivpleUF6/wbhA==
You will notice that the first two entries are commented out. They are included to represent a complete LDIF file. However, the osixia/docker-openldap
container help us by provisioning these automatically.
Further, you will notice that passwords are included. This makes things easier for our playground, but is definitely a bad idea in real life / production applications.
Create LDAP Server
Now let's create the server itself!
docker network create playground-network
docker run \
-d --name openldap --rm \
-p 389:389 \
--network playground-network \
-v $(pwd)/users.ldif:/container/service/slapd/assets/config/bootstrap/ldif/50-bootstrap.ldif \
-e LDAP_TLS=false \
-e LDAP_DOMAIN="angl.dev" \
-e LDAP_ADMIN_PASSWORD="admin" \
osixia/openldap:1.5.0 \
--copy-service --loglevel debug
And check that it is working
docker exec -it openldap ldapsearch -D cn=admin,dc=angl,dc=dev -b dc=angl,dc=dev -w admin cn
docker exec -it openldap ldapsearch -D cn=admin,dc=angl,dc=dev -b dc=angl,dc=dev -w admin cn=julie \*
If you look carefully, you will notice that:
- We created a persistent network for our containers to share
- We provisioned users from our
ldif
file - We disabled TLS on the service
- We bumped up the logging verbosity for debugging purposes
These are all useful tidbits to dig into if you are not familiar!
Configure sssd Server
It is possible to run sssd
in a fairly vanilla ubuntu:jammy
container.
docker run -it --name sssd --rm --network playground-network ubuntu:jammy bash
apt update && apt install -y sssd ldap-utils vim
Then you need to create your sssd.conf
file. Notice our magic option ldap_auth_disable_tls_never_use_in_production=true
. This will be the magic that makes things work for us!
cat << EOF > /etc/sssd/sssd.conf
[sssd]
config_file_version = 2
services = nss, pam
domains = LDAP
[nss]
filter_users = root,named,avahi,haldaemon,dbus,radiusd,news,nscd
filter_groups =
[pam]
[domain/LDAP]
id_provider = ldap
auth_provider = ldap
chpass_provider = ldap
sudo_provider = ldap
enumerate = true
# ignore_group_members = true
cache_credentials = false
ldap_schema = rfc2307
ldap_uri = ldap://openldap:389
ldap_search_base = dc=angl,dc=dev
ldap_user_search_base = dc=angl,dc=dev
ldap_user_object_class = posixAccount
ldap_user_name = uid
ldap_group_search_base = dc=angl,dc=dev
ldap_group_object_class = posixGroup
ldap_group_name = cn
ldap_id_use_start_tls = false
ldap_tls_reqcert = never
ldap_tls_cacert = /etc/ssl/certs/ca-certificates.crt
ldap_default_bind_dn = cn=admin,dc=angl,dc=dev
ldap_default_authtok = admin
access_provider = ldap
ldap_access_filter = (objectClass=posixAccount)
min_id = 1
max_id = 0
ldap_user_uuid = entryUUID
ldap_user_shell = loginShell
ldap_user_home_directory = homeDirectory
ldap_user_uid_number = uidNumber
ldap_user_gid_number = gidNumber
ldap_group_gid_number = gidNumber
ldap_group_uuid = entryUUID
ldap_group_member = memberUid
ldap_auth_disable_tls_never_use_in_production = true
use_fully_qualified_names = false
ldap_access_order = filter
debug_level=6
EOF
chmod 600 /etc/sssd/sssd.conf
Now let's start the sssd
service
sssd -i
# should see some log messages that suggest things are happening!
Be sure it works!
Now let's make sure that this works by starting another shell in our jammy
container.
docker exec -it sssd bash
id joe
# uid=1000(joe) gid=500(engineering_group) groups=500(engineering_group)
id julie
# uid=1001(julie) gid=500(engineering_group) groups=500(engineering_group)
Using docker-compose
For playground environments like this, docker-compose
makes this setup much easier to architect and reuse. You can use my example compose setup in lieu of the above if you prefer.
cd compose/
docker network create playground-network
NETWORK=playground-network docker-compose -f ldap.yml -f sssd.yml -f network.yml up -d
docker exec -it compose_sssd_1 bash
sssd -i >/tmp/sssd.log 2>&1 &
id joe
Review
Well done! You have successfully started your own sssd
container. Although this is very much a toy, it is a great "jumping off point" to learn and understand how sssd
works in more detail!
Any time you need a toy LDAP server for sssd
, just remember: ldap_auth_disable_tls_never_use_in_production = true
.
Photo by Jacek Dylag on Unsplash
Top comments (0)