我打造了 Goliat:開源、自行託管的 Azure 資產盤點與 FinOps 儀錶板
I built Goliat: an open-source, self-hosted Azure inventory and FinOps dashboard
作者開發並以 MIT 授權開源 Goliat,一款可自行託管的 Azure 資產盤點與 FinOps 儀錶板。它涵蓋 12 個服務組別的 73 個檢視,可分析 Azure Cost Management 的實際及攤銷成本,並以唯讀權限在自己的 Azure 租戶運行。
If you manage more than a couple of Azure subscriptions, you know the drill: the portal is great for one resource at a time, but answering simple questions across everything gets painful. Which VMs are running where? Which resources have no Owner tag? What did we actually spend on AKS last month?
I wanted one place to answer those questions, running in my own tenant with read-only access. So I built Goliat Cloud Inventory and released it as open source under the MIT license.
- 🌐 Website and interactive demo: https://danieljsaldana.github.io/goliat-cloud-inventory/
- 💻 Code: https://github.com/danieljsaldana/goliat-cloud-inventory
- 📚 Wiki (English and Spanish): https://github.com/danieljsaldana/goliat-cloud-inventory/wiki
What it does
- Inventory: 73 views in 12 service groups: compute, containers, web and APIs, networking, storage, databases, security, integration, data and AI, observability, and tags. Each category has an overview with KPIs and charts. Every table supports subscription filters, search, column filters, grouping, sorting, pagination and export.
-
Global search (
Ctrl+K/⌘K) over resources, IDs, tags, subscriptions and views, with no extra cloud calls. - FinOps: actual and amortized costs from Azure Cost Management, with daily trends and breakdowns by service, subscription, resource group and resource. Missing data or permissions are shown explicitly, never as zero cost, and currencies are never mixed.
- Administration: Function, PostgreSQL and Blob Storage health and metrics, the collector schedule, monitored tag keys, and a warning when the published inventory differs from the imported one.
- Roles: sign-in with Microsoft Entra ID, plus an optional Members view to grant or revoke the Goliat admin role, with an audit trail.
- Bilingual UI in English and Spanish.
How it works
Azure Function (timer / queue / authenticated HTTP)
│ Resource Graph + ARM, managed identity (Reader)
▼
Blob Storage ── azure/latest.json (versioned contract, ETag)
│ read-only identity
▼
Next.js backend ── normaliser → PostgreSQL snapshot (one transaction)
│
▼
Dashboard (React, shadcn/ui, Recharts)
│
└── FinOps → Azure Cost Management
Collection and presentation are fully decoupled. They communicate through a single versioned JSON document in Blob Storage.
- An Azure Function (Flex Consumption) runs on a timer or on demand. It queries Azure Resource Graph, fills in the gaps from ARM, validates the whole document and publishes it with an ETag condition. If any query fails, nothing is published.
- The Next.js backend downloads the blob, validates the contract and imports all 73 views into PostgreSQL in a single transaction. A failed import keeps the previous snapshot, and the same ETag is never imported twice.
- The Refresh button asks the Function for a new generation with an Entra token, waits for it, imports it and reloads the UI. A PostgreSQL advisory lock allows only one manual refresh at a time across all users and replicas.
Security by design
This was the part I cared about most, since an inventory tool sees everything:
- Managed identities everywhere. There are no secrets in the code, and credentials never reach the browser.
- Least privilege. The collector only has Reader. The web gets blob read access, Cost Management Reader, and two small custom roles for metrics and Function management.
- Configuration only. The collector never reads blob contents, database data, Key Vault secrets, account keys or connection strings.
- Fail closed. If the auth configuration is invalid, access is blocked; Goliat never falls back to public mode. Roles are re-checked on the server on every request.
- Careful logging. Request bodies, cookies, tokens, query strings and SQL are never logged.
Deploying it
Everything lives in one resource group, created with Bicep and a PowerShell wrapper:
.\goliat.ps1 init
.\goliat.ps1 plan
.\goliat.ps1 deploy -GrantReader -RunAfterDeploy
By default this creates App Service F1, PostgreSQL Flexible Server B1ms, a Flex Consumption Function and a Storage account. To be clear: it isn't free, because PostgreSQL doesn't scale to zero. There are stop, start and destroy-plan commands to keep costs under control.
Prefer containers? The Dockerfile has runner, collector and migrator targets.
To try it locally with fake data, you only need Node.js and PostgreSQL:
npm ci
cp .env.example .env # demo login + local PostgreSQL
npm run db:init
npm run db:seed # 5 subscriptions, 214 fictional resources
npm run dev
Stack
Next.js 16 · React · shadcn/ui · Tailwind CSS 4 · Recharts · Auth.js · PostgreSQL · Azure Functions (Node.js) · Bicep · PowerShell · Playwright · GitHub Actions
The project has unit tests, PostgreSQL integration tests and Playwright browser tests on desktop and mobile. They run on every push and need no cloud credentials.
Try it
You don't need an Azure account to look around. The interactive demo runs entirely in your browser with fictional data, including the inventory, FinOps, user management and admin views.
If you try it, I'd love to hear what you think. Feedback, issues and stars are all very welcome. ⭐
來源:DEV Community · dev.to