Skip to main content

14_policy_basics/
14_policy_basics.rs

1//! Policy Basics
2//!
3//! This example demonstrates:
4//! - Creating IAM policies with allow/deny statements
5//! - Attaching policies to users and roles
6//! - Testing basic access control
7//!
8//! Scenario: Creating policies for read-only and admin access.
9//!
10//! Run with: `cargo run --example 14_policy_basics`
11
12use 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    // Create context
28    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    // === CREATE USERS ===
46    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    // === CREATE READ-ONLY POLICY ===
67    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    // === CREATE DENY POLICY ===
96    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    // === CREATE ADMIN POLICY ===
125    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    // === LIST ALL POLICIES ===
151    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    // === DEMONSTRATE POLICY CONCEPTS ===
170    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}