- Documented Fluent-based i18n system with locale detection - Bumped version from 1.0.10 to 1.0.11
499 lines
13 KiB
Plaintext
499 lines
13 KiB
Plaintext
# SecretumVault Plugin Wrapper with HTTP Fallback
|
|
# Provides high-level functions for SecretumVault operations with graceful HTTP fallback
|
|
|
|
use ../config/accessor.nu *
|
|
|
|
# Check if SecretumVault plugin is available
|
|
def is-plugin-available [] {
|
|
(which secretumvault | length) > 0
|
|
}
|
|
|
|
# Check if SecretumVault plugin is enabled in config
|
|
def is-plugin-enabled [] {
|
|
config-get "plugins.secretumvault_enabled" true
|
|
}
|
|
|
|
# Get SecretumVault service URL
|
|
def get-secretumvault-url [] {
|
|
config-get "kms.secretumvault.server_url" "http://localhost:8200"
|
|
}
|
|
|
|
# Get SecretumVault auth token
|
|
def get-secretumvault-token [] {
|
|
let token = (
|
|
if ($env.SECRETUMVAULT_TOKEN? != null) {
|
|
$env.SECRETUMVAULT_TOKEN
|
|
} else {
|
|
""
|
|
}
|
|
)
|
|
if ($token | is-empty) {
|
|
config-get "kms.secretumvault.auth_token" ""
|
|
} else {
|
|
$token
|
|
}
|
|
}
|
|
|
|
# Get SecretumVault mount point
|
|
def get-secretumvault-mount-point [] {
|
|
config-get "kms.secretumvault.mount_point" "transit"
|
|
}
|
|
|
|
# Get default SecretumVault key name
|
|
def get-secretumvault-key-name [] {
|
|
config-get "kms.secretumvault.key_name" "provisioning-master"
|
|
}
|
|
|
|
# Helper to safely execute a closure and return null on error
|
|
def try-plugin [callback: closure] {
|
|
do -i $callback
|
|
}
|
|
|
|
# Encrypt data using SecretumVault plugin
|
|
export def plugin-secretumvault-encrypt [
|
|
plaintext: string
|
|
--key-id: string = "" # Encryption key ID
|
|
] {
|
|
let enabled = is-plugin-enabled
|
|
let available = is-plugin-available
|
|
let key_name = if ($key_id | is-empty) { get-secretumvault-key-name } else { $key_id }
|
|
|
|
if $enabled and $available {
|
|
let plugin_result = (try-plugin {
|
|
let args = if ($key_id | is-empty) {
|
|
[encrypt $plaintext]
|
|
} else {
|
|
[encrypt $plaintext --key-id $key_id]
|
|
}
|
|
|
|
secretumvault ...$args
|
|
})
|
|
|
|
if $plugin_result != null {
|
|
return $plugin_result
|
|
}
|
|
|
|
print "⚠️ Plugin SecretumVault encrypt failed, falling back to HTTP"
|
|
}
|
|
|
|
# HTTP fallback - call SecretumVault service directly
|
|
print "⚠️ Using HTTP fallback (plugin not available)"
|
|
|
|
let sv_url = (get-secretumvault-url)
|
|
let sv_token = (get-secretumvault-token)
|
|
let mount_point = (get-secretumvault-mount-point)
|
|
let url = $"($sv_url)/v1/($mount_point)/encrypt/($key_name)"
|
|
|
|
if ($sv_token | is-empty) {
|
|
error make {
|
|
msg: "SecretumVault authentication failed"
|
|
label: {
|
|
text: "SECRETUMVAULT_TOKEN not set"
|
|
span: (metadata $plaintext).span
|
|
}
|
|
}
|
|
}
|
|
|
|
let result = (do -i {
|
|
let plaintext_b64 = ($plaintext | encode base64)
|
|
let body = {plaintext: $plaintext_b64}
|
|
|
|
http post -H ["X-Vault-Token" $sv_token] $url $body
|
|
})
|
|
|
|
if $result != null {
|
|
return $result
|
|
}
|
|
|
|
error make {
|
|
msg: "SecretumVault encryption failed"
|
|
label: {
|
|
text: $"Failed to encrypt data with key ($key_name)"
|
|
span: (metadata $plaintext).span
|
|
}
|
|
}
|
|
}
|
|
|
|
# Decrypt data using SecretumVault plugin
|
|
export def plugin-secretumvault-decrypt [
|
|
ciphertext: string
|
|
--key-id: string = "" # Encryption key ID
|
|
] {
|
|
let enabled = is-plugin-enabled
|
|
let available = is-plugin-available
|
|
let key_name = if ($key_id | is-empty) { get-secretumvault-key-name } else { $key_id }
|
|
|
|
if $enabled and $available {
|
|
let plugin_result = (try-plugin {
|
|
let args = if ($key_id | is-empty) {
|
|
[decrypt $ciphertext]
|
|
} else {
|
|
[decrypt $ciphertext --key-id $key_id]
|
|
}
|
|
|
|
secretumvault ...$args
|
|
})
|
|
|
|
if $plugin_result != null {
|
|
return $plugin_result
|
|
}
|
|
|
|
print "⚠️ Plugin SecretumVault decrypt failed, falling back to HTTP"
|
|
}
|
|
|
|
# HTTP fallback - call SecretumVault service directly
|
|
print "⚠️ Using HTTP fallback (plugin not available)"
|
|
|
|
let sv_url = (get-secretumvault-url)
|
|
let sv_token = (get-secretumvault-token)
|
|
let mount_point = (get-secretumvault-mount-point)
|
|
let url = $"($sv_url)/v1/($mount_point)/decrypt/($key_name)"
|
|
|
|
if ($sv_token | is-empty) {
|
|
error make {
|
|
msg: "SecretumVault authentication failed"
|
|
label: {
|
|
text: "SECRETUMVAULT_TOKEN not set"
|
|
span: (metadata $ciphertext).span
|
|
}
|
|
}
|
|
}
|
|
|
|
let result = (do -i {
|
|
let body = {ciphertext: $ciphertext}
|
|
|
|
let response = (http post -H ["X-Vault-Token" $sv_token] $url $body)
|
|
|
|
if ($response.data.plaintext? != null) {
|
|
{
|
|
plaintext: ($response.data.plaintext | decode base64),
|
|
key_id: ($response.data.key_id? // $key_name)
|
|
}
|
|
} else {
|
|
$response
|
|
}
|
|
})
|
|
|
|
if $result != null {
|
|
return $result
|
|
}
|
|
|
|
error make {
|
|
msg: "SecretumVault decryption failed"
|
|
label: {
|
|
text: $"Failed to decrypt data with key ($key_name)"
|
|
span: (metadata $ciphertext).span
|
|
}
|
|
}
|
|
}
|
|
|
|
# Generate data key using SecretumVault plugin
|
|
export def plugin-secretumvault-generate-key [
|
|
--bits: int = 256 # Key size in bits (128, 256, 2048, 4096)
|
|
--key-id: string = "" # Encryption key ID
|
|
] {
|
|
let enabled = is-plugin-enabled
|
|
let available = is-plugin-available
|
|
let key_name = if ($key_id | is-empty) { get-secretumvault-key-name } else { $key_id }
|
|
|
|
if $enabled and $available {
|
|
let plugin_result = (try-plugin {
|
|
let args = if ($key_id | is-empty) {
|
|
[generate-key --bits $bits]
|
|
} else {
|
|
[generate-key --bits $bits --key-id $key_id]
|
|
}
|
|
|
|
secretumvault ...$args
|
|
})
|
|
|
|
if $plugin_result != null {
|
|
return $plugin_result
|
|
}
|
|
|
|
print "⚠️ Plugin SecretumVault generate-key failed, falling back to HTTP"
|
|
}
|
|
|
|
# HTTP fallback
|
|
print "⚠️ Using HTTP fallback (plugin not available)"
|
|
|
|
let sv_url = (get-secretumvault-url)
|
|
let sv_token = (get-secretumvault-token)
|
|
let mount_point = (get-secretumvault-mount-point)
|
|
let url = $"($sv_url)/v1/($mount_point)/datakey/plaintext/($key_name)"
|
|
|
|
if ($sv_token | is-empty) {
|
|
error make {
|
|
msg: "SecretumVault authentication failed"
|
|
label: {
|
|
text: "SECRETUMVAULT_TOKEN not set"
|
|
}
|
|
}
|
|
}
|
|
|
|
let result = (do -i {
|
|
let body = {bits: $bits}
|
|
http post -H ["X-Vault-Token" $sv_token] $url $body
|
|
})
|
|
|
|
if $result != null {
|
|
return $result
|
|
}
|
|
|
|
error make {
|
|
msg: "SecretumVault key generation failed"
|
|
label: {
|
|
text: $"Failed to generate key with ($bits) bits"
|
|
}
|
|
}
|
|
}
|
|
|
|
# Check SecretumVault health using plugin
|
|
export def plugin-secretumvault-health [] {
|
|
let enabled = is-plugin-enabled
|
|
let available = is-plugin-available
|
|
|
|
if $enabled and $available {
|
|
let plugin_result = (try-plugin {
|
|
secretumvault health
|
|
})
|
|
|
|
if $plugin_result != null {
|
|
return $plugin_result
|
|
}
|
|
|
|
print "⚠️ Plugin SecretumVault health check failed, falling back to HTTP"
|
|
}
|
|
|
|
# HTTP fallback
|
|
print "⚠️ Using HTTP fallback (plugin not available)"
|
|
|
|
let sv_url = (get-secretumvault-url)
|
|
let url = $"($sv_url)/v1/sys/health"
|
|
|
|
let result = (do -i {
|
|
http get $url
|
|
})
|
|
|
|
if $result != null {
|
|
return $result
|
|
}
|
|
|
|
{
|
|
healthy: false
|
|
status: "unavailable"
|
|
message: "SecretumVault service unreachable"
|
|
}
|
|
}
|
|
|
|
# Get SecretumVault version using plugin
|
|
export def plugin-secretumvault-version [] {
|
|
let enabled = is-plugin-enabled
|
|
let available = is-plugin-available
|
|
|
|
if $enabled and $available {
|
|
let plugin_result = (try-plugin {
|
|
secretumvault version
|
|
})
|
|
|
|
if $plugin_result != null {
|
|
return $plugin_result
|
|
}
|
|
|
|
print "⚠️ Plugin SecretumVault version failed, falling back to HTTP"
|
|
}
|
|
|
|
# HTTP fallback
|
|
print "⚠️ Using HTTP fallback (plugin not available)"
|
|
|
|
let sv_url = (get-secretumvault-url)
|
|
let url = $"($sv_url)/v1/sys/health"
|
|
|
|
let result = (do -i {
|
|
let response = (http get $url)
|
|
$response.version? // "unknown"
|
|
})
|
|
|
|
if $result != null {
|
|
return $result
|
|
}
|
|
|
|
"unavailable"
|
|
}
|
|
|
|
# Rotate encryption key using plugin
|
|
export def plugin-secretumvault-rotate-key [
|
|
--key-id: string = "" # Key ID to rotate
|
|
] {
|
|
let enabled = is-plugin-enabled
|
|
let available = is-plugin-available
|
|
let key_name = if ($key_id | is-empty) { get-secretumvault-key-name } else { $key_id }
|
|
|
|
if $enabled and $available {
|
|
let plugin_result = (try-plugin {
|
|
let args = if ($key_id | is-empty) {
|
|
[rotate-key]
|
|
} else {
|
|
[rotate-key --key-id $key_id]
|
|
}
|
|
|
|
secretumvault ...$args
|
|
})
|
|
|
|
if $plugin_result != null {
|
|
return $plugin_result
|
|
}
|
|
|
|
print "⚠️ Plugin SecretumVault rotate-key failed, falling back to HTTP"
|
|
}
|
|
|
|
# HTTP fallback
|
|
print "⚠️ Using HTTP fallback (plugin not available)"
|
|
|
|
let sv_url = (get-secretumvault-url)
|
|
let sv_token = (get-secretumvault-token)
|
|
let mount_point = (get-secretumvault-mount-point)
|
|
let url = $"($sv_url)/v1/($mount_point)/keys/($key_name)/rotate"
|
|
|
|
if ($sv_token | is-empty) {
|
|
error make {
|
|
msg: "SecretumVault authentication failed"
|
|
label: {
|
|
text: "SECRETUMVAULT_TOKEN not set"
|
|
span: (metadata $key_name).span
|
|
}
|
|
}
|
|
}
|
|
|
|
let result = (do -i {
|
|
http post -H ["X-Vault-Token" $sv_token] $url
|
|
})
|
|
|
|
if $result != null {
|
|
return $result
|
|
}
|
|
|
|
error make {
|
|
msg: "SecretumVault key rotation failed"
|
|
label: {
|
|
text: $"Failed to rotate key ($key_name)"
|
|
span: (metadata $key_name).span
|
|
}
|
|
}
|
|
}
|
|
|
|
# Get SecretumVault plugin status and configuration
|
|
export def plugin-secretumvault-info [] {
|
|
let plugin_available = is-plugin-available
|
|
let plugin_enabled = is-plugin-enabled
|
|
let sv_url = get-secretumvault-url
|
|
let mount_point = get-secretumvault-mount-point
|
|
let key_name = get-secretumvault-key-name
|
|
let has_token = (not (get-secretumvault-token | is-empty))
|
|
|
|
{
|
|
plugin_available: $plugin_available
|
|
plugin_enabled: $plugin_enabled
|
|
service_url: $sv_url
|
|
mount_point: $mount_point
|
|
default_key: $key_name
|
|
authenticated: $has_token
|
|
mode: (if ($plugin_enabled and $plugin_available) { "plugin (native)" } else { "http fallback" })
|
|
}
|
|
}
|
|
|
|
# Encrypt configuration file using SecretumVault
|
|
export def encrypt-config-file [
|
|
config_file: string
|
|
--output: string = "" # Output file path (default: <file>.enc)
|
|
--key-id: string = "" # Encryption key ID
|
|
] {
|
|
let out_file = if ($output | is-empty) {
|
|
$"($config_file).enc"
|
|
} else {
|
|
$output
|
|
}
|
|
|
|
let result = (do -i {
|
|
let content = (open $config_file --raw)
|
|
let encrypted = (plugin-secretumvault-encrypt $content --key-id $key_id)
|
|
|
|
# Save encrypted content
|
|
if ($encrypted | type) == "record" {
|
|
$encrypted.ciphertext | save --force $out_file
|
|
} else {
|
|
$encrypted | save --force $out_file
|
|
}
|
|
|
|
print $"✅ Configuration encrypted to: ($out_file)"
|
|
{
|
|
success: true
|
|
input_file: $config_file
|
|
output_file: $out_file
|
|
key_id: (if ($key_id | is-empty) { (get-secretumvault-key-name) } else { $key_id })
|
|
}
|
|
})
|
|
|
|
if $result == null {
|
|
error make {
|
|
msg: "Failed to encrypt configuration file"
|
|
label: {
|
|
text: "Check file permissions and SecretumVault service"
|
|
span: (metadata $config_file).span
|
|
}
|
|
}
|
|
}
|
|
|
|
$result
|
|
}
|
|
|
|
# Decrypt configuration file using SecretumVault
|
|
export def decrypt-config-file [
|
|
encrypted_file: string
|
|
--output: string = "" # Output file path (default: <file>.dec)
|
|
--key-id: string = "" # Encryption key ID
|
|
] {
|
|
let out_file = if ($output | is-empty) {
|
|
let base_name = ($encrypted_file | str replace '.enc' '')
|
|
$"($base_name).dec"
|
|
} else {
|
|
$output
|
|
}
|
|
|
|
let result = (do -i {
|
|
let encrypted_content = (open $encrypted_file --raw)
|
|
let decrypted = (plugin-secretumvault-decrypt $encrypted_content --key-id $key_id)
|
|
|
|
# Save decrypted content
|
|
if ($decrypted | type) == "record" {
|
|
if ($decrypted.plaintext? != null) {
|
|
$decrypted.plaintext | save --force $out_file
|
|
} else {
|
|
$decrypted | to json | save --force $out_file
|
|
}
|
|
} else {
|
|
$decrypted | save --force $out_file
|
|
}
|
|
|
|
print $"✅ Configuration decrypted to: ($out_file)"
|
|
{
|
|
success: true
|
|
input_file: $encrypted_file
|
|
output_file: $out_file
|
|
key_id: (if ($key_id | is-empty) { (get-secretumvault-key-name) } else { $key_id })
|
|
}
|
|
})
|
|
|
|
if $result == null {
|
|
error make {
|
|
msg: "Failed to decrypt configuration file"
|
|
label: {
|
|
text: "Check file permissions and SecretumVault service"
|
|
span: (metadata $encrypted_file).span
|
|
}
|
|
}
|
|
}
|
|
|
|
$result
|
|
}
|