param( [switch]$Store, [switch]$UnlockOnly, [string]$ClientId, [string]$ClientSecret, [string]$Password ) $ErrorActionPreference = 'Stop' Add-Type -AssemblyName System.Security $Dir = Join-Path $env:LOCALAPPDATA 'bw-cli' $CredFile = Join-Path $Dir 'creds.bin' $SessionFile = Join-Path $Dir 'session.txt' $LogFile = Join-Path $Dir 'auth.log' function Write-Log($msg) { ("{0} {1}" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $msg) | Add-Content -Path $LogFile } function Protect-String([string]$plain) { [System.Security.Cryptography.ProtectedData]::Protect([Text.Encoding]::UTF8.GetBytes($plain), $null, 'CurrentUser') } function Unprotect-String([byte[]]$blob) { [Text.Encoding]::UTF8.GetString([System.Security.Cryptography.ProtectedData]::Unprotect($blob, $null, 'CurrentUser')) } if ($Store) { if (-not $ClientId) { $ClientId = Read-Host 'BW_CLIENTID' } if (-not $ClientSecret) { $ClientSecret = Read-Host 'BW_CLIENTSECRET' -AsSecureString; $ClientSecret = [Net.NetworkCredential]::new('', $ClientSecret).Password } if (-not $Password) { $Password = Read-Host 'Master password' -AsSecureString; $Password = [Net.NetworkCredential]::new('', $Password).Password } New-Item -ItemType Directory -Path $Dir -Force | Out-Null $payload = [PSCustomObject]@{ clientId = $ClientId; clientSecret = $ClientSecret; password = $Password } | ConvertTo-Json -Compress [IO.File]::WriteAllBytes($CredFile, (Protect-String $payload)) Write-Log "Credential stored (DPAPI, user scope)" "OK: credential tersimpan DPAPI di $CredFile" exit 0 } if (-not (Test-Path $CredFile)) { Write-Error 'Credential file tidak ada. Jalankan dulu: ./bw-auth.ps1 -Store' } $cred = Unprotect-String ([IO.File]::ReadAllBytes($CredFile)) | ConvertFrom-Json $env:BW_CLIENTID = $cred.clientId $env:BW_CLIENTSECRET = $cred.clientSecret $env:BW_PASSWORD = $cred.password # Ensure server config (may error if already logged in — harmless) try { bw config server https://vault.s.dimanaaja.biz.id 2>$null | Out-Null } catch {} Write-Log 'Server config ensured' # Login if not authenticated $status = bw status 2>&1 | Out-String | ConvertFrom-Json if ($status.status -eq 'unauthenticated') { bw login --apikey 2>&1 | Out-Null Write-Log 'Logged in via API key' $status = bw status 2>&1 | Out-String | ConvertFrom-Json } if ($status.status -eq 'locked' -or $UnlockOnly) { $session = (bw unlock --raw --passwordenv BW_PASSWORD 2>$null) if (-not $session) { Write-Error 'Unlock gagal — cek master password / creds' } Set-Content -Path $SessionFile -Value $session -NoNewline $env:BW_SESSION = $session Write-Log 'Unlocked; session cached' $status = bw status 2>&1 | Out-String | ConvertFrom-Json } $session = Get-Content $SessionFile -Raw # Inject into tmux session if running if (tmux ls 2>$null | Select-String 'bw-session') { tmux send-keys -t bw-session "`$env:BW_SESSION='$session'; clear" Enter Write-Log 'BW_SESSION injected into tmux bw-session' } "status=$($status.status) user=$($status.userEmail) server=$($status.serverUrl)"