Using sssd in a Playground Without TLS

October 1, 2022 / 5 minute read

Share this:

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: [email protected]
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: [email protected]
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:

  1. We created a persistent network for our containers to share
  2. We provisioned users from our ldif file
  3. We disabled TLS on the service
  4. 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 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.