Initial commit: Full Crawl API implementation
This commit is contained in:
69
crates/api/src/secrets/mod.rs
Normal file
69
crates/api/src/secrets/mod.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
use shared::error::AppError;
|
||||
|
||||
pub async fn get_secret(key: &str) -> Result<String, AppError> {
|
||||
// Priority 1: Environment variable (for local dev)
|
||||
if let Ok(val) = std::env::var(key) {
|
||||
return Ok(val);
|
||||
}
|
||||
|
||||
// Priority 2: Try Vault
|
||||
if let Ok(val) = get_vault_secret(key).await {
|
||||
return Ok(val);
|
||||
}
|
||||
|
||||
// Priority 3: Try AWS Secrets Manager
|
||||
if let Ok(val) = get_aws_secret(key).await {
|
||||
return Ok(val);
|
||||
}
|
||||
|
||||
Err(AppError::Internal(format!("Secret {} not found in any provider", key)))
|
||||
}
|
||||
|
||||
async fn get_vault_secret(key: &str) -> Result<String, AppError> {
|
||||
let vault_addr = match std::env::var("VAULT_ADDR") {
|
||||
Ok(addr) => addr,
|
||||
Err(_) => return Err(AppError::Internal("VAULT_ADDR not set".to_string())),
|
||||
};
|
||||
|
||||
let vault_token = match std::env::var("VAULT_TOKEN") {
|
||||
Ok(token) => token,
|
||||
Err(_) => return Err(AppError::Internal("VAULT_TOKEN not set".to_string())),
|
||||
};
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
.get(format!("{}/v1/secret/data/{}", vault_addr, key))
|
||||
.header("X-Vault-Token", vault_token)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| AppError::Internal(format!("Vault request failed: {}", e)))?;
|
||||
|
||||
let data: serde_json::Value = response
|
||||
.json()
|
||||
.await
|
||||
.map_err(|e| AppError::Internal(format!("Vault response parse failed: {}", e)))?;
|
||||
|
||||
data["data"]["data"][key]
|
||||
.as_str()
|
||||
.map(|s| s.to_string())
|
||||
.ok_or_else(|| AppError::Internal(format!("Secret {} not found in Vault", key)))
|
||||
}
|
||||
|
||||
async fn get_aws_secret(key: &str) -> Result<String, AppError> {
|
||||
let secret_name = format!("crawlapi/{}", key.to_lowercase().replace('_', "/"));
|
||||
|
||||
let config = aws_config::from_env().load().await;
|
||||
let client = aws_sdk_secretsmanager::Client::new(&config);
|
||||
|
||||
let response = client
|
||||
.get_secret_value()
|
||||
.secret_id(&secret_name)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| AppError::Internal(format!("AWS Secrets Manager error: {}", e)))?;
|
||||
|
||||
response
|
||||
.secret_string()
|
||||
.map(|s| s.to_string())
|
||||
.ok_or_else(|| AppError::Internal(format!("Secret {} not found in AWS", key)))
|
||||
}
|
||||
Reference in New Issue
Block a user