Using sssd in a Playground Without TLS
Tags: authentication, beginners, devops, tutorial
Published: 2022-10-01 23:59:50


[`sssd`](https://sssd.io/) 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](https://github.com/osixia/docker-openldap), [although there are other options](https://github.com/nitnelave/lldap).

```bash
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](https://github.com/colearendt/container-playground):

_users.ldif_
```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!

```bash
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

```bash
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.

```bash
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!
```bash
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
```bash
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.

```bash
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](https://github.com/colearendt/container-playground) in lieu of the above if you prefer.

```bash
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 <a href="https://unsplash.com/@dylu?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Jacek Dylag</a> on <a href="https://unsplash.com/photos/PMxT0XtQ--A?utm_source=unsplash&utm_medium=referral&utm_content=creditShareLink">Unsplash</a>