STACKIT Policy-as-Code Framework

Overview

This framework implements a three-layer Policy-as-Code (PaC) architecture for STACKIT, a German public-sector cloud provider. It enforces security, compliance, and operational policies across IaaS, PaaS, and managed Spring runtime workloads using Open Policy Agent (OPA) and Terraform.

Architecture

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
┌─────────────────────────────────────────────────────────────┐
│                    Layer 1: AUTHORING                        │
│                                                              │
│  policies/iaas/        → IaaS networking & compute rules     │
│  policies/paas/        → PaaS database & storage rules       │
│  policies/spring/      → Managed Spring runtime rules        │
│  policies/shared/      → Shared helpers and constants        │
│                                                              │
│  Each policy includes:                                       │
│  • Metadata (id, severity, enforcement level)                │
│  • Compliance annotations (BSI C5, GDPR)                     │
│  • Exception handling with expiry                            │
└──────────────────────────┬──────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│                   Layer 2: EVALUATION                        │
│                                                              │
│  OPA evaluates Terraform plan JSON against Rego policies:    │
│                                                              │
│  terraform plan → JSON → OPA evaluate → deny[] / warn[]      │
│                                                              │
│  Evaluation modes:                                           │
│  • deny[]  — Hard enforcement, blocks deployment             │
│  • warn[]  — Soft enforcement, advisory only                 │
│  • Exceptions — Time-bound policy waivers with audit trail   │
└──────────────────────────┬──────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│                  Layer 3: ENFORCEMENT                        │
│                                                              │
│  CI/CD pipeline (.github/workflows/policy-ci.yml):           │
│                                                              │
│  1. opa fmt --check       → Lint Rego formatting             │
│  2. opa test              → Run policy unit tests            │
│  3. terraform validate    → Validate Terraform configs       │
│  4. checkov               → Security scan Terraform          │
│  5. conftest test         → Evaluate plan against policies   │
│                                                              │
│  Pre-commit hooks enforce formatting at dev time.            │
└─────────────────────────────────────────────────────────────┘

Policy Layers

IaaS — Network Security (policies/iaas/network_security.rego)

Controls for STACKIT compute and networking resources:

Rule Severity Enforcement BSI C5 GDPR
No public IPs in production Critical Hard OPS-05
Traffic via approved ingress only Critical Hard OPS-05
EU-region-only deployment Critical Hard OPS-20 Art. 44-49
Encryption in transit (TLS) Critical Hard CRY-01 Art. 32

PaaS — Database Security (policies/paas/database_security.rego)

Controls for STACKIT managed database services:

Rule Severity Enforcement BSI C5 GDPR
Encryption at rest Critical Hard CRY-02 Art. 32
EU-region deployment Critical Hard OPS-20 Art. 44-49
Daily backups minimum Critical Hard OPS-08
No public endpoints Critical Hard OPS-05
Multi-AZ for tier-1 (prod) Critical Hard
Multi-AZ for tier-2 (prod) Medium Soft (warn)

Spring Runtime — Application Security (policies/spring/runtime_security.rego)

Controls for STACKIT managed Spring applications:

Rule Severity Enforcement BSI C5 GDPR
LTS JDK versions only High Hard
Approved base images only High Hard
No secrets in env vars Critical Hard IDM-01 Art. 5(1)(c)
TLS for DB connections Critical Hard CRY-01 Art. 32
JSON structured logging Medium Hard OPS-13
Central logging sink Medium Hard OPS-13
Actuator health endpoints Medium Hard

Compliance Mapping

BSI C5 (Cloud Computing Compliance Criteria Catalogue)

The framework maps policies to BSI C5 controls:

  • OPS-05 — Network segmentation and access controls
  • OPS-08 — Backup and recovery procedures
  • OPS-13 — Logging and monitoring
  • OPS-20 — Data location and sovereignty
  • CRY-01 — Encryption of data in transit
  • CRY-02 — Encryption of data at rest
  • IDM-01 — Identity and access management

GDPR

  • Article 5(1)(c) — Data minimisation (no secrets in plain text)
  • Article 25 — Data protection by design and by default
  • Article 32 — Security of processing (encryption requirements)
  • Articles 44-49 — Cross-border data transfers (EU-region enforcement)

Exception Handling

Policies support time-bound exceptions for justified deviations:

1
2
3
4
5
6
7
8
9
10
11
{
  "exceptions": [
    {
      "policy_id": "STACKIT-IAAS-NET-001-PUB-IP",
      "ticket_id": "SEC-1234",
      "approver": "ciso@example.com",
      "risk_category": "accepted",
      "expiry_date": "2025-06-30T23:59:59Z"
    }
  ]
}

Required fields:

  • ticket_id — Reference to the approval ticket
  • approver — Email of the person who approved the exception
  • risk_category — Classification (accepted, mitigated, transferred)
  • expiry_date — RFC 3339 timestamp; exception is automatically invalidated after this date

Shared Components

Constants (policies/shared/constants.rego)

Centralised configuration for approved regions, JDK versions, base images, sensitive env var patterns, and compliance control mappings.

Helpers (policies/shared/helpers.rego)

Reusable functions: region validation, exception checking, violation message formatting, and sensitive pattern detection.


University of Plymouth · Cybersecurity PhD · Elias Lenz