f
Some checks failed
smoke-mm / Install & smoke test mm --help (push) Has been cancelled
Some checks failed
smoke-mm / Install & smoke test mm --help (push) Has been cancelled
This commit is contained in:
@@ -1,231 +0,0 @@
|
|||||||
<#
|
|
||||||
ssh-key-cleanup.ps1
|
|
||||||
Interactive PowerShell script to: backup existing SSH keys/config, choose or generate an ED25519 key, add it to ssh-agent, copy public key to clipboard (so you can add it to Gitea), update your SSH config for a host/port, test SSH auth, and optionally update git remote and run a fetch/pull.
|
|
||||||
|
|
||||||
IMPORTANT: If you exposed a private key publicly, treat it as compromised. The script can generate a fresh key for you (recommended in that case) and helps you remove old keys from Gitea if you provide a token.
|
|
||||||
#>
|
|
||||||
|
|
||||||
Set-StrictMode -Version Latest
|
|
||||||
$ErrorActionPreference = 'Stop'
|
|
||||||
|
|
||||||
# Defaults - change when prompted
|
|
||||||
$defaultHost = 'code.glowers.club'
|
|
||||||
$defaultPort = 1488
|
|
||||||
$defaultKeyBasename = 'id_ed25519_gitea'
|
|
||||||
$defaultOwner = 'goyimnose'
|
|
||||||
$defaultRepo = 'Medios-Macina'
|
|
||||||
$defaultGitName = 'Nose'
|
|
||||||
$defaultGitEmail = 'goyimnose@nothing.blah'
|
|
||||||
|
|
||||||
function Show-Header {
|
|
||||||
Write-Host "`n=== SSH Key Cleanup & Setup ===`n" -ForegroundColor Cyan
|
|
||||||
}
|
|
||||||
|
|
||||||
Show-Header
|
|
||||||
|
|
||||||
# Interactive prompts
|
|
||||||
$sshHost = Read-Host "Gitea SSH host [$defaultHost]"
|
|
||||||
if ([string]::IsNullOrWhiteSpace($sshHost)) { $sshHost = $defaultHost }
|
|
||||||
$portInput = Read-Host "SSH port (22 or custom) [$defaultPort]"
|
|
||||||
if ([string]::IsNullOrWhiteSpace($portInput)) { $sshPort = [int]$defaultPort } else { $sshPort = [int]$portInput }
|
|
||||||
$owner = Read-Host "Repo owner [$defaultOwner]"
|
|
||||||
if ([string]::IsNullOrWhiteSpace($owner)) { $owner = $defaultOwner }
|
|
||||||
$repo = Read-Host "Repo name [$defaultRepo]"
|
|
||||||
if ([string]::IsNullOrWhiteSpace($repo)) { $repo = $defaultRepo }
|
|
||||||
$gitName = Read-Host "Git user.name [$defaultGitName]"
|
|
||||||
if ([string]::IsNullOrWhiteSpace($gitName)) { $gitName = $defaultGitName }
|
|
||||||
$gitEmail = Read-Host "Git user.email [$defaultGitEmail]"
|
|
||||||
if ([string]::IsNullOrWhiteSpace($gitEmail)) { $gitEmail = $defaultGitEmail }
|
|
||||||
|
|
||||||
Write-Host "`nSummary:`n Host: $sshHost`n Port: $sshPort`n Repo: $owner/$repo`n Git identity: $gitName <$gitEmail>`n"
|
|
||||||
$confirm = Read-Host "Proceed and start (this will back up existing keys/config first)? (Y/N)"
|
|
||||||
if ($confirm.ToUpper() -ne 'Y') { Write-Host 'Aborted.'; exit 0 }
|
|
||||||
|
|
||||||
# Paths
|
|
||||||
$sshDir = Join-Path $env:USERPROFILE '.ssh'
|
|
||||||
if (-not (Test-Path $sshDir)) { New-Item -ItemType Directory -Path $sshDir -Force | Out-Null }
|
|
||||||
$ts = Get-Date -Format "yyyyMMdd-HHmmss"
|
|
||||||
$backupDir = Join-Path $sshDir "backup_$ts"
|
|
||||||
|
|
||||||
# 1) Backup existing id_* keys and config (copy, safe)
|
|
||||||
$toBackup = Get-ChildItem -Path $sshDir -File -Force | Where-Object { $_.Name -match '^id_' -or $_.Name -eq 'config' }
|
|
||||||
if ($toBackup) {
|
|
||||||
New-Item -ItemType Directory -Path $backupDir -Force | Out-Null
|
|
||||||
foreach ($f in $toBackup) {
|
|
||||||
Copy-Item -Path $f.FullName -Destination $backupDir -Force
|
|
||||||
}
|
|
||||||
Write-Host "Backed up existing keys/config to: $backupDir" -ForegroundColor Yellow
|
|
||||||
} else {
|
|
||||||
Write-Host "No existing id_* keys or config found to back up." -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
|
|
||||||
# Helper to print fingerprint safely
|
|
||||||
function Get-Fingerprint($path) {
|
|
||||||
if (-not (Test-Path $path)) { return '<missing>' }
|
|
||||||
try { return (& ssh-keygen -lf $path 2>$null).Trim() } catch { return '<error reading>' }
|
|
||||||
}
|
|
||||||
|
|
||||||
# 2) Show existing public keys
|
|
||||||
$pubFiles = Get-ChildItem -Path $sshDir -Filter 'id_*.pub' -File -ErrorAction SilentlyContinue | Sort-Object Name
|
|
||||||
if ($pubFiles -and $pubFiles.Count -gt 0) {
|
|
||||||
Write-Host "`nFound public keys:`n" -ForegroundColor Cyan
|
|
||||||
for ($i=0; $i -lt $pubFiles.Count; $i++) {
|
|
||||||
$f = $pubFiles[$i]
|
|
||||||
$fp = Get-Fingerprint $f.FullName
|
|
||||||
Write-Host "[$($i+1)] $($f.Name) - $fp"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Write-Host "No public keys found in $sshDir." -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
|
|
||||||
# 3) Choose to use existing or generate new
|
|
||||||
$choice = Read-Host "Enter the number of the key to keep as default, or 'n' to generate a NEW key (recommended if a key was exposed) [n]"
|
|
||||||
if ([string]::IsNullOrWhiteSpace($choice)) { $choice = 'n' }
|
|
||||||
|
|
||||||
if ($choice -eq 'n' -or $choice -eq 'N') {
|
|
||||||
$keyBasename = Read-Host "Key basename to create (default: $defaultKeyBasename)"
|
|
||||||
if ([string]::IsNullOrWhiteSpace($keyBasename)) { $keyBasename = $defaultKeyBasename }
|
|
||||||
$privKey = Join-Path $sshDir $keyBasename
|
|
||||||
$pubKey = "${privKey}.pub"
|
|
||||||
|
|
||||||
if (Test-Path $privKey) {
|
|
||||||
$ov = Read-Host "Private key $privKey already exists; overwrite it? (Y/N)"
|
|
||||||
if ($ov.ToUpper() -ne 'Y') { Write-Host 'Aborted by user (kept existing files).'; exit 1 }
|
|
||||||
Remove-Item $privKey -Force -ErrorAction SilentlyContinue
|
|
||||||
Remove-Item $pubKey -Force -ErrorAction SilentlyContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "Generating ED25519 key: $privKey" -ForegroundColor Green
|
|
||||||
& ssh-keygen -t ed25519 -C $gitEmail -f $privKey -N "" | Out-Null
|
|
||||||
if (-not (Test-Path $pubKey)) { Write-Host "Key generation failed." -ForegroundColor Red; exit 1 }
|
|
||||||
} else {
|
|
||||||
# try to parse number
|
|
||||||
$ok = $false
|
|
||||||
try { $idx = [int]$choice - 1 } catch { $idx = -1 }
|
|
||||||
if ($idx -ge 0 -and $idx -lt $pubFiles.Count) {
|
|
||||||
$pubKey = $pubFiles[$idx].FullName
|
|
||||||
$privKey = $pubKey -replace '\.pub$',''
|
|
||||||
if (-not (Test-Path $privKey)) {
|
|
||||||
Write-Host "Private key associated with $pubKey is missing. You must generate a new key or restore the private key from backup." -ForegroundColor Red
|
|
||||||
$regen = Read-Host "Generate a new key instead (Y/N)?"
|
|
||||||
if ($regen.ToUpper() -ne 'Y') { Write-Host 'Aborted.'; exit 1 }
|
|
||||||
$keyBasename = Read-Host "New key basename (default: $defaultKeyBasename)"
|
|
||||||
if ([string]::IsNullOrWhiteSpace($keyBasename)) { $keyBasename = $defaultKeyBasename }
|
|
||||||
$privKey = Join-Path $sshDir $keyBasename
|
|
||||||
$pubKey = "${privKey}.pub"
|
|
||||||
& ssh-keygen -t ed25519 -C $gitEmail -f $privKey -N "" | Out-Null
|
|
||||||
if (-not (Test-Path $pubKey)) { Write-Host "Key generation failed." -ForegroundColor Red; exit 1 }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Write-Host "Invalid selection. Aborting." -ForegroundColor Red
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Resolve full absolute path (and normalize)
|
|
||||||
$privKeyFull = (Resolve-Path $privKey).Path
|
|
||||||
$pubKeyFull = "$privKeyFull.pub"
|
|
||||||
|
|
||||||
Write-Host "`nSelected private key: $privKeyFull`nPublic key: $pubKeyFull" -ForegroundColor Cyan
|
|
||||||
Write-Host "Fingerprint: $(Get-Fingerprint $pubKeyFull)" -ForegroundColor Cyan
|
|
||||||
|
|
||||||
# 4) Ensure ssh-agent running and add the key
|
|
||||||
try {
|
|
||||||
$svc = Get-Service -Name ssh-agent -ErrorAction SilentlyContinue
|
|
||||||
if ($svc -and $svc.Status -ne 'Running') {
|
|
||||||
try { Start-Service -Name ssh-agent -ErrorAction Stop } catch { Write-Host "Could not start ssh-agent service — run PowerShell as Administrator to start it or add the key manually." -ForegroundColor Yellow }
|
|
||||||
} elseif (-not $svc) {
|
|
||||||
Write-Host "ssh-agent service not found (OpenSSH Client may not be installed). The script will still try to add the key but agent may be unavailable." -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
} catch { Write-Host "Error checking ssh-agent: $_" -ForegroundColor Red }
|
|
||||||
|
|
||||||
Write-Host "Adding key to ssh-agent..."
|
|
||||||
try {
|
|
||||||
& ssh-add -D 2>$null | Out-Null
|
|
||||||
& ssh-add $privKeyFull 2>&1 | Write-Host
|
|
||||||
} catch { Write-Host "ssh-add failed: $_" -ForegroundColor Red }
|
|
||||||
|
|
||||||
Write-Host "Agent identities:`n"; & ssh-add -l
|
|
||||||
|
|
||||||
# 5) Copy public key to clipboard and open Gitea SSH keys page
|
|
||||||
try {
|
|
||||||
$pubText = Get-Content -Raw $pubKeyFull
|
|
||||||
} catch { Write-Host "Could not read public key file: $pubKeyFull" -ForegroundColor Red; exit 1 }
|
|
||||||
|
|
||||||
if (Get-Command Set-Clipboard -ErrorAction SilentlyContinue) { $pubText | Set-Clipboard } else { $pubText | clip }
|
|
||||||
Write-Host "Public key copied to clipboard. Opening Gitea SSH keys page..." -ForegroundColor Green
|
|
||||||
Start-Process "https://$sshHost/user/settings/keys"
|
|
||||||
|
|
||||||
$added = Read-Host "Paste the key into Gitea and save it (or use API). Press Enter once you've added it to proceed"
|
|
||||||
|
|
||||||
# Optionally add key via Gitea API if user provides a token
|
|
||||||
$useApi = Read-Host "Add key to Gitea automatically using API (requires token)? (Y/N) [N]"
|
|
||||||
if ([string]::IsNullOrWhiteSpace($useApi) -or $useApi.ToUpper() -ne 'Y') { $useApi = 'N' }
|
|
||||||
if ($useApi -eq 'Y') {
|
|
||||||
$token = Read-Host "Enter Gitea personal access token (will not be stored)"
|
|
||||||
if (-not [string]::IsNullOrWhiteSpace($token)) {
|
|
||||||
try {
|
|
||||||
$body = @{ title = "ps-key-$ts"; key = $pubText } | ConvertTo-Json
|
|
||||||
$resp = Invoke-RestMethod -Uri "https://$sshHost/api/v1/user/keys" -Method Post -Headers @{ Authorization = "token $token" } -Body $body -ContentType "application/json"
|
|
||||||
Write-Host "Added key via API: id $($resp.id) title $($resp.title)" -ForegroundColor Green
|
|
||||||
} catch { Write-Host "API add failed: $_" -ForegroundColor Yellow }
|
|
||||||
} else { Write-Host "No token provided; skipped API add." -ForegroundColor Yellow }
|
|
||||||
}
|
|
||||||
|
|
||||||
# 6) Clean stray problematic host entries and write host block
|
|
||||||
$configPath = Join-Path $sshDir 'config'
|
|
||||||
$hostBlock = @"
|
|
||||||
Host $sshHost
|
|
||||||
HostName $sshHost
|
|
||||||
User git
|
|
||||||
Port $sshPort
|
|
||||||
IdentityFile $(($privKeyFull).Replace('\','/'))
|
|
||||||
IdentitiesOnly yes
|
|
||||||
"@
|
|
||||||
|
|
||||||
if (Test-Path $configPath) {
|
|
||||||
$cfg = Get-Content -Raw $configPath
|
|
||||||
# Remove stray automation host entries and any existing block for this host
|
|
||||||
$cfg = [regex]::Replace($cfg, "(?ms)Host\s+System\.Management\.Automation\.[^\r\n]*\b.*?(?=(?:^Host\s+\S)|\z)", '')
|
|
||||||
$cfg = [regex]::Replace($cfg, "(?ms)Host\s+$([regex]::Escape($sshHost))\b.*?(?=(?:^Host\s+\S)|\z)", '')
|
|
||||||
($cfg.TrimEnd() + "`n`n" + $hostBlock) | Out-File -FilePath $configPath -Encoding ascii
|
|
||||||
Write-Host "Updated $configPath with host config for $sshHost" -ForegroundColor Green
|
|
||||||
} else {
|
|
||||||
$hostBlock | Out-File -FilePath $configPath -Encoding ascii
|
|
||||||
Write-Host "Wrote new SSH config at $configPath" -ForegroundColor Green
|
|
||||||
}
|
|
||||||
|
|
||||||
# 7) Verify SSH connection
|
|
||||||
Write-Host "`nTesting SSH connection to git@$sshHost (port $sshPort)..." -ForegroundColor Cyan
|
|
||||||
$sshTest = & ssh -i $privKeyFull -p $sshPort -o IdentitiesOnly=yes -vT "git@$sshHost" 2>&1
|
|
||||||
$sshTest | Select-Object -Last 60 | ForEach-Object { Write-Host $_ }
|
|
||||||
if ($sshTest -match "Permission denied") {
|
|
||||||
Write-Host "SSH authentication failed: Permission denied (publickey)." -ForegroundColor Red
|
|
||||||
Write-Host "Double-check that you added the exact public key to the correct Gitea account and that that account has access to $owner/$repo." -ForegroundColor Yellow
|
|
||||||
Write-Host "If you previously exposed a private key, remove it from Gitea and generate a new key (this script can do that)." -ForegroundColor Yellow
|
|
||||||
exit 1
|
|
||||||
} else {
|
|
||||||
Write-Host "SSH test did not report Permission denied — good sign. Check above for an authenticated greeting." -ForegroundColor Green
|
|
||||||
}
|
|
||||||
|
|
||||||
# 8) Update Git remote to SSH (with port if non-standard)
|
|
||||||
if ($sshPort -eq 22) { $sshRemote = "git@${sshHost}:${owner}/${repo}.git" } else { $sshRemote = "ssh://git@${sshHost}:${sshPort}/${owner}/${repo}.git" }
|
|
||||||
$setRemote = Read-Host "Set git remote 'origin' to $sshRemote ? (Y/N) [Y]"
|
|
||||||
if ([string]::IsNullOrWhiteSpace($setRemote) -or $setRemote.ToUpper() -eq 'Y') {
|
|
||||||
& git remote set-url origin $sshRemote
|
|
||||||
Write-Host "Updated git remote origin to: $sshRemote" -ForegroundColor Green
|
|
||||||
& git remote -v
|
|
||||||
try {
|
|
||||||
Write-Host "Running a test fetch (using the selected key)..." -ForegroundColor Cyan
|
|
||||||
& git -c core.sshCommand="ssh -i $privKeyFull -p $sshPort -o IdentitiesOnly=yes" fetch origin
|
|
||||||
Write-Host "Fetch succeeded." -ForegroundColor Green
|
|
||||||
$pullOk = Read-Host "Attempt 'git pull --tags origin main' now? (Y/N) [N]"
|
|
||||||
if ($pullOk -and $pullOk.ToUpper() -eq 'Y') {
|
|
||||||
& git -c core.sshCommand="ssh -i $privKeyFull -p $sshPort -o IdentitiesOnly=yes" pull --tags origin main
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
Write-Host "Git fetch/pull failed: $_" -ForegroundColor Red
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "`nDone. If everything succeeded, SSH and Git should now use the selected key. If you still see permission errors, paste 'ssh -vT git@$sshHost' and 'ssh-add -l' output so I can help debug." -ForegroundColor Cyan
|
|
||||||
Reference in New Issue
Block a user