106 lines
2.7 KiB
Text
106 lines
2.7 KiB
Text
|
|
#!/usr/bin/env nu
|
||
|
|
# SOPS encryption with vault-service age keys
|
||
|
|
# Encrypts configuration files using Age public key from vault-service
|
||
|
|
# Usage: secrets-encrypt <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-public-key [environment: string] {
|
||
|
|
let url = $"(get-vault-url)/api/v1/age/get-public?env=($environment)"
|
||
|
|
let token = (get-vault-token)
|
||
|
|
|
||
|
|
let headers = if ($token | is-empty) {
|
||
|
|
{}
|
||
|
|
} else {
|
||
|
|
{"X-Vault-Token": $token}
|
||
|
|
}
|
||
|
|
|
||
|
|
let response = (http get -H $headers $url | complete)
|
||
|
|
|
||
|
|
if $response.exit_code != 0 {
|
||
|
|
error make {
|
||
|
|
msg: "Cannot connect to vault-service"
|
||
|
|
label: {
|
||
|
|
text: $"Check VAULT_SERVICE_URL (set to: (get-vault-url))"
|
||
|
|
span: (metadata $environment).span
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
let json = ($response.stdout | from json)
|
||
|
|
$json.public_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) {
|
||
|
|
$"($input_path).enc"
|
||
|
|
} else {
|
||
|
|
$output
|
||
|
|
}
|
||
|
|
|
||
|
|
print $"Fetching Age public key for ($environment)..."
|
||
|
|
let pubkey = (fetch-age-public-key $environment)
|
||
|
|
print $"✓ Age public key: ($pubkey | str substring 0..20)..."
|
||
|
|
|
||
|
|
print $"Encrypting ($input_path) with SOPS..."
|
||
|
|
let result = (
|
||
|
|
^sops --encrypt --age $pubkey --encrypted-regex '^(password|token|key|secret|api_key)$' --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 encryption failed"
|
||
|
|
label: {
|
||
|
|
text: $stderr
|
||
|
|
span: (metadata $file).span
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
print $"✓ Encrypted file: ($output_path)"
|
||
|
|
{
|
||
|
|
success: true
|
||
|
|
input: $input_path
|
||
|
|
output: $output_path
|
||
|
|
environment: $environment
|
||
|
|
public_key: $pubkey
|
||
|
|
}
|
||
|
|
}
|