plugins/vault/public/Get-JaxVaultStatus.ps1
|
function Get-JaxVaultStatus { [CmdletBinding()] param() $repoRoot = Get-JaxRepoRoot $config = Get-JaxConfig -RepoRoot $repoRoot $tokenPath = Get-JaxVaultTokenPath -RepoRoot $repoRoot -Config $config $vaultCfg = $null try { $vaultCfg = Get-JaxVaultPluginConfig } catch {} $cfgAddr = $null $cfgPolicy = $null $secretCheckPath = 'secret/hello' if ($vaultCfg -and $vaultCfg.Contains('address') -and $vaultCfg['address'] -is [string] -and -not [string]::IsNullOrWhiteSpace($vaultCfg['address'])) { $cfgAddr = $vaultCfg['address'] } if ($vaultCfg -and $vaultCfg.Contains('policy') -and $vaultCfg['policy'] -is [string] -and -not [string]::IsNullOrWhiteSpace($vaultCfg['policy'])) { $cfgPolicy = $vaultCfg['policy'] } if ($vaultCfg -and $vaultCfg.Contains('secretCheckPath') -and $vaultCfg['secretCheckPath'] -is [string] -and -not [string]::IsNullOrWhiteSpace($vaultCfg['secretCheckPath'])) { $secretCheckPath = $vaultCfg['secretCheckPath'] } $secretMount = 'secret' $secretPath = 'hello' if ($secretCheckPath -match '^(?<mount>[^/]+)/(?<path>.+)$') { $secretMount = $Matches['mount'] $secretPath = $Matches['path'] } $addr = $cfgAddr if ([string]::IsNullOrWhiteSpace($addr) -and (Test-Path Env:\VAULT_ADDR)) { $addr = (Get-Item Env:\VAULT_ADDR).Value } if ([string]::IsNullOrWhiteSpace($addr)) { $addr = "Not Set" } $token = Get-JaxVaultToken $tokenStatus = if (-not [string]::IsNullOrWhiteSpace($token)) { "Present (Length: $($token.Length))" } else { "Not Found" } Write-Host "Vault Status" -ForegroundColor Cyan Write-Host "------------" Write-Host "Address: $addr" Write-Host "Token: $tokenStatus" Write-Host "Token path: $tokenPath" if (-not [string]::IsNullOrWhiteSpace($cfgPolicy)) { Write-Host "Policy: $cfgPolicy" } # Best-effort: show token expiry info when we have address + token. if (-not [string]::IsNullOrWhiteSpace($addr) -and -not [string]::IsNullOrWhiteSpace($token)) { $oldAddr = $env:VAULT_ADDR $oldToken = $env:VAULT_TOKEN try { $env:VAULT_ADDR = $addr $env:VAULT_TOKEN = $token # Vault CLI versions differ: # - newer: `vault token lookup-self` # - some: `vault token lookup -self` # - older: `vault token lookup` (with no token arg, uses VAULT_TOKEN) $lookupOut = & vault token lookup-self -format=json 2>&1 $lookupExit = $LASTEXITCODE if ($lookupExit -ne 0 -or -not $lookupOut) { $lookupOut = & vault token lookup -self -format=json 2>&1 $lookupExit = $LASTEXITCODE } if ($lookupExit -ne 0 -or -not $lookupOut) { $lookupOut = & vault token lookup -format=json 2>&1 $lookupExit = $LASTEXITCODE } if ($lookupExit -ne 0 -or -not $lookupOut) { $details = if ($lookupOut) { ([string]$lookupOut).Trim() } else { '' } Write-Warning "Unable to lookup token info (exit: $lookupExit). Vault said: $details" return } $data = $lookupOut | ConvertFrom-Json -ErrorAction Stop if (-not $data -or -not $data.data) { return } $ttlSeconds = $null if ($data.data.PSObject.Properties.Name -contains 'ttl') { $ttlSeconds = $data.data.ttl } $expireTimeRaw = $null if ($data.data.PSObject.Properties.Name -contains 'expire_time') { $expireTimeRaw = $data.data.expire_time } if ($null -ne $ttlSeconds) { Write-Host ("TTL (seconds): {0}" -f $ttlSeconds) try { $ttlSpan = [TimeSpan]::FromSeconds([double]$ttlSeconds) $ttlDays = [int][Math]::Floor($ttlSpan.TotalDays) $ttlHours = $ttlSpan.Hours $ttlMinutes = $ttlSpan.Minutes $ttlSecondsInt = $ttlSpan.Seconds if ($ttlDays -gt 0) { Write-Host ("TTL: {0}d {1}h {2}m {3}s" -f $ttlDays, $ttlHours, $ttlMinutes, $ttlSecondsInt) } else { Write-Host ("TTL: {0}h {1}m {2}s" -f ([int]$ttlSpan.TotalHours), $ttlMinutes, $ttlSecondsInt) } } catch { # best-effort } } if (-not [string]::IsNullOrWhiteSpace([string]$expireTimeRaw)) { Write-Host ("Expire time: {0}" -f $expireTimeRaw) try { $expireAt = [datetime]::Parse([string]$expireTimeRaw, [System.Globalization.CultureInfo]::InvariantCulture) $remaining = $expireAt.ToUniversalTime() - [datetime]::UtcNow if ($remaining.TotalSeconds -lt 0) { Write-Host "Expires in: EXPIRED" -ForegroundColor Yellow } else { $days = [int][Math]::Floor($remaining.TotalDays) $hours = $remaining.Hours $minutes = $remaining.Minutes $seconds = $remaining.Seconds if ($days -gt 0) { Write-Host ("Expires in: {0}d {1}h {2}m {3}s" -f $days, $hours, $minutes, $seconds) } else { Write-Host ("Expires in: {0}h {1}m {2}s" -f ([int]$remaining.TotalHours), $minutes, $seconds) } } } catch { # best-effort: leave as raw string } } # Simple live checks to validate token access (keys only). # 1) Expected secret presence (do not print secret values). $secretOk = $false $null = & vault kv get -format=json $secretCheckPath 2>&1 $getExit = $LASTEXITCODE if ($getExit -eq 0) { $secretOk = $true } else { $null = & vault kv get -mount $secretMount -format=json $secretPath 2>&1 $getExit = $LASTEXITCODE if ($getExit -eq 0) { $secretOk = $true } } $secretStatus = if ($secretOk) { '✅' } else { '❌' } Write-Host "Secret check ($secretCheckPath): $secretStatus" # 2) List root keys under the secret mount (does not output values). $listOut = & vault kv list -format=json "$secretMount/" 2>&1 $listExit = $LASTEXITCODE if ($listExit -ne 0 -or -not $listOut) { $listOut = & vault kv list "-mount=$secretMount" -format=json / 2>&1 $listExit = $LASTEXITCODE } if ($listExit -eq 0 -and $listOut) { Write-Host "Secret keys under $secretMount/:" -ForegroundColor Cyan Write-Host ([string]$listOut).Trim() } else { $details = if ($listOut) { ([string]$listOut).Trim() } else { '' } Write-Warning "Unable to list $secretMount/ keys (exit: $listExit). Vault said: $details" } } catch { Write-Warning "Failed to retrieve token expiry info: $_" } finally { $env:VAULT_ADDR = $oldAddr $env:VAULT_TOKEN = $oldToken } } } |