From 492c3da36c5911f04740ec0e8bb941833f0ccb10 Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Thu, 1 Feb 2024 02:18:05 +0100 Subject: [PATCH] docs: Add application passwords design document (#2427) Related to #41. Signed-off-by: Samuel Cabrero Pair-Programmed-With: Firstyear --- .../designs/application_passwords.md | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 book/src/developers/designs/application_passwords.md diff --git a/book/src/developers/designs/application_passwords.md b/book/src/developers/designs/application_passwords.md new file mode 100644 index 000000000..261644fe6 --- /dev/null +++ b/book/src/developers/designs/application_passwords.md @@ -0,0 +1,212 @@ +# Rationale + +Kanidm exists to provide an authentication source for external applications. +These applications need to have standardised ways to integrate with Kanidm to +allow that application to interact and trust Kanidm's authentication results. + +For web based applications we offer Oauth2/OIDC. For Linux machines we offer a +Kanidm specific HTTPS channel for identifying users (UNIX integration). +Currently, for applications that don't support other protocols we offer an LDAPS +gateway that allows users to bind using their UNIX password. + +However this has the issue that due to how limited Linux authentication is, UNIX +passwords are always single factor. We also don't want the same UNIX credentials +that are used, e.g. for sudo on machines, to be leaked and used for applications +like email. + +To improve this we need a way to offer authentication services to applications +that are unable to support anything modern. + +Since LDAP is the "lingua franca" of authentication and almost universally +implemented as an authentication for all applications, we can use this to +provide *application specific* password based authentication and remove the +ability to bind with the UNIX password. + +# User experience + +The administrator configures two applications on their Kanidm instance. One is +"mail" for a generic SMTP+IMAP service. The other is HTTP basic auth to a legacy +web server. Then the administrator configures which users will be able to use +application passwords for each application. + +The mail services and web services are configured to point to Kanidm's LDAP +gateway with a customized search base DN. + +The users can login to the webui or command line and list what linked +applications exist on their accounts that require application passwords. + +The users can then request a new "application password" for the mail server for +their laptop and another one for their phone. They can copy-paste the generated +passwords to their mail clients which uses this password on their behalf. +Similarly, they can request a new application password to access the web server +basic auth. + +# Technical Details + +## Client + +Currently the LDAP basedn is configurable by an admin, or generated from domain. +For example, example.com becomes dc=example,dc=com. + +Each configured application will define a new naming context, like +app=mail,dc=example,dc=com or app=httpd,dc=example,dc=com + +(NOTE: Should this be app=? Some broken clients could try to validate this rdn +and error, so perhaps it should be a standard rdn value like cn?) + +The application then uses this app=mail,dc=example,dc=com as their search base +rather than dc=example,dc=com. Within this search base, we show the same content +from dc=example,dc=com. + +(NOTE: We could limit this to application only entries via group membership, but +the issue then is when you have a group for allowing access to the application, +but then still need other groups reflected into the subtree. In this case, if we +limited the view to application access only, we wouldn't be displaying the +non-access groups that the application may still rely on. Ultimately, in this +case the application needs to make it's own authorisation decisions to an +extend. Kanidm can limit which users are members of the access allowed group as +only they can bind still as an extra layer of defence) + +The application must bind with its api-token if it wishes to read extended user +information. With this, only basic info limited to anonymous rights are granted. + +(NOTE: We can't assume these DNs are private - I did consider making these +app=,dc=example,dc=com, but client applications may disclose this +basedn in ui elements). + +When a user authenticates the binddn of the account is set to +spn=user,app=name,dc=example,dc=com. This difference in base DN triggers Kanidm +to re-route the authentication to the application specific password, rather than +the UNIX one. + +## Kanidm + +### Application Entries + +A new class for applications will be added. Each application will have a single +associated group so only members of this group will be able to bind with the +application password for the associated application. + +Creating a new application will not create an associated group automatically. It +will be the administrator who will configure the association after creating the +application and optionally a new group. It will be possible to associate +`idm_all_persons` to an application. Removing an application will not delete the +associated group nor its members. + +When users are removed from a group associated to an application all of their +application passwords for the application will be disabled. + +Application schema class will supplement service account class to allow +generating tokens for them. These are optional since an anonymous bind to kanidm +and searching under the basedn or application base dn will continue to work. + +Application should have a URL reference to help admins identify where the +application may be located or accessed. + +(NOTE: Future, it could be good to allow customisable instructions for users on +where to go to use their app password?) + +### Accounts + +The user may wish to have multiple passwords per application. Each password must +have, at minimum, a label to identify it. For example: + +``` + MAIL + iphone: abcd... + laptop: bcde... + HTTP + workstation: cdef... +``` + +Person accounts will need a new `Attribute::ApplicationPassword` that stores a +`ValueSetApplicationPassword`. Each value in the set is a new type to manage these +secrets and their labeling and the references to the applications. + +``` +struct ApplicationPAssword { + label: String, + password: Password, +} + +type ApplicationPasswords = BTreeMap; + ^ ^ + | | + | +-> Application password + +-> Application password UUID + +type ApplicationUuid = Uuid; + +struct ValueSetApplicationPassword { + map: Map +} +``` + +Each value in the set is queried by its UUID. This defines the value as +`Value::ApplicationPassword(Uuid, ApplicationPassword)`. The +`ApplicationPassword` type implements `PartialEq` so two application passwords +are equal if their label is equal and they refer to the same application. + +The user must be able to delete credentials individually. The generated password +is only displayed once when the user creates it and it is not possible to +recover the clear-text form, only hashed form is stored. It is not allowed to +store duplicated application passwords (same app refer and label). + +We do not need temporary locks or holds - users can delete and recreate as +needed. + +### Reference integrity + +Since application passwords are related to applications, on delete of an +application all entries that have a bound application password should be removed +from user accounts. + +### Access controls + +The "Application administrators" group will manage the applications, and +applications will allow "managed by" so that they can have delegated +administration. + +The "Application user passwords administrators" group will be able to list the +users's application passwords and delete them but only the users will be able +to, additionally to listing and deleting, self-create their own application +passwords. + +### LDAP + +The bind DN regular expression needs to adjusted to detect and determine the +bind dn if it is related to an application or not. The application bind dn +regular expression will capture the user name, and the application name. + +If the session is related to an application we should only accept application +passwords in the bind. The user needs to be a member of the associated +application group. Binds to an application password must be limited by account +validity and expiration. + +We need to add a cache of available applications for lookup. + +(NOTE: Caching and reload needs more explanation) + +An application can bind with its api-token because the application may need to +search LDAP with elevated read permissions. + +### kanidm CLI + +The `kanidm` command line tool will be extended to satisfy the following +configuration requirements: + +* List applications + +* Create an application + +* Delete an application + +* Manage application - group association + +* Manage the application api-token + +* List application passwords + +* Create application password + +* Delete application password