Building a FreeIPA Lab
May 14 2020
By: Julian Catrambone • 7 min read
Recently I started a series of blog posts detailing some of the lessons I learned about FreeIPA, how it works, and my methodology behind attacking it. In this post I wanted to document how I built a lab to conduct my research, because the process was a huge learning experience for me. If you want to checkout the other posts from that series I will link them below:
- The first post details how authentication works inside of FreeIPA, and how an adversary may abuse it inside of a production environment.
- The second post details how various objects and structures in FreeIPA work as well as how they interact with each other. It also covers how an adversary may enumerate and identify attack paths based on these objects.
Having a lab environment provides a safe space to deploy, learn, and ultimately destroy hosts without the consequences that would normally come from researching in production. The process to build and deploy FreeIPA is not simple, and there are a lot of roadblocks that I hit along the way. I am creating this post to document the struggles I encountered, and how I eventually solved them. Hopefully this helps others who have run into issues creating a stable FreeIPA lab environment.
Before we get into the actual lab setup process let me document my current system configuration. This small detail may not seem important but the setup does vary based on the host os and virtualization platform. I am building this lab on a host running MacOS Catalina 10.15.4, and Docker Desktop 2.3.0.2 (Engine 19.03.8).
Okay so let’s get started. Red Hat maintains several docker images prebuilt for both FreeIPA servers, and clients available on dockerhub. They also include some documentation on getting everything running. However, for this tutorial I will be using a forked version of the existing images due to the existing images lacking SSH.
First let’s grab and build the containers from Github.
git clone https://github.com/n0pe-sled/freeipa-container.git
cd freeipa-container
docker build -t freeipa-server .
Once the container is built we need to create a docker managed volume to store all the custom data associated with our FreeIPA Server. We can create this volume with the following command:
docker volume create --name ipa
docker volume inspect ipa
Next we need to create a network inside of Docker for the FreeIPA range to utilize:
docker network create ipanet
docker inspect ipanet
Now we should be able to create our FreeIPA Server using the pulled image, and our docker volume:
sudo docker run --name ipa.westeros.local -ti -h ipa.westeros.local --sysctl net.ipv6.conf.all.disable_ipv6=0 -v /sys/fs/cgroup:/sys/fs/cgroup:ro --mount source=ipa,target=/data --network ipanet --publish 127.0.0.1:443:443 freeipa-server:latest
If everything works you should see output fairly similar to the following:

Now that the container is running we need to configure the actual server. Here is how I responded to the installation prompts:
Do you want to configure integrated DNS (BIND)? : noEnter the fully qualified domain name of the computer
on which you're setting up server software. Using the form
<hostname>.<domainname>
Example: master.example.com.
Server host name [ipa.westeros.local]: ipa.westeros.localPlease confirm the domain name [westeros.local]: westeros.localPlease provide a realm name [WESTEROS.LOCAL]: WESTEROS.LOCAL
Certain directory server operations require an administrative user.This user is referred to as the Directory Manager and has full access to the Directory for system management tasks and will be added to theinstance of directory server created for IPA.
The password must be at least 8 characters long.Directory Manager password: <password>
Password (confirm): <password>The IPA server requires an administrative user, named 'admin'.
This user is a regular system account used for IPA server administration.IPA admin password: <password>
Password (confirm): <password>Do you want to configure chrony with NTP server or pool address? [no]: noThe IPA Master Server will be configured with:Hostname: ipa.westeros.local
IP address(es): 172.18.0.2
Domain name: westeros.local
Realm name: WESTEROS.LOCALThe CA will be configured with:
Subject DN: CN=Certificate Authority,O=WESTEROS.LOCAL
Subject base: O=WESTEROS.LOCAL
Chaining: self-signed
Once all the prompts are completed the docker container will begin the setup process for the FreeIPA server. This may take some time so grab a coffee, stretch, or just take a break. Make sure to remember the admin passwords set above, as well as the IP Address reported under the hostname.
After the installation finishes open a new terminal window and restart the instance:
docker stop ipa.westeros.local
docker start ipa.westeros.local
Once restarted, lets begin configuring DNS. Obtain an interactive shell to ipa.westeros.local with the following docker command:
docker exec -it ipa.westeros.local bash
Inside the shell run the following to configure DNS:
ipa-dns-install --ip-address=172.18.0.2 --no-forwardersThe log file for this installation can be found in /var/log/ipaserver-install.log==============================================================================This program will setup DNS for the FreeIPA Server.
This includes:
* Configure DNS (bind)
* Configure SoftHSM (required by DNSSEC)
* Configure ipa-dnskeysyncd (required by DNSSEC)NOTE: DNSSEC zone signing is not enabled by defaultTo accept the default shown in brackets, press the Enter key.
Do you want to search for missing reverse zones? [yes]: yesThe following operations may take some minutes to complete.
Please wait until the prompt is returned.
After a few minutes it should report setup complete! Now that our server is up and running let’s verify that we can obtain a ticket for our admin user:
[root@ipa /]# kinit admin
Password for admin@WESTEROS.LOCAL:[root@ipa /]# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: admin@WESTEROS.LOCALValid starting Expires Service principal
05/11/20 19:37:56 05/12/20 19:37:53
krbtgt/WESTEROS.LOCAL@WESTEROS.LOCAL
[root@ipa /]#
Awesome, we just built a working FreeIPA server with integrated DNS. Let’s add a client. Open a fresh terminal window and return to the FreeIPA Container code we cloned from Github earlier. Use git checkout to switch the branch to the client image, and build it using the following commands:
git checkout centos-7-client
docker build -t freeipa-client .
Once built we can create a new client for our FreeIPA domain. For each client we create, we also need to create a respective docker volume to store data associated with the container. We can do that with the following command:
docker volume create bastion
Now that the volume is created we can start creating the new client. However, before we continue take time to recall the admin password, and the ip address for the IPA server set above. Ensure that you change the following variables before running the docker command:
-e PASSWORD=<password set above>
--dns=<IPA Server IP Address>
--mount source=<name of new volume created>,target=/data
Fill in those three variables to the docker run command below to create a new client inside of the FreeIPA Domain.
sudo docker run --name bastion.westeros.local -ti -h bastion.westeros.local --sysctl net.ipv6.conf.all.disable_ipv6=0 -v /sys/fs/cgroup:/sys/fs/cgroup:ro --mount source=<name of volume created>,target=/data -e PASSWORD=<Password set earlier> --network ipanet --dns <IPA Server IP Address> --dns 1.1.1.1 freeipa-client:latest
If all goes well you should be dropped into an interactive shell! Just repeat the steps above to create new clients for your FreeIPA domain, ensuring to change the name, hostname, and volume for each one.
Finally, now that the environment is setup lets discuss how to utilize the administrative web application to manage this environment. Earlier while creating the FreeIPA server we published port 443 from the server to 127.0.0.1:443 specifically to enable this functionality. In a new terminal window the following line to the /etc/hosts file:
127.0.0.1 ipa.westeros.local
With that entry, and the IPA server docker container running we should be able to login to the admin interface through any web browser.

Hopefully this post can help serve as a guide to get more people researching this technology!