Storing SSH keys in Active Directory for easy deployment
Public key authentication has long been considered one of the most secure methods of remote SSH authentication. However, using the same key-pair for more than one machine can pose security risks, especially if that key is not secured by a passphrase but managing unique keys for each system a user has access to can be nightmare inducing. For this reason, we have leveraged Active Directory as our SSH public key store. For the purpose of this article, you should already have your Linux machines pulling user data from Active Directory, you should be running Windows Server 2012 R2 and you should have access to your domain Administrator
user.
Extending the Active Directory Schema
1. Our first tasks is to extend the schema. First off, launch a cmd
prompt then spawn an Administrator
cmd by running:
runas /user:DOMAIN\Administrator cmd
2. Now run regedit in that prompt
3. In the Registry Editor, we need to enable Schema updates.
I. Browse to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters
II. Add a new DWORD key named Schema Update Allowed
with value 1
4. Back in your Administrator command prompt, run regsvr32 schmmgmt.dll
to enable the Schema Editor Snap-in.
5. Run mmc
from the aforementioned Admin cmd
6. Hit Ctrl + M in the Management Console and add the Schema Editor
Now lets add the new Attribute:
I. Right Click on Attributes
and click ‘Create New Attribute’
II. For ‘Common Name’ and ‘LDAP Display Name’, enter sshPublicKeys
III. For ‘Unique X500 Object ID’ enter 1.3.6.1.4.1.24552.1.1.1.13
IV. For Syntax, select IA5-String
V. Check the ‘Multi-Valued’ box
VI. Minimum and Maximum can be left blank
We can now create a new class for the attribute:
I. Right click on Classes
and click ‘Create class’
II. For ‘Common Name’ and ‘LDAP Display Name’, enter ldapPublicKey
.
III. For ‘Unique X500 Object ID’ enter 1.3.6.1.4.1.24552.500.1.1.2.0
IV. For Parent Class
enter ‘top’ and for Class Type
select ‘Auxiliary’.
Click next.
I. Under optional add sshPublicKeys
We can now associate that class to user
objects.
I. Expand Classes and right click User then select properties.
II. Click on the Relationship
tab then click Add Class
under Auxiliary class
III. Add ldapPublicKey
and click ‘Apply’
Close all windows.
Now, open ADUC (dsa.mmc) and enabled Advanced Features
Once complete, browse to a user and select the ‘Attribute Editor’ tab. You will now be able to add public keys to this user.
From here, you should create a script to automatically pull public keys from AD for a given box and schedule it via Cron. Please remember to disable your domain Administrator
account when you’re done!
Good luck!
19
Your instructions say to use sshPublicKey, but your screenshot says to use sshPublicKeys – which one is it?
Geoff,
Good catch! The typo has been updated to `sshPublicKeys`.
Thanks!
-Ted
How would you expect users to maintain their keys? Is there any documentation that might help role out this functionality across a large number of seats without increasing support cases?
James,
That’s a very good question! We will be creating a new post later on this month discussing a solution for this. Ideally, we will allow users self write to their AD SSH keys and create a PowerShell script for Windows users to manage their keys and a Python script for Linux/OS X users. We’ll follow up when the post is online.
Thanks!
-Ted
Hi James – Take a look at our new article, which outlines a key management strategy – https://blog.laslabs.com/2017/04/managing-ssh-keys-stored-in-active-directory/
Hey, really nice posts.. just a remark and two questions.
R) For the sshPublicKeys attribute you *write* that Multi-Valued should be checked. But it’s not checked in the screenshot, so that might confuse some people (like me at first).
Q1) Why are you using sshPublicKeys instead of sshPublicKey? I have seen quite a few other tutorials that do similar things and it’s almost always sshPublicKey. Does it matter at all?
Q2) Hope I didn’t overlook anything, but I didn’t see how the SSH keys are then used.. e.g. would you have a sample for the cronjob or SSHd AuthorizedKeysCommand?
Thanks for the note regarding the screenshot – we’ll get it updated!
Regarding the pluralization of PublicKey – it’s a matter of preference. We have it pluralized because most of our users actually have multiple public keys stored due to our key policies, so it just kind of made sense. If you’re only using one key, singular may make more sense.
You actually didn’t overlook anything – we haven’t written about the deployment aspect yet. I did go ahead and publish our Ansible deployer on Github if you’d like to take a look though – https://github.com/LasLabs/ansible-ad-ssh-key-deployer
Thanks for the quick reply.
I decided to use a less “sophisticated” approach because in our environment we are not using separate keys per hosts.
Using ansible for regularly deploying the keys sounds like a good idea, but I don’t like the idea of having a service account (hardcoded in the script) for this. I adapted a GIST I found and use the machine keytab for the LDAP bind which appears to be working in my lab: https://gist.github.com/frennkie/390892c2c58efa2594046e888fe8054c
Do I need to restart any services (or servers) for the sshPublicKeys attribute to appear in the attribute editor?
The user class (via the schema editor) definitely shows that class “ldapPublicKey” is in the auxiliary classes, and class “ldapPublicKey” definitely has optional attribute “sshPublicKeys”, however when I go to edit a user the “sshPublicKeys” attribute is not listed. (Advanced view is on.)
Great post. I know this is a few years old but I just tried this with server 2019 and it did not work. Is there any update for newer versions of MS servers? Thanks.
Hi there,
I think you may like this tool => http://github.com/samber/sync-ssh-keys
It syncs your SSH keys to your servers based on Github/Gitlab groups memberships.
It looks like one other thing is missing. When modifying the “user” class Relationship, you must select the Attributes tab, click Add, find the sshPublicKeys attribute, and click OK. If you do not do this I have found the attribute will never show up in the user profile.
Would it be possible to use a wildcard as host in sshPublicKeys? E.g
`*:ssh-rsa…`
This way you don’t have to add each and every host, something like Frennkie said.
When following applying this guide to Server 2012 R2, for the step “We can now associate that class to user objects.” I had to apply it to person rather than user.