use super::*;
impl AuthStore {
pub fn put_access_key(&mut self, key: AccessKey) -> Result<(), AuthError> {
self.require_enabled_principal(&key.principal_id)?;
self.credentials
.insert(key.access_key_id.clone(), CredentialRecord::AccessKey(key));
Ok(())
}
pub fn put_session(&mut self, session: SessionCredential) -> Result<(), AuthError> {
self.require_enabled_principal(&session.principal_id)?;
self.resolve_credential(&session.parent_access_key_id, 0)
.map_err(|_| AuthError::UnknownParentAccessKey(session.parent_access_key_id.clone()))?;
self.credentials.insert(
session.access_key_id.clone(),
CredentialRecord::Session(session),
);
Ok(())
}
pub fn put_mtls_client_certificate(
&mut self,
certificate: MtlsClientCertificate,
) -> Result<(), AuthError> {
self.require_enabled_principal(&certificate.principal_id)?;
self.mtls_certificates
.insert(certificate.certificate_fingerprint.clone(), certificate);
Ok(())
}
pub fn disable_mtls_client_certificate(
&mut self,
certificate_fingerprint: &str,
) -> Result<(), AuthError> {
let certificate = self
.mtls_certificates
.get_mut(certificate_fingerprint)
.ok_or_else(|| {
AuthError::UnknownClientCertificate(certificate_fingerprint.to_string())
})?;
certificate.disable();
Ok(())
}
pub fn disable_access_key(&mut self, access_key_id: &str) -> Result<(), AuthError> {
match self.credential_mut(access_key_id)? {
CredentialRecord::AccessKey(key) => {
key.disable();
Ok(())
}
CredentialRecord::Session(_) => Err(AuthError::NotAccessKey(access_key_id.to_string())),
}
}
pub fn revoke_credential(
&mut self,
access_key_id: &str,
now_epoch_seconds: u64,
) -> Result<(), AuthError> {
match self.credential_mut(access_key_id)? {
CredentialRecord::AccessKey(key) => key.revoke(now_epoch_seconds),
CredentialRecord::Session(session) => session.revoke(now_epoch_seconds),
}
Ok(())
}
pub fn revoke_mtls_client_certificate(
&mut self,
certificate_fingerprint: &str,
now_epoch_seconds: u64,
) -> Result<(), AuthError> {
let certificate = self
.mtls_certificates
.get_mut(certificate_fingerprint)
.ok_or_else(|| {
AuthError::UnknownClientCertificate(certificate_fingerprint.to_string())
})?;
certificate.revoke(now_epoch_seconds);
Ok(())
}
pub fn rotate_access_key(
&mut self,
old_access_key_id: &str,
new_access_key_id: impl Into<String>,
new_secret_access_key: impl Into<String>,
now_epoch_seconds: u64,
) -> Result<CredentialRotation, AuthError> {
let (principal_id, old_access_key_id) = match self.credential_mut(old_access_key_id)? {
CredentialRecord::AccessKey(key) => {
if key.revoked_at_epoch_seconds.is_some() {
return Err(AuthError::RevokedCredential(key.access_key_id.clone()));
}
key.revoke(now_epoch_seconds);
(key.principal_id.clone(), key.access_key_id.clone())
}
CredentialRecord::Session(_) => {
return Err(AuthError::NotAccessKey(old_access_key_id.to_string()));
}
};
let new_access_key_id = new_access_key_id.into();
let mut replacement = AccessKey::active(
principal_id.clone(),
new_access_key_id.clone(),
new_secret_access_key,
);
replacement.previous_access_key_id = Some(old_access_key_id.clone());
replacement.rotated_at_epoch_seconds = Some(now_epoch_seconds);
self.put_access_key(replacement)?;
Ok(CredentialRotation {
old_access_key_id,
new_access_key_id,
principal_id,
rotated_at_epoch_seconds: now_epoch_seconds,
})
}
pub fn report_leaked_access_key(
&mut self,
access_key_id: &str,
now_epoch_seconds: u64,
) -> Result<LeakedKeyResponse, AuthError> {
match self.credential_mut(access_key_id)? {
CredentialRecord::AccessKey(key) => {
key.leaked_at_epoch_seconds = Some(now_epoch_seconds);
key.revoke(now_epoch_seconds);
Ok(LeakedKeyResponse {
access_key_id: key.access_key_id.clone(),
principal_id: key.principal_id.clone(),
leaked_at_epoch_seconds: now_epoch_seconds,
revoked: true,
})
}
CredentialRecord::Session(_) => Err(AuthError::NotAccessKey(access_key_id.to_string())),
}
}
pub fn mark_used(
&mut self,
access_key_id: &str,
now_epoch_seconds: u64,
) -> Result<(), AuthError> {
match self.credential_mut(access_key_id)? {
CredentialRecord::AccessKey(key) => {
key.last_used_epoch_seconds = Some(now_epoch_seconds)
}
CredentialRecord::Session(session) => {
session.last_used_epoch_seconds = Some(now_epoch_seconds)
}
}
Ok(())
}
pub fn credential(&self, access_key_id: &str) -> Option<&CredentialRecord> {
self.credentials.get(access_key_id)
}
pub fn mtls_certificate(
&self,
certificate_fingerprint: &str,
) -> Option<&MtlsClientCertificate> {
self.mtls_certificates.get(certificate_fingerprint)
}
pub fn mtls_certificate_count(&self) -> usize {
self.mtls_certificates.len()
}
pub fn credential_count(&self) -> usize {
self.credentials.len()
}
pub fn credential_count_for_tenant(&self, tenant_id: &str) -> usize {
self.credentials
.values()
.filter(|credential| {
self.principal_tenant_id(credential.principal_id()) == Some(tenant_id)
})
.count()
}
}