diff --git a/scripts/ssh-key-cleanup.ps1 b/scripts/ssh-key-cleanup.ps1 deleted file mode 100644 index 8949ae0..0000000 --- a/scripts/ssh-key-cleanup.ps1 +++ /dev/null @@ -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 '' } - try { return (& ssh-keygen -lf $path 2>$null).Trim() } catch { return '' } -} - -# 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