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

[[image:Runas_Cmd.png|medium]]

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`

[[image:Edit_Registry_Enable_Schema_Updates.png|medium]]

4. Back in your Administrator command prompt, run regsvr32 schmmgmt.dll to enable the Schema Editor Snap-in.

[[image:Enable_Schema_Snapin.png|medium]]

5. Run `mmc` from the aforementioned Admin `cmd`
6. Hit Ctrl + M in the Management Console and add the Schema Editor

[[image:Schema_Snapin.png|medium]]

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

[[image:https://blog.laslabs.com/user-files/uploads/2017/07/SSH_Key_Attribute.png|SSH Key Attribute|medium]]

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’.

[[image:Create_class.png|medium]]

Click next.

I. Under optional add `sshPublicKeys`

[[image:Create_class_II.png|medium]]

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’

[[image:Assoc_Class.png|medium]]

Close all windows.

Now, open ADUC (dsa.mmc) and enabled Advanced Features

[[image:Enable_Advanced_ADUC.png|medium]]

Once complete, browse to a user and select the ‘Attribute Editor’ tab. You will now be able to add public keys to this user.

[[image:sshPublicKeys.png|medium]]

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!


Posted

in

,

by

Tags:

Comments

14 responses to “Storing SSH keys in Active Directory for easy deployment”

  1. Geoff Avatar
    Geoff

    Your instructions say to use sshPublicKey, but your screenshot says to use sshPublicKeys – which one is it?

    1. Ted Salmon Avatar

      Geoff,

      Good catch! The typo has been updated to `sshPublicKeys`.

      Thanks!
      -Ted

  2. James Avatar
    James

    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?

    1. Ted Salmon Avatar

      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

    2. Dave Lasley Avatar

      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/

  3. frennkie Avatar
    frennkie

    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?

    1. Dave Lasley Avatar

      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

      1. frennkie Avatar
        frennkie

        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

  4. Adam Reece Avatar
    Adam Reece

    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.)

  5. Chris Avatar
    Chris

    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.

  6. Samuel Avatar
    Samuel

    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.

  7. Tim Melander Avatar
    Tim Melander

    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.

  8. Jan Reilink Avatar

    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.

  9. Rodney Kahane Avatar

    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.

Leave a Reply to Chris Cancel reply

Your email address will not be published. Required fields are marked *