Implement JSON credential storage

- Add JSON format for storing Vault credentials
- Update save_credentials function to support both formats
- Save both .json and .txt files for compatibility
- Update test_docker.sh to use jq for reliable JSON parsing
- Improve key extraction for unseal operations
- Update .gitignore to exclude JSON credentials

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Harald Hoyer 2025-03-20 13:16:39 +01:00
parent 98384791c3
commit 9b3ac63c3e
3 changed files with 150 additions and 159 deletions

1
.gitignore vendored
View file

@ -13,6 +13,7 @@ Cargo.lock
# Vault related files # Vault related files
vault-credentials.txt vault-credentials.txt
vault-credentials.json
vault-config/ vault-config/
# Temporary test files # Temporary test files

View file

@ -6,7 +6,6 @@ use std::{
fs::File, fs::File,
io::Write, io::Write,
path::Path, path::Path,
process::Command,
time::Duration, time::Duration,
}; };
use tokio::time::sleep; use tokio::time::sleep;
@ -40,6 +39,21 @@ struct UnsealRequest {
// Function to save Vault credentials to a file // Function to save Vault credentials to a file
fn save_credentials(response: &InitResponse, file_path: &str) -> Result<()> { fn save_credentials(response: &InitResponse, file_path: &str) -> Result<()> {
// For JSON output
if file_path.ends_with(".json") {
let json = serde_json::json!({
"keys": response.keys,
"keys_base64": response.keys_base64,
"root_token": response.root_token
});
let mut file = File::create(Path::new(file_path))?;
file.write_all(serde_json::to_string_pretty(&json)?.as_bytes())?;
println!("Credentials saved to JSON file: {}", file_path);
return Ok(());
}
// For plaintext output (legacy format)
let mut file = File::create(Path::new(file_path))?; let mut file = File::create(Path::new(file_path))?;
writeln!(file, "Unseal Keys:")?; writeln!(file, "Unseal Keys:")?;
for (i, key) in response.keys.iter().enumerate() { for (i, key) in response.keys.iter().enumerate() {
@ -51,7 +65,7 @@ fn save_credentials(response: &InitResponse, file_path: &str) -> Result<()> {
} }
writeln!(file)?; writeln!(file)?;
writeln!(file, "Root Token: {}", response.root_token)?; writeln!(file, "Root Token: {}", response.root_token)?;
println!("Credentials saved to {}", file_path); println!("Credentials saved to {}", file_path);
Ok(()) Ok(())
} }
@ -59,12 +73,12 @@ fn save_credentials(response: &InitResponse, file_path: &str) -> Result<()> {
// Wait for Vault to become available // Wait for Vault to become available
async fn wait_for_vault(addr: &str) -> Result<()> { async fn wait_for_vault(addr: &str) -> Result<()> {
println!("Waiting for Vault to be ready..."); println!("Waiting for Vault to be ready...");
let client = Client::new(); let client = Client::new();
for i in 1..=30 { for i in 1..=30 {
let health_url = format!("{}/v1/sys/health?standbyok=true&sealedok=true&uninitok=true", addr); let health_url = format!("{}/v1/sys/health?standbyok=true&sealedok=true&uninitok=true", addr);
match client.get(&health_url).timeout(Duration::from_secs(1)).send().await { match client.get(&health_url).timeout(Duration::from_secs(1)).send().await {
Ok(response) => { Ok(response) => {
let status = response.status().as_u16(); let status = response.status().as_u16();
@ -73,121 +87,55 @@ async fn wait_for_vault(addr: &str) -> Result<()> {
println!("Vault is available! Status code: {}", status); println!("Vault is available! Status code: {}", status);
return Ok(()); return Ok(());
} }
println!("Vault returned unexpected status code: {}", status); println!("Vault returned unexpected status code: {}", status);
}, },
Err(e) => { Err(e) => {
println!("Error connecting to Vault: {}", e); println!("Error connecting to Vault: {}", e);
} }
} }
if i == 30 { if i == 30 {
return Err(anyhow::anyhow!("Timed out waiting for Vault to become available")); return Err(anyhow::anyhow!("Timed out waiting for Vault to become available"));
} }
println!("Vault is unavailable - sleeping (attempt {}/30)", i); println!("Vault is unavailable - sleeping (attempt {}/30)", i);
sleep(Duration::from_secs(2)).await; sleep(Duration::from_secs(2)).await;
} }
Ok(())
}
// Function to copy credentials to a mounted volume if available
fn copy_credentials_to_volume(src_path: &str) -> Result<()> {
println!("Searching for credentials file...");
if let Ok(metadata) = std::fs::metadata(src_path) {
if metadata.is_file() {
println!("Found credentials at {}, copying...", src_path);
// Create the data directory if it doesn't exist
if let Err(e) = std::fs::create_dir_all("/app/data") {
println!("Warning: Couldn't create /app/data directory: {}", e);
} else {
let dest_path = "/app/data/vault-credentials.txt";
// Check if source and destination are the same
if src_path == dest_path {
println!("Source and destination are the same file, skipping copy");
} else {
match std::fs::copy(src_path, dest_path) {
Ok(_) => println!("Credentials saved to {}", dest_path),
Err(e) => println!("Failed to copy credentials: {}", e),
}
}
}
}
} else {
// If the file doesn't exist in the current directory, search for it
let output = Command::new("find")
.args(["/", "-name", "vault-credentials.txt", "-type", "f"])
.output();
match output {
Ok(output) => {
let files = String::from_utf8_lossy(&output.stdout);
let files: Vec<&str> = files.split('\n').filter(|s| !s.is_empty()).collect();
if !files.is_empty() {
println!("Found credentials at {}, copying...", files[0]);
// Create the data directory if it doesn't exist
if let Err(e) = std::fs::create_dir_all("/app/data") {
println!("Warning: Couldn't create /app/data directory: {}", e);
} else {
let dest_path = "/app/data/vault-credentials.txt";
// Check if source and destination are the same
if files[0] == dest_path {
println!("Source and destination are the same file, skipping copy");
} else {
match std::fs::copy(files[0], dest_path) {
Ok(_) => println!("Credentials saved to {}", dest_path),
Err(e) => println!("Failed to copy credentials: {}", e),
}
}
}
} else {
println!("Could not find credentials file");
}
},
Err(e) => println!("Failed to search for credentials: {}", e),
}
}
Ok(()) Ok(())
} }
async fn check_init_status(client: &Client, addr: &str) -> Result<bool> { async fn check_init_status(client: &Client, addr: &str) -> Result<bool> {
println!("Checking if Vault is already initialized..."); println!("Checking if Vault is already initialized...");
let response = client let response = client
.get(format!("{}/v1/sys/init", addr)) .get(format!("{}/v1/sys/init", addr))
.send() .send()
.await?; .await?;
if response.status().is_success() { if response.status().is_success() {
let status = response.json::<serde_json::Value>().await?; let status = response.json::<serde_json::Value>().await?;
if let Some(initialized) = status.get("initialized").and_then(|v| v.as_bool()) { if let Some(initialized) = status.get("initialized").and_then(|v| v.as_bool()) {
return Ok(initialized); return Ok(initialized);
} }
} }
// If we couldn't determine, assume not initialized // If we couldn't determine, assume not initialized
Ok(false) Ok(false)
} }
async fn check_seal_status(client: &Client, addr: &str) -> Result<SealStatusResponse> { async fn check_seal_status(client: &Client, addr: &str) -> Result<SealStatusResponse> {
println!("Checking Vault seal status..."); println!("Checking Vault seal status...");
let response = client let response = client
.get(format!("{}/v1/sys/seal-status", addr)) .get(format!("{}/v1/sys/seal-status", addr))
.send() .send()
.await?; .await?;
if response.status().is_success() { if response.status().is_success() {
let status = response.json::<SealStatusResponse>().await?; let status = response.json::<SealStatusResponse>().await?;
println!("Seal status: sealed={}, threshold={}, shares={}, progress={}", println!("Seal status: sealed={}, threshold={}, shares={}, progress={}",
status.sealed, status.t, status.n, status.progress); status.sealed, status.t, status.n, status.progress);
return Ok(status); return Ok(status);
} else { } else {
@ -199,26 +147,26 @@ async fn check_seal_status(client: &Client, addr: &str) -> Result<SealStatusResp
async fn init_vault(client: &Client, addr: &str) -> Result<InitResponse> { async fn init_vault(client: &Client, addr: &str) -> Result<InitResponse> {
// First check if already initialized // First check if already initialized
let initialized = check_init_status(client, addr).await?; let initialized = check_init_status(client, addr).await?;
if initialized { if initialized {
anyhow::bail!("Vault is already initialized. Cannot re-initialize."); anyhow::bail!("Vault is already initialized. Cannot re-initialize.");
} }
println!("Initializing Vault..."); println!("Initializing Vault...");
// Configure with 5 key shares and a threshold of 3 // Configure with 5 key shares and a threshold of 3
// This is a standard production configuration, requiring 3 out of 5 keys to unseal // This is a standard production configuration, requiring 3 out of 5 keys to unseal
let init_req = InitRequest { let init_req = InitRequest {
secret_shares: 5, secret_shares: 5,
secret_threshold: 3, secret_threshold: 3,
}; };
let response = client let response = client
.put(format!("{}/v1/sys/init", addr)) .put(format!("{}/v1/sys/init", addr))
.json(&init_req) .json(&init_req)
.send() .send()
.await?; .await?;
match response.status() { match response.status() {
StatusCode::OK => { StatusCode::OK => {
let init_response = response.json::<InitResponse>().await?; let init_response = response.json::<InitResponse>().await?;
@ -235,59 +183,59 @@ async fn init_vault(client: &Client, addr: &str) -> Result<InitResponse> {
async fn unseal_vault(client: &Client, addr: &str, unseal_keys: &[String]) -> Result<()> { async fn unseal_vault(client: &Client, addr: &str, unseal_keys: &[String]) -> Result<()> {
// First check the current seal status // First check the current seal status
let mut seal_status = check_seal_status(client, addr).await?; let mut seal_status = check_seal_status(client, addr).await?;
if !seal_status.sealed { if !seal_status.sealed {
println!("Vault is already unsealed!"); println!("Vault is already unsealed!");
return Ok(()); return Ok(());
} }
println!("Unsealing Vault..."); println!("Unsealing Vault...");
// We need to provide enough keys to meet the threshold // We need to provide enough keys to meet the threshold
// The threshold is in seal_status.t // The threshold is in seal_status.t
let required_keys = seal_status.t as usize; let required_keys = seal_status.t as usize;
if unseal_keys.len() < required_keys { if unseal_keys.len() < required_keys {
anyhow::bail!( anyhow::bail!(
"Not enough unseal keys provided. Need {} keys, but only have {}", "Not enough unseal keys provided. Need {} keys, but only have {}",
required_keys, required_keys,
unseal_keys.len() unseal_keys.len()
); );
} }
// Apply each key one at a time until unsealed // Apply each key one at a time until unsealed
for (i, key) in unseal_keys.iter().take(required_keys).enumerate() { for (i, key) in unseal_keys.iter().take(required_keys).enumerate() {
println!("Applying unseal key {}/{}...", i + 1, required_keys); println!("Applying unseal key {}/{}...", i + 1, required_keys);
let unseal_req = UnsealRequest { let unseal_req = UnsealRequest {
key: key.clone(), key: key.clone(),
}; };
let response = client let response = client
.put(format!("{}/v1/sys/unseal", addr)) .put(format!("{}/v1/sys/unseal", addr))
.json(&unseal_req) .json(&unseal_req)
.send() .send()
.await?; .await?;
if !response.status().is_success() { if !response.status().is_success() {
let error_text = response.text().await?; let error_text = response.text().await?;
anyhow::bail!("Failed to apply unseal key: {}", error_text); anyhow::bail!("Failed to apply unseal key: {}", error_text);
} }
// Check the updated seal status // Check the updated seal status
seal_status = check_seal_status(client, addr).await?; seal_status = check_seal_status(client, addr).await?;
if !seal_status.sealed { if !seal_status.sealed {
println!("Vault unsealed successfully after applying {} keys!", i + 1); println!("Vault unsealed successfully after applying {} keys!", i + 1);
return Ok(()); return Ok(());
} }
} }
// If we get here, we've applied all keys but Vault is still sealed // If we get here, we've applied all keys but Vault is still sealed
if seal_status.sealed { if seal_status.sealed {
anyhow::bail!("Applied all available unseal keys, but Vault is still sealed"); anyhow::bail!("Applied all available unseal keys, but Vault is still sealed");
} }
Ok(()) Ok(())
} }
@ -296,13 +244,13 @@ async fn main() -> Result<()> {
// Get Vault address from env var or use default // Get Vault address from env var or use default
let vault_addr = env::var("VAULT_ADDR").unwrap_or_else(|_| "http://127.0.0.1:8200".to_string()); let vault_addr = env::var("VAULT_ADDR").unwrap_or_else(|_| "http://127.0.0.1:8200".to_string());
let client = Client::new(); let client = Client::new();
println!("Vault address: {}", vault_addr); println!("Vault address: {}", vault_addr);
println!("Connecting to Vault at: {}", vault_addr); println!("Connecting to Vault at: {}", vault_addr);
// Wait for Vault to be available // Wait for Vault to be available
wait_for_vault(&vault_addr).await?; wait_for_vault(&vault_addr).await?;
// Get Vault status to display // Get Vault status to display
let health_url = format!("{}/v1/sys/health?standbyok=true&sealedok=true&uninitok=true", vault_addr); let health_url = format!("{}/v1/sys/health?standbyok=true&sealedok=true&uninitok=true", vault_addr);
match client.get(&health_url).send().await { match client.get(&health_url).send().await {
@ -314,19 +262,19 @@ async fn main() -> Result<()> {
}, },
Err(e) => println!("Error getting Vault status: {}", e), Err(e) => println!("Error getting Vault status: {}", e),
} }
// First check if Vault is already initialized // First check if Vault is already initialized
let initialized = check_init_status(&client, &vault_addr).await?; let initialized = check_init_status(&client, &vault_addr).await?;
if initialized { if initialized {
println!("Vault is already initialized."); println!("Vault is already initialized.");
// Check if Vault is sealed // Check if Vault is sealed
let seal_status = check_seal_status(&client, &vault_addr).await?; let seal_status = check_seal_status(&client, &vault_addr).await?;
if seal_status.sealed { if seal_status.sealed {
println!("Vault is sealed. Looking for unseal keys..."); println!("Vault is sealed. Looking for unseal keys...");
// Try to load unseal keys from environment variables // Try to load unseal keys from environment variables
let mut unseal_keys = Vec::new(); let mut unseal_keys = Vec::new();
for i in 1..=5 { for i in 1..=5 {
@ -340,7 +288,7 @@ async fn main() -> Result<()> {
} }
} }
} }
// If we have unseal keys, try to unseal // If we have unseal keys, try to unseal
if !unseal_keys.is_empty() { if !unseal_keys.is_empty() {
println!("Found {} unseal keys. Attempting to unseal...", unseal_keys.len()); println!("Found {} unseal keys. Attempting to unseal...", unseal_keys.len());
@ -356,21 +304,32 @@ async fn main() -> Result<()> {
// Initialize Vault // Initialize Vault
println!("Vault is not initialized. Proceeding with initialization..."); println!("Vault is not initialized. Proceeding with initialization...");
let init_response = init_vault(&client, &vault_addr).await?; let init_response = init_vault(&client, &vault_addr).await?;
// Save credentials to files // Save credentials to files
println!("Saving credentials to file..."); println!("Saving credentials to files...");
let current_dir = std::env::current_dir().context("Failed to get current directory")?; let current_dir = std::env::current_dir().context("Failed to get current directory")?;
let cred_path = current_dir.join("vault-credentials.txt");
save_credentials(&init_response, cred_path.to_str().unwrap())?;
println!("Credentials saved to: {}", cred_path.display());
// Save as JSON (new format)
let json_path = current_dir.join("vault-credentials.json");
save_credentials(&init_response, json_path.to_str().unwrap())?;
println!("JSON credentials saved to: {}", json_path.display());
// Save as text (for backward compatibility)
let text_path = current_dir.join("vault-credentials.txt");
save_credentials(&init_response, text_path.to_str().unwrap())?;
println!("Text credentials saved to: {}", text_path.display());
// Also save to /app/data as a backup for Docker volume mounting // Also save to /app/data as a backup for Docker volume mounting
if let Ok(()) = std::fs::create_dir_all("/app/data") { if let Ok(()) = std::fs::create_dir_all("/app/data") {
let docker_path = "/app/data/vault-credentials.txt"; let docker_json_path = "/app/data/vault-credentials.json";
save_credentials(&init_response, docker_path)?; save_credentials(&init_response, docker_json_path)?;
println!("Backup credentials saved to Docker volume at: {}", docker_path); println!("Backup JSON credentials saved to Docker volume at: {}", docker_json_path);
let docker_text_path = "/app/data/vault-credentials.txt";
save_credentials(&init_response, docker_text_path)?;
println!("Backup text credentials saved to Docker volume at: {}", docker_text_path);
} }
println!("========================================="); println!("=========================================");
println!("IMPORTANT: SAVE THESE CREDENTIALS SECURELY"); println!("IMPORTANT: SAVE THESE CREDENTIALS SECURELY");
println!("========================================="); println!("=========================================");
@ -380,33 +339,44 @@ async fn main() -> Result<()> {
println!("Key {}: {}", i + 1, key); println!("Key {}: {}", i + 1, key);
} }
println!("========================================="); println!("=========================================");
// Unseal Vault using the first three keys // Unseal Vault using the first three keys
let unseal_keys = init_response.keys_base64.iter() let unseal_keys = init_response.keys_base64.iter()
.take(3) // We only need threshold number of keys (3) .take(3) // We only need threshold number of keys (3)
.cloned() .cloned()
.collect::<Vec<String>>(); .collect::<Vec<String>>();
unseal_vault(&client, &vault_addr, &unseal_keys).await?; unseal_vault(&client, &vault_addr, &unseal_keys).await?;
println!("Vault is now initialized and unsealed");
// Store the root token and unseal keys in environment variables
// Using unsafe block as set_var is now considered unsafe in recent Rust
unsafe {
env::set_var("VAULT_TOKEN", &init_response.root_token);
for (i, key) in init_response.keys_base64.iter().enumerate() {
env::set_var(format!("VAULT_UNSEAL_KEY_{}", i + 1), key);
}
}
println!("Vault initialization and unseal complete!"); println!("Vault initialization and unseal complete!");
} }
// Copy credentials to the mounted volume (former docker-entrypoint.sh functionality) // Look for any existing credentials and copy them to the mounted volume
copy_credentials_to_volume("vault-credentials.txt")?; if let Ok(metadata) = std::fs::metadata("vault-credentials.json") {
if metadata.is_file() {
println!("Found JSON credentials file, ensuring it's saved to Docker volume...");
if let Ok(()) = std::fs::create_dir_all("/app/data") {
match std::fs::copy("vault-credentials.json", "/app/data/vault-credentials.json") {
Ok(_) => println!("JSON credentials saved to Docker volume"),
Err(e) => println!("Failed to copy JSON credentials: {}", e),
}
}
}
}
if let Ok(metadata) = std::fs::metadata("vault-credentials.txt") {
if metadata.is_file() {
println!("Found text credentials file, ensuring it's saved to Docker volume...");
if let Ok(()) = std::fs::create_dir_all("/app/data") {
match std::fs::copy("vault-credentials.txt", "/app/data/vault-credentials.txt") {
Ok(_) => println!("Text credentials saved to Docker volume"),
Err(e) => println!("Failed to copy text credentials: {}", e),
}
}
}
}
println!("Operation complete!"); println!("Operation complete!");
Ok(()) Ok(())
} }

View file

@ -99,22 +99,28 @@ wait_for_vault_init() {
# Wait for vault-init to complete # Wait for vault-init to complete
wait_for_vault_init wait_for_vault_init
# Check if vault-credentials.txt was created # Check if vault-credentials.json was created
if [ -f "vault-credentials.txt" ]; then if [ -f "vault-credentials.json" ]; then
log "INFO" "Credentials file was created successfully" log "INFO" "JSON credentials file was created successfully"
else else
log "ERROR" "Credentials file was not created" log "ERROR" "JSON credentials file was not created"
exit 1 exit 1
fi fi
# Verify the content of vault-credentials.txt # Verify the content of vault-credentials.json
if grep -q "Unseal Keys:" vault-credentials.txt && grep -q "Root Token:" vault-credentials.txt; then if jq -e '.keys_base64 | length' vault-credentials.json >/dev/null && \
log "INFO" "Credentials file contains expected content" jq -e '.root_token' vault-credentials.json >/dev/null; then
log "INFO" "JSON credentials file contains expected content"
else else
log "ERROR" "Credentials file doesn't contain expected content" log "ERROR" "JSON credentials file doesn't contain expected content"
exit 1 exit 1
fi fi
# Also check for backward compatibility
if [ -f "vault-credentials.txt" ]; then
log "INFO" "Text credentials file was also created (for backward compatibility)"
fi
# Verify Vault is unsealed after initial setup # Verify Vault is unsealed after initial setup
vault_status=$(docker-compose exec -T vault env VAULT_ADDR=http://127.0.0.1:8200 vault status -format=json 2>/dev/null || echo '{"sealed": true}') vault_status=$(docker-compose exec -T vault env VAULT_ADDR=http://127.0.0.1:8200 vault status -format=json 2>/dev/null || echo '{"sealed": true}')
@ -157,28 +163,35 @@ else
echo $vault_status echo $vault_status
fi fi
# Extract keys from credentials file and root token # Extract keys from JSON credentials file
log "INFO" "Extracting unseal keys and root token from credentials file..." log "INFO" "Extracting unseal keys and root token from JSON credentials file..."
unseal_keys=$(grep "Base64 Unseal Keys:" -A 3 vault-credentials.txt | grep "Key" | awk '{print $3}') # Using jq to extract the first 3 unseal keys (as that's the threshold)
root_token=$(grep "Root Token:" vault-credentials.txt | awk '{print $3}') unseal_keys=$(jq -r '.keys_base64[0:3][]' vault-credentials.json)
root_token=$(jq -r '.root_token' vault-credentials.json)
# First, try running 'vault operator unseal' directly for a more robust test # First, try running 'vault operator unseal' directly for a more robust test
log "INFO" "Attempting to unseal Vault directly with unseal keys..." log "INFO" "Attempting to unseal Vault directly with unseal keys..."
key1=$(echo "$unseal_keys" | head -n 1) # Using an array to capture the keys
key2=$(echo "$unseal_keys" | head -n 2 | tail -n 1) readarray -t key_array <<< "$unseal_keys"
key3=$(echo "$unseal_keys" | head -n 3 | tail -n 1)
docker-compose exec -T vault env VAULT_ADDR=http://127.0.0.1:8200 vault operator unseal "$key1" for key in "${key_array[@]}"; do
docker-compose exec -T vault env VAULT_ADDR=http://127.0.0.1:8200 vault operator unseal "$key2" log "INFO" "Applying unseal key: ${key:0:8}..." # Show only first 8 chars for security
docker-compose exec -T vault env VAULT_ADDR=http://127.0.0.1:8200 vault operator unseal "$key3" docker-compose exec -T vault env VAULT_ADDR=http://127.0.0.1:8200 vault operator unseal "$key"
done
# As a fallback, also try running vault-init with environment variables # As a fallback, also try running vault-init with environment variables
log "INFO" "Starting vault-init with environment variables..." log "INFO" "Starting vault-init with environment variables..."
docker-compose run -e VAULT_ADDR=http://vault:8200 \ # Check how many keys we have
-e VAULT_UNSEAL_KEY_1=$(echo "$unseal_keys" | head -n 1) \ key_count=${#key_array[@]}
-e VAULT_UNSEAL_KEY_2=$(echo "$unseal_keys" | head -n 2 | tail -n 1) \ env_vars="-e VAULT_ADDR=http://vault:8200"
-e VAULT_UNSEAL_KEY_3=$(echo "$unseal_keys" | head -n 3 | tail -n 1) \
--rm vault-init # Add each key to environment variables
for i in $(seq 0 $((key_count-1))); do
env_vars="$env_vars -e VAULT_UNSEAL_KEY_$((i+1))=${key_array[$i]}"
done
# Run the command with all environment variables
docker-compose run $env_vars --rm vault-init
# Verify Vault is unsealed now # Verify Vault is unsealed now
vault_status=$(docker-compose exec -T vault env VAULT_ADDR=http://127.0.0.1:8200 vault status -format=json 2>/dev/null || echo '{"sealed": true}') vault_status=$(docker-compose exec -T vault env VAULT_ADDR=http://127.0.0.1:8200 vault status -format=json 2>/dev/null || echo '{"sealed": true}')
@ -197,9 +210,16 @@ fi
# Test some basic Vault operations # Test some basic Vault operations
log "INFO" "Testing basic Vault operations..." log "INFO" "Testing basic Vault operations..."
# Write a secret # Write a secret using the root token from JSON credentials
token_result=$(docker-compose exec -T vault env VAULT_ADDR=http://127.0.0.1:8200 vault login "$root_token" 2>&1) token_result=$(docker-compose exec -T vault env VAULT_ADDR=http://127.0.0.1:8200 vault login "$root_token" 2>&1)
log "INFO" "Login result: $(echo "$token_result" | grep "Success")" login_success=$(echo "$token_result" | grep -c "Success" || echo "0")
if [ "$login_success" -gt 0 ]; then
log "INFO" "Successfully logged in with root token"
else
log "ERROR" "Failed to log in with root token"
echo "$token_result"
exit 1
fi
# Enable KV secrets engine # Enable KV secrets engine
enable_result=$(docker-compose exec -T vault env VAULT_ADDR=http://127.0.0.1:8200 vault secrets enable -path=kv kv 2>&1 || echo "KV already enabled") enable_result=$(docker-compose exec -T vault env VAULT_ADDR=http://127.0.0.1:8200 vault secrets enable -path=kv kv 2>&1 || echo "KV already enabled")