bucketwarden-auth 0.1.0

BucketWarden local identity, access key, and session credential store.
Documentation
use super::*;

impl AuthStore {
    pub fn resolve_credential(
        &self,
        access_key_id: &str,
        now_epoch_seconds: u64,
    ) -> Result<ResolvedCredential, AuthError> {
        let record = self
            .credentials
            .get(access_key_id)
            .ok_or_else(|| AuthError::UnknownAccessKey(access_key_id.to_string()))?;
        let principal = self.require_enabled_principal(record.principal_id())?;
        match record {
            CredentialRecord::AccessKey(key) => {
                if !key.enabled {
                    return Err(AuthError::DisabledAccessKey(access_key_id.to_string()));
                }
                if key.revoked_at_epoch_seconds.is_some() {
                    return Err(AuthError::RevokedCredential(access_key_id.to_string()));
                }
                if key
                    .expires_at_epoch_seconds
                    .is_some_and(|expires_at| now_epoch_seconds > expires_at)
                {
                    return Err(AuthError::ExpiredCredential(access_key_id.to_string()));
                }
            }
            CredentialRecord::Session(session) => {
                if session.revoked_at_epoch_seconds.is_some() {
                    return Err(AuthError::RevokedCredential(access_key_id.to_string()));
                }
                if now_epoch_seconds > session.expires_at_epoch_seconds {
                    return Err(AuthError::ExpiredCredential(access_key_id.to_string()));
                }
            }
        }
        Ok(ResolvedCredential {
            principal_id: principal.id.clone(),
            tenant_id: principal.tenant_id.clone(),
            access_key_id: record.access_key_id().to_string(),
            credentials: record.credentials(),
            scope: match record {
                CredentialRecord::AccessKey(_) => None,
                CredentialRecord::Session(session) => session.scope.clone(),
            },
        })
    }

    pub fn authenticate_mtls_client(
        &mut self,
        certificate_fingerprint: &str,
        now_epoch_seconds: u64,
    ) -> Result<ResolvedMtlsIdentity, AuthError> {
        let certificate = self
            .mtls_certificates
            .get(certificate_fingerprint)
            .ok_or_else(|| {
                AuthError::UnknownClientCertificate(certificate_fingerprint.to_string())
            })?;
        if !certificate.enabled {
            return Err(AuthError::DisabledClientCertificate(
                certificate_fingerprint.to_string(),
            ));
        }
        if certificate.revoked_at_epoch_seconds.is_some() {
            return Err(AuthError::RevokedCredential(
                certificate_fingerprint.to_string(),
            ));
        }
        if certificate
            .expires_at_epoch_seconds
            .is_some_and(|expires_at| now_epoch_seconds > expires_at)
        {
            return Err(AuthError::ExpiredCredential(
                certificate_fingerprint.to_string(),
            ));
        }
        let principal = self.require_enabled_principal(&certificate.principal_id)?;
        let identity = ResolvedMtlsIdentity {
            principal_id: principal.id.clone(),
            tenant_id: principal.tenant_id.clone(),
            certificate_fingerprint: certificate.certificate_fingerprint.clone(),
        };
        if let Some(certificate) = self.mtls_certificates.get_mut(certificate_fingerprint) {
            certificate.last_used_epoch_seconds = Some(now_epoch_seconds);
        }
        Ok(identity)
    }
}