krb5: Pin kpasswd server to a primary one

There are time gaps in which kinit requests may fail due to
offlined SSSD's locator and replication delays.

Since `IPA` provider or SSSD offline the locator plugin for libkrb5
(man 8 sssd_krb5_locator_plugin) can do nothing about this and kinit
fallbacks to the standard libkrb5 algorithm described in `man 5 krb5.conf`.
`krb5.conf` on IPA server doesn't include `kpasswd_server` and kinit
fallbacks to DNS way. DNS (URI or SRV) RRs don't preserve any order
and kinit may contact either master or replica kpasswd servers.
This may result in a password was changed on a replica but was not
replicated to master:
master(kinit)->master(initial)->replica(kpasswd)->master(can't
obtain initial creds with new password)

So, `kpasswd_server` serves as fallback for the offlined locator.

Note: primary_kdc(the former master_kdc) doesn't help here because
it is only used if the initial credentials obtaining fails (see
`krb5_get_init_creds_password` in libkrb5) and not a password change.

Fixes: https://pagure.io/freeipa/issue/8353
Signed-off-by: Stanislav Levin <slev@altlinux.org>
Reviewed-By: Francois Cami <fcami@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
Stanislav Levin authored and Florence Blanc-Renaud committed 2021-09-15 10:16:54 +02:00
1 parent a941e8f602
commit 93126e01a5
2 files changed
+25

No files matched your search

+1
View File
@@ -19,6 +19,7 @@ $OTHER_LIBDEFAULTS
$REALM = {
kdc = $FQDN:88
master_kdc = $FQDN:88
kpasswd_server = $FQDN:464
admin_server = $FQDN:749
default_domain = $DOMAIN
pkinit_anchors = FILE:$KDC_CA_BUNDLE_PEM
+24
View File
@@ -1262,6 +1262,29 @@ def enable_server_snippet():
tasks.restore_context(paths.KRB5_FREEIPA_SERVER)
def setup_kpasswd_server(krb):
logger.info("[Setup kpasswd_server]")
aug = Augeas(
flags=Augeas.NO_LOAD | Augeas.NO_MODL_AUTOLOAD,
loadpath=paths.USR_SHARE_IPA_DIR,
)
try:
aug.transform("IPAKrb5", paths.KRB5_CONF)
aug.load()
kpass_srv_path = "/files{}/realms/{}/kpasswd_server"
kpass_srv_path = kpass_srv_path.format(paths.KRB5_CONF, krb.realm)
if aug.match(kpass_srv_path):
return
aug.set(kpass_srv_path, f"{krb.fqdn}:464")
aug.save()
finally:
aug.close()
def ntpd_cleanup(fqdn, fstore):
sstore = sysrestore.StateFile(paths.SYSRESTORE)
timeconf.restore_forced_timeservices(sstore, 'ntpd')
@@ -1874,6 +1897,7 @@ def upgrade_configuration():
setup_spake(krb)
setup_pkinit(krb)
enable_server_snippet()
setup_kpasswd_server(krb)
# Must be executed after certificate_renewal_update
# (see function docstring for details)