Skip to content

Commit 0cac142

Browse files
committed
FEATURE: Keyfile support for connect-ssh and tunnel-ssh
1 parent a4f6de0 commit 0cac142

File tree

6 files changed

+313
-102
lines changed

6 files changed

+313
-102
lines changed

Connect-SSH.ps1

Lines changed: 98 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,23 @@ if (-not $config) {
1515

1616
# Get servers from config
1717
$servers = @{}
18+
$serverKeyFiles = @{}
1819
if ($config.ssh.servers) {
1920
foreach ($key in $config.ssh.servers.PSObject.Properties.Name) {
2021
$servers[$key] = $config.ssh.servers.$key.hostname
22+
if ($config.ssh.servers.$key.keyFile) {
23+
$serverKeyFiles[$key] = $config.ssh.servers.$key.keyFile
24+
}
2125
}
2226
}
2327

24-
# Resolve hostname
28+
# Resolve hostname and key file
29+
$keyFile = $null
2530
if ($servers.ContainsKey($Target)) {
2631
$Server = $servers[$Target]
32+
if ($serverKeyFiles.ContainsKey($Target)) {
33+
$keyFile = $serverKeyFiles[$Target]
34+
}
2735
} else {
2836
$Server = $Target
2937
}
@@ -44,49 +52,107 @@ if (-not $wsl) {
4452
}
4553
}
4654

47-
# Get credentials
55+
# Get credentials directory
4856
$credsDir = Join-Path $scriptDir "creds"
49-
$credFile = $config.ssh.credentialFile
50-
if (-not $credFile) {
51-
$credFile = "ssh-credentials.xml"
52-
}
53-
$credPath = Join-Path $credsDir $credFile
5457

55-
if (-not (Test-Path $credPath)) {
56-
Write-Host ""
57-
Write-Host "Credential file not found!" -ForegroundColor Yellow
58-
Write-Host ""
59-
Write-Host "To set up SSH credentials:" -ForegroundColor Cyan
60-
Write-Host " 1. Create credentials directory if needed:" -ForegroundColor White
61-
Write-Host " New-Item -Path '$credsDir' -ItemType Directory -Force" -ForegroundColor Gray
62-
Write-Host ""
63-
Write-Host " 2. Store your credentials:" -ForegroundColor White
64-
Write-Host " `$cred = Get-Credential -UserName 'your-ssh-username'" -ForegroundColor Gray
65-
Write-Host " `$cred | Export-Clixml '$credPath'" -ForegroundColor Gray
66-
Write-Host ""
67-
exit 1
58+
# Check for key file authentication
59+
$keyFilePath = $null
60+
if ($keyFile) {
61+
$keyFilePath = Join-Path $credsDir $keyFile
62+
if (-not (Test-Path $keyFilePath)) {
63+
Write-Host ""
64+
Write-Host "Key file not found: $keyFilePath" -ForegroundColor Yellow
65+
Write-Host ""
66+
Write-Host "To set up SSH key authentication:" -ForegroundColor Cyan
67+
Write-Host " 1. Place your key file (.pem) in the creds directory:" -ForegroundColor White
68+
Write-Host " Copy-Item 'C:\path\to\your-key.pem' '$keyFilePath'" -ForegroundColor Gray
69+
Write-Host ""
70+
exit 1
71+
}
6872
}
6973

70-
$cred = Import-Clixml $credPath
71-
$username = $cred.UserName
72-
$password = $cred.GetNetworkCredential().Password
74+
# Get password credentials (not needed if using key file)
75+
$username = $null
76+
$password = $null
77+
$cred = $null
78+
79+
if (-not $keyFile) {
80+
$credFile = $config.ssh.credentialFile
81+
if (-not $credFile) {
82+
$credFile = "ssh-credentials.xml"
83+
}
84+
$credPath = Join-Path $credsDir $credFile
85+
86+
if (-not (Test-Path $credPath)) {
87+
Write-Host ""
88+
Write-Host "Credential file not found!" -ForegroundColor Yellow
89+
Write-Host ""
90+
Write-Host "To set up SSH credentials:" -ForegroundColor Cyan
91+
Write-Host " 1. Create credentials directory if needed:" -ForegroundColor White
92+
Write-Host " New-Item -Path '$credsDir' -ItemType Directory -Force" -ForegroundColor Gray
93+
Write-Host ""
94+
Write-Host " 2. Store your credentials:" -ForegroundColor White
95+
Write-Host " `$cred = Get-Credential -UserName 'your-ssh-username'" -ForegroundColor Gray
96+
Write-Host " `$cred | Export-Clixml '$credPath'" -ForegroundColor Gray
97+
Write-Host ""
98+
Write-Host " Or configure a key file in config.json:" -ForegroundColor Cyan
99+
Write-Host ' "keyFile": "your-key.pem"' -ForegroundColor Gray
100+
Write-Host ""
101+
exit 1
102+
}
103+
104+
$cred = Import-Clixml $credPath
105+
$username = $cred.UserName
106+
$password = $cred.GetNetworkCredential().Password
107+
} else {
108+
# For key file auth, we need a username from config or credential file
109+
$credFile = $config.ssh.credentialFile
110+
if ($credFile) {
111+
$credPath = Join-Path $credsDir $credFile
112+
if (Test-Path $credPath) {
113+
$cred = Import-Clixml $credPath
114+
$username = $cred.UserName
115+
}
116+
}
117+
118+
if (-not $username) {
119+
Write-Host ""
120+
Write-Host "Username required for key file authentication." -ForegroundColor Yellow
121+
Write-Host "Create a credential file with just the username:" -ForegroundColor Cyan
122+
Write-Host " `$cred = Get-Credential -UserName 'your-ssh-username'" -ForegroundColor Gray
123+
Write-Host " `$cred | Export-Clixml '.\creds\ssh-credentials.xml'" -ForegroundColor Gray
124+
Write-Host ""
125+
exit 1
126+
}
127+
}
73128

74129
# Use WSL with sshpass for proper terminal handling
75130
if ($useWSL) {
76-
# Check if sshpass is installed
77-
$hasSshpass = wsl bash -c "command -v sshpass >/dev/null 2>&1 && echo 'yes' || echo 'no'"
78-
if ($hasSshpass -match 'no') {
79-
Write-Host "Installing sshpass in WSL (one-time setup)..." -ForegroundColor Yellow
80-
wsl bash -c "sudo apt-get update && sudo apt-get install -y sshpass"
131+
if ($keyFile) {
132+
# Convert Windows path to WSL path for key file
133+
$wslKeyPath = wsl wslpath -u "'$keyFilePath'"
134+
Write-Host "Connecting to $Server as $username (using key file)..." -ForegroundColor Cyan
135+
wsl bash -c "ssh -o StrictHostKeyChecking=no -i $wslKeyPath $username@$Server"
136+
} else {
137+
# Check if sshpass is installed
138+
$hasSshpass = wsl bash -c "command -v sshpass >/dev/null 2>&1 && echo 'yes' || echo 'no'"
139+
if ($hasSshpass -match 'no') {
140+
Write-Host "Installing sshpass in WSL (one-time setup)..." -ForegroundColor Yellow
141+
wsl bash -c "sudo apt-get update && sudo apt-get install -y sshpass"
142+
}
143+
144+
# Connect using sshpass through WSL (proper terminal handling)
145+
wsl bash -c "SSHPASS='$password' sshpass -e ssh -o StrictHostKeyChecking=no $username@$Server"
81146
}
82-
83-
# Connect using sshpass through WSL (proper terminal handling)
84-
wsl bash -c "SSHPASS='$password' sshpass -e ssh -o StrictHostKeyChecking=no $username@$Server"
85147
} else {
86148
# Fallback to Posh-SSH
87149
Write-Host "Connecting to $Server as $username..." -ForegroundColor Cyan
88150
try {
89-
$session = New-SSHSession -ComputerName $Server -Credential $cred -AcceptKey
151+
if ($keyFile) {
152+
$session = New-SSHSession -ComputerName $Server -KeyFile $keyFilePath -AcceptKey
153+
} else {
154+
$session = New-SSHSession -ComputerName $Server -Credential $cred -AcceptKey
155+
}
90156
Invoke-SSHCommand -SessionId $session.SessionId -Command "bash -l" -TimeOut 3600
91157
Remove-SSHSession -SessionId $session.SessionId | Out-Null
92158
} catch {

Connect-SSHTunnel.ps1

Lines changed: 98 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,13 @@ if (-not $config) {
2424

2525
# Get servers from config
2626
$servers = @{}
27+
$serverKeyFiles = @{}
2728
if ($config.ssh.servers) {
2829
foreach ($key in $config.ssh.servers.PSObject.Properties.Name) {
2930
$servers[$key] = $config.ssh.servers.$key.hostname
31+
if ($config.ssh.servers.$key.keyFile) {
32+
$serverKeyFiles[$key] = $config.ssh.servers.$key.keyFile
33+
}
3034
}
3135
}
3236

@@ -60,39 +64,90 @@ if ($LocalPort -eq 0) {
6064
$LocalPort = $RemotePort
6165
}
6266

63-
# Resolve hostname
67+
# Resolve hostname and key file
68+
$keyFile = $null
6469
if ($servers.ContainsKey($Target)) {
6570
$Server = $servers[$Target]
71+
if ($serverKeyFiles.ContainsKey($Target)) {
72+
$keyFile = $serverKeyFiles[$Target]
73+
}
6674
} else {
6775
$Server = $Target
6876
}
6977

70-
# Get credentials
78+
# Get credentials directory
7179
$credsDir = Join-Path $scriptDir "creds"
72-
$credFile = $config.ssh.credentialFile
73-
if (-not $credFile) {
74-
$credFile = "ssh-credentials.xml"
75-
}
76-
$credPath = Join-Path $credsDir $credFile
7780

78-
if (-not (Test-Path $credPath)) {
79-
Write-Host ""
80-
Write-Host "Credential file not found!" -ForegroundColor Yellow
81-
Write-Host ""
82-
Write-Host "To set up SSH credentials:" -ForegroundColor Cyan
83-
Write-Host " 1. Create credentials directory if needed:" -ForegroundColor White
84-
Write-Host " New-Item -Path '$credsDir' -ItemType Directory -Force" -ForegroundColor Gray
85-
Write-Host ""
86-
Write-Host " 2. Store your credentials:" -ForegroundColor White
87-
Write-Host " `$cred = Get-Credential -UserName 'your-ssh-username'" -ForegroundColor Gray
88-
Write-Host " `$cred | Export-Clixml '$credPath'" -ForegroundColor Gray
89-
Write-Host ""
90-
exit 1
81+
# Check for key file authentication
82+
$keyFilePath = $null
83+
if ($keyFile) {
84+
$keyFilePath = Join-Path $credsDir $keyFile
85+
if (-not (Test-Path $keyFilePath)) {
86+
Write-Host ""
87+
Write-Host "Key file not found: $keyFilePath" -ForegroundColor Yellow
88+
Write-Host ""
89+
Write-Host "To set up SSH key authentication:" -ForegroundColor Cyan
90+
Write-Host " 1. Place your key file (.pem) in the creds directory:" -ForegroundColor White
91+
Write-Host " Copy-Item 'C:\path\to\your-key.pem' '$keyFilePath'" -ForegroundColor Gray
92+
Write-Host ""
93+
exit 1
94+
}
9195
}
9296

93-
$cred = Import-Clixml $credPath
94-
$username = $cred.UserName
95-
$password = $cred.GetNetworkCredential().Password
97+
# Get password credentials (not needed if using key file)
98+
$username = $null
99+
$password = $null
100+
$cred = $null
101+
102+
if (-not $keyFile) {
103+
$credFile = $config.ssh.credentialFile
104+
if (-not $credFile) {
105+
$credFile = "ssh-credentials.xml"
106+
}
107+
$credPath = Join-Path $credsDir $credFile
108+
109+
if (-not (Test-Path $credPath)) {
110+
Write-Host ""
111+
Write-Host "Credential file not found!" -ForegroundColor Yellow
112+
Write-Host ""
113+
Write-Host "To set up SSH credentials:" -ForegroundColor Cyan
114+
Write-Host " 1. Create credentials directory if needed:" -ForegroundColor White
115+
Write-Host " New-Item -Path '$credsDir' -ItemType Directory -Force" -ForegroundColor Gray
116+
Write-Host ""
117+
Write-Host " 2. Store your credentials:" -ForegroundColor White
118+
Write-Host " `$cred = Get-Credential -UserName 'your-ssh-username'" -ForegroundColor Gray
119+
Write-Host " `$cred | Export-Clixml '$credPath'" -ForegroundColor Gray
120+
Write-Host ""
121+
Write-Host " Or configure a key file in config.json:" -ForegroundColor Cyan
122+
Write-Host ' "keyFile": "your-key.pem"' -ForegroundColor Gray
123+
Write-Host ""
124+
exit 1
125+
}
126+
127+
$cred = Import-Clixml $credPath
128+
$username = $cred.UserName
129+
$password = $cred.GetNetworkCredential().Password
130+
} else {
131+
# For key file auth, we need a username from config or credential file
132+
$credFile = $config.ssh.credentialFile
133+
if ($credFile) {
134+
$credPath = Join-Path $credsDir $credFile
135+
if (Test-Path $credPath) {
136+
$cred = Import-Clixml $credPath
137+
$username = $cred.UserName
138+
}
139+
}
140+
141+
if (-not $username) {
142+
Write-Host ""
143+
Write-Host "Username required for key file authentication." -ForegroundColor Yellow
144+
Write-Host "Create a credential file with just the username:" -ForegroundColor Cyan
145+
Write-Host " `$cred = Get-Credential -UserName 'your-ssh-username'" -ForegroundColor Gray
146+
Write-Host " `$cred | Export-Clixml '.\creds\ssh-credentials.xml'" -ForegroundColor Gray
147+
Write-Host ""
148+
exit 1
149+
}
150+
}
96151

97152
Write-Host "Setting up SSH tunnel..." -ForegroundColor Cyan
98153
Write-Host " Local: 127.0.0.1:$LocalPort" -ForegroundColor Green
@@ -104,20 +159,31 @@ Write-Host ""
104159
# Use WSL with sshpass for the tunnel
105160
$wsl = Get-Command wsl -ErrorAction SilentlyContinue
106161
if ($wsl) {
107-
# Check if sshpass is installed
108-
$hasSshpass = wsl bash -c "command -v sshpass >/dev/null 2>&1 && echo 'yes' || echo 'no'"
109-
if ($hasSshpass -match 'no') {
110-
Write-Host "Installing sshpass in WSL (one-time setup)..." -ForegroundColor Yellow
111-
wsl bash -c "sudo apt-get update && sudo apt-get install -y sshpass"
162+
if ($keyFile) {
163+
# Convert Windows path to WSL path for key file
164+
$wslKeyPath = wsl wslpath -u "'$keyFilePath'"
165+
# Create SSH tunnel using key file through WSL
166+
wsl bash -c "ssh -o StrictHostKeyChecking=no -i $wslKeyPath -N -L ${LocalPort}:${RemoteHost}:${RemotePort} $username@$Server"
167+
} else {
168+
# Check if sshpass is installed
169+
$hasSshpass = wsl bash -c "command -v sshpass >/dev/null 2>&1 && echo 'yes' || echo 'no'"
170+
if ($hasSshpass -match 'no') {
171+
Write-Host "Installing sshpass in WSL (one-time setup)..." -ForegroundColor Yellow
172+
wsl bash -c "sudo apt-get update && sudo apt-get install -y sshpass"
173+
}
174+
175+
# Create SSH tunnel using sshpass through WSL
176+
wsl bash -c "SSHPASS='$password' sshpass -e ssh -o StrictHostKeyChecking=no -N -L ${LocalPort}:${RemoteHost}:${RemotePort} $username@$Server"
112177
}
113-
114-
# Create SSH tunnel using sshpass through WSL
115-
wsl bash -c "SSHPASS='$password' sshpass -e ssh -o StrictHostKeyChecking=no -N -L ${LocalPort}:${RemoteHost}:${RemotePort} $username@$Server"
116178
} else {
117179
# Fallback to Posh-SSH
118180
try {
119181
Import-Module Posh-SSH -ErrorAction Stop
120-
$session = New-SSHSession -ComputerName $Server -Credential $cred -AcceptKey
182+
if ($keyFile) {
183+
$session = New-SSHSession -ComputerName $Server -KeyFile $keyFilePath -AcceptKey
184+
} else {
185+
$session = New-SSHSession -ComputerName $Server -Credential $cred -AcceptKey
186+
}
121187

122188
Write-Host "Tunnel established. Keep this window open." -ForegroundColor Green
123189
Write-Host "Press Ctrl+C to close..." -ForegroundColor Yellow

0 commit comments

Comments
 (0)