pub trait Validate {
// Required method
fn validate(&self, context: &mut ValidationContext) -> ValidationResult;
// Provided methods
fn is_valid(&self) -> bool { ... }
fn validate_result(&self) -> ValidationResult { ... }
}
Expand description
Trait for validating IAM policy components All validation is strict and enforces high quality standards
Required Methods§
Sourcefn validate(&self, context: &mut ValidationContext) -> ValidationResult
fn validate(&self, context: &mut ValidationContext) -> ValidationResult
Validate the component within the given context
§Errors
Returns ValidationError
if the component is invalid
Provided Methods§
Sourcefn is_valid(&self) -> bool
fn is_valid(&self) -> bool
Convenience method for basic validation
Examples found in repository?
examples/validation_demo.rs (line 25)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7 println!("=== IAM Policy Validation Demo ===\n");
8
9 // Example 1: Valid Policy
10 println!("1. Valid Policy Validation:");
11 let valid_policy = IAMPolicy::new()
12 .with_id("550e8400-e29b-41d4-a716-446655440000")
13 .add_statement(
14 IAMStatement::new(IAMEffect::Allow)
15 .with_sid("AllowS3Read")
16 .with_action(IAMAction::Single("s3:GetObject".to_string()))
17 .with_resource(IAMResource::Single("arn:aws:s3:::my-bucket/*".to_string()))
18 .with_condition(
19 IAMOperator::StringEquals,
20 "aws:PrincipalTag/department".to_string(),
21 ConditionValue::String("engineering".to_string()),
22 ),
23 );
24
25 if valid_policy.is_valid() {
26 println!("✓ Policy is valid!");
27 } else {
28 println!("✗ Policy is invalid");
29 }
30
31 match valid_policy.validate_result() {
32 Ok(()) => println!("✓ Policy passes validation"),
33 Err(e) => println!("✗ Policy fails validation: {}", e),
34 }
35
36 println!();
37
38 // Example 2: Invalid Policy - Missing Required Fields
39 println!("2. Invalid Policy - Missing Required Fields:");
40 let invalid_policy = IAMPolicy::new().add_statement(IAMStatement::new(IAMEffect::Allow)); // Missing action and resource
41
42 if !invalid_policy.is_valid() {
43 println!("✗ Policy is invalid (as expected)");
44 match invalid_policy.validate_result() {
45 Err(e) => println!(" Validation errors: {}", e),
46 Ok(()) => println!(" Unexpected: validation passed"),
47 }
48 }
49
50 println!();
51
52 // Example 3: Policy with Multiple Validation Errors
53 println!("3. Policy with Multiple Validation Errors:");
54 let multi_error_policy = IAMPolicy::new()
55 .with_id("") // Empty ID
56 .add_statement(
57 IAMStatement::new(IAMEffect::Allow)
58 .with_action(IAMAction::Single("invalid-action".to_string())) // Invalid action format
59 .with_resource(IAMResource::Single("invalid-resource".to_string())), // Invalid resource
60 )
61 .add_statement(
62 IAMStatement::new(IAMEffect::Allow)
63 .with_sid("DuplicateId")
64 .with_action(IAMAction::Single("s3:GetObject".to_string()))
65 .with_resource(IAMResource::Single("*".to_string())),
66 )
67 .add_statement(
68 IAMStatement::new(IAMEffect::Deny)
69 .with_sid("DuplicateId") // Duplicate SID
70 .with_action(IAMAction::Single("s3:DeleteObject".to_string()))
71 .with_resource(IAMResource::Single("*".to_string())),
72 );
73
74 match multi_error_policy.validate_result() {
75 Err(ValidationError::Multiple(errors)) => {
76 println!("✗ Found {} validation errors:", errors.len());
77 for (i, error) in errors.iter().enumerate() {
78 println!(" {}. {}", i + 1, error);
79 }
80 }
81 Err(e) => {
82 println!("✗ Single validation error: {}", e);
83 }
84 Ok(()) => {
85 println!("✓ Unexpected: validation passed");
86 }
87 }
88
89 println!();
90
91 // Example 4: Comprehensive Validation
92 println!("4. Comprehensive Validation:");
93 let comprehensive_policy = IAMPolicy::new()
94 .with_id("short") // Short ID - will fail validation
95 .add_statement(
96 IAMStatement::new(IAMEffect::Allow)
97 .with_action(IAMAction::Single("s3:GetObject".to_string()))
98 .with_resource(IAMResource::Single("*".to_string()))
99 .with_condition(
100 IAMOperator::NumericEquals,
101 "aws:RequestedRegion".to_string(),
102 ConditionValue::String("not-a-number".to_string()), // Numeric operator with string value - will fail
103 ),
104 );
105
106 match comprehensive_policy.validate_result() {
107 Ok(()) => println!("✓ Policy passes validation"),
108 Err(e) => println!("✗ Policy fails validation: {}", e),
109 }
110
111 println!();
112
113 // Example 5: Logical Policy Errors
114 println!("5. Logical Policy Errors:");
115
116 // NotPrincipal with Allow effect (invalid)
117 let mut logical_error_policy = IAMStatement::new(IAMEffect::Allow);
118 logical_error_policy.action = Some(IAMAction::Single("s3:GetObject".to_string()));
119 logical_error_policy.resource = Some(IAMResource::Single("*".to_string()));
120 logical_error_policy.not_principal = Some(Principal::Aws(iam_rs::PrincipalId::String(
121 "arn:aws:iam::123456789012:user/test".to_string(),
122 )));
123
124 match logical_error_policy.validate_result() {
125 Err(e) => println!("✗ Logical error detected: {}", e),
126 Ok(()) => println!("✓ Unexpected: validation passed"),
127 }
128
129 // Both Action and NotAction (invalid)
130 let mut conflicting_statement = IAMStatement::new(IAMEffect::Allow);
131 conflicting_statement.action = Some(IAMAction::Single("s3:GetObject".to_string()));
132 conflicting_statement.not_action = Some(IAMAction::Single("s3:PutObject".to_string()));
133 conflicting_statement.resource = Some(IAMResource::Single("*".to_string()));
134
135 match conflicting_statement.validate_result() {
136 Err(e) => println!("✗ Logical error detected: {}", e),
137 Ok(()) => println!("✓ Unexpected: validation passed"),
138 }
139
140 println!();
141
142 // Example 6: Component Validation
143 println!("6. Individual Component Validation:");
144
145 // Invalid action
146 let invalid_action = IAMAction::Single("invalid-action".to_string());
147 match invalid_action.validate_result() {
148 Err(e) => println!("✗ Invalid action: {}", e),
149 Ok(()) => println!("✓ Action is valid"),
150 }
151
152 // Invalid principal
153 let invalid_principal = Principal::Aws(PrincipalId::String("invalid-principal".to_string()));
154 match invalid_principal.validate_result() {
155 Err(e) => println!("✗ Invalid principal: {}", e),
156 Ok(()) => println!("✓ Principal is valid"),
157 }
158
159 // Valid service principal
160 let service_principal =
161 Principal::Service(PrincipalId::String("lambda.amazonaws.com".to_string()));
162 if service_principal.is_valid() {
163 println!("✓ Service principal is valid");
164 } else {
165 println!("✗ Service principal is invalid");
166 }
167
168 println!("\n=== Validation Demo Complete ===");
169
170 Ok(())
171}
Sourcefn validate_result(&self) -> ValidationResult
fn validate_result(&self) -> ValidationResult
Validate with detailed errors (same as regular validation)
§Errors
Returns ValidationError
if the component is invalid
Examples found in repository?
examples/validation_demo.rs (line 31)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7 println!("=== IAM Policy Validation Demo ===\n");
8
9 // Example 1: Valid Policy
10 println!("1. Valid Policy Validation:");
11 let valid_policy = IAMPolicy::new()
12 .with_id("550e8400-e29b-41d4-a716-446655440000")
13 .add_statement(
14 IAMStatement::new(IAMEffect::Allow)
15 .with_sid("AllowS3Read")
16 .with_action(IAMAction::Single("s3:GetObject".to_string()))
17 .with_resource(IAMResource::Single("arn:aws:s3:::my-bucket/*".to_string()))
18 .with_condition(
19 IAMOperator::StringEquals,
20 "aws:PrincipalTag/department".to_string(),
21 ConditionValue::String("engineering".to_string()),
22 ),
23 );
24
25 if valid_policy.is_valid() {
26 println!("✓ Policy is valid!");
27 } else {
28 println!("✗ Policy is invalid");
29 }
30
31 match valid_policy.validate_result() {
32 Ok(()) => println!("✓ Policy passes validation"),
33 Err(e) => println!("✗ Policy fails validation: {}", e),
34 }
35
36 println!();
37
38 // Example 2: Invalid Policy - Missing Required Fields
39 println!("2. Invalid Policy - Missing Required Fields:");
40 let invalid_policy = IAMPolicy::new().add_statement(IAMStatement::new(IAMEffect::Allow)); // Missing action and resource
41
42 if !invalid_policy.is_valid() {
43 println!("✗ Policy is invalid (as expected)");
44 match invalid_policy.validate_result() {
45 Err(e) => println!(" Validation errors: {}", e),
46 Ok(()) => println!(" Unexpected: validation passed"),
47 }
48 }
49
50 println!();
51
52 // Example 3: Policy with Multiple Validation Errors
53 println!("3. Policy with Multiple Validation Errors:");
54 let multi_error_policy = IAMPolicy::new()
55 .with_id("") // Empty ID
56 .add_statement(
57 IAMStatement::new(IAMEffect::Allow)
58 .with_action(IAMAction::Single("invalid-action".to_string())) // Invalid action format
59 .with_resource(IAMResource::Single("invalid-resource".to_string())), // Invalid resource
60 )
61 .add_statement(
62 IAMStatement::new(IAMEffect::Allow)
63 .with_sid("DuplicateId")
64 .with_action(IAMAction::Single("s3:GetObject".to_string()))
65 .with_resource(IAMResource::Single("*".to_string())),
66 )
67 .add_statement(
68 IAMStatement::new(IAMEffect::Deny)
69 .with_sid("DuplicateId") // Duplicate SID
70 .with_action(IAMAction::Single("s3:DeleteObject".to_string()))
71 .with_resource(IAMResource::Single("*".to_string())),
72 );
73
74 match multi_error_policy.validate_result() {
75 Err(ValidationError::Multiple(errors)) => {
76 println!("✗ Found {} validation errors:", errors.len());
77 for (i, error) in errors.iter().enumerate() {
78 println!(" {}. {}", i + 1, error);
79 }
80 }
81 Err(e) => {
82 println!("✗ Single validation error: {}", e);
83 }
84 Ok(()) => {
85 println!("✓ Unexpected: validation passed");
86 }
87 }
88
89 println!();
90
91 // Example 4: Comprehensive Validation
92 println!("4. Comprehensive Validation:");
93 let comprehensive_policy = IAMPolicy::new()
94 .with_id("short") // Short ID - will fail validation
95 .add_statement(
96 IAMStatement::new(IAMEffect::Allow)
97 .with_action(IAMAction::Single("s3:GetObject".to_string()))
98 .with_resource(IAMResource::Single("*".to_string()))
99 .with_condition(
100 IAMOperator::NumericEquals,
101 "aws:RequestedRegion".to_string(),
102 ConditionValue::String("not-a-number".to_string()), // Numeric operator with string value - will fail
103 ),
104 );
105
106 match comprehensive_policy.validate_result() {
107 Ok(()) => println!("✓ Policy passes validation"),
108 Err(e) => println!("✗ Policy fails validation: {}", e),
109 }
110
111 println!();
112
113 // Example 5: Logical Policy Errors
114 println!("5. Logical Policy Errors:");
115
116 // NotPrincipal with Allow effect (invalid)
117 let mut logical_error_policy = IAMStatement::new(IAMEffect::Allow);
118 logical_error_policy.action = Some(IAMAction::Single("s3:GetObject".to_string()));
119 logical_error_policy.resource = Some(IAMResource::Single("*".to_string()));
120 logical_error_policy.not_principal = Some(Principal::Aws(iam_rs::PrincipalId::String(
121 "arn:aws:iam::123456789012:user/test".to_string(),
122 )));
123
124 match logical_error_policy.validate_result() {
125 Err(e) => println!("✗ Logical error detected: {}", e),
126 Ok(()) => println!("✓ Unexpected: validation passed"),
127 }
128
129 // Both Action and NotAction (invalid)
130 let mut conflicting_statement = IAMStatement::new(IAMEffect::Allow);
131 conflicting_statement.action = Some(IAMAction::Single("s3:GetObject".to_string()));
132 conflicting_statement.not_action = Some(IAMAction::Single("s3:PutObject".to_string()));
133 conflicting_statement.resource = Some(IAMResource::Single("*".to_string()));
134
135 match conflicting_statement.validate_result() {
136 Err(e) => println!("✗ Logical error detected: {}", e),
137 Ok(()) => println!("✓ Unexpected: validation passed"),
138 }
139
140 println!();
141
142 // Example 6: Component Validation
143 println!("6. Individual Component Validation:");
144
145 // Invalid action
146 let invalid_action = IAMAction::Single("invalid-action".to_string());
147 match invalid_action.validate_result() {
148 Err(e) => println!("✗ Invalid action: {}", e),
149 Ok(()) => println!("✓ Action is valid"),
150 }
151
152 // Invalid principal
153 let invalid_principal = Principal::Aws(PrincipalId::String("invalid-principal".to_string()));
154 match invalid_principal.validate_result() {
155 Err(e) => println!("✗ Invalid principal: {}", e),
156 Ok(()) => println!("✓ Principal is valid"),
157 }
158
159 // Valid service principal
160 let service_principal =
161 Principal::Service(PrincipalId::String("lambda.amazonaws.com".to_string()));
162 if service_principal.is_valid() {
163 println!("✓ Service principal is valid");
164 } else {
165 println!("✗ Service principal is invalid");
166 }
167
168 println!("\n=== Validation Demo Complete ===");
169
170 Ok(())
171}