Skip to main content

PDP Integration with EnforceAuth

A Policy Decision Point (PDP) runs OPA or Enterprise OPA and evaluates Rego. EnforceAuth is the control plane: it builds bundles from Git, publishes them to your bundle destination, and ingests decision logs for audit and coverage.

This guide covers the PDP side — pulling bundles and reporting decisions back.

Architecture

Git (policy source) ──► EnforceAuth deploy ──► S3 / GCS / Azure (bundle)

▼ pull bundle
OPA / EOPA (PDP)

▼ decision logs + status
EnforceAuth API (API key)

Your PEP (application or gateway) sends input to the PDP; the PDP returns allow/deny. EnforceAuth does not sit in the request path — it governs policy lifecycle and evidence.

1. Pull bundles from EnforceAuth

After a successful deployment, the bundle object lives at the path configured in Bundle Destination (e.g. policies/bundle.tar.gz on S3).

Configure OPA to poll that location using management bundles. Example for S3 (illustrative — substitute your bucket, region, and path):

services:
enforceauth-bundle:
url: https://YOUR_BUCKET.s3.YOUR_REGION.amazonaws.com
credentials:
s3_signing:
environment_credentials: {}

bundles:
authz:
service: enforceauth-bundle
resource: policies/bundle.tar.gz
polling:
min_delay_seconds: 10
max_delay_seconds: 20

For GCS or Azure, use the credential plugin appropriate to your cloud — match the same destination you configured in the console. See Bundle destinations.

Verify activation:

opa inspect /path/to/downloaded/bundle.tar.gz
# or on a running OPA with bundle mode:
curl -s localhost:8181/v1/data/authz/allow | jq .

Drift tip: If the console shows Success but decisions reference an old bundle revision, the PDP is likely still pointed at a stale URL or path.

Bundle polling — how often, and what happens when things break

This is the most common operations question after initial setup. Bundle polling (OPA → object storage) is separate from decision log upload (OPA → EnforceAuth API) and separate from authorization queries (PEP → OPA).

EnforceAuth deploy ──writes──► S3 / GCS / Azure (bundle)

│ poll every min–max seconds
OPA / EOPA

│ every request
App (PEP)

How often does OPA check for a new bundle?

With management bundle polling:

bundles:
authz:
service: enforceauth-bundle
resource: policies/bundle.tar.gz
polling:
min_delay_seconds: 10
max_delay_seconds: 20
FieldMeaning
min_delay_secondsShortest wait between poll attempts after the previous attempt finished
max_delay_secondsLongest wait between poll attempts

OPA picks a random delay between min and max for each cycle — not a fixed interval. With 10 / 20, expect a new check roughly every 10–20 seconds on average after the prior download attempt completes.

This is not the same as decision log reporting (decision_logs.reporting uses its own min/max, typically 30–60s). Bundle polling controls policy freshness; decision log reporting controls audit latency.

EnvironmentBundle min / maxNotes
Dev10 / 20See policy changes quickly
Staging30 / 60Balance freshness and storage API load
Production60 / 120 (or wider)Stagger across pods — avoid thundering herd on deploy
Large fleet (100+ sidecars)90 / 180 + jitterConsider EOPA delta bundles if downloads are heavy

Widen intervals in production unless you have a hard real-time promotion SLO — EnforceAuth deploy completes in seconds; PDP pickup time is dominated by your poll window.

What happens on startup?

ScenarioBehavior
Polling config, bundle reachableOPA downloads, activates bundle, then serves /v1/data/...
Polling config, bundle unreachable on first bootOPA retries on the poll schedule; no policy to evaluate until first successful activation — PEP requests fail or return undefined until then
Local bundle (opa run -b bundle.tar.gz)No polling; static bundle until restart

For Kubernetes, use readiness probes on /health and confirm bundle activation (status plugin or logs) before marking the pod ready.

What if the bundle server is unreachable?

After a bundle has been successfully activated at least once, OPA keeps serving the last good bundle in memory. Authorization continues — it does not automatically deny all traffic when S3/GCS/Azure is down.

StateWhat the PDP doesRisk
Bundle server down, prior bundle loadedKeeps evaluating stale policyFalse confidence — you think new deny rules are live but PDP has not picked them up
Bundle server down, never activatedNo policy loadedDeny/undefined behavior depending on Rego defaults
Bundle server recoversNext successful poll downloads and activates new revisionLag = up to max_delay_seconds plus download time

This is fail operational with stale policy, not fail closed. For security-sensitive promotions, verify bundle revision in decision logs or via the status plugin — do not assume deploy Success in the console means every PDP has activated.

Enable status reporting (section 4) so EnforceAuth receives OPA's native bundle activation success/failure payloads. Failed downloads surface in fleet monitoring when status:write is configured.

What if EnforceAuth API is unreachable?

Decision log and status plugins use a different URL (ENFORCEAUTH_URL) than bundle storage. If the EnforceAuth API is down or blocked:

ComponentImpact
Authorization (PEP → PDP)Unaffected — OPA evaluates locally with the active bundle
Decision logsOPA buffers and retries per plugin config; sustained outage → gaps in console Decisions / coverage
StatusFleet health reports may stop updating
Bundle pollingUnaffected — bundles live in your object storage, not the EnforceAuth API

Design alerts on decision log gaps separately from bundle activation failures.

What if the app cannot reach the PDP?

That is a PEP → PDP problem (sidecar down, wrong OPA_URL, network policy). OPA cannot evaluate if the PEP cannot connect. See Application integration — fail open vs fail closed.

This is independent of bundle polling — the PDP may have a fresh bundle but be unreachable from the app.

Verifying bundle revision at runtime

# OPA exposes bundle state on the status API (when server is running)
curl -s localhost:8181/v1/status | jq '.bundles'

Compare active_revision / etag against the bundle version in your latest EnforceAuth deployment run.

With status:write configured, the same information flows to EnforceAuth for fleet views.

Thundering herd on deploy

When EnforceAuth publishes a new bundle, every PDP polling that path will discover the change on its own schedule. If all sidecars share identical min_delay / max_delay, they may hit object storage simultaneously.

Mitigations:

  • Stagger min/max per deployment zone or use a spread of values in Helm values
  • Widen production poll windows
  • EOPA delta bundles for large artifacts (OPA vs EOPA)

2. Create an API key for telemetry

Decision log ingestion requires an entity-scoped API key with decisions:write. See API keys for creation and rotation.

Use View Config in the console to copy the PDP YAML template.

3. Send decision logs

EnforceAuth expects OPA's decision log plugin pointed at the EnforceAuth API. The console-generated template (from decisions:write scope):

services:
enforceauth:
url: ${ENFORCEAUTH_URL}/v1
headers:
X-API-Key: ${ENFORCEAUTH_API_KEY}

decision_logs:
service: enforceauth
reporting:
min_delay_seconds: 30
max_delay_seconds: 60

Environment variables:

VariableValue
ENFORCEAUTH_URLhttps://api.enforceauth.com or https://api.enforceauth.dev
ENFORCEAUTH_API_KEYSecret from key creation (shown once)

The /v1 prefix belongs on the service URL — OPA plugins append /logs and /status paths relative to that base.

After traffic flows, verify:

  • Decisions in the console shows entries for the entity
  • Policy Coverage moves from Never evaluated to Evaluated
  • Bundle revision in logs matches your latest deployment

4. Optional: status reporting

Keys with status:write can add:

status:
service: enforceauth

Status reports help fleet health views. Read scope status:read allows fetching status via API.

5. Enterprise OPA (EOPA)

OPA vs EOPA — when to choose EOPA, industry context, masking/delta/partitioning depth.

Historical products and trademarks

Styra DAS™ was decommissioned April 30, 2026. EnforceAuth is the enterprise authorization platform for policy lifecycle, promotion, audit, and fleet operations. EOPA was donated to the CNCF Open Policy Agent project (open-policy-agent/eopa) as a PDP subproject. DAS™ may be a trademark of its respective owner. EnforceAuth is not affiliated with or endorsed by Apple Inc.

Enterprise OPA (EOPA) is an extended OPA distribution for data-heavy and enterprise PDP workloads. It runs the same Rego and bundle format EnforceAuth publishes — swap the container image and add EOPA-specific plugins where needed.

When teams choose EOPA

CapabilityOne-line benefit
Decision log maskingRedact sensitive input fields before logs leave your network
Delta bundlesSmaller updates when only part of the bundle changes
PartitioningLarge fleets with isolated policy partitions
Datasource integrationsSQL, DynamoDB, Kafka, LDAP, S3, Vault — without custom plugins
Fleet scaleDelta bundles + partitioning + data-heavy evaluation tuning

Expand each capability below for why it matters and when to use it.

Decision log masking — redact PII before logs leave the PDP

The problem: Every authorization check sends the full input document to the decision log plugin — user emails, employee IDs, bearer tokens, account numbers, internal URLs. EnforceAuth stores these for audit and policy coverage. In regulated environments, shipping raw PII to any external endpoint (even your own control plane) triggers compliance review.

What OSS OPA requires: Mask in the PEP before calling OPA, run a log proxy between OPA and EnforceAuth, or accept the compliance exposure. PEP-side masking is error-prone — one new field in input and PII leaks until someone notices.

What EOPA provides: Native decision_logs.mask paths redact fields inside the PDP before the log payload leaves your network:

decision_logs:
service: enforceauth
mask:
- "/input/user/email"
- "/input/user/ssn"
- "/input/request/headers/authorization"

Why this is a benefit:

  • Compliance — HIPAA, PCI-DSS, and GDPR often require minimization before data crosses zone boundaries; masking at the PDP is a clean audit story
  • Defense in depth — even if EnforceAuth is trusted, logs transiting corporate proxies or SIEM pipelines carry less sensitive payload
  • Operational safety — engineers reviewing decision logs in the console see authorization context without full PII

Choose masking when: input routinely carries identifiers you would not paste into a ticket, or legal has flagged decision log retention.

Delta bundles — smaller bundle updates at scale

The problem: OSS OPA downloads the entire bundle.tar.gz on each bundle activation. A one-line Rego change still pulls the full artifact — every sidecar, every poll cycle where the etag changed.

What EOPA provides: Delta bundles apply a patch containing only changed files instead of re-downloading the whole archive.

Why this is a benefit:

Without deltasWith deltas
50 MB bundle × 500 pods = 25 GB egress per deploy wavePatch might be kilobytes — proportional to the diff
Longer activation time — parse and load full bundleFaster activation — less CPU and memory spike on rollout
Higher object-storage egress costLower cost at fleet scale
Wider window where pods run mixed revisions during downloadShorter convergence time after deploy

Choose delta bundles when:

  • You have dozens to thousands of PDP instances polling the same bundle destination
  • Bundles are large (shared data.json, many packages, WASM helpers)
  • You deploy policy multiple times per day and see S3 throttling or slow rollouts

At small scale (a handful of sidecars, sub-megabyte bundles), full bundles are fine — see Bundle polling for poll tuning.

Partitioning — large multi-tenant fleets

The problem: A single monorepo builds one fat bundle with policies for payments, catalog, admin, and internal tools. Every microservice PDP loads all of it — wasted memory, slower startup, and broader blast radius if one package fails compilation at activation.

What EOPA provides: Partitions let different PDP fleets subscribe to named slices of a release — e.g. payments vs catalog — from one overall build.

Why this is a benefit:

  • Memory and startup — each PDP loads only the Rego and data it needs
  • Isolation — a bad rule in one domain does not block activation of unrelated packages in another partition
  • Multi-tenant operations — platform teams can align partition boundaries with team or system ownership
  • Rollout control — promote or roll back one partition without touching others

EnforceAuth alternative: Configure separate bundle paths per system entity — each gets its own bundle.tar.gz from the same Git repo via path overrides. That works well when domains map cleanly to EnforceAuth entities. EOPA partitioning helps when you want one build artifact, many slices at the PDP without splitting storage paths.

Choose partitioning when: One repo feeds many services with distinct policy domains, or you are mirroring a legacy layout that already used partition names.

OSS OPA is sufficient for many workloads. EOPA is common when migrating from Styra DAS™ (deprecated April 30, 2026) or when masking, delta bundles, or partitioning are hard requirements.

EOPA config example

Combine bundle polling (section 1), EnforceAuth telemetry (sections 2–3), and optional masking:

services:
enforceauth-bundle:
url: https://YOUR_BUCKET.s3.YOUR_REGION.amazonaws.com
credentials:
s3_signing:
environment_credentials: {}

enforceauth:
url: ${ENFORCEAUTH_URL}/v1
headers:
X-API-Key: ${ENFORCEAUTH_API_KEY}

bundles:
authz:
service: enforceauth-bundle
resource: policies/bundle.tar.gz
polling:
min_delay_seconds: 10
max_delay_seconds: 20

decision_logs:
service: enforceauth
reporting:
min_delay_seconds: 30
max_delay_seconds: 60
mask:
- "/input/user/email"
- "/input/user/ssn"
- "/input/request/headers/authorization"

status:
service: enforceauth

labels:
id: ${OPA_INSTANCE_ID}
environment: production

Use an EOPA build from the CNCF project (open-policy-agent/eopa) with the same opa run --server --config-file=... entrypoint as OSS OPA. Legacy ghcr.io/styrainc/enterprise-opa images may still run in existing fleets during migration — plan to move to CNCF builds.

Sidecars and deployment patterns

EOPA uses the same deployment patterns as OSS OPA — sidecar, host daemon, centralized service, or gateway-backed. Configure bundle polling and plugins in the PDP config.yaml; mount it the same way in Kubernetes.

Migrating from DAS™? See Migration from Styra DAS™ / EOPA.

Local development without EnforceAuth

opa run --server --bundle ./build/bundle.tar.gz
opa eval -i input.json -d bundle.tar.gz 'data.authz.allow'

Use EnforceAuth dev (api.enforceauth.dev, docs.enforceauth.dev) for integration testing before production keys.

Troubleshooting

SymptomCheck
No decision logsAPI key scopes, ENFORCEAUTH_URL, network egress to API
401 on ingestRevoked or wrong key; create a new key
Policies unevaluated in consolePDP not receiving traffic, or logs pointed at wrong tenant entity
Stale bundle revisionBundle polling config vs latest deployment path; see Bundle polling
Deploy succeeded but old policy in decisionsPDP serving last good bundle — poll lag or wrong bundle path; check /v1/status bundles
New pods deny everythingFirst bundle activation failed — credentials, path, or bucket policy
Intermittent 403s after deployMixed fleet — some pods on new bundle, some on stale; rolling restart or wait for poll cycle
S3 throttling on deployPoll intervals too aggressive across fleet — stagger min/max

Official OPA docs

Next