# ============================================================================= # AI Gateway Policy — OPA/Rego Reference Implementation # ============================================================================= # This file is a reference-only translation of policies.yaml into OPA Rego. # It is NOT processed by the gateway; it exists to show how the same rules # would look if evaluated by Open Policy Agent. # ============================================================================= package gateway.policy import rego.v1 # ---------- data ---------- allowed_projects := {"SAFE", "PLATFORM", "OPS"} allowed_changelogs := {"release_*.xml", "hotfix_*.xml"} business_hours := {"start": "08:00", "end": "18:00", "timezone": "Europe/Oslo"} rate_limit_default := 30 # ---------- default decision ---------- default decision := "deny" # ---------- scope-based allow ---------- decision := "allow" if { input.tool == "jira.*" # pattern: starts_with(input.tool, "jira.") startswith(input.tool, "jira.") "jira.read" in input.subject.scopes input.action in {"read", "get", "list", "search"} } decision := "allow" if { startswith(input.tool, "jira.") "jira.write" in input.subject.scopes input.action in {"create", "update", "delete"} } decision := "allow" if { input.tool == "db.queryReadonly" "db.read" in input.subject.scopes } # ---------- environment-based rules ---------- decision := "allow" if { input.tool == "jenkins.deploy" input.context.environment == "staging" } decision := "require_approval" if { input.tool == "jenkins.deploy" input.context.environment == "prod" } # ---------- argument allowlist ---------- decision := "deny" if { input.tool == "jira.createTicket" not input.arguments.project in allowed_projects } decision := "deny" if { input.tool == "db.runLiquibase" not glob_match_any(allowed_changelogs, input.arguments.changelog) } # ---------- block rule ---------- decision := "deny" if { input.tool == "db.executeScript" } # ---------- rate limit ---------- decision := "deny" if { input.context.rate.current > rate_limit_default } # ---------- time window ---------- decision := "deny" if { input.tool == "jenkins.deploy" not within_business_hours(input.context.timestamp) } # ---------- helpers ---------- within_business_hours(timestamp) if { # Simplified: real implementation would parse timestamp and convert to Europe/Oslo hour := to_number(substring(timestamp, 11, 2)) hour >= 8 hour < 18 } glob_match_any(patterns, value) if { some pattern in patterns glob.match(pattern, ["/"], value) } # ---------- reason ---------- reason := "Project not in allowlist" if { input.tool == "jira.createTicket" not input.arguments.project in allowed_projects } reason := "Changelog not in allowlist" if { input.tool == "db.runLiquibase" not glob_match_any(allowed_changelogs, input.arguments.changelog) } reason := "db.executeScript is blocked by policy" if { input.tool == "db.executeScript" } reason := "Rate limit exceeded" if { input.context.rate.current > rate_limit_default } reason := "Deployments only allowed during business hours" if { input.tool == "jenkins.deploy" not within_business_hours(input.context.timestamp) }