Skip to content

Commit 138c773

Browse files
feat: added my-aws-dashboard app
1 parent 011f7aa commit 138c773

13 files changed

Lines changed: 2999 additions & 0 deletions

File tree

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# My AWS Dashboards
2+
3+
> A browser-based AWS cost and billing monitor with interactive charts, service breakdowns, and exportable reports — built as part of [vibe.j2team.org](https://vibe.j2team.org).
4+
5+
![My AWS Dashboards](https://vibe.j2team.org/my-aws-dashboard)
6+
7+
## Overview
8+
9+
**My AWS Dashboards** is a self-contained, client-side tool for visualizing AWS account costs and billing data. It ships with a full-featured demo mode using realistic simulated data so you can explore the dashboard immediately — no AWS account required.
10+
11+
When connected to a real AWS account, the app authenticates through **Amazon Cognito Identity Pools**, which issues short-lived STS credentials. No long-lived IAM access keys are ever entered or stored.
12+
13+
> [!IMPORTANT]
14+
> AWS Cost Explorer does not support CORS for direct browser requests. When connected via Cognito, the app will attempt a live connection and gracefully fall back to demo mode if CORS blocks the request. See [Real AWS Data](#real-aws-data) for workarounds.
15+
16+
## Features
17+
18+
- **Cost Explorer Dashboard** — visualize spending across all AWS services in a selected date range
19+
- **4 Chart Types** — grouped bar, stacked bar, line chart, and donut chart
20+
- **Date Range Filter** — pick any custom date range with daily or monthly granularity
21+
- **Service Filter** — show or hide individual AWS services from the chart
22+
- **Summary Cards** — total cost, top service, average per period, cost trend vs. previous period
23+
- **Sortable Breakdown Table** — sort services by name, cost, or percentage share
24+
- **Export Reports** — download the current dashboard data as **CSV** or **XLSX**
25+
- **Demo Mode** — instantly explore with 6 months of realistic simulated AWS data
26+
- **Cognito Authentication** — zero long-lived keys; temporary STS credentials only
27+
- **5-Minute Auto-Logout** — session expires automatically; countdown shown in the header
28+
29+
## Authentication
30+
31+
### Security Model
32+
33+
The app follows AWS best practices for browser-based credential management:
34+
35+
| Old approach (removed) | New approach |
36+
|---|---|
37+
| Long-lived IAM Access Key + Secret stored in `localStorage` | Temporary STS credentials from Cognito — **in memory only** |
38+
| Credentials persist indefinitely across sessions | Session expires after **5 minutes**, then auto-logout |
39+
| Secret key visible in browser storage | No secrets ever touch storage |
40+
41+
### How It Works
42+
43+
1. User provides their **Cognito Identity Pool ID** (a non-secret public identifier).
44+
2. The app calls the **Cognito Identity API** (`GetId``GetCredentialsForIdentity`) to obtain temporary STS credentials.
45+
3. Credentials are held **in memory only** — never written to `localStorage`, `sessionStorage`, or any cache.
46+
4. A **5-minute countdown timer** is displayed in the header. When it reaches zero the session is cleared and the user is logged out automatically.
47+
5. On the next visit (or page refresh), the Identity Pool ID is pre-filled; one click reconnects and issues fresh credentials.
48+
49+
### Setting Up a Cognito Identity Pool
50+
51+
1. Open **AWS Console → Cognito → Identity Pools** and click *Create identity pool*.
52+
2. Enable **Guest access (unauthenticated identities)**.
53+
3. On the IAM role step, attach a role with the minimum policy:
54+
55+
```json
56+
{
57+
"Version": "2012-10-17",
58+
"Statement": [
59+
{
60+
"Effect": "Allow",
61+
"Action": ["ce:GetCostAndUsage"],
62+
"Resource": "*"
63+
}
64+
]
65+
}
66+
```
67+
68+
4. Copy the **Identity Pool ID** (format: `us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`).
69+
5. Paste it into the app and click **Connect via Cognito**.
70+
71+
> [!TIP]
72+
> The Identity Pool ID is a public identifier — it is safe to save in localStorage (which the app does for reconnect UX). Only the temporary STS credentials are sensitive, and those are never persisted.
73+
74+
## Architecture
75+
76+
```
77+
src/views/my-aws-dashboard/
78+
├── index.vue # Page entry — orchestrates auth vs. dashboard state
79+
├── meta.ts # Page metadata for the launcher
80+
├── types.ts # Shared TypeScript interfaces (CognitoConfig, CognitoSession, …)
81+
├── components/
82+
│ ├── AwsAuth.vue # Cognito Identity Pool credential form
83+
│ └── CostDashboard.vue # Full dashboard with charts, table, and export
84+
├── composables/
85+
│ ├── useCognitoAuth.ts # Cognito auth flow, session timer, and auto-logout
86+
│ └── useAwsCost.ts # Data fetching — real or demo fallback
87+
└── utils/
88+
├── cognitoClient.ts # Cognito GetId + GetCredentialsForIdentity API calls
89+
├── demoData.ts # Deterministic demo cost data generator
90+
├── chartUtils.ts # Chart.js config builders for each chart type
91+
├── exportUtils.ts # CSV and XLSX export logic
92+
└── sigv4.ts # AWS Signature Version 4 signing (Web Crypto API)
93+
```
94+
95+
## Getting Started
96+
97+
This app is part of the vibe.j2team.org project. To run it locally:
98+
99+
```sh
100+
pnpm install
101+
pnpm dev
102+
```
103+
104+
Visit `http://localhost:5173/my-aws-dashboard`.
105+
106+
### Demo Mode
107+
108+
On first visit the Cognito auth form is shown. Click **Try with Demo Data** to instantly load simulated data — no configuration needed. You can also click the **Demo** button in the page header at any time.
109+
110+
### Real AWS Data
111+
112+
To connect to your AWS account:
113+
114+
1. [Set up a Cognito Identity Pool](#setting-up-a-cognito-identity-pool) as described above.
115+
2. Click **Connect AWS** in the page header (or use the auth form on first visit).
116+
3. Enter the **Identity Pool ID** and **Region**, then click **Connect via Cognito**.
117+
118+
> [!WARNING]
119+
> Due to CORS restrictions on the AWS Cost Explorer API endpoint (`ce.us-east-1.amazonaws.com`), direct browser requests are blocked. The app will show an error and revert to demo data.
120+
121+
**Workarounds for real data:**
122+
123+
- Use a browser extension that disables CORS (development only)
124+
- Set up a local CORS proxy and point requests through it
125+
- Run the equivalent AWS CLI command and paste the output:
126+
127+
```sh
128+
aws ce get-cost-and-usage \
129+
--time-period Start=2025-11-01,End=2026-04-30 \
130+
--granularity MONTHLY \
131+
--group-by Type=DIMENSION,Key=SERVICE \
132+
--metrics BlendedCost
133+
```
134+
135+
## Security
136+
137+
- **No long-lived keys** — the app never asks for or stores IAM Access Keys or Secret Access Keys.
138+
- **In-memory credentials only** — STS credentials from Cognito are held in a Vue reactive ref; they disappear on page refresh or tab close.
139+
- **5-minute session timeout** — auto-logout is enforced client-side via `setTimeout`; a countdown is visible in the header.
140+
- **Public config only in storage**`localStorage` holds only the non-secret Identity Pool ID for reconnect UX.
141+
- **No third-party data transmission** — all API calls go directly to `*.amazonaws.com` and `cognito-identity.*.amazonaws.com`.
142+
- **Static deployment** — the app runs as a static site on Cloudflare Workers with no backend.
143+
144+
## Tech Stack
145+
146+
| Library | Purpose |
147+
|---------|---------|
148+
| Vue 3 + TypeScript | UI framework |
149+
| VueUse `useLocalStorage` | Non-secret config persistence (Identity Pool ID only) |
150+
| VueUse `useScriptTag` | Lazy-load Chart.js and SheetJS from CDN |
151+
| Amazon Cognito Identity | Federated identity and temporary STS credential issuance |
152+
| [Chart.js 4](https://www.chartjs.org/) | Interactive charts (loaded from CDN) |
153+
| [SheetJS (xlsx)](https://sheetjs.com/) | XLSX export (loaded from CDN on demand) |
154+
| Tailwind CSS v4 | Styling via project design system |
155+
156+
## Author
157+
158+
Built by **J2TEAM** as part of [vibe.j2team.org](https://vibe.j2team.org).

0 commit comments

Comments
 (0)