Adds KMS, secrets management, config encryption, and auth plugins to enable zero-trust security architecture across the provisioning platform.
249 lines
8.1 KiB
Plaintext
249 lines
8.1 KiB
Plaintext
# SSH Temporal Key Management CLI
|
|
#
|
|
# Provides Nushell commands for managing temporal SSH keys with automatic cleanup.
|
|
|
|
# Generate temporal SSH key
|
|
export def "ssh generate-key" [
|
|
server: string # Target server (hostname or IP)
|
|
--user: string = "root" # SSH user
|
|
--ttl: duration = 1hr # Key lifetime
|
|
--type: string = "dynamic" # Key type: ca, otp, or dynamic
|
|
--ip: string # Allowed IP (for OTP mode)
|
|
--principal: string # Principal (for CA mode)
|
|
] {
|
|
let ttl_seconds = ($ttl | into int) / 1_000_000_000
|
|
|
|
let request = {
|
|
key_type: (match $type {
|
|
"ca" => "certificate"
|
|
"otp" => "otp"
|
|
"dynamic" => "dynamickeypair"
|
|
_ => (error make {msg: $"Invalid key type: ($type). Use: ca, otp, or dynamic"})
|
|
})
|
|
user: $user
|
|
target_server: $server
|
|
ttl_seconds: $ttl_seconds
|
|
allowed_ip: $ip
|
|
principal: $principal
|
|
}
|
|
|
|
let response = (http post http://localhost:8080/api/v1/ssh/generate $request)
|
|
|
|
if $response.success {
|
|
print $"✓ SSH key generated successfully"
|
|
print $" Key ID: ($response.data.id)"
|
|
print $" Type: ($response.data.key_type)"
|
|
print $" User: ($response.data.user)"
|
|
print $" Server: ($response.data.target_server)"
|
|
print $" Expires: ($response.data.expires_at)"
|
|
print $" Fingerprint: ($response.data.fingerprint)"
|
|
|
|
if $response.data.private_key != null {
|
|
print ""
|
|
print "Private Key (save this securely, will not be shown again):"
|
|
print $"($response.data.private_key)"
|
|
}
|
|
|
|
$response.data
|
|
} else {
|
|
error make {msg: $"Failed to generate SSH key: ($response.error)"}
|
|
}
|
|
}
|
|
|
|
# Deploy SSH key to server
|
|
export def "ssh deploy-key" [
|
|
key_id: string # SSH key ID
|
|
] {
|
|
let response = (http post $"http://localhost:8080/api/v1/ssh/($key_id)/deploy" {})
|
|
|
|
if $response.success {
|
|
if $response.data.success {
|
|
print $"✓ SSH key deployed successfully to ($response.data.server)"
|
|
} else {
|
|
error make {msg: $"Failed to deploy key: ($response.data.error)"}
|
|
}
|
|
$response.data
|
|
} else {
|
|
error make {msg: $"Failed to deploy SSH key: ($response.error)"}
|
|
}
|
|
}
|
|
|
|
# List active SSH keys
|
|
export def "ssh list-keys" [
|
|
--expired: bool = false # Include expired keys
|
|
] {
|
|
let response = (http get http://localhost:8080/api/v1/ssh/keys)
|
|
|
|
if $response.success {
|
|
let keys = $response.data
|
|
|
|
if ($keys | is-empty) {
|
|
print "No active SSH keys found"
|
|
return []
|
|
}
|
|
|
|
print $"Found ($keys | length) active SSH keys:"
|
|
$keys | select id key_type user target_server expires_at deployed
|
|
} else {
|
|
error make {msg: $"Failed to list SSH keys: ($response.error)"}
|
|
}
|
|
}
|
|
|
|
# Revoke SSH key
|
|
export def "ssh revoke-key" [
|
|
key_id: string # SSH key ID to revoke
|
|
] {
|
|
let response = (http post $"http://localhost:8080/api/v1/ssh/($key_id)/revoke" {})
|
|
|
|
if $response.success {
|
|
print $"✓ SSH key revoked: ($key_id)"
|
|
$response.data
|
|
} else {
|
|
error make {msg: $"Failed to revoke SSH key: ($response.error)"}
|
|
}
|
|
}
|
|
|
|
# Get SSH key details
|
|
export def "ssh get-key" [
|
|
key_id: string # SSH key ID
|
|
] {
|
|
let response = (http get $"http://localhost:8080/api/v1/ssh/($key_id)")
|
|
|
|
if $response.success {
|
|
$response.data
|
|
} else {
|
|
error make {msg: $"Failed to get SSH key: ($response.error)"}
|
|
}
|
|
}
|
|
|
|
# SSH with temporal key (auto-generate, deploy, connect, revoke)
|
|
export def "ssh connect" [
|
|
server: string # Target server
|
|
--user: string = "root" # SSH user
|
|
--ttl: duration = 1hr # Key lifetime
|
|
--type: string = "dynamic" # Key type: ca, otp, or dynamic
|
|
--keep: bool = false # Keep key after disconnect
|
|
] {
|
|
print $"Generating temporal SSH key for ($user)@($server)..."
|
|
let key = (ssh generate-key $server --user $user --ttl $ttl --type $type)
|
|
|
|
print "Deploying key to server..."
|
|
ssh deploy-key $key.id
|
|
|
|
# Save private key to temp file
|
|
let key_file = $"/tmp/ssh_temp_($key.id)"
|
|
$key.private_key | save -f $key_file
|
|
chmod 600 $key_file
|
|
|
|
print $"Connecting to ($user)@($server)..."
|
|
^ssh -i $key_file -o "StrictHostKeyChecking=no" $"($user)@($server)"
|
|
|
|
# Cleanup
|
|
rm $key_file
|
|
|
|
if not $keep {
|
|
print "Revoking temporary key..."
|
|
ssh revoke-key $key.id
|
|
} else {
|
|
print $"Key ($key.id) kept active until expiration"
|
|
}
|
|
}
|
|
|
|
# Show SSH key statistics
|
|
export def "ssh stats" [] {
|
|
let response = (http get http://localhost:8080/api/v1/ssh/stats)
|
|
|
|
if $response.success {
|
|
let stats = $response.data
|
|
print "SSH Key Statistics:"
|
|
print $" Total generated: ($stats.total_generated)"
|
|
print $" Active keys: ($stats.active_keys)"
|
|
print $" Expired keys: ($stats.expired_keys)"
|
|
print ""
|
|
print "Keys by type:"
|
|
$stats.keys_by_type | transpose key value | each {|row| print $" ($row.key): ($row.value)"}
|
|
|
|
if $stats.last_cleanup_at != null {
|
|
print ""
|
|
print $"Last cleanup: ($stats.last_cleanup_at)"
|
|
print $" Cleaned keys: ($stats.last_cleanup_count)"
|
|
}
|
|
|
|
$stats
|
|
} else {
|
|
error make {msg: $"Failed to get SSH statistics: ($response.error)"}
|
|
}
|
|
}
|
|
|
|
# Trigger manual cleanup of expired keys
|
|
export def "ssh cleanup" [] {
|
|
print "Triggering cleanup of expired SSH keys..."
|
|
let response = (http post http://localhost:8080/api/v1/ssh/cleanup {})
|
|
|
|
if $response.success {
|
|
print $"✓ Cleaned up ($response.data.cleaned_count) expired keys"
|
|
if ($response.data.cleaned_key_ids | length) > 0 {
|
|
print "Cleaned key IDs:"
|
|
$response.data.cleaned_key_ids | each {|id| print $" - ($id)"}
|
|
}
|
|
$response.data
|
|
} else {
|
|
error make {msg: $"Failed to cleanup expired keys: ($response.error)"}
|
|
}
|
|
}
|
|
|
|
# Quick test - generate, deploy, and revoke a test key
|
|
export def "ssh test" [
|
|
server: string # Target server
|
|
--user: string = "root" # SSH user
|
|
] {
|
|
print "=== SSH Temporal Key Test ==="
|
|
print ""
|
|
|
|
print "1. Generating test key..."
|
|
let key = (ssh generate-key $server --user $user --ttl 5min)
|
|
print ""
|
|
|
|
print "2. Deploying key to server..."
|
|
ssh deploy-key $key.id
|
|
print ""
|
|
|
|
print "3. Testing SSH connection..."
|
|
print "(Manual step: Try connecting with the private key shown above)"
|
|
print ""
|
|
|
|
print "4. Revoking key..."
|
|
ssh revoke-key $key.id
|
|
print ""
|
|
|
|
print "✓ Test complete"
|
|
}
|
|
|
|
# Show help for SSH commands
|
|
export def "ssh help" [] {
|
|
print "SSH Temporal Key Management Commands:"
|
|
print ""
|
|
print " ssh generate-key <server> Generate new SSH key"
|
|
print " ssh deploy-key <key_id> Deploy key to server"
|
|
print " ssh list-keys List active keys"
|
|
print " ssh get-key <key_id> Get key details"
|
|
print " ssh revoke-key <key_id> Revoke key immediately"
|
|
print " ssh connect <server> Connect with auto-generated key"
|
|
print " ssh stats Show statistics"
|
|
print " ssh cleanup Cleanup expired keys"
|
|
print " ssh test <server> Run quick test"
|
|
print ""
|
|
print "Options:"
|
|
print " --user <name> SSH user (default: root)"
|
|
print " --ttl <duration> Key lifetime (default: 1hr)"
|
|
print " --type <ca|otp|dynamic> Key type (default: dynamic)"
|
|
print " --ip <address> Allowed IP (OTP mode)"
|
|
print " --principal <name> Principal (CA mode)"
|
|
print ""
|
|
print "Examples:"
|
|
print " ssh generate-key server.example.com --ttl 30min"
|
|
print " ssh connect server.example.com --user deploy"
|
|
print " ssh list-keys | where deployed == true"
|
|
print " ssh stats"
|
|
}
|