Validate

Trait Validate 

Source
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§

Source

fn validate(&self, context: &mut ValidationContext) -> ValidationResult

Validate the component within the given context

§Errors

Returns ValidationError if the component is invalid

Provided Methods§

Source

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}
Source

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}

Implementors§