-
-
Notifications
You must be signed in to change notification settings - Fork 809
/
SshUtils.ps1
229 lines (204 loc) · 6.71 KB
/
SshUtils.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#
# SshUtils.ps1
#
function setenv($key, $value) {
[void][Environment]::SetEnvironmentVariable($key, $value)
Set-TempEnv $key $value
}
function Get-TempEnv($key) {
$path = Get-TempEnvPath($key)
if (Test-Path $path) {
$value = Get-Content $path
[void][Environment]::SetEnvironmentVariable($key, $value)
}
}
function Set-TempEnv($key, $value) {
$path = Get-TempEnvPath($key)
if ($null -eq $value) {
if (Test-Path $path) {
Remove-Item $path
}
}
else {
New-Item $path -Force -ItemType File > $null
$value | Out-File -FilePath $path -Encoding ascii -Force
}
}
function Get-TempEnvPath($key){
$path = Join-Path ([System.IO.Path]::GetTempPath()) ".ssh\$key.env"
return $path
}
# Retrieve the current SSH agent PID (or zero). Can be used to determine if there
# is a running agent.
function Get-SshAgent() {
if ($env:GIT_SSH -imatch 'plink') {
$pageantPid = Get-Process | Where-Object { $_.Name -eq 'pageant' } | Select-Object -ExpandProperty Id -First 1
if ($null -ne $pageantPid) { return $pageantPid }
}
else {
$agentPid = $Env:SSH_AGENT_PID
if ($agentPid) {
$sshAgentProcess = Get-Process | Where-Object { ($_.Id -eq $agentPid) -and ($_.Name -eq 'ssh-agent') }
if ($null -ne $sshAgentProcess) {
return $agentPid
}
else {
setenv 'SSH_AGENT_PID' $null
setenv 'SSH_AUTH_SOCK' $null
}
}
}
return 0
}
# Attempt to guess Pageant's location
function Find-Pageant() {
Write-Verbose "Pageant not in path. Trying to guess location."
$gitSsh = $env:GIT_SSH
if ($gitSsh -and (test-path $gitSsh)) {
$pageant = join-path (split-path $gitSsh) pageant
}
if (!(get-command $pageant -Erroraction SilentlyContinue)) {
return # Guessing failed.
}
else {
return $pageant
}
}
# Attempt to guess $program's location. For ssh-agent/ssh-add.
function Find-Ssh($program = 'ssh-agent') {
Write-Verbose "$program not in path. Trying to guess location."
$gitItem = Get-Command git -CommandType Application -Erroraction SilentlyContinue | Get-Item
if ($null -eq $gitItem) {
Write-Warning 'git not in path'
return
}
$sshLocation = join-path $gitItem.directory.parent.fullname bin/$program
if (get-command $sshLocation -Erroraction SilentlyContinue) {
return $sshLocation
}
$sshLocation = join-path $gitItem.directory.parent.fullname usr/bin/$program
if (get-command $sshLocation -Erroraction SilentlyContinue) {
return $sshLocation
}
}
# Loosely based on bash script from http://help.github.com/ssh-key-passphrases/
function Start-SshAgent([switch]$Quiet) {
[int]$agentPid = Get-SshAgent
if ($agentPid -gt 0) {
if (!$Quiet) {
$agentName = Get-Process -Id $agentPid | Select-Object -ExpandProperty Name
if (!$agentName) { $agentName = "SSH Agent" }
Write-Host "$agentName is already running (pid $($agentPid))"
}
return
}
if ($env:GIT_SSH -imatch 'plink') {
Write-Host "GIT_SSH set to $($env:GIT_SSH), using Pageant as SSH agent."
$pageant = Get-Command pageant -TotalCount 1 -Erroraction SilentlyContinue
$pageant = if ($pageant) { $pageant } else { Find-Pageant }
if (!$pageant) {
if (!$Quiet) {
Write-Warning 'Could not find Pageant'
}
return
}
Start-Process -NoNewWindow $pageant
}
else {
$sshAgent = Get-Command ssh-agent -TotalCount 1 -ErrorAction SilentlyContinue
$sshAgent = if ($sshAgent) { $sshAgent } else { Find-Ssh('ssh-agent') }
if (!$sshAgent) {
if (!$Quiet) {
Write-Warning 'Could not find ssh-agent'
}
return
}
& $sshAgent | ForEach-Object {
if ($_ -match '(?<key>[^=]+)=(?<value>[^;]+);') {
setenv $Matches['key'] $Matches['value']
}
}
}
Add-SshKey -Quiet:$Quiet
}
function Get-SshPath($File = 'id_rsa') {
# Avoid paths with path separator char since it is different on Linux/macOS.
# Also avoid ~ as it is invalid if the user is cd'd into say cert:\ or hklm:\.
# Also, apparently using the PowerShell built-in $HOME variable may not cut it for msysGit with has different
# ideas about the path to the user's home dir e.g. /c/Users/Keith
# $homePath = Invoke-NullCoalescing $Env:HOME $Home
$homePath = if ($Env:HOME) {$Env:HOME} else {$Home}
Join-Path $homePath (Join-Path .ssh $File)
}
<#
.SYNOPSIS
Add a key to the SSH agent
.DESCRIPTION
Adds one or more SSH keys to the SSH agent.
.EXAMPLE
PS C:\> Add-SshKey
Adds ~\.ssh\id_rsa to the SSH agent.
.EXAMPLE
PS C:\> Add-SshKey ~\.ssh\mykey, ~\.ssh\myotherkey
Adds ~\.ssh\mykey and ~\.ssh\myotherkey to the SSH agent.
.INPUTS
None.
You cannot pipe input to this cmdlet.
#>
function Add-SshKey([switch]$Quiet) {
if ($env:GIT_SSH -imatch 'plink') {
$pageant = Get-Command pageant -Erroraction SilentlyContinue | Select-Object -First 1 -ExpandProperty Name
$pageant = if ($pageant) { $pageant } else { Find-Pageant }
if (!$pageant) {
if (!$Quiet) {
Write-Warning 'Could not find Pageant'
}
return
}
if ($args.Count -eq 0) {
$keyPath = Join-Path $Env:HOME .ssh
$keys = Get-ChildItem $keyPath/*.ppk -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName
if ($keys) {
& $pageant $keys
}
}
else {
foreach ($value in $args) {
& $pageant $value
}
}
}
else {
$sshAdd = Get-Command ssh-add -TotalCount 1 -ErrorAction SilentlyContinue
$sshAdd = if ($sshAdd) { $sshAdd } else { Find-Ssh('ssh-add') }
if (!$sshAdd) {
if (!$Quiet) {
Write-Warning 'Could not find ssh-add'
}
return
}
if ($args.Count -eq 0) {
& $sshAdd
}
else {
foreach ($value in $args) {
& $sshAdd $value
}
}
}
}
# Stop a running SSH agent
function Stop-SshAgent() {
[int]$agentPid = Get-SshAgent
if ($agentPid -gt 0) {
# Stop agent process
$proc = Get-Process -Id $agentPid -ErrorAction SilentlyContinue
if ($null -ne $proc) {
Stop-Process $agentPid
}
setenv 'SSH_AGENT_PID' $null
setenv 'SSH_AUTH_SOCK' $null
}
}
Get-TempEnv 'SSH_AGENT_PID'
Get-TempEnv 'SSH_AUTH_SOCK'