14_policy_basics/
14_policy_basics.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::wami::identity::user::requests::CreateUserRequest;
19use wami::wami::policies::policy::requests::{CreatePolicyRequest, ListPoliciesRequest};
20
21#[tokio::main]
22async fn main() -> Result<(), Box<dyn std::error::Error>> {
23 println!("=== Policy Basics ===\n");
24
25 let store = Arc::new(RwLock::new(InMemoryWamiStore::default()));
26
27 let context = WamiContext::builder()
29 .instance_id("123456789012")
30 .tenant_path(TenantPath::single(0))
31 .caller_arn(
32 WamiArn::builder()
33 .service(wami::arn::Service::Iam)
34 .tenant_path(TenantPath::single(0))
35 .wami_instance("123456789012")
36 .resource("user", "admin")
37 .build()?,
38 )
39 .is_root(false)
40 .build()?;
41
42 let policy_service = PolicyService::new(store.clone());
43 let user_service = UserService::new(store.clone());
44
45 println!("Step 1: Creating users...\n");
47
48 let alice_req = CreateUserRequest {
49 user_name: "alice".to_string(),
50 path: Some("/".to_string()),
51 permissions_boundary: None,
52 tags: None,
53 };
54 user_service.create_user(&context, alice_req).await?;
55 println!("✓ Created alice");
56
57 let bob_req = CreateUserRequest {
58 user_name: "bob".to_string(),
59 path: Some("/".to_string()),
60 permissions_boundary: None,
61 tags: None,
62 };
63 user_service.create_user(&context, bob_req).await?;
64 println!("✓ Created bob");
65
66 println!("\n\nStep 2: Creating read-only policy...\n");
68
69 let readonly_policy_doc = r#"{
70 "Version": "2012-10-17",
71 "Statement": [{
72 "Effect": "Allow",
73 "Action": [
74 "s3:GetObject",
75 "s3:ListBucket"
76 ],
77 "Resource": "*"
78 }]
79}"#;
80
81 let readonly_req = CreatePolicyRequest {
82 policy_name: "ReadOnlyAccess".to_string(),
83 path: Some("/policies/".to_string()),
84 policy_document: readonly_policy_doc.to_string(),
85 description: Some("Grants read-only access to resources".to_string()),
86 tags: None,
87 };
88
89 let readonly_policy = policy_service.create_policy(&context, readonly_req).await?;
90 println!("✓ Created ReadOnlyAccess policy:");
91 println!(" - ARN: {}", readonly_policy.arn);
92 println!(" - Actions: s3:GetObject, s3:ListBucket");
93 println!(" - Effect: Allow");
94
95 println!("\n\nStep 3: Creating deny policy...\n");
97
98 let deny_policy_doc = r#"{
99 "Version": "2012-10-17",
100 "Statement": [{
101 "Effect": "Deny",
102 "Action": [
103 "s3:DeleteObject",
104 "s3:DeleteBucket"
105 ],
106 "Resource": "*"
107 }]
108}"#;
109
110 let deny_req = CreatePolicyRequest {
111 policy_name: "DenyDelete".to_string(),
112 path: Some("/policies/".to_string()),
113 policy_document: deny_policy_doc.to_string(),
114 description: Some("Explicitly denies delete operations".to_string()),
115 tags: None,
116 };
117
118 let deny_policy = policy_service.create_policy(&context, deny_req).await?;
119 println!("✓ Created DenyDelete policy:");
120 println!(" - ARN: {}", deny_policy.arn);
121 println!(" - Actions: s3:DeleteObject, s3:DeleteBucket");
122 println!(" - Effect: Deny (overrides all allows)");
123
124 println!("\n\nStep 4: Creating admin policy...\n");
126
127 let admin_policy_doc = r#"{
128 "Version": "2012-10-17",
129 "Statement": [{
130 "Effect": "Allow",
131 "Action": "*",
132 "Resource": "*"
133 }]
134}"#;
135
136 let admin_req = CreatePolicyRequest {
137 policy_name: "AdministratorAccess".to_string(),
138 path: Some("/policies/".to_string()),
139 policy_document: admin_policy_doc.to_string(),
140 description: Some("Grants full access to all resources".to_string()),
141 tags: None,
142 };
143
144 let admin_policy = policy_service.create_policy(&context, admin_req).await?;
145 println!("✓ Created AdministratorAccess policy:");
146 println!(" - ARN: {}", admin_policy.arn);
147 println!(" - Actions: * (all actions)");
148 println!(" - Resources: * (all resources)");
149
150 println!("\n\nStep 5: Listing all policies...\n");
152
153 let (policies, _, _) = policy_service
154 .list_policies(
155 &context,
156 ListPoliciesRequest {
157 scope: None,
158 only_attached: None,
159 path_prefix: None,
160 pagination: None,
161 },
162 )
163 .await?;
164 println!("✓ Found {} policies:", policies.len());
165 for policy in &policies {
166 println!(" - {} ({})", policy.policy_name, policy.arn);
167 }
168
169 println!("\n\nStep 6: Understanding policy concepts...\n");
171
172 println!("Policy evaluation order:");
173 println!("1. Explicit DENY - Always wins");
174 println!("2. Explicit ALLOW - Required for access");
175 println!("3. Implicit DENY - Default if no allow");
176 println!();
177 println!("Policy types:");
178 println!("- Identity-based: Attached to users/roles/groups");
179 println!("- Resource-based: Attached to resources (not shown here)");
180 println!("- Permissions boundaries: Maximum permissions (not shown here)");
181 println!();
182 println!("Best practices:");
183 println!("- Use deny policies for critical restrictions");
184 println!("- Grant least privilege with allow policies");
185 println!("- Use managed policies for common patterns");
186 println!("- Regularly audit policy attachments");
187
188 println!("\n✅ Example completed successfully!");
189 println!("Key takeaways:");
190 println!("- Policies define permissions using JSON documents");
191 println!("- Statements contain Effect, Action, and Resource");
192 println!("- Deny always overrides allow");
193 println!("- Policies can be attached to principals (users/roles)");
194
195 Ok(())
196}