Introduction

I have been working on a feature that will allow centrally managed users to log in locally to a computer with passkeys. For the purpose of this work, passkey is a FIDO2 compatible device supported by the libfido2 library. As the feature is still under development I’ve prepared an environment to test it.

Requirements

First of all a FIDO2 key is needed. I’m using a Yubikey 5 series, but you can use any FIDO2 compliant key. Besides, the test environment uses docker/podman to set up the containers and ansible to provision them. On top of that, yubikey-manager is needed to manage the FIDO2 device options. Moreover, I’ve created a COPR repository to deliver the patched versions of SSSD and IPA that will enable this feature. Finally, I’ve prepared a new sssd-ci-container branch to automate the provision of everything. The following sections will explain how to set up the environment and how to test it.

Passwords

All passwords are set to Secret123.

How to set up the environment

  • Clone sssd-ci-containers locally and checkout the passkey branch:
$ git clone https://github.com/ikerexxe/sssd-ci-containers/
$ cd sssd-ci-containers
$ git checkout --track origin/passkey
  • Host package installation and configuration. The following commands should be executed only once:
$ sudo dnf install -y podman podman-docker docker-compose yubikey-manager fido2-tools
$ sudo systemctl enable --now podman.socket
$ sudo setsebool -P container_manage_cgroup true
$ cp env.example .env
  • Check if the ansible community.general module is installed:
$ ansible-galaxy collection list | grep community.general
community.general             4.8.2
  • If it isn’t installed then do it:
$ sudo ansible-galaxy collection install community.general
  • If you haven’t done so, connect the key to the computer.

  • Set up the containers (make up) and update the packages with the passkey patches (make passkey). For the latter command to run correctly you will need to input the password. It will take some time to execute as it needs to update the dnf cache and then update the sssd packages.

$ sudo make up
$ sudo make passkey

This way the environment is ready for testing. From now on you can use the following command to connect to the client container:

$ sudo podman exec -it client /bin/bash

Additional configuration

It is advisable to add a PIN to the key to reinforce the security. You only need to do this once.

$ ykman fido access change-pin

IPA

Add a user

  • First of all obtain a kerberos ticket:
$ kinit admin@IPA.TEST
  • Add the user and enable passkey authentication:
$ ipa user-add joe --first=joe --last=doe --user-auth-type=passkey

Register a key

Client

  • Register the key with sssctl:
$ sssctl passkey-register --username=joe --domain=ipa.test

Note: If you’d like the full logs to be printed in the command line then append --debug-level=9 --logger=stderr

  • Next, the PIN will be requested and once it is introduced the key will blink indicating that you need to touch it.

  • Finally, this will output a string with the following format:

PASSKEY:credentialId,publicKey

Example:

passkey:aEgemlnC6a/WOoEZ8qU1YMwsTW9+uwmMsJnrgOXwTID0qIBHirzHp6d+e1d3WBhcSf7t9Ji8fl3AdSPtlbdN5Q==,MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENwDQHwyZmnYaUEp0UNqqnw0tGOGnqOMBGdds6O3+JKbmmJGTn0vo7sKNNcDWDsFhJFU/RLWXmHXglxSo+yw9iQ==

Server

  • Add the attribute to the user:
$ ipa user-add-passkey joe passkey:aEgemlnC6a/WOoEZ8qU1YMwsTW9+uwmMsJnrgOXwTID0qIBHirzHp6d+e1d3WBhcSf7t9Ji8fl3AdSPtlbdN5Q==,MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENwDQHwyZmnYaUEp0UNqqnw0tGOGnqOMBGdds6O3+JKbmmJGTn0vo7sKNNcDWDsFhJFU/RLWXmHXglxSo+yw9iQ==
------------------------------------
Added passkey mappings to user "joe"
------------------------------------
  User login: joe
  Passkey mapping: passkey:aEgemlnC6a/WOoEZ8qU1YMwsTW9+uwmMsJnrgOXwTID0qIBHirzHp6d+e1d3WBhcSf7t9Ji8fl3AdSPtlbdN5Q==,MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENwDQHwyZmnYaUEp0UNqqnw0tGOGnqOMBGdds6O3+JKbmmJGTn0vo7sKNNcDWDsFhJFU/RLWXmHXglxSo+yw9iQ==
  • Checking that it has been added correctly:
$ ipa user-show joe
  User login: joe
  First name: joe
  Last name: doe
  Home directory: /home/joe
  Login shell: /bin/sh
  Principal name: joe@IPA.TEST
  Principal alias: joe@IPA.TEST
  Email address: joe@ipa.test
  UID: 805400005
  GID: 805400005
  Passkey mapping: passkey:aEgemlnC6a/WOoEZ8qU1YMwsTW9+uwmMsJnrgOXwTID0qIBHirzHp6d+e1d3WBhcSf7t9Ji8fl3AdSPtlbdN5Q==,MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENwDQHwyZmnYaUEp0UNqqnw0tGOGnqOMBGdds6O3+JKbmmJGTn0vo7sKNNcDWDsFhJFU/RLWXmHXglxSo+yw9iQ==
  Account disabled: False
  Password: False
  Member of groups: ipausers
  Kerberos keys available: False

User authentication

  • Change to ci user, as root will always authenticate as another user:
$ su - ci
  • Now you can proceed to authenticate as the newly created user using the passkey. Remember to enter the PIN when requested and to touch the device when the LED starts blinking:
$ su - joe@ipa.test
Insert your passkey device, then press ENTER.
Enter PIN:
Creating home directory for joe@ipa.test.
  • Check the user id:
$ id
uid=805400005(joe@ipa.test) gid=805400005(joe@ipa.test) groups=805400005(joe@ipa.test)

Congratulations! You’ve succesfully authenticate as joe using the passkey. Besides, while performing the authentication a Kerberos ticket has also been granted.

LDAP

This part is more complicated than IPA as a custom schema needs to be created. This schema will be used to hold the passkey data.

Register a key

Client

  • As with the IPA server we also need to register the key with sssctl:
$ sssctl passkey-register --username=alice --domain=ldap.test

Note: If you’d like the full logs to be printed in the command line then append --debug-level=9 --logger=stderr

  • Next, the PIN will be requested and once it is introduced the key will blink indicating that you need to touch it.

  • Finally, this will output the passkey string:

passkey:oducA9WSTrzBHX2gUKylRNl2PD2XCb4a7V0XJOtahqIX7wGcAugflvrVjbWG2JPTsLlVf+j/dmia7SNIVhK5AA==,MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGEa7EktmUw4AOR6Y6r1W2zxXptQh3YaDNdvQEifZ3NpgRosVv+GS85uR3h6Ed1E7FtgfugwsZYeR8+9+GM6h8g==

Server

  • You will need to connect to the LDAP container for the next steps:
$ sudo podman exec -it ldap /bin/bash
  • Edit /etc/dirsrv/slapd-localhost/schema/60base.ldif to add the custom schema:
dn: cn=schema
attributeTypes: ( 2.16.840.1.113730.3.8.24.27 NAME 'passkey' DESC 'Passkey mapping' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
objectclasses: ( 2.16.840.1.113730.3.8.24.9 NAME 'passkeyUser' DESC 'IPA passkey user' AUXILIARY MAY passkey)
  • Dynamically reload the schemas:
$ dsconf -D "cn=Directory Manager" localhost schema reload
  • Create the user and its attributes in user.ldif:
dn: uid=alice,dc=ldap,dc=test
mail: alice@ldap.test
uid: alice
givenName: Alice
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetorgperson
objectClass: posixAccount
objectClass: inetuser
sn: Moreau
cn: Alice Moreau
uidNumber: 2000
gidNumber: 2000
homeDirectory: /home/alice
loginShell: /bin/bash
gecos: alice
passkey: passkey:oducA9WSTrzBHX2gUKylRNl2PD2XCb4a7V0XJOtahqIX7wGcAugflvrVjbWG2JPTsLlVf+j/dmia7SNIVhK5AA==,MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGEa7EktmUw4AOR6Y6r1W2zxXptQh3YaDNdvQEifZ3NpgRosVv+GS85uR3h6Ed1E7FtgfugwsZYeR8+9+GM6h8g==
objectclass: passkeyUser
  • Add the user to the LDAP database:
$ ldapadd -D "cn=Directory Manager" -w Secret123 -H ldap://localhost -x -f user.ldif

User authentication

  • From the client machine change to ci user, as root will always authenticate as another user:
$ su - ci
  • Now you can proceed to authenticate as the newly created user using the passkey. Remember to enter the PIN when requested and to touch the device when the LED starts blinking:
$ su - alice@ldap.test
Insert your passkey device, then press ENTER.
Enter PIN:
Creating home directory for alice@ldap.test.
  • Check the user id:
$ id
uid=2000(alice@ldap.test) gid=2000 groups=2000

Congratulations! You’ve succesfully authenticate as alice using the passkey.

AD

You could also use Active Directory to manage the user. The specific instructions are out of the scope of this post, but you should follow the instructions to set up the Windows VM, create the user and add the passkey to the altSecurityIdentities attribute.

Cleaning up the environment

First you need to exit the container and then execute the clean up command (make down).

$ exit
$ sudo make down

Additional information

More information regarding the sssd-ci-containers can be found here.

There are several options to tune the SSSD behaviour in the sssd.conf file. I’d recommend you to read the man page to learn how to do it.

Edit: Install ansible module for root. Thanks to Thorsten Scherf for catching it.

Edit2: Include Kerberos ticket granting for IPA users.

Edit3: Updated sssctl passkey registration command.