26_secure_instance_bootstrap/
26_secure_instance_bootstrap.rs1use std::sync::Arc;
21use tokio::sync::RwLock;
22use wami::store::memory::InMemoryWamiStore;
23use wami::{
24 AmiError, AuthenticationService, CreateUserRequest, InstanceBootstrap, RootCredentials,
25 UserService,
26};
27
28#[tokio::main]
29async fn main() -> Result<(), Box<dyn std::error::Error>> {
30 println!("🔐 WAMI Secure Instance Bootstrap Example\n");
31 println!("{}", "=".repeat(60));
32
33 println!("\n📦 Step 1: Initialize Store");
37 let store = Arc::new(RwLock::new(InMemoryWamiStore::default()));
38 println!("✅ In-memory store created");
39
40 println!("\n🚀 Step 2: Bootstrap Instance");
44 println!(" Creating instance '999888777' with root user...");
45
46 let instance_id = "999888777";
47 let root_creds = InstanceBootstrap::initialize_instance(store.clone(), instance_id).await?;
48
49 println!("\n✅ Instance initialized successfully!");
50 println!("\n🔑 ROOT CREDENTIALS (SAVE THESE SECURELY!):");
51 println!("{}", "=".repeat(60));
52 println!(" Access Key ID: {}", root_creds.access_key_id);
53 println!(" Secret Access Key: {}", root_creds.secret_access_key);
54 println!(" Instance ID: {}", root_creds.instance_id);
55 println!(" User ARN: {}", root_creds.user_arn);
56 println!("{}", "=".repeat(60));
57 println!("\n⚠️ CRITICAL: These credentials are shown ONLY ONCE!");
58 println!("⚠️ Save them in a secure location (secrets manager, vault, etc.)");
59 println!("⚠️ They CANNOT be retrieved later!");
60
61 println!("\n🔓 Step 3: Authenticate as Root");
65 println!(" Using access key authentication...");
66
67 let auth_service = AuthenticationService::new(store.clone());
68
69 let root_context = auth_service
70 .authenticate(&root_creds.access_key_id, &root_creds.secret_access_key)
71 .await?;
72
73 println!("✅ Authentication successful!");
74 println!(" Authenticated as: {}", root_context.caller_arn());
75 println!(" Instance ID: {}", root_context.instance_id());
76 println!(" Tenant Path: {}", root_context.tenant_path());
77 println!(" Is Root: {}", root_context.is_root());
78
79 println!("\n👤 Step 4: Create Admin User (as root)");
83
84 let user_service = UserService::new(store.clone());
87 let admin_user = user_service
88 .create_user(
89 &root_context,
90 CreateUserRequest {
91 user_name: "admin".to_string(),
92 path: Some("/".to_string()),
93 permissions_boundary: None,
94 tags: None,
95 },
96 )
97 .await?;
98
99 println!("✅ Admin user created: {}", admin_user.user_name);
100 println!(" ARN: {}", admin_user.wami_arn);
101 println!(" Context is required for all operations");
102 println!(" Root context bypasses authorization checks");
103
104 println!("\n🛡️ Step 5: Demonstrate Security");
108 println!(" Attempting authentication with invalid secret...");
109
110 let result = auth_service
111 .authenticate(&root_creds.access_key_id, "wrong_secret_key")
112 .await;
113
114 match result {
115 Err(AmiError::AccessDenied { .. }) => {
116 println!("✅ Invalid credentials rejected (as expected)");
117 println!(" Brute force attacks are prevented!");
118 }
119 Ok(_) => {
120 println!("❌ ERROR: Invalid credentials should have been rejected!");
121 }
122 Err(e) => {
123 println!("❌ Unexpected error: {:?}", e);
124 }
125 }
126
127 println!("\n🔍 Step 6: Check Instance State");
131
132 let is_initialized = InstanceBootstrap::is_initialized(store.clone(), instance_id).await?;
133 println!(
134 " Instance '{}' initialized: {}",
135 instance_id, is_initialized
136 );
137
138 let other_instance_initialized =
139 InstanceBootstrap::is_initialized(store.clone(), "123456789").await?;
140 println!(
141 " Instance '123456789' initialized: {}",
142 other_instance_initialized
143 );
144
145 println!("\n📋 SECURITY SUMMARY");
149 println!("{}", "=".repeat(60));
150 println!("✅ Instance requires initialization before use");
151 println!("✅ Root user has cryptographically secure credentials");
152 println!("✅ Credentials are hashed with bcrypt (never plaintext)");
153 println!("✅ Authentication is mandatory for all operations");
154 println!("✅ Invalid credentials are rejected");
155 println!("✅ No way to brute force instance IDs without credentials");
156 println!("{}", "=".repeat(60));
157
158 println!("\n🎯 BEST PRACTICES");
159 println!("{}", "=".repeat(60));
160 println!("1. Store credentials in secrets manager (AWS/Vault/etc.)");
161 println!("2. Never commit credentials to version control");
162 println!("3. Never log plaintext secrets");
163 println!("4. Use root only for initial setup");
164 println!("5. Create admin users with specific policies");
165 println!("6. Rotate credentials regularly");
166 println!("7. Use principle of least privilege");
167 println!("{}", "=".repeat(60));
168
169 println!("\n✅ Example completed successfully!");
170
171 Ok(())
172}
173
174#[allow(dead_code)]
187async fn store_credentials_securely(
188 creds: &RootCredentials,
189) -> Result<(), Box<dyn std::error::Error>> {
190 println!("📝 Credentials stored in secrets manager");
199 println!(" Secret name: wami/instance/{}/root", creds.instance_id);
200
201 Ok(())
202}
203
204#[allow(dead_code)]
206async fn retrieve_credentials_from_vault(
207 instance_id: &str,
208) -> Result<RootCredentials, Box<dyn std::error::Error>> {
209 println!("🔑 Credentials retrieved from vault");
219
220 Ok(RootCredentials {
222 access_key_id: "AKIAIOSFODNN7EXAMPLE".to_string(),
223 secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY".to_string(),
224 instance_id: instance_id.to_string(),
225 user_arn: format!("arn:wami:iam:root:wami:{}:user/root", instance_id),
226 })
227}
228
229#[allow(dead_code)]
231async fn rotate_root_credentials(
232 store: Arc<tokio::sync::RwLock<InMemoryWamiStore>>,
233 instance_id: &str,
234 old_creds: &RootCredentials,
235) -> Result<RootCredentials, Box<dyn std::error::Error>> {
236 println!("🔄 Rotating root credentials...");
237
238 let auth_service = AuthenticationService::new(store.clone());
240 let _context = auth_service
241 .authenticate(&old_creds.access_key_id, &old_creds.secret_access_key)
242 .await?;
243
244 println!("✅ Credentials rotated successfully");
256 println!("⚠️ Save the new credentials and delete the old ones!");
257
258 Ok(RootCredentials {
260 access_key_id: "AKIANEWKEY123456789".to_string(),
261 secret_access_key: "newSecretKey0123456789abcdefghijklmnop".to_string(),
262 instance_id: instance_id.to_string(),
263 user_arn: old_creds.user_arn.clone(),
264 })
265}