Skip to main content

Assess and map: migrate governance, not Rego

Objective

Run a pre-migration assessment of an existing OPA deployment and map its source-system organizing concepts onto Writ's entity hierarchy, without rewriting the Rego.

Concept

The first thing to understand about migrating to EnforceAuth is what does not change. If your policy already runs on OPA, the decision engine stays OPA (or Enterprise OPA). The Rego stays Rego. Migration moves the parts around the policy: where it is stored, how it is signed and promoted, how it is delivered to the PDP, and how decisions are audited. The policy itself is preserved. That is what makes a clean parity proof possible later, and it is why a migration is measured in days, not a rewrite quarter.

Assess first. Inventory what you run today before you move anything:

  • Policies and their inputs. Which Rego packages exist, what input shape each expects, and which decisions (allow, filter, masks) are consumed. Capture a set of real requests and the decisions the source system returns for them. Those become your golden decisions for the parity suite in lesson 3.
  • Where the PDPs run. OPA sidecars in Kubernetes, an Envoy ext_authz filter, standalone services on VMs, Enterprise OPA for scale. You are not moving the PDPs; you are re-pointing where they pull bundles from.
  • Embedded authorization. Authorization logic still hard-coded in application code is not yet policy. Zift, the open-source scanner, does a structural pass over a codebase and extracts embedded checks into Rego or Cedar, reporting an externalization percentage. Run it during assessment to find rules that never made it into the source system, so they come along in the migration rather than getting stranded.

Then map. Source systems organize policy their own way. Styra DAS groups policy into systems and stacks; an OpenShift deployment organizes by cluster, namespace, and workload. EnforceAuth's control plane, Writ, organizes entities as a hierarchy:

tenant -> org -> system -> app

Mapping is a translation of that structure, not of the code. A DAS "system" that fronts one service usually maps to a Writ system (or app) under the right org; environments (dev, staging, prod) become promotion stages within Writ rather than separate copies you hand-maintain. The Rego packages move under those entities unchanged.

Two boundaries to keep straight while mapping:

  • Writ is the control plane that governs OPA, Enterprise OPA, and Cedar-compatible PDPs. It signs and promotes bundles and keeps decision logs. It is not a PDP and is not on the request path. The PDP still decides.
  • Do not "improve" the Rego during migration. A rewrite mixed into a migration destroys your ability to prove parity, because you can no longer tell a migration bug from an intended change. Preserve now, refactor later, each behind its own parity run.
Source system EnforceAuth
------------- -----------
DAS system / OCP workload --> Writ system/app under org (governance)
DAS stack (shared rules) --> shared bundle under org/tenant
env copies (dev/stg/prod) --> promotion stages in Writ
the Rego packages --> unchanged, same OPA/eopa PDP
embedded code checks --> extracted with Zift into Rego/Cedar

Hands-on lab

Open ../lab/policy.rego. This is the policy under migration: a default-deny document with tenant isolation, role rules, and owner-delete. Treat it as Rego you are lifting from a Styra DAS system, untouched.

Read it as an assessor would. The rules the source system enforced are documented at the top of the file (tenant isolation, admin full access, editor read/write, public read, owner delete). Identify the input shape it expects (subject with id, role, tenant; an action; a resource with owner, tenant, classification) and list the distinct decisions it makes. Those inputs and decisions are exactly what you capture as golden decisions.

The lab ships as a starter: policy.rego has the same_tenant gate but leaves the allow rules as a # TODO(learner) stub, and the parity suite in policy_test.rego is the set of golden decisions you migrate against. Run it to see that baseline:

git clone https://github.com/EnforceAuth/university-labs.git
cd university-labs
opa test courses/migrating-to-enforceauth -v

The starter reports PASS: 4/8: the four deny cases hold under default-deny, and the four allow cases fail until the preserved rules are written. You reconstruct those rules and drive the suite to PASS: 8/8 in lesson 3. For now, the eight tests are your assessment baseline: every one is a decision captured from the source system.

Check for understanding

  1. During a migration to EnforceAuth, does the Rego get rewritten? What actually changes, and why does keeping the policy unchanged matter for the rest of the migration?
  2. Writ organizes entities as tenant -> org -> system -> app. A Styra DAS "system" fronting one service maps onto which part of that hierarchy, and where do dev/staging/prod go?
  3. Which tool finds authorization logic still hard-coded in application code so it comes along in the migration, and what does it extract that code into?