heimdal
heimdal copied to clipboard
Rethinking kinit behavior -- specifying user intent
We're considering changes to Heimdal's kinit
's default behaviors. We want to make it more useful, less surprising, and more user-friendly.
Final design
-
kinit
- add behavior selection options
-
--default-for-principal
-
--search
-
--unique
-
- the default behavior when none of those new options is given is to honor the
-c CACHE
/--cache=CACHE
/$KRB5CCNAME
/configured default cache - if any of those new options is used, then the given cache is only used to identify a collection
- all cache types are collections
- if
--search
is given, then search for a cache in the collection identified by the-c CACHE
/..., and use it if found, else use the--default-for-principal
behavior unless--unique
is given - if
--default-for-principal
is given, the use a cache in the collection identified by the-c CACHE
/... with a subsidiary name derived from the name of the principal we're getting credentials for - if
--unique
is given, use a new, unique cache in the collection identified by the-c CACHE
/... - when using the cache identified by the
-c CACHE
/..., refuse to overwrite it if it has credentials for a different principal - when giving a command to
kinit
, as always, use a new unique cache, but error out if--default-for-principal
or--search
are given
- add behavior selection options
-
klist
- add
--default-for=principal
and--search-for=principal
options toklist
- add
-
kswitch
- try
krb5_cc_default_for()
first when-p principal
/--principal=principal
is given, then fallback onkrb5_cc_match()
- try
Motivation
There are cases when MIT's and Heimdal's kinit
(prior to this PR) will honor the -c CACHE
/--cache=CACHE
/$KRB5CCNAME
, and cases where they'll search the user's credentials cache collection, and cases where they will create a "new unique" ccache different from what the user might have intended, and other cases where MIT will refuse to write out a ccache while Heimdal will not refuse.
- That is a hot mess and terribly confusing UI/UX. We'd like to make this better.
Another motivation is that "new unique" ccache names become garbage that piles up and has to be collected. This is not a friendly UX. As well, "new unique" ccache names are meaningless but leak into UIs anyways -- another poor UX.
Relatedly, setting KRB5CCNAME
or using -c
-like options when doing manual identity selection... requires running klist -l
to pick a cache name. But if we name the caches after the principals for which they store credentials, then one can just type, for example, KRB5CCNAME=KCM:${UID}:${USER}@MY.REALM.EXAMPLE ssh somewhere
.
So we want to a) make sure that user intent is clear, b) make it easy to name ccaches after principals so it's easy to find the right ccache for each context, and c) provide some safety belt and suspenders.
Background:
- Cache collections exist for several reasons:
- To support having credentials for multiple different principals. (In principle a single credentials cache can store tickets for multiple different client principals, but in practice this is not supported by any implementations.)
- To use an atomic "default cache switch" operation on collections to work around lack of atomic ccache initialization.
- In both, MIT and Heimdal,
krb5_cc_default()
andkrb5_cc_default_name()
use the value ofKRB5CCNAME
from the environ if it's set, else a configureddefault_ccache_name
[libdefaults]
param, else the compiled-in default ccache for the configured or compiled-in default ccache type. - In Heimdal we have
krb5_cc_move()
to rename ccaches, and most ccache types in Heimdal support atomickrb5_cc_move()
s -- we leave it to the ccache type to get this right, and if not, too bad. - MIT does not appear to have atomic ccache renaming operations. Neither does the
sssd
kcm
. Neither doesCCAPI
. - In Heimdal, every ccache type is a collection type (yes, even
FILE
!). Not so in MIT.- Heimdal has a
--default-for-principal
kinit option in master, and corresponding APIs, for creating a ccache in a given collection but with a cache name derived from the principal name whose credentials will be stored in it -- this makes use of collections user-friendly because the cache names reflect the principal whose credentials they contain.
- Heimdal has a
Proposed UX -- Explicit User Intent
-
The user must specify intent. There are only so many behaviors to choose from, so let's have options for all of them, a reasonable default, and let's not deviate from user intent.
-
By default
kinit
should operate on the named ccache. Any alternative requires the use of specific options. No more "some cases create a new unique" cache silently. -
Using
TYPE:
(e.g.,KCM:
) or equivalent collection names (e.g.,KCM:12345
when the process' real UID is12345
) refers to the whole collection and denotes user intent to use specific caches in that collection whose names are derived from those of the client principals that they store credentials for.When using such a "whole collection" ccache name, using
kinit
to initialize a ccache with some principal's credentials should create a cache with a name based on that principal name (as if--default-for-principal
had been given), and should make that the current ccache for the whole collection unless--no-change-default
is given. -
If the ccache exists and has creds for a different principal than we would be storing creds for, then fail unless other options (
--overwrite
) alter this understanding.
Proposed new library APIs/behaviors
-
Make
TYPE:
a ccache name that refers to a) the whole collection for the user for that cache type, and b) the current default ccache for that collection (e.g.,KCM:
would be "the whole collection of caches and the current default ccache in that collection as well, for the real user ID of the current process").This is already so for some, but not all ccache types in Heimdal.
This will require a new
krb5_cc_ops
method, and a correspondingkrb5_cc
API. -
Make every ccache type have and report a specific residual ccache name that also refers to the whole collection and its default (e.g., if the current real UID is
12345
thenKCM:12345
would be equivalent toKCM:
, while forFILE
that would be/tmp/krb5cc_%{UID}
). The ccache types should report this value with tokens unexpanded.
Proposed new kinit
behavior
See above.
But what about atomicity?
We get atomicity for free in Heimdal for ccache types that support atomic ccache rename. However, not all do.
For ccache types that don't support atomic ccache rename, the above proposal will simply mean no atomicity. We could have kinit
act differently for such ccache types, however.
Existing uses of "new unique then switch" still have atomicity issues even though the "switch" operation is atomic. The reason is that when users use KRB5CCNAME
to pick a specific ccache from their collection to use in some application, when credentials in that cache are near expiration and the user goes to kinit -R
them, if the operation to install the new credentials is non-atomic, then there is a race condition anyways.
See also Greg's comment about atomicity.
The asprintf()
issue is probably very common in our tree.
MIT does not appear to have atomic ccache renaming operations. Neither does the sssd kcm. Neither does CCAPI.
We do as of commit 371f09d4bf4ca0c7ba15c5ef909bc35307ed9cc3, for FILE, DIR, MEMORY, and KCM if the daemon supports it (but none of them do yet, as far as I know).