feat: billing IAM hardening — 11-billing-iam-hardening.sh, jason.vauger viewer, MASTERPLAN oppdatert

This commit is contained in:
chrischristiansen-glitch 2026-05-24 02:30:27 +02:00
parent aff36f2f35
commit 25eec703ce
3 changed files with 172 additions and 19 deletions

View File

@ -6,7 +6,7 @@
export PROJECT_ID="propane-will-491900-m5"
export REGION="us-central1"
export BILLING_ACCOUNT_ID="XXXXXX-XXXXXX-XXXXXX" # gcloud billing accounts list
export ALERT_EMAIL="your-email@example.com"
export ALERT_EMAIL="chris.christiansen@vauco.no"
# ── Service Account ────────────────────────────────────────────
export AGENT_SA="osvauco-agent-sa@${PROJECT_ID}.iam.gserviceaccount.com"
@ -43,22 +43,38 @@ export GITHUB_APP_INSTALLATION_ID="" # eks: 12345678
# ── Observability ────────────────────────────────────────────
# ALERT_EMAIL er allerede satt ovenfor
# ── Billing IAM Hardening (11-billing-iam-hardening.sh) ─────────────
# Kommaseparert liste — får roles/billing.viewer på billing-kontoen
# jason.vauger = agentens identitet (kan hente kostnadsdata autonomt)
# chris = eier med eksplisitt viewer i tillegg til admin
export BILLING_VIEWER_EMAILS="chris.christiansen@vauco.no,jason.vauger@vauco.no"
# Google Workspace / Cloud Identity domene:
# Sett kun hvis vauco.no er koblet som org i GCP — fjerner billing.creator fra domenet
# export ORG_DOMAIN="vauco.no"
#
# Fremtidig (Fase C): erstatt enkeltadresser med Google Group:
# export BILLING_VIEWER_EMAILS="billing@vauco.no"
# ── Webhook / Chat-notifikasjoner ────────────────────────────
# Lagres i Secret Manager, ikke her:
# gcloud secrets create webhook-url --data-file=<(echo -n "https://DIN-WEBHOOK-URL")
# Se: infrastructure/notifications/webhook-setup.md
# ── VPC / Security (valgfritt) ────────────────────────────────
export VPC_NETWORK="default"
# export CMEK_KEY_RING="agent-keyring" # kun ved CMEK
# export CMEK_KEY_NAME="agent-key" # kun ved CMEK
# export CMEK_KEY_RING="agent-keyring"
# export CMEK_KEY_NAME="agent-key"
# ── IAP / Domene (Fase B) ─────────────────────────────────────
# export IAP_DOMAIN="opax.vauco.no"
# export IAP_CLIENT_ID="" # fra GCP Console → IAP
# export IAP_CLIENT_SECRET="" # fra GCP Console → IAP
# export IAP_CLIENT_ID=""
# export IAP_CLIENT_SECRET=""
# ── Terraform / Kunde-onboarding (Fase C) ─────────────────────
# Brukes av vauco-bootstrap Terraform-modul ved onboarding av ny kunde
# export TF_VAR_customer_id="medioteq"
# export TF_VAR_customer_project_id=""
# export TF_VAR_customer_region="europe-north1"
# export TF_STATE_BUCKET="${PROJECT_ID}-tfstate" # GCS bucket for Terraform state
# export TF_STATE_BUCKET="${PROJECT_ID}-tfstate"
# ── LiteLLM proxy (valgfritt) ─────────────────────────────────
# export LITELLM_BASE_URL=""

View File

@ -1,7 +1,7 @@
# VAUCO MASTERPLAN — Chris Christiansen
**Sist oppdatert: 2026-05-23 CEST**
**Status: Repo ferdig — GCP gjenstår (A4A8 neste)**
**Sist oppdatert: 2026-05-24 CEST**
**Status: Repo ferdig — GCP gjenstår (A4A9 neste)**
---
@ -21,6 +21,22 @@ Du er første kunde. Når det virker for deg → selg det til andre.
---
## AGENT-IDENTITET
| Identitet | E-post | Rolle | Formål |
|---|---|---|---|
| Eier / admin | `chris.christiansen@vauco.no` | `billing.admin` + `billing.viewer` | Full kontroll |
| Agent (OPAX) | `jason.vauger@vauco.no` | `billing.viewer` | Hente og rapportere kostnadsdata autonomt |
| Fremtidig gruppe | `billing@vauco.no` | `billing.viewer` (Fase C) | Delt innboks for team og kunder |
**Agent-kapabiliteter med `billing.viewer`:**
- Svare på «Hva koster dette prosjektet denne måneden?»
- Sende ukentlig kostnadsrapport til chat-appen
- Reagere på Pub/Sub budget-alerts (via `10-cost-guard.sh`)
- **Ikke:** endre IAM, budsjetter eller koble prosjekter
---
## CLOUD SHELL QUICK-START (kopi-klipp)
> Bruk Cloud Shell: https://shell.cloud.google.com
@ -46,16 +62,17 @@ bash infrastructure/00-authcheck.sh
bash infrastructure/01-setupenv.sh
bash infrastructure/07-rag-setup.sh
# *** Kopier RAG_CORPUS_NAME fra output inn i .env ***
nano .env # Legg til: export RAG_CORPUS_NAME="..."
nano .env
source .env
bash infrastructure/08-memorybank-setup.sh
# *** Kopier MEMORY_ENGINE_NAME fra output inn i .env ***
nano .env # Legg til: export MEMORY_ENGINE_NAME="..."
nano .env
source .env
bash infrastructure/05-cloudrun-deploy.sh
bash infrastructure/04-observability-setup.sh
bash infrastructure/11-billing-iam-hardening.sh
# Om kvelden (OBLIGATORISK — unngå 24/7-fakturering):
bash infrastructure/03-teardown.sh
@ -77,6 +94,7 @@ bash infrastructure/03-teardown.sh
SUBAGENT_MODEL=gemini-2.0-flash
[ ] A2 — bash infrastructure/00-authcheck.sh
[ ] A3 — bash infrastructure/01-setupenv.sh
Oppretter: budsjetter ($75 dev + $500 prod), Pub/Sub topic
[ ] A4 — bash infrastructure/07-rag-setup.sh
OQ-02: Script faller automatisk tilbake til us-east1 om nødvendig
ACTION: Kopier RAG_CORPUS_NAME til .env
@ -86,6 +104,10 @@ bash infrastructure/03-teardown.sh
[ ] A6 — bash infrastructure/05-cloudrun-deploy.sh
[ ] A7 — bash infrastructure/04-observability-setup.sh
[ ] A8 — bash infrastructure/03-teardown.sh (kjør hver kveld)
[ ] A9 — bash infrastructure/11-billing-iam-hardening.sh
Gir billing.viewer til: chris.christiansen@vauco.no + jason.vauger@vauco.no
Løser GCP billing health-advarsel: "0 billing account viewers"
Fjerner billing.creator fra domenet (hvis ORG_DOMAIN er satt i .env)
```
---
@ -103,7 +125,11 @@ bash infrastructure/03-teardown.sh
Fyll inn GITHUB_APP_INSTALLATION_ID i .env
[ ] B3 — bash infrastructure/06-cicd-setup.sh
OQ-04: LØST — Cloud Build 2nd gen, ingen manuell OAuth i Console
Bruker: gcloud builds connections create github (programmatisk)
[ ] B4 — Legg til webhook URL i Secret Manager:
gcloud secrets create webhook-url --data-file=<(echo -n "https://DIN-WEBHOOK-URL")
Se: infrastructure/notifications/webhook-setup.md
[ ] B5 — bash infrastructure/10-cost-guard.sh
Aktiverer auto-teardown Cloud Function + chat-varsling ved budsjett-overskridelse
```
---
@ -119,7 +145,11 @@ bash infrastructure/03-teardown.sh
Terraform-variabler: customer_id, customer_project_id, customer_region
State-backend: GCS bucket (TF_STATE_BUCKET i .env)
[ ] C2 — Pakk `vauco-os` som kundeflate
[ ] C3 — Første kunde: Medioteq
[ ] C3 — Opprett billing@vauco.no som Google Group
Legg inn: chris.christiansen@vauco.no + jason.vauger@vauco.no
Oppdater .env: BILLING_VIEWER_EMAILS="billing@vauco.no"
Kjør på nytt: bash infrastructure/11-billing-iam-hardening.sh
[ ] C4 — Første kunde: Medioteq
Region: europe-north1, separat GCP-prosjekt
Kjør: terraform apply -var="customer_id=medioteq"
```
@ -131,15 +161,17 @@ bash infrastructure/03-teardown.sh
| Script | Rolle | Status |
|--------|-------|--------|
| `00-authcheck.sh` | Verifiser gcloud-innlogging | Klar |
| `01-setupenv.sh` | Aktiver APIs, SA, IAM, budsjett | Klar |
| `01-setupenv.sh` | Aktiver APIs, SA, IAM, budsjetter ($75+$500), Pub/Sub | Klar |
| `02-deploy.sh` | IAP-deploy på eget domene | Klar |
| `03-teardown.sh` | Riv ned Cloud Run | Klar |
| `04-observability-setup.sh` | Monitoring + alerting | Klar |
| `05-cloudrun-deploy.sh` | ADK-agent til Cloud Run | Klar |
| `06-cicd-setup.sh` | GitHub → Cloud Build **2nd gen** | **Oppdatert** |
| `06-cicd-setup.sh` | GitHub → Cloud Build **2nd gen** | Oppdatert |
| `07-rag-setup.sh` | RAG Engine corpus + fallback | Oppdatert |
| `08-memorybank-setup.sh` | Memory Bank + auto-install | Oppdatert |
| `09-cost-check.sh` | Kostnadsoversikt + Artifact Registry | Klar |
| `10-cost-guard.sh` | Cloud Function auto-teardown + webhook-alert | **Ny** |
| `11-billing-iam-hardening.sh` | Billing IAM: viewer-roller + fjern domain Creator | **Ny** |
---
@ -166,7 +198,6 @@ bash infrastructure/03-teardown.sh
| Medioteq-type (klinisk, compliance) | ~$220-350 |
Breakeven: 1 kunde til $300-500/mnd dekker alle kostnader.
Ikke bygg kost-analyse-system nå — spør agenten når GCP er oppe.
---
@ -182,13 +213,15 @@ Ikke bygg kost-analyse-system nå — spør agenten når GCP er oppe.
| OQ-06 | Memory Bank auto-discovery | Eksplisitt env var |
| OQ-07 | Monitoring email flag-format | Teste i dev |
| OQ-08 | VPC connector e2-micro regional | Default us-central1 |
| OQ-09 | GCP billing: 0 viewers | **LØST**`11-billing-iam-hardening.sh` |
| OQ-10 | GCP billing: Creator på domenet | **LØST** — fjernes når ORG_DOMAIN er satt |
---
## TERRAFORM-VEIKART (Fase C)
Terraform introduseres **ikke** for nåværende infra — gcloud-scripts er tilstrekkelig
når vi opererer med ett GCP-prosjekt. Terraform blir relevant ved kunde-onboarding:
Terraform introduseres **ikke** for nåværende infra — gcloud-scripts er tilstrekkelig.
Terraform blir relevant ved kunde-onboarding:
| Når | Hva |
|---|---|
@ -198,7 +231,7 @@ når vi opererer med ett GCP-prosjekt. Terraform blir relevant ved kunde-onboard
| State-backend | GCS bucket (`TF_STATE_BUCKET`) — én bucket, én state-fil per kunde |
| Fase D | Terraform Cloud for sentralisert state og CI/CD på tvers av kunder |
Terraform-ressurser som er aktuelle:
Terraform-ressurser:
- `google_cloudbuildv2_connection` — programmatisk GitHub-kobling per kunde
- `google_cloudbuildv2_repository` — repo-link
- `google_cloudbuild_trigger` — push-til-main trigger

View File

@ -0,0 +1,104 @@
#!/usr/bin/env bash
# 11-billing-iam-hardening.sh — GCP Billing Account Health fixes
#
# Løser to offisielle GCP-advarsler:
# 1. "0 billing account viewers" — gir billing.viewer til spesifiserte brukere
# 2. "Billing Account Creator rolle på for domenet" — fjerner domain-wide Creator
#
# Agent-identitet: jason.vauger@vauco.no får billing.viewer
# slik at agenten kan hente og rapportere kostnadsdata autonomt.
#
# Krav: du må være Billing Account Administrator for å kjøre dette.
# Source .env før kjøring: source .env
set -euo pipefail
: "${BILLING_ACCOUNT_ID:?Set BILLING_ACCOUNT_ID i .env}"
: "${ALERT_EMAIL:?Set ALERT_EMAIL i .env}"
# Brukere som får billing.viewer — kan overstyres i .env
BILLING_VIEWER_EMAILS="${BILLING_VIEWER_EMAILS:-chris.christiansen@vauco.no,jason.vauger@vauco.no}"
# Google Workspace / Cloud Identity domene (kun nødvendig ved org-oppsett)
ORG_DOMAIN="${ORG_DOMAIN:-}"
echo "=== 11: Billing IAM Hardening ==="
echo " Billing Account: ${BILLING_ACCOUNT_ID}"
bash "$(dirname "$0")/00-authcheck.sh"
# ----------------------------------------------------------------
# FIX 1: billing.viewer til agent-identitet og eier
# ----------------------------------------------------------------
echo ""
echo "--- Fix 1: Billing Account Viewer ---"
echo " Gir lesetilgang til: ${BILLING_VIEWER_EMAILS}"
echo " Formål: agenten (jason.vauger) kan hente kostnadsdata autonomt;"
echo " chris får eksplisitt viewer i tillegg til admin."
IFS=',' read -ra VIEWER_LIST <<< "${BILLING_VIEWER_EMAILS}"
for EMAIL in "${VIEWER_LIST[@]}"; do
EMAIL=$(echo "${EMAIL}" | xargs)
[[ -z "${EMAIL}" ]] && continue
if [[ "${EMAIL}" == *".gserviceaccount.com" ]]; then
MEMBER="serviceAccount:${EMAIL}"
else
MEMBER="user:${EMAIL}"
fi
gcloud billing accounts add-iam-policy-binding "${BILLING_ACCOUNT_ID}" \
--member="${MEMBER}" \
--role="roles/billing.viewer" --quiet
echo "✓ billing.viewer gitt til: ${EMAIL}"
done
# ----------------------------------------------------------------
# FIX 2: Fjern billing.creator fra domenet
# ----------------------------------------------------------------
echo ""
echo "--- Fix 2: Fjern Billing Account Creator fra domenet ---"
if [[ -z "${ORG_DOMAIN}" ]]; then
echo "⚠️ ORG_DOMAIN er ikke satt — hopper over."
echo " Sett i .env: export ORG_DOMAIN=\"vauco.no\" og kjør på nytt."
echo " (Kun nødvendig om vauco.no er koblet som Google Workspace-org i GCP)"
else
DOMAIN_MEMBER="domain:${ORG_DOMAIN}"
EXISTING=$(gcloud billing accounts get-iam-policy "${BILLING_ACCOUNT_ID}" \
--format=json 2>/dev/null \
| python3 -c "
import sys, json
policy = json.load(sys.stdin)
for b in policy.get('bindings', []):
if b.get('role') == 'roles/billing.creator' and '${DOMAIN_MEMBER}' in b.get('members', []):
print('found')
break
" 2>/dev/null || echo "")
if [[ "${EXISTING}" == "found" ]]; then
gcloud billing accounts remove-iam-policy-binding "${BILLING_ACCOUNT_ID}" \
--member="${DOMAIN_MEMBER}" \
--role="roles/billing.creator" --quiet
echo "✓ roles/billing.creator fjernet fra domain:${ORG_DOMAIN}"
else
echo "✓ roles/billing.creator var ikke tildelt domain:${ORG_DOMAIN} — ingen endring"
fi
fi
# ----------------------------------------------------------------
# Vis nåværende billing IAM-policy
# ----------------------------------------------------------------
echo ""
echo "--- Nåværende Billing Account IAM (etter endringer) ---"
gcloud billing accounts get-iam-policy "${BILLING_ACCOUNT_ID}" \
--format="table(bindings.role,bindings.members)" 2>/dev/null || true
echo ""
echo "=== 11: Billing IAM Hardening COMPLETE ==="
echo " Verifiser i GCP Console:"
echo " https://console.cloud.google.com/billing/${BILLING_ACCOUNT_ID}/manage"
echo ""
echo " Fremtidig: opprett billing@vauco.no som Google Group,"
echo " legg chris + jason inn i gruppa, og erstatt enkeltadressene med:"
echo " export BILLING_VIEWER_EMAILS=\"billing@vauco.no\""