292 lines
8.9 KiB
Plaintext
292 lines
8.9 KiB
Plaintext
|
|
#!/usr/bin/env nu
|
||
|
|
# Register provisioning critical plugins with Nushell
|
||
|
|
#
|
||
|
|
# This script registers the three critical provisioning plugins:
|
||
|
|
# - nu_plugin_auth: JWT authentication with system keyring
|
||
|
|
# - nu_plugin_kms: Multi-backend KMS encryption
|
||
|
|
# - nu_plugin_orchestrator: Local orchestrator operations
|
||
|
|
#
|
||
|
|
# Usage:
|
||
|
|
# nu scripts/register-provisioning-plugins.nu
|
||
|
|
# nu scripts/register-provisioning-plugins.nu --verify
|
||
|
|
# nu scripts/register-provisioning-plugins.nu --force
|
||
|
|
|
||
|
|
use std log
|
||
|
|
|
||
|
|
# Plugin metadata
|
||
|
|
const PROVISIONING_PLUGINS = [
|
||
|
|
{
|
||
|
|
name: "nu_plugin_auth"
|
||
|
|
description: "JWT authentication with system keyring"
|
||
|
|
commands: ["auth login", "auth logout", "auth verify", "auth sessions", "auth mfa enroll", "auth mfa verify"]
|
||
|
|
priority: 1
|
||
|
|
}
|
||
|
|
{
|
||
|
|
name: "nu_plugin_kms"
|
||
|
|
description: "Multi-backend KMS encryption (RustyVault, Age, AWS, Vault, Cosmian)"
|
||
|
|
commands: ["kms encrypt", "kms decrypt", "kms generate-key", "kms status", "kms list-backends"]
|
||
|
|
priority: 2
|
||
|
|
}
|
||
|
|
{
|
||
|
|
name: "nu_plugin_orchestrator"
|
||
|
|
description: "Local orchestrator operations (10-30x faster than HTTP)"
|
||
|
|
commands: ["orch status", "orch tasks", "orch validate", "orch submit", "orch monitor"]
|
||
|
|
priority: 3
|
||
|
|
}
|
||
|
|
]
|
||
|
|
|
||
|
|
# Get plugin binary path for the current platform
|
||
|
|
def get-plugin-path [plugin_name: string, base_dir: path]: nothing -> path {
|
||
|
|
let release_path = ($base_dir | path join $plugin_name "target" "release" $plugin_name)
|
||
|
|
let debug_path = ($base_dir | path join $plugin_name "target" "debug" $plugin_name)
|
||
|
|
|
||
|
|
# Prefer release build
|
||
|
|
if ($release_path | path exists) {
|
||
|
|
return $release_path
|
||
|
|
}
|
||
|
|
|
||
|
|
# Fall back to debug build
|
||
|
|
if ($debug_path | path exists) {
|
||
|
|
return $debug_path
|
||
|
|
}
|
||
|
|
|
||
|
|
# Not found
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check if plugin is already registered
|
||
|
|
def is-plugin-registered [plugin_name: string]: nothing -> bool {
|
||
|
|
let registered = (plugin list | where name == $plugin_name)
|
||
|
|
($registered | length) > 0
|
||
|
|
}
|
||
|
|
|
||
|
|
# Register a single plugin
|
||
|
|
def register-plugin [
|
||
|
|
plugin_name: string
|
||
|
|
plugin_path: path
|
||
|
|
--force: bool = false
|
||
|
|
]: nothing -> record {
|
||
|
|
let start_time = (date now)
|
||
|
|
|
||
|
|
# Check if already registered
|
||
|
|
if (not $force) and (is-plugin-registered $plugin_name) {
|
||
|
|
return {
|
||
|
|
name: $plugin_name
|
||
|
|
status: "already_registered"
|
||
|
|
message: "Plugin already registered (use --force to re-register)"
|
||
|
|
duration_ms: 0
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check if plugin binary exists
|
||
|
|
if ($plugin_path | is-empty) or (not ($plugin_path | path exists)) {
|
||
|
|
return {
|
||
|
|
name: $plugin_name
|
||
|
|
status: "not_found"
|
||
|
|
message: $"Plugin binary not found at expected location"
|
||
|
|
duration_ms: 0
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Register the plugin
|
||
|
|
try {
|
||
|
|
plugin add $plugin_path
|
||
|
|
let duration = ((date now) - $start_time) | into int | $in / 1_000_000
|
||
|
|
|
||
|
|
return {
|
||
|
|
name: $plugin_name
|
||
|
|
status: "registered"
|
||
|
|
message: "Plugin registered successfully"
|
||
|
|
path: $plugin_path
|
||
|
|
duration_ms: $duration
|
||
|
|
}
|
||
|
|
} catch { |err|
|
||
|
|
let duration = ((date now) - $start_time) | into int | $in / 1_000_000
|
||
|
|
|
||
|
|
return {
|
||
|
|
name: $plugin_name
|
||
|
|
status: "error"
|
||
|
|
message: $"Failed to register: ($err.msg)"
|
||
|
|
duration_ms: $duration
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Verify plugin registration by checking commands
|
||
|
|
def verify-plugin-registration [plugin_name: string]: nothing -> record {
|
||
|
|
let plugin_info = (PROVISIONING_PLUGINS | where name == $plugin_name | first)
|
||
|
|
|
||
|
|
if ($plugin_info == null) {
|
||
|
|
return {
|
||
|
|
name: $plugin_name
|
||
|
|
verified: false
|
||
|
|
message: "Unknown plugin"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check if plugin is in plugin list
|
||
|
|
let registered = (plugin list | where name == $plugin_name)
|
||
|
|
|
||
|
|
if ($registered | length) == 0 {
|
||
|
|
return {
|
||
|
|
name: $plugin_name
|
||
|
|
verified: false
|
||
|
|
message: "Plugin not found in registry"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
name: $plugin_name
|
||
|
|
verified: true
|
||
|
|
description: $plugin_info.description
|
||
|
|
commands: $plugin_info.commands
|
||
|
|
message: "Plugin verified successfully"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Main entry point
|
||
|
|
def main [
|
||
|
|
--force (-f) # Force re-registration even if already registered
|
||
|
|
--verify (-v) # Verify registration after completion
|
||
|
|
--quiet (-q) # Suppress output
|
||
|
|
]: nothing -> nothing {
|
||
|
|
let base_dir = ($env.PWD | path dirname | path dirname | path dirname | path join "plugins" "nushell-plugins")
|
||
|
|
|
||
|
|
# Fallback: try current directory if we're already in nushell-plugins
|
||
|
|
let base_dir = if ($base_dir | path join "nu_plugin_auth" | path exists) {
|
||
|
|
$base_dir
|
||
|
|
} else if (($env.PWD | path join "nu_plugin_auth") | path exists) {
|
||
|
|
$env.PWD
|
||
|
|
} else {
|
||
|
|
# Try to find from script location
|
||
|
|
let script_dir = ($env.CURRENT_FILE? | default $env.PWD | path dirname)
|
||
|
|
let parent = ($script_dir | path dirname)
|
||
|
|
if ($parent | path join "nu_plugin_auth" | path exists) {
|
||
|
|
$parent
|
||
|
|
} else {
|
||
|
|
$env.PWD
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if not $quiet {
|
||
|
|
print ""
|
||
|
|
print "======================================================"
|
||
|
|
print " Provisioning Plugins Registration"
|
||
|
|
print "======================================================"
|
||
|
|
print ""
|
||
|
|
print $"Base directory: ($base_dir)"
|
||
|
|
print ""
|
||
|
|
}
|
||
|
|
|
||
|
|
mut results = []
|
||
|
|
mut registered_count = 0
|
||
|
|
mut failed_count = 0
|
||
|
|
|
||
|
|
# Register each plugin
|
||
|
|
for plugin_info in $PROVISIONING_PLUGINS {
|
||
|
|
let plugin_name = $plugin_info.name
|
||
|
|
let plugin_path = (get-plugin-path $plugin_name $base_dir)
|
||
|
|
|
||
|
|
if not $quiet {
|
||
|
|
print $"Registering ($plugin_name)..."
|
||
|
|
}
|
||
|
|
|
||
|
|
let result = (register-plugin $plugin_name $plugin_path --force=$force)
|
||
|
|
$results = ($results | append $result)
|
||
|
|
|
||
|
|
match $result.status {
|
||
|
|
"registered" | "already_registered" => {
|
||
|
|
$registered_count = ($registered_count + 1)
|
||
|
|
if not $quiet {
|
||
|
|
if $result.status == "registered" {
|
||
|
|
print $" [OK] ($result.message) \(($result.duration_ms)ms\)"
|
||
|
|
} else {
|
||
|
|
print $" [SKIP] ($result.message)"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
"not_found" => {
|
||
|
|
$failed_count = ($failed_count + 1)
|
||
|
|
if not $quiet {
|
||
|
|
print $" [WARN] ($result.message)"
|
||
|
|
print $" Expected at: ($base_dir)/($plugin_name)/target/release/($plugin_name)"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
"error" => {
|
||
|
|
$failed_count = ($failed_count + 1)
|
||
|
|
if not $quiet {
|
||
|
|
print $" [ERROR] ($result.message)"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
_ => {
|
||
|
|
$failed_count = ($failed_count + 1)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if not $quiet {
|
||
|
|
print ""
|
||
|
|
print "------------------------------------------------------"
|
||
|
|
print $"Summary: ($registered_count) registered, ($failed_count) failed"
|
||
|
|
print "------------------------------------------------------"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Verify if requested
|
||
|
|
if $verify {
|
||
|
|
if not $quiet {
|
||
|
|
print ""
|
||
|
|
print "Verifying plugin registration..."
|
||
|
|
print ""
|
||
|
|
}
|
||
|
|
|
||
|
|
for plugin_info in $PROVISIONING_PLUGINS {
|
||
|
|
let verification = (verify-plugin-registration $plugin_info.name)
|
||
|
|
|
||
|
|
if not $quiet {
|
||
|
|
if $verification.verified {
|
||
|
|
print $"[OK] ($verification.name): ($verification.description)"
|
||
|
|
print $" Commands: ($verification.commands | str join ', ')"
|
||
|
|
} else {
|
||
|
|
print $"[FAIL] ($verification.name): ($verification.message)"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if not $quiet {
|
||
|
|
print ""
|
||
|
|
print "Plugin commands available:"
|
||
|
|
print " - auth login/logout/verify/sessions/mfa"
|
||
|
|
print " - kms encrypt/decrypt/generate-key/status/list-backends"
|
||
|
|
print " - orch status/tasks/validate/submit/monitor"
|
||
|
|
print ""
|
||
|
|
print "Verify with: plugin list"
|
||
|
|
print ""
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Export for use as module
|
||
|
|
export def "provisioning-plugins register" [--force (-f), --verify (-v), --quiet (-q)] {
|
||
|
|
main --force=$force --verify=$verify --quiet=$quiet
|
||
|
|
}
|
||
|
|
|
||
|
|
export def "provisioning-plugins list" [] {
|
||
|
|
PROVISIONING_PLUGINS
|
||
|
|
}
|
||
|
|
|
||
|
|
export def "provisioning-plugins status" [] {
|
||
|
|
mut status_list = []
|
||
|
|
|
||
|
|
for plugin_info in $PROVISIONING_PLUGINS {
|
||
|
|
let registered = (is-plugin-registered $plugin_info.name)
|
||
|
|
$status_list = ($status_list | append {
|
||
|
|
name: $plugin_info.name
|
||
|
|
registered: $registered
|
||
|
|
description: $plugin_info.description
|
||
|
|
commands: ($plugin_info.commands | length)
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
$status_list
|
||
|
|
}
|