Craton HSM
Authentication and RBAC
Authentication and RBAC
The craton-hsm-auth crate provides enterprise identity, role-based
access control, multi-factor re-auth for destructive operations, dual-
control approvals, and per-tenant key isolation. It sits in front of any
CryptoBackend and enforces who can do what with which key.
- Crate:
craton-hsm-auth - License: BSL 1.1
- MSRV: Rust 1.75
- Status: production-ready
- Safety: no
unsafe;clippy::unwrap_used,expect_used,panic,unreachable, andindexing_slicingdenied in non-test builds.
Public Modules
auth— providers, credential types,AuthManager.rbac— roles, permissions, ACL evaluation, dual-control approval.tenant— tenant manager, per-tenant quotas, atomictry_reserve_keyquota enforcement.error— theAuthErrortype.
Feature Flags
| Flag | Adds | Extra deps |
|---|---|---|
ldap-auth | LDAP / Active Directory provider | ldap3, tokio |
oidc-auth | OpenID Connect provider | jsonwebtoken, reqwest |
cert-auth | X.509 client certificate provider | x509-parser |
All features are off by default. Enable them in your Cargo.toml:
[dependencies]
craton-hsm-auth = { path = "../craton-hsm-auth", features = ["ldap-auth", "oidc-auth"] }
Authentication Providers
Local PIN (dev / test only)
Wraps PKCS#11 PIN-based login in a pluggable provider. PINs are salted and hashed; comparison is constant-time. Not supported in production — use LDAP, OIDC, or certificate auth instead.
use craton_hsm_auth::auth::{AuthConfig, manager::AuthManager, provider::AuthCredentials};
use zeroize::Zeroizing;
let config = AuthConfig::default();
let mgr = AuthManager::new(&config)?;
let creds = AuthCredentials::Pin {
user_type: 1,
pin: Zeroizing::new(b"my-pin".to_vec()),
};
let identity = mgr.authenticate(&creds)?;
# Ok::<(), craton_hsm_auth::error::AuthError>(())
LDAP / Active Directory (ldap-auth)
Bind-based authentication with:
- LDAPv3 over TLS (LDAPS or StartTLS — TLS is mandatory).
- Injection-safe DN and filter escaping.
- A connection pool.
- Per-source rate limit with lockout.
Per-process state only: the rate limiter does not coordinate across nodes in a multi-node deployment.
OpenID Connect (oidc-auth)
OIDC Core 1.0 token validation:
- JWKS cache with stale-serve fallback if the issuer is briefly unavailable.
- Accepted algorithms: RS256, RS384, RS512, ES256, ES384.
alg: noneis rejected.
X.509 Certificate (cert-auth)
Client certificate authentication:
- Full chain validation against configured trust anchors.
- PKCS#7 / PEM / DER input formats.
- Static (pre-loaded) DER-encoded CRLs. OCSP and HTTP CRL Distribution Point fetching are not implemented in 0.1.x. CRL parse failure fails closed (returns an error rather than warn-and-skip).
Multi-Factor (TOTP)
RFC 6238 TOTP challenge/response before destructive operations:
- SHA-1 (legacy) and SHA-256.
- Constant-time comparison via
subtle::ConstantTimeEq. OsRng(notthread_rng) for challenge IDs, approval IDs, and PIN salts.
RBAC and Dual-Control
Per-operation ACLs gate every dispatched action. For high-impact operations (key destruction, tenant deletion, policy change), a dual-control approval workflow requires two distinct identities:
- Requester and approver must both have non-empty user IDs. Empty
strings and
Noneare rejected. - Self-approval is rejected.
- Approvals are consumed through TOCTOU-safe
consume_approved; each approval is single-use.
Multi-Tenancy
craton-hsm-auth implements per-tenant isolation:
- Each tenant has a unique ID, display name, and status
(
Active/Suspended). - Per-tenant key quotas enforce resource limits via atomic
try_reserve_key. Concurrent reservation attempts that would cross the quota boundary are rejected without double-counting. - Tenant context is propagated through sessions. Key operations are scoped to the authenticated tenant.
- Suspended tenants cannot perform cryptographic operations.
- RBAC policies are evaluated per-tenant: a role grant in tenant A does not confer access in tenant B.
Configuration Examples
LDAPS authentication
[auth.ldap]
enabled = true
url = "ldaps://ldap.example.internal:636"
bind_dn_template = "uid={user},ou=people,dc=example,dc=internal"
ca_bundle_path = "/etc/craton-hsm/ldap-ca.pem"
pool_size = 8
[auth.ldap.rate_limit]
max_attempts = 5
window_secs = 60
lockout_secs = 900
OIDC authentication
[auth.oidc]
enabled = true
issuer = "https://idp.example.com"
audiences = ["craton-hsm"]
jwks_uri = "https://idp.example.com/.well-known/jwks.json"
algorithms = ["RS256", "ES256"]
leeway_secs = 30
X.509 client-cert authentication
[auth.cert]
enabled = true
trust_anchors = ["/etc/craton-hsm/ca/root.pem", "/etc/craton-hsm/ca/intermediate.pem"]
static_crl_paths = ["/etc/craton-hsm/crl/example.crl"]
subject_regex = "^CN=([^,]+),OU=hsm-operators,DC=example,DC=com$"
Per-tenant quota
[[tenants]]
id = "acme"
display_name = "ACME Corp"
status = "active"
max_keys = 10000
[[tenants]]
id = "widgets"
display_name = "Widgets Ltd"
status = "active"
max_keys = 500
Error Reporting
All provider and RBAC failures surface as
craton_hsm_auth::error::AuthError. See the module docs for the full
variant list.
Limitations
- Local PIN store is for testing and development only.
- Certificate revocation supports only static, pre-loaded DER CRLs. HTTP CRL Distribution Points and OCSP are not implemented in the 0.1.x series.
- Rate limiter state is per-process. In multi-node deployments the limiter does not coordinate between nodes; attackers distributing attempts across nodes can stretch the per-node budget.
Related Documents
- Cluster and replication — tenants and roles are replicated via the Raft state machine.
- KMIP server — delegates authentication to
craton-hsm-authafter mTLS termination.