Skip to main content

12_provider_specific_features/
12_provider_specific_features.rs

1//! Provider-Specific Features
2//!
3//! This example demonstrates:
4//! - Leveraging unique features of each cloud provider
5//! - AWS IAM roles with trust policies
6//! - GCP service accounts
7//! - Azure managed identities
8//!
9//! Scenario: Using provider-specific identity patterns.
10//!
11//! Run with: `cargo run --example 12_provider_specific_features`
12
13use std::sync::Arc;
14use tokio::sync::RwLock;
15use wami::arn::{TenantPath, WamiArn};
16use wami::context::WamiContext;
17use wami::service::RoleService;
18use wami::store::memory::InMemoryWamiStore;
19use wami::wami::identity::role::requests::{CreateRoleRequest, ListRolesRequest};
20
21#[tokio::main]
22async fn main() -> Result<(), Box<dyn std::error::Error>> {
23    println!("=== Provider-Specific Features ===\n");
24
25    let store = Arc::new(RwLock::new(InMemoryWamiStore::default()));
26
27    // Create AWS context
28    let aws_context = WamiContext::builder()
29        .instance_id("123456789012")
30        .tenant_path(TenantPath::single(10000001)) // Numeric tenant ID for AWS
31        .caller_arn(
32            WamiArn::builder()
33                .service(wami::arn::Service::Iam)
34                .tenant_path(TenantPath::single(10000001))
35                .wami_instance("123456789012")
36                .resource("user", "admin")
37                .build()?,
38        )
39        .is_root(false)
40        .build()?;
41
42    // Create GCP context
43    let gcp_context = WamiContext::builder()
44        .instance_id("my-gcp-project")
45        .tenant_path(TenantPath::single(20000001)) // Numeric tenant ID for GCP
46        .caller_arn(
47            WamiArn::builder()
48                .service(wami::arn::Service::Iam)
49                .tenant_path(TenantPath::single(20000001))
50                .wami_instance("my-gcp-project")
51                .resource("user", "admin")
52                .build()?,
53        )
54        .is_root(false)
55        .build()?;
56
57    // Create Azure context
58    let azure_context = WamiContext::builder()
59        .instance_id("my-subscription")
60        .tenant_path(TenantPath::single(30000001)) // Numeric tenant ID for Azure
61        .caller_arn(
62            WamiArn::builder()
63                .service(wami::arn::Service::Iam)
64                .tenant_path(TenantPath::single(30000001))
65                .wami_instance("my-subscription")
66                .resource("user", "admin")
67                .build()?,
68        )
69        .is_root(false)
70        .build()?;
71
72    let role_service = RoleService::new(store.clone());
73
74    // === AWS: IAM ROLES WITH TRUST POLICIES ===
75    println!("Step 1: AWS IAM Role with Trust Policy...\n");
76
77    let aws_trust_policy = r#"{
78  "Version": "2012-10-17",
79  "Statement": [{
80    "Effect": "Allow",
81    "Principal": {"Service": "lambda.amazonaws.com"},
82    "Action": "sts:AssumeRole"
83  }]
84}"#;
85
86    let aws_role_req = CreateRoleRequest {
87        role_name: "lambda-execution-role".to_string(),
88        path: Some("/service-roles/".to_string()),
89        assume_role_policy_document: aws_trust_policy.to_string(),
90        description: Some("Role for Lambda function execution".to_string()),
91        max_session_duration: Some(3600),
92        permissions_boundary: None,
93        tags: None,
94    };
95
96    let aws_role = role_service.create_role(&aws_context, aws_role_req).await?;
97    println!("✓ Created AWS Lambda execution role:");
98    println!("  - ARN: {}", aws_role.arn);
99    println!("  - WAMI ARN: {}", aws_role.wami_arn);
100    println!("  - Trust Policy: Allows lambda.amazonaws.com to assume");
101    println!("  - Use case: Serverless function execution");
102
103    // === GCP: SERVICE ACCOUNT PATTERN ===
104    println!("\n\nStep 2: GCP Service Account Pattern...\n");
105
106    let gcp_trust_policy = r#"{
107  "bindings": [{
108    "role": "roles/iam.serviceAccountUser",
109    "members": ["serviceAccount:compute@my-gcp-project.iam.gserviceaccount.com"]
110  }]
111}"#;
112
113    let gcp_role_req = CreateRoleRequest {
114        role_name: "compute-service-account".to_string(),
115        path: Some("/service-accounts/".to_string()),
116        assume_role_policy_document: gcp_trust_policy.to_string(),
117        description: Some("Service account for Compute Engine".to_string()),
118        max_session_duration: Some(3600),
119        permissions_boundary: None,
120        tags: None,
121    };
122
123    let gcp_role = role_service.create_role(&gcp_context, gcp_role_req).await?;
124    println!("✓ Created GCP service account:");
125    println!("  - ARN: {}", gcp_role.arn);
126    println!("  - WAMI ARN: {}", gcp_role.wami_arn);
127    println!("  - Bindings: Compute Engine service usage");
128    println!("  - Use case: VM instance identity");
129
130    // === AZURE: MANAGED IDENTITY PATTERN ===
131    println!("\n\nStep 3: Azure Managed Identity Pattern...\n");
132
133    let azure_trust_policy = r#"{
134  "properties": {
135    "principalType": "ServicePrincipal",
136    "tenantId": "tenant-id",
137    "type": "SystemAssigned"
138  }
139}"#;
140
141    let azure_role_req = CreateRoleRequest {
142        role_name: "app-managed-identity".to_string(),
143        path: Some("/managed-identities/".to_string()),
144        assume_role_policy_document: azure_trust_policy.to_string(),
145        description: Some("Managed identity for App Service".to_string()),
146        max_session_duration: Some(3600),
147        permissions_boundary: None,
148        tags: None,
149    };
150
151    let azure_role = role_service
152        .create_role(&azure_context, azure_role_req)
153        .await?;
154    println!("✓ Created Azure managed identity:");
155    println!("  - ARN: {}", azure_role.arn);
156    println!("  - Type: System-assigned managed identity");
157    println!("  - Use case: App Service authentication");
158
159    // === COMPARE PATTERNS ===
160    println!("\n\nStep 4: Comparing provider identity patterns...\n");
161
162    println!("AWS IAM Roles:");
163    println!("- Trust policies define who can assume the role");
164    println!("- Used for cross-account and service-to-service access");
165    println!("- Temporary credentials via STS");
166    println!();
167    println!("GCP Service Accounts:");
168    println!("- Special type of account for applications");
169    println!("- IAM bindings control permissions");
170    println!("- Can be impersonated by other principals");
171    println!();
172    println!("Azure Managed Identities:");
173    println!("- Automatically managed by Azure");
174    println!("- System-assigned (bound to resource) or User-assigned");
175    println!("- No credential management required");
176
177    // === DEMONSTRATE UNIFIED VIEW ===
178    println!("\n\nStep 5: Unified view across providers...\n");
179
180    let (all_roles, _, _) = role_service
181        .list_roles(
182            &aws_context,
183            ListRolesRequest {
184                path_prefix: None,
185                pagination: None,
186            },
187        )
188        .await?;
189    println!(
190        "✓ Total roles/identities across all providers: {}",
191        all_roles.len()
192    );
193    for role in &all_roles {
194        let provider = if role.wami_arn.to_string().contains("aws") {
195            "AWS"
196        } else if role.wami_arn.to_string().contains("gcp") {
197            "GCP"
198        } else {
199            "Azure"
200        };
201        println!("  - {} ({}) → {}", role.role_name, provider, role.wami_arn);
202    }
203
204    println!("\n✅ Example completed successfully!");
205    println!("Key takeaways:");
206    println!("- Each provider has unique identity patterns");
207    println!("- WAMI abstracts differences while preserving provider semantics");
208    println!("- Trust policies define security boundaries");
209    println!("- Choose patterns based on provider strengths");
210
211    Ok(())
212}