diff --git a/hugo/content/en/security/cloud_security_management/review_remediate/ownership_agent.md b/hugo/content/en/security/cloud_security_management/review_remediate/ownership_agent.md index b315da5dd904..bcb82e0419a9 100644 --- a/hugo/content/en/security/cloud_security_management/review_remediate/ownership_agent.md +++ b/hugo/content/en/security/cloud_security_management/review_remediate/ownership_agent.md @@ -27,8 +27,8 @@ The Ownership Agent reads multiple data sources and combines them into a ranked | Priority | Signal | Description | | -------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 1 | **Owner tags** | Cloud resource tags with keys such as `owner`, `dd-team`, or `team`. An explicit ownership tag is the strongest signal. | -| 2 | **Ownership preferences** | Custom tag mappings and rules you define in a [reference table](/reference_tables). These act as organization-level overrides and are evaluated alongside direct tags. Learn more at [set up ownership preferences](/security/cloud_security_management/review_remediate/ownership_preferences/). | -| 3 | **Service Catalog** | Team ownership data from the Datadog Service Catalog, matched against the resource's service, application, or component tags. | +| 2 | **Ownership preferences** | Tag mappings, exclusions, and custom instructions you define on the [Ownership Agent settings page](https://app.datadoghq.com/security/configuration/csm/ownership-agent). These act as organization-level overrides. Datadog evaluates ownership preferences alongside direct tags. Learn more at [Set Up Ownership Preferences](/security/cloud_security_management/review_remediate/ownership_preferences/). | +| 3 | **Software Catalog** | Team ownership data from the Datadog Software Catalog, matched against the resource's service, application, or component tags. | | 4 | **Cloud audit logs** | The identity of the user or principal that created the resource, extracted from cloud provider audit logs (for example, AWS CloudTrail). Automation accounts and CI principals are filtered out. | | 5 | **Container and host catalog** | Registry and host metadata for container images and host VMs, including image labels and host annotations. | | 6 | **Naming patterns** | Heuristics that infer ownership from resource names, service identifiers, or tag values that match known team naming conventions. | diff --git a/hugo/content/en/security/cloud_security_management/review_remediate/ownership_preferences.md b/hugo/content/en/security/cloud_security_management/review_remediate/ownership_preferences.md index 8bee1b58a96c..befcf5de0ce0 100644 --- a/hugo/content/en/security/cloud_security_management/review_remediate/ownership_preferences.md +++ b/hugo/content/en/security/cloud_security_management/review_remediate/ownership_preferences.md @@ -9,399 +9,128 @@ further_reading: - link: "/security/cloud_security_management/guide/frontier_group/" tag: "Documentation" text: "Cloud Security Frontier Group" -- link: "/integrations/guide/reference-tables/" - tag: "Documentation" - text: "Reference Tables" +description: "Customize the Ownership Agent with tag mappings, exclusions, and custom instructions on the Ownership Agent settings page." --- ## Overview -The Ownership Agent selects a subset of cloud resources with security findings and infers an owner for each one. By default, it uses cloud resource tags, service catalog data, and other data sources to infer ownership. - -**Ownership preferences** let you customize this process by providing your own rules. You store them in a Datadog [reference table][1], and the Ownership Agent reads them automatically to enhance its results. - -## Create an ownership preference file - -1. Create a CSV file following the format described below. Optionally, use the [Ownership Agent AI skill][5] with your AI coding assistant to generate the CSV interactively. -2. [Upload](#upload-your-ownership-preferences) it as a reference table named `k9_ownership_preferences`. Preferences take effect within 24 hours. - -### Preference types - -Each row in your reference table is one preference. The `preference_type` column determines what the row does. - -| Type | What it does | -|---------------|----------------------------------------------------------------| -| `tag_mapping` | When a resource has a matching tag, assign the specified owner | -| `exclusion` | Prevent a specific handle from ever being assigned as owner | -| `prompt_text` | Provide custom guidance to the AI inference engine | - -### Tag mappings - -A tag mapping says: _"When a resource has tag `X:Y`, it belongs to this owner."_ - -The Ownership Agent checks cloud resource tags against your mappings. When it finds a match, it adds the specified owner as a candidate. Multiple mappings can match the same resource, producing multiple candidates that the Ownership Agent ranks alongside other data sources. - -Tag mappings complement existing ownership data sources. They do not override a direct ownership tag (like `dd-team`) already present on the resource. - -#### Columns - -| Column | Description | -|------------------------|----------------------------------------------------------------------------| -| `preference_type` | Must be `tag_mapping` | -| `tag_key` | Tag key to match (for example, `cost-center`, `project`) | -| `tag_value` (optional) | Tag value to match. Leave empty to match any value for that key (wildcard) | -| `owner` | Owner to assign (for example, `team-platform`, `alice@example.com`) | -| `owner_type` | Type of owner: `team`, `user`, or `service` | -| `confidence` | How strongly this mapping indicates ownership: `high`, `medium`, or `low` | - -#### Owner type - -The `owner_type` field tells the Ownership Agent what kind of entity the owner is. This helps the AI engine make better decisions when ranking candidates. - -| Value | When to use | -| --- | --- | -| `team` | The owner is a team handle (for example, `team-platform`, `sre-team`) | -| `user` | The owner is an individual (for example, `alice@example.com`) | -| `service` | The owner is a service or automation account (for example, `payment-svc`) | - -#### Matching behavior - -- Tag key and value matching is **case-insensitive**. `Cost-Center` matches `cost-center`. -- An empty `tag_value` matches **any value** for that tag key (wildcard). -- If multiple mappings match, all produce candidates. The Ownership Agent ranks them by confidence. - -#### Confidence levels - -| Level | When to use | -| --- | --- | -| `high` | The tag reliably identifies the owner. Example: a `cost-center` tag that maps 1:1 to a team | -| `medium` | The tag is a good indicator but may not always be correct. Example: a `project` tag shared across teams | -| `low` | The tag provides a hint but needs corroboration. Example: an `env` tag that loosely correlates with a team | - -#### Example: Map cost centers to teams - -```text -id,preference_type,tag_key,tag_value,owner,owner_type,confidence,handle,exclusion_type,exclusion_resource_type,prompt_text,priority -1,tag_mapping,cost-center,CC-100,team-platform,team,high,,,,, -2,tag_mapping,cost-center,CC-200,team-data-eng,team,high,,,,, -3,tag_mapping,cost-center,CC-300,team-security,team,high,,,,, -``` - -#### Example: Map projects to owners - -```text -id,preference_type,tag_key,tag_value,owner,owner_type,confidence,handle,exclusion_type,exclusion_resource_type,prompt_text,priority -1,tag_mapping,project,atlas,team-atlas,team,medium,,,,, -2,tag_mapping,project,hermes,alice@example.com,user,medium,,,,, -3,tag_mapping,project,payments,team-fintech,team,high,,,,, -``` - -#### Example: Wildcard match any resource with a `managed-by` tag - -```text -id,preference_type,tag_key,tag_value,owner,owner_type,confidence,handle,exclusion_type,exclusion_resource_type,prompt_text,priority -1,tag_mapping,managed-by,,team-infra,team,low,,,,, -``` - -This matches any value of the `managed-by` tag and assigns it to `team-infra` with low confidence. Because the confidence is low, stronger data sources take priority. - -### Exclusions - -An exclusion tells the Ownership Agent, "Never assign this handle as a resource owner." - -Bot accounts, CI runners, and shared service accounts often appear in cloud resource metadata (for example, as the creator or last modifier). Exclusions remove these from ownership results so they only surface real owners. - -#### Columns - -| Column | Description | -|--------------------------------------|------------------------------------------------------------------------------------------------------------------------------| -| `preference_type` | Must be `exclusion` | -| `handle` | Owner handle to exclude (for example, `deploy-bot`, `ci-runner`) | -| `exclusion_type` (optional) | Limit exclusion to a specific owner type: `team`, `user`, or `service`. Leave empty to exclude for all exclusion types | -| `exclusion_resource_type` (optional) | Limit exclusion to a specific resource type (for example, `aws_ec2_instance`). Leave empty to exclude for all resource types | - -#### Matching behavior - -- The `handle` is matched **case-insensitively**. -- Optional filters use **AND** logic. All non-empty fields must match for the exclusion to apply. -- Leave `exclusion_type` and `exclusion_resource_type` empty to exclude the handle from all results (most common). - -#### Example: Exclude common bot accounts from all results - -```text -id,preference_type,tag_key,tag_value,owner,owner_type,confidence,handle,exclusion_type,exclusion_resource_type,prompt_text,priority -1,exclusion,,,,,,deploy-bot,,,, -2,exclusion,,,,,,ci-runner,,,, -3,exclusion,,,,,,github-actions,,,, -4,exclusion,,,,,,terraform-automation,,,, -``` - -#### Example: Exclude a service account only for specific resource types - -```text -id,preference_type,tag_key,tag_value,owner,owner_type,confidence,handle,exclusion_type,exclusion_resource_type,prompt_text,priority -1,exclusion,,,,,,k8s-node-controller,service,aws_ec2_instance,, -2,exclusion,,,,,,autoscaler-svc,service,aws_ec2_instance,, -``` - -These exclusions only apply to EC2 instances. The same handles are still eligible as owners for other resource types. - -#### Example: Exclude a team handle for a specific resource type - -```text -id,preference_type,tag_key,tag_value,owner,owner_type,confidence,handle,exclusion_type,exclusion_resource_type,prompt_text,priority -1,exclusion,,,,,,legacy-ops,team,aws_ec2_instance,, -``` - -This excludes `legacy-ops` only when it appears as a team candidate for EC2 instances. It is still considered for S3 buckets or other resource types. - -### Custom prompt text - -Custom prompt text provides free-form guidance to the AI inference engine. Use it to share organizational context that helps the AI make better ownership decisions, such as naming conventions, team structures, or which data sources to prioritize. - -You can provide up to **three** prompt text entries, one for each priority level (`high`, `medium`, `low`). Entries with the same priority are concatenated. Use priority to control which guidance the AI engine considers first. - -#### Columns - -| Column | Description | -|-----------------------|---------------------------------------------------------------------------------------------------| -| `preference_type` | Must be `prompt_text` | -| `prompt_text` | Your guidance text (up to 4,096 bytes per entry) | -| `priority` (optional) | Controls ordering: `high` entries are considered first, then `medium`, then `low`. Default: `low` | - -#### Tips for writing effective guidance - -- Be specific and actionable. "The `cost-center` tag is the most reliable ownership signal" is better than "Use tags". -- Explain your organization's conventions: team naming patterns, how to interpret specific tags, etc. -- Call out accounts that should not be owners (also add these as exclusion rows for enforcement). -- Use one entry per priority level to organize your guidance by importance. - -#### Example: organization-specific context split by priority - -```text -id,preference_type,tag_key,tag_value,owner,owner_type,confidence,handle,exclusion_type,exclusion_resource_type,prompt_text,priority -1,prompt_text,,,,,,,,Our organization assigns ownership by cost center. The cost-center tag is the primary ownership signal for all cloud resources. Team identifiers always use the team- prefix followed by the team name (e.g. team-platform team-data-eng).,high -2,prompt_text,,,,,,,,Shared infrastructure accounts (deploy-bot ci-runner github-actions terraform-automation) are automation accounts and should never be assigned as resource owners. Look for the human or team that configured the automation instead.,medium -3,prompt_text,,,,,,,,For container images the repository owner in our GitHub organization is a reliable secondary signal when cost-center tags are missing.,low -``` - -### Reference table format - -#### Column schema - -Your reference table must be named `k9_ownership_preferences` and contain these 12 columns: - -| Column | Type | Description | -|---------------------------|--------|-------------------------------------------------------------------------------------| -| `id` | String | **Required for all rows.** Unique identifier for the row. Used as the primary key | -| `preference_type` | String | **Required for all rows.** Row type: `tag_mapping`, `exclusion`, or `prompt_text` | -| `tag_key` | String | Tag key to match (tag mappings only) | -| `tag_value` | String | Tag value to match; leave empty as a wildcard (tag mappings only) | -| `owner` | String | Owner handle to assign (tag mappings only) | -| `owner_type` | String | Owner type: `team`, `user`, or `service` (tag mappings only) | -| `confidence` | String | Confidence level: `high`, `medium`, or `low` (tag mappings only) | -| `handle` | String | Owner handle to exclude (exclusions only) | -| `exclusion_type` | String | Owner type filter for exclusion; leave empty to exclude all types (exclusions only) | -| `exclusion_resource_type` | String | Resource type filter for exclusion; leave empty to exclude all (exclusions only) | -| `prompt_text` | String | Guidance text (prompt text only) | -| `priority` | String | Ordering priority: `high`, `medium`, or `low` (prompt text only) | - -Each row uses a subset of columns depending on `preference_type`. Leave unused columns empty. - -#### Column usage by preference type - -| Column | `tag_mapping` | `exclusion` | `prompt_text` | -| --- | --- | --- | --- | -| `id` | required | required | required | -| `preference_type` | `"tag_mapping"` | `"exclusion"` | `"prompt_text"` | -| `tag_key` | required | — | — | -| `tag_value` | optional (empty means wildcard) | — | — | -| `owner` | required | — | — | -| `owner_type` | required | — | — | -| `confidence` | required | — | — | -| `handle` | — | required | — | -| `exclusion_type` | — | optional | — | -| `exclusion_resource_type` | — | optional | — | -| `prompt_text` | — | — | required | -| `priority` | — | — | optional | - -### Complete example - -A ready-to-use CSV with all three preference types: - -```text -id,preference_type,tag_key,tag_value,owner,owner_type,confidence,handle,exclusion_type,exclusion_resource_type,prompt_text,priority -1,tag_mapping,cost-center,CC-100,team-platform,team,high,,,,, -2,tag_mapping,cost-center,CC-200,team-data-eng,team,high,,,,, -3,tag_mapping,cost-center,CC-300,team-security,team,high,,,,, -4,tag_mapping,project,atlas,team-atlas,team,medium,,,,, -5,tag_mapping,project,hermes,alice@example.com,user,medium,,,,, -6,tag_mapping,env,production,sre-team,team,low,,,,, -7,tag_mapping,managed-by,,team-infra,team,low,,,,, -8,exclusion,,,,,,deploy-bot,,,, -9,exclusion,,,,,,ci-runner,service,,, -10,exclusion,,,,,,github-actions,service,,, -11,exclusion,,,,,,legacy-ops,team,aws_ec2_instance,, -12,prompt_text,,,,,,,,Our organization assigns ownership by cost center. The cost-center tag is the primary ownership signal for all cloud resources. Team identifiers always use the team- prefix followed by the team name (e.g. team-platform team-data-eng).,high -13,prompt_text,,,,,,,,Shared infrastructure accounts (deploy-bot ci-runner github-actions) are automation accounts and should never be assigned as resource owners. Look for the human or team that configured the automation instead.,medium -14,prompt_text,,,,,,,,For container images the repository owner in GitHub is a reliable secondary signal when cost-center tags are missing.,low -``` - -## Validation rules - -All preference data is validated when the Ownership Agent reads your reference table. **Validation is all-or-nothing**: if any row fails validation, the Ownership Agent rejects the **entire** preference set for that sync cycle. When this happens, the preferences are left empty until a valid set is uploaded. - -This strict approach helps ensure you are working with a consistent, fully valid set of preferences. - -### Allowed characters - -Different fields accept different character sets: - -| Field type | Allowed characters | Applies to | -| --- | --- | --- | -| Structured fields | Letters, digits, `-` `_` `.` `:` `/` `@` | `tag_key`, `owner`, `handle`, `exclusion_type`, `exclusion_resource_type`, `owner_type`, `confidence`, `priority` | -| Tag values | Same as structured fields, plus spaces | `tag_value` | -| Prompt text | Letters, digits, `-` `_` `.` `:` `/` `@` `#` `,` `;` `!` `?` `(` `)` `'` `"` `` ` `` spaces, tabs, newlines | `prompt_text` | - -#### Notable restrictions - -- **Angle brackets** (`<`, `>`) are **not allowed** in any field, including prompt text. -- **Curly braces** (`{`, `}`) are **not allowed** in any field. -- **Pipe characters** (`|`) are **not allowed** in any field. - -These restrictions prevent formatting artifacts and help ensure clean processing by the AI engine. - -### Size limits - -| Limit | Value | -|-------------------------------------|------------------------------------------------------------------------------------| -| Maximum tag mappings | 50 rows | -| Maximum exclusions | 20 rows | -| Maximum prompt text entries | Three rows (one per priority level) | -| Maximum bytes per field | 1,024 bytes (applies to tag keys, tag values, owners, handles, and similar fields) | -| Maximum bytes per prompt text entry | 4,096 bytes | - -### Duplicate detection +The Ownership Agent infers an owner for cloud resources with security findings, using cloud resource tags, Software Catalog data, and other data sources. **Ownership preferences** let you customize this process with three kinds of rules: -The Ownership Agent rejects the entire preference set if it contains conflicting or duplicate entries: +- **Tag mappings** use a tag on your resources to suggest an owner. +- **Exclusions** prevent an owner from ever being suggested. +- **Custom instructions** give the Ownership Agent organization-specific context in plain text. -- **Tag mappings**: Two rows with the same `tag_key` and `tag_value` but different `owner` values are a conflict. Two rows with the same `tag_key`, `tag_value`, and `owner` but different `confidence` levels are also a conflict. Exact duplicates (all fields identical) are allowed. -- **Exclusions**: Two rows with the same `handle`, `exclusion_type`, and `exclusion_resource_type` are a duplicate. Comparisons are case-insensitive. +{{< img src="security/csm/ownership_preferences.png" alt="The Ownership preferences section of the Ownership Agent settings page, with the Tag mappings, Exclusions, and Custom instructions panels." width="100%">}} -If the Ownership Agent detects any conflict or duplicate, it rejects the entire preference set. +## Manage ownership preferences -### Content guidelines for prompt text +To add, edit, or delete preferences, you need the **Security Monitoring Findings Write** permission. -The AI engine processes prompt text as organizational context. To help ensure your guidance is effective: +1. In Datadog, go to **Security** > **Settings** > **Cloud Security** > [**Ownership Agent**][1]. +2. In the **Ownership preferences** section, click **Add Tag Mapping**, **Add Exclusion**, or **Add Instruction**. +3. Fill in the form and click **Add**. -- **Use plain, declarative sentences**: Describe facts about your organization. -- **Avoid special formatting**: Markdown headings, HTML tags, and XML-like tags are stripped during processing. -- **Focus on ownership data sources**: Describe which tags, naming conventions, or team structures indicate ownership. +Every rule needs a **Name** that is unique within its panel. You cannot rename a rule after you create it. To rename a rule, delete it and add it again. -#### Examples +The Ownership Agent picks up saved rules automatically. Each resource keeps its current ownership suggestion until its next inference run. -- "The cost-center tag is the most reliable ownership signal for all cloud resources." -- "Team identifiers always use the team- prefix (for example, team-platform, team-data-eng)." -- "Resources in the us-east-1/prod account are managed by team-sre." +## Tag mappings -## Upload your ownership preferences +A tag mapping assigns an owner to resources that have a specific tag. When a resource's tag matches a mapping, the Ownership Agent adds the owner as a candidate and ranks it alongside other data sources. Tag mappings don't override a direct ownership tag (such as `dd-team`) already on the resource. -Datadog stores your preferences as a [reference table][1]. The table must be named `k9_ownership_preferences` and contain all 12 column headers, even if some rows leave them empty. +You can add up to 50 tag mappings. -There are several ways to create and update the table: +| Field | Description | +|---------------------------|--------------------------------------------------------------------------------------------------------------------------------------| +| **Confidence** | How strongly this mapping indicates ownership: **High**, **Medium**, or **Low** | +| **Tag key** | Tag key to match (for example, `cost-center`) | +| **Tag value** (optional) | Tag value to match. Leave empty to match any value for that key | +| **Owner type** (optional) | **User**, **Team**, or **Service**. Selecting a type filters the suggestions in the **Owner** field | +| **Owner** (optional) | Owner to assign. Pick a suggested team, user, or service, or type a handle. Leave empty to use the resource's tag value as the owner | -### Option 1: Manual CSV upload (Datadog UI) +Tag keys and values match case-insensitively. If several mappings match a resource, each one adds a candidate. -This approach is best for getting started or making occasional updates. +| Confidence | When to use | +|------------|-----------------------------------------------------------------------------------------------------------| +| **High** | The tag reliably identifies the owner. Example: a `cost-center` tag that maps 1:1 to a team | +| **Medium** | The tag is a good indicator but may not always be correct. Example: a `project` tag shared across teams | +| **Low** | The tag provides a hint but needs corroboration. Example: an `env` tag that loosely correlates with a team | -1. Prepare your CSV file (see [Complete example](#complete-example)). -2. In Datadog, go to **Integrations** > [**Reference Tables**][6]. -3. Click **New Reference Table**. -4. Upload your CSV file. -5. Set the table name to `k9_ownership_preferences`. -6. Choose `id` as the primary key. -7. Click **Save**. +For example, the following mappings assign resources by cost center, and use the value of any `squad` tag as the owning team: -To update your reference table, upload a new CSV to the same table to fully replace its contents. +| Name | Tag key | Tag value | Owner type | Owner | Confidence | +|----------|---------------|-----------|------------|-----------------|------------| +| `cc-100` | `cost-center` | `CC-100` | Team | `team-platform` | High | +| `squad` | `squad` | | Team | | Medium | -Manual uploads support files up to 4 MB. +With these rules, a resource tagged `squad:payments` gets `payments` as a team candidate. -### Option 2: Cloud storage sync (S3, Azure Blob, GCS) +## Exclusions -This approach is best for automated, recurring updates. Store your CSV in a cloud storage bucket so Datadog can periodically import it. +An exclusion prevents the Ownership Agent from suggesting a specific owner. Use exclusions for bot accounts, CI runners, and shared service accounts that appear in cloud resource metadata but don't own the resource. -1. Upload your CSV to an **Amazon S3 bucket**, **Azure Blob Storage container**, or **Google Cloud Storage bucket**. -2. In Datadog, go to **Integrations** > [**Reference Tables**][6]. -3. Click **New Reference Table** and select **Cloud Storage** as the source. -4. Provide the storage path and credentials (IAM role for S3, connection string for Azure, service account for GCS). -5. Set the table name to `k9_ownership_preferences`. -6. Choose `id` as the primary key. -7. Click **Save**. +You can add up to 20 exclusions. -Datadog periodically re-imports the file, so it automatically picks up updates to the CSV in your bucket. +| Field | Description | +|------------------------------|--------------------------------------------------------------------------------------------------------------| +| **Owner type** (optional) | Exclude only the owner for this type: **User**, **Team**, or **Service**. Leave empty to exclude it for any type | +| **Owner** | Owner to exclude (for example, `deploy-bot`). Matched case-insensitively | +| **Resource type** (optional) | Exclude only the owner for this resource type (for example, `aws_ec2_instance`). Leave empty for any type | -Cloud storage uploads support files up to 200 MB. +When you set both optional fields, the exclusion applies only when both match. The settings page shows empty optional fields as **Any**. For example: -See the [Reference Tables documentation][1] for detailed setup instructions per cloud provider. +| Name | Owner type | Owner | Resource type | +|----------------------|------------|--------------|--------------------| +| `exclude-deploy-bot` | Any | `deploy-bot` | Any | +| `exclude-legacy-ops` | Team | `legacy-ops` | `aws_ec2_instance` | -### Option 3: Terraform +The first rule removes `deploy-bot` from all results. The second removes the `legacy-ops` team only for EC2 instances. -This approach is best for managing preferences as infrastructure-as-code alongside your other Datadog resources. +## Custom instructions -The [Datadog Terraform provider][2] supports reference tables. Use it to create and update the table declaratively. +Custom instructions give the Ownership Agent context that you can't express as a tag mapping or exclusion. For example, describe naming conventions or which data sources to trust most. -For more information, see [datadog_reference_table (Resource)][7] in the Datadog Terraform provider documentation. +You can add up to three instructions of up to 4,000 characters each. Set an optional **Priority** (**High**, **Medium**, or **Low**) to control the order in which the agent reads them. Instructions without a priority come last, and every instruction is used. -### API +When you write instructions: -You can also manage reference tables programmatically through the [Reference Tables API][3]. See the API documentation for available endpoints. +- Be specific. "The `cost-center` tag is the most reliable ownership signal" is better than "Use tags." +- Use plain sentences that describe your organization. Markdown headings and HTML or XML tags are stripped. +- Don't include phrases that try to change the agent's behavior, such as "ignore previous instructions" or "act as". Datadog rejects them. +- Also add accounts that should never be owners as [exclusions](#exclusions). -Replace `api.datadoghq.com` with your [Datadog site URL][4] if applicable (for example, `api.datadoghq.eu`, `api.us3.datadoghq.com`). +For example: -## When preferences take effect +| Name | Priority | Instruction | +|--------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------| +| `cost-center-convention` | High | Ownership is assigned by cost center. Team identifiers always start with `team-` (for example, `team-platform`). | -1. You upload or update your reference table. -2. The Ownership Agent reads the table periodically (approximately once per day per organization). -3. The Ownership Agent validates the preferences in your table. If validation passes, the new preferences replace the previous set. -4. On the next ownership inference run for each resource: - - **Tag mappings** add ownership candidates based on your tag rules. - - **Exclusions** remove unwanted handles from results. - - **Custom prompt text** guides the AI inference engine. -5. Updated results appear in the Cloud Security posture management UI. +## Ownership preference validation rules -Changes to your reference table take effect within **24 hours**. +The settings page checks each rule before saving it and shows any problem next to the field. -
If you delete all rows from the table (leaving it empty), the Ownership Agent actively clears your previous preferences. Deleting the table entirely has the same effect—the cached preferences expire and are left empty.
+- Fields accept only the characters listed in the following table. Accented letters, emoji, and typographic (curly) quotes are not allowed. +- Fields are limited to 1,024 characters, and instructions to 4,000 characters. +- Two tag mappings with the same tag key and value must have the same owner and confidence. Exact duplicates are not allowed. +- An exclusion can't duplicate another exclusion with the same owner, owner type, and resource type. -## Troubleshooting +| Field | Allowed characters | +|-------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------| +| **Name** | Letters, digits, and `-` `_` `.` `:` `@` | +| **Tag key**, **Owner**, **Owner type**, **Resource type**, **Priority** | Letters, digits, and `-` `_` `.` `:` `/` `@` | +| **Tag value** | Letters, digits, spaces, and `-` `_` `.` `:` `/` `@` | +| **Instruction** | Letters, digits, spaces, line breaks, and `-` `_` `.` `:` `/` `@` `#` `,` `;` `!` `?` `(` `)` `'` `"` `` ` `` | -Validation is all-or-nothing. If any row has an issue, the Ownership Agent rejects the entire preference and leaves all preferences empty until you upload a valid set. +## Troubleshoot ownership preferences -| Problem | Likely cause | Fix | -|------------------------------------------|-----------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Preferences not in effect after 24 hours | Table name is wrong | Must be exactly `k9_ownership_preferences` | -| Preferences not in effect after 24 hours | Missing column headers | All 12 columns must exist as CSV headers, even if rows leave them empty | -| Preferences not in effect after 24 hours | Feature not enabled for your org | Contact [Datadog support][8] to enable ownership preferences | -| All preferences rejected | Invalid characters in any field | See [Allowed characters](#allowed-characters). Angle brackets, curly braces, and pipe characters are not permitted | -| All preferences rejected | Missing required field in any row | Check that `tag_key`, `owner`, `owner_type`, and `confidence` are populated for tag mappings; `handle` for exclusions; `prompt_text` for prompt text entries | -| All preferences rejected | Duplicate or conflicting rows | Two tag mappings with the same `tag_key`+`tag_value` but different `owner` or `confidence` values cause rejection. Exact duplicates of exclusions also cause rejection. See [Duplicate detection](#duplicate-detection) | -| All preferences rejected | Invalid `confidence` value | Must be exactly `high`, `medium`, or `low` | -| All preferences rejected | Invalid `owner_type` value | Must be `team`, `user`, or `service` (case-insensitive) | -| All preferences rejected | Size limit exceeded | Check row counts (50 tag mappings, 20 exclusions, three prompt text entries) and field lengths (1,024 bytes per field, 4,096 per prompt entry) | -| All preferences rejected | Prompt text formatting | Markdown headings and HTML/XML tags are stripped during processing. Use plain text only | -| Tag mapping not matching a resource | Spelling mismatch | Matching is case-insensitive, but verify the exact tag key and value on your resource | -| Exclusion not applied | Scoping filters too narrow | All non-empty fields must match (AND logic). Leave `exclusion_type` and `exclusion_resource_type` empty for broad exclusions | -| Preferences cleared unexpectedly | Table was emptied or deleted | Both an empty table and a deleted table cause cached preferences to expire. Upload a valid CSV to restore preferences | +| Problem | Fix | +|--------------------------------------------|----------------------------------------------------------------------------------------------------------------------------| +| A rule shows a warning icon and saving fails | Hover over the icon to see the problem, then edit the rule. If the problem is with the name, delete the rule and add it again | +| A tag mapping doesn't match a resource | Check the exact tag key and value on the resource | +| An exclusion isn't applied | Leave **Owner type** and **Resource type** empty unless you need to narrow the exclusion | ## Further reading {{< partial name="whats-next/whats-next.html" >}} -[1]: /integrations/guide/reference-tables/ -[2]: https://registry.terraform.io/providers/DataDog/datadog/latest/docs -[3]: /api/latest/reference-tables/ -[4]: /getting_started/site/ -[5]: https://github.com/datadog-labs/agent-skills/tree/main/dd-security/csm/ownership-agent -[6]: https://app.datadoghq.com/reference-tables -[7]: https://registry.terraform.io/providers/DataDog/datadog/latest/docs/resources/reference_table -[8]: /help \ No newline at end of file +[1]: https://app.datadoghq.com/security/configuration/csm/ownership-agent diff --git a/hugo/static/images/security/csm/ownership_preferences.png b/hugo/static/images/security/csm/ownership_preferences.png new file mode 100644 index 000000000000..88237998122c Binary files /dev/null and b/hugo/static/images/security/csm/ownership_preferences.png differ