Skip to content

Latest commit

 

History

History
726 lines (566 loc) · 18.7 KB

API.md

File metadata and controls

726 lines (566 loc) · 18.7 KB

API Reference

Complete reference for all REST APIs exposed by the SCC Orchestration System.

The system exposes two API surfaces:

Service Default Port Protocol Description
Governance API 3000 HTTP/JSON Policy evaluation, migration registry, audit, SCC version tracking
Admission Webhook 8443 HTTPS/JSON Pod interception (K8s AdmissionReview) and per-pod mutation log

Table of Contents


Authentication & Authorization

The Governance API uses header-based RBAC (role-based access control). In production, an upstream API broker proxy or service mesh sets these headers after authenticating the caller.

Header Description Example
X-User-Role Caller's role. Controls endpoint access. admin, operator, auditor, viewer
X-Authenticated-User Authenticated username (for audit logging) john.doe@example.com

Role permissions:

Role /validate /admission/check /audit Other endpoints
admin ✅ ✅ ✅ ✅
operator ✅ ✅ ❌ ✅
auditor ❌ ✅ ✅ ✅
viewer ❌ ✅ ❌ ✅

Note: RBAC enforcement is controlled by the ENFORCE_RBAC=true environment variable. When not set, all roles are allowed (development mode).


Governance API

Base URL: http://<governance-api-host>:3000

POST /api/v1/validate

Validate a migration plan against all governance policy rules. Called by the SCC Migration Controller during the Validating phase.

Authorization: admin, operator

Request Body:

{
  "planName": "migrate-anyuid-to-restricted",
  "namespace": "app-team-alpha",
  "sourceSCC": "anyuid",
  "targetSCC": "restricted",
  "namespaces": ["app-team-alpha", "app-team-beta"]
}
Field Type Required Description
planName string No Name of the SCCMigrationPlan CR
namespace string No Namespace of the CR
sourceSCC string Yes Current SCC policy (e.g. anyuid)
targetSCC string Yes Desired SCC policy (e.g. restricted)
namespaces string[] Yes Namespaces affected by the migration

Response — 200 OK:

{
  "approved": true,
  "violations": [],
  "riskLevel": "low",
  "recommendations": [
    "[rule-001] Transition \"anyuid→restricted\" is explicitly approved by \"Allow privilege reduction\""
  ]
}
Field Type Description
approved boolean true if the plan passes all governance rules
violations string[] List of rule violations (empty when approved)
riskLevel string low, medium, or high
recommendations string[] Optional suggestions for the operator

Response — 400 Bad Request:

{
  "approved": false,
  "violations": ["Missing required fields: sourceSCC, targetSCC, namespaces"]
}

POST /api/v1/admission/check

Real-time admission check for individual pod creation. Called by the Admission Webhook for every intercepted pod.

Authorization: All roles

Request Body:

{
  "podName": "my-app-7d4b8c6f9-x2k5l",
  "namespace": "app-team-alpha",
  "currentSCC": "anyuid",
  "requestedSCC": "anyuid",
  "labels": {
    "app": "my-app",
    "version": "v2"
  },
  "serviceAccount": "my-app-sa",
  "deploymentPhase": "stable",
  "telemetrySignals": {
    "scc.poc/error-rate": "low",
    "scc.poc/cpu-usage": "normal"
  }
}
Field Type Required Description
podName string No Name of the pod being admitted
namespace string No Pod's namespace
currentSCC string No SCC currently assigned to the pod
requestedSCC string No SCC requested via annotations
labels object No Pod labels for selector matching
serviceAccount string No Pod's service account name
deploymentPhase string No Inferred phase: canary, stable, etc.
telemetrySignals object No Runtime telemetry hints from pod annotations

Response — 200 OK (mutation approved):

{
  "allow": true,
  "mutateSCC": "restricted",
  "reason": "Active migration \"migrate-anyuid-to-restricted\" in progress"
}

Response — 200 OK (no mutation needed):

{
  "allow": true,
  "mutateSCC": "",
  "reason": "No active migration for this namespace/SCC combination"
}
Field Type Description
allow boolean Always true (fail-open design)
mutateSCC string Target SCC to mutate to, or empty string if no mutation
reason string Human-readable explanation of the decision

Context-aware skip conditions:

  • deploymentPhase: "canary" → skips mutation for safety
  • telemetrySignals["scc.poc/error-rate"]: "high" → defers mutation

GET /api/v1/policies

List all governance policy rules.

Authorization: All roles

Response — 200 OK:

[
  {
    "id": "rule-001",
    "name": "Allow privilege reduction",
    "description": "Allows migration from more privileged to less privileged SCCs",
    "enabled": true,
    "allowedTransitions": [
      "privileged→anyuid",
      "privileged→restricted",
      "anyuid→restricted",
      "anyuid→nonroot",
      "nonroot→restricted"
    ],
    "blockedNamespaces": []
  }
]

GET /api/v1/migrations/active

List all currently active migrations.

Authorization: All roles

Response — 200 OK:

[
  {
    "planName": "migrate-anyuid-to-restricted",
    "namespace": "app-team-alpha",
    "sourceSCC": "anyuid",
    "targetSCC": "restricted",
    "namespaces": ["app-team-alpha"],
    "phase": "Migrating",
    "updatedAt": "2026-03-12T10:30:00.000Z"
  }
]

POST /api/v1/migrations/active

Register or update an active migration. Called by the controller when a migration enters the Migrating or Mirroring phase.

Authorization: All roles

Request Body:

{
  "planName": "migrate-anyuid-to-restricted",
  "namespace": "app-team-alpha",
  "sourceSCC": "anyuid",
  "targetSCC": "restricted",
  "namespaces": ["app-team-alpha"],
  "phase": "Migrating"
}
Field Type Required Description
planName string Yes Name of the migration plan
namespace string No Namespace of the CR
sourceSCC string No Source SCC being migrated from
targetSCC string No Target SCC being migrated to
namespaces string[] No Namespaces affected
phase string No Current phase (default: Migrating)

Response — 200 OK:

{
  "status": "registered",
  "key": "app-team-alpha/migrate-anyuid-to-restricted"
}

Side effect: When a new migration is registered, SCC version activated events are recorded in the SCC Version Registry for both source and target SCCs.


DELETE /api/v1/migrations/active/:namespace/:name

Remove an active migration. Called when a migration completes, fails, or is rolled back.

Authorization: All roles

Path Parameters:

Parameter Description
namespace Namespace of the migration plan
name Name of the migration plan

Response — 200 OK:

{
  "status": "removed",
  "key": "app-team-alpha/migrate-anyuid-to-restricted"
}

Response — 404 Not Found:

{
  "error": "Migration not found",
  "key": "app-team-alpha/migrate-anyuid-to-restricted"
}

Side effect: Records SCC version deactivated event for the source SCC.


GET /api/v1/scc-versions

Query the SCC Version Registry — a complete lifecycle history of SCC version activations and deactivations across all migrations.

Authorization: All roles

Query Parameters:

Parameter Type Default Description
version string — Filter by SCC version name (e.g. restricted)
action string — Filter by lifecycle action: activated or deactivated
limit integer 100 Maximum entries to return

Example: GET /api/v1/scc-versions?version=restricted&action=activated&limit=50

Response — 200 OK:

{
  "total": 2,
  "activeVersions": ["anyuid", "restricted"],
  "entries": [
    {
      "timestamp": "2026-03-12T10:30:00.000Z",
      "version": "restricted",
      "role": "target",
      "action": "activated",
      "planName": "migrate-anyuid-to-restricted",
      "namespace": "app-team-alpha"
    }
  ]
}
Field Type Description
total integer Number of entries returned
activeVersions string[] SCC versions currently active (activated but not yet deactivated)
entries object[] Lifecycle event records

POST /api/v1/pod-migrations

Record a per-pod SCC migration event. Called by the webhook to push individual pod mutation decisions for centralised tracking.

Authorization: All roles

Request Body:

{
  "podName": "my-app-7d4b8c6f9-x2k5l",
  "namespace": "app-team-alpha",
  "fromSCC": "anyuid",
  "toSCC": "restricted",
  "serviceAccount": "my-app-sa",
  "deploymentPhase": "stable",
  "status": "Mutated",
  "reason": "Active migration in progress"
}
Field Type Required Description
podName string Yes Name of the pod
namespace string Yes Pod's namespace
fromSCC string No Source SCC
toSCC string No Target SCC
serviceAccount string No Pod's service account (default: default)
deploymentPhase string No Deployment phase (default: stable)
status string No Mutated, Skipped, or Failed
reason string No Human-readable reason

Response — 200 OK:

{
  "status": "recorded",
  "entry": {
    "timestamp": "2026-03-12T10:35:00.000Z",
    "podName": "my-app-7d4b8c6f9-x2k5l",
    "namespace": "app-team-alpha",
    "fromSCC": "anyuid",
    "toSCC": "restricted",
    "serviceAccount": "my-app-sa",
    "deploymentPhase": "stable",
    "status": "Mutated",
    "reason": "Active migration in progress"
  }
}

GET /api/v1/pod-migrations

Query per-pod SCC migration records with filtering support.

Authorization: All roles

Query Parameters:

Parameter Type Default Description
namespace string — Filter by namespace
status string — Filter by status: Mutated, Skipped, Failed
fromSCC string — Filter by source SCC
toSCC string — Filter by target SCC
limit integer 100 Maximum entries to return

Example: GET /api/v1/pod-migrations?namespace=app-team-alpha&status=Mutated&limit=50

Response — 200 OK:

{
  "total": 3,
  "summary": {
    "totalRecords": 15,
    "mutated": 10,
    "skipped": 4,
    "failed": 1
  },
  "entries": [
    {
      "timestamp": "2026-03-12T10:35:00.000Z",
      "podName": "my-app-7d4b8c6f9-x2k5l",
      "namespace": "app-team-alpha",
      "fromSCC": "anyuid",
      "toSCC": "restricted",
      "serviceAccount": "my-app-sa",
      "deploymentPhase": "stable",
      "status": "Mutated",
      "reason": "Active migration in progress"
    }
  ]
}

GET /api/v1/audit

Retrieve audit log entries. Every governance API operation is recorded with timestamp, actor, role, action, and result.

Authorization: admin, auditor

Query Parameters:

Parameter Type Default Description
action string — Filter by action type (e.g. validate, admission-check, migration-register)
limit integer 100 Maximum entries to return

Example: GET /api/v1/audit?action=validate&limit=50

Response — 200 OK:

{
  "total": 2,
  "entries": [
    {
      "timestamp": "2026-03-12T10:30:00.000Z",
      "action": "validate",
      "actor": "controller@scc-poc.svc",
      "role": "operator",
      "sourceIP": "10.0.0.15",
      "userAgent": "scc-controller/1.0",
      "details": {
        "planName": "migrate-anyuid-to-restricted",
        "sourceSCC": "anyuid",
        "targetSCC": "restricted",
        "namespaces": ["app-team-alpha"]
      },
      "result": "approved"
    }
  ]
}

Audit action types:

Action Triggered by
validate Plan validation request
admission-check Pod admission check
migration-register Active migration registered
migration-remove Active migration removed
pod-migration Per-pod mutation recorded
audit-read Audit log queried
rbac-denied RBAC access denied

GET /healthz

Health check endpoint.

Authorization: None

Response — 200 OK:

{
  "status": "healthy",
  "timestamp": "2026-03-12T10:30:00.000Z",
  "policyCount": 3,
  "activeMigrations": 1,
  "auditLogSize": 42,
  "sccVersionRegistrySize": 4,
  "podMigrationLogSize": 15
}

Admission Webhook

Base URL: https://<webhook-host>:8443

The webhook communicates with Kubernetes via the standard AdmissionReview protocol. It also exposes a per-pod mutation log query endpoint.

POST /mutate-pods

Kubernetes Mutating Admission Webhook endpoint. Intercepts pod CREATE operations and optionally mutates the SCC annotation and security context.

Note: This endpoint is called by the Kubernetes API server, not directly by users. It is configured via a MutatingWebhookConfiguration resource.

Request: Standard Kubernetes AdmissionReview (API version admission.k8s.io/v1)

Response: AdmissionReview with an AdmissionResponse containing:

  • allowed: true (always — fail-open design)
  • Optional JSON Patch (RFC 6902) that:
    • Sets openshift.io/scc annotation to the target SCC
    • Reconciles pod security context (privilege escalation, capabilities, SELinux, runAsNonRoot)
    • Reconciles container-level security contexts for all containers and init containers

Fail-open guarantee: The webhook never blocks pod creation. On any error (governance API unreachable, deserialization failure, patch build error), the pod is admitted unchanged.


GET /api/v1/pod-mutations

Query the webhook's local per-pod mutation log. Returns recent SCC mutation decisions with filtering.

Query Parameters:

Parameter Type Default Description
namespace string — Filter by namespace
status string — Filter by status: Mutated, Skipped, Failed
limit integer 100 Maximum entries to return

Example: GET /api/v1/pod-mutations?namespace=app-team-alpha&status=Mutated&limit=50

Response — 200 OK:

{
  "total": 5,
  "entries": [
    {
      "timestamp": "2026-03-12T10:35:00Z",
      "podName": "my-app-7d4b8c6f9-x2k5l",
      "namespace": "app-team-alpha",
      "fromSCC": "anyuid",
      "toSCC": "restricted",
      "serviceAccount": "my-app-sa",
      "deploymentPhase": "stable",
      "status": "Mutated",
      "reason": "Active migration in progress",
      "telemetrySignals": {
        "scc.poc/error-rate": "low"
      }
    }
  ],
  "summary": {
    "totalRecords": 20,
    "mutated": 15,
    "skipped": 4,
    "failed": 1
  }
}

Error Handling

All endpoints return standard HTTP status codes:

Status Meaning
200 Success
400 Bad request — missing required fields
403 Forbidden — insufficient RBAC role
404 Resource not found
500 Internal server error

Error response format:

{
  "error": "Forbidden",
  "message": "Role \"viewer\" is not permitted. Required: admin, operator"
}

Data Schemas

PolicyRule

{
  "id": "string",
  "name": "string",
  "description": "string",
  "enabled": "boolean",
  "allowedTransitions": ["string"],
  "blockedTransitions": ["string"],
  "blockedNamespaces": ["string"]
}

ActiveMigration

{
  "planName": "string",
  "namespace": "string",
  "sourceSCC": "string",
  "targetSCC": "string",
  "namespaces": ["string"],
  "phase": "string",
  "updatedAt": "ISO 8601 timestamp"
}

SCCVersionEvent

{
  "timestamp": "ISO 8601 timestamp",
  "version": "string",
  "role": "source | target",
  "action": "activated | deactivated",
  "planName": "string",
  "namespace": "string"
}

PodMigrationEntry

{
  "timestamp": "ISO 8601 timestamp",
  "podName": "string",
  "namespace": "string",
  "fromSCC": "string",
  "toSCC": "string",
  "serviceAccount": "string",
  "deploymentPhase": "string",
  "status": "Mutated | Skipped | Failed",
  "reason": "string",
  "telemetrySignals": { "key": "value" }
}

AuditLogEntry

{
  "timestamp": "ISO 8601 timestamp",
  "action": "string",
  "actor": "string",
  "role": "string",
  "sourceIP": "string",
  "userAgent": "string",
  "details": { },
  "result": "string"
}

Configuration

Governance API Environment Variables

Variable Default Description
PORT 3000 Server listen port
LOG_LEVEL info Logging level
ENFORCE_RBAC false Set to true to enforce RBAC role checks

Webhook Environment Variables

Variable Default Description
WEBHOOK_PORT 8443 HTTPS listen port
TLS_CERT_FILE /certs/tls.crt Path to TLS certificate
TLS_KEY_FILE /certs/tls.key Path to TLS private key
GOVERNANCE_API_URL http://governance-api:3000 Governance API base URL