pub struct IAMRequest {
pub principal: Principal,
pub action: String,
pub resource: Arn,
pub context: Context,
}
Expand description
Core IAM request containing principal, action, and resource
§Understanding the PARC model
The PARC model represents the request context based on the four JSON elements in the policy language:
- Principal – The entity making the request. A principal represents a human user or programmatic workload that can be authenticated and then authorized to perform actions in AWS accounts.
- Action – The operation being performed. Often the action will map to an API action.
- Resource – The AWS resource on which the action is being performed.
- Condition – Additional constraints that must be met for the request to be allowed.
The following shows an example of how the PARC model might represent a request context:
Principal: AIDA123456789EXAMPLE
Action: s3:CreateBucket
Resource: arn:aws:s3:::amzn-s3-demo-bucket1
Context:
- aws:UserId=AIDA123456789EXAMPLE:BobsSession
- aws:PrincipalAccount=123456789012
- aws:PrincipalOrgId=o-example
- aws:PrincipalARN=arn:aws:iam::AIDA123456789EXAMPLE:role/HR
- aws:MultiFactorAuthPresent=true
- aws:CurrentTime=...
- aws:EpochTime=...
- aws:SourceIp=...
- aws:PrincipalTag/dept=123
- aws:PrincipalTag/project=blue
- aws:RequestTag/dept=123
Fields§
§principal: Principal
The principal making the request (e.g., AROA123456789EXAMPLE)
action: String
The action being requested (e.g., iam:DeactivateMFADevice)
resource: Arn
The resource being accessed (e.g., arn:aws:iam::user/martha
)
context: Context
Additional context for condition evaluation
Implementations§
Source§impl IAMRequest
impl IAMRequest
Sourcepub fn new<S: Into<String>>(
principal: Principal,
action: S,
resource: Arn,
) -> Self
pub fn new<S: Into<String>>( principal: Principal, action: S, resource: Arn, ) -> Self
Creates a new request
Examples found in repository?
examples/evaluation_demo.rs (lines 21-27)
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8 println!("=== IAM Policy Evaluation Engine Demo ===\n");
9
10 // Example 1: Simple Allow Policy
11 println!("1. Simple Allow Policy:");
12 let allow_policy = IAMPolicy::new()
13 .with_id("550e8400-e29b-41d4-a716-446655440000")
14 .add_statement(
15 IAMStatement::new(IAMEffect::Allow)
16 .with_sid("AllowS3Read")
17 .with_action(IAMAction::Single("s3:GetObject".to_string()))
18 .with_resource(IAMResource::Single("arn:aws:s3:::my-bucket/*".to_string())),
19 );
20
21 let request = IAMRequest::new(
22 Principal::Aws(PrincipalId::String(
23 "arn:aws:iam::123456789012:user/alice".to_string(),
24 )),
25 "s3:GetObject",
26 Arn::parse("arn:aws:s3:::my-bucket/file.txt").unwrap(),
27 );
28
29 match evaluate_policy(&allow_policy, &request)? {
30 Decision::Allow => println!("✓ Access ALLOWED"),
31 Decision::Deny => println!("✗ Access DENIED"),
32 Decision::NotApplicable => println!("? No applicable policy (implicit deny)"),
33 }
34 println!();
35
36 // Example 2: Simple Deny Policy
37 println!("2. Simple Deny Policy:");
38 let deny_policy = IAMPolicy::new()
39 .with_id("550e8400-e29b-41d4-a716-446655440001")
40 .add_statement(
41 IAMStatement::new(IAMEffect::Deny)
42 .with_sid("DenyS3Delete")
43 .with_action(IAMAction::Single("s3:DeleteObject".to_string()))
44 .with_resource(IAMResource::Single(
45 "arn:aws:s3:::protected-bucket/*".to_string(),
46 )),
47 );
48
49 let delete_request = IAMRequest::new(
50 Principal::Aws(PrincipalId::String(
51 "arn:aws:iam::123456789012:user/alice".to_string(),
52 )),
53 "s3:DeleteObject",
54 Arn::parse("arn:aws:s3:::protected-bucket/important.txt").unwrap(),
55 );
56
57 match evaluate_policy(&deny_policy, &delete_request)? {
58 Decision::Allow => println!("✓ Access ALLOWED"),
59 Decision::Deny => println!("✗ Access DENIED"),
60 Decision::NotApplicable => println!("? No applicable policy (implicit deny)"),
61 }
62 println!();
63
64 // Example 3: Wildcard Action Matching
65 println!("3. Wildcard Action Matching:");
66 let wildcard_policy = IAMPolicy::new()
67 .with_id("550e8400-e29b-41d4-a716-446655440002")
68 .add_statement(
69 IAMStatement::new(IAMEffect::Allow)
70 .with_sid("AllowAllS3")
71 .with_action(IAMAction::Single("s3:*".to_string()))
72 .with_resource(IAMResource::Single("arn:aws:s3:::my-bucket/*".to_string())),
73 );
74
75 let wildcard_request = IAMRequest::new(
76 Principal::Aws(PrincipalId::String(
77 "arn:aws:iam::123456789012:user/alice".to_string(),
78 )),
79 "s3:PutObject",
80 Arn::parse("arn:aws:s3:::my-bucket/new-file.txt").unwrap(),
81 );
82
83 match evaluate_policy(&wildcard_policy, &wildcard_request)? {
84 Decision::Allow => println!("✓ Wildcard action matched - Access ALLOWED"),
85 Decision::Deny => println!("✗ Access DENIED"),
86 Decision::NotApplicable => println!("? No applicable policy"),
87 }
88 println!();
89
90 // Example 4: Condition-Based Policy
91 println!("4. Condition-Based Policy:");
92 let mut context = Context::new();
93 context.insert(
94 "aws:userid".to_string(),
95 ContextValue::String("alice".to_string()),
96 );
97 context.insert(
98 "aws:CurrentTime".to_string(),
99 ContextValue::String("2024-01-15T10:00:00Z".to_string()),
100 );
101
102 let condition_policy = IAMPolicy::new()
103 .with_id("550e8400-e29b-41d4-a716-446655440003")
104 .add_statement(
105 IAMStatement::new(IAMEffect::Allow)
106 .with_sid("AllowWithCondition")
107 .with_action(IAMAction::Single("s3:GetObject".to_string()))
108 .with_resource(IAMResource::Single(
109 "arn:aws:s3:::private-bucket/*".to_string(),
110 ))
111 .with_condition(
112 IAMOperator::StringEquals,
113 "aws:userid".to_string(),
114 ConditionValue::String("alice".to_string()),
115 ),
116 );
117
118 let condition_request = IAMRequest::new_with_context(
119 Principal::Aws(PrincipalId::String(
120 "arn:aws:iam::123456789012:user/alice".to_string(),
121 )),
122 "s3:GetObject",
123 Arn::parse("arn:aws:s3:::private-bucket/personal.txt").unwrap(),
124 context,
125 );
126
127 match evaluate_policy(&condition_policy, &condition_request)? {
128 Decision::Allow => println!("✓ Condition satisfied - Access ALLOWED"),
129 Decision::Deny => println!("✗ Access DENIED"),
130 Decision::NotApplicable => println!("? Condition not satisfied"),
131 }
132 println!();
133
134 // Example 5: Failed Condition
135 println!("5. Failed Condition:");
136 let mut wrong_context = Context::new();
137 wrong_context.insert(
138 "aws:userid".to_string(),
139 ContextValue::String("bob".to_string()),
140 );
141
142 let failed_condition_request = IAMRequest::new_with_context(
143 Principal::Aws(PrincipalId::String(
144 "arn:aws:iam::123456789012:user/bob".to_string(),
145 )),
146 "s3:GetObject",
147 Arn::parse("arn:aws:s3:::private-bucket/personal.txt").unwrap(),
148 wrong_context,
149 );
150
151 match evaluate_policy(&condition_policy, &failed_condition_request)? {
152 Decision::Allow => println!("✓ Access ALLOWED"),
153 Decision::Deny => println!("✗ Access DENIED"),
154 Decision::NotApplicable => println!("? Condition failed - No applicable policy"),
155 }
156 println!();
157
158 // Example 6: Explicit Deny Overrides Allow
159 println!("6. Explicit Deny Overrides Allow:");
160 let combined_policies = vec![
161 IAMPolicy::new()
162 .with_id("550e8400-e29b-41d4-a716-446655440004")
163 .add_statement(
164 IAMStatement::new(IAMEffect::Allow)
165 .with_sid("AllowAll")
166 .with_action(IAMAction::Single("s3:*".to_string()))
167 .with_resource(IAMResource::Single("*".to_string())),
168 ),
169 IAMPolicy::new()
170 .with_id("550e8400-e29b-41d4-a716-446655440005")
171 .add_statement(
172 IAMStatement::new(IAMEffect::Deny)
173 .with_sid("DenyProtected")
174 .with_action(IAMAction::Single("s3:DeleteObject".to_string()))
175 .with_resource(IAMResource::Single(
176 "arn:aws:s3:::protected-bucket/*".to_string(),
177 )),
178 ),
179 ];
180
181 let evaluator = PolicyEvaluator::with_policies(combined_policies);
182 let protected_request = IAMRequest::new(
183 Principal::Aws(PrincipalId::String(
184 "arn:aws:iam::123456789012:user/alice".to_string(),
185 )),
186 "s3:DeleteObject",
187 Arn::parse("arn:aws:s3:::protected-bucket/critical.txt").unwrap(),
188 );
189
190 match evaluator.evaluate(&protected_request)?.decision {
191 Decision::Allow => println!("✓ Access ALLOWED"),
192 Decision::Deny => println!("✗ Explicit DENY overrides Allow"),
193 Decision::NotApplicable => println!("? No applicable policy"),
194 }
195 println!();
196
197 // Example 7: Numeric Condition
198 println!("7. Numeric Condition:");
199 let mut numeric_context = Context::new();
200 numeric_context.insert("aws:RequestCount".to_string(), ContextValue::Number(5.0));
201
202 let numeric_policy = IAMPolicy::new()
203 .with_id("550e8400-e29b-41d4-a716-446655440006")
204 .add_statement(
205 IAMStatement::new(IAMEffect::Allow)
206 .with_sid("AllowLimitedRequests")
207 .with_action(IAMAction::Single("s3:GetObject".to_string()))
208 .with_resource(IAMResource::Single("*".to_string()))
209 .with_condition(
210 IAMOperator::NumericLessThan,
211 "aws:RequestCount".to_string(),
212 ConditionValue::Number(10),
213 ),
214 );
215
216 let numeric_request = IAMRequest::new_with_context(
217 Principal::Aws(PrincipalId::String(
218 "arn:aws:iam::123456789012:user/alice".to_string(),
219 )),
220 "s3:GetObject",
221 Arn::parse("arn:aws:s3:::any-bucket/file.txt").unwrap(),
222 numeric_context,
223 );
224
225 match evaluate_policy(&numeric_policy, &numeric_request)? {
226 Decision::Allow => println!("✓ Numeric condition satisfied - Access ALLOWED"),
227 Decision::Deny => println!("✗ Access DENIED"),
228 Decision::NotApplicable => println!("? Numeric condition failed"),
229 }
230 println!();
231
232 // Example 8: Detailed Evaluation with Options
233 println!("8. Detailed Evaluation with Options:");
234 let detailed_evaluator = PolicyEvaluator::with_policies(vec![allow_policy.clone()])
235 .with_options(EvaluationOptions {
236 collect_match_details: true,
237 stop_on_explicit_deny: false,
238 max_statements: 100,
239 ignore_resource_constraints: false,
240 });
241
242 let detailed_result = detailed_evaluator.evaluate(&request)?;
243 println!("Decision: {:?}", detailed_result.decision);
244 println!("Matched Statements:");
245 for (i, statement_match) in detailed_result.matched_statements.iter().enumerate() {
246 println!(
247 " {}. SID: {:?}, Effect: {:?}, Satisfied: {}, Reason: {}",
248 i + 1,
249 statement_match.sid,
250 statement_match.effect,
251 statement_match.conditions_satisfied,
252 statement_match.reason
253 );
254 }
255 println!();
256
257 // Example 9: No Applicable Policy (Implicit Deny)
258 println!("9. No Applicable Policy (Implicit Deny):");
259 let unrelated_request = IAMRequest::new(
260 Principal::Aws(PrincipalId::String(
261 "arn:aws:iam::123456789012:user/alice".to_string(),
262 )),
263 "ec2:DescribeInstances",
264 Arn::parse("arn:aws:ec2:us-east-1:123456789012:instance/*").unwrap(),
265 );
266
267 match evaluate_policy(&allow_policy, &unrelated_request)? {
268 Decision::Allow => println!("✓ Access ALLOWED"),
269 Decision::Deny => println!("✗ Access DENIED"),
270 Decision::NotApplicable => println!("? No applicable policy - Implicit DENY"),
271 }
272 println!();
273
274 // Example 10: Resource Pattern Matching
275 println!("10. Resource Pattern Matching:");
276 let pattern_policy = IAMPolicy::new()
277 .with_id("550e8400-e29b-41d4-a716-446655440007")
278 .add_statement(
279 IAMStatement::new(IAMEffect::Allow)
280 .with_sid("AllowBucketAccess")
281 .with_action(IAMAction::Multiple(vec![
282 "s3:GetObject".to_string(),
283 "s3:PutObject".to_string(),
284 ]))
285 .with_resource(IAMResource::Single(
286 "arn:aws:s3:::user-data-*/*".to_string(),
287 )),
288 );
289
290 let pattern_request = IAMRequest::new(
291 Principal::Aws(PrincipalId::String(
292 "arn:aws:iam::123456789012:user/alice".to_string(),
293 )),
294 "s3:GetObject",
295 Arn::parse("arn:aws:s3:::user-data-alice/profile.json").unwrap(),
296 );
297
298 match evaluate_policy(&pattern_policy, &pattern_request)? {
299 Decision::Allow => println!("✓ Resource pattern matched - Access ALLOWED"),
300 Decision::Deny => println!("✗ Access DENIED"),
301 Decision::NotApplicable => println!("? Resource pattern didn't match"),
302 }
303
304 println!("\n=== Policy Evaluation Demo Complete ===");
305 println!("\nThe Policy Evaluation Engine successfully:");
306 println!("• ✅ Evaluates Allow/Deny effects");
307 println!("• ✅ Handles wildcard actions and resources");
308 println!("• ✅ Processes condition blocks with various operators");
309 println!("• ✅ Implements proper IAM logic (explicit deny overrides)");
310 println!("• ✅ Supports detailed evaluation with match information");
311 println!("• ✅ Handles multiple policies with complex interactions");
312 println!("• ✅ Provides clear Allow/Deny/NotApplicable decisions");
313
314 Ok(())
315}
Sourcepub fn new_with_context<S: Into<String>>(
principal: Principal,
action: S,
resource: Arn,
context: Context,
) -> Self
pub fn new_with_context<S: Into<String>>( principal: Principal, action: S, resource: Arn, context: Context, ) -> Self
Creates a request with context
Examples found in repository?
examples/evaluation_demo.rs (lines 118-125)
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8 println!("=== IAM Policy Evaluation Engine Demo ===\n");
9
10 // Example 1: Simple Allow Policy
11 println!("1. Simple Allow Policy:");
12 let allow_policy = IAMPolicy::new()
13 .with_id("550e8400-e29b-41d4-a716-446655440000")
14 .add_statement(
15 IAMStatement::new(IAMEffect::Allow)
16 .with_sid("AllowS3Read")
17 .with_action(IAMAction::Single("s3:GetObject".to_string()))
18 .with_resource(IAMResource::Single("arn:aws:s3:::my-bucket/*".to_string())),
19 );
20
21 let request = IAMRequest::new(
22 Principal::Aws(PrincipalId::String(
23 "arn:aws:iam::123456789012:user/alice".to_string(),
24 )),
25 "s3:GetObject",
26 Arn::parse("arn:aws:s3:::my-bucket/file.txt").unwrap(),
27 );
28
29 match evaluate_policy(&allow_policy, &request)? {
30 Decision::Allow => println!("✓ Access ALLOWED"),
31 Decision::Deny => println!("✗ Access DENIED"),
32 Decision::NotApplicable => println!("? No applicable policy (implicit deny)"),
33 }
34 println!();
35
36 // Example 2: Simple Deny Policy
37 println!("2. Simple Deny Policy:");
38 let deny_policy = IAMPolicy::new()
39 .with_id("550e8400-e29b-41d4-a716-446655440001")
40 .add_statement(
41 IAMStatement::new(IAMEffect::Deny)
42 .with_sid("DenyS3Delete")
43 .with_action(IAMAction::Single("s3:DeleteObject".to_string()))
44 .with_resource(IAMResource::Single(
45 "arn:aws:s3:::protected-bucket/*".to_string(),
46 )),
47 );
48
49 let delete_request = IAMRequest::new(
50 Principal::Aws(PrincipalId::String(
51 "arn:aws:iam::123456789012:user/alice".to_string(),
52 )),
53 "s3:DeleteObject",
54 Arn::parse("arn:aws:s3:::protected-bucket/important.txt").unwrap(),
55 );
56
57 match evaluate_policy(&deny_policy, &delete_request)? {
58 Decision::Allow => println!("✓ Access ALLOWED"),
59 Decision::Deny => println!("✗ Access DENIED"),
60 Decision::NotApplicable => println!("? No applicable policy (implicit deny)"),
61 }
62 println!();
63
64 // Example 3: Wildcard Action Matching
65 println!("3. Wildcard Action Matching:");
66 let wildcard_policy = IAMPolicy::new()
67 .with_id("550e8400-e29b-41d4-a716-446655440002")
68 .add_statement(
69 IAMStatement::new(IAMEffect::Allow)
70 .with_sid("AllowAllS3")
71 .with_action(IAMAction::Single("s3:*".to_string()))
72 .with_resource(IAMResource::Single("arn:aws:s3:::my-bucket/*".to_string())),
73 );
74
75 let wildcard_request = IAMRequest::new(
76 Principal::Aws(PrincipalId::String(
77 "arn:aws:iam::123456789012:user/alice".to_string(),
78 )),
79 "s3:PutObject",
80 Arn::parse("arn:aws:s3:::my-bucket/new-file.txt").unwrap(),
81 );
82
83 match evaluate_policy(&wildcard_policy, &wildcard_request)? {
84 Decision::Allow => println!("✓ Wildcard action matched - Access ALLOWED"),
85 Decision::Deny => println!("✗ Access DENIED"),
86 Decision::NotApplicable => println!("? No applicable policy"),
87 }
88 println!();
89
90 // Example 4: Condition-Based Policy
91 println!("4. Condition-Based Policy:");
92 let mut context = Context::new();
93 context.insert(
94 "aws:userid".to_string(),
95 ContextValue::String("alice".to_string()),
96 );
97 context.insert(
98 "aws:CurrentTime".to_string(),
99 ContextValue::String("2024-01-15T10:00:00Z".to_string()),
100 );
101
102 let condition_policy = IAMPolicy::new()
103 .with_id("550e8400-e29b-41d4-a716-446655440003")
104 .add_statement(
105 IAMStatement::new(IAMEffect::Allow)
106 .with_sid("AllowWithCondition")
107 .with_action(IAMAction::Single("s3:GetObject".to_string()))
108 .with_resource(IAMResource::Single(
109 "arn:aws:s3:::private-bucket/*".to_string(),
110 ))
111 .with_condition(
112 IAMOperator::StringEquals,
113 "aws:userid".to_string(),
114 ConditionValue::String("alice".to_string()),
115 ),
116 );
117
118 let condition_request = IAMRequest::new_with_context(
119 Principal::Aws(PrincipalId::String(
120 "arn:aws:iam::123456789012:user/alice".to_string(),
121 )),
122 "s3:GetObject",
123 Arn::parse("arn:aws:s3:::private-bucket/personal.txt").unwrap(),
124 context,
125 );
126
127 match evaluate_policy(&condition_policy, &condition_request)? {
128 Decision::Allow => println!("✓ Condition satisfied - Access ALLOWED"),
129 Decision::Deny => println!("✗ Access DENIED"),
130 Decision::NotApplicable => println!("? Condition not satisfied"),
131 }
132 println!();
133
134 // Example 5: Failed Condition
135 println!("5. Failed Condition:");
136 let mut wrong_context = Context::new();
137 wrong_context.insert(
138 "aws:userid".to_string(),
139 ContextValue::String("bob".to_string()),
140 );
141
142 let failed_condition_request = IAMRequest::new_with_context(
143 Principal::Aws(PrincipalId::String(
144 "arn:aws:iam::123456789012:user/bob".to_string(),
145 )),
146 "s3:GetObject",
147 Arn::parse("arn:aws:s3:::private-bucket/personal.txt").unwrap(),
148 wrong_context,
149 );
150
151 match evaluate_policy(&condition_policy, &failed_condition_request)? {
152 Decision::Allow => println!("✓ Access ALLOWED"),
153 Decision::Deny => println!("✗ Access DENIED"),
154 Decision::NotApplicable => println!("? Condition failed - No applicable policy"),
155 }
156 println!();
157
158 // Example 6: Explicit Deny Overrides Allow
159 println!("6. Explicit Deny Overrides Allow:");
160 let combined_policies = vec![
161 IAMPolicy::new()
162 .with_id("550e8400-e29b-41d4-a716-446655440004")
163 .add_statement(
164 IAMStatement::new(IAMEffect::Allow)
165 .with_sid("AllowAll")
166 .with_action(IAMAction::Single("s3:*".to_string()))
167 .with_resource(IAMResource::Single("*".to_string())),
168 ),
169 IAMPolicy::new()
170 .with_id("550e8400-e29b-41d4-a716-446655440005")
171 .add_statement(
172 IAMStatement::new(IAMEffect::Deny)
173 .with_sid("DenyProtected")
174 .with_action(IAMAction::Single("s3:DeleteObject".to_string()))
175 .with_resource(IAMResource::Single(
176 "arn:aws:s3:::protected-bucket/*".to_string(),
177 )),
178 ),
179 ];
180
181 let evaluator = PolicyEvaluator::with_policies(combined_policies);
182 let protected_request = IAMRequest::new(
183 Principal::Aws(PrincipalId::String(
184 "arn:aws:iam::123456789012:user/alice".to_string(),
185 )),
186 "s3:DeleteObject",
187 Arn::parse("arn:aws:s3:::protected-bucket/critical.txt").unwrap(),
188 );
189
190 match evaluator.evaluate(&protected_request)?.decision {
191 Decision::Allow => println!("✓ Access ALLOWED"),
192 Decision::Deny => println!("✗ Explicit DENY overrides Allow"),
193 Decision::NotApplicable => println!("? No applicable policy"),
194 }
195 println!();
196
197 // Example 7: Numeric Condition
198 println!("7. Numeric Condition:");
199 let mut numeric_context = Context::new();
200 numeric_context.insert("aws:RequestCount".to_string(), ContextValue::Number(5.0));
201
202 let numeric_policy = IAMPolicy::new()
203 .with_id("550e8400-e29b-41d4-a716-446655440006")
204 .add_statement(
205 IAMStatement::new(IAMEffect::Allow)
206 .with_sid("AllowLimitedRequests")
207 .with_action(IAMAction::Single("s3:GetObject".to_string()))
208 .with_resource(IAMResource::Single("*".to_string()))
209 .with_condition(
210 IAMOperator::NumericLessThan,
211 "aws:RequestCount".to_string(),
212 ConditionValue::Number(10),
213 ),
214 );
215
216 let numeric_request = IAMRequest::new_with_context(
217 Principal::Aws(PrincipalId::String(
218 "arn:aws:iam::123456789012:user/alice".to_string(),
219 )),
220 "s3:GetObject",
221 Arn::parse("arn:aws:s3:::any-bucket/file.txt").unwrap(),
222 numeric_context,
223 );
224
225 match evaluate_policy(&numeric_policy, &numeric_request)? {
226 Decision::Allow => println!("✓ Numeric condition satisfied - Access ALLOWED"),
227 Decision::Deny => println!("✗ Access DENIED"),
228 Decision::NotApplicable => println!("? Numeric condition failed"),
229 }
230 println!();
231
232 // Example 8: Detailed Evaluation with Options
233 println!("8. Detailed Evaluation with Options:");
234 let detailed_evaluator = PolicyEvaluator::with_policies(vec![allow_policy.clone()])
235 .with_options(EvaluationOptions {
236 collect_match_details: true,
237 stop_on_explicit_deny: false,
238 max_statements: 100,
239 ignore_resource_constraints: false,
240 });
241
242 let detailed_result = detailed_evaluator.evaluate(&request)?;
243 println!("Decision: {:?}", detailed_result.decision);
244 println!("Matched Statements:");
245 for (i, statement_match) in detailed_result.matched_statements.iter().enumerate() {
246 println!(
247 " {}. SID: {:?}, Effect: {:?}, Satisfied: {}, Reason: {}",
248 i + 1,
249 statement_match.sid,
250 statement_match.effect,
251 statement_match.conditions_satisfied,
252 statement_match.reason
253 );
254 }
255 println!();
256
257 // Example 9: No Applicable Policy (Implicit Deny)
258 println!("9. No Applicable Policy (Implicit Deny):");
259 let unrelated_request = IAMRequest::new(
260 Principal::Aws(PrincipalId::String(
261 "arn:aws:iam::123456789012:user/alice".to_string(),
262 )),
263 "ec2:DescribeInstances",
264 Arn::parse("arn:aws:ec2:us-east-1:123456789012:instance/*").unwrap(),
265 );
266
267 match evaluate_policy(&allow_policy, &unrelated_request)? {
268 Decision::Allow => println!("✓ Access ALLOWED"),
269 Decision::Deny => println!("✗ Access DENIED"),
270 Decision::NotApplicable => println!("? No applicable policy - Implicit DENY"),
271 }
272 println!();
273
274 // Example 10: Resource Pattern Matching
275 println!("10. Resource Pattern Matching:");
276 let pattern_policy = IAMPolicy::new()
277 .with_id("550e8400-e29b-41d4-a716-446655440007")
278 .add_statement(
279 IAMStatement::new(IAMEffect::Allow)
280 .with_sid("AllowBucketAccess")
281 .with_action(IAMAction::Multiple(vec![
282 "s3:GetObject".to_string(),
283 "s3:PutObject".to_string(),
284 ]))
285 .with_resource(IAMResource::Single(
286 "arn:aws:s3:::user-data-*/*".to_string(),
287 )),
288 );
289
290 let pattern_request = IAMRequest::new(
291 Principal::Aws(PrincipalId::String(
292 "arn:aws:iam::123456789012:user/alice".to_string(),
293 )),
294 "s3:GetObject",
295 Arn::parse("arn:aws:s3:::user-data-alice/profile.json").unwrap(),
296 );
297
298 match evaluate_policy(&pattern_policy, &pattern_request)? {
299 Decision::Allow => println!("✓ Resource pattern matched - Access ALLOWED"),
300 Decision::Deny => println!("✗ Access DENIED"),
301 Decision::NotApplicable => println!("? Resource pattern didn't match"),
302 }
303
304 println!("\n=== Policy Evaluation Demo Complete ===");
305 println!("\nThe Policy Evaluation Engine successfully:");
306 println!("• ✅ Evaluates Allow/Deny effects");
307 println!("• ✅ Handles wildcard actions and resources");
308 println!("• ✅ Processes condition blocks with various operators");
309 println!("• ✅ Implements proper IAM logic (explicit deny overrides)");
310 println!("• ✅ Supports detailed evaluation with match information");
311 println!("• ✅ Handles multiple policies with complex interactions");
312 println!("• ✅ Provides clear Allow/Deny/NotApplicable decisions");
313
314 Ok(())
315}
Trait Implementations§
Source§impl Clone for IAMRequest
impl Clone for IAMRequest
Source§fn clone(&self) -> IAMRequest
fn clone(&self) -> IAMRequest
Returns a duplicate of the value. Read more
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source
. Read moreSource§impl Debug for IAMRequest
impl Debug for IAMRequest
Source§impl<'de> Deserialize<'de> for IAMRequest
impl<'de> Deserialize<'de> for IAMRequest
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read more
Source§impl PartialEq for IAMRequest
impl PartialEq for IAMRequest
Source§impl Serialize for IAMRequest
impl Serialize for IAMRequest
impl StructuralPartialEq for IAMRequest
Auto Trait Implementations§
impl Freeze for IAMRequest
impl RefUnwindSafe for IAMRequest
impl Send for IAMRequest
impl Sync for IAMRequest
impl Unpin for IAMRequest
impl UnwindSafe for IAMRequest
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more