Getting Started with Policy Information Points (PIPs)
What is a PIP?
A Policy Information Point (PIP) is a data source that provides real-time context and attributes for your access control policies. Think of it as connecting your authorization system to the sources of truth in your organization.
Why Connect Data Sources?
Without PIPs, your policies are limited to information in the request itself. With PIPs, your policies can access:
- User Information from your identity provider (roles, department, manager, clearance level)
- Resource Metadata from databases (owner, sensitivity, environment, status)
- HR Context from your HR system (employment status, start date, certifications)
- Business Context from CRM/ERP systems (customer tier, account status)
- Real-Time Context for dynamic, intelligent authorization decisions
Where PIPs Sit in the System
Data sources (PIPs) are configured in the Control Plane. The Policy Bridge distributes that data to all bouncers so policies can use it at evaluation time.
Click to enlarge
Real-World Example
Without PIP:
User requests access to "Production Database"
Policy checks: Does user have "database-admin" role?
Decision: Simple yes/no based on static role
With PIP:
User requests access to "Production Database"
Policy checks:
- User's department (from Okta)
- User's employment status (from Workday)
- Resource owner (from PostgreSQL metadata)
- Time of day and user's location
- User's clearance level and certifications
Decision: Smart, context-aware authorization
Quick Start: Connect Your First Data Source
The flow from adding a data source to using it in policies:
Click to enlarge
Step 1: Access PIP Management
You can access PIP Management in two places:
- During Onboarding: In the Getting Started Wizard → "Connect Data Sources" step
- Anytime Later: Settings → Data Sources
Step 2: Choose Your Data Source
Click "Add Data Source" and select from 13 categories:
Identity & HR
- Identity Provider (Okta, Azure AD, Auth0, LDAP)
- HR System (Workday, BambooHR, ADP)
Enterprise Systems
- CRM (Salesforce, HubSpot, Dynamics)
- ERP (SAP, Oracle, NetSuite)
- Ticketing (ServiceNow, Jira, Zendesk)
Data & Storage
- Database (PostgreSQL, MySQL, MongoDB)
- Document Storage (SharePoint, Google Drive, S3)
- Data Warehouse (Snowflake, BigQuery, Redshift)
Technical
- OpenAPI Specification
- Custom API
- Configuration Management Database (CMDB)
Step 3: Configure Connection
Let's walk through connecting Okta as an example:
3.1 Enter Basic Information
- Name: "Production Okta" (friendly name for your team)
- Provider: Select "Okta"
3.2 Choose Authentication Method
- OAuth 2.0 (Recommended) - Most secure, tokens auto-refresh
- API Key - Simpler setup, good for read-only access
- Username/Password - For legacy systems only
3.3 Configure OAuth (if selected)
- Okta Domain:
your-company.okta.com - Client ID: From your Okta admin console
- Client Secret: From your Okta admin console
- Scopes:
openid profile email groups(default is good!)
Where to get OAuth credentials: In Okta, go to Applications → Create App Integration → API Services or Web App
3.4 Test Connection
Click "Test Connection" - this is where the magic happens!
The system will:
- Connect to your Okta instance
- Discover all available user fields
- Show you REAL metadata from your Okta
Step 4: Understanding the Metadata
After successful connection test, you'll see two sections:
Available Metadata Fields (LEFT SIDE)
These are REAL fields from your data source:
For Okta, you'll see actual fields like:
id- User IDemail- Email addressfirstName,lastName- Name fieldsstatus- User status (ACTIVE, INACTIVE, etc.)profile.department- User's departmentprofile.title- Job titlegroups- Group membershipslastLogin- Last login timestamp- Plus any custom fields you've added to Okta!
This is NOT sample data - it's the actual schema from your connected system!
Authorization Attributes (RIGHT SIDE)
These are standard attribute names used in your policies:
user.id- Unique user identifieruser.email- User email addressuser.department- Department nameuser.roles- Role assignmentsuser.groups- Group membershipsuser.mfa_enabled- MFA statususer.clearance_level- Security clearance
Step 5: Map the Attributes
Mapping connects real fields to policy attributes:
| Policy Attribute (What policies use) | Okta Field (Real field name) |
|---|---|
user.email | → email |
user.department | → profile.department |
user.roles | → groups |
user.manager | → profile.manager |
Why map?
- Policies use standard names like
user.department - Different providers have different field names (Okta:
profile.department, Azure AD:department) - Mapping lets you switch providers without rewriting policies!
Step 6: Configure Sync Settings
Sync Frequency: How often to refresh data from the source
- Real-time (Webhooks): Instant updates when data changes (best for critical data)
- Every 5 minutes: Near real-time
- Hourly: Standard refresh rate (good for most use cases)
- Daily: For relatively static data
- Weekly: For reference data
Recommendation: Start with "Hourly" - you can adjust later!
Step 7: Save and You're Done!
Click "Save Information Source"
Your data source is now connected! Within minutes:
- Control Core fetches user data from Okta
- Applies your attribute mappings
- Makes the data available to ALL your policies
- Distributes to ALL your Bouncers (PEPs) automatically
Common Use Cases
Use Case 1: Department-Based Access
Scenario: Only Engineering team can access development APIs
Setup:
- Connect Okta (for user department)
- Map
user.department→profile.department
Policy (automatically gets department from Okta):
Allow access if:
- User's department = "Engineering"
- Resource environment = "development"
Use Case 2: Resource Ownership
Scenario: Users can only access resources they own
Setup:
- Connect Okta (for user ID)
- Connect PostgreSQL (for resource metadata)
- Map
user.id→id - Map
resource.owner_id→owner_id(from database)
Policy (gets data from both sources):
Allow access if:
- Resource owner = Current user ID
OR
- User has "admin" role
Use Case 3: Compliance & Clearance
Scenario: Only certified employees can access PII data
Setup:
- Connect Workday (for employee certifications)
- Connect PostgreSQL (for data classification)
- Map
user.certifications→certifications - Map
resource.classification→data_classification
Policy:
Allow access if:
- User has "PII-Handler" certification
- User's background check = "Passed"
- Resource classification = "PII"
Real-world PIP scenario library
These eight scenarios show how Policy Information Points (PIPs) turn static request attributes into controls that match Canadian and regulated enterprise workloads. Each scenario lists business context, required PIPs, attribute mapping, a Rego snippet, and what happens if you skip the PIP.
Terminology: In Control Core the rules you author are controls. Under the hood each control is a Rego policy evaluated by OPA. PIP data arrives via the Policy Bridge (OPAL) as
data.pip.*— never as a per-request round-trip to Okta or Workday.
1. Canadian bank wire certification (Workday + Postgres + Okta)
Business context: A Schedule I bank must prove that wire initiators hold current AML certification and an active employment record before high-value transfers leave the payment rail (FINTRAC / OSFI B-13).
PIPs required: Workday (HR), PostgreSQL (certification ledger), Okta (identity groups).
| Control attribute | PIP source field |
|---|---|
user.employment_status | Workday Worker_Status |
user.aml_cert_expiry | Postgres certifications.aml_expiry |
user.groups | Okta groups |
package controlcore.wire_cert
import rego.v1
default allow := false
allow if {
data.pip.workday.users[input.user.id].employment_status == "Active"
time.now_ns() < time.parse_rfc3339_ns(data.pip.postgres.certifications[input.user.id].aml_expiry)
"wire-operators" in data.pip.okta.users[input.user.id].groups
}
Without PIP: Controls can only inspect JWT roles. Terminated or uncertified staff with a leftover group claim still initiate wires; auditors see no employment or certification evidence.
2. Healthcare EMR patient consent (PIPEDA / PHIPA)
Business context: An Ontario hospital EMR must block chart access unless the clinician has an active encounter relationship and the patient has not withdrawn consent (PIPEDA 4.3 / PHIPA).
PIPs required: PostgreSQL (encounter + consent tables), Azure AD or Okta (clinician identity).
| Control attribute | PIP source field |
|---|---|
user.npi | IdP employeeId |
resource.patient_id | Request path / body (traffic) |
patient.consent_status | Postgres consents.status |
encounter.active | Postgres encounters.active |
package controlcore.emr_consent
import rego.v1
default allow := false
allow if {
data.pip.postgres.encounters[input.resource.patient_id][input.user.id].active == true
data.pip.postgres.consents[input.resource.patient_id].status == "granted"
}
Without PIP: Encounter and consent are invisible. Controls either over-allow (privacy breach) or over-deny (care disruption) with no audit trail tied to consent state.
3. Financial AI prompt clearance (OSFI / NIST AI RMF)
Business context: A capital-markets desk routes analyst prompts to an LLM gateway. Prompts that reference restricted issuer data require clearance ≥ Secret and an AI-use attestation (OSFI B-13 model risk / NIST AI RMF Govern + Map).
PIPs required: Okta (clearance custom attribute), Workday (AI attestation training), optional Postgres (model risk register).
| Control attribute | PIP source field |
|---|---|
user.clearance_level | Okta profile.clearance |
user.ai_attestation | Workday Training_Completion |
resource.model_risk_tier | Postgres model_register.tier |
package controlcore.ai_prompt_clearance
import rego.v1
default allow := false
allow if {
data.pip.okta.users[input.user.id].clearance_level in {"secret", "top_secret"}
data.pip.workday.users[input.user.id].ai_attestation == true
input.agent_context.prompt_classification != "restricted_issuer"
}
Without PIP: Prompt controls see only path/model name. Restricted issuer content slips through; compliance packs mark related AI controls CANNOT_ASSESS.
4. HR Workday termination — instant revoke
Business context: When HR marks a worker terminated in Workday, every Bouncer must deny privileged API access within the webhook/sync window — not at next nightly IdP sync.
PIPs required: Workday with real-time webhooks (primary), Okta (secondary group cleanup).
| Control attribute | PIP source field |
|---|---|
user.employment_status | Workday Worker_Status |
user.active | Okta status |
package controlcore.hr_terminate
import rego.v1
default allow := false
allow if {
data.pip.workday.users[input.user.id].employment_status == "Active"
data.pip.okta.users[input.user.id].status == "ACTIVE"
}
Without PIP: JWT exp can remain valid for hours. Terminated users retain API access until session expiry — a classic OSFI / SOC 2 access-revocation finding.
5. Defense clearance + compartment (CCCP L3)
Business context: A defence contractor protecting CUI-class APIs must enforce personnel clearance and compartment membership before tool or document access (CCCP Level 3 / CPCSC L2+ identity assurance).
PIPs required: LDAP or Okta (clearance), PostgreSQL or CMDB (compartment assignments).
| Control attribute | PIP source field |
|---|---|
user.clearance_level | LDAP clearance / Okta custom |
user.compartments | Postgres personnel_compartments |
resource.compartment | Resource metadata PIP |
package controlcore.defense_compartment
import rego.v1
default allow := false
allow if {
data.pip.identity.users[input.user.id].clearance_level in {"secret", "top_secret"}
input.resource.compartment in data.pip.postgres.personnel_compartments[input.user.id]
}
Without PIP: Compartment membership cannot be proven at decision time. Gap reports emit CANNOT_ASSESS for CCCP identity controls.
6. Multi-tenant SaaS isolation
Business context: A SaaS platform hosts many customer tenants behind one Bouncer fleet. Controls must prove the caller's tenant matches the resource tenant — never trust a client-supplied tenant_id header alone.
PIPs required: PostgreSQL (tenant membership), Okta or Auth0 (org / tenant claims mirrored into PIP).
| Control attribute | PIP source field |
|---|---|
user.tenant_ids | Postgres memberships.tenant_id |
resource.tenant_id | Postgres resources.tenant_id |
package controlcore.tenant_isolation
import rego.v1
default allow := false
allow if {
input.resource.tenant_id in data.pip.postgres.memberships[input.user.id]
}
Without PIP: Tenant isolation collapses to header checks — trivial to spoof. Cross-tenant data exposure becomes an auditor show-stopper.
7. Legacy LDAP → Okta dual-PIP migration
Business context: During IdP migration, some apps still resolve groups from LDAP while new apps use Okta. Controls must accept either authoritative source until cutover completes — without rewriting Rego twice.
PIPs required: LDAP and Okta, mapped to the same control attributes with documented precedence (see Multi-PIP composition).
| Control attribute | LDAP field | Okta field |
|---|---|---|
user.groups | memberOf | groups |
user.department | department | profile.department |
package controlcore.dual_idp
import rego.v1
default allow := false
_groups := data.pip.okta.users[input.user.id].groups if {
data.pip.okta.users[input.user.id]
} else := data.pip.ldap.users[input.user.id].groups
allow if {
"app-readers" in _groups
}
Without PIP (single source only): Half the user population fails open or closed during migration; cutover risk spikes and rollback is painful.
8. Multi-cloud data residency (Law 25 / PIPEDA)
Business context: Québec Law 25 and PIPEDA require that personal information processing stay in approved regions. Controls deny requests when the subject's residency region or the resource's storage region is outside the allowlist.
PIPs required: Okta/Azure AD (user residency / province), PostgreSQL or CMDB (resource region tags), optional Snowflake/BigQuery metadata PIP.
| Control attribute | PIP source field |
|---|---|
user.residency_region | IdP profile.province / usageLocation |
resource.storage_region | CMDB / Postgres resources.region |
package controlcore.data_residency
import rego.v1
default allow := false
_allowed := {"ca-central-1", "ca-west-1", "ca-on", "ca-qc"}
allow if {
data.pip.identity.users[input.user.id].residency_region in _allowed
data.pip.cmdb.resources[input.resource.id].storage_region in _allowed
}
Without PIP: Residency is guessed from IP or ignored. Law 25 §12 accountability and PIPEDA 4.7 safeguards cannot be evidenced in shadow or enforce modes.
Next: Configure attribute precedence and CANNOT_ASSESS behavior in the PIP Administrator Guide — Multi-PIP composition.
Understanding Multi-Bouncer Architecture
The Big Question: "We have 5 Bouncers protecting different apps - do we configure PIPs 5 times?"
Answer: NO! Configure ONCE, benefit EVERYWHERE!
Here's how it works:
You Configure (ONE TIME):
┌─────────────────────────────┐
│ Control Core PAP │
│ │
│ PIP Connections: │
│ ✓ Okta │
│ ✓ PostgreSQL │
│ ✓ Workday │
└──────────┬──────────────────┘
│
│ Publishes to Policy Bridge
▼
┌──────────────┐
│ Policy Bridge│ ← Single source of truth
└──────┬───────┘
│
│ Distributes to ALL Bouncers
│
┌──────┼──────┬──────┬──────┐
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌────────┐ │ │ │ │ │ │ │ │
│Bouncer1│ │ │ │ │ │ │ │ │
│Protects│ │ │ │ │ │ │ │ │
│API A │ │ │ │ │ │ │ │ │
└────────┘ │ │ │ │ │ │ │ │
All bouncers automatically
get the same fresh data!
Benefits:
- Configure data sources ONCE in PAP
- ALL Bouncers automatically receive the data
- Consistent authorization decisions across all protected resources
- Real-time updates propagate to all enforcement points
FAQs
Q: Is the metadata I see real or just examples?
A: It depends on whether you've tested the connection!
- Before Testing: You see sample fields (examples of what might be available)
- After Testing: You see REAL fields from your actual data source!
When you click "Test Connection" and it succeeds, the system:
- Connects to your Okta/Database/API
- Discovers the actual schema
- Shows you the real fields available
For example, after testing Okta, you'll see:
- Your actual custom attributes
- Your specific group names
- Your configured profile fields
Q: Do I need to set up Authorization Attributes before connecting data sources?
A: NO! Authorization Attributes are pre-defined by Control Core.
The Authorization Attributes (like user.department, user.roles) are standard attribute names recommended by Control Core for policy writing. They're always available.
You just need to map them to your provider's field names:
user.department→ Maps to →profile.department(in Okta)user.department→ Maps to →department(in Azure AD)
This standardization means your policies work with any provider!
Q: What if my data source isn't in the list?
You have options:
- Use "Custom API" - Works with any REST API
- Use "Custom" provider - Within each category
- Request Integration - Click "Request New Integration" button
- Contact Support - We can help build custom connectors
Q: How often should I sync data?
Recommendations:
- Hourly: Good default for most use cases
- Every 15 minutes: For frequently changing data
- Real-time (Webhooks): For critical security decisions
- Daily: For relatively static reference data
Rule of thumb: More frequent = more current data, but higher load on source systems
Q: Is my data secure?
Absolutely! Control Core uses enterprise-grade security:
- Credentials Encrypted: AES-256 encryption for all stored credentials
- TLS in Transit: All API calls use HTTPS/TLS
- Secure Storage: Credentials stored separately from configuration
- Audit Logging: Every data access is logged
- Sensitivity-Based Caching: Sensitive data cached for shorter periods
- No Plain Text: Passwords and secrets never stored unencrypted
Q: Can I edit a connection after it's created?
Yes! Go to Settings → Data Sources → Click on connection → Edit
You can change:
- Authentication credentials
- Sync frequency
- Attribute mappings
- Connection settings
Note: Changes take effect on the next sync cycle.
Q: What happens if a connection fails?
Control Core handles failures gracefully:
- Connection marked as "Error" - You'll see the status
- Policies still work - Use last cached data
- Alerts sent - Admins notified of failure
- Auto-retry - System attempts reconnection
- Audit logged - Failure details captured
You can manually retry or fix credentials and re-test.
Troubleshooting
| Issue | What to check |
|---|---|
| Connection test fails | Verify URL, credentials, and network access from the Control Plane to the data source. Check firewall and TLS/SSL certificates. |
| Data not appearing in policies | Confirm attribute mappings and that the data source sync has completed. Check PIP status in Settings → Data Sources. |
| Sync errors or stale data | Review sync interval and retry; check data source rate limits and API availability. Inspect Control Plane logs for sync errors. |
| Multiple bouncers not receiving data | Data is distributed from the Control Plane to all bouncers; ensure bouncers are registered and Policy Bridge is reachable. |
For more, see the Troubleshooting Guide.
Next Steps
Now that you understand PIPs, you can:
- Connect More Sources: Add databases, HR systems, CRM
- Write Policies: Use your mapped attributes in policies
- Monitor Connections: Check sync status and health
- Optimize: Adjust sync frequencies based on usage
Need Help?
- Admin Guide: For detailed configuration and monitoring
- Developer Guide: For policy development and API integration
- Support: Help & Support icon (?) in top navigation
- Community: Join our Discord for questions and discussions
You've successfully connected your first data source! Your policies now have real-time context from your organization's systems.