Public/Set-Ssh.ps1
|
function Set-Ssh { <# .SYNOPSIS Configure or convert the published location to SSH-based access. .DESCRIPTION Set-Ssh sets the published location for the active project folder to an SSH URL. If you do not provide one, Set-Ssh reads the existing HTTPS URL and converts it to its SSH form (for example, https://github.com/example/repo.git becomes git@github.com:example/repo.git). Use it when SSH is preferred over HTTPS, or when corporate environments require key-based authentication. .PARAMETER RemoteName The name of the published location to configure. Defaults to origin. .PARAMETER RemoteUrl Optional SSH URL. If omitted, Set-Ssh converts the existing HTTPS URL. .PARAMETER LogPath Override the directory where the diagnostic log for this run is written. .EXAMPLE Set-Ssh .EXAMPLE Set-Ssh -RemoteUrl 'git@github.com:example/repo.git' .NOTES Safety: - Do not commit private keys. - After Set-Ssh, run Test-Login to confirm key-based authentication works. - If SSH unexpectedly prompts for credentials, run Show-Remote and verify the URL. Steps: 1. Probe for the project folder root and start a diagnostic log session. 2. If no URL was provided, read the existing HTTPS URL and convert it to SSH form. 3. Validate that the final URL does not embed credentials and matches the expected SSH format. 4. Handle WhatIf and return early if applicable. 5. Set or add the published location with the SSH URL. 6. Return a structured result with the remote name and configured URL. .LINK Test-Login .LINK Show-Remote .LINK Reset-Login #> [CmdletBinding(SupportsShouldProcess)] [OutputType([PSCustomObject])] param( [string]$RemoteName = 'origin', [string]$RemoteUrl, [string]$LogPath = '' ) $repoRoot = $null try { $repoRoot = Get-GERepoRoot } catch { $repoRoot = $null } $session = Start-GELogSession -Command 'Set-Ssh' -Repository ([string]$repoRoot) -LogPath $LogPath $userMessageOnFailure = 'Could not configure the SSH published location.' try { if (-not $repoRoot) { $repoRoot = Get-GERepoRoot } if ([string]::IsNullOrWhiteSpace($RemoteUrl)) { $currentUrl = Get-GERemoteUrl -RemoteName $RemoteName -Path $repoRoot if ([string]::IsNullOrWhiteSpace($currentUrl)) { throw "Remote '$RemoteName' is not configured. Provide -RemoteUrl." } # F-04 defence in depth: validate the input read from .git/config # before passing to Convert-GERemoteToSsh. An embedded user:token@ # in the read path would otherwise be silently carried through to # `git remote set-url` and the diagnostic log header. Convert # itself also refuses, but failing here gives a clear input-side # error rather than relying on the conversion helper's guard. Test-GERemoteUrlSafe -RemoteUrl $currentUrl | Out-Null $RemoteUrl = Convert-GERemoteToSsh -RemoteUrl $currentUrl } Test-GERemoteUrlSafe -RemoteUrl $RemoteUrl | Out-Null if ($RemoteUrl -notmatch '^git@[^:]+:.+$') { throw 'Set-Ssh requires an SSH remote URL or an existing HTTPS remote that can be converted.' } if (-not $PSCmdlet.ShouldProcess($repoRoot, "Set $RemoteName to SSH remote URL")) { Complete-GELogSession -Path $session.Path -Outcome 'SUCCESS' -UserMessage 'Skipped (WhatIf).' return } $existing = Get-GERemoteUrl -RemoteName $RemoteName -Path $repoRoot if ([string]::IsNullOrWhiteSpace($existing)) { Invoke-GEGit -ArgumentList @('remote', 'add', $RemoteName, $RemoteUrl) -WorkingDirectory $repoRoot -LogPath $session.Path | Out-Null } else { Invoke-GEGit -ArgumentList @('remote', 'set-url', $RemoteName, $RemoteUrl) -WorkingDirectory $repoRoot -LogPath $session.Path | Out-Null } $result = [PSCustomObject]@{ Repository = $repoRoot Remote = $RemoteName Url = $RemoteUrl Message = 'SSH remote configured. Run Test-Login to validate access.' } Complete-GELogSession -Path $session.Path -Outcome 'SUCCESS' return $result } catch { $err = $_ $msg = if ($err.Exception.Message -like 'git *') { $userMessageOnFailure } else { $err.Exception.Message } Complete-GELogSession -Path $session.Path -Outcome 'FAILURE' -UserMessage $msg -ErrorMessage $err.Exception.Message throw "$msg Details: $($session.Path)" } } |