#!/usr/bin/env pwsh # run_once_windows_setup-ssh-keys.ps1.tmpl # Pulls SSH private keys from Bitwarden and writes them to ~/.ssh/. # # Public keys (.pub files) are committed directly to the repo in dot_ssh/ # and are applied automatically by chezmoi — no Bitwarden needed for those. # # Requires: bw (Bitwarden CLI) to be logged in and unlocked. # To unlock Bitwarden before running chezmoi: # $env:BW_SESSION = bw unlock --raw # chezmoi apply $ErrorActionPreference = "Stop" Write-Host "==> Setting up SSH keys from Bitwarden..." -ForegroundColor Cyan $SshDir = Join-Path $env:USERPROFILE ".ssh" New-Item -ItemType Directory -Force $SshDir | Out-Null # Verify Bitwarden is unlocked before fetching keys Write-Host " Checking Bitwarden vault status... " -NoNewline $bwStatus = (bw status 2>&1 | ConvertFrom-Json).status if ($bwStatus -ne "unlocked") { Write-Host "locked" -ForegroundColor Yellow if ($env:BW_SESSION) { Write-Host " Session locked — unlocking with BW_SESSION..." -ForegroundColor Yellow $env:BW_SESSION = bw unlock --raw 2>&1 $bwStatus = (bw status 2>&1 | ConvertFrom-Json).status } if ($bwStatus -ne "unlocked") { Write-Host " WARNING: Bitwarden vault is not unlocked. Skipping SSH key setup." -ForegroundColor Yellow Write-Host " Run: `$env:BW_SESSION = bw unlock --raw; chezmoi apply" exit 0 } } else { Write-Host "unlocked" -ForegroundColor Green } # Pre-sync to avoid sequential sync delays per key fetch Write-Host " Syncing vault..." bw sync 2>&1 | Out-Null function Write-Key($name, $bwItemName) { $keyPath = Join-Path $SshDir $name if (Test-Path $keyPath) { Write-Host " Key already exists: $name (skipping)" -ForegroundColor DarkGray return } Write-Host " Fetching key: $bwItemName -> $name" -NoNewline try { $content = bw get notes --session $env:BW_SESSION "$bwItemName" 2>&1 if ($LASTEXITCODE -ne 0) { throw $content } [System.IO.File]::WriteAllText($keyPath, $content) & icacls $keyPath /inheritance:r /grant "$env:USERNAME:(R,W)" /q 2>&1 | Out-Null Write-Host "" -NoNewline Write-Host " Wrote: $keyPath" -ForegroundColor Green } catch { Write-Host "" -NoNewline Write-Host " WARNING: Could not fetch '$bwItemName' from Bitwarden. Skipping." -ForegroundColor Yellow if (Test-Path $keyPath) { Remove-Item $keyPath -Force } } } # Derive private key names from the public key files in dot_ssh/ $chezmoiSourceDir = "{{ .chezmoi.sourceDir }}" Get-ChildItem "$chezmoiSourceDir\dot_ssh\*.pub" | ForEach-Object { $keyName = $_.BaseName Write-Key $keyName "SSH Key - $keyName" } Write-Host "==> SSH key setup complete!" -ForegroundColor Cyan