001 - Centos SSH Active Directory

Its a big pain to manage a lot of users in linux without centralized user management. One way is to use ansible but i have found LDAP and Active directory is great for this. I have done some testing in my lab environment and had to write this down for later reference.

Usually with few servers and users this simple ansible script can be used.

- name: Create user patrikwm
  user:
    name: patrikwm
    groups: wheel,sshusers
    password: "$6$rounds=656....Jce6tPRvP6Rl2a2oZ621"
    shell: /bin/bash

- name: Copy ssh public key for patrikwm
  authorized_key:
    user: patrikwm
    key: "ssh-rsa AAAAB3Nxo8...EROBCQlXr8Mw== patrikwm-workstation"

It nice at start. But then with more and more servers it becomes cumbersome to remove users and to know what users are added on the linux machines.

It is really easy to connect a centos 7 machine to Active directory with this guide. https://outsideit.net/realmd-sssd-ad-authentication/ It goes a little something like this.

LDAP AUTHENTICATION

  • domain: lab.local

  • user: patrikwm

Basically it went with the instructions from that page with small modifications. I install openldap-clients to get ldapsearch for later pubkeyauthentication.

yum -y install realmd sssd oddjob oddjob-mkhomedir adcli samba-common samba-common-tools ntpdate ntp openldap-clients

The linux NTP is really crutial for logging in to Active directory. Edit /etc/ntp.conf so it points to domainctroller. (Remember to open port udp/123 in the firewall on domaincontroller.

server dc01.lab.local
server dc02.lab.local

Enable ntpd and update the NTP time on linux machine.

systemctl enable ntpd
ntpdate -u dc01.lab.local
sysemctl start ntpd

Join the domain with Linux-server

realm join --user=patrikwm@lab.local lab.local

I was first trying to set the SSH user access group in sshd_config but i noticed that user groups are only updated after the user has logged in. This means that users that are not alredy in the system can not login if sshd_config AllowGroups sshusers@lab.local would not work if the user is not alredy on the system with that group.

Edit the /etc/sssd/sssd.conf file with following. And notice in the bottom there is a ad_access_filter group that specifies the allowed user group. https://github.com/patrikwm/Centos-SSH-Active-Directory/blob/master/sssd.conf

[sssd]
domains = lab.local
config_file_version = 2
services = nss, pam
default_domain_suffix = LAB.LOCAL

[domain/lab.local]
ad_domain = lab.local
krb5_realm = LAB.LOCAL
realmd_tags = manages-system joined-with-samba
cache_credentials = True
id_provider = ad
krb5_store_password_if_offline = True
default_shell = /bin/bash
ldap_id_mapping = True
use_fully_qualified_names = True
fallback_homedir = /home/%u@%d
access_provider = ad
ad_access_filter = memberOf=CN=linux_users,OU=company,DC=lab,DC=local

Now users should be able to login to the Linux system with ssh.

LDAP USER PUBKEY

Now when users can login to Linux with SSH lets continue with pubkey authentication. I started with adding a attribute to LDAP that hosted the sshkey for each user following this guide.

If you only want to use the functions in the script they can be loaded to the shell. The .<space> loads the function to the shell.

. .\functions.ps1

I created a script that adds the sshPublicKey attribute to the active directory schema. You can download it here. https://github.com/patrikwm/Centos-SSH-Active-Directory/blob/master/add-sshPublicKey-attribute.ps1

Following command adds a key to a user after running add-sshPublicKey-attribute.ps1 script.

./add-sshPublicKey-attribute.ps1
Get-ADUser patrikwm | Set-ADUser -Add @{sshPublicKey = 'ssh-rsa AAAAB3Nxo8...EROBCQlXr8Mw== patrikwm-workstation'}

When the key attribute is created we need to create a Class named ldapPublicKey and add it as a Auxiliary class to the User class in Activedirectory Schema. I have not figured out how to create a class in Powershell so i made this manually as in link 1 step (K). (https://technet.microsoft.com/en-us/library/2008.05.schema.aspx this could be some sollution for making it scriptable.)

SSH Key from LDAP to Centos

To get the ssh key to linux i use ldapsearch which is installed with the openldap-clients package. A link to the script is here. https://github.com/patrikwm/Centos-SSH-Active-Directory/blob/master/fetchSSHKeysFromLDAP

It is probably not best practice to write down a user and password in a file so machine authentication or so would be prefered but in a lab its ok i think.

wget https://raw.githubusercontent.com/patrikwm/Centos-SSH-Active-Directory/master/fetchSSHKeysFromLDAP -P /usr/local/bin/
chmod 0500 /usr/local/bin/fetchSSHKeysFromLDAP

Now the centos 7 host needs to use this script when ever the users are connecting this is done with following lines in /etc/ssh/sshd_config. AuthorizedKeysCommand executes the command and sends username after it. Since i use sAMAccountName which does not contain the @domain i removed everything after @ with a regexp in fetchSSHKeysFromLDAP. So AuthorizedKeysCommand would run this command in my lab. /usr/local/bin/fetchSSHKeysFromLDAP patrikwm@lab.local

PubkeyAuthentication yes
AuthorizedKeysCommandUser root
AuthorizedKeysCommand /usr/local/bin/fetchSSHKeysFromLDAP

If above does not work. try turning off selinux

setenforce 0

Fixing SELINUX

First i always mess up the locale. So i need to fix it.

export LC_ALL="en_US.UTF-8"
export LC_CTYPE="en_US.UTF-8"

Install following TE files.

wget https://github.com/patrikwm/Centos-SSH-Active-Directory/raw/master/my-ldapsearch.pp
wget https://github.com/patrikwm/Centos-SSH-Active-Directory/raw/master/my-sssd.pp
semodule -i my-sssd.pp
semodule -i my-ldapsearch.pp

Now it should work to login with ssh key LDAP user and setenforce 1 on the server.

Troubleshooting.

check logfiles!

tail -f /var/log/audit/audit.log
tail -f /var/log/sssd/*