Getting Started

Prerequisites

Quick Start

1. Install OPA

1
2
3
4
5
6
# macOS
brew install opa

# Linux
curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64_static
chmod 755 opa && sudo mv opa /usr/local/bin/

2. Run Policy Tests

1
2
3
4
5
# Run all tests with verbose output
opa test ./policies ./tests -v

# Run tests with coverage
opa test ./policies ./tests -v --coverage

3. Check Policy Formatting

1
opa fmt --check --fail policies/ tests/

4. Evaluate a Terraform Plan

1
2
3
4
5
6
7
8
# Generate Terraform plan JSON
cd terraform/environments/dev
terraform init
terraform plan -out=tfplan.bin
terraform show -json tfplan.bin > tfplan.json

# Evaluate against policies using Conftest
conftest test tfplan.json -p ../../policies/

5. Evaluate a Single Resource

You can test policies against individual resource JSON:

1
2
3
4
5
6
7
8
9
echo '{
  "resource_type": "stackit_compute_instance",
  "environment": "production",
  "values": {
    "name": "web-server-01",
    "public_ip": "203.0.113.10",
    "region": "eu-central-1"
  }
}' | opa eval -d policies/ -I 'data.policies.iaas.network_security.deny'

6. Set Up Pre-commit Hooks

1
2
pip install pre-commit
pre-commit install

Project Structure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
├── policies/
│   ├── iaas/           # IaaS networking and compute policies
│   ├── paas/           # PaaS database and storage policies
│   ├── spring/         # Managed Spring runtime policies
│   └── shared/         # Shared helpers and constants
├── tests/
│   ├── iaas/           # IaaS policy tests
│   ├── paas/           # PaaS policy tests
│   └── spring/         # Spring policy tests
├── terraform/
│   ├── modules/        # Reusable Terraform modules
│   └── environments/   # Per-environment configs (dev, staging, prod)
├── docs/               # Documentation
└── .github/workflows/  # CI/CD pipelines

Writing New Policies

  1. Create a .rego file in the appropriate policies/ subdirectory
  2. Import shared constants and helpers
  3. Add policy metadata with compliance annotations
  4. Write deny rules (hard enforcement) or warn rules (soft enforcement)
  5. Create a corresponding test file in tests/
  6. Run opa fmt -w to format and opa test to verify

Policy Template

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package policies.<layer>.<policy_name>

import data.shared.constants
import data.shared.helpers

import rego.v1

metadata := {
    "id": "STACKIT-<LAYER>-<ABBREV>-NNN",
    "description": "...",
    "scope": {"provider": "stackit", "layer": "<layer>"},
    "severity": "critical|high|medium|low",
    "enforcement": "hard|soft",
    "compliance": {
        "bsi_c5": [...],
        "gdpr": [...],
    },
}

deny contains msg if {
    # Rule conditions
    not helpers.has_valid_exception(input, "POLICY-ID")
    msg := helpers.violation_msg("POLICY-ID", "severity", resource_name, "message")
}

Troubleshooting

OPA tests fail with “undefined”: Ensure the package name in your test file matches <policy_package>_test and imports the policy package correctly.

Conftest finds no policies: Check that the -p flag points to the policies/ directory and that your Rego files have the correct package declarations.

Pre-commit hooks fail: Run opa fmt -w policies/ tests/ to auto-format, then retry.


University of Plymouth · Cybersecurity PhD · Elias Lenz