provisioning/scripts/secrets-decrypt.nu

113 lines
3 KiB
Text
Raw Normal View History

#!/usr/bin/env nu
# SOPS decryption with vault-service age keys
# Decrypts SOPS-encrypted files using Age private key from vault-service
# Usage: secrets-decrypt <file> [--environment dev|staging|prod] [--output <file>]
use std log
def get-vault-url [] {
$env.VAULT_SERVICE_URL? // "http://localhost:9094"
}
def get-vault-token [] {
$env.VAULT_SERVICE_TOKEN? // ""
}
def fetch-age-private-key [environment: string] {
let url = $"(get-vault-url)/api/v1/age/get-private?env=($environment)"
let token = (get-vault-token)
if ($token | is-empty) {
error make {
msg: "VAULT_SERVICE_TOKEN required for private key retrieval"
label: {
text: "Set environment variable or pass token"
span: (metadata $environment).span
}
}
}
let response = (http get -H {"X-Vault-Token": $token} $url | complete)
if $response.exit_code != 0 {
error make {
msg: "Failed to fetch age private key"
label: {
text: "vault-service rejected request (check token and permissions)"
span: (metadata $environment).span
}
}
}
let json = ($response.stdout | from json)
$json.private_key
}
def main [
file: string
--environment: string = "dev"
--output: string = ""
] {
let input_path = if ($file | path exists) {
$file
} else {
error make {
msg: "File not found"
label: {
text: $file
span: (metadata $file).span
}
}
}
# Validate environment
if $environment not-in ["dev", "staging", "prod"] {
error make {
msg: "Invalid environment"
label: {
text: "Must be: dev, staging, or prod"
span: (metadata $file).span
}
}
}
let output_path = if ($output | is-empty) {
let base = ($input_path | str replace '.enc' '')
$"($base).dec"
} else {
$output
}
print $"SENSITIVE: Fetching Age private key for ($environment) from vault-service..."
let privkey = (fetch-age-private-key $environment)
print "✓ Age private key retrieved (check audit logs for access tracking)"
print $"Decrypting ($input_path) with SOPS..."
let result = (
with-env {"SOPS_AGE_KEY": $privkey} {
^sops --decrypt --input-type "yaml" --output-type "yaml" --output $output_path $input_path
| complete
}
)
if $result.exit_code != 0 {
let stderr = $result.stderr
error make {
msg: "SOPS decryption failed"
label: {
text: $stderr
span: (metadata $file).span
}
}
}
print $"✓ Decrypted file: ($output_path)"
{
success: true
input: $input_path
output: $output_path
environment: $environment
message: "Private key was used from vault-service and is NOT stored locally"
}
}