Sign inSign up

syalioune/gcp-finops-sentinel

By syalioune

Updated 10 months ago

Automated GCP cost control through policy enforcement.

Image
Integration & delivery
Monitoring & observability
0

3.4K

syalioune/gcp-finops-sentinel repository overview

GCP FinOps Sentinel

Automated GCP cost control through policy enforcement. Event-driven Cloud Run service that automatically enforces organization policies when budget thresholds are exceeded.

Quick Start

# Pull the latest image
docker pull syalioune/gcp-finops-sentinel:latest

# Run with basic configuration
docker run -p 8080:8080 \
  -e ORGANIZATION_ID=123456789012 \
  -e RULES_CONFIG='{"rules":[{"name":"budget_alert","conditions":{"threshold_percent":{"operator":">=","value":100}},"actions":[{"type":"log_only","message":"Budget exceeded"}]}]}' \
  -e DRY_RUN=true \
  syalioune/gcp-finops-sentinel:latest

What It Does

  • 🚨 Automatically responds to GCP Budget Alerts via Pub/Sub
  • 🔒 Enforces organization policies (restrict services, apply constraints)
  • 🎯 Targets projects, folders, or organizations
  • 📧 Sends email notifications via SMTP
  • 📡 Publishes audit events to Pub/Sub
  • 🏷️ Discovers projects dynamically by labels

Container Tags

TagDescriptionUse Case
latestLatest stable releaseProduction
1.0.0Specific versionVersion pinning
developDevelopment buildTesting

Environment Variables

VariableRequiredDescription
ORGANIZATION_ID✅ YesGCP Organization ID
RULES_CONFIG⚠️ Yes*Rules as JSON/YAML string
RULES_CONFIG_PATH⚠️ Yes*Path to rules file (default: /workspace/rules.json)
DRY_RUN❌ NoSet to true for testing without enforcement
ACTION_EVENT_TOPIC❌ NoPub/Sub topic for action events
LOG_LEVEL❌ NoDEBUG, INFO, WARNING, ERROR (default: INFO)

* Either RULES_CONFIG or RULES_CONFIG_PATH must be provided.

SMTP Configuration (Optional)
VariableDefaultDescription
SMTP_HOST-SMTP server hostname
SMTP_PORT587SMTP server port
SMTP_USER-SMTP username
SMTP_PASSWORD-SMTP password
SMTP_USE_TLStrueEnable STARTTLS
SMTP_FROM_EMAIL$SMTP_USERSender email address

Rules Configuration

Rules define when and what actions to take based on budget thresholds. Both JSON and YAML formats are supported.

Supported Threshold Operators
OperatorDescriptionExample
>=Greater than or equalTrigger at 100% or higher
>Greater thanTrigger above 100%
==EqualsTrigger exactly at 100%
<Less thanTrigger below 100%
<=Less than or equalTrigger at 100% or lower
minMinimum (inclusive)Range: 80-89.99% (use with max)
maxMaximum (inclusive)Range: 80-89.99% (use with min)
Simple Rule Example (JSON)
{
  "rules": [
    {
      "name": "critical_budget_breach",
      "description": "Restrict compute when budget exceeds 100%",
      "conditions": {
        "threshold_percent": {
          "operator": ">=",
          "value": 100
        }
      },
      "actions": [
        {
          "type": "restrict_services",
          "target_projects": ["prod-web-1", "prod-api-1"],
          "services": ["compute.googleapis.com"]
        },
        {
          "type": "send_mail",
          "to_emails": ["[email protected]"],
          "template": "budget_alert",
          "custom_message": "Critical budget breach detected!"
        }
      ]
    }
  ]
}
Advanced Rule Example (YAML)
rules:
  - name: tiered_response
    description: Graduated response based on budget thresholds
    conditions:
      # Range-based threshold: 80-89.99%
      threshold_percent:
        - operator: min
          value: 80
        - operator: max
          value: 89.99
      billing_account_filter: "012345-6789AB-CDEF01"
    actions:
      # Target projects by labels (dynamic discovery)
      - type: restrict_services
        target_labels:
          env: prod
          cost-center: engineering
        services:
          - compute.googleapis.com
          - container.googleapis.com

      # Apply constraint at folder level
      - type: apply_constraint
        target_folders:
          - "123456789012"
        constraint: compute.vmExternalIpAccess
        enforce: true
Action Types
ActionDescriptionParameters
restrict_servicesDeny specific GCP servicesservices, targeting
apply_constraintApply org policy constraintconstraint, enforce, targeting
send_mailSend HTML email notificationto_emails, template
log_onlyLog without taking actionmessage, targeting
Targeting Methods

All actions (except send_mail) require at least one:

  • target_projects: List of project IDs
  • target_folders: List of folder IDs
  • target_organization: Organization ID
  • target_labels: Label key-value pairs (dynamic discovery)

Testing Locally

Clone the repository and use the provided Docker Compose environment with Pub/Sub emulator and MailHog:

# Clone repository
git clone https://github.com/syalioune/gcp-finops-sentinel.git
cd gcp-finops-sentinel

# Start complete local environment
docker compose up -d

# Publish test budget alert (120% threshold)
export PUBSUB_EMULATOR_HOST=localhost:8681
python scripts/publish-budget-alert-event.py --cost-amount 1200 --budget-amount 1000

# View logs
docker compose logs -f budget-function

# View email notifications at http://localhost:8025

Services:

Option 2: Manual Docker Setup
# Start Pub/Sub emulator
docker run -d --name pubsub-emulator \
  -p 8681:8681 \
  gcr.io/google.com/cloudsdktool/google-cloud-cli:emulators \
  gcloud beta emulators pubsub start --host-port=0.0.0.0:8681

# Start MailHog for email testing
docker run -d --name mailhog \
  -p 8025:8025 -p 1025:1025 \
  mailhog/mailhog

# Run FinOps Sentinel
docker run -d --name finops-sentinel \
  -p 8080:8080 \
  -e ORGANIZATION_ID=123456789012 \
  -e DRY_RUN=true \
  -e PUBSUB_EMULATOR_HOST=pubsub-emulator:8681 \
  -e SMTP_HOST=mailhog \
  -e SMTP_PORT=1025 \
  --link pubsub-emulator \
  --link mailhog \
  syalioune/gcp-finops-sentinel:latest

# View emails at http://localhost:8025

Deployment

Deploy to Cloud Run
# Deploy with gcloud
gcloud run deploy gcp-finops-sentinel \
  --image=syalioune/gcp-finops-sentinel:latest \
  --platform=managed \
  --region=us-central1 \
  --set-env-vars="ORGANIZATION_ID=123456789012" \
  --set-secrets="RULES_CONFIG=finops-rules:latest" \
  --no-allow-unauthenticated

# Create Eventarc trigger for Pub/Sub
gcloud eventarc triggers create budget-alerts-trigger \
  --destination-run-service=gcp-finops-sentinel \
  --destination-run-region=us-central1 \
  --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
  --transport-topic=projects/YOUR_PROJECT/topics/budget-alerts
Deploy with Docker Compose
version: '3.8'
services:
  finops-sentinel:
    image: syalioune/gcp-finops-sentinel:latest
    ports:
      - "8080:8080"
    environment:
      - ORGANIZATION_ID=123456789012
      - DRY_RUN=true
      - LOG_LEVEL=DEBUG
    volumes:
      - ./rules.json:/workspace/rules.json:ro
Deploy with OpenTofu/Terraform
resource "google_cloud_run_v2_service" "finops_sentinel" {
  name     = "gcp-finops-sentinel"
  location = "us-central1"

  template {
    service_account = google_service_account.finops_sentinel.email

    containers {
      image = "syalioune/gcp-finops-sentinel:latest"

      env {
        name  = "ORGANIZATION_ID"
        value = var.organization_id
      }

      env {
        name = "RULES_CONFIG"
        value_source {
          secret_key_ref {
            secret  = google_secret_manager_secret.rules.secret_id
            version = "latest"
          }
        }
      }

      resources {
        limits = {
          cpu    = "1"
          memory = "512Mi"
        }
      }
    }
  }
}

IAM Requirements

The service account running the container needs:

RoleScopePurpose
roles/browserOrganizationProject discovery by labels
roles/orgpolicy.policyAdminOrganizationPolicy enforcement
roles/pubsub.publisherTopicAction event publishing (optional)

Health Check

# The container exposes port 8080
curl http://localhost:8080/

Logging

Container outputs structured JSON logs:

{
  "severity": "INFO",
  "message": "Processing budget alert",
  "budget_id": "budget-123",
  "threshold_percent": 120.5,
  "matched_rules": 2
}

Documentation

Support

License

Apache License 2.0 - See LICENSE


Built for cloud cost optimization | Python 3.13 | Cloud Run | OpenTofu

Tag summary

Content type

Image

Digest

sha256:876cdae52

Size

64.9 MB

Last updated

10 months ago

docker pull syalioune/gcp-finops-sentinel