refactor: Harden and improve SSH agent module
- Add extensive security validations for SSH agent - Implement robust `ssh-agent` auto-start script - Enhance `sshagent` operations with improved error handling - Revamp `sshagent` test suite for comprehensive coverage - Update `sshagent` README with detailed documentation
This commit is contained in:
65
examples/osal/sshagent/sshagent.vsh
Executable file
65
examples/osal/sshagent/sshagent.vsh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.osal.sshagent
|
||||
import freeflowuniverse.herolib.builder
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
console.print_header('SSH Agent Management Example')
|
||||
|
||||
// Create SSH agent with single instance guarantee
|
||||
mut agent := sshagent.new_single()!
|
||||
println('SSH Agent initialized and ensured single instance')
|
||||
|
||||
// Show diagnostics
|
||||
diag := agent.diagnostics()
|
||||
console.print_header('SSH Agent Diagnostics:')
|
||||
for key, value in diag {
|
||||
console.print_item('${key}: ${value}')
|
||||
}
|
||||
|
||||
// Show current agent status
|
||||
println(agent)
|
||||
|
||||
// Example: Generate a test key if no keys exist
|
||||
if agent.keys.len == 0 {
|
||||
console.print_header('No keys found, generating example key...')
|
||||
mut key := agent.generate('example_key', '')!
|
||||
console.print_debug('Generated key: ${key}')
|
||||
|
||||
// Load the generated key
|
||||
key.load()!
|
||||
console.print_debug('Key loaded into agent')
|
||||
}
|
||||
|
||||
// Example: Push key to remote node (uncomment and modify for actual use)
|
||||
/*
|
||||
console.print_header('Testing remote node key deployment...')
|
||||
mut b := builder.new()!
|
||||
|
||||
// Create connection to remote node
|
||||
mut node := b.node_new(
|
||||
ipaddr: 'root@192.168.1.100:22' // Replace with actual remote host
|
||||
name: 'test_node'
|
||||
)!
|
||||
|
||||
if agent.keys.len > 0 {
|
||||
key_name := agent.keys[0].name
|
||||
console.print_debug('Pushing key "${key_name}" to remote node...')
|
||||
|
||||
// Push the key
|
||||
agent.push_key_to_node(mut node, key_name)!
|
||||
|
||||
// Verify access
|
||||
if agent.verify_key_access(mut node, key_name)! {
|
||||
console.print_debug('✓ SSH key access verified')
|
||||
} else {
|
||||
console.print_debug('✗ SSH key access verification failed')
|
||||
}
|
||||
|
||||
// Optional: Remove key from remote (for testing)
|
||||
// agent.remove_key_from_node(mut node, key_name)!
|
||||
// console.print_debug('Key removed from remote node')
|
||||
}
|
||||
*/
|
||||
|
||||
console.print_header('SSH Agent example completed successfully')
|
||||
@@ -1,51 +0,0 @@
|
||||
module main
|
||||
|
||||
import freeflowuniverse.herolib.osal.sshagent
|
||||
import freeflowuniverse.herolib.osal.linux
|
||||
|
||||
fn do1() ! {
|
||||
mut agent := sshagent.new()!
|
||||
println(agent)
|
||||
k := agent.get(name: 'kds') or { panic('notgound') }
|
||||
println(k)
|
||||
|
||||
mut k2 := agent.get(name: 'books') or { panic('notgound') }
|
||||
k2.load()!
|
||||
println(k2.agent)
|
||||
|
||||
println(agent)
|
||||
|
||||
k2.forget()!
|
||||
println(k2.agent)
|
||||
|
||||
// println(agent)
|
||||
}
|
||||
|
||||
fn test_user_mgmt() ! {
|
||||
mut lf := linux.new()!
|
||||
// Test user creation
|
||||
lf.user_create(
|
||||
name: 'testuser'
|
||||
sshkey: 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM3/2K7R8A/l0kM0/d'
|
||||
)!
|
||||
|
||||
// Test ssh key creation
|
||||
lf.sshkey_create(
|
||||
username: 'testuser'
|
||||
sshkey_name: 'testkey'
|
||||
)!
|
||||
|
||||
// Test ssh key deletion
|
||||
lf.sshkey_delete(
|
||||
username: 'testuser'
|
||||
sshkey_name: 'testkey'
|
||||
)!
|
||||
|
||||
// Test user deletion
|
||||
lf.user_delete(name: 'testuser')!
|
||||
}
|
||||
|
||||
fn main() {
|
||||
do1() or { panic(err) }
|
||||
test_user_mgmt() or { panic(err) }
|
||||
}
|
||||
168
examples/osal/sshagent/sshagent_example.vsh
Executable file
168
examples/osal/sshagent/sshagent_example.vsh
Executable file
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.osal.sshagent
|
||||
import freeflowuniverse.herolib.osal.linux
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
fn demo_sshagent_basic() ! {
|
||||
console.print_header('SSH Agent Basic Demo')
|
||||
|
||||
// Create SSH agent
|
||||
mut agent := sshagent.new()!
|
||||
console.print_debug('SSH Agent initialized')
|
||||
|
||||
// Show current status
|
||||
console.print_header('Current SSH Agent Status:')
|
||||
println(agent)
|
||||
|
||||
// Show diagnostics
|
||||
diag := agent.diagnostics()
|
||||
console.print_header('SSH Agent Diagnostics:')
|
||||
for key, value in diag {
|
||||
console.print_item('${key}: ${value}')
|
||||
}
|
||||
}
|
||||
|
||||
fn demo_sshagent_key_management() ! {
|
||||
console.print_header('SSH Agent Key Management Demo')
|
||||
|
||||
mut agent := sshagent.new()!
|
||||
|
||||
// Generate a test key if it doesn't exist
|
||||
test_key_name := 'herolib_demo_key'
|
||||
|
||||
// Clean up any existing test key first
|
||||
if existing_key := agent.get(name: test_key_name) {
|
||||
console.print_debug('Removing existing test key...')
|
||||
// Remove existing key files
|
||||
mut key_file := agent.homepath.file_get_new('${test_key_name}')!
|
||||
mut pub_key_file := agent.homepath.file_get_new('${test_key_name}.pub')!
|
||||
key_file.delete() or {}
|
||||
pub_key_file.delete() or {}
|
||||
} else {
|
||||
console.print_debug('No existing test key found')
|
||||
}
|
||||
|
||||
// Generate new key with empty passphrase
|
||||
console.print_debug('Generating new SSH key: ${test_key_name}')
|
||||
mut new_key := agent.generate(test_key_name, '')!
|
||||
console.print_green('✓ Generated new SSH key: ${test_key_name}')
|
||||
|
||||
// Show key information
|
||||
console.print_item('Key name: ${new_key.name}')
|
||||
console.print_item('Key type: ${new_key.cat}')
|
||||
console.print_item('Key loaded: ${new_key.loaded}')
|
||||
|
||||
// Demonstrate key operations without loading (to avoid passphrase issues)
|
||||
console.print_header('Key file operations:')
|
||||
mut key_path := new_key.keypath()!
|
||||
mut pub_key_path := new_key.keypath_pub()!
|
||||
console.print_item('Private key path: ${key_path.path}')
|
||||
console.print_item('Public key path: ${pub_key_path.path}')
|
||||
|
||||
// Show public key content
|
||||
pub_key_content := new_key.keypub()!
|
||||
preview_len := if pub_key_content.len > 60 { 60 } else { pub_key_content.len }
|
||||
console.print_item('Public key: ${pub_key_content[0..preview_len]}...')
|
||||
|
||||
// Show agent status
|
||||
console.print_header('Agent status after key generation:')
|
||||
println(agent)
|
||||
|
||||
// Clean up test key
|
||||
console.print_debug('Cleaning up test key...')
|
||||
key_path.delete()!
|
||||
pub_key_path.delete()!
|
||||
console.print_green('✓ Test key cleaned up')
|
||||
}
|
||||
|
||||
fn demo_sshagent_with_existing_keys() ! {
|
||||
console.print_header('SSH Agent with Existing Keys Demo')
|
||||
|
||||
mut agent := sshagent.new()!
|
||||
|
||||
if agent.keys.len == 0 {
|
||||
console.print_debug('No SSH keys found. Generating example key...')
|
||||
mut key := agent.generate('example_demo_key', '')!
|
||||
key.load()!
|
||||
console.print_green('✓ Created and loaded example key')
|
||||
}
|
||||
|
||||
console.print_header('Available SSH keys:')
|
||||
for key in agent.keys {
|
||||
status := if key.loaded { 'LOADED' } else { 'NOT LOADED' }
|
||||
console.print_item('${key.name} - ${status} (${key.cat})')
|
||||
}
|
||||
|
||||
// Try to work with the first available key
|
||||
if agent.keys.len > 0 {
|
||||
mut first_key := agent.keys[0]
|
||||
console.print_header('Working with key: ${first_key.name}')
|
||||
|
||||
if first_key.loaded {
|
||||
console.print_debug('Key is loaded, showing public key info...')
|
||||
pubkey := first_key.keypub() or { 'Could not read public key' }
|
||||
preview_len := if pubkey.len > 50 { 50 } else { pubkey.len }
|
||||
console.print_item('Public key preview: ${pubkey[0..preview_len]}...')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_user_mgmt() ! {
|
||||
console.print_header('User Management Test')
|
||||
|
||||
// Note: This requires root privileges and should be run carefully
|
||||
console.print_debug('User management test requires root privileges')
|
||||
console.print_debug('Skipping user management test in this demo')
|
||||
|
||||
// Uncomment below to test user management (requires root)
|
||||
/*
|
||||
mut lf := linux.new()!
|
||||
// Test user creation
|
||||
lf.user_create(
|
||||
name: 'testuser'
|
||||
sshkey: 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM3/2K7R8A/l0kM0/d'
|
||||
)!
|
||||
|
||||
// Test ssh key creation
|
||||
lf.sshkey_create(
|
||||
username: 'testuser'
|
||||
sshkey_name: 'testkey'
|
||||
)!
|
||||
|
||||
// Test ssh key deletion
|
||||
lf.sshkey_delete(
|
||||
username: 'testuser'
|
||||
sshkey_name: 'testkey'
|
||||
)!
|
||||
|
||||
// Test user deletion
|
||||
lf.user_delete(name: 'testuser')!
|
||||
*/
|
||||
}
|
||||
|
||||
fn main() {
|
||||
console.print_header('🔑 SSH Agent Example - HeroLib')
|
||||
|
||||
demo_sshagent_basic() or {
|
||||
console.print_stderr('❌ Basic demo failed: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
demo_sshagent_key_management() or {
|
||||
console.print_stderr('❌ Key management demo failed: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
demo_sshagent_with_existing_keys() or {
|
||||
console.print_stderr('❌ Existing keys demo failed: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
test_user_mgmt() or {
|
||||
console.print_stderr('❌ User management test failed: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
console.print_header('🎉 All SSH Agent demos completed successfully!')
|
||||
}
|
||||
Reference in New Issue
Block a user