<# .SYNOPSIS Migrates Fuchs Intranet secrets to Azure Key Vault "pcwkeys". .DESCRIPTION Reads secret values from a JSON file and uploads them to Key Vault under the "fuchs--" prefix convention used by the OCORE SecretManagement library. Secret naming: fuchs--{ConfigSection}--{ConfigKey} e.g. "fuchs--ConnectionStrings--ocms_ConnectionString" The JSON file must have the format: { "fuchs--ConnectionStrings--ocms_ConnectionString": "actual-value", ... } .NOTES Run once as part of the initial Key Vault migration. NEVER commit the secrets JSON file - it is listed in .gitignore. Requires: Az PowerShell module (Install-Module Az -Scope CurrentUser) Requires: Key Vault Secrets Officer role (or legacy Access Policy: Set + Get + List) .EXAMPLE .\migrate-fuchs-secrets-to-keyvault.ps1 -SecretsFile .\Scripts\secrets.json .\migrate-fuchs-secrets-to-keyvault.ps1 -SecretsFile .\Scripts\secrets.json -WhatIf #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)] [string] $SecretsFile, [string] $VaultName = "pcwkeys" ) # --------------------------------------------------------------------------- # 1. Login check # --------------------------------------------------------------------------- $ctx = Get-AzContext -ErrorAction SilentlyContinue if (-not $ctx) { Write-Host "Not logged in - running Connect-AzAccount..." -ForegroundColor Yellow Connect-AzAccount } else { Write-Host "Using Azure account: $($ctx.Account.Id)" -ForegroundColor Cyan } # --------------------------------------------------------------------------- # 2. Load secrets from JSON file # --------------------------------------------------------------------------- if (-not (Test-Path $SecretsFile)) { Write-Host "" Write-Host "ERROR: Secrets file not found: $SecretsFile" -ForegroundColor Red Write-Host "Create it from the template: Scripts\secrets.json" -ForegroundColor Yellow exit 1 } try { $json = Get-Content $SecretsFile -Raw -Encoding UTF8 -ErrorAction Stop $parsed = $json | ConvertFrom-Json -ErrorAction Stop $secrets = [ordered]@{} $parsed.PSObject.Properties | ForEach-Object { $secrets[$_.Name] = $_.Value } } catch { Write-Host "" Write-Host "ERROR: Failed to parse $SecretsFile - $($_.Exception.Message)" -ForegroundColor Red exit 1 } Write-Host "Loaded $($secrets.Count) secrets from: $SecretsFile" -ForegroundColor Cyan # --------------------------------------------------------------------------- # 3. Validate - abort if any value is still empty # --------------------------------------------------------------------------- $empty = $secrets.Keys | Where-Object { [string]::IsNullOrWhiteSpace($secrets[$_]) } if ($empty) { Write-Host "" Write-Host "ERROR: The following secrets have no value set:" -ForegroundColor Red $empty | ForEach-Object { Write-Host " $_" -ForegroundColor Red } Write-Host "" Write-Host "Fill in the values in secrets.json, then run again." -ForegroundColor Yellow exit 1 } # --------------------------------------------------------------------------- # 4. Write secrets to Key Vault # --------------------------------------------------------------------------- $total = $secrets.Count $done = 0 $failed = @() Write-Host "" Write-Host "Migrating $total secrets to Key Vault '$VaultName'..." -ForegroundColor Cyan Write-Host "" foreach ($name in $secrets.Keys) { $done++ $pct = [int](($done / $total) * 100) Write-Progress -Activity "Uploading secrets to $VaultName" -Status "$name" -PercentComplete $pct if ($PSCmdlet.ShouldProcess($VaultName, "Set secret '$name'")) { try { $secureValue = ConvertTo-SecureString $secrets[$name] -AsPlainText -Force $null = Set-AzKeyVaultSecret -VaultName $VaultName -Name $name -SecretValue $secureValue Write-Host " [OK] [$done/$total] $name" -ForegroundColor Green } catch { Write-Host " [FAIL] [$done/$total] $name - $($_.Exception.Message)" -ForegroundColor Red $failed += $name } } else { Write-Host " [WhatIf] Would set: $name" -ForegroundColor DarkCyan } } Write-Progress -Activity "Uploading secrets" -Completed # --------------------------------------------------------------------------- # 5. Summary # --------------------------------------------------------------------------- Write-Host "" if ($failed.Count -eq 0) { Write-Host "Migration complete - $done/$total secrets written." -ForegroundColor Green } else { Write-Host "Migration finished with $($failed.Count) error(s):" -ForegroundColor Yellow $failed | ForEach-Object { Write-Host " $_" -ForegroundColor Red } } Write-Host "" Write-Host "Next steps:" -ForegroundColor Cyan Write-Host " 1. Verify appsettings.json has VaultUri set to https://pcwkeys.vault.azure.net/" Write-Host " 2. Start the app and confirm '[OCORE.Secrets:fuchs] Sync OK' appears in logs" Write-Host " 3. Clear the secret values from secrets.json after a successful run"