System Administration

Joining Enterprise Linux to Active Directory

In this post I’ll outline the steps to join an Enterprise Linux host to Microsoft Active Directory for user account management.

Why would you want to do this?

In an Enterprise environment it’s common to have a mix of Windows and Unix/Linux machines. To resolve the issues of user account management across a network of systems you’ll typically find a centralised directory service such as Microsoft Active Directory. Active Directory manages the creation and administration of user accounts for any system joined to the domain, so an administrator can create a single user account once and deploy it anywhere in the Enterprise.

If all the systems across the network are Windows machines it’s simple to join them to the domain . However when you introduce Linux hosts into the mix things can get a little complicated.

Fortunately there’s a lot of high quality tools that help make this process relatively simple.

For this post I’m not going to go into the details of setting up a Windows domain controller. I’ll be using an already configured DC running on Windows Server 2016 in VirtualBox. I’ve also set up a user account to test.

I’ve also got an Oracle Linux 7 host set up on the same host-only network. The steps here should work for any RHEL based Linux distribution, such as CentOS or Red Hat Enterprise Linux. The process for Debian based distributions should be similar however the package names might be slightly different.

Install the required packages.

$ sudo yum install adcli sssd authconfig realmd krb5-workstation oddjob oddjob-mkhomedir samba-common-tools

Once those are installed we can use realm to join to the Windows domain. For simplicity sake I’ve used my domain name for the domain controller. This isn’t a publicly accessible system and I’ve updated the /etc/hosts file to point the Linux host to the Windows machine.

$ sudo realm discover

realm discover will print the domain configuration for the domain.

Next we can use realm join to join the Linux host to the domain.

$ sudo realm join --verbose --user=Administrator

If the domain controller is setup correctly and everything worked you should see the message at the bottom of the screen “Successfully enrolled machine in realm”.

Verify the Linux client is connected to the Windows domain.

$ realm list

Now we can configure NSS to authenticate users.

$ authconfig --enablesssd --enablesssdauth --enablemkhomedir --update

I had to manually edit the /etc/samba/smb.conf, /etc/krb5.conf and /etc/sssd/sssd.conf files to make sure all the settings were correct. I’d also recommend updating your nameserver settings in /etc/resolv.conf to point to the Windows Server.

If everything went according to plan (which mine didn’t at first) you should be able to query Active Directory for a user and then login as that user.

$ id DAVIDRODDICK\\droddick
$ su - DAVIDRODDICK\\droddick

If you can now successfully log into the user account that was created in Active Directory from the Linux host everything should be set up correctly.

System Administration

Managing Linux servers with Ansible

Recently I was contracted to work on a security upgrade program across a fleet of Linux servers. Most of the servers are Red Hat based and are configured using Ansible, which is a configuration management and automation tool sponsored by Red Hat.

Ansible lets you define the state that your servers should be in using YAML and then proceeds to create that state over SSH. For example, the state might be that Apache should be present and enabled.

The great thing about Ansible is if the server is already in the state that you’ve defined in your playbook then nothing happens. Ansible wont try to reinstall anything or change anything.

This might not seem like a big deal if you’ve only got to configure a small number of servers, but on larger installations where there’s 10s or 100s of servers or more being able to define how you want the servers to be and automating the configuration is essential.

For the purposes of this demonstration I’ll launch a small CentOS server in Linode and install Apache using Ansible.

Once the server is running, we can test the connection to the remote host by running ansible’s setup module.

$ ansible -i hosts -m setup -u centos all

Note the arguments being passed to ansible. The -m setup loads the setup module. The setup module gathers all the facts about the host and displays them in JSON format.

The -u centos is the user I’ve configured (with sudo privileges) that will be running the tasks.

The -i hosts argument loads a text file in the ansible project directory (in this case it’s just a directory in my local user home) that has a list of IP addresses for the servers ansible will be communicating with. The file could have been named anything. As an example it might look like this:


Where the word in square brackets is the host group, in this case the host is in the www group, and underneath is a list of IP addresses.

Now that I know I can communicate with the server using ansible, I’m going to deploy Apache.

The previous setup command was known as an adhoc ansible command and is essentially just for running once off commands across your fleet. Normally though you’d define your tasks in a playbook and instruct ansible to run those which would allow you to ensure the state is always how you expect it be and also allows you to store your tasks in version control to track changes.

The ansible task looks like this:

- name: Install Apache
    name: httpd 
    state: present

This task instructs Ansible to use the yum module which is the package manager module for Red Hat based Linux systems, and install the httpd package. Setting state to present ensures that if the server doesn’t have Apache installed then yum will install it.

Once it’s installed we want to make sure it’s running.

- name: Start apache
    name: httpd
    state: started

How you structure your ansible project will depend on the scope of tasks you need completed. For small tasks like this I can use a simple playbook, but for larger installations with many tasks you might consider using ansible roles. Roles are a bit beyond what I want to discuss here, so I’ll stick with a simple playbook. In a file called site.yml the complete play might look like this:

- hosts: www
  become: yes

    - name: Install Apache
        name: httpd
        state: present

    - name: Start Apache
        name: httpd
        state: started

Then run the playbook with the following command:

$ ansible-playbook -i hosts -u centos site.yml 

The command ansible-playbook is used instead of ansible that we ran previously and instead of passing the -m command to load a module we pass the name of the playbook, in this case site.yml.

We should now be able to go the server IP and see the default Apache page.