use remora_domain::{BucketName, OpaqueId, StorageScope, Target, TargetPrefix, TargetStoreId}; use remora_identity::{ AuthorizedResource, DefaultTarget, IdentityError, ManagementOperation, ResourceVisibility, TargetOverride, can_target, decode_roles, encode_admin_role, encode_storage_role, filter_visible, may_manage, may_request_execution_grant_revocation, parse_default_target, principal_id_for, resolve_authorized_target, resolve_target, resource_visibility, roles_from_names, }; fn scope(store: &str, bucket: &str, prefix: &str) -> StorageScope { StorageScope { store: TargetStoreId::parse(store).unwrap(), bucket: BucketName::parse(bucket).unwrap(), prefix: TargetPrefix::parse(prefix, ["_remora"]).unwrap(), } } fn target(store: &str, bucket: &str, prefix: &str) -> Target { Target { store: TargetStoreId::parse(store).unwrap(), bucket: BucketName::parse(bucket).unwrap(), prefix: TargetPrefix::parse(prefix, ["_remora"]).unwrap(), } } fn principal( label: &str, administrator: bool, scopes: Vec, ) -> remora_identity::Principal { remora_identity::Principal { id: OpaqueId::parse(format!("principal-{label}-aaaa")).unwrap(), issuer: format!("https://issuer.example/{label}"), subject: format!("subject-{label}"), administrator, scopes, } } #[test] fn scope_segment_matching_rejects_textual_prefix_coincidence() { let owner = principal( "owner", false, vec![scope("target-main", "target-bucket", "research")], ); assert!(can_target( &owner, &target("target-main", "target-bucket", "research/data") )); assert!(!can_target( &owner, &target("target-main", "target-bucket", "researchers") )); assert!(!can_target( &owner, &target("target-main", "target-bucket", "researc") )); } #[test] fn unicode_prefix_nfc_canonicalization_and_reserved_segments() { let defaults = parse_default_target("target-main", "target-bucket", "", &["_remora"]).unwrap(); let resolved = resolve_target( &defaults, &TargetOverride { bucket: None, prefix: Some("cafe\u{0301}/models".into()), }, &["_remora"], ) .unwrap(); assert_eq!(resolved.prefix.canonical(), "caf\u{e9}/models"); let reserved = resolve_target( &defaults, &TargetOverride { bucket: None, prefix: Some("_remora/private".into()), }, &["_remora"], ); assert!(reserved.is_err()); let category_c = resolve_target( &defaults, &TargetOverride { bucket: None, prefix: Some("private/\u{e000}".into()), }, &["_remora"], ); assert!(category_c.is_err()); } #[test] fn default_target_applies_bucket_and_prefix_overrides() { let defaults = DefaultTarget { store: TargetStoreId::parse("target-main").unwrap(), bucket: BucketName::parse("default-bucket").unwrap(), prefix: TargetPrefix::parse("defaults", []).unwrap(), }; let full_default = resolve_target(&defaults, &TargetOverride::default(), &[]).unwrap(); assert_eq!(full_default.bucket.as_str(), "default-bucket"); assert_eq!(full_default.prefix.canonical(), "defaults"); let overridden = resolve_target( &defaults, &TargetOverride { bucket: Some("other-bucket".into()), prefix: Some("models/current/".into()), }, &[], ) .unwrap(); assert_eq!(overridden.store.as_str(), "target-main"); assert_eq!(overridden.bucket.as_str(), "other-bucket"); assert_eq!(overridden.prefix.canonical(), "models/current"); } #[test] fn resolve_authorized_target_requires_covering_scope() { let defaults = DefaultTarget { store: TargetStoreId::parse("target-main").unwrap(), bucket: BucketName::parse("target-bucket").unwrap(), prefix: TargetPrefix::parse("defaults", []).unwrap(), }; let scoped = principal( "scoped", false, vec![scope("target-main", "target-bucket", "models")], ); let ok = resolve_authorized_target( &scoped, &defaults, &TargetOverride { bucket: None, prefix: Some("models/current".into()), }, &[], ) .unwrap(); assert_eq!(ok.prefix.canonical(), "models/current"); let denied = resolve_authorized_target( &scoped, &defaults, &TargetOverride { bucket: None, prefix: Some("other".into()), }, &[], ); assert!(matches!(denied, Err(IdentityError::UnauthorizedTarget))); let admin = principal("admin", true, vec![]); let admin_ok = resolve_authorized_target( &admin, &defaults, &TargetOverride { bucket: Some("any-bucket".into()), prefix: Some("anywhere".into()), }, &[], ) .unwrap(); assert_eq!(admin_ok.bucket.as_str(), "any-bucket"); } #[test] fn revocation_of_roles_removes_current_management_not_admin_revoke_for_owners() { let target = target("target-main", "target-bucket", "models/current"); let resource = AuthorizedResource { owner: OpaqueId::parse("principal-owner-aaaa").unwrap(), target: target.clone(), }; let with_scope = principal( "owner", false, vec![scope("target-main", "target-bucket", "models")], ); assert!(may_manage( &with_scope, &resource, ManagementOperation::Cancel )); assert!(!may_request_execution_grant_revocation(&with_scope)); let after_role_loss = principal("owner", false, vec![]); assert!(!may_manage( &after_role_loss, &resource, ManagementOperation::Read )); assert_eq!( resource_visibility(&after_role_loss, Some(&resource), ManagementOperation::Read), ResourceVisibility::NotFound ); let admin = principal("admin", true, vec![]); assert!(may_manage( &admin, &resource, ManagementOperation::HardDelete )); assert!(may_request_execution_grant_revocation(&admin)); } #[test] fn missing_and_unauthorized_resources_are_indistinguishable() { let owner = principal( "owner", false, vec![scope("target-main", "target-bucket", "")], ); let other = principal( "other", false, vec![scope("target-main", "target-bucket", "")], ); let resource = AuthorizedResource { owner: owner.id.clone(), target: target("target-main", "target-bucket", "models"), }; let missing = resource_visibility(&owner, None, ManagementOperation::Read); let unauthorized = resource_visibility(&other, Some(&resource), ManagementOperation::Read); assert_eq!(missing, ResourceVisibility::NotFound); assert_eq!(unauthorized, ResourceVisibility::NotFound); assert_eq!(missing, unauthorized); let visible = resource_visibility(&owner, Some(&resource), ManagementOperation::Read); assert_eq!(visible, ResourceVisibility::Visible); } #[test] fn list_filtering_hides_unauthorized_existence() { let owner = principal( "owner", false, vec![scope("target-main", "target-bucket", "models")], ); let mine = AuthorizedResource { owner: owner.id.clone(), target: target("target-main", "target-bucket", "models/a"), }; let outside = AuthorizedResource { owner: owner.id.clone(), target: target("target-main", "target-bucket", "other"), }; let peer = AuthorizedResource { owner: OpaqueId::parse("principal-peer-aaaaaa").unwrap(), target: target("target-main", "target-bucket", "models/b"), }; let visible = filter_visible(&owner, [&mine, &outside, &peer]); assert_eq!(visible, vec![&mine]); } #[test] fn principal_ids_are_stable_for_issuer_subject_pairs() { let first = principal_id_for("https://issuer.example", "user-1").unwrap(); let second = principal_id_for("https://issuer.example", "user-1").unwrap(); let other = principal_id_for("https://issuer.example", "user-2").unwrap(); assert_eq!(first, second); assert_ne!(first, other); } #[test] fn role_encoding_round_trip_and_foreign_roles_ignored() { let storage = encode_storage_role(&scope("target-main", "target-bucket", "models/current")).unwrap(); let decoded = decode_roles( [encode_admin_role().as_str(), "test-user", storage.as_str()], &["_remora"], ) .unwrap(); assert!(decoded.administrator); assert_eq!(decoded.scopes.len(), 1); assert!(decoded.scopes[0].covers(&target( "target-main", "target-bucket", "models/current/file" ))); let roles = roles_from_names(&[remora_identity::ADMIN_ROLE], &[]).unwrap(); assert!(roles.administrator); let bare = roles_from_names(&["admin"], &[]).unwrap(); assert!(!bare.administrator); }