#!/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 [--environment dev|staging|prod] [--output ] 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" } }