Skip to main content

13_disaster_recovery_multi_cloud/
13_disaster_recovery_multi_cloud.rs

1//! Disaster Recovery Multi-Cloud
2//!
3//! This example demonstrates:
4//! - Replicating resources from primary to secondary cloud
5//! - Failover scenarios
6//! - Multi-cloud redundancy patterns
7//!
8//! Scenario: Replicating critical resources from AWS (primary) to GCP (backup).
9//!
10//! Run with: `cargo run --example 13_disaster_recovery_multi_cloud`
11
12use std::sync::Arc;
13use tokio::sync::RwLock;
14use wami::arn::{TenantPath, WamiArn};
15use wami::context::WamiContext;
16use wami::service::{GroupService, UserService};
17use wami::store::memory::InMemoryWamiStore;
18use wami::wami::identity::group::requests::CreateGroupRequest;
19use wami::wami::identity::user::requests::{CreateUserRequest, ListUsersRequest};
20
21#[tokio::main]
22async fn main() -> Result<(), Box<dyn std::error::Error>> {
23    println!("=== Disaster Recovery Multi-Cloud ===\n");
24
25    let store = Arc::new(RwLock::new(InMemoryWamiStore::default()));
26
27    // Create AWS (primary) context
28    let aws_context = WamiContext::builder()
29        .instance_id("111111111111")
30        .tenant_path(TenantPath::single(40000001)) // Numeric tenant ID for AWS primary
31        .caller_arn(
32            WamiArn::builder()
33                .service(wami::arn::Service::Iam)
34                .tenant_path(TenantPath::single(40000001))
35                .wami_instance("111111111111")
36                .resource("user", "admin")
37                .build()?,
38        )
39        .is_root(false)
40        .build()?;
41
42    // Create GCP (secondary) context
43    let gcp_context = WamiContext::builder()
44        .instance_id("backup-project")
45        .tenant_path(TenantPath::single(50000001)) // Numeric tenant ID for GCP backup
46        .caller_arn(
47            WamiArn::builder()
48                .service(wami::arn::Service::Iam)
49                .tenant_path(TenantPath::single(50000001))
50                .wami_instance("backup-project")
51                .resource("user", "admin")
52                .build()?,
53        )
54        .is_root(false)
55        .build()?;
56
57    let user_service = UserService::new(store.clone());
58    let group_service = GroupService::new(store.clone());
59
60    // === SETUP PRIMARY (AWS) ===
61    println!("Step 1: Creating resources in PRIMARY (AWS)...\n");
62
63    // Create users in primary
64    println!("Creating critical users in AWS...");
65    let admin_req = CreateUserRequest {
66        user_name: "admin".to_string(),
67        path: Some("/critical/".to_string()),
68        permissions_boundary: None,
69        tags: Some(vec![
70            wami::types::Tag {
71                key: "Criticality".to_string(),
72                value: "High".to_string(),
73            },
74            wami::types::Tag {
75                key: "ReplicationTarget".to_string(),
76                value: "GCP".to_string(),
77            },
78        ]),
79    };
80    let aws_admin = user_service.create_user(&aws_context, admin_req).await?;
81    println!("✓ Created admin in AWS: {}", aws_admin.wami_arn);
82
83    let operator_req = CreateUserRequest {
84        user_name: "operator".to_string(),
85        path: Some("/critical/".to_string()),
86        permissions_boundary: None,
87        tags: Some(vec![wami::types::Tag {
88            key: "Criticality".to_string(),
89            value: "High".to_string(),
90        }]),
91    };
92    let aws_operator = user_service.create_user(&aws_context, operator_req).await?;
93    println!("✓ Created operator in AWS: {}", aws_operator.wami_arn);
94
95    // Create group in primary
96    let group_req = CreateGroupRequest {
97        group_name: "emergency-responders".to_string(),
98        path: Some("/critical/".to_string()),
99        tags: None,
100    };
101    let aws_group = group_service.create_group(&aws_context, group_req).await?;
102    println!("\n✓ Created group in AWS: {}", aws_group.wami_arn);
103
104    // Add users to group
105    group_service
106        .add_user_to_group(&aws_context, "emergency-responders", "admin")
107        .await?;
108    group_service
109        .add_user_to_group(&aws_context, "emergency-responders", "operator")
110        .await?;
111    println!("✓ Added users to group");
112
113    // === REPLICATE TO SECONDARY (GCP) ===
114    println!("\n\nStep 2: Replicating to SECONDARY (GCP)...\n");
115
116    // Replicate users
117    println!("Replicating users to GCP...");
118    let admin_replica_req = CreateUserRequest {
119        user_name: aws_admin.user_name.clone(),
120        path: Some(aws_admin.path.clone()),
121        permissions_boundary: None,
122        tags: Some(aws_admin.tags.clone()),
123    };
124    let gcp_admin = user_service
125        .create_user(&gcp_context, admin_replica_req)
126        .await?;
127    println!("✓ Replicated admin to GCP: {}", gcp_admin.wami_arn);
128
129    let operator_replica_req = CreateUserRequest {
130        user_name: aws_operator.user_name.clone(),
131        path: Some(aws_operator.path.clone()),
132        permissions_boundary: None,
133        tags: Some(aws_operator.tags.clone()),
134    };
135    let gcp_operator = user_service
136        .create_user(&gcp_context, operator_replica_req)
137        .await?;
138    println!("✓ Replicated operator to GCP: {}", gcp_operator.wami_arn);
139
140    // Replicate group
141    let group_replica_req = CreateGroupRequest {
142        group_name: aws_group.group_name.clone(),
143        path: Some(aws_group.path.clone()),
144        tags: None,
145    };
146    let gcp_group = group_service
147        .create_group(&gcp_context, group_replica_req)
148        .await?;
149    println!("\n✓ Replicated group to GCP: {}", gcp_group.wami_arn);
150
151    // Replicate group membership
152    group_service
153        .add_user_to_group(&gcp_context, "emergency-responders", "admin")
154        .await?;
155    group_service
156        .add_user_to_group(&gcp_context, "emergency-responders", "operator")
157        .await?;
158    println!("✓ Replicated group membership");
159
160    // === SIMULATE FAILOVER ===
161    println!("\n\nStep 3: Simulating failover scenario...\n");
162
163    println!("Scenario: AWS region becomes unavailable");
164    println!("Action: Failover to GCP backup");
165    println!();
166    println!("✓ GCP resources are ready to serve:");
167    println!("  - {} users available", 2);
168    println!("  - {} groups available", 1);
169    println!("  - All group memberships preserved");
170
171    // === DEMONSTRATE STATUS ===
172    println!("\n\nStep 4: Disaster recovery status...\n");
173
174    let (all_users, _, _) = user_service
175        .list_users(
176            &aws_context,
177            ListUsersRequest {
178                path_prefix: Some("/critical/".to_string()),
179                pagination: None,
180            },
181        )
182        .await?;
183
184    let aws_users: Vec<_> = all_users
185        .iter()
186        .filter(|u| u.wami_arn.to_string().contains("40000001"))
187        .collect();
188    let gcp_users: Vec<_> = all_users
189        .iter()
190        .filter(|u| u.wami_arn.to_string().contains("50000001"))
191        .collect();
192
193    println!("PRIMARY (AWS) status:");
194    println!("  - Users: {}", aws_users.len());
195    for user in aws_users {
196        println!("    • {} → {}", user.user_name, user.wami_arn);
197    }
198
199    println!("\nSECONDARY (GCP) status:");
200    println!("  - Users: {}", gcp_users.len());
201    for user in gcp_users {
202        println!("    • {} → {}", user.user_name, user.wami_arn);
203    }
204
205    // === BEST PRACTICES ===
206    println!("\n\nStep 5: Disaster recovery best practices...\n");
207
208    println!("Replication strategies:");
209    println!("- Active-passive: Primary handles all traffic, secondary standby");
210    println!("- Active-active: Both regions serve traffic simultaneously");
211    println!("- Periodic sync: Scheduled replication of critical resources");
212    println!("- Event-driven: Real-time replication on changes");
213    println!();
214    println!("Implementation considerations:");
215    println!("- Replicate user accounts, roles, and policies");
216    println!("- Sync group memberships and permissions");
217    println!("- Test failover procedures regularly");
218    println!("- Monitor replication lag and health");
219    println!("- Implement automated failover triggers");
220    println!("- Document runbooks for manual failover");
221
222    println!("\n✅ Example completed successfully!");
223    println!("Key takeaways:");
224    println!("- Multi-cloud provides redundancy and disaster recovery");
225    println!("- Replicate critical identity resources across clouds");
226    println!("- Test failover scenarios before disasters occur");
227    println!("- WAMI enables cloud-agnostic DR strategies");
228
229    Ok(())
230}