Functions/New-SshAccess.ps1
|
<#
.SYNOPSIS Provisions key-based SSH access to a host: generates (or reuses) a key pair, installs the public key on the server, registers a Host alias in ~/.ssh/config, and verifies it. .DESCRIPTION One command to get `ssh <alias>` working against a server with a dedicated key. Cross-platform (Windows / Linux under PowerShell). Fills the gap left by the absence of `ssh-copy-id` on Windows and adds -TargetUser/-Sudo support for service accounts. The private key never leaves ~/.ssh. The public key is appended (idempotently) to the target user's authorized_keys; when the bootstrap login differs from the target user, the install runs via sudo. .PARAMETER Server Alias to create in ~/.ssh/config (this is what later goes in publish.yaml as `server:`). .PARAMETER HostName IP or DNS name of the server. .PARAMETER User Account the alias logs in as and that will own the key on the server (e.g. svc-fotos). .PARAMETER Port SSH port (default 22). .PARAMETER BootstrapUser Account used to install the public key the first time (defaults to -User). Use this when you cannot yet log in as -User (e.g. a no-login service account): connect as your own account and install into the service account's authorized_keys with -Sudo. .PARAMETER Sudo Install into -User's authorized_keys via sudo. Implied when BootstrapUser differs from User. .PARAMETER KeyType Key algorithm (default ed25519). .PARAMETER KeyPath Path of the key. Defaults to ~/.ssh/<Server>. If the path already exists it is REUSED (install/register an existing key); otherwise a new pair is generated. .PARAMETER Comment Public key comment (default "<User>@<Server>-<yyyyMMdd>"). .PARAMETER Force Overwrite an existing key at -KeyPath and replace an existing Host alias. .EXAMPLE New-SshAccess -Server fotos-vm -HostName 192.168.10.110 -User svc-fotos -BootstrapUser '44358590@cacsi.local' -Sudo #> function New-SshAccess { [CmdletBinding()] param( [Parameter(Mandatory)][string]$Server, [Parameter(Mandatory)][string]$HostName, [Parameter(Mandatory)][string]$User, [int]$Port = 22, [string]$BootstrapUser, [switch]$Sudo, [string]$KeyType = 'ed25519', [string]$KeyPath, [string]$Comment, [switch]$Force ) $ErrorActionPreference = 'Stop' . "$PSScriptRoot/../Private/SshHelpers.ps1" . "$PSScriptRoot/../Private/PublishHelpers.ps1" Write-Host "" Write-Host " New-SshAccess - $Server ($User@$HostName)" -ForegroundColor Cyan $sshDir = Get-SshUserDir if (-not $KeyPath) { $KeyPath = Join-Path $sshDir $Server } if (-not $Comment) { $Comment = "$User@$Server-$(Get-Date -Format 'yyyyMMdd')" } # 1. Key pair: reuse if KeyPath exists, otherwise generate. if ((Test-Path $KeyPath) -and -not $Force) { if (-not (Test-Path "$KeyPath.pub")) { throw "Private key '$KeyPath' exists but '$KeyPath.pub' is missing. Provide the public key or use -Force to regenerate." } Write-Host " Reusing existing key: $KeyPath" -ForegroundColor DarkGray $pub = (Get-Content "$KeyPath.pub" -Raw).Trim() $fingerprint = Get-SshKeyFingerprint -PublicKeyPath "$KeyPath.pub" Protect-SshPrivateKey -Path $KeyPath } else { Write-Host " Generating key pair ($KeyType): $KeyPath" -ForegroundColor DarkGray $key = New-SshKeyPair -Path $KeyPath -Type $KeyType -Comment $Comment -Force:$Force $pub = $key.PublicKey $fingerprint = $key.Fingerprint } # 2. Install the public key on the server (bootstrap login; sudo if needed). $bootstrap = if ($BootstrapUser) { $BootstrapUser } else { $User } $useSudo = ($Sudo -or ($bootstrap -ne $User)) Write-Host " Installing public key for '$User' via '$bootstrap' (sudo=$useSudo)..." -ForegroundColor DarkGray $installScript = Get-BashScript -ScriptName 'Install-AuthorizedKey.sh' -Placeholders @{ '__TARGET_USER__' = $User '__PUBKEY__' = $pub '__USE_SUDO__' = ($(if ($useSudo) { '1' } else { '0' })) } $rc = Invoke-RemoteBash -ScriptContent $installScript -User $bootstrap -HostName $HostName -Port $Port -Tty:$useSudo -Prefix 'macss_authkey_' if ($rc -ne 0) { throw "Public key install failed (exit $rc)." } # 3. Register the Host alias. $configPath = Join-Path $sshDir 'config' $cfg = Add-SshConfigHost -ConfigPath $configPath -Alias $Server -HostName $HostName -User $User -Port $Port -IdentityFile $KeyPath -Force:$Force Write-Host " ssh config: $($cfg.Action) Host '$Server'" -ForegroundColor DarkGray # 4. Verify key-based login works. Write-Host " Verifying key-based login..." -ForegroundColor DarkGray $vrc = Invoke-RemoteBash -ScriptContent 'exit 0' -User $User -HostName $HostName -Port $Port -IdentityFile $KeyPath -Prefix 'macss_verify_' if ($vrc -ne 0) { Write-Host " WARNING: verification failed (exit $vrc). Key installed but login not confirmed." -ForegroundColor Yellow } else { Write-Host " OK: ssh $Server (login as $User)" -ForegroundColor Green } return [pscustomobject]@{ Server = $Server HostName = $HostName User = $User KeyPath = $KeyPath Fingerprint = $fingerprint Verified = ($vrc -eq 0) } } |