// rust/01-environment-variables.rs/*Environment variables patterns and best practices*/usestd::collections::HashMap;usestd::sync::Arc;usestd::time::{Duration,Instant};usetokio::sync::RwLock;useserde::{Deserialize,Serialize};usestd::env;/// Environment variables manager.pubstructEnvManager{variables:Arc<RwLock<HashMap<String,String>>>,required_vars:Vec<String>,sensitive_vars:Vec<String>,validation_rules:HashMap<String,ValidationRule>,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructValidationRule{pubrequired:bool,pubmin_length:Option<usize>,pubmax_length:Option<usize>,pubpattern:Option<String>,puballowed_values:Option<Vec<String>>,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructEnvConfig{pubdatabase_url:String,pubredis_url:String,pubjwt_secret:String,pubapi_key:String,pubencryption_key:String,publog_level:String,pubport:u16,pubhost:String,}implEnvManager{pubfnnew()->Self{letmutmanager=Self{variables:Arc::new(RwLock::new(HashMap::new())),required_vars:vec!["DATABASE_URL".to_string(),"REDIS_URL".to_string(),"JWT_SECRET".to_string(),"API_KEY".to_string(),"ENCRYPTION_KEY".to_string(),],sensitive_vars:vec!["DATABASE_URL".to_string(),"JWT_SECRET".to_string(),"API_KEY".to_string(),"ENCRYPTION_KEY".to_string(),],validation_rules:HashMap::new(),};// Set up validation rulesmanager.setup_validation_rules();manager}/// Load environment variables.pubasyncfnload(&mutself)->Result<(),String>{letmutvariables=self.variables.write().await;// Load all environment variablesfor(key,value)inenv::vars(){variables.insert(key,value);}// Validate required variablesforvarin&self.required_vars{if!variables.contains_key(var){returnErr(format!("Required environment variable {} not set",var));}}// Validate sensitive variablesforvarin&self.sensitive_vars{ifletSome(value)=variables.get(var){ifvalue.is_empty(){returnErr(format!("Sensitive environment variable {} is empty",var));}}}Ok(())}/// Get environment variable.pubasyncfnget(&self,key:&str)->Option<String>{letvariables=self.variables.read().await;variables.get(key).cloned()}/// Get environment variable with default.pubasyncfnget_with_default(&self,key:&str,default:&str)->String{self.get(key).await.unwrap_or_else(||default.to_string())}/// Get required environment variable.pubasyncfnget_required(&self,key:&str)->Result<String,String>{self.get(key).await.ok_or_else(||format!("Required environment variable {} not set",key))}/// Set environment variable.pubasyncfnset(&self,key:&str,value:&str)->Result<(),String>{// Validate sensitive variablesifself.sensitive_vars.contains(&key.to_string()){ifvalue.is_empty(){returnErr(format!("Sensitive environment variable {} cannot be empty",key));}}// Validate against rulesifletSome(rule)=self.validation_rules.get(key){self.validate_value(key,value,rule)?;}letmutvariables=self.variables.write().await;variables.insert(key.to_string(),value.to_string());Ok(())}/// Validate environment variable value.fnvalidate_value(&self,key:&str,value:&str,rule:&ValidationRule)->Result<(),String>{ifrule.required&&value.is_empty(){returnErr(format!("Environment variable {} is required",key));}ifletSome(min_length)=rule.min_length{ifvalue.len()<min_length{returnErr(format!("Environment variable {} must be at least {} characters long",key,min_length));}}ifletSome(max_length)=rule.max_length{ifvalue.len()>max_length{returnErr(format!("Environment variable {} must be no more than {} characters long",key,max_length));}}ifletSome(pattern)=&rule.pattern{ifletOk(regex)=regex::Regex::new(pattern){if!regex.is_match(value){returnErr(format!("Environment variable {} does not match required pattern",key));}}}ifletSome(allowed_values)=&rule.allowed_values{if!allowed_values.contains(&value.to_string()){returnErr(format!("Environment variable {} must be one of: {}",key,allowed_values.join(", ")));}}Ok(())}/// Setup validation rules.fnsetup_validation_rules(&mutself){// Database URL validationself.validation_rules.insert("DATABASE_URL".to_string(),ValidationRule{required:true,min_length:Some(10),max_length:Some(500),pattern:Some(r"^postgres://.*$".to_string()),allowed_values:None,});// JWT Secret validationself.validation_rules.insert("JWT_SECRET".to_string(),ValidationRule{required:true,min_length:Some(32),max_length:Some(256),pattern:None,allowed_values:None,});// API Key validationself.validation_rules.insert("API_KEY".to_string(),ValidationRule{required:true,min_length:Some(16),max_length:Some(128),pattern:None,allowed_values:None,});// Log Level validationself.validation_rules.insert("LOG_LEVEL".to_string(),ValidationRule{required:false,min_length:None,max_length:None,pattern:None,allowed_values:Some(vec!["debug".to_string(),"info".to_string(),"warn".to_string(),"error".to_string()]),});}/// Get configuration struct.pubasyncfnget_config(&self)->Result<EnvConfig,String>{Ok(EnvConfig{database_url:self.get_required("DATABASE_URL").await?,redis_url:self.get_required("REDIS_URL").await?,jwt_secret:self.get_required("JWT_SECRET").await?,api_key:self.get_required("API_KEY").await?,encryption_key:self.get_required("ENCRYPTION_KEY").await?,log_level:self.get_with_default("LOG_LEVEL","info").await,port:self.get_with_default("PORT","8080").await.parse().unwrap_or(8080),host:self.get_with_default("HOST","0.0.0.0").await,})}/// Mask sensitive values for logging.pubfnmask_sensitive(&self,key:&str,value:&str)->String{ifself.sensitive_vars.contains(&key.to_string()){ifvalue.len()<=8{"*".repeat(value.len())}else{format!("{}...{}",&value[..4],"*".repeat(value.len()-8))}}else{value.to_string()}}/// Get all variables (with sensitive ones masked).pubasyncfnget_all_masked(&self)->HashMap<String,String>{letvariables=self.variables.read().await;letmutmasked=HashMap::new();for(key,value)invariables.iter(){masked.insert(key.clone(),self.mask_sensitive(key,value));}masked}}#[cfg(test)]modtests{usesuper::*;#[tokio::test]asyncfntest_env_manager(){letmutmanager=EnvManager::new();// Set test environment variablesmanager.set("DATABASE_URL","postgres://user:pass@localhost/db").await.unwrap();manager.set("REDIS_URL","redis://localhost:6379").await.unwrap();manager.set("JWT_SECRET","super-secret-jwt-key").await.unwrap();manager.set("API_KEY","api-key-123456789").await.unwrap();manager.set("ENCRYPTION_KEY","encryption-key-123456789").await.unwrap();letconfig=manager.get_config().await.unwrap();assert_eq!(config.database_url,"postgres://user:pass@localhost/db");assert_eq!(config.jwt_secret,"super-secret-jwt-key");}#[tokio::test]asyncfntest_validation(){letmutmanager=EnvManager::new();// Test invalid database URLletresult=manager.set("DATABASE_URL","invalid-url").await;assert!(result.is_err());// Test valid database URLletresult=manager.set("DATABASE_URL","postgres://user:pass@localhost/db").await;assert!(result.is_ok());}}
// rust/02-secret-stores.rs/*Secret stores patterns and best practices*/usestd::collections::HashMap;usestd::sync::Arc;usestd::time::{Duration,Instant};usetokio::sync::RwLock;useserde::{Deserialize,Serialize};usestd::path::PathBuf;/// Secret store manager.pubstructSecretStore{secrets:Arc<RwLock<HashMap<String,Secret>>>,encryption_key:String,rotation_interval:Duration,last_rotation:Instant,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructSecret{pubkey:String,pubvalue:String,pubversion:u32,pubcreated_at:Instant,pubexpires_at:Option<Instant>,pubtags:HashMap<String,String>,pubis_active:bool,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructSecretMetadata{pubkey:String,pubversion:u32,pubcreated_at:Instant,pubexpires_at:Option<Instant>,pubtags:HashMap<String,String>,pubis_active:bool,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructSecretRotationConfig{pubkey:String,pubrotation_interval:Duration,pubauto_rotation:bool,pubnotification_webhook:Option<String>,}implSecretStore{pubfnnew(encryption_key:String,rotation_interval:Duration)->Self{Self{secrets:Arc::new(RwLock::new(HashMap::new())),encryption_key,rotation_interval,last_rotation:Instant::now(),}}/// Store a secret.pubasyncfnstore_secret(&self,key:String,value:String,tags:HashMap<String,String>)->Result<SecretMetadata,String>{// Encrypt the secret valueletencrypted_value=self.encrypt_value(&value)?;// Create secretletsecret=Secret{key:key.clone(),value:encrypted_value,version:1,created_at:Instant::now(),expires_at:None,tags,is_active:true,};// Store secretletmutsecrets=self.secrets.write().await;secrets.insert(key.clone(),secret);Ok(SecretMetadata{key,version:1,created_at:Instant::now(),expires_at:None,tags:HashMap::new(),is_active:true,})}/// Retrieve a secret.pubasyncfnget_secret(&self,key:&str)->Result<String,String>{letsecrets=self.secrets.read().await;ifletSome(secret)=secrets.get(key){if!secret.is_active{returnErr("Secret is not active".to_string());}ifletSome(expires_at)=secret.expires_at{ifexpires_at<Instant::now(){returnErr("Secret has expired".to_string());}}// Decrypt the secret valueletdecrypted_value=self.decrypt_value(&secret.value)?;Ok(decrypted_value)}else{Err("Secret not found".to_string())}}/// Update a secret.pubasyncfnupdate_secret(&self,key:&str,value:String,tags:Option<HashMap<String,String>>)->Result<SecretMetadata,String>{letmutsecrets=self.secrets.write().await;ifletSome(secret)=secrets.get_mut(key){// Encrypt the new valueletencrypted_value=self.encrypt_value(&value)?;// Update secretsecret.value=encrypted_value;secret.version+=1;secret.created_at=Instant::now();ifletSome(new_tags)=tags{secret.tags=new_tags;}Ok(SecretMetadata{key:key.to_string(),version:secret.version,created_at:secret.created_at,expires_at:secret.expires_at,tags:secret.tags.clone(),is_active:secret.is_active,})}else{Err("Secret not found".to_string())}}/// Delete a secret.pubasyncfndelete_secret(&self,key:&str)->Result<(),String>{letmutsecrets=self.secrets.write().await;ifletSome(secret)=secrets.get_mut(key){secret.is_active=false;Ok(())}else{Err("Secret not found".to_string())}}/// List secrets.pubasyncfnlist_secrets(&self,prefix:Option<&str>)->Result<Vec<SecretMetadata>,String>{letsecrets=self.secrets.read().await;letmutresult=Vec::new();for(key,secret)insecrets.iter(){ifletSome(prefix)=prefix{if!key.starts_with(prefix){continue;}}result.push(SecretMetadata{key:key.clone(),version:secret.version,created_at:secret.created_at,expires_at:secret.expires_at,tags:secret.tags.clone(),is_active:secret.is_active,});}Ok(result)}/// Rotate a secret.pubasyncfnrotate_secret(&self,key:&str,new_value:String)->Result<SecretMetadata,String>{letmutsecrets=self.secrets.write().await;ifletSome(secret)=secrets.get_mut(key){// Encrypt the new valueletencrypted_value=self.encrypt_value(&new_value)?;// Update secretsecret.value=encrypted_value;secret.version+=1;secret.created_at=Instant::now();Ok(SecretMetadata{key:key.to_string(),version:secret.version,created_at:secret.created_at,expires_at:secret.expires_at,tags:secret.tags.clone(),is_active:secret.is_active,})}else{Err("Secret not found".to_string())}}/// Set secret expiration.pubasyncfnset_secret_expiration(&self,key:&str,expires_at:Instant)->Result<(),String>{letmutsecrets=self.secrets.write().await;ifletSome(secret)=secrets.get_mut(key){secret.expires_at=Some(expires_at);Ok(())}else{Err("Secret not found".to_string())}}/// Get secret metadata.pubasyncfnget_secret_metadata(&self,key:&str)->Result<SecretMetadata,String>{letsecrets=self.secrets.read().await;ifletSome(secret)=secrets.get(key){Ok(SecretMetadata{key:key.to_string(),version:secret.version,created_at:secret.created_at,expires_at:secret.expires_at,tags:secret.tags.clone(),is_active:secret.is_active,})}else{Err("Secret not found".to_string())}}/// Check if secret rotation is needed.pubfnneeds_rotation(&self)->bool{self.last_rotation.elapsed()>=self.rotation_interval}/// Rotate all secrets.pubasyncfnrotate_all_secrets(&self)->Result<Vec<String>,String>{letmutrotated_keys=Vec::new();letsecrets=self.secrets.read().await;for(key,secret)insecrets.iter(){ifsecret.is_active{// In a real implementation, you would generate new values// and rotate the secretsrotated_keys.push(key.clone());}}Ok(rotated_keys)}/// Encrypt secret value.fnencrypt_value(&self,value:&str)->Result<String,String>{// In a real implementation, you would use proper encryption// For this example, we'll just base64 encodeusebase64::Engine;letencoded=base64::engine::general_purpose::STANDARD.encode(value);Ok(encoded)}/// Decrypt secret value.fndecrypt_value(&self,encrypted_value:&str)->Result<String,String>{// In a real implementation, you would use proper decryption// For this example, we'll just base64 decodeusebase64::Engine;letdecoded=base64::engine::general_purpose::STANDARD.decode(encrypted_value).map_err(|e|format!("Decryption failed: {}",e))?;String::from_utf8(decoded).map_err(|e|format!("UTF-8 conversion failed: {}",e))}}#[cfg(test)]modtests{usesuper::*;#[tokio::test]asyncfntest_secret_store(){letstore=SecretStore::new("encryption-key".to_string(),Duration::from_days(30));letmuttags=HashMap::new();tags.insert("environment".to_string(),"production".to_string());tags.insert("service".to_string(),"api".to_string());letmetadata=store.store_secret("database_password","secret123",tags).await.unwrap();assert_eq!(metadata.key,"database_password");assert_eq!(metadata.version,1);letvalue=store.get_secret("database_password").await.unwrap();assert_eq!(value,"secret123");}#[tokio::test]asyncfntest_secret_rotation(){letstore=SecretStore::new("encryption-key".to_string(),Duration::from_days(30));store.store_secret("api_key","old-key",HashMap::new()).await.unwrap();letmetadata=store.rotate_secret("api_key","new-key").await.unwrap();assert_eq!(metadata.version,2);letvalue=store.get_secret("api_key").await.unwrap();assert_eq!(value,"new-key");}}
// rust/03-key-management.rs/*Key management patterns and best practices*/usestd::collections::HashMap;usestd::sync::Arc;usestd::time::{Duration,Instant};usetokio::sync::RwLock;useserde::{Deserialize,Serialize};usestd::path::PathBuf;/// Key manager.pubstructKeyManager{keys:Arc<RwLock<HashMap<String,Key>>>,key_rotation_interval:Duration,last_rotation:Instant,master_key:String,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructKey{pubid:String,pubname:String,pubalgorithm:KeyAlgorithm,pubkey_data:Vec<u8>,pubcreated_at:Instant,pubexpires_at:Option<Instant>,pubis_active:bool,pubversion:u32,pubtags:HashMap<String,String>,}#[derive(Debug, Clone, Serialize, Deserialize)]pubenumKeyAlgorithm{Aes256,Rsa2048,Rsa4096,EcdsaP256,EcdsaP384,Ed25519,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructKeyMetadata{pubid:String,pubname:String,pubalgorithm:KeyAlgorithm,pubcreated_at:Instant,pubexpires_at:Option<Instant>,pubis_active:bool,pubversion:u32,pubtags:HashMap<String,String>,}#[derive(Debug, Clone, Serialize, Deserialize)]pubstructKeyRotationConfig{pubkey_id:String,pubrotation_interval:Duration,pubauto_rotation:bool,pubnotification_webhook:Option<String>,}implKeyManager{pubfnnew(master_key:String,rotation_interval:Duration)->Self{Self{keys:Arc::new(RwLock::new(HashMap::new())),key_rotation_interval:rotation_interval,last_rotation:Instant::now(),master_key,}}/// Generate a new key.pubasyncfngenerate_key(&self,name:String,algorithm:KeyAlgorithm,tags:HashMap<String,String>)->Result<KeyMetadata,String>{letkey_id=uuid::Uuid::new_v4().to_string();letkey_data=self.generate_key_data(&algorithm)?;letkey=Key{id:key_id.clone(),name:name.clone(),algorithm:algorithm.clone(),key_data,created_at:Instant::now(),expires_at:None,is_active:true,version:1,tags,};// Store keyletmutkeys=self.keys.write().await;keys.insert(key_id.clone(),key);Ok(KeyMetadata{id:key_id,name,algorithm,created_at:Instant::now(),expires_at:None,is_active:true,version:1,tags:HashMap::new(),})}/// Get a key.pubasyncfnget_key(&self,key_id:&str)->Result<Key,String>{letkeys=self.keys.read().await;ifletSome(key)=keys.get(key_id){if!key.is_active{returnErr("Key is not active".to_string());}ifletSome(expires_at)=key.expires_at{ifexpires_at<Instant::now(){returnErr("Key has expired".to_string());}}Ok(key.clone())}else{Err("Key not found".to_string())}}/// List keys.pubasyncfnlist_keys(&self,prefix:Option<&str>)->Result<Vec<KeyMetadata>,String>{letkeys=self.keys.read().await;letmutresult=Vec::new();for(key_id,key)inkeys.iter(){ifletSome(prefix)=prefix{if!key.name.starts_with(prefix){continue;}}result.push(KeyMetadata{id:key_id.clone(),name:key.name.clone(),algorithm:key.algorithm.clone(),created_at:key.created_at,expires_at:key.expires_at,is_active:key.is_active,version:key.version,tags:key.tags.clone(),});}Ok(result)}/// Rotate a key.pubasyncfnrotate_key(&self,key_id:&str)->Result<KeyMetadata,String>{letmutkeys=self.keys.write().await;ifletSome(key)=keys.get_mut(key_id){// Generate new key dataletnew_key_data=self.generate_key_data(&key.algorithm)?;// Update keykey.key_data=new_key_data;key.version+=1;key.created_at=Instant::now();Ok(KeyMetadata{id:key_id.to_string(),name:key.name.clone(),algorithm:key.algorithm.clone(),created_at:key.created_at,expires_at:key.expires_at,is_active:key.is_active,version:key.version,tags:key.tags.clone(),})}else{Err("Key not found".to_string())}}/// Set key expiration.pubasyncfnset_key_expiration(&self,key_id:&str,expires_at:Instant)->Result<(),String>{letmutkeys=self.keys.write().await;ifletSome(key)=keys.get_mut(key_id){key.expires_at=Some(expires_at);Ok(())}else{Err("Key not found".to_string())}}/// Deactivate a key.pubasyncfndeactivate_key(&self,key_id:&str)->Result<(),String>{letmutkeys=self.keys.write().await;ifletSome(key)=keys.get_mut(key_id){key.is_active=false;Ok(())}else{Err("Key not found".to_string())}}/// Get key metadata.pubasyncfnget_key_metadata(&self,key_id:&str)->Result<KeyMetadata,String>{letkeys=self.keys.read().await;ifletSome(key)=keys.get(key_id){Ok(KeyMetadata{id:key_id.to_string(),name:key.name.clone(),algorithm:key.algorithm.clone(),created_at:key.created_at,expires_at:key.expires_at,is_active:key.is_active,version:key.version,tags:key.tags.clone(),})}else{Err("Key not found".to_string())}}/// Check if key rotation is needed.pubfnneeds_rotation(&self)->bool{self.last_rotation.elapsed()>=self.key_rotation_interval}/// Rotate all keys.pubasyncfnrotate_all_keys(&self)->Result<Vec<String>,String>{letmutrotated_keys=Vec::new();letkeys=self.keys.read().await;for(key_id,key)inkeys.iter(){ifkey.is_active{// In a real implementation, you would rotate the keysrotated_keys.push(key_id.clone());}}Ok(rotated_keys)}/// Generate key data based on algorithm.fngenerate_key_data(&self,algorithm:&KeyAlgorithm)->Result<Vec<u8>,String>{matchalgorithm{KeyAlgorithm::Aes256=>{letmutkey=vec![0u8;32];userand::RngCore;rand::thread_rng().fill_bytes(&mutkey);Ok(key)},KeyAlgorithm::Rsa2048=>{// In a real implementation, you would generate RSA keysOk(vec![0u8;256])},KeyAlgorithm::Rsa4096=>{// In a real implementation, you would generate RSA keysOk(vec![0u8;512])},KeyAlgorithm::EcdsaP256=>{letmutkey=vec![0u8;32];userand::RngCore;rand::thread_rng().fill_bytes(&mutkey);Ok(key)},KeyAlgorithm::EcdsaP384=>{letmutkey=vec![0u8;48];userand::RngCore;rand::thread_rng().fill_bytes(&mutkey);Ok(key)},KeyAlgorithm::Ed25519=>{letmutkey=vec![0u8;32];userand::RngCore;rand::thread_rng().fill_bytes(&mutkey);Ok(key)},}}/// Encrypt data with a key.pubasyncfnencrypt_data(&self,key_id:&str,data:&[u8])->Result<Vec<u8>,String>{letkey=self.get_key(key_id).await?;matchkey.algorithm{KeyAlgorithm::Aes256=>{// In a real implementation, you would use AES-256-GCMOk(data.to_vec())},KeyAlgorithm::Rsa2048|KeyAlgorithm::Rsa4096=>{// In a real implementation, you would use RSA encryptionOk(data.to_vec())},_=>Err("Unsupported algorithm for encryption".to_string()),}}/// Decrypt data with a key.pubasyncfndecrypt_data(&self,key_id:&str,encrypted_data:&[u8])->Result<Vec<u8>,String>{letkey=self.get_key(key_id).await?;matchkey.algorithm{KeyAlgorithm::Aes256=>{// In a real implementation, you would use AES-256-GCMOk(encrypted_data.to_vec())},KeyAlgorithm::Rsa2048|KeyAlgorithm::Rsa4096=>{// In a real implementation, you would use RSA decryptionOk(encrypted_data.to_vec())},_=>Err("Unsupported algorithm for decryption".to_string()),}}}#[cfg(test)]modtests{usesuper::*;#[tokio::test]asyncfntest_key_manager(){letmanager=KeyManager::new("master-key".to_string(),Duration::from_days(30));letmuttags=HashMap::new();tags.insert("environment".to_string(),"production".to_string());tags.insert("service".to_string(),"api".to_string());letmetadata=manager.generate_key("encryption-key",KeyAlgorithm::Aes256,tags).await.unwrap();assert_eq!(metadata.name,"encryption-key");assert_eq!(metadata.algorithm,KeyAlgorithm::Aes256);assert_eq!(metadata.version,1);letkey=manager.get_key(&metadata.id).await.unwrap();assert_eq!(key.name,"encryption-key");assert_eq!(key.algorithm,KeyAlgorithm::Aes256);}#[tokio::test]asyncfntest_key_rotation(){letmanager=KeyManager::new("master-key".to_string(),Duration::from_days(30));letmetadata=manager.generate_key("test-key",KeyAlgorithm::Aes256,HashMap::new()).await.unwrap();letoriginal_version=metadata.version;letrotated_metadata=manager.rotate_key(&metadata.id).await.unwrap();assert_eq!(rotated_metadata.version,original_version+1);}}