17_attribute_based_access_control/
17_attribute_based_access_control.rs1use std::sync::Arc;
13use tokio::sync::RwLock;
14use wami::arn::{TenantPath, WamiArn};
15use wami::context::WamiContext;
16use wami::service::{PolicyService, UserService};
17use wami::store::memory::InMemoryWamiStore;
18use wami::types::Tag;
19use wami::wami::identity::user::requests::CreateUserRequest;
20use wami::wami::policies::policy::requests::CreatePolicyRequest;
21
22#[tokio::main]
23async fn main() -> Result<(), Box<dyn std::error::Error>> {
24 println!("=== Attribute-Based Access Control (ABAC) ===\n");
25
26 let store = Arc::new(RwLock::new(InMemoryWamiStore::default()));
27
28 let context = WamiContext::builder()
30 .instance_id("123456789012")
31 .tenant_path(TenantPath::single(0))
32 .caller_arn(
33 WamiArn::builder()
34 .service(wami::arn::Service::Iam)
35 .tenant_path(TenantPath::single(0))
36 .wami_instance("123456789012")
37 .resource("user", "admin")
38 .build()?,
39 )
40 .is_root(false)
41 .build()?;
42
43 let user_service = UserService::new(store.clone());
44 let policy_service = PolicyService::new(store.clone());
45
46 println!("Step 1: Creating users with department/project tags...\n");
48
49 user_service
50 .create_user(
51 &context,
52 CreateUserRequest {
53 user_name: "alice".to_string(),
54 path: Some("/".to_string()),
55 permissions_boundary: None,
56 tags: Some(vec![
57 Tag {
58 key: "Department".to_string(),
59 value: "Engineering".to_string(),
60 },
61 Tag {
62 key: "Project".to_string(),
63 value: "ProjectA".to_string(),
64 },
65 ]),
66 },
67 )
68 .await?;
69 println!("✓ Created alice (Engineering, ProjectA)");
70
71 user_service
72 .create_user(
73 &context,
74 CreateUserRequest {
75 user_name: "bob".to_string(),
76 path: Some("/".to_string()),
77 permissions_boundary: None,
78 tags: Some(vec![
79 Tag {
80 key: "Department".to_string(),
81 value: "Engineering".to_string(),
82 },
83 Tag {
84 key: "Project".to_string(),
85 value: "ProjectB".to_string(),
86 },
87 ]),
88 },
89 )
90 .await?;
91 println!("✓ Created bob (Engineering, ProjectB)");
92
93 user_service
94 .create_user(
95 &context,
96 CreateUserRequest {
97 user_name: "charlie".to_string(),
98 path: Some("/".to_string()),
99 permissions_boundary: None,
100 tags: Some(vec![
101 Tag {
102 key: "Department".to_string(),
103 value: "Sales".to_string(),
104 },
105 Tag {
106 key: "Project".to_string(),
107 value: "ProjectC".to_string(),
108 },
109 ]),
110 },
111 )
112 .await?;
113 println!("✓ Created charlie (Sales, ProjectC)");
114
115 println!("\n\nStep 2: Creating ABAC policy...\n");
117
118 let abac_policy_doc = r#"{
119 "Version": "2012-10-17",
120 "Statement": [{
121 "Effect": "Allow",
122 "Action": "s3:*",
123 "Resource": "arn:aws:s3:::${aws:PrincipalTag/Project}/*",
124 "Condition": {
125 "StringEquals": {
126 "s3:ExistingObjectTag/Department": "${aws:PrincipalTag/Department}"
127 }
128 }
129 }]
130}"#;
131
132 policy_service
133 .create_policy(
134 &context,
135 CreatePolicyRequest {
136 policy_name: "ABACPolicy".to_string(),
137 path: Some("/abac/".to_string()),
138 policy_document: abac_policy_doc.to_string(),
139 description: Some("ABAC policy using tags".to_string()),
140 tags: None,
141 },
142 )
143 .await?;
144 println!("✓ Created ABAC policy with tag-based conditions");
145 println!(" - Resource access based on PrincipalTag/Project");
146 println!(" - Object access requires matching Department tag");
147
148 println!("\n\n✅ Example completed successfully!");
149 println!("Key takeaways:");
150 println!("- ABAC uses tags for dynamic access control");
151 println!("- Policies reference ${{aws:PrincipalTag/Key}}");
152 println!("- Scales better than RBAC for large organizations");
153
154 Ok(())
155}