OpenLDAP already knows an objectclass that adds an attribute for managing public keys to LDAP. Why shouldn’t this also work in Samba AD? All you need to do is adjust the attribute and enter it as a schema extension in AD. That’s what we’ll be looking at here.
But first, a reminder:
Schema extensions cannot be removed from the Active Directory schema. Therefore, plan carefully.
First, create an LDIF file to import the attribute. Only then can you customize the user objectclass. To create your own attributes and objectclasses, you need your own ODI, which you can register for free with IANA. This ensures that the attribute is unique. I am also using my prefix “stka” here again to keep the name of the attribute unique. Below you can see the LDIF file for the attribute:
dn: CN=stka-sshPublicKey,CN=Schema,CN=Configuration,DC=example,DC=net
changetype: add
objectClass: attributeSchema
attributeID: 1.3.1.5.1.4.1.123456.3.1
attributeSyntax: 2.5.5.12
oMSyntax: 64
lDAPDisplayName: stka-sshPublicKey
adminDisplayName: stka-sshPublicKeydn:
changetype: modify
add: schemaUpdateNow
schemaUpdateNow: 1
Replace “123456” with your own ODI. A Unicode string is used as the syntax here. It would also be possible to use an octet string, but the Unicode string allows you to manage the attribute later with the Windows tool ADSI Editor.
Import the new attribute with the command “ldbmodify -H /var/lib/samba/private/sam.ldb ssh-attribut.ldif”.
Only after you have imported the attribute can you extend the objectclass of the users with the following LDIF file:
dn: CN=User,CN=Schema,CN=Configuration,DC=example,DC=net
changetype: modify
add: mayContain
mayContain: stka-sshPublicKeydn:
changetype: modify
add: schemaUpdateNow
schemaUpdateNow: 1
Under no circumstances should you use “mustContain” here, because then you will no longer be able to create users with ADUC. This is because you would then have to change the mask for creating a new user.
To modify the object, use the command “ldbmodify -H /var/lib/samba/private/sam.ldb ch-user.ldif” again.
You are now able to extend your user objects with the ssh publickey. You can do this either graphically, with the ADSI editor, or via a corresponding LDIF file. Here is an example of an LDIF file:
dn: CN=username,CN=Users,DC=example,DC=net
changeType: modify
add: stka-sshPublicKey
stka-sshPublicKey: ssh-ed25519 thepublickeyoftheuser usernam@myclient01.example.net
But how does an ssh server get the public key?
This requires a little trick. Unlike OpenLDAP, Kerberos authentication is always required to access the Samba Active Directory. However, since the ssh server has to search for a user’s publickey, a few small intermediate steps are necessary.
First, create a user with a random password that never expires.
root@addc01:~# samba-tool user create –random-password sshsearch
User ‘sshsearch’ added successfully
root@addc01:~# samba-tool user setexpiry sshsearch –noexpiry
Expiry for user ‘sshsearch’ disabled
Next, create the keytab file for the user, which is then copied to all servers where sshd should search for the public keys in Active Directory.
root@addc01:~# samba-tool domain exportkeytab –principal=sshsearch@EXAMPLE.NET /root/sshsearch.keytab
Export one principal to /root/sshsearch.keytab
Once you have created the user, generated the keytab file, and copied it, you now need a script for the search. The script is shown in the following listing:
(To later run the script you need to install the heimdal-clients or mit5-user package on your server)
#!/bin/sh
kinit -k -t /etc/sshsearch.keytab sshsearchfor i in $(host -t srv _ldap._tcp.example.net | cut -d “ ” -f 8 | cut -d “.” -f 1)
do
ss -tlpn | grep 389
if true
then
DC=$i
break
fi
done
echo “domaincontroller = $DC”
ldbsearch -H ldap://“$DC” ‘(&(objectClass=user)(sAMAccountName=’“$1”‘))’ ‘stka-sshPublicKey’ –use-kerberos=required | sed -n ‘/^ /{H;d};/ stka-sshPublicKey:/x;$g;s/\n *//g;s/stka-sshPublicKey: //gp’
kdestroy
Save the script under /usr/local/bin/fetchSSHKeysFromAD.bash. Don’t forget to make the script executable.
The script first requests a Kerberos ticket with the previously created user and his keytab file. The loop searches for active domain controllers. If an active domain controller is found, the loop is exited. The script then searches for the user who wants to establish the ssh session and loads any publickey. Finally, the ticket is deleted again.
Once this is done, the sshd can now be configured. Make sure that the following lines are entered in the configuration file /etc/ssh/sshd_config.
PubkeyAuthentication yes
AuthorizedKeysCommand /usr/local/bin/fetchSSHKeysFromAD.bash
AuthorizedKeysCommandUser root
AllowGroups ssh-user
The script must be executed as root. This is ensured by the “AuthorizedKeysCommandUser” option.
Only members of the “ssh-user” group can log in to the server via ssh. You should definitely set this up this way, because otherwise any user who has a publickey in Active Directory could log in to the server.
There is still one small hurdle to overcome. To ensure that group membership can be determined, add the line “winbind expand groups = 1” to the global configuration of smb.conf. If you are working with nested groups, increase the value by your nesting depth.
Now restart sshd. Nothing stands in the way of logging in with central public keys. You will find all needed files here.