# 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](/how-tos/data-control-center/protection-profiles)), 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.

<Note>
  **Estimated time**: 20–30 minutes. Complete [Getting Started](/terraform/getting-started) first. For the concepts, see the [Data Control Center overview](/how-tos/data-control-center/overview).
</Note>

## Before You Begin

* A configured `provider "barndoor"` block (see [Getting Started](/terraform/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:

```hcl theme={null}
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`](https://registry.terraform.io/providers/barndoor-ai/barndoor/latest/docs/resources/dlp_org_config)

<Note>
  Because it's a singleton, `terraform destroy` doesn't delete anything — it resets both settings to the platform defaults (`enabled = true`, `global_dry_run = false`) and drops the resource from state.
</Note>

## 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:

<Tabs>
  <Tab title="New engine">
    ```hcl theme={null}
    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",
      ]
    }
    ```
  </Tab>

<Tab title="Existing engine (data source)">
    ```hcl theme={null}
    data "barndoor_dlp_detection_engine" "secrets" {
      # Names are unique per provider_type; set provider_type (or use id)
      # when one profile spans several engines.
      name          = "Credential secrets"
      provider_type = "builtin_secrets_regex"
    }
    ```
  </Tab>
</Tabs>

References: [`barndoor_dlp_detection_engine` resource](https://registry.terraform.io/providers/barndoor-ai/barndoor/latest/docs/resources/dlp_detection_engine), [data source](https://registry.terraform.io/providers/barndoor-ai/barndoor/latest/docs/data-sources/dlp_detection_engine)

<Note>
  Engines are unique per (`name`, `provider_type`) — the same name across several provider types renders as one merged profile in the app. Deleting an engine that is the only one on an enforcement policy fails with an error naming the referencing policy.
</Note>

## 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:

```hcl theme={null}
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`](https://registry.terraform.io/providers/barndoor-ai/barndoor/latest/docs/resources/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:

```hcl theme={null}
# 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`](https://registry.terraform.io/providers/barndoor-ai/barndoor/latest/docs/resources/dlp_allow_list_entry)

<Note>
  The platform has no update operation for allow-list entries, so changing **any** attribute replaces the entry (delete + create). Plans will show this as a replacement — that's expected.
</Note>

## 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:

```hcl theme={null}
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:

```hcl theme={null}
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`](https://registry.terraform.io/providers/barndoor-ai/barndoor/latest/docs/resources/dlp_enforcement_policy)

<Warning>
  **The two lanes don't mix.** `MCP_SERVER` policies use `mcp_targets` with the `RUNTIME_STAGE_TOOL_INPUT` / `RUNTIME_STAGE_TOOL_OUTPUT` stages and may not set `provider_ids` or `model_alias`; `MODEL_PROVIDER` policies are the reverse, with `RUNTIME_STAGE_PROMPT` / `RUNTIME_STAGE_RESPONSE`. The API rejects mixed shapes. It also rejects (with a 422) any detection engine that doesn't support the policy's `action`.
</Warning>

## 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:

```hcl theme={null}
  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.

<Tip>
  There are two dry-run levers, and they compose: `global_dry_run` on the org config forces *every* policy to observe-only (useful during initial rollout of the whole system), while per-policy `dry_run` stages an individual policy. Enforcement happens only when both are off.
</Tip>

## Complete example

<Expandable title="Full configuration from this guide">
  ```hcl theme={null}
  resource "barndoor_dlp_org_config" "this" {
    enabled        = true
    global_dry_run = false
  }

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>
