Jesús Pérez 1fe83246d6
feat: integrate enterprise security system into core libraries
Adds KMS, secrets management, config encryption, and auth plugins to enable
zero-trust security architecture across the provisioning platform.
2025-10-09 16:36:27 +01:00

395 lines
13 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Configuration Encryption CLI Commands
# Provides user-friendly commands for config encryption operations
use encryption.nu *
use accessor.nu *
# Encrypt a configuration file
export def "config encrypt" [
file: path # Configuration file to encrypt
--output (-o): path # Output path (default: <file>.enc)
--kms (-k): string = "age" # KMS backend: age, aws-kms, vault, cosmian
--in-place (-i) # Encrypt in-place (overwrites original)
--debug (-d) # Enable debug output
] {
if not ($file | path exists) {
print $"❌ File not found: ($file)"
return
}
print $"🔒 Encrypting configuration file: ($file)"
print $" Backend: ($kms)"
if $in_place {
print $" Mode: In-place (will overwrite original)"
} else if ($output | is-not-empty) {
print $" Output: ($output)"
} else {
print $" Output: ($file).enc"
}
try {
if $in_place {
encrypt-config $file --kms=$kms --in-place --debug=$debug
} else {
encrypt-config $file $output --kms=$kms --debug=$debug
}
} catch { |err|
print $"❌ Encryption failed: ($err.msg)"
}
}
# Decrypt a configuration file
export def "config decrypt" [
file: path # Encrypted configuration file
--output (-o): path # Output path (default: removes .enc extension)
--in-place (-i) # Decrypt in-place (overwrites original)
--debug (-d) # Enable debug output
] {
if not ($file | path exists) {
print $"❌ File not found: ($file)"
return
}
print $"🔓 Decrypting configuration file: ($file)"
try {
if $in_place {
decrypt-config $file --in-place --debug=$debug
} else {
decrypt-config $file $output --debug=$debug
}
} catch { |err|
print $"❌ Decryption failed: ($err.msg)"
}
}
# Edit encrypted configuration file securely
export def "config edit-secure" [
file: path # Encrypted configuration file
--editor (-e): string # Editor to use (default: $EDITOR or vim)
--debug (-d) # Enable debug output
] {
if not ($file | path exists) {
print $"❌ File not found: ($file)"
return
}
try {
if ($editor | is-not-empty) {
edit-encrypted-config $file --editor=$editor --debug=$debug
} else {
edit-encrypted-config $file --debug=$debug
}
} catch { |err|
print $"❌ Edit failed: ($err.msg)"
}
}
# Rotate encryption keys for a configuration file
export def "config rotate-keys" [
file: path # Encrypted configuration file
new_key: string # New key ID or recipient
--debug (-d) # Enable debug output
] {
if not ($file | path exists) {
print $"❌ File not found: ($file)"
return
}
print $"🔄 Rotating encryption keys"
print $" File: ($file)"
print $" New key: ($new_key)"
try {
rotate-encryption-keys $file $new_key --debug=$debug
} catch { |err|
print $"❌ Key rotation failed: ($err.msg)"
}
}
# Check if a configuration file is encrypted
export def "config is-encrypted" [
file: path # Configuration file to check
] {
if not ($file | path exists) {
print $"❌ File not found: ($file)"
return
}
let encrypted = (is-encrypted-config $file)
if $encrypted {
print $"🔒 File is encrypted: ($file)"
} else {
print $"🔓 File is not encrypted: ($file)"
}
$encrypted
}
# Validate encryption configuration and setup
export def "config validate-encryption" [] {
print $"🔍 Validating encryption configuration..."
print ""
let validation = (validate-encryption-config)
# Show summary
print $"📊 Encryption Configuration Summary"
print $"=================================="
print $" SOPS installed: ($validation.summary.sops_installed)"
print $" Age backend: ($validation.summary.age_backend)"
print $" KMS enabled: ($validation.summary.kms_enabled)"
print $" Errors: ($validation.summary.total_errors)"
print $" Warnings: ($validation.summary.total_warnings)"
print ""
# Show errors
if ($validation.errors | length) > 0 {
print $"❌ Errors:"
for error in $validation.errors {
print $" • ($error.message)"
}
print ""
}
# Show warnings
if ($validation.warnings | length) > 0 {
print $"⚠️ Warnings:"
for warning in $validation.warnings {
print $" • ($warning.message)"
}
print ""
}
if $validation.valid {
print $"✅ Encryption configuration is valid"
} else {
print $"❌ Encryption configuration has errors"
}
$validation
}
# Scan directory for unencrypted sensitive configurations
export def "config scan-sensitive" [
directory: path = "." # Directory to scan
--recursive (-r) # Scan recursively
] {
if not ($directory | path exists) {
print $"❌ Directory not found: ($directory)"
return
}
print $"🔍 Scanning for unencrypted sensitive configs in: ($directory)"
let results = (scan-unencrypted-configs $directory --recursive=$recursive)
if ($results | is-empty) {
print $"✅ No unencrypted sensitive configs found"
} else {
print $"\n⚠ Found ($results | length) unencrypted sensitive configs:"
print ""
print $results
print ""
print $"💡 Run 'config encrypt-all ($directory)' to encrypt them"
}
$results
}
# Encrypt all sensitive configurations in directory
export def "config encrypt-all" [
directory: path = "." # Directory to encrypt
--kms (-k): string = "age" # KMS backend: age, aws-kms, vault, cosmian
--recursive (-r) # Scan recursively
--dry-run (-n) # Dry run (no actual encryption)
] {
if not ($directory | path exists) {
print $"❌ Directory not found: ($directory)"
return
}
try {
encrypt-sensitive-configs $directory --kms=$kms --recursive=$recursive --dry-run=$dry_run
} catch { |err|
print $"❌ Bulk encryption failed: ($err.msg)"
}
}
# Show encryption information for configuration
export def "config encryption-info" [
file: path # Configuration file
] {
if not ($file | path exists) {
print $"❌ File not found: ($file)"
return
}
print $"📋 Encryption Information"
print $"========================"
print $" File: ($file)"
let encrypted = (is-encrypted-config $file)
print $" Encrypted: ($encrypted)"
if $encrypted {
# Try to extract SOPS metadata
try {
let content = (open $file --raw)
if ($content | str contains "sops:") {
print $" Type: SOPS encrypted"
# Extract some metadata (without decrypting)
if ($content | str contains "age:") {
print $" Backend: Age"
}
if ($content | str contains "kms:") {
print $" Backend: AWS KMS"
}
if ($content | str contains "vault:") {
print $" Backend: Vault"
}
}
} catch {
print $" Type: Encrypted (unknown format)"
}
} else {
let sensitive = (contains-sensitive-data $file)
print $" Contains sensitive data: ($sensitive)"
if $sensitive {
print ""
print $"⚠️ This file contains sensitive data but is not encrypted!"
print $"💡 Run 'config encrypt ($file)' to encrypt it"
}
}
}
# Initialize encryption setup (generate keys, create SOPS config)
export def "config init-encryption" [
--kms (-k): string = "age" # KMS backend to initialize: age, aws-kms, vault
--force (-f) # Force re-initialization
] {
print $"🔧 Initializing encryption setup with ($kms)"
print ""
match $kms {
"age" => {
# Check if age is installed
let age_check = (^which age | complete)
if $age_check.exit_code != 0 {
print $"❌ Age is not installed"
print $"💡 Install with: brew install age"
return
}
# Generate age key if not exists
let age_key_file = ($env.HOME | path join ".config" | path join "sops" | path join "age" | path join "keys.txt")
let age_key_dir = ($age_key_file | path dirname)
if ($age_key_file | path exists) and not $force {
print $"✅ Age key already exists: ($age_key_file)"
print $" Use --force to regenerate"
} else {
# Create directory
mkdir $age_key_dir
# Generate new age key
print $"🔑 Generating new Age key..."
let key_output = (^age-keygen -o $age_key_file | complete)
if $key_output.exit_code == 0 {
print $"✅ Age key generated: ($age_key_file)"
# Extract recipient
let key_content = (open $age_key_file --raw)
let recipient = ($key_content | lines | where ($it | str starts-with "# public key:") | first | split row ": " | get 1)
print $" Public key (recipient): ($recipient)"
print ""
print $"💡 Set this environment variable:"
print $" export SOPS_AGE_RECIPIENTS=($recipient)"
} else {
print $"❌ Failed to generate Age key"
return
}
}
# Create .sops.yaml if not exists
let sops_config = ($env.PWD | path join ".sops.yaml")
if not ($sops_config | path exists) or $force {
print $"📝 Creating SOPS configuration: ($sops_config)"
let key_content = (open $age_key_file --raw)
let recipient = ($key_content | lines | where ($it | str starts-with "# public key:") | first | split row ": " | get 1)
let sops_yaml = $"creation_rules:
- path_regex: .*\\.enc\\.yaml$
age: ($recipient)
- path_regex: .*\\.enc\\.yml$
age: ($recipient)
- path_regex: .*\\.enc\\.toml$
age: ($recipient)
- path_regex: .*\\.enc\\.json$
age: ($recipient)
- path_regex: workspace/.*/config/secure\\.yaml$
age: ($recipient)
"
$sops_yaml | save --force $sops_config
print $"✅ SOPS configuration created"
}
}
"aws-kms" => {
print $"⚠️ AWS KMS requires manual configuration"
print $"💡 Follow these steps:"
print $" 1. Create KMS key in AWS Console"
print $" 2. Update .sops.yaml with KMS ARN"
print $" 3. Configure AWS credentials"
}
"vault" | "cosmian" => {
print $"⚠️ ($kms) KMS requires manual configuration"
print $"💡 Configure KMS settings in config file"
}
_ => {
print $"❌ Unknown KMS backend: ($kms)"
print $" Supported: age, aws-kms, vault, cosmian"
}
}
print ""
print $"✅ Encryption initialization completed"
}
# Main help command
export def main [] {
print "Configuration Encryption Commands"
print "================================="
print ""
print "Encryption/Decryption:"
print " config encrypt <file> Encrypt configuration file"
print " config decrypt <file> Decrypt configuration file"
print " config edit-secure <file> Edit encrypted file securely"
print " config rotate-keys <file> Rotate encryption keys"
print ""
print "Information:"
print " config is-encrypted <file> Check if file is encrypted"
print " config encryption-info <file> Show encryption details"
print " config validate-encryption Validate encryption setup"
print ""
print "Bulk Operations:"
print " config scan-sensitive <dir> Find unencrypted sensitive configs"
print " config encrypt-all <dir> Encrypt all sensitive configs"
print ""
print "Setup:"
print " config init-encryption Initialize encryption (generate keys)"
print ""
print "Examples:"
print " config encrypt workspace/config/secure.yaml"
print " config edit-secure workspace/config/secure.enc.yaml"
print " config scan-sensitive workspace/config --recursive"
print " config init-encryption --kms age"
}