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