Enforce CI guardrails centrally with Harness Policy as Code: write an OPA
Rego policy, group it into a Policy Set, bind that set to the Pipeline
entity on the On Run event, and Harness will evaluate every pipeline run
before any step executes. This tidbit teaches one atomic skill: apply an OPA
policy that (1) requires a mandatory security/scan step and (2) blocks a risky
curl … | sh command, then watch a compliant pipeline pass and a violating
pipeline get blocked.
This is the CI governance tidbit. A separate CD tidbit covers governance for deploy stages (approval gates). Here the rules are CI-specific: scan steps and risky shell commands.
- The Policy as Code model: Policy (one Rego rule) → Policy Set (group + entity + event + severity) → enforcement (On Save / On Run).
- How to write a Rego
denyrule against the expanded pipeline payload. - How a Policy Set on On Run / Error and exit blocks a non-compliant run.
- Where to read the policy evaluation result for any run.
Pipeline run requested
│
▼
Harness OPA server evaluates Policy Set "CI Governance" ◄── policies/ci_governance.rego
│
┌──────┴───────┐
PASS DENY (severity = Error)
│ │
steps run run rejected, 0 steps execute
(Success) (Policy Set Evaluations panel shows why)
The policy receives the full pipeline YAML as JSON under input.pipeline. Two
independent deny rules (see policies/ci_governance.rego):
- Mandatory scan — every CI stage must have a step whose name/identifier
contains
scanorsecurity. - Block risky commands — no
Runstep may pipe a remote script into a shell (curl … | sh,wget … | bash).
| Path | Purpose |
|---|---|
policies/ci_governance.rego |
OPA/Rego policy source — copy the entire file into Harness to create a Policy |
.harness/governance_pipeline_success.yaml |
Compliant pipeline — satisfies both rules, runs to Success |
.harness/governance_pipeline_violation.yaml |
Violating pipeline — breaks both rules, rejected at run time (no steps execute) |
- A Harness account with Policy as Code / Governance enabled (Enterprise tier; not available on Free).
- Permissions: ability to create Policies and Policy Sets at your chosen scope (Account / Org / Project).
- Your Project ID and Org ID (found in Project/Org Settings in Harness).
- Infrastructure: No Kubernetes, delegate, or STO license needed — this runs on Harness Cloud (managed runners).
- Harness terminology: New to Harness? Scope = Account (global) / Org (organization) / Project (team's work container).
Clone or fork this repo to your GitHub account (you'll need to push it to import pipelines into Harness later).
git clone https://github.com/harness-community/ci-tidbits-governance-opa
cd ci-tidbits-governance-opaBoth pipeline YAML files need your organization and project IDs. Open them and replace the marked lines:
File: .harness/governance_pipeline_success.yaml
- Line 4:
projectIdentifier: <+project.identifier>→ your actual project ID (e.g.,my_project) - Line 5:
orgIdentifier: <+org.identifier>→ your actual org ID (e.g.,my_org)
File: .harness/governance_pipeline_violation.yaml
- Line 4:
projectIdentifier: <+project.identifier>→ your actual project ID (same as success pipeline) - Line 5:
orgIdentifier: <+org.identifier>→ your actual org ID (same as success pipeline)
In Harness UI: Account Settings (or Org/Project Settings) → Security and Governance → Policies → + New Policy.
- Policy Name:
Tidbit CI Governance OPA - Policy Type:
Inline - Paste entire contents of
policies/ci_governance.regointo the editor - Save
Important: Do NOT change the first line package pipeline — Harness requires this exact package name to route policy evaluations correctly.
Back on the Security and Governance page → Policy Sets tab → + New Policy Set.
- Policy Set Name:
Tidbit CI Governance OPA Set - Entity Type:
Pipeline(what does this policy apply to?) - Deployment Type:
All(keep default) - Event:
On Run(evaluate when a pipeline run is triggered; also available:On Saveto gate at edit time) - Continue → + Add Policy → select your policy (
Tidbit CI Governance OPA) → Severity: Error and exit → Apply → Finish - Back in the Policy Sets list, confirm the Enforced toggle is ON (blue)
Scope note: This Policy Set applies to all pipelines of type Pipeline in your scope. If you create it at Project level, it only affects that project's pipelines. Recommended for first tests.
In Harness: Pipelines → + New → + Import from YAML.
- Copy the full contents of
.harness/governance_pipeline_success.yaml - Paste into the editor → Import
- Click Run on the pipeline
- When prompted, select branch main
- Expected outcome:
- ✓ Policy Evaluations tab shows PASSED (both rules satisfied)
- ✓ All steps execute: Install dependencies → Security scan → Success
- ✓ The scan runs
pip-auditon the sample dependency list
In Harness: Pipelines → + New → + Import from YAML.
- Copy the full contents of
.harness/governance_pipeline_violation.yaml - Paste into the editor → Import
- Click Run
- Expected outcome (this is the teaching moment):
- ✗ Run is rejected BEFORE ANY STEP STARTS (status: Errored / Policy Violation)
- ✗ Policy Set Evaluations panel displays both deny messages:
CI stage 'risky_build' must contain a security/scan step (identifier or name containing 'scan' or 'security'). Run step 'risky_install' contains a risky 'pipe remote script to shell' command (e.g. curl | sh). Blocked by CI governance policy. - ✗ NO steps execute — the policy stops the run cold.
Fix the violation: Remove the curl | sh command from the YAML, add a scan step named "security_scan", re-import, and re-run — it will now pass.
| Symptom | Cause | Fix |
|---|---|---|
| "Policy as Code" not visible in Harness | Not on Enterprise tier or no Governance permission | Use an account with Policy as Code licensed and assigned to you |
| Compliant pipeline gets blocked anyway | Scan step name doesn't contain "scan" or "security" | Rename the step or its identifier to include one of those keywords. Rule is exact: check the YAML identifier field. |
| Violating pipeline runs successfully (shouldn't) | Policy Set not enforced or wrong severity | Check: (1) Policy Set Enforced toggle is ON, (2) Severity is Error and exit (not Warn), (3) Event is On Run (not On Save) |
| Org / project identifier errors on import | YAML has placeholder IDs like <+project.identifier> |
Replace with actual IDs. Find them: Project Settings (bottom-left) → Identifier; or Org Settings → Identifier |
| Policy evaluation not shown in run details | Policy Set not attached to your project's Pipeline entity | Verify: Security and Governance → Policy Sets → your set → Enforced ON. Try scope: Project level first, not Account. |
- Add
On Saveto the Policy Set so violations are caught when authors save, not just at run. - Extend Rule 2 to block other patterns (e.g.
chmod 777, hardcoded secrets,latestimage tags). - Require a specific native scan step type (e.g. an STO
Aqua/Snykstep) instead of a name match, if you have the STO module.