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, RwLock};
14use wami::provider::{AwsProvider, AzureProvider, GcpProvider};
15use wami::service::RoleService;
16use wami::store::memory::InMemoryWamiStore;
17use wami::wami::identity::role::requests::{CreateRoleRequest, ListRolesRequest};
18
19#[tokio::main]
20async fn main() -> Result<(), Box<dyn std::error::Error>> {
21    println!("=== Provider-Specific Features ===\n");
22
23    let store = Arc::new(RwLock::new(InMemoryWamiStore::default()));
24
25    // === AWS: IAM ROLES WITH TRUST POLICIES ===
26    println!("Step 1: AWS IAM Role with Trust Policy...\n");
27
28    let _aws_provider = Arc::new(AwsProvider::new());
29    let aws_service = RoleService::new(store.clone(), "123456789012".to_string());
30
31    let aws_trust_policy = r#"{
32  "Version": "2012-10-17",
33  "Statement": [{
34    "Effect": "Allow",
35    "Principal": {"Service": "lambda.amazonaws.com"},
36    "Action": "sts:AssumeRole"
37  }]
38}"#;
39
40    let aws_role_req = CreateRoleRequest {
41        role_name: "lambda-execution-role".to_string(),
42        path: Some("/service-roles/".to_string()),
43        assume_role_policy_document: aws_trust_policy.to_string(),
44        description: Some("Role for Lambda function execution".to_string()),
45        max_session_duration: Some(3600),
46        permissions_boundary: None,
47        tags: None,
48    };
49
50    let aws_role = aws_service.create_role(aws_role_req).await?;
51    println!("✓ Created AWS Lambda execution role:");
52    println!("  - ARN: {}", aws_role.arn);
53    println!("  - Trust Policy: Allows lambda.amazonaws.com to assume");
54    println!("  - Use case: Serverless function execution");
55
56    // === GCP: SERVICE ACCOUNT PATTERN ===
57    println!("\n\nStep 2: GCP Service Account Pattern...\n");
58
59    let _gcp_provider = Arc::new(GcpProvider::new("my-gcp-project".to_string()));
60    let gcp_service = RoleService::new(store.clone(), "my-gcp-project".to_string());
61
62    let gcp_trust_policy = r#"{
63  "bindings": [{
64    "role": "roles/iam.serviceAccountUser",
65    "members": ["serviceAccount:compute@my-gcp-project.iam.gserviceaccount.com"]
66  }]
67}"#;
68
69    let gcp_role_req = CreateRoleRequest {
70        role_name: "compute-service-account".to_string(),
71        path: Some("/service-accounts/".to_string()),
72        assume_role_policy_document: gcp_trust_policy.to_string(),
73        description: Some("Service account for Compute Engine".to_string()),
74        max_session_duration: Some(3600),
75        permissions_boundary: None,
76        tags: None,
77    };
78
79    let gcp_role = gcp_service.create_role(gcp_role_req).await?;
80    println!("✓ Created GCP service account:");
81    println!("  - ARN: {}", gcp_role.arn);
82    println!("  - Bindings: Compute Engine service usage");
83    println!("  - Use case: VM instance identity");
84
85    // === AZURE: MANAGED IDENTITY PATTERN ===
86    println!("\n\nStep 3: Azure Managed Identity Pattern...\n");
87
88    let _azure_provider = Arc::new(AzureProvider::new(
89        "my-subscription".to_string(),
90        "default-rg".to_string(),
91    ));
92    let azure_service = RoleService::new(store.clone(), "my-subscription".to_string());
93
94    let azure_trust_policy = r#"{
95  "properties": {
96    "principalType": "ServicePrincipal",
97    "tenantId": "tenant-id",
98    "type": "SystemAssigned"
99  }
100}"#;
101
102    let azure_role_req = CreateRoleRequest {
103        role_name: "app-managed-identity".to_string(),
104        path: Some("/managed-identities/".to_string()),
105        assume_role_policy_document: azure_trust_policy.to_string(),
106        description: Some("Managed identity for App Service".to_string()),
107        max_session_duration: Some(3600),
108        permissions_boundary: None,
109        tags: None,
110    };
111
112    let azure_role = azure_service.create_role(azure_role_req).await?;
113    println!("✓ Created Azure managed identity:");
114    println!("  - ARN: {}", azure_role.arn);
115    println!("  - Type: System-assigned managed identity");
116    println!("  - Use case: App Service authentication");
117
118    // === COMPARE PATTERNS ===
119    println!("\n\nStep 4: Comparing provider identity patterns...\n");
120
121    println!("AWS IAM Roles:");
122    println!("- Trust policies define who can assume the role");
123    println!("- Used for cross-account and service-to-service access");
124    println!("- Temporary credentials via STS");
125    println!();
126    println!("GCP Service Accounts:");
127    println!("- Special type of account for applications");
128    println!("- IAM bindings control permissions");
129    println!("- Can be impersonated by other principals");
130    println!();
131    println!("Azure Managed Identities:");
132    println!("- Automatically managed by Azure");
133    println!("- System-assigned (bound to resource) or User-assigned");
134    println!("- No credential management required");
135
136    // === DEMONSTRATE UNIFIED VIEW ===
137    println!("\n\nStep 5: Unified view across providers...\n");
138
139    let (all_roles, _, _) = aws_service
140        .list_roles(ListRolesRequest {
141            path_prefix: None,
142            pagination: None,
143        })
144        .await?;
145    println!(
146        "✓ Total roles/identities across all providers: {}",
147        all_roles.len()
148    );
149    for role in &all_roles {
150        let provider = if role.arn.contains("aws") {
151            "AWS"
152        } else if role.arn.contains("gcp") {
153            "GCP"
154        } else {
155            "Azure"
156        };
157        println!("  - {} ({}) → {}", role.role_name, provider, role.arn);
158    }
159
160    println!("\n✅ Example completed successfully!");
161    println!("Key takeaways:");
162    println!("- Each provider has unique identity patterns");
163    println!("- WAMI abstracts differences while preserving provider semantics");
164    println!("- Trust policies define security boundaries");
165    println!("- Choose patterns based on provider strengths");
166
167    Ok(())
168}