diff --git a/SSH Manager/ssh-manager.ps1 b/SSH Manager/ssh-manager.ps1 index 90eda98..48155f3 100644 --- a/SSH Manager/ssh-manager.ps1 +++ b/SSH Manager/ssh-manager.ps1 @@ -1,135 +1,400 @@ -<# -SSH Manager - -Interactive SSH launcher for Windows PowerShell. - -This portfolio-safe version uses mock server names, documentation-friendly -domains, and example certificate paths. Replace the entries in $servers with -real hosts before using it in an internal environment. -#> - -param ( - [string]$SshUser = "", - [string]$IdentityFile = "", - [string]$CertificateFile = "" -) - $ErrorActionPreference = "Stop" -$defaultIdentityFile = Join-Path $PSScriptRoot "..\..\ssh\id_ed25519" -$defaultCertificatePath = Join-Path $PSScriptRoot "certificates" - -if ([string]::IsNullOrWhiteSpace($IdentityFile) -and (Test-Path -LiteralPath $defaultIdentityFile -PathType Leaf)) { - $IdentityFile = (Resolve-Path -LiteralPath $defaultIdentityFile).Path -} - $servers = @( @{ - Environment = "DEV" - Name = "Development - arlapi-dev-01.example.com" - Domain = "api-dev-01.example.com" - Host = "192.0.2.11" - Hostname = "arlapi-dev-01" - CertificatePath = $defaultCertificatePath - Port = 22 + Environment = "DEV" + Name = "Development - dev-server001.contoso.com" + Host = "dev-server001.contoso.com" + Port = 22 }, @{ - Environment = "DEV" - Name = "Development - arlworker-dev-01.example.com" - Domain = "worker-dev-01.example.com" - Host = "192.0.2.12" - Hostname = "arlworker-dev-01" - CertificatePath = $defaultCertificatePath - Port = 22 + Environment = "PROD" + Name = "Production - prod-server001.contoso.com" + Host = "prod-server001.contoso.com" + Port = 22 }, @{ - Environment = "QAS" - Name = "Quality - arlapi-qas-01.example.com" - Domain = "api-qas-01.example.com" - Host = "198.51.100.21" - Hostname = "arlapi-qas-01" - CertificatePath = $defaultCertificatePath - Port = 22 + Environment = "PROD" + Name = "Production - prod-server002.contoso.com" + Host = "prod-server002.contoso.com" + Port = 22 }, @{ - Environment = "QAS" - Name = "Quality - arldb-qas-01.example.com" - Domain = "db-qas-01.example.com" - Host = "198.51.100.22" - Hostname = "arldb-qas-01" - CertificatePath = $defaultCertificatePath - Port = 22 + Environment = "PROD" + Name = "Production - prod-server003.contoso.com" + Host = "prod-server003.contoso.com" + Port = 22 }, @{ - Environment = "QAS" - Name = "Quality - arlworker-qas-01.example.com" - Domain = "worker-qas-01.example.com" - Host = "198.51.100.23" - Hostname = "arlworker-qas-01" - CertificatePath = $defaultCertificatePath - Port = 22 + Environment = "PROD" + Name = "Production - prod-server004.contoso.com" + Host = "prod-server004.contoso.com" + Port = 22 }, @{ - Environment = "PROD" - Name = "Production - arlapi-prd-01.example.com" - Domain = "api-prd-01.example.com" - Host = "203.0.113.31" - Hostname = "arlapi-prd-01" - CertificatePath = $defaultCertificatePath - Port = 22 + Environment = "PROD" + Name = "Production - prod-server005.contoso.com" + Host = "prod-server005.contoso.com" + Port = 22 }, @{ - Environment = "PROD" - Name = "Production - arlapi-prd-02.example.com" - Domain = "api-prd-02.example.com" - Host = "203.0.113.32" - Hostname = "arlapi-prd-02" - CertificatePath = $defaultCertificatePath - Port = 22 + Environment = "PROD" + Name = "Production - prod-server006.contoso.com" + Host = "prod-server006.contoso.com" + Port = 22 }, @{ - Environment = "PROD" - Name = "Production - arldb-prd-01.example.com" - Domain = "db-prd-01.example.com" - Host = "203.0.113.33" - Hostname = "arldb-prd-01" - CertificatePath = $defaultCertificatePath - Port = 22 + Environment = "PROD" + Name = "Production - prod-server007.contoso.com" + Host = "prod-server007.contoso.com" + Port = 22 }, @{ - Environment = "PROD" - Name = "Production - arlmonitor-prd-01.example.com" - Domain = "monitor-prd-01.example.com" - Host = "203.0.113.34" - Hostname = "arlmonitor-prd-01" - CertificatePath = $defaultCertificatePath - Port = 22 + Environment = "PROD" + Name = "Production - prod-server008.contoso.com" + Host = "prod-server008.contoso.com" + Port = 22 }, @{ - Environment = "PROD" - Name = "Production - arlworker-prd-01.example.com" - Domain = "worker-prd-01.example.com" - Host = "203.0.113.35" - Hostname = "arlworker-prd-01" - CertificatePath = $defaultCertificatePath - Port = 22 + Environment = "PROD" + Name = "Production - prod-server009.contoso.com" + Host = "prod-server009.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server010.contoso.com" + Host = "prod-server010.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server011.contoso.com" + Host = "prod-server011.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server012.contoso.com" + Host = "prod-server012.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server013.contoso.com" + Host = "prod-server013.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server014.contoso.com" + Host = "prod-server014.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server015.contoso.com" + Host = "prod-server015.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server016.contoso.com" + Host = "prod-server016.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server017.contoso.com" + Host = "prod-server017.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server018.contoso.com" + Host = "prod-server018.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server019.contoso.com" + Host = "prod-server019.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server020.contoso.com" + Host = "prod-server020.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server021.contoso.com" + Host = "prod-server021.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server022.contoso.com" + Host = "prod-server022.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server023.contoso.com" + Host = "prod-server023.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server024.contoso.com" + Host = "prod-server024.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server001.contoso.com" + Host = "qas-server001.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server002.contoso.com" + Host = "qas-server002.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server003.contoso.com" + Host = "qas-server003.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server004.contoso.com" + Host = "qas-server004.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server005.contoso.com" + Host = "qas-server005.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server006.contoso.com" + Host = "qas-server006.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server007.contoso.com" + Host = "qas-server007.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server008.contoso.com" + Host = "qas-server008.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server009.contoso.com" + Host = "qas-server009.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server010.contoso.com" + Host = "qas-server010.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server011.contoso.com" + Host = "qas-server011.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server012.contoso.com" + Host = "qas-server012.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server013.contoso.com" + Host = "qas-server013.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server014.contoso.com" + Host = "qas-server014.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server015.contoso.com" + Host = "qas-server015.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server016.contoso.com" + Host = "qas-server016.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server017.contoso.com" + Host = "qas-server017.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server018.contoso.com" + Host = "qas-server018.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server019.contoso.com" + Host = "qas-server019.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server020.contoso.com" + Host = "qas-server020.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server021.contoso.com" + Host = "qas-server021.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server022.contoso.com" + Host = "qas-server022.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server023.contoso.com" + Host = "qas-server023.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server024.contoso.com" + Host = "qas-server024.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server025.contoso.com" + Host = "qas-server025.contoso.com" + Port = 22 + }, + @{ + Environment = "QAS" + Name = "Quality - qas-server026.contoso.com" + Host = "qas-server026.contoso.com" + Port = 22 + }, + @{ + Environment = "PROD" + Name = "Production - prod-server025.contoso.com" + Host = "prod-server025.contoso.com" + Port = 22 + }, + @{ + Environment = "THIRD_PARTY" + Name = "ThirdParty - thirdparty-server001.contoso.com" + Host = "thirdparty-server001.contoso.com" + Port = 22 + }, + @{ + Environment = "THIRD_PARTY" + Name = "ThirdParty - thirdparty-server002.contoso.com" + Host = "thirdparty-server002.contoso.com" + Port = 22 + }, + @{ + Environment = "THIRD_PARTY" + Name = "ThirdParty - thirdparty-server003.contoso.com" + Host = "thirdparty-server003.contoso.com" + Port = 22 + }, + @{ + Environment = "THIRD_PARTY" + Name = "ThirdParty - thirdparty-server004.contoso.com" + Host = "thirdparty-server004.contoso.com" + Port = 22 + }, + @{ + Environment = "THIRD_PARTY" + Name = "ThirdParty - thirdparty-server005.contoso.com" + Host = "thirdparty-server005.contoso.com" + Port = 22 + }, + @{ + Environment = "THIRD_PARTY" + Name = "ThirdParty - thirdparty-server006.contoso.com" + Host = "thirdparty-server006.contoso.com" + Port = 22 + }, + @{ + Environment = "THIRD_PARTY" + Name = "ThirdParty - thirdparty-server007.contoso.com" + Host = "thirdparty-server007.contoso.com" + Port = 22 + }, + @{ + Environment = "THIRD_PARTY" + Name = "ThirdParty - thirdparty-server008.contoso.com" + Host = "thirdparty-server008.contoso.com" + Port = 22 + }, + @{ + Environment = "THIRD_PARTY" + Name = "ThirdParty - thirdparty-server009.contoso.com" + Host = "thirdparty-server009.contoso.com" + Port = 22 + }, + @{ + Environment = "THIRD_PARTY" + Name = "ThirdParty - thirdparty-server010.contoso.com" + Host = "thirdparty-server010.contoso.com" + Port = 22 + }, + @{ + Environment = "THIRD_PARTY" + Name = "ThirdParty - thirdparty-server011.contoso.com" + Host = "thirdparty-server011.contoso.com" + Port = 22 + }, + @{ + Environment = "THIRD_PARTY" + Name = "ThirdParty - thirdparty-server012.contoso.com" + Host = "thirdparty-server012.contoso.com" + Port = 22 + }, + @{ + Environment = "THIRD_PARTY" + Name = "ThirdParty - thirdparty-server013.contoso.com" + Host = "thirdparty-server013.contoso.com" + Port = 22 } ) -$environments = @( - @{ - Label = "DEV" - Value = "DEV" - }, - @{ - Label = "QAS" - Value = "QAS" - }, - @{ - Label = "PRD" - Value = "PROD" - } -) +$sshUser = "brazildevops" +$environments = @("DEV", "QAS", "PROD", "THIRD_PARTY") function Show-EnvironmentMenu { Clear-Host @@ -137,7 +402,7 @@ function Show-EnvironmentMenu { Write-Host "" for ($i = 0; $i -lt $environments.Count; $i++) { - Write-Host ("[{0:D2}] {1}" -f ($i + 1), $environments[$i].Label) + Write-Host ("[{0}] {1}" -f ($i + 1), $environments[$i]) } Write-Host "" @@ -145,37 +410,6 @@ function Show-EnvironmentMenu { Write-Host "" } -function Get-EnvironmentLabel { - param ( - [hashtable]$Server - ) - - if ($Server.Name -match "^(?.+?)\s+-\s+") { - return $Matches.EnvironmentLabel - } - - return $Server.Environment -} - -function Get-ShortServerName { - param ( - [hashtable]$Server - ) - - $shortName = $Server.Hostname - - if ([string]::IsNullOrWhiteSpace($shortName)) { - $shortName = $Server.Host - } - - $shortName = $shortName.ToLowerInvariant() - $shortName = $shortName -replace "^arl", "" - $shortName = $shortName -replace "\.(e?corp|lrd)\.cat\.com$", "" - $shortName = $shortName -replace "\.example\.com$", "" - - return $shortName -} - function Show-ServerMenu { param ( [string]$Environment @@ -185,27 +419,11 @@ function Show-ServerMenu { Write-Host ("Select server from {0}:" -f $Environment) -ForegroundColor Cyan Write-Host "" - $environmentServers = @( - $servers | - Where-Object { $_.Environment -eq $Environment } | - Sort-Object { Get-ShortServerName -Server $_ } - ) - - $shortNameWidth = 0 - foreach ($server in $environmentServers) { - $shortNameLength = (Get-ShortServerName -Server $server).Length - - if ($shortNameLength -gt $shortNameWidth) { - $shortNameWidth = $shortNameLength - } - } + $environmentServers = @($servers | Where-Object { $_.Environment -eq $Environment }) for ($i = 0; $i -lt $environmentServers.Count; $i++) { $server = $environmentServers[$i] - $environmentLabel = Get-EnvironmentLabel -Server $server - $shortName = Get-ShortServerName -Server $server - - Write-Host ("[{0:D2}] {1,-11} {2,-$shortNameWidth} ({3} / {4}:{5})" -f ($i + 1), $environmentLabel, $shortName, $server.Domain, $server.Host, $server.Port) + Write-Host ("[{0}] {1} ({2}:{3})" -f ($i + 1), $server.Name, $server.Host, $server.Port) } Write-Host "" @@ -213,86 +431,9 @@ function Show-ServerMenu { Write-Host "" } -function Resolve-CertificateFile { - param ( - [string]$Path - ) - - if ([string]::IsNullOrWhiteSpace($Path)) { - return "" - } - - if (Test-Path -LiteralPath $Path -PathType Leaf) { - return $Path - } - - if (Test-Path -LiteralPath $Path -PathType Container) { - $certificateFile = Get-ChildItem -LiteralPath $Path -File | - Where-Object { $_.Name -match "(-cert\.pub|\.pem|\.crt|\.cer)$" } | - Sort-Object Name | - Select-Object -First 1 - - if ($null -ne $certificateFile) { - return $certificateFile.FullName - } - } - - return "" -} - -function Get-SshArguments { - param ( - [hashtable]$Server, - [string]$User - ) - - $sshArguments = @() - - if (-not [string]::IsNullOrWhiteSpace($IdentityFile)) { - if (-not (Test-Path -LiteralPath $IdentityFile)) { - throw "Identity file not found: $IdentityFile" - } - - Write-Host ("Using identity file: {0}" -f $IdentityFile) -ForegroundColor DarkGray - $sshArguments += @("-i", $IdentityFile) - } - - if (-not [string]::IsNullOrWhiteSpace($CertificateFile)) { - $resolvedCertificateFile = Resolve-CertificateFile -Path $CertificateFile - - if ([string]::IsNullOrWhiteSpace($resolvedCertificateFile)) { - throw "Certificate file not found: $CertificateFile" - } - - Write-Host ("Using certificate file: {0}" -f $resolvedCertificateFile) -ForegroundColor DarkGray - $sshArguments += @("-o", "CertificateFile=$resolvedCertificateFile") - } - - if ([string]::IsNullOrWhiteSpace($CertificateFile) -and $Server.ContainsKey("CertificatePath")) { - $serverCertificatePath = $Server.CertificatePath - $resolvedServerCertificateFile = Resolve-CertificateFile -Path $serverCertificatePath - - if (-not [string]::IsNullOrWhiteSpace($resolvedServerCertificateFile)) { - Write-Host ("Using certificate file: {0}" -f $resolvedServerCertificateFile) -ForegroundColor DarkGray - $sshArguments += @("-o", "CertificateFile=$resolvedServerCertificateFile") - } - elseif (-not [string]::IsNullOrWhiteSpace($serverCertificatePath)) { - Write-Host ("Certificate not found or not a file: {0}" -f $serverCertificatePath) -ForegroundColor Yellow - } - } - - if ([string]::IsNullOrWhiteSpace($User)) { - throw "SSH user not defined." - } - - $sshArguments += @("-p", $Server.Port, "$User@$($Server.Host)") - - return $sshArguments -} - if (-not (Get-Command ssh.exe -ErrorAction SilentlyContinue)) { - Write-Host "ssh.exe was not found on Windows." -ForegroundColor Red - Write-Host "Install or enable the OpenSSH Client optional feature." -ForegroundColor Yellow + Write-Host "Could not find ssh.exe on Windows." -ForegroundColor Red + Write-Host "Install or enable the OpenSSH client in Windows Optional Features." -ForegroundColor Yellow exit 1 } @@ -305,15 +446,13 @@ while ($true) { exit 0 } - $parsedEnvironmentChoice = 0 - - if (-not [int]::TryParse($environmentChoice, [ref]$parsedEnvironmentChoice)) { + if (-not [int]::TryParse($environmentChoice, [ref]$null)) { Write-Host "Invalid choice." -ForegroundColor Red Start-Sleep -Seconds 2 continue } - $environmentIndex = $parsedEnvironmentChoice - 1 + $environmentIndex = [int]$environmentChoice - 1 if ($environmentIndex -lt 0 -or $environmentIndex -ge $environments.Count) { Write-Host "Invalid choice." -ForegroundColor Red @@ -322,30 +461,23 @@ while ($true) { } $selectedEnvironment = $environments[$environmentIndex] - $selectedEnvironmentValue = $selectedEnvironment.Value - $environmentServers = @( - $servers | - Where-Object { $_.Environment -eq $selectedEnvironmentValue } | - Sort-Object { Get-ShortServerName -Server $_ } - ) + $environmentServers = @($servers | Where-Object { $_.Environment -eq $selectedEnvironment }) while ($true) { - Show-ServerMenu -Environment $selectedEnvironmentValue + Show-ServerMenu -Environment $selectedEnvironment $serverChoice = Read-Host "Your choice" if ($serverChoice -eq "0") { break } - $parsedServerChoice = 0 - - if (-not [int]::TryParse($serverChoice, [ref]$parsedServerChoice)) { + if (-not [int]::TryParse($serverChoice, [ref]$null)) { Write-Host "Invalid choice." -ForegroundColor Red Start-Sleep -Seconds 2 continue } - $serverIndex = $parsedServerChoice - 1 + $serverIndex = [int]$serverChoice - 1 if ($serverIndex -lt 0 -or $serverIndex -ge $environmentServers.Count) { Write-Host "Invalid choice." -ForegroundColor Red @@ -354,25 +486,12 @@ while ($true) { } $selectedServer = $environmentServers[$serverIndex] - $sshUserForConnection = $SshUser - - if ([string]::IsNullOrWhiteSpace($sshUserForConnection)) { - $sshUserForConnection = Read-Host "SSH user" - } - - if ([string]::IsNullOrWhiteSpace($sshUserForConnection)) { - Write-Host "SSH user is required." -ForegroundColor Red - Start-Sleep -Seconds 2 - continue - } - - $sshArguments = Get-SshArguments -Server $selectedServer -User $sshUserForConnection Write-Host "" - Write-Host ("Connecting to {0} as {1}..." -f $selectedServer.Name, $sshUserForConnection) -ForegroundColor Green + Write-Host ("Connecting to {0}..." -f $selectedServer.Name) -ForegroundColor Green - & ssh.exe @sshArguments + & ssh.exe -p $selectedServer.Port "$sshUser@$($selectedServer.Host)" exit $LASTEXITCODE } } - +