data protection.md
Manage Data Protection
Define custom detection types, allow lists, and enforcement policies as code, with a dry-run-first rollout
This guide manages your organization's Data Control Center configuration in Terraform: the org-level switch, a detection engine (Protection Profile), a custom detection type, allow-list entries that suppress false positives, and an enforcement policy rolled out safely with dry run. The whole flow is self-contained — no IDs need to be copied from the app.
Before You Begin
- A configured
provider "barndoor"block (see Getting Started)
Step 1: Adopt the organization config
Data protection has one configuration object per organization, provisioned by the platform. The barndoor_dlp_org_config resource adopts that singleton rather than creating anything:
resource "barndoor_dlp_org_config" "this" {
enabled = true
# Observe-only mode: every policy records findings without acting.
global_dry_run = false
}
Reference: barndoor_dlp_org_config
Step 2: Define a detection engine (Protection Profile)
A detection engine — a Protection Profile in the app — binds a detection provider to the data types it scans for. Enforcement policies reference engines, so at least one must exist. Manage it in Terraform, or look up one that was created in the portal:
enabled_detection_types = [ "DETECTION_TYPE_AWS_ACCESS_KEY_ID", "DETECTION_TYPE_GITHUB_PAT", ] } ```
References: barndoor_dlp_detection_engine resource, data source
Step 3: Define a custom detection type
Custom detection types extend the built-in detectors with organization-specific patterns — project codenames, internal ticket formats, customer ID shapes:
resource "barndoor_dlp_custom_detection_type" "codenames" {
name = "Project codenames"
description = "Internal project codenames that must not leave the organization"
patterns = [
{ pattern = "(?i)project\s+aurora", pattern_type = "PATTERN_TYPE_REGEX" },
{ pattern = "AURORA-CLASSIFIED", pattern_type = "PATTERN_TYPE_LITERAL" },
]
# Both default to *_MEDIUM when omitted.
default_severity = "DETECTION_SEVERITY_HIGH"
default_confidence = "DETECTION_CONFIDENCE_HIGH"
}
Reference: barndoor_dlp_custom_detection_type
Patterns are evaluated in order. Regex patterns use Rust regex syntax and are validated by the API — a pattern that doesn't compile is rejected at apply time, not silently ignored.
The platform assigns the type's wire name (DETECTION_TYPE_CUSTOM_…), exposed as the detection_type attribute — that's the value other data protection resources reference.
Step 4: Suppress false positives with allow-list entries
Allow-list entries stop known-safe values from being reported (and acted on) as findings:
# Scoped to specific detection types — including the custom one from Step 3.
resource "barndoor_dlp_allow_list_entry" "codename_docs_site" {
pattern = "aurora.docs.example.com"
pattern_type = "PATTERN_TYPE_LITERAL"
detection_types = [barndoor_dlp_custom_detection_type.codenames.detection_type]
reason = "Public documentation host, not a leak"
}
# Omit detection_types to suppress matches for every detection type.
resource "barndoor_dlp_allow_list_entry" "support_mailbox" {
pattern = "support@example.com"
pattern_type = "PATTERN_TYPE_LITERAL"
detection_types = ["DETECTION_TYPE_EMAIL"]
reason = "Shared support mailbox, not PII"
}
Reference: barndoor_dlp_allow_list_entry
Step 5: Enforce with a policy — dry run first
Enforcement policies decide what happens when a detection engine reports a finding. A policy targets exactly one lane: MCP traffic (tool inputs/outputs) or model-provider traffic (prompts/responses).
Start in dry run — the policy evaluates and records findings in activity, but takes no action:
resource "barndoor_dlp_enforcement_policy" "block_secrets_in_prompts" {
name = "Block secrets in prompts"
action = "POLICY_ACTION_BLOCK"
provider_ids = ["openai"]
runtime_stage = "RUNTIME_STAGE_PROMPT"
# Roll out observing first; flip to false to enforce.
dry_run = true
detection_engine_ids = [barndoor_dlp_detection_engine.secrets.id]
}
And an MCP-lane example — tokenize PII in tool traffic for one group:
resource "barndoor_dlp_enforcement_policy" "tokenize_mcp_pii" {
name = "Tokenize PII on MCP traffic"
action = "POLICY_ACTION_TOKENIZE"
mcp_targets = [
{ mcp_server_id = "*", direction = "BOTH" },
]
principals = [
{ principal_type = "GROUP", principal_id = "engineering" },
]
dry_run = true
detection_engine_ids = [barndoor_dlp_detection_engine.secrets.id]
}
Reference: barndoor_dlp_enforcement_policy
Step 6: Flip to enforcement
Once dry-run findings in the activity view look right — expected matches, no false positives that an allow-list entry should cover — enforce by changing one line and re-applying:
dry_run = false
This is the code-review moment the dry-run pattern exists for: the diff that turns on enforcement is one visible line in a pull request.
Complete example
resource "barndoor_dlp_detection_engine" "secrets" { name = "Credential secrets" provider_type = "builtin_secrets_regex"
enabled_detection_types = [ "DETECTION_TYPE_AWS_ACCESS_KEY_ID", "DETECTION_TYPE_GITHUB_PAT", ] }
resource "barndoor_dlp_custom_detection_type" "codenames" { name = "Project codenames" description = "Internal project codenames that must not leave the organization"
default_severity = "DETECTION_SEVERITY_HIGH" default_confidence = "DETECTION_CONFIDENCE_HIGH" }
resource "barndoor_dlp_allow_list_entry" "codename_docs_site" { pattern = "aurora.docs.example.com" pattern_type = "PATTERN_TYPE_LITERAL" detection_types = [barndoor_dlp_custom_detection_type.codenames.detection_type] reason = "Public documentation host, not a leak" }
resource "barndoor_dlp_enforcement_policy" "block_secrets_in_prompts" { name = "Block secrets in prompts" action = "POLICY_ACTION_BLOCK" provider_ids = ["openai"] runtime_stage = "RUNTIME_STAGE_PROMPT" dry_run = true
detection_engine_ids = [barndoor_dlp_detection_engine.secrets.id] }
</Expandable>