Core orchestration service for CloudScan platform - manages scan lifecycle, dispatches Kubernetes jobs, and coordinates all scanning activities
The cloudscan-orchestrator is the heart of the CloudScan platform. It:
- π Manages scan lifecycle (create, queue, execute, complete)
- π Dispatches Kubernetes Jobs for scanner runners
- ποΈ Persists scan metadata and findings in PostgreSQL
- π Runs background workers (sweeper, cleaner, notifier)
- π Handles multi-tenant data isolation
- π‘ Exposes gRPC and HTTP APIs
- π Collects and exposes Prometheus metrics
βββββββββββββββββββ
β API Gateway β
β (REST/gRPC) β
ββββββββββ¬βββββββββ
β CreateScan(artifact_id)
β GetScan(), ListScans()
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Orchestrator Service (This) β
β β
β ββββββββββββββ ββββββββββββ βββββββββββββββ β
β β gRPC Serverβ β Sweeper β β Cleaner β β
β β (Port 9999)β β (Worker) β β (Worker) β β
β βββββββ¬βββββββ ββββββ¬ββββββ ββββββββ¬βββββββ β
β β β β β
β βΌ βΌ βΌ β
β ββββββββββββββββββββββββββββββββββββββββββββ β
β β Job Dispatcher (K8s client-go) β β
β ββββββββββββββββ¬ββββββββββββββββββββββββββββ β
βββββββββββββββββββΌβββββββββββββββββββββββββββββββ
β
ββββββββββΌβββββββββ
β β β
β βΌ β
β ββββββββββββββββββββ
β β Storage Service β
β β (gRPC) β
β β GetArtifact() β
β ββββββββββββββββββββ
β β
β β presigned URL
β βΌ
β ββββββββββββββββββββ
β β S3/MinIO/GCS β
β β Object Storage β
β ββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β Kubernetes Cluster β
β β
β βββββββββββββββββ β
β β Runner Job β β
β β (Pod) β β
β β β β
β β - Downloads ββββΌβββ S3 (presigned URL)
β β source β β
β β - Runs β β
β β scanners β β
β β - Reports β β
β β findings ββββΌβββ Orchestrator.CreateFindings()
β βββββββββββββββββ β Orchestrator.UpdateScan()
βββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β PostgreSQL β
β - Scans β
β - Findings β
β - Projects β
βββββββββββββββββββββββ
cloudscan-orchestrator
βββ cmd/
β βββ main.go # Application entrypoint
βββ pkg/
β βββ controller/ # Main controller & component manager
β β βββ controller.go
β β βββ grpc.go # gRPC server component
β β βββ http.go # HTTP server component
β βββ dispatcher/ # Kubernetes job dispatcher
β β βββ dispatcher.go # Job creation & dispatch logic
β β βββ job_spec.go # K8s Job spec builder
β βββ handlers/
β β βββ grpc/ # gRPC service implementations
β β β βββ scans.go # Scan management
β β β βββ jobs.go # Job operations
β β β βββ health.go # Health checks
β β βββ http/ # HTTP handlers (optional REST API)
β β βββ scans.go
β β βββ middleware.go
β βββ persistence/ # Database layer
β β βββ scans.go # Scan CRUD operations
β β βββ findings.go # Findings storage
β β βββ projects.go # Project management
β β βββ users.go # User management
β βββ sweeper/ # Background worker: job status monitor
β β βββ sweeper.go
β βββ cleaner/ # Background worker: retention cleanup
β β βββ cleaner.go
β βββ authentication/ # Auth providers (JWT, mTLS)
β β βββ jwt.go
β β βββ mtls.go
β βββ metrics/ # Prometheus metrics
β β βββ metrics.go
β βββ config/ # Configuration management
β βββ config.go
βββ proto/ # Protocol buffers definitions
β βββ scans.proto # Scan service gRPC API
βββ migrations/ # Database migrations (SQL)
β βββ 001_initial_schema.up.sql
β βββ 001_initial_schema.down.sql
βββ Dockerfile
βββ go.mod
βββ go.sum
βββ README.md
- Go 1.23+
- PostgreSQL 15+
- Kubernetes cluster (for job dispatching)
- kubectl configured
# Clone the repository
cd cloudscan-orchestrator
# Install dependencies
go mod download
# Run PostgreSQL locally (via Docker)
docker run --name postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=cloudscan \
-p 5432:5432 \
-d postgres:15
# Run database migrations
# TODO: Add migration tool (e.g., golang-migrate)
# Run the service
go run cmd/main.go \
--db-host=localhost \
--db-port=5432 \
--db-name=cloudscan \
--db-user=postgres \
--db-password=postgres \
--grpc-port=9999 \
--http-port=8081Configuration can be provided via:
- Environment variables (recommended for production)
- Config file (
config.yaml) - Command-line flags
Environment Variables:
# Database
export DB_HOST=localhost
export DB_PORT=5432
export DB_NAME=cloudscan
export DB_USER=postgres
export DB_PASSWORD=postgres
# Kubernetes
export KUBE_NAMESPACE=cloudscan
export KUBE_IN_CLUSTER=false # Set to true when running in K8s
# Ports
export GRPC_PORT=9999
export HTTP_PORT=8081
# Observability
export PROMETHEUS_PORT=9090
export JAEGER_URL=http://jaeger:14268/api/traces
# Storage Service
export STORAGE_SERVICE_URL=cloudscan-storage:8082The orchestrator exposes gRPC services defined in proto/scans.proto:
Key RPCs:
CreateScan- Start a new security scanGetScan- Retrieve scan status and resultsListScans- List scans with filtersCancelScan- Cancel a running scanGetFindings- Get security findings for a scanUpdateScan- Update scan metadata
Example gRPC call:
grpcurl -plaintext \
-d '{"project_id": "proj-123", "scan_types": ["sast", "sca"]}' \
localhost:9999 \
cloudscan.ScanService.CreateScanIf enabled, provides RESTful endpoints:
POST /api/v1/scans # Create scan
GET /api/v1/scans/:id # Get scan details
GET /api/v1/scans # List scans
DELETE /api/v1/scans/:id # Cancel scan
GET /api/v1/scans/:id/findings # Get findings
Monitors Kubernetes Jobs and updates scan status:
- Polls K8s Job status every 30 seconds
- Updates scan state:
queuedβrunningβcompleted/failed - Handles job failures and retries
- Cleans up completed jobs after retention period
Enforces data retention policies:
- Deletes scans older than configured retention (default: 90 days)
- Removes associated findings and artifacts
- Runs daily at midnight
- Configurable retention per organization
Key tables:
organizations - Multi-tenant isolation
CREATE TABLE organizations (
id UUID PRIMARY KEY,
name TEXT NOT NULL,
slug TEXT UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);scans - Scan metadata (partitioned by date)
CREATE TABLE scans (
id UUID PRIMARY KEY,
organization_id UUID NOT NULL,
project_id UUID REFERENCES projects(id),
status TEXT NOT NULL, -- queued, running, completed, failed
scan_types TEXT[] NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
) PARTITION BY RANGE (created_at);findings - Security vulnerabilities
CREATE TABLE findings (
id UUID PRIMARY KEY,
scan_id UUID REFERENCES scans(id),
severity TEXT NOT NULL, -- critical, high, medium, low
title TEXT NOT NULL,
file_path TEXT,
line_number INT
);See migrations/ for full schema.
Supports multiple authentication methods:
-
JWT (recommended for UI/API access)
- Tokens issued by API gateway
- Validated on each request
-
mTLS (for service-to-service)
- Client certificates validated
- Used by scanner runners
-
Disabled (development only)
- No authentication
Prometheus metrics exposed on /metrics:
Key metrics:
cloudscan_scans_total{status="completed|failed"}- Total scanscloudscan_scan_duration_seconds- Scan duration histogramcloudscan_queue_depth- Number of queued scanscloudscan_findings_total{severity="critical|high|medium|low"}- Total findingscloudscan_k8s_jobs_active- Active Kubernetes jobs
# Run unit tests
go test ./pkg/...
# Run with coverage
go test -cover ./pkg/...
# Run integration tests (requires PostgreSQL)
go test -tags=integration ./pkg/...
# Run specific package tests
go test ./pkg/dispatcher/...# Build for linux/amd64
docker build -t cloudscan/orchestrator:latest .
# Multi-platform build
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t cloudscan/orchestrator:latest \
--push .docker run -p 9999:9999 -p 8081:8081 \
-e DB_HOST=postgres \
-e DB_PASSWORD=secret \
cloudscan/orchestrator:latestapiVersion: apps/v1
kind: Deployment
metadata:
name: cloudscan-orchestrator
spec:
replicas: 3
selector:
matchLabels:
app: cloudscan-orchestrator
template:
metadata:
labels:
app: cloudscan-orchestrator
spec:
serviceAccountName: cloudscan-orchestrator
containers:
- name: orchestrator
image: cloudscan/orchestrator:latest
ports:
- containerPort: 9999 # gRPC
- containerPort: 8081 # HTTP
- containerPort: 9090 # Metrics
env:
- name: DB_HOST
value: postgres
- name: KUBE_IN_CLUSTER
value: "true"
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 2000m
memory: 2GiService Account: The orchestrator needs permissions to create/manage Kubernetes Jobs.
See cloudscan-umbrella for complete Helm deployment.
- Fork the repository
- Create a feature branch
- Make changes with tests
- Submit a pull request
Code style:
- Follow Go conventions
- Run
gofmtandgolint - Add unit tests for new features
Apache 2.0 - See LICENSE