Running a containerized ActiveDirectory for developers

If you develop software for larger organizations one big aspect is integrating it with existing infrastructure. While you may prefer simple deployments of services in docker containers a customer may want you to deploy to their wildfly infrastructure for example.

One common case of infrastructure is an Active Directory (AD) or plain LDAP service used for organization wide authentication and authorization. As a small company we do not have such an infrastructure ourselves and it would not be a great idea to use it for development anyway.

So how do you develop and test your authentication module without an AD being available for you?

Fortunately, nowadays this is relatively easy using tools like Docker and Samba. Let us see how to put such a development infrastructure up and where the pitfalls are.

Running Samba in a Container

Samba cannot only serve windows shares or act as an domain controller for Microsoft Windows based networks but includes a full AD implementation with proper LDAP support. It takes a small amount of work besides installing Samba in a container to set it up, so we have two small shell scripts for setup and launch in a container. I think most of the Dockerfile and scripts should be self-explanatory and straightforward:

Dockerfile:

FROM ubuntu:20.04

RUN DEBIAN_FRONTEND=noninteractive apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install samba krb5-config winbind smbclient 
RUN DEBIAN_FRONTEND=noninteractive apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install iproute2
RUN DEBIAN_FRONTEND=noninteractive apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install openssl
RUN DEBIAN_FRONTEND=noninteractive apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install vim

RUN rm /etc/krb5.conf
RUN mkdir -p /opt/ad-scripts

WORKDIR /opt/ad-scripts

CMD chmod +x *.sh && ./samba-ad-setup.sh && ./samba-ad-run.sh

samba-ad-setup.sh:

#!/bin/bash

set -e

info () {
    echo "[INFO] $@"
}

info "Running setup"

# Check if samba is setup
[ -f /var/lib/samba/.setup ] && info "Already setup..." && exit 0

info "Provisioning domain controller..."

info "Given admin password: ${SMB_ADMIN_PASSWORD}"

rm /etc/samba/smb.conf

samba-tool domain provision\
 --server-role=dc\
 --use-rfc2307\
 --dns-backend=SAMBA_INTERNAL\
 --realm=`hostname`\
 --domain=DEV-AD\
 --adminpass=${SMB_ADMIN_PASSWORD}

mv /etc/samba/smb.conf /var/lib/samba/private/smb.conf

touch /var/lib/samba/.setup

Using samba-ad-run.sh we start samba directly instead of running it as a service which you would do outside a container:

#!/bin/bash

set -e

[ -f /var/lib/samba/.setup ] || {
    >&2 echo "[ERROR] Samba is not setup yet, which should happen automatically. Look for errors!"
    exit 127
}

samba -i -s /var/lib/samba/private/smb.conf

With the scripts and the Dockerfile in place you can simply build the container image using a command like

docker build -t dev-ad -f Dockerfile .

We then run it like follows and use the local mounts to preserve the data in the AD we will be using for testing and toying around:

 docker run --name dev-ad --hostname ldap.schneide.dev --privileged -p 636:636 -e SMB_ADMIN_PASSWORD=admin123! -v $PWD/:/opt/ad-scripts -v $PWD/samba-data:/var/lib/samba dev-ad

To have everything running seamlessly you should add the specified hostname – ldap.schneide.dev in our example – to /etc/hosts so that all tools work as expected and like it was a real AD host somewhere.

Testing our setup

Now of course you may want to check if your development AD works as expected and maybe add some groups and users which you need for your implementation to work.

While there are a bunch of tools for working with an AD/LDAP I found the old and sturdy LdapAdmin the easiest and most straightforward to use. It comes as one self-contained executable file (downloadable from Sourceforge) ready to use without installation or other hassles.

After getting the container and LdapAdmin up and running and logging in you should see something like this below:

LdapAdmin Window showing our Samba AD

Then you can browse and edit your active directory to fit your needs allowing you to develop your authentication and authorization module based on LDAP.

I hope you found the above useful for you development setup.

12 thoughts on “Running a containerized ActiveDirectory for developers”

  1. I have followed all the steps, but I’m getting an error message “/usr/sbin/samba_dnsupdate: ERROR: Record already exist; record could not be added. zone[ldap.act.local] name[_ldap._tcp.Default-First-Site-Name._sites.ForestDnsZones] dnsupdate_nameupdate_done: Failed DNS update with exit code 29”

      1. I’m trying to login through the LdapAdmin tool but I keep getting an error message.

        LDAP error! Invalid Credentials: 80090308: LdapErr: DSID-0C0903A9, commnet: AcceptSecurityContext error, data 52e, v1db1.
        The token supplied to the function is invalid.

        In the Base filed I have: DC=ldap,DC=schneide,DC=dev
        In the Username field I have: CN=Administrator,DC=ldap,DC=schneide,DC=dev

        Also, when I try to run the samba-ad-run.sh I get the following error: “[ERROR] Samba is not setup yet, which should happen automatically. Look for errors!”.

  2. Is there a way to get rid of the warning “The server you are trying to connect to is using a certificate which could not be verified! – Issuer certificate not found”?

    1. In development I tend to avoid the certificate hassle by connecting unencrypted to the LDAP. Usually you have to allow unencrypted authentication using samba explicitly by setting

      [global]
      ldap server require strong auth = no

      in /var/lib/samba/private/smb.conf of the container/samba. Do NOT use this setting for your production environment unless you are really knowing what you are doing.

  3. Is there a way to connect to the LDAP tool using the domain name, instead of the full base DN path DC=ldap,DC=schneide,DC=dev?

  4. I am able to add users to my LDAP server using LDAP Admin by using the Edit > New > User wizard. But when I try to create a new group using the Edit > New > Group wizard, I get the following error:

    LDAP error! Object Class Violation: no structural object class provided

    How can I create new groups in LDAP Admin?

      1. I tried right-click on a folder -> New -> Group and also the shortcut is ctrl+G.

        LDAP error! Unwilling to perform: Failed to find a structural class for CN=testgroup,CN=Users,DC=test,DC=ad,DC=dev.

      2. I tried creating a group using the shortcut ctrl+G, but I’m still getting an error message: LDAP error! Unwilling to perform: Failed to find a structural class for CN=testgroup,CN=Users,DC=test,DC=ad,DC=dev.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.