Skip to main content

What are Policies?

Formal’s policy system uses Open Policy Agent (OPA), an open-source policy engine that enables you to express access control rules as code. Policies are evaluated in real-time as users connect to resources and execute queries. Your policies can:
  • Block connections to resources or specific tables/schemas
  • Redact query results automatically
  • Encrypt and decrypt data fields
  • Rewrite queries before they reach the database
  • Filter and limit result sets
  • Enforce MFA for sensitive operations

How Policies Work

Policies are written in Rego, OPA’s purpose-built language for access control. They are evaluated at three stages:
  1. Session - When a connection is established
  2. Pre-request - Before a query reaches the resource
  3. Post-request - When data returns from the resource
Each stage has specific actions available based on when the policy is evaluated. See Enforcement for details on available actions.

Policy Structure

Every policy consists of these essential components:
A unique identifier for the policy. No two policies can share the same name.
A clear explanation of the policy’s purpose and scope. This helps other admins understand what the policy does.
The administrators responsible for maintaining and enforcing the policy. Owners receive notifications when policies are triggered (if configured).
The policy logic, written in Rego, OPA’s purpose-built language for access control.

Policy Status

Policies can be in one of three states:
StatusDescriptionUse Case
DraftUnder development, not enforcedWriting and testing new policies
Dry-runLogs violations without enforcingTesting policies with real traffic before enforcement
ActiveFully enforced and monitoringProduction enforcement
Use dry-run mode to test policies against real traffic without impacting users. Review the logs to ensure the policy works as intended before activating it.

Notifications

Configure notifications for policy triggers:
  • None: No notifications sent
  • Consumer: Notify the user who triggered the policy
  • Owners: Notify policy owners
  • All: Notify both user and owners
Notifications can be sent via:
  • Email
  • Slack (requires integration setup)

End-User Identity Propagation

Formal can extract end-user identity from applications like Looker, Metabase, or Retool, enabling policies that work for both direct connections and application-mediated access:
  • Direct connection: Alice uses psql to query a resource → user and end-user are both Alice
  • Application connection: Katie uses Metabase → user is the machine user, end-user is Katie
This allows you to write policies that consider the actual person behind the query, even when they’re using a BI tool.

Quick Example

Block all connections by default, but allow admins using a specific machine user:
package formal.v2

import future.keywords.if
import future.keywords.in

default session := {
  "action": "block",
  "type": "block_with_formal_message"
}

session := {
  "action": "allow",
  "reason": "Admin access via authorized app"
} if {
  "admin" in input.end_user.groups
  input.user.username == "idp:formal:machine:backoffice"
  not input.end_user.email == "john.doe@joinformal.com"
}

Managing Policies

  • Web Console
  • Terraform
  1. Navigate to Policies
  2. Click New Policy
  3. Fill in name, description, and owners
  4. Write Rego code in the editor
  5. Set status (Draft, Dry-run, or Active)
  6. Configure notifications
  7. Save the policy

Best Practices

Always test new policies in dry-run mode first. Review logs to ensure they work as expected before activating.
Instead of writing policies for individual users, use groups. This makes policies scalable and easier to maintain.
Write clear descriptions and use meaningful reason fields. Future you (and your team) will thank you during audits.
Use Policy Data Loaders to fetch dynamic approval lists, compliance data, or business logic from external systems.

Learn More