24_policy_attachment/
24_policy_attachment.rs1use std::sync::Arc;
7use tokio::sync::RwLock;
8use wami::arn::{TenantPath, WamiArn};
9use wami::context::WamiContext;
10use wami::service::{AttachmentService, InlinePolicyService, PolicyService, UserService};
11use wami::store::memory::InMemoryWamiStore;
12use wami::wami::identity::user::CreateUserRequest;
13use wami::wami::policies::attachment::{AttachUserPolicyRequest, ListAttachedUserPoliciesRequest};
14use wami::wami::policies::inline::{
15 GetUserPolicyRequest, ListUserPoliciesRequest, PutUserPolicyRequest,
16};
17use wami::wami::policies::policy::CreatePolicyRequest;
18
19#[tokio::main]
20async fn main() -> Result<(), Box<dyn std::error::Error>> {
21 env_logger::init();
23
24 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 println!("=== Policy Attachment Example ===\n");
43
44 println!("1. Creating user 'alice'...");
46 let user_service = UserService::new(store.clone());
47 let create_user_req = CreateUserRequest {
48 user_name: "alice".to_string(),
49 path: Some("/".to_string()),
50 tags: Some(vec![]),
51 permissions_boundary: None,
52 };
53 let user = user_service.create_user(&context, create_user_req).await?;
54 println!(" Created user: {} (ARN: {})\n", user.user_name, user.arn);
55
56 println!("2. Creating managed policy 'S3ReadOnly'...");
58 let policy_service = PolicyService::new(store.clone());
59 let policy_doc = r#"{
60 "Version": "2012-10-17",
61 "Statement": [{
62 "Effect": "Allow",
63 "Action": ["s3:GetObject", "s3:ListBucket"],
64 "Resource": "*"
65 }]
66 }"#;
67
68 let create_policy_req = CreatePolicyRequest {
69 policy_name: "S3ReadOnly".to_string(),
70 path: Some("/".to_string()),
71 policy_document: policy_doc.to_string(),
72 description: Some("Read-only access to S3".to_string()),
73 tags: Some(vec![]),
74 };
75 let policy = policy_service
76 .create_policy(&context, create_policy_req)
77 .await?;
78 println!(
79 " Created policy: {} (ARN: {})\n",
80 policy.policy_name, policy.arn
81 );
82
83 println!("3. Attaching managed policy to user...");
85 let attachment_service = AttachmentService::new(store.clone());
86 let attach_req = AttachUserPolicyRequest {
87 user_name: "alice".to_string(),
88 policy_arn: policy.arn.clone(),
89 };
90 let attach_resp = attachment_service
91 .attach_user_policy(&context, attach_req)
92 .await?;
93 println!(" {}\n", attach_resp.message);
94
95 println!("4. Listing attached policies for user 'alice'...");
97 let list_req = ListAttachedUserPoliciesRequest {
98 user_name: "alice".to_string(),
99 };
100 let list_resp = attachment_service
101 .list_attached_user_policies(&context, list_req)
102 .await?;
103 println!(
104 " Found {} attached policies:",
105 list_resp.attached_policies.len()
106 );
107 for p in &list_resp.attached_policies {
108 println!(" - {} ({})", p.policy_name, p.policy_arn);
109 }
110 println!();
111
112 println!("5. Adding inline policy 'DenyDelete' to user...");
114 let inline_service = InlinePolicyService::new(store.clone());
115 let inline_doc = r#"{
116 "Version": "2012-10-17",
117 "Statement": [{
118 "Effect": "Deny",
119 "Action": ["*:Delete*"],
120 "Resource": "*"
121 }]
122 }"#;
123
124 let put_inline_req = PutUserPolicyRequest {
125 user_name: "alice".to_string(),
126 policy_name: "DenyDelete".to_string(),
127 policy_document: inline_doc.to_string(),
128 };
129 let put_resp = inline_service
130 .put_user_policy(&context, put_inline_req)
131 .await?;
132 println!(" {}\n", put_resp.message);
133
134 println!("6. Listing inline policies for user 'alice'...");
136 let list_inline_req = ListUserPoliciesRequest {
137 user_name: "alice".to_string(),
138 };
139 let list_inline_resp = inline_service
140 .list_user_policies(&context, list_inline_req)
141 .await?;
142 println!(
143 " Found {} inline policies:",
144 list_inline_resp.policy_names.len()
145 );
146 for name in &list_inline_resp.policy_names {
147 println!(" - {}", name);
148 }
149 println!();
150
151 println!("7. Getting inline policy 'DenyDelete'...");
153 let get_inline_req = GetUserPolicyRequest {
154 user_name: "alice".to_string(),
155 policy_name: "DenyDelete".to_string(),
156 };
157 let get_resp = inline_service
158 .get_user_policy(&context, get_inline_req)
159 .await?;
160 println!(" Policy document:\n{}\n", get_resp.policy_document);
161
162 println!("=== Summary ===");
163 println!("User 'alice' now has:");
164 println!(
165 "- {} managed policy attached (S3ReadOnly)",
166 list_resp.attached_policies.len()
167 );
168 println!(
169 "- {} inline policy (DenyDelete)",
170 list_inline_resp.policy_names.len()
171 );
172 println!("\nThis grants alice read access to S3 but denies all delete operations.");
173
174 Ok(())
175}