aiondb-security

Authentication, authorization, and credential handling primitives. Defines the Authenticator and Authorizer traits, the AuthenticatedIdentity returned to the engine, SCRAM-SHA-256 verifier crypto, secret wrappers that zeroize on drop, and rate limiters used to back off failed authentication attempts.

cargo

[dependencies]
aiondb-security = { path = "../aiondb-security" }

modules

modulepurpose
authnAuthenticator trait, Credential, TransportInfo, TransportKind, AuthenticatedIdentity.
authzAuthorizer trait, Action, AccessTarget, AccessRequest.
identityIdentityExt extension trait (has_role).
policyDefault trait implementations: AllowAllAuthenticator, AllowAllAuthorizer, DenyAllAuthorizer.
rate_limitAuthRateLimiter trait and three backends: NoopAuthRateLimiter, InMemoryAuthRateLimiter, FileBackedAuthRateLimiter.
scramScramVerifier (RFC 5802 / 7677 server-side state).
secretsSecretString, SecretBytes wrappers with redacted Debug and constant-time equality.

key types

example

use aiondb_security::{
    AccessRequest, Action, AllowAllAuthenticator, Authenticator, Credential,
    DenyAllAuthorizer, Authorizer, IdentityExt, SecretString, TransportInfo,
};

let auth = AllowAllAuthenticator;
let cred = Credential::CleartextPassword {
    user: "alice".to_string(),
    password: SecretString::new("hunter2".to_string()),
};
let transport = TransportInfo::in_process();

let identity = auth
    .authenticate(&cred, "postgres", &transport)
    .expect("anonymous authenticator always succeeds");
assert_eq!(identity.user, "alice");
assert!(identity.has_role("alice"));

let authz = DenyAllAuthorizer;
let request = AccessRequest {
    action: Action::Select,
    target: None,
};
assert!(authz.authorize(&identity, &request).is_err());

scram

use aiondb_security::ScramVerifier;

let verifier = ScramVerifier::from_password("hunter2").expect("derive verifier");
assert!(!verifier.salt.is_empty());
assert_eq!(verifier.stored_key.len(), 32);
assert_eq!(verifier.server_key.len(), 32);

secrets

SecretString and SecretBytes never leak through Debug and clear their backing buffer on drop:

use aiondb_security::SecretString;

let s = SecretString::new("hunter2".to_string());
assert_eq!(format!("{s:?}"), "SecretString(**redacted**)");
assert_eq!(s, SecretString::new("hunter2".to_string()));