Struct Arn

Source
pub struct Arn {
    pub partition: String,
    pub service: String,
    pub region: String,
    pub account_id: String,
    pub resource: String,
}
Expand description

Represents an Amazon Resource Name (ARN)

ARNs uniquely identify AWS resources. The general format is: arn:partition:service:region:account-id:resource-type/resource-id

Some services use slightly different formats:

  • arn:partition:service:region:account-id:resource-type:resource-id
  • arn:partition:service:region:account-id:resource-type/resource-id/sub-resource

Fields§

§partition: String

The partition (e.g., “aws”, “aws-cn”, “aws-us-gov”)

§service: String

The service namespace (e.g., “s3”, “ec2”, “iam”)

§region: String

The region (e.g., “us-east-1”, can be empty for global services)

§account_id: String

The account ID (12-digit number, can be empty for some services)

§resource: String

The resource specification (format varies by service)

Implementations§

Source§

impl Arn

Source

pub fn parse(arn_str: &str) -> Result<Self, ArnError>

Parse an ARN string into an Arn struct This method is extremely lenient and only validates bare format requirements. Use is_valid() to perform comprehensive validation.

Examples found in repository?
examples/arn_demo.rs (line 19)
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4    println!("=== IAM ARN Validator Demo ===\n");
5
6    // Example 1: Parse and validate ARNs
7    println!("1. Parsing and validating ARNs:");
8
9    let valid_arns = vec![
10        "arn:aws:s3:::my-bucket/folder/file.txt",
11        "arn:aws:iam::123456789012:user/alice",
12        "arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0",
13        "arn:aws:lambda:us-east-1:123456789012:function:MyFunction",
14        "arn:aws:dynamodb:us-east-1:123456789012:table/MyTable",
15        "arn:aws-eu-gov:dynamodb:us-east-1:123456789012:table/MyTable",
16    ];
17
18    for arn_str in &valid_arns {
19        match Arn::parse(arn_str) {
20            Ok(arn) => {
21                println!("✓ Valid ARN: {}", arn);
22                println!("  - Service: {}", arn.service);
23                println!(
24                    "  - Region: {}",
25                    if arn.region.is_empty() {
26                        "global"
27                    } else {
28                        &arn.region
29                    }
30                );
31                println!(
32                    "  - Account: {}",
33                    if arn.account_id.is_empty() {
34                        "none"
35                    } else {
36                        &arn.account_id
37                    }
38                );
39                if let Some(resource_type) = arn.resource_type() {
40                    println!("  - Resource Type: {}", resource_type);
41                }
42                if let Some(resource_id) = arn.resource_id() {
43                    println!("  - Resource ID: {}", resource_id);
44                }
45                println!();
46            }
47            Err(e) => println!("✗ Invalid ARN {}: {}", arn_str, e),
48        }
49    }
50
51    // Example 2: Wildcard matching
52    println!("2. Wildcard pattern matching:");
53
54    let resource_arn = Arn::parse("arn:aws:s3:::my-bucket/uploads/user123/document.pdf")?;
55    println!("Resource ARN: {}", resource_arn);
56
57    let patterns = vec![
58        "arn:aws:s3:::my-bucket/*",
59        "arn:aws:s3:::my-bucket/uploads/*",
60        "arn:aws:s3:::my-bucket/uploads/user123/*",
61        "arn:aws:s3:::*/uploads/user123/document.pdf",
62        "arn:aws:s3:::my-bucket/uploads/*/document.pdf",
63        "arn:aws:s3:::my-bucket/uploads/user???/document.pdf",
64        "arn:aws:s3:::other-bucket/*",
65        "arn:aws:ec2:*:*:instance/*",
66    ];
67
68    for pattern in &patterns {
69        match resource_arn.matches(pattern) {
70            Ok(matches) => {
71                let status = if matches { "✓ MATCH" } else { "✗ NO MATCH" };
72                println!("  {} Pattern: {}", status, pattern);
73            }
74            Err(e) => println!("  ✗ ERROR Pattern: {} ({})", pattern, e),
75        }
76    }
77
78    // Example 3: Integration with IAM policies
79    println!("\n3. Using ARNs in IAM policies:");
80
81    let policy = IAMPolicy::new()
82        .with_id("s3-access-policy")
83        .add_statement(
84            IAMStatement::new(Effect::Allow)
85                .with_sid("AllowS3Read")
86                .with_action(Action::Multiple(vec![
87                    "s3:GetObject".to_string(),
88                    "s3:ListBucket".to_string(),
89                ]))
90                .with_resource(Resource::Multiple(vec![
91                    "arn:aws:s3:::my-bucket".to_string(),
92                    "arn:aws:s3:::my-bucket/*".to_string(),
93                ])),
94        )
95        .add_statement(
96            IAMStatement::new(Effect::Allow)
97                .with_sid("AllowS3Write")
98                .with_action(Action::Single("s3:PutObject".to_string()))
99                .with_resource(Resource::Single(
100                    "arn:aws:s3:::my-bucket/uploads/*".to_string(),
101                )),
102        );
103
104    let policy_json = policy.to_json()?;
105    println!("Generated IAM Policy:");
106    println!("{}", policy_json);
107
108    // Example 4: Validate all ARNs in the policy
109    println!("\n4. Validating ARNs in policy:");
110
111    for (i, statement) in policy.statement.iter().enumerate() {
112        println!(
113            "Statement {}: {}",
114            i + 1,
115            statement.sid.as_ref().unwrap_or(&"(no sid)".to_string())
116        );
117
118        let resources = match &statement.resource {
119            Some(Resource::Single(arn)) => vec![arn.clone()],
120            Some(Resource::Multiple(arns)) => arns.clone(),
121            None => vec![],
122        };
123
124        for resource in resources {
125            match Arn::parse(&resource) {
126                Ok(arn) => {
127                    let validity = if arn.is_valid() {
128                        "✓ Valid"
129                    } else {
130                        "⚠ Invalid"
131                    };
132                    println!("  {} Resource: {}", validity, resource);
133                }
134                Err(e) => println!("  ✗ Parse Error: {} ({})", resource, e),
135            }
136        }
137    }
138
139    Ok(())
140}
Source

pub fn to_string(&self) -> String

Convert the ARN back to string format

Source

pub fn matches(&self, pattern: &str) -> Result<bool, ArnError>

Check if this ARN matches another ARN or pattern Supports wildcards (* and ?) in any component except service

Examples found in repository?
examples/arn_demo.rs (line 69)
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4    println!("=== IAM ARN Validator Demo ===\n");
5
6    // Example 1: Parse and validate ARNs
7    println!("1. Parsing and validating ARNs:");
8
9    let valid_arns = vec![
10        "arn:aws:s3:::my-bucket/folder/file.txt",
11        "arn:aws:iam::123456789012:user/alice",
12        "arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0",
13        "arn:aws:lambda:us-east-1:123456789012:function:MyFunction",
14        "arn:aws:dynamodb:us-east-1:123456789012:table/MyTable",
15        "arn:aws-eu-gov:dynamodb:us-east-1:123456789012:table/MyTable",
16    ];
17
18    for arn_str in &valid_arns {
19        match Arn::parse(arn_str) {
20            Ok(arn) => {
21                println!("✓ Valid ARN: {}", arn);
22                println!("  - Service: {}", arn.service);
23                println!(
24                    "  - Region: {}",
25                    if arn.region.is_empty() {
26                        "global"
27                    } else {
28                        &arn.region
29                    }
30                );
31                println!(
32                    "  - Account: {}",
33                    if arn.account_id.is_empty() {
34                        "none"
35                    } else {
36                        &arn.account_id
37                    }
38                );
39                if let Some(resource_type) = arn.resource_type() {
40                    println!("  - Resource Type: {}", resource_type);
41                }
42                if let Some(resource_id) = arn.resource_id() {
43                    println!("  - Resource ID: {}", resource_id);
44                }
45                println!();
46            }
47            Err(e) => println!("✗ Invalid ARN {}: {}", arn_str, e),
48        }
49    }
50
51    // Example 2: Wildcard matching
52    println!("2. Wildcard pattern matching:");
53
54    let resource_arn = Arn::parse("arn:aws:s3:::my-bucket/uploads/user123/document.pdf")?;
55    println!("Resource ARN: {}", resource_arn);
56
57    let patterns = vec![
58        "arn:aws:s3:::my-bucket/*",
59        "arn:aws:s3:::my-bucket/uploads/*",
60        "arn:aws:s3:::my-bucket/uploads/user123/*",
61        "arn:aws:s3:::*/uploads/user123/document.pdf",
62        "arn:aws:s3:::my-bucket/uploads/*/document.pdf",
63        "arn:aws:s3:::my-bucket/uploads/user???/document.pdf",
64        "arn:aws:s3:::other-bucket/*",
65        "arn:aws:ec2:*:*:instance/*",
66    ];
67
68    for pattern in &patterns {
69        match resource_arn.matches(pattern) {
70            Ok(matches) => {
71                let status = if matches { "✓ MATCH" } else { "✗ NO MATCH" };
72                println!("  {} Pattern: {}", status, pattern);
73            }
74            Err(e) => println!("  ✗ ERROR Pattern: {} ({})", pattern, e),
75        }
76    }
77
78    // Example 3: Integration with IAM policies
79    println!("\n3. Using ARNs in IAM policies:");
80
81    let policy = IAMPolicy::new()
82        .with_id("s3-access-policy")
83        .add_statement(
84            IAMStatement::new(Effect::Allow)
85                .with_sid("AllowS3Read")
86                .with_action(Action::Multiple(vec![
87                    "s3:GetObject".to_string(),
88                    "s3:ListBucket".to_string(),
89                ]))
90                .with_resource(Resource::Multiple(vec![
91                    "arn:aws:s3:::my-bucket".to_string(),
92                    "arn:aws:s3:::my-bucket/*".to_string(),
93                ])),
94        )
95        .add_statement(
96            IAMStatement::new(Effect::Allow)
97                .with_sid("AllowS3Write")
98                .with_action(Action::Single("s3:PutObject".to_string()))
99                .with_resource(Resource::Single(
100                    "arn:aws:s3:::my-bucket/uploads/*".to_string(),
101                )),
102        );
103
104    let policy_json = policy.to_json()?;
105    println!("Generated IAM Policy:");
106    println!("{}", policy_json);
107
108    // Example 4: Validate all ARNs in the policy
109    println!("\n4. Validating ARNs in policy:");
110
111    for (i, statement) in policy.statement.iter().enumerate() {
112        println!(
113            "Statement {}: {}",
114            i + 1,
115            statement.sid.as_ref().unwrap_or(&"(no sid)".to_string())
116        );
117
118        let resources = match &statement.resource {
119            Some(Resource::Single(arn)) => vec![arn.clone()],
120            Some(Resource::Multiple(arns)) => arns.clone(),
121            None => vec![],
122        };
123
124        for resource in resources {
125            match Arn::parse(&resource) {
126                Ok(arn) => {
127                    let validity = if arn.is_valid() {
128                        "✓ Valid"
129                    } else {
130                        "⚠ Invalid"
131                    };
132                    println!("  {} Resource: {}", validity, resource);
133                }
134                Err(e) => println!("  ✗ Parse Error: {} ({})", resource, e),
135            }
136        }
137    }
138
139    Ok(())
140}
Source

pub fn wildcard_match(text: &str, pattern: &str) -> bool

Check if a string matches a pattern with wildcards

  • matches any sequence of characters ? matches any single character
Source

pub fn is_valid(&self) -> bool

Check if this ARN is valid according to AWS ARN rules

Examples found in repository?
examples/arn_demo.rs (line 127)
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4    println!("=== IAM ARN Validator Demo ===\n");
5
6    // Example 1: Parse and validate ARNs
7    println!("1. Parsing and validating ARNs:");
8
9    let valid_arns = vec![
10        "arn:aws:s3:::my-bucket/folder/file.txt",
11        "arn:aws:iam::123456789012:user/alice",
12        "arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0",
13        "arn:aws:lambda:us-east-1:123456789012:function:MyFunction",
14        "arn:aws:dynamodb:us-east-1:123456789012:table/MyTable",
15        "arn:aws-eu-gov:dynamodb:us-east-1:123456789012:table/MyTable",
16    ];
17
18    for arn_str in &valid_arns {
19        match Arn::parse(arn_str) {
20            Ok(arn) => {
21                println!("✓ Valid ARN: {}", arn);
22                println!("  - Service: {}", arn.service);
23                println!(
24                    "  - Region: {}",
25                    if arn.region.is_empty() {
26                        "global"
27                    } else {
28                        &arn.region
29                    }
30                );
31                println!(
32                    "  - Account: {}",
33                    if arn.account_id.is_empty() {
34                        "none"
35                    } else {
36                        &arn.account_id
37                    }
38                );
39                if let Some(resource_type) = arn.resource_type() {
40                    println!("  - Resource Type: {}", resource_type);
41                }
42                if let Some(resource_id) = arn.resource_id() {
43                    println!("  - Resource ID: {}", resource_id);
44                }
45                println!();
46            }
47            Err(e) => println!("✗ Invalid ARN {}: {}", arn_str, e),
48        }
49    }
50
51    // Example 2: Wildcard matching
52    println!("2. Wildcard pattern matching:");
53
54    let resource_arn = Arn::parse("arn:aws:s3:::my-bucket/uploads/user123/document.pdf")?;
55    println!("Resource ARN: {}", resource_arn);
56
57    let patterns = vec![
58        "arn:aws:s3:::my-bucket/*",
59        "arn:aws:s3:::my-bucket/uploads/*",
60        "arn:aws:s3:::my-bucket/uploads/user123/*",
61        "arn:aws:s3:::*/uploads/user123/document.pdf",
62        "arn:aws:s3:::my-bucket/uploads/*/document.pdf",
63        "arn:aws:s3:::my-bucket/uploads/user???/document.pdf",
64        "arn:aws:s3:::other-bucket/*",
65        "arn:aws:ec2:*:*:instance/*",
66    ];
67
68    for pattern in &patterns {
69        match resource_arn.matches(pattern) {
70            Ok(matches) => {
71                let status = if matches { "✓ MATCH" } else { "✗ NO MATCH" };
72                println!("  {} Pattern: {}", status, pattern);
73            }
74            Err(e) => println!("  ✗ ERROR Pattern: {} ({})", pattern, e),
75        }
76    }
77
78    // Example 3: Integration with IAM policies
79    println!("\n3. Using ARNs in IAM policies:");
80
81    let policy = IAMPolicy::new()
82        .with_id("s3-access-policy")
83        .add_statement(
84            IAMStatement::new(Effect::Allow)
85                .with_sid("AllowS3Read")
86                .with_action(Action::Multiple(vec![
87                    "s3:GetObject".to_string(),
88                    "s3:ListBucket".to_string(),
89                ]))
90                .with_resource(Resource::Multiple(vec![
91                    "arn:aws:s3:::my-bucket".to_string(),
92                    "arn:aws:s3:::my-bucket/*".to_string(),
93                ])),
94        )
95        .add_statement(
96            IAMStatement::new(Effect::Allow)
97                .with_sid("AllowS3Write")
98                .with_action(Action::Single("s3:PutObject".to_string()))
99                .with_resource(Resource::Single(
100                    "arn:aws:s3:::my-bucket/uploads/*".to_string(),
101                )),
102        );
103
104    let policy_json = policy.to_json()?;
105    println!("Generated IAM Policy:");
106    println!("{}", policy_json);
107
108    // Example 4: Validate all ARNs in the policy
109    println!("\n4. Validating ARNs in policy:");
110
111    for (i, statement) in policy.statement.iter().enumerate() {
112        println!(
113            "Statement {}: {}",
114            i + 1,
115            statement.sid.as_ref().unwrap_or(&"(no sid)".to_string())
116        );
117
118        let resources = match &statement.resource {
119            Some(Resource::Single(arn)) => vec![arn.clone()],
120            Some(Resource::Multiple(arns)) => arns.clone(),
121            None => vec![],
122        };
123
124        for resource in resources {
125            match Arn::parse(&resource) {
126                Ok(arn) => {
127                    let validity = if arn.is_valid() {
128                        "✓ Valid"
129                    } else {
130                        "⚠ Invalid"
131                    };
132                    println!("  {} Resource: {}", validity, resource);
133                }
134                Err(e) => println!("  ✗ Parse Error: {} ({})", resource, e),
135            }
136        }
137    }
138
139    Ok(())
140}
Source

pub fn resource_type(&self) -> Option<&str>

Get the resource type from the resource string For resources like “bucket/object”, returns “bucket” For resources like “user/username”, returns “user”

Examples found in repository?
examples/arn_demo.rs (line 39)
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4    println!("=== IAM ARN Validator Demo ===\n");
5
6    // Example 1: Parse and validate ARNs
7    println!("1. Parsing and validating ARNs:");
8
9    let valid_arns = vec![
10        "arn:aws:s3:::my-bucket/folder/file.txt",
11        "arn:aws:iam::123456789012:user/alice",
12        "arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0",
13        "arn:aws:lambda:us-east-1:123456789012:function:MyFunction",
14        "arn:aws:dynamodb:us-east-1:123456789012:table/MyTable",
15        "arn:aws-eu-gov:dynamodb:us-east-1:123456789012:table/MyTable",
16    ];
17
18    for arn_str in &valid_arns {
19        match Arn::parse(arn_str) {
20            Ok(arn) => {
21                println!("✓ Valid ARN: {}", arn);
22                println!("  - Service: {}", arn.service);
23                println!(
24                    "  - Region: {}",
25                    if arn.region.is_empty() {
26                        "global"
27                    } else {
28                        &arn.region
29                    }
30                );
31                println!(
32                    "  - Account: {}",
33                    if arn.account_id.is_empty() {
34                        "none"
35                    } else {
36                        &arn.account_id
37                    }
38                );
39                if let Some(resource_type) = arn.resource_type() {
40                    println!("  - Resource Type: {}", resource_type);
41                }
42                if let Some(resource_id) = arn.resource_id() {
43                    println!("  - Resource ID: {}", resource_id);
44                }
45                println!();
46            }
47            Err(e) => println!("✗ Invalid ARN {}: {}", arn_str, e),
48        }
49    }
50
51    // Example 2: Wildcard matching
52    println!("2. Wildcard pattern matching:");
53
54    let resource_arn = Arn::parse("arn:aws:s3:::my-bucket/uploads/user123/document.pdf")?;
55    println!("Resource ARN: {}", resource_arn);
56
57    let patterns = vec![
58        "arn:aws:s3:::my-bucket/*",
59        "arn:aws:s3:::my-bucket/uploads/*",
60        "arn:aws:s3:::my-bucket/uploads/user123/*",
61        "arn:aws:s3:::*/uploads/user123/document.pdf",
62        "arn:aws:s3:::my-bucket/uploads/*/document.pdf",
63        "arn:aws:s3:::my-bucket/uploads/user???/document.pdf",
64        "arn:aws:s3:::other-bucket/*",
65        "arn:aws:ec2:*:*:instance/*",
66    ];
67
68    for pattern in &patterns {
69        match resource_arn.matches(pattern) {
70            Ok(matches) => {
71                let status = if matches { "✓ MATCH" } else { "✗ NO MATCH" };
72                println!("  {} Pattern: {}", status, pattern);
73            }
74            Err(e) => println!("  ✗ ERROR Pattern: {} ({})", pattern, e),
75        }
76    }
77
78    // Example 3: Integration with IAM policies
79    println!("\n3. Using ARNs in IAM policies:");
80
81    let policy = IAMPolicy::new()
82        .with_id("s3-access-policy")
83        .add_statement(
84            IAMStatement::new(Effect::Allow)
85                .with_sid("AllowS3Read")
86                .with_action(Action::Multiple(vec![
87                    "s3:GetObject".to_string(),
88                    "s3:ListBucket".to_string(),
89                ]))
90                .with_resource(Resource::Multiple(vec![
91                    "arn:aws:s3:::my-bucket".to_string(),
92                    "arn:aws:s3:::my-bucket/*".to_string(),
93                ])),
94        )
95        .add_statement(
96            IAMStatement::new(Effect::Allow)
97                .with_sid("AllowS3Write")
98                .with_action(Action::Single("s3:PutObject".to_string()))
99                .with_resource(Resource::Single(
100                    "arn:aws:s3:::my-bucket/uploads/*".to_string(),
101                )),
102        );
103
104    let policy_json = policy.to_json()?;
105    println!("Generated IAM Policy:");
106    println!("{}", policy_json);
107
108    // Example 4: Validate all ARNs in the policy
109    println!("\n4. Validating ARNs in policy:");
110
111    for (i, statement) in policy.statement.iter().enumerate() {
112        println!(
113            "Statement {}: {}",
114            i + 1,
115            statement.sid.as_ref().unwrap_or(&"(no sid)".to_string())
116        );
117
118        let resources = match &statement.resource {
119            Some(Resource::Single(arn)) => vec![arn.clone()],
120            Some(Resource::Multiple(arns)) => arns.clone(),
121            None => vec![],
122        };
123
124        for resource in resources {
125            match Arn::parse(&resource) {
126                Ok(arn) => {
127                    let validity = if arn.is_valid() {
128                        "✓ Valid"
129                    } else {
130                        "⚠ Invalid"
131                    };
132                    println!("  {} Resource: {}", validity, resource);
133                }
134                Err(e) => println!("  ✗ Parse Error: {} ({})", resource, e),
135            }
136        }
137    }
138
139    Ok(())
140}
Source

pub fn resource_id(&self) -> Option<&str>

Get the resource ID from the resource string For resources like “bucket/object”, returns “object” For resources like “user/username”, returns “username”

Examples found in repository?
examples/arn_demo.rs (line 42)
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4    println!("=== IAM ARN Validator Demo ===\n");
5
6    // Example 1: Parse and validate ARNs
7    println!("1. Parsing and validating ARNs:");
8
9    let valid_arns = vec![
10        "arn:aws:s3:::my-bucket/folder/file.txt",
11        "arn:aws:iam::123456789012:user/alice",
12        "arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0",
13        "arn:aws:lambda:us-east-1:123456789012:function:MyFunction",
14        "arn:aws:dynamodb:us-east-1:123456789012:table/MyTable",
15        "arn:aws-eu-gov:dynamodb:us-east-1:123456789012:table/MyTable",
16    ];
17
18    for arn_str in &valid_arns {
19        match Arn::parse(arn_str) {
20            Ok(arn) => {
21                println!("✓ Valid ARN: {}", arn);
22                println!("  - Service: {}", arn.service);
23                println!(
24                    "  - Region: {}",
25                    if arn.region.is_empty() {
26                        "global"
27                    } else {
28                        &arn.region
29                    }
30                );
31                println!(
32                    "  - Account: {}",
33                    if arn.account_id.is_empty() {
34                        "none"
35                    } else {
36                        &arn.account_id
37                    }
38                );
39                if let Some(resource_type) = arn.resource_type() {
40                    println!("  - Resource Type: {}", resource_type);
41                }
42                if let Some(resource_id) = arn.resource_id() {
43                    println!("  - Resource ID: {}", resource_id);
44                }
45                println!();
46            }
47            Err(e) => println!("✗ Invalid ARN {}: {}", arn_str, e),
48        }
49    }
50
51    // Example 2: Wildcard matching
52    println!("2. Wildcard pattern matching:");
53
54    let resource_arn = Arn::parse("arn:aws:s3:::my-bucket/uploads/user123/document.pdf")?;
55    println!("Resource ARN: {}", resource_arn);
56
57    let patterns = vec![
58        "arn:aws:s3:::my-bucket/*",
59        "arn:aws:s3:::my-bucket/uploads/*",
60        "arn:aws:s3:::my-bucket/uploads/user123/*",
61        "arn:aws:s3:::*/uploads/user123/document.pdf",
62        "arn:aws:s3:::my-bucket/uploads/*/document.pdf",
63        "arn:aws:s3:::my-bucket/uploads/user???/document.pdf",
64        "arn:aws:s3:::other-bucket/*",
65        "arn:aws:ec2:*:*:instance/*",
66    ];
67
68    for pattern in &patterns {
69        match resource_arn.matches(pattern) {
70            Ok(matches) => {
71                let status = if matches { "✓ MATCH" } else { "✗ NO MATCH" };
72                println!("  {} Pattern: {}", status, pattern);
73            }
74            Err(e) => println!("  ✗ ERROR Pattern: {} ({})", pattern, e),
75        }
76    }
77
78    // Example 3: Integration with IAM policies
79    println!("\n3. Using ARNs in IAM policies:");
80
81    let policy = IAMPolicy::new()
82        .with_id("s3-access-policy")
83        .add_statement(
84            IAMStatement::new(Effect::Allow)
85                .with_sid("AllowS3Read")
86                .with_action(Action::Multiple(vec![
87                    "s3:GetObject".to_string(),
88                    "s3:ListBucket".to_string(),
89                ]))
90                .with_resource(Resource::Multiple(vec![
91                    "arn:aws:s3:::my-bucket".to_string(),
92                    "arn:aws:s3:::my-bucket/*".to_string(),
93                ])),
94        )
95        .add_statement(
96            IAMStatement::new(Effect::Allow)
97                .with_sid("AllowS3Write")
98                .with_action(Action::Single("s3:PutObject".to_string()))
99                .with_resource(Resource::Single(
100                    "arn:aws:s3:::my-bucket/uploads/*".to_string(),
101                )),
102        );
103
104    let policy_json = policy.to_json()?;
105    println!("Generated IAM Policy:");
106    println!("{}", policy_json);
107
108    // Example 4: Validate all ARNs in the policy
109    println!("\n4. Validating ARNs in policy:");
110
111    for (i, statement) in policy.statement.iter().enumerate() {
112        println!(
113            "Statement {}: {}",
114            i + 1,
115            statement.sid.as_ref().unwrap_or(&"(no sid)".to_string())
116        );
117
118        let resources = match &statement.resource {
119            Some(Resource::Single(arn)) => vec![arn.clone()],
120            Some(Resource::Multiple(arns)) => arns.clone(),
121            None => vec![],
122        };
123
124        for resource in resources {
125            match Arn::parse(&resource) {
126                Ok(arn) => {
127                    let validity = if arn.is_valid() {
128                        "✓ Valid"
129                    } else {
130                        "⚠ Invalid"
131                    };
132                    println!("  {} Resource: {}", validity, resource);
133                }
134                Err(e) => println!("  ✗ Parse Error: {} ({})", resource, e),
135            }
136        }
137    }
138
139    Ok(())
140}

Trait Implementations§

Source§

impl Clone for Arn

Source§

fn clone(&self) -> Arn

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Arn

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Arn

Source§

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 Display for Arn

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl FromStr for Arn

Source§

type Err = ArnError

The associated error which can be returned from parsing.
Source§

fn from_str(s: &str) -> Result<Self, Self::Err>

Parses a string s to return a value of this type. Read more
Source§

impl PartialEq for Arn

Source§

fn eq(&self, other: &Arn) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for Arn

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl Eq for Arn

Source§

impl StructuralPartialEq for Arn

Auto Trait Implementations§

§

impl Freeze for Arn

§

impl RefUnwindSafe for Arn

§

impl Send for Arn

§

impl Sync for Arn

§

impl Unpin for Arn

§

impl UnwindSafe for Arn

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,