nss/pam resolver should reauth faster (#3309)

This can have visible impacts on accounts that don't have a pam password
cached yet, but then appear to "stall" for a minute or two until it works
due to the fact that the provider was offline and waiting to reauth.

When we are still connected but our provider auth session has expired
we should reconnect faster. This reduces the timeout for reauthentication
for the provider so that it can return to the online state sooner. We
also loop when we detect the provider session is no longer authenticated
so that we can reauth immediately, rather than causing a noticable
interuption.
This commit is contained in:
Firstyear 2024-12-21 17:08:39 +10:00 committed by GitHub
parent bbefb0b1b1
commit c4441c1fca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -23,6 +23,7 @@ use kanidm_unix_common::unix_proto::PamAuthRequest;
const KANIDM_HMAC_KEY: &str = "kanidm-hmac-key";
const KANIDM_PWV1_KEY: &str = "kanidm-pw-v1";
// If the provider is offline, we need to backoff and wait a bit.
const OFFLINE_NEXT_CHECK: Duration = Duration::from_secs(60);
#[derive(Debug, Clone)]
@ -243,6 +244,7 @@ impl UserToken {
}
impl KanidmProviderInternal {
#[instrument(level = "debug", skip_all)]
async fn check_online(&mut self, tpm: &mut tpm::BoxedDynTpm, now: SystemTime) -> bool {
match self.state {
// Proceed
@ -255,24 +257,36 @@ impl KanidmProviderInternal {
}
}
#[instrument(level = "debug", skip_all)]
async fn attempt_online(&mut self, _tpm: &mut tpm::BoxedDynTpm, now: SystemTime) -> bool {
let mut max_attempts = 3;
while max_attempts > 0 {
max_attempts -= 1;
match self.client.auth_anonymous().await {
Ok(_uat) => {
debug!("provider is now online");
self.state = CacheState::Online;
true
return true;
}
Err(ClientError::Transport(err)) => {
warn!(?err, "transport failure");
self.state = CacheState::OfflineNextCheck(now + OFFLINE_NEXT_CHECK);
false
Err(ClientError::Http(StatusCode::UNAUTHORIZED, reason, opid)) => {
error!(?reason, ?opid, "Provider authentication returned unauthorized, {max_attempts} attempts remaining.");
// Provider needs to re-auth ASAP. We set this state value here
// so that if we exceed max attempts, the next caller knows to check
// online immediately.
self.state = CacheState::OfflineNextCheck(now);
// attempt again immediately!!!!
continue;
}
Err(err) => {
error!(?err, "Provider authentication failed");
error!(?err, "Provider online failed");
self.state = CacheState::OfflineNextCheck(now + OFFLINE_NEXT_CHECK);
false
return false;
}
}
}
warn!("Exceeded maximum number of attempts to bring provider online");
return false;
}
}
#[async_trait]
@ -351,7 +365,8 @@ impl IdProvider for KanidmProvider {
e, opid
),
};
inner.state = CacheState::OfflineNextCheck(now + OFFLINE_NEXT_CHECK);
// Provider needs to re-auth ASAP
inner.state = CacheState::OfflineNextCheck(now);
Ok(UserTokenState::UseCached)
}
// 404 / Removed.