use std::collections::HashMap;
use std::sync::Arc;
use super::policies::{self as iam_policies, Decision, EvalContext, Policy, ResourceRef};
pub const PLATFORM_OWNER_USERNAME: &str = "__platform_owner__";
pub const PLATFORM_OWNER_UNLOCK_POLICY_ID: &str = "__platform_owner_unlock__";
pub const BREAK_GLASS_ENV: &str = "REDDB_POLICY_BREAK_GLASS";
pub fn unlock_policy() -> Policy {
let json = format!(
r#"{{
"id": "{id}",
"version": 1,
"statements": [
{{
"sid": "unlock-policy-lifecycle",
"effect": "allow",
"actions": ["policy:*", "admin:bootstrap"],
"resources": ["*"]
}}
]
}}"#,
id = PLATFORM_OWNER_UNLOCK_POLICY_ID,
);
Policy::from_json_str(&json).expect("unlock policy must compile")
}
pub fn is_synthetic_principal(username: &str) -> bool {
username == PLATFORM_OWNER_USERNAME
}
pub fn is_unlock_policy(policy_id: &str) -> bool {
policy_id == PLATFORM_OWNER_UNLOCK_POLICY_ID
}
pub fn synthetic_eval_context() -> EvalContext {
EvalContext {
principal_tenant: None,
current_tenant: None,
peer_ip: None,
mfa_present: false,
now_ms: 0,
principal_is_admin_role: true,
principal_is_system_owned: true,
principal_is_platform_scoped: true,
}
}
#[derive(Debug, Clone)]
pub enum InvariantOutcome {
Ok,
Blocked {
policy_id: String,
sid: Option<String>,
reason: String,
},
}
pub fn check_self_lock_invariant(existing_policies: &[Arc<Policy>]) -> InvariantOutcome {
let unlock = unlock_policy();
let mut refs: Vec<&Policy> = Vec::with_capacity(existing_policies.len() + 1);
refs.push(&unlock);
for p in existing_policies {
if p.id == PLATFORM_OWNER_UNLOCK_POLICY_ID {
continue;
}
refs.push(p.as_ref());
}
let ctx = synthetic_eval_context();
let resource = ResourceRef::new("policy", "*");
let outcome = iam_policies::simulate(&refs, "policy:detach", &resource, &ctx);
match outcome.decision {
Decision::Allow { .. } | Decision::AdminBypass => InvariantOutcome::Ok,
Decision::Deny {
matched_policy_id,
matched_sid,
} => InvariantOutcome::Blocked {
policy_id: matched_policy_id,
sid: matched_sid,
reason: outcome.reason,
},
Decision::DefaultDeny => InvariantOutcome::Blocked {
policy_id: PLATFORM_OWNER_UNLOCK_POLICY_ID.to_string(),
sid: None,
reason: outcome.reason,
},
}
}
pub fn format_block_error(outcome: &InvariantOutcome) -> Option<String> {
match outcome {
InvariantOutcome::Ok => None,
InvariantOutcome::Blocked {
policy_id,
sid,
reason,
} => {
let sid_part = sid
.as_ref()
.map(|s| format!(" (sid={s})"))
.unwrap_or_default();
Some(format!(
"self-lock invariant: attach would block `__platform_owner__` \
from detaching policies — offending statement in policy `{policy_id}`{sid_part}: {reason}"
))
}
}
}
pub fn break_glass_audit_fields(boot_ts_ms: u128) -> HashMap<String, String> {
let mut map = HashMap::new();
map.insert("boot_ts_ms".into(), boot_ts_ms.to_string());
map.insert("env_var".into(), BREAK_GLASS_ENV.into());
map.insert("policy_id".into(), PLATFORM_OWNER_UNLOCK_POLICY_ID.into());
map.insert("principal".into(), PLATFORM_OWNER_USERNAME.into());
map
}
#[cfg(test)]
mod tests {
use super::*;
fn parse(json: &str) -> Arc<Policy> {
Arc::new(Policy::from_json_str(json).expect("policy parses"))
}
#[test]
fn unlock_policy_compiles() {
let p = unlock_policy();
assert_eq!(p.id, PLATFORM_OWNER_UNLOCK_POLICY_ID);
assert_eq!(p.statements.len(), 1);
}
#[test]
fn synthetic_principal_check() {
assert!(is_synthetic_principal(PLATFORM_OWNER_USERNAME));
assert!(!is_synthetic_principal("alice"));
assert!(is_unlock_policy(PLATFORM_OWNER_UNLOCK_POLICY_ID));
assert!(!is_unlock_policy("p-something-else"));
}
#[test]
fn invariant_ok_when_only_unlock() {
let outcome = check_self_lock_invariant(&[]);
assert!(matches!(outcome, InvariantOutcome::Ok));
}
#[test]
fn invariant_blocks_deny_detach_on_wildcard() {
let p = parse(
r#"{
"id": "p-self-lock",
"version": 1,
"statements": [{
"sid": "lock",
"effect": "deny",
"actions": ["policy:detach"],
"resources": ["*"]
}]
}"#,
);
let outcome = check_self_lock_invariant(&[p]);
match outcome {
InvariantOutcome::Blocked { policy_id, sid, .. } => {
assert_eq!(policy_id, "p-self-lock");
assert_eq!(sid.as_deref(), Some("lock"));
}
other => panic!("expected Blocked, got {other:?}"),
}
}
#[test]
fn invariant_blocks_deny_detach_on_policy_wildcard() {
let p = parse(
r#"{
"id": "p-policy-lock",
"version": 1,
"statements": [{
"effect": "deny",
"actions": ["policy:detach"],
"resources": ["policy:*"]
}]
}"#,
);
let outcome = check_self_lock_invariant(&[p]);
assert!(matches!(outcome, InvariantOutcome::Blocked { .. }));
}
#[test]
fn invariant_allows_narrower_deny() {
let p = parse(
r#"{
"id": "p-narrow",
"version": 1,
"statements": [{
"effect": "deny",
"actions": ["policy:detach"],
"resources": ["*"],
"condition": { "system_owned": false }
}]
}"#,
);
let outcome = check_self_lock_invariant(&[p]);
assert!(matches!(outcome, InvariantOutcome::Ok));
}
#[test]
fn format_block_error_for_blocked() {
let outcome = InvariantOutcome::Blocked {
policy_id: "p-x".into(),
sid: Some("s-y".into()),
reason: "deny at p-x.statement[0] (sid=s-y)".into(),
};
let msg = format_block_error(&outcome).expect("blocked carries a message");
assert!(msg.contains("p-x"));
assert!(msg.contains("s-y"));
assert!(msg.contains("__platform_owner__"));
}
#[test]
fn format_block_error_none_for_ok() {
assert!(format_block_error(&InvariantOutcome::Ok).is_none());
}
#[test]
fn break_glass_audit_fields_carries_marker() {
let fields = break_glass_audit_fields(123_456);
assert_eq!(fields.get("boot_ts_ms").unwrap(), "123456");
assert_eq!(fields.get("env_var").unwrap(), BREAK_GLASS_ENV);
assert_eq!(
fields.get("policy_id").unwrap(),
PLATFORM_OWNER_UNLOCK_POLICY_ID
);
assert_eq!(fields.get("principal").unwrap(), PLATFORM_OWNER_USERNAME);
}
mod end_to_end {
use super::*;
use crate::auth::store::{PolicyMutationControl, PrincipalRef};
use crate::auth::{AuthConfig, AuthError, AuthStore, Role, UserId};
use crate::runtime::control_events::{
ActorRef, ControlEvent, ControlEventConfig, ControlEventCtx, ControlEventError,
ControlEventLedger, EventId, EventKind,
};
struct NoopLedger;
impl ControlEventLedger for NoopLedger {
fn emit(
&self,
_: &ControlEventCtx<'_>,
_: ControlEvent,
) -> Result<EventId, ControlEventError> {
Ok(EventId("test".into()))
}
}
fn fresh_store() -> std::sync::Arc<AuthStore> {
std::sync::Arc::new(AuthStore::new(AuthConfig::default()))
}
fn attach_with_ledger(
store: &std::sync::Arc<AuthStore>,
principal: PrincipalRef,
policy_id: &str,
actor: &UserId,
) -> Result<(), AuthError> {
let ledger = NoopLedger;
let ctx = ControlEventCtx {
actor: ActorRef::User(actor),
scope: None,
request_id: None,
trace_id: None,
};
let eval_ctx = EvalContext {
principal_tenant: None,
current_tenant: None,
peer_ip: None,
mfa_present: false,
now_ms: 0,
principal_is_admin_role: true,
principal_is_system_owned: true,
principal_is_platform_scoped: true,
};
let control = PolicyMutationControl {
ctx: &ctx,
ledger: &ledger,
config: ControlEventConfig::default(),
registry: None,
actor,
eval_ctx: &eval_ctx,
};
store.attach_policy_with_control_events(principal, policy_id, &control)
}
#[test]
fn attach_refuses_self_lock_policy() {
let store = fresh_store();
store.create_user("alice", "p", Role::Admin).unwrap();
let alice = UserId::platform("alice");
let lock = Policy::from_json_str(
r#"{
"id": "p-self-lock",
"version": 1,
"statements": [{
"sid": "brick",
"effect": "deny",
"actions": ["policy:detach"],
"resources": ["*"]
}]
}"#,
)
.unwrap();
store.put_policy(lock).unwrap();
let err = attach_with_ledger(
&store,
PrincipalRef::User(alice.clone()),
"p-self-lock",
&alice,
)
.expect_err("self-lock attach must be refused");
let msg = err.to_string();
assert!(msg.contains("self-lock invariant"), "msg={msg}");
assert!(msg.contains("p-self-lock"), "msg={msg}");
assert!(msg.contains("brick"), "msg={msg}");
}
#[test]
fn attach_allows_narrower_deny() {
let store = fresh_store();
store.create_user("alice", "p", Role::Admin).unwrap();
let alice = UserId::platform("alice");
let narrow = Policy::from_json_str(
r#"{
"id": "p-narrow",
"version": 1,
"statements": [{
"effect": "deny",
"actions": ["policy:detach"],
"resources": ["*"],
"condition": { "system_owned": false }
}]
}"#,
)
.unwrap();
store.put_policy(narrow).unwrap();
attach_with_ledger(
&store,
PrincipalRef::User(alice.clone()),
"p-narrow",
&alice,
)
.expect("narrower deny attaches normally");
}
#[test]
fn break_glass_installs_rebinds_and_hides_synthetic() {
let store = fresh_store();
store
.apply_policy_break_glass(123_000)
.expect("break-glass");
assert!(store.get_policy(PLATFORM_OWNER_UNLOCK_POLICY_ID).is_some());
let users = store.list_users();
assert!(
!users.iter().any(|u| u.username == PLATFORM_OWNER_USERNAME),
"synthetic principal must not appear in list_users"
);
let scoped = store.list_users_scoped(Some(None));
assert!(
!scoped.iter().any(|u| u.username == PLATFORM_OWNER_USERNAME),
"synthetic principal must not appear in list_users_scoped"
);
let err = store
.authenticate_in_tenant(None, PLATFORM_OWNER_USERNAME, "")
.expect_err("synthetic principal must not authenticate");
assert!(matches!(err, AuthError::InvalidCredentials));
store.apply_policy_break_glass(124_000).expect("idempotent");
assert!(store.get_policy(PLATFORM_OWNER_UNLOCK_POLICY_ID).is_some());
}
#[test]
fn break_glass_recovers_from_tampered_attachment() {
let store = fresh_store();
store.apply_policy_break_glass(100).expect("install");
let owner = UserId::platform(PLATFORM_OWNER_USERNAME);
store
.detach_policy(
PrincipalRef::User(owner.clone()),
PLATFORM_OWNER_UNLOCK_POLICY_ID,
)
.expect("detach");
store.apply_policy_break_glass(200).expect("rebind");
let effective = store.effective_policies(&owner);
assert!(
effective
.iter()
.any(|p| p.id == PLATFORM_OWNER_UNLOCK_POLICY_ID),
"break-glass must rebind unlock policy to synthetic principal"
);
}
#[test]
fn event_kind_break_glass_str() {
assert_eq!(EventKind::PolicyBreakGlass.as_str(), "policy.break_glass");
}
}
}