mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 12:37:00 +01:00
docs: Add application passwords design document (#2427)
Related to #41. Signed-off-by: Samuel Cabrero <scabrero@suse.de> Pair-Programmed-With: Firstyear <william@blackhats.net.au>
This commit is contained in:
parent
ed2bd846cc
commit
492c3da36c
212
book/src/developers/designs/application_passwords.md
Normal file
212
book/src/developers/designs/application_passwords.md
Normal file
|
@ -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 <http://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=<secret key>,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<Uuid, ApplicationPassword>;
|
||||||
|
^ ^
|
||||||
|
| |
|
||||||
|
| +-> Application password
|
||||||
|
+-> Application password UUID
|
||||||
|
|
||||||
|
type ApplicationUuid = Uuid;
|
||||||
|
|
||||||
|
struct ValueSetApplicationPassword {
|
||||||
|
map: Map<ApplicationUuid, ApplicationPasswords>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
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
|
Loading…
Reference in a new issue