v1.7.0 — Multi-Account + Real-time Streaming
A major release featuring multi-account support (PR #6) and real-time Bedrock streaming as core features. Includes 25 security fixes.
Multi-Account (PR #6) · Real-time Streaming · Cache Pre-warming · 25 Security Fixes · Customer Logo Customization
Multi-Account Architecture (PR #6)
Manage multiple AWS accounts from a single dashboard using the Steampipe Aggregator pattern. Add accounts by simply changing the accounts[] array in data/config.json with no code changes required.
| Component | File | Role |
|---|---|---|
AccountContext | src/components/ | Account state management + useAccount() hook |
AccountSelector | src/components/ | Account switching dropdown (ARIA, keyboard support) |
AccountBadge | src/components/ | Per-account color dot + alias display |
buildSearchPath() | src/lib/steampipe.ts | Returns public, aws_{id}, kubernetes, trivy |
runCostQueriesPerAccount() | src/lib/steampipe.ts | Runs Cost queries per account then merges with account_id tags |
/accounts page | src/app/accounts/ | Account add/remove/test UI |
cross_account.py | agent/ | STS AssumeRole (credential caching, ExternalId, audit logging) |
| Setup Script | scripts/11-setup-multi-account.sh | Aggregator + cross-account IAM role automation |
Added account_id column to all 25 SQL queries and applied useAccountContext() to all 35 pages. DataTable auto-adds an Account column when isMultiAccount && data[0].account_id is detected.
config.json Structure
{
"accounts": [
{
"accountId": "111111111111",
"alias": "Host",
"connectionName": "aws_111111111111",
"region": "ap-northeast-2",
"isHost": true,
"features": {
"costEnabled": true,
"eksEnabled": true,
"k8sEnabled": true
}
},
{
"accountId": "222222222222",
"alias": "Staging",
"connectionName": "aws_222222222222",
"region": "ap-northeast-2",
"isHost": false,
"features": {
"costEnabled": false,
"eksEnabled": false,
"k8sEnabled": false
}
}
]
}
Security Fixes (25 Items)
25 security issues were fixed, classified into 3 severity levels.
Cross-account AssumeRole now requires audit logging and ExternalId to prevent privilege escalation and Confused Deputy attacks.
| Severity | Count | Key Items |
|---|---|---|
| CRITICAL | 2 | AssumeRole audit logging, ExternalId enforcement |
| HIGH | 5 | Rate Limiting (5 req/min), input validation hardening, execFileSync security |
| MEDIUM | 18 | Pool exhaustion prevention, connection destruction, error message filtering |
CRITICAL Details:
| Issue | Risk | Fix |
|---|---|---|
| No AssumeRole audit | Cross-account access untraceable | All AssumeRole calls logged in cross_account.py |
| No ExternalId | Confused Deputy attack possible | ExternalId added as required parameter for AssumeRole |
HIGH Details:
| Issue | Risk | Fix |
|---|---|---|
| No Rate Limiting | API abuse, cost explosion | 5 req/min limit applied to AI route |
| Insufficient input validation | SQL Injection possible | Query parameter whitelist validation |
execFileSync usage | Command Injection | Converted to argument array approach |
Real-time Bedrock Streaming
Bedrock responses are transmitted in real time, chunk by chunk.
| Item | Before (v1.6.0) | After (v1.7.0) |
|---|---|---|
| Bedrock Response | Full text at once | Chunk-based real-time |
| API | InvokeModelCommand | InvokeModelWithResponseStreamCommand |
| Delivery Method | done event after completion | Continuous chunk event delivery |
| Client | Full text rendering | Real-time rendering with streamingContent state |
The streamBedrockToSSE() function (src/app/api/ai/route.ts) reads chunks from the Bedrock stream and converts them to SSE chunk events.
Cache Pre-warming
Background cache pre-warming introduced to improve dashboard loading speed.
| Item | Description |
|---|---|
| Queries | Dashboard 23 + Monitoring 10 = 33 |
| Refresh Cycle | 4 minutes (before 5-min cache TTL expiration) |
| Initialization | ensureCacheWarmerStarted() — lazy-init pattern |
| Effect | Cache hit on first page load for instant response |
Customer Logo Customization
Set a customer logo in data/config.json and it reflects within 1 minute without server restart.
{
"customerLogo": "/logos/customer-logo.png",
"customerName": "Customer Corp",
"customerLogoBg": "#ffffff"
}
- Place logo files in the
public/logos/directory - Brand switching via config change only — no code changes required
Version Comparison
| Item | v1.6.0 | v1.7.0 | Change |
|---|---|---|---|
| Pages | 35 | 36 | +accounts |
| Components | 15 | 17 | +AccountBadge, AccountSelector |
| ADRs | 7 | 8 | +multi-account |
| Deploy Scripts | 10 | 11 | +Step 11 |
| SQL Queries | 25 | 25 | +account_id column added |
| Security Fixes | - | 25 items | CRITICAL 2, HIGH 5, MEDIUM 18 |