diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index f5dd9090d3..dc2fd7efec 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -42088,12 +42088,14 @@ components: - INTEGRATION_KUBERNETES - INTEGRATION_SCRIPT - INTEGRATION_REMOTE_ACTION + - INTEGRATION_SLACK example: INTEGRATION_SCRIPT type: string x-enum-varnames: - INTEGRATION_KUBERNETES - INTEGRATION_SCRIPT - INTEGRATION_REMOTE_ACTION + - INTEGRATION_SLACK ExecutionPolicyKubernetesScope: description: Restricts the policy to specific Kubernetes namespaces. properties: @@ -42216,9 +42218,9 @@ components: type: object ExecutionPolicyScope: description: |- - Restricts where the policy applies. At most one of `kubernetes`, `scripts`, - or `remote_action_rshell` can be set. An empty object means the policy has - no scope restriction. + Restricts where the policy applies. At most one scope type can be set, + and it must match the action pattern's integration. An empty object means + the policy has no scope restriction. properties: kubernetes: $ref: "#/components/schemas/ExecutionPolicyKubernetesScope" @@ -42226,6 +42228,8 @@ components: $ref: "#/components/schemas/ExecutionPolicyRemoteActionRshellScope" scripts: $ref: "#/components/schemas/ExecutionPolicyScriptScope" + slack: + $ref: "#/components/schemas/ExecutionPolicySlackScope" type: object ExecutionPolicyScriptScope: description: Restricts the policy to specific scripts. @@ -42251,11 +42255,43 @@ components: required: - target_script_names type: object + ExecutionPolicySlackScope: + description: Restricts the policy to specific Slack private channel names. + properties: + rules: + description: The Slack scope rules. + items: + $ref: "#/components/schemas/ExecutionPolicySlackScopeRule" + minItems: 1 + type: array + required: + - rules + type: object + ExecutionPolicySlackScopeRule: + description: A rule restricting a Slack scope to specific private channel names. + properties: + channel_name_selectors: + description: |- + The private channel name selectors this rule applies to. Selectors are lowercase private channel names + without the leading `#`, and can contain `*` wildcards. Use `*` alone to match any private channel name. + example: + - "incident-*" + items: + maxLength: 80 + minLength: 1 + type: string + maxItems: 100 + minItems: 1 + type: array + uniqueItems: true + required: + - channel_name_selectors + type: object ExecutionPolicyTarget: - description: A target this policy is scoped to, expressed as a set of Agent tags. + description: A target this policy is scoped to, expressed as a set of tags. properties: agent_tags: - description: The Agent tags identifying the target. + description: The tags identifying the target. example: - "env:prod" items: @@ -255987,9 +256023,8 @@ tags: name: Events - description: |- Execution policies control which actions Datadog Action Platform is allowed to run - against your infrastructure, and where. Each policy pairs an effect (allow or deny) - with a pattern of actions, and can scope that decision to specific Kubernetes - namespaces, scripts, or remote shell paths. + and where. Each policy pairs an effect (allow or deny) with a pattern of actions, + and can scope that decision to specific resources. name: Execution Policy - description: Create and manage experiments, metrics, subject types, SQL models, and protocols. name: Experiments diff --git a/examples/v2/execution-policy/CreateExecutionPolicy_1868371302.py b/examples/v2/execution-policy/CreateExecutionPolicy_1868371302.py new file mode 100644 index 0000000000..fd3b27d8f8 --- /dev/null +++ b/examples/v2/execution-policy/CreateExecutionPolicy_1868371302.py @@ -0,0 +1,39 @@ +""" +Create a Slack execution policy returns "Created" response +""" + +from os import environ +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.execution_policy_api import ExecutionPolicyApi +from datadog_api_client.v2.model.execution_policy_action_pattern import ExecutionPolicyActionPattern +from datadog_api_client.v2.model.execution_policy_create_request import ExecutionPolicyCreateRequest +from datadog_api_client.v2.model.execution_policy_create_request_data import ExecutionPolicyCreateRequestData +from datadog_api_client.v2.model.execution_policy_effect import ExecutionPolicyEffect +from datadog_api_client.v2.model.execution_policy_integration import ExecutionPolicyIntegration +from datadog_api_client.v2.model.execution_policy_type import ExecutionPolicyType +from datadog_api_client.v2.model.execution_policy_write_attributes import ExecutionPolicyWriteAttributes + +body = ExecutionPolicyCreateRequest( + data=ExecutionPolicyCreateRequestData( + type=ExecutionPolicyType.EXECUTION_POLICY, + attributes=ExecutionPolicyWriteAttributes( + name="Cassette Execution Policy exampleexecutionpolicy", + effect=ExecutionPolicyEffect.ALLOW, + action_pattern=ExecutionPolicyActionPattern( + integration=ExecutionPolicyIntegration.INTEGRATION_SLACK, + action_fqns=[ + "com.datadoghq.slack.*", + ], + ), + ), + ), +) + +configuration = Configuration() +configuration.access_token = environ["DD_BEARER_TOKEN"] +configuration.unstable_operations["create_execution_policy"] = True +with ApiClient(configuration) as api_client: + api_instance = ExecutionPolicyApi(api_client) + response = api_instance.create_execution_policy(body=body) + + print(response) diff --git a/examples/v2/execution-policy/CreateExecutionPolicy_3240435177.py b/examples/v2/execution-policy/CreateExecutionPolicy_3240435177.py new file mode 100644 index 0000000000..4246612f0c --- /dev/null +++ b/examples/v2/execution-policy/CreateExecutionPolicy_3240435177.py @@ -0,0 +1,62 @@ +""" +Create a Slack execution policy with scope and targets returns "Created" response +""" + +from os import environ +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.execution_policy_api import ExecutionPolicyApi +from datadog_api_client.v2.model.execution_policy_action_pattern import ExecutionPolicyActionPattern +from datadog_api_client.v2.model.execution_policy_create_request import ExecutionPolicyCreateRequest +from datadog_api_client.v2.model.execution_policy_create_request_data import ExecutionPolicyCreateRequestData +from datadog_api_client.v2.model.execution_policy_effect import ExecutionPolicyEffect +from datadog_api_client.v2.model.execution_policy_integration import ExecutionPolicyIntegration +from datadog_api_client.v2.model.execution_policy_scope import ExecutionPolicyScope +from datadog_api_client.v2.model.execution_policy_slack_scope import ExecutionPolicySlackScope +from datadog_api_client.v2.model.execution_policy_slack_scope_rule import ExecutionPolicySlackScopeRule +from datadog_api_client.v2.model.execution_policy_target import ExecutionPolicyTarget +from datadog_api_client.v2.model.execution_policy_type import ExecutionPolicyType +from datadog_api_client.v2.model.execution_policy_write_attributes import ExecutionPolicyWriteAttributes + +body = ExecutionPolicyCreateRequest( + data=ExecutionPolicyCreateRequestData( + type=ExecutionPolicyType.EXECUTION_POLICY, + attributes=ExecutionPolicyWriteAttributes( + name="Cassette Execution Policy exampleexecutionpolicy", + effect=ExecutionPolicyEffect.ALLOW, + action_pattern=ExecutionPolicyActionPattern( + integration=ExecutionPolicyIntegration.INTEGRATION_SLACK, + action_fqns=[ + "com.datadoghq.slack.*", + ], + ), + scope=ExecutionPolicyScope( + slack=ExecutionPolicySlackScope( + rules=[ + ExecutionPolicySlackScopeRule( + channel_name_selectors=[ + "incident-*", + ], + ), + ], + ), + ), + targets=[ + ExecutionPolicyTarget( + name="Incident workspace", + agent_tags=[ + "slack_workspace_id:T01234567", + ], + ), + ], + ), + ), +) + +configuration = Configuration() +configuration.access_token = environ["DD_BEARER_TOKEN"] +configuration.unstable_operations["create_execution_policy"] = True +with ApiClient(configuration) as api_client: + api_instance = ExecutionPolicyApi(api_client) + response = api_instance.create_execution_policy(body=body) + + print(response) diff --git a/examples/v2/execution-policy/ListExecutionPolicies_4120778561.py b/examples/v2/execution-policy/ListExecutionPolicies_4120778561.py new file mode 100644 index 0000000000..6b74de764b --- /dev/null +++ b/examples/v2/execution-policy/ListExecutionPolicies_4120778561.py @@ -0,0 +1,21 @@ +""" +List execution policies filtered by Slack returns "OK" response +""" + +from os import environ +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.execution_policy_api import ExecutionPolicyApi +from datadog_api_client.v2.model.execution_policy_integration import ExecutionPolicyIntegration + +configuration = Configuration() +configuration.access_token = environ["DD_BEARER_TOKEN"] +configuration.unstable_operations["list_execution_policies"] = True +with ApiClient(configuration) as api_client: + api_instance = ExecutionPolicyApi(api_client) + response = api_instance.list_execution_policies( + filter_integration=[ + ExecutionPolicyIntegration.INTEGRATION_SLACK, + ], + ) + + print(response) diff --git a/examples/v2/execution-policy/UpdateExecutionPolicy_2851872075.py b/examples/v2/execution-policy/UpdateExecutionPolicy_2851872075.py new file mode 100644 index 0000000000..01735bffad --- /dev/null +++ b/examples/v2/execution-policy/UpdateExecutionPolicy_2851872075.py @@ -0,0 +1,66 @@ +""" +Update an execution policy to Slack with scope and targets returns "OK" response +""" + +from os import environ +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.execution_policy_api import ExecutionPolicyApi +from datadog_api_client.v2.model.execution_policy_action_pattern import ExecutionPolicyActionPattern +from datadog_api_client.v2.model.execution_policy_effect import ExecutionPolicyEffect +from datadog_api_client.v2.model.execution_policy_integration import ExecutionPolicyIntegration +from datadog_api_client.v2.model.execution_policy_scope import ExecutionPolicyScope +from datadog_api_client.v2.model.execution_policy_slack_scope import ExecutionPolicySlackScope +from datadog_api_client.v2.model.execution_policy_slack_scope_rule import ExecutionPolicySlackScopeRule +from datadog_api_client.v2.model.execution_policy_target import ExecutionPolicyTarget +from datadog_api_client.v2.model.execution_policy_type import ExecutionPolicyType +from datadog_api_client.v2.model.execution_policy_update_request import ExecutionPolicyUpdateRequest +from datadog_api_client.v2.model.execution_policy_update_request_data import ExecutionPolicyUpdateRequestData +from datadog_api_client.v2.model.execution_policy_write_attributes import ExecutionPolicyWriteAttributes + +# there is a valid "execution_policy" in the system +EXECUTION_POLICY_DATA_ID = environ["EXECUTION_POLICY_DATA_ID"] + +body = ExecutionPolicyUpdateRequest( + data=ExecutionPolicyUpdateRequestData( + id=EXECUTION_POLICY_DATA_ID, + type=ExecutionPolicyType.EXECUTION_POLICY, + attributes=ExecutionPolicyWriteAttributes( + name="Cassette Execution Policy Updated", + effect=ExecutionPolicyEffect.DENY, + action_pattern=ExecutionPolicyActionPattern( + integration=ExecutionPolicyIntegration.INTEGRATION_SLACK, + action_fqns=[ + "*", + ], + ), + scope=ExecutionPolicyScope( + slack=ExecutionPolicySlackScope( + rules=[ + ExecutionPolicySlackScopeRule( + channel_name_selectors=[ + "incident-denied", + ], + ), + ], + ), + ), + targets=[ + ExecutionPolicyTarget( + name="Incident workspace", + agent_tags=[ + "slack_workspace_id:T01234567", + ], + ), + ], + ), + ), +) + +configuration = Configuration() +configuration.access_token = environ["DD_BEARER_TOKEN"] +configuration.unstable_operations["update_execution_policy"] = True +with ApiClient(configuration) as api_client: + api_instance = ExecutionPolicyApi(api_client) + response = api_instance.update_execution_policy(policy_id=EXECUTION_POLICY_DATA_ID, body=body) + + print(response) diff --git a/src/datadog_api_client/v2/api/execution_policy_api.py b/src/datadog_api_client/v2/api/execution_policy_api.py index eceb195d29..0d0aea7033 100644 --- a/src/datadog_api_client/v2/api/execution_policy_api.py +++ b/src/datadog_api_client/v2/api/execution_policy_api.py @@ -22,9 +22,8 @@ class ExecutionPolicyApi: """ Execution policies control which actions Datadog Action Platform is allowed to run - against your infrastructure, and where. Each policy pairs an effect (allow or deny) - with a pattern of actions, and can scope that decision to specific Kubernetes - namespaces, scripts, or remote shell paths. + and where. Each policy pairs an effect (allow or deny) with a pattern of actions, + and can scope that decision to specific resources. """ def __init__(self, api_client=None): diff --git a/src/datadog_api_client/v2/model/execution_policy_attributes.py b/src/datadog_api_client/v2/model/execution_policy_attributes.py index 0404bfcca1..bd7cfc89e7 100644 --- a/src/datadog_api_client/v2/model/execution_policy_attributes.py +++ b/src/datadog_api_client/v2/model/execution_policy_attributes.py @@ -93,9 +93,9 @@ def __init__( :param name: The name of the execution policy. :type name: str - :param scope: Restricts where the policy applies. At most one of ``kubernetes`` , ``scripts`` , - or ``remote_action_rshell`` can be set. An empty object means the policy has - no scope restriction. + :param scope: Restricts where the policy applies. At most one scope type can be set, + and it must match the action pattern's integration. An empty object means + the policy has no scope restriction. :type scope: ExecutionPolicyScope, optional :param targets: The targets this policy applies to. diff --git a/src/datadog_api_client/v2/model/execution_policy_integration.py b/src/datadog_api_client/v2/model/execution_policy_integration.py index b6182fcfcd..d4d346651e 100644 --- a/src/datadog_api_client/v2/model/execution_policy_integration.py +++ b/src/datadog_api_client/v2/model/execution_policy_integration.py @@ -16,7 +16,7 @@ class ExecutionPolicyIntegration(ModelSimple): """ The integration the action pattern applies to. - :param value: Must be one of ["INTEGRATION_KUBERNETES", "INTEGRATION_SCRIPT", "INTEGRATION_REMOTE_ACTION"]. + :param value: Must be one of ["INTEGRATION_KUBERNETES", "INTEGRATION_SCRIPT", "INTEGRATION_REMOTE_ACTION", "INTEGRATION_SLACK"]. :type value: str """ @@ -24,10 +24,12 @@ class ExecutionPolicyIntegration(ModelSimple): "INTEGRATION_KUBERNETES", "INTEGRATION_SCRIPT", "INTEGRATION_REMOTE_ACTION", + "INTEGRATION_SLACK", } INTEGRATION_KUBERNETES: ClassVar["ExecutionPolicyIntegration"] INTEGRATION_SCRIPT: ClassVar["ExecutionPolicyIntegration"] INTEGRATION_REMOTE_ACTION: ClassVar["ExecutionPolicyIntegration"] + INTEGRATION_SLACK: ClassVar["ExecutionPolicyIntegration"] @cached_property def openapi_types(_): @@ -39,3 +41,4 @@ def openapi_types(_): ExecutionPolicyIntegration.INTEGRATION_KUBERNETES = ExecutionPolicyIntegration("INTEGRATION_KUBERNETES") ExecutionPolicyIntegration.INTEGRATION_SCRIPT = ExecutionPolicyIntegration("INTEGRATION_SCRIPT") ExecutionPolicyIntegration.INTEGRATION_REMOTE_ACTION = ExecutionPolicyIntegration("INTEGRATION_REMOTE_ACTION") +ExecutionPolicyIntegration.INTEGRATION_SLACK = ExecutionPolicyIntegration("INTEGRATION_SLACK") diff --git a/src/datadog_api_client/v2/model/execution_policy_scope.py b/src/datadog_api_client/v2/model/execution_policy_scope.py index e5a04e7687..877a73bee8 100644 --- a/src/datadog_api_client/v2/model/execution_policy_scope.py +++ b/src/datadog_api_client/v2/model/execution_policy_scope.py @@ -19,6 +19,7 @@ ExecutionPolicyRemoteActionRshellScope, ) from datadog_api_client.v2.model.execution_policy_script_scope import ExecutionPolicyScriptScope + from datadog_api_client.v2.model.execution_policy_slack_scope import ExecutionPolicySlackScope class ExecutionPolicyScope(ModelNormal): @@ -29,17 +30,20 @@ def openapi_types(_): ExecutionPolicyRemoteActionRshellScope, ) from datadog_api_client.v2.model.execution_policy_script_scope import ExecutionPolicyScriptScope + from datadog_api_client.v2.model.execution_policy_slack_scope import ExecutionPolicySlackScope return { "kubernetes": (ExecutionPolicyKubernetesScope,), "remote_action_rshell": (ExecutionPolicyRemoteActionRshellScope,), "scripts": (ExecutionPolicyScriptScope,), + "slack": (ExecutionPolicySlackScope,), } attribute_map = { "kubernetes": "kubernetes", "remote_action_rshell": "remote_action_rshell", "scripts": "scripts", + "slack": "slack", } def __init__( @@ -47,12 +51,13 @@ def __init__( kubernetes: Union[ExecutionPolicyKubernetesScope, UnsetType] = unset, remote_action_rshell: Union[ExecutionPolicyRemoteActionRshellScope, UnsetType] = unset, scripts: Union[ExecutionPolicyScriptScope, UnsetType] = unset, + slack: Union[ExecutionPolicySlackScope, UnsetType] = unset, **kwargs, ): """ - Restricts where the policy applies. At most one of ``kubernetes`` , ``scripts`` , - or ``remote_action_rshell`` can be set. An empty object means the policy has - no scope restriction. + Restricts where the policy applies. At most one scope type can be set, + and it must match the action pattern's integration. An empty object means + the policy has no scope restriction. :param kubernetes: Restricts the policy to specific Kubernetes namespaces. :type kubernetes: ExecutionPolicyKubernetesScope, optional @@ -62,6 +67,9 @@ def __init__( :param scripts: Restricts the policy to specific scripts. :type scripts: ExecutionPolicyScriptScope, optional + + :param slack: Restricts the policy to specific Slack private channel names. + :type slack: ExecutionPolicySlackScope, optional """ if kubernetes is not unset: kwargs["kubernetes"] = kubernetes @@ -69,4 +77,6 @@ def __init__( kwargs["remote_action_rshell"] = remote_action_rshell if scripts is not unset: kwargs["scripts"] = scripts + if slack is not unset: + kwargs["slack"] = slack super().__init__(kwargs) diff --git a/src/datadog_api_client/v2/model/execution_policy_slack_scope.py b/src/datadog_api_client/v2/model/execution_policy_slack_scope.py new file mode 100644 index 0000000000..7991d6fa33 --- /dev/null +++ b/src/datadog_api_client/v2/model/execution_policy_slack_scope.py @@ -0,0 +1,46 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.execution_policy_slack_scope_rule import ExecutionPolicySlackScopeRule + + +class ExecutionPolicySlackScope(ModelNormal): + validations = { + "rules": { + "min_items": 1, + }, + } + + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.execution_policy_slack_scope_rule import ExecutionPolicySlackScopeRule + + return { + "rules": ([ExecutionPolicySlackScopeRule],), + } + + attribute_map = { + "rules": "rules", + } + + def __init__(self_, rules: List[ExecutionPolicySlackScopeRule], **kwargs): + """ + Restricts the policy to specific Slack private channel names. + + :param rules: The Slack scope rules. + :type rules: [ExecutionPolicySlackScopeRule] + """ + super().__init__(kwargs) + + self_.rules = rules diff --git a/src/datadog_api_client/v2/model/execution_policy_slack_scope_rule.py b/src/datadog_api_client/v2/model/execution_policy_slack_scope_rule.py new file mode 100644 index 0000000000..4298e1bd71 --- /dev/null +++ b/src/datadog_api_client/v2/model/execution_policy_slack_scope_rule.py @@ -0,0 +1,42 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +class ExecutionPolicySlackScopeRule(ModelNormal): + validations = { + "channel_name_selectors": { + "max_items": 100, + "min_items": 1, + }, + } + + @cached_property + def openapi_types(_): + return { + "channel_name_selectors": ([str],), + } + + attribute_map = { + "channel_name_selectors": "channel_name_selectors", + } + + def __init__(self_, channel_name_selectors: List[str], **kwargs): + """ + A rule restricting a Slack scope to specific private channel names. + + :param channel_name_selectors: The private channel name selectors this rule applies to. Selectors are lowercase private channel names + without the leading ``#`` , and can contain ``*`` wildcards. Use ``*`` alone to match any private channel name. + :type channel_name_selectors: [str] + """ + super().__init__(kwargs) + + self_.channel_name_selectors = channel_name_selectors diff --git a/src/datadog_api_client/v2/model/execution_policy_target.py b/src/datadog_api_client/v2/model/execution_policy_target.py index c9b652c679..0d05aad91d 100644 --- a/src/datadog_api_client/v2/model/execution_policy_target.py +++ b/src/datadog_api_client/v2/model/execution_policy_target.py @@ -29,9 +29,9 @@ def openapi_types(_): def __init__(self_, agent_tags: List[str], name: Union[str, none_type, UnsetType] = unset, **kwargs): """ - A target this policy is scoped to, expressed as a set of Agent tags. + A target this policy is scoped to, expressed as a set of tags. - :param agent_tags: The Agent tags identifying the target. + :param agent_tags: The tags identifying the target. :type agent_tags: [str] :param name: A human-readable name for the target. diff --git a/src/datadog_api_client/v2/model/execution_policy_write_attributes.py b/src/datadog_api_client/v2/model/execution_policy_write_attributes.py index 8eb31cd718..d63a6b7e4a 100644 --- a/src/datadog_api_client/v2/model/execution_policy_write_attributes.py +++ b/src/datadog_api_client/v2/model/execution_policy_write_attributes.py @@ -65,9 +65,9 @@ def __init__( :param name: The name of the execution policy. :type name: str - :param scope: Restricts where the policy applies. At most one of ``kubernetes`` , ``scripts`` , - or ``remote_action_rshell`` can be set. An empty object means the policy has - no scope restriction. + :param scope: Restricts where the policy applies. At most one scope type can be set, + and it must match the action pattern's integration. An empty object means + the policy has no scope restriction. :type scope: ExecutionPolicyScope, optional :param targets: The targets this policy applies to. diff --git a/src/datadog_api_client/v2/models/__init__.py b/src/datadog_api_client/v2/models/__init__.py index eef8c21703..66758c8bbe 100644 --- a/src/datadog_api_client/v2/models/__init__.py +++ b/src/datadog_api_client/v2/models/__init__.py @@ -3342,6 +3342,8 @@ from datadog_api_client.v2.model.execution_policy_scope import ExecutionPolicyScope from datadog_api_client.v2.model.execution_policy_script_scope import ExecutionPolicyScriptScope from datadog_api_client.v2.model.execution_policy_script_scope_rule import ExecutionPolicyScriptScopeRule +from datadog_api_client.v2.model.execution_policy_slack_scope import ExecutionPolicySlackScope +from datadog_api_client.v2.model.execution_policy_slack_scope_rule import ExecutionPolicySlackScopeRule from datadog_api_client.v2.model.execution_policy_target import ExecutionPolicyTarget from datadog_api_client.v2.model.execution_policy_type import ExecutionPolicyType from datadog_api_client.v2.model.execution_policy_update_request import ExecutionPolicyUpdateRequest @@ -15501,6 +15503,8 @@ "ExecutionPolicyScope", "ExecutionPolicyScriptScope", "ExecutionPolicyScriptScopeRule", + "ExecutionPolicySlackScope", + "ExecutionPolicySlackScopeRule", "ExecutionPolicyTarget", "ExecutionPolicyType", "ExecutionPolicyUpdateRequest", diff --git a/tests/generated-test/test-runner-data/manifest.json b/tests/generated-test/test-runner-data/manifest.json index e760ee710f..8f52bf4529 100644 --- a/tests/generated-test/test-runner-data/manifest.json +++ b/tests/generated-test/test-runner-data/manifest.json @@ -5502,6 +5502,34 @@ "scenario": "Search events returns \"OK\" response with pagination", "version": "v2" }, + { + "feature": "Execution Policy", + "feature_file": "../../v2/features/execution_policy.feature", + "file": "v2/execution-policy/create-a-slack-execution-policy-returns-created-response.json", + "scenario": "Create a Slack execution policy returns \"Created\" response", + "version": "v2" + }, + { + "feature": "Execution Policy", + "feature_file": "../../v2/features/execution_policy.feature", + "file": "v2/execution-policy/create-a-slack-execution-policy-with-empty-channel-selectors-returns-bad-request-response.json", + "scenario": "Create a Slack execution policy with empty channel selectors returns \"Bad Request\" response", + "version": "v2" + }, + { + "feature": "Execution Policy", + "feature_file": "../../v2/features/execution_policy.feature", + "file": "v2/execution-policy/create-a-slack-execution-policy-with-mismatched-scope-returns-bad-request-response.json", + "scenario": "Create a Slack execution policy with mismatched scope returns \"Bad Request\" response", + "version": "v2" + }, + { + "feature": "Execution Policy", + "feature_file": "../../v2/features/execution_policy.feature", + "file": "v2/execution-policy/create-a-slack-execution-policy-with-scope-and-targets-returns-created-response.json", + "scenario": "Create a Slack execution policy with scope and targets returns \"Created\" response", + "version": "v2" + }, { "feature": "Execution Policy", "feature_file": "../../v2/features/execution_policy.feature", @@ -5551,6 +5579,13 @@ "scenario": "Get an execution policy returns \"OK\" response", "version": "v2" }, + { + "feature": "Execution Policy", + "feature_file": "../../v2/features/execution_policy.feature", + "file": "v2/execution-policy/list-execution-policies-filtered-by-slack-returns-ok-response.json", + "scenario": "List execution policies filtered by Slack returns \"OK\" response", + "version": "v2" + }, { "feature": "Execution Policy", "feature_file": "../../v2/features/execution_policy.feature", @@ -5593,6 +5628,13 @@ "scenario": "Update an execution policy returns \"OK\" response", "version": "v2" }, + { + "feature": "Execution Policy", + "feature_file": "../../v2/features/execution_policy.feature", + "file": "v2/execution-policy/update-an-execution-policy-to-slack-with-scope-and-targets-returns-ok-response.json", + "scenario": "Update an execution policy to Slack with scope and targets returns \"OK\" response", + "version": "v2" + }, { "feature": "Experiments", "feature_file": "../../v2/features/experiments.feature", diff --git a/tests/generated-test/test-runner-data/v2/execution-policy/create-a-slack-execution-policy-returns-created-response.json b/tests/generated-test/test-runner-data/v2/execution-policy/create-a-slack-execution-policy-returns-created-response.json new file mode 100644 index 0000000000..a753f54d84 --- /dev/null +++ b/tests/generated-test/test-runner-data/v2/execution-policy/create-a-slack-execution-policy-returns-created-response.json @@ -0,0 +1,40 @@ +{ + "api": "ExecutionPolicy", + "expected_status": 201, + "feature": "Execution Policy", + "id": "v2/Execution Policy/Create a Slack execution policy returns \"Created\" response", + "operation_id": "CreateExecutionPolicy", + "request": { + "body": { + "schema": { + "format": null, + "ref": "ExecutionPolicyCreateRequest", + "type": "object" + }, + "source": "inline", + "value": { + "data": { + "attributes": { + "action_pattern": { + "action_fqns": [ + "com.datadoghq.slack.*" + ], + "integration": "INTEGRATION_SLACK" + }, + "effect": "allow", + "name": "Cassette Execution Policy {{ unique_lower_alnum }}" + }, + "type": "execution_policy" + } + } + }, + "content_type": "application/json", + "method": "POST", + "pagination": false, + "parameters": [], + "path": "/api/v2/actions/execution-policies" + }, + "scenario": "Create a Slack execution policy returns \"Created\" response", + "schema_version": 1, + "version": "v2" +} diff --git a/tests/generated-test/test-runner-data/v2/execution-policy/create-a-slack-execution-policy-with-empty-channel-selectors-returns-bad-request-response.json b/tests/generated-test/test-runner-data/v2/execution-policy/create-a-slack-execution-policy-with-empty-channel-selectors-returns-bad-request-response.json new file mode 100644 index 0000000000..dc5b818e8f --- /dev/null +++ b/tests/generated-test/test-runner-data/v2/execution-policy/create-a-slack-execution-policy-with-empty-channel-selectors-returns-bad-request-response.json @@ -0,0 +1,49 @@ +{ + "api": "ExecutionPolicy", + "expected_status": 400, + "feature": "Execution Policy", + "id": "v2/Execution Policy/Create a Slack execution policy with empty channel selectors returns \"Bad Request\" response", + "operation_id": "CreateExecutionPolicy", + "request": { + "body": { + "schema": { + "format": null, + "ref": "ExecutionPolicyCreateRequest", + "type": "object" + }, + "source": "inline", + "value": { + "data": { + "attributes": { + "action_pattern": { + "action_fqns": [ + "com.datadoghq.slack.*" + ], + "integration": "INTEGRATION_SLACK" + }, + "effect": "allow", + "name": "Cassette Execution Policy {{ unique_lower_alnum }}", + "scope": { + "slack": { + "rules": [ + { + "channel_name_selectors": [] + } + ] + } + } + }, + "type": "execution_policy" + } + } + }, + "content_type": "application/json", + "method": "POST", + "pagination": false, + "parameters": [], + "path": "/api/v2/actions/execution-policies" + }, + "scenario": "Create a Slack execution policy with empty channel selectors returns \"Bad Request\" response", + "schema_version": 1, + "version": "v2" +} diff --git a/tests/generated-test/test-runner-data/v2/execution-policy/create-a-slack-execution-policy-with-mismatched-scope-returns-bad-request-response.json b/tests/generated-test/test-runner-data/v2/execution-policy/create-a-slack-execution-policy-with-mismatched-scope-returns-bad-request-response.json new file mode 100644 index 0000000000..8a403d635c --- /dev/null +++ b/tests/generated-test/test-runner-data/v2/execution-policy/create-a-slack-execution-policy-with-mismatched-scope-returns-bad-request-response.json @@ -0,0 +1,51 @@ +{ + "api": "ExecutionPolicy", + "expected_status": 400, + "feature": "Execution Policy", + "id": "v2/Execution Policy/Create a Slack execution policy with mismatched scope returns \"Bad Request\" response", + "operation_id": "CreateExecutionPolicy", + "request": { + "body": { + "schema": { + "format": null, + "ref": "ExecutionPolicyCreateRequest", + "type": "object" + }, + "source": "inline", + "value": { + "data": { + "attributes": { + "action_pattern": { + "action_fqns": [ + "com.datadoghq.slack.*" + ], + "integration": "INTEGRATION_SLACK" + }, + "effect": "allow", + "name": "Cassette Execution Policy {{ unique_lower_alnum }}", + "scope": { + "scripts": { + "rules": [ + { + "target_script_names": [ + "restart_service.sh" + ] + } + ] + } + } + }, + "type": "execution_policy" + } + } + }, + "content_type": "application/json", + "method": "POST", + "pagination": false, + "parameters": [], + "path": "/api/v2/actions/execution-policies" + }, + "scenario": "Create a Slack execution policy with mismatched scope returns \"Bad Request\" response", + "schema_version": 1, + "version": "v2" +} diff --git a/tests/generated-test/test-runner-data/v2/execution-policy/create-a-slack-execution-policy-with-scope-and-targets-returns-created-response.json b/tests/generated-test/test-runner-data/v2/execution-policy/create-a-slack-execution-policy-with-scope-and-targets-returns-created-response.json new file mode 100644 index 0000000000..5c3766cffa --- /dev/null +++ b/tests/generated-test/test-runner-data/v2/execution-policy/create-a-slack-execution-policy-with-scope-and-targets-returns-created-response.json @@ -0,0 +1,59 @@ +{ + "api": "ExecutionPolicy", + "expected_status": 201, + "feature": "Execution Policy", + "id": "v2/Execution Policy/Create a Slack execution policy with scope and targets returns \"Created\" response", + "operation_id": "CreateExecutionPolicy", + "request": { + "body": { + "schema": { + "format": null, + "ref": "ExecutionPolicyCreateRequest", + "type": "object" + }, + "source": "inline", + "value": { + "data": { + "attributes": { + "action_pattern": { + "action_fqns": [ + "com.datadoghq.slack.*" + ], + "integration": "INTEGRATION_SLACK" + }, + "effect": "allow", + "name": "Cassette Execution Policy {{ unique_lower_alnum }}", + "scope": { + "slack": { + "rules": [ + { + "channel_name_selectors": [ + "incident-*" + ] + } + ] + } + }, + "targets": [ + { + "agent_tags": [ + "slack_workspace_id:T01234567" + ], + "name": "Incident workspace" + } + ] + }, + "type": "execution_policy" + } + } + }, + "content_type": "application/json", + "method": "POST", + "pagination": false, + "parameters": [], + "path": "/api/v2/actions/execution-policies" + }, + "scenario": "Create a Slack execution policy with scope and targets returns \"Created\" response", + "schema_version": 1, + "version": "v2" +} diff --git a/tests/generated-test/test-runner-data/v2/execution-policy/list-execution-policies-filtered-by-slack-returns-ok-response.json b/tests/generated-test/test-runner-data/v2/execution-policy/list-execution-policies-filtered-by-slack-returns-ok-response.json new file mode 100644 index 0000000000..cd4cd82bb0 --- /dev/null +++ b/tests/generated-test/test-runner-data/v2/execution-policy/list-execution-policies-filtered-by-slack-returns-ok-response.json @@ -0,0 +1,42 @@ +{ + "api": "ExecutionPolicy", + "expected_status": 200, + "feature": "Execution Policy", + "id": "v2/Execution Policy/List execution policies filtered by Slack returns \"OK\" response", + "operation_id": "ListExecutionPolicies", + "request": { + "body": null, + "content_type": null, + "method": "GET", + "pagination": false, + "parameters": [ + { + "explode": true, + "in": "query", + "name": "filter[integration]", + "required": false, + "schema": { + "format": null, + "items": { + "format": null, + "ref": "ExecutionPolicyIntegration", + "type": "string" + }, + "ref": null, + "type": "array" + }, + "source": { + "type": "literal", + "value": [ + "INTEGRATION_SLACK" + ] + }, + "style": "form" + } + ], + "path": "/api/v2/actions/execution-policies" + }, + "scenario": "List execution policies filtered by Slack returns \"OK\" response", + "schema_version": 1, + "version": "v2" +} diff --git a/tests/generated-test/test-runner-data/v2/execution-policy/update-an-execution-policy-to-slack-with-scope-and-targets-returns-ok-response.json b/tests/generated-test/test-runner-data/v2/execution-policy/update-an-execution-policy-to-slack-with-scope-and-targets-returns-ok-response.json new file mode 100644 index 0000000000..49df041f32 --- /dev/null +++ b/tests/generated-test/test-runner-data/v2/execution-policy/update-an-execution-policy-to-slack-with-scope-and-targets-returns-ok-response.json @@ -0,0 +1,77 @@ +{ + "api": "ExecutionPolicy", + "expected_status": 200, + "feature": "Execution Policy", + "id": "v2/Execution Policy/Update an execution policy to Slack with scope and targets returns \"OK\" response", + "operation_id": "UpdateExecutionPolicy", + "request": { + "body": { + "schema": { + "format": null, + "ref": "ExecutionPolicyUpdateRequest", + "type": "object" + }, + "source": "inline", + "value": { + "data": { + "attributes": { + "action_pattern": { + "action_fqns": [ + "*" + ], + "integration": "INTEGRATION_SLACK" + }, + "effect": "deny", + "name": "Cassette Execution Policy Updated", + "scope": { + "slack": { + "rules": [ + { + "channel_name_selectors": [ + "incident-denied" + ] + } + ] + } + }, + "targets": [ + { + "agent_tags": [ + "slack_workspace_id:T01234567" + ], + "name": "Incident workspace" + } + ] + }, + "id": "{{ execution_policy.data.id }}", + "type": "execution_policy" + } + } + }, + "content_type": "application/json", + "method": "PUT", + "pagination": false, + "parameters": [ + { + "explode": null, + "in": "path", + "name": "policy_id", + "required": true, + "schema": { + "format": null, + "ref": null, + "type": "string" + }, + "source": { + "path": "execution_policy.data.id", + "type": "fixture" + }, + "style": null + } + ], + "path": "/api/v2/actions/execution-policies/{policy_id}" + }, + "scenario": "Update an execution policy to Slack with scope and targets returns \"OK\" response", + "schema_version": 1, + "version": "v2" +} diff --git a/tests/generated-test/test-server-data/v2/execution-policy.json b/tests/generated-test/test-server-data/v2/execution-policy.json index 1bd16ddff7..100f936d0f 100644 --- a/tests/generated-test/test-server-data/v2/execution-policy.json +++ b/tests/generated-test/test-server-data/v2/execution-policy.json @@ -1,6 +1,267 @@ { "feature": "Execution Policy", "recordings": [ + { + "feature": "Execution Policy", + "frozen_at": "2026-10-28T14:08:54.779Z", + "interactions": [ + { + "request": { + "body": { + "type": "json", + "value": { + "data": { + "attributes": { + "action_pattern": { + "action_fqns": [ + "com.datadoghq.slack.*" + ], + "integration": "INTEGRATION_SLACK" + }, + "effect": "allow", + "name": "Cassette Execution Policy testcreateaslackexecutionpolicyreturnscreatedresponse1793196534" + }, + "type": "execution_policy" + } + } + }, + "content_type": "application/json", + "method": "POST", + "path": "/api/v2/actions/execution-policies", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "{\"data\":{\"id\":\"1eca132c-5b3d-482a-a282-07393abdc9d5\",\"type\":\"execution_policy\",\"attributes\":{\"action_pattern\":{\"integration\":\"INTEGRATION_SLACK\",\"action_fqns\":[\"com.datadoghq.slack.*\"]},\"created_at\":\"2026-10-28T14:08:56Z\",\"created_by\":\"028000b7-d90f-4d20-b4a9-6ff4a83b7950\",\"effect\":\"allow\",\"name\":\"Cassette Execution Policy testcreateaslackexecutionpolicyreturnscreatedresponse1793196534\",\"targets\":[],\"updated_at\":\"2026-10-28T14:08:56Z\",\"updated_by\":\"028000b7-d90f-4d20-b4a9-6ff4a83b7950\",\"version\":1}}}" + }, + "headers": { + "content-type": "application/vnd.api+json" + }, + "reason": "Created", + "status": 201 + } + }, + { + "request": { + "body": { + "type": "empty", + "value": null + }, + "content_type": "", + "method": "DELETE", + "path": "/api/v2/actions/execution-policies/1eca132c-5b3d-482a-a282-07393abdc9d5", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "" + }, + "headers": {}, + "reason": "No Content", + "status": 204 + } + } + ], + "scenario": "Create a Slack execution policy returns \"Created\" response", + "version": "v2" + }, + { + "feature": "Execution Policy", + "frozen_at": "2026-10-28T14:08:56.579Z", + "interactions": [ + { + "request": { + "body": { + "type": "json", + "value": { + "data": { + "attributes": { + "action_pattern": { + "action_fqns": [ + "com.datadoghq.slack.*" + ], + "integration": "INTEGRATION_SLACK" + }, + "effect": "allow", + "name": "Cassette Execution Policy testcreateaslackexecutionpolicywithemptychannelselectorsreturnsbadrequestresponse1793196536", + "scope": { + "slack": { + "rules": [ + { + "channel_name_selectors": [] + } + ] + } + } + }, + "type": "execution_policy" + } + } + }, + "content_type": "application/json", + "method": "POST", + "path": "/api/v2/actions/execution-policies", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "{\"errors\":[{\"title\":\"Generic Error\",\"detail\":\"error creating execution policy\"}]}" + }, + "headers": { + "content-type": "application/vnd.api+json" + }, + "reason": "Bad Request", + "status": 400 + } + } + ], + "scenario": "Create a Slack execution policy with empty channel selectors returns \"Bad Request\" response", + "version": "v2" + }, + { + "feature": "Execution Policy", + "frozen_at": "2026-10-28T14:08:56.677Z", + "interactions": [ + { + "request": { + "body": { + "type": "json", + "value": { + "data": { + "attributes": { + "action_pattern": { + "action_fqns": [ + "com.datadoghq.slack.*" + ], + "integration": "INTEGRATION_SLACK" + }, + "effect": "allow", + "name": "Cassette Execution Policy testcreateaslackexecutionpolicywithmismatchedscopereturnsbadrequestresponse1793196536", + "scope": { + "scripts": { + "rules": [ + { + "target_script_names": [ + "restart_service.sh" + ] + } + ] + } + } + }, + "type": "execution_policy" + } + } + }, + "content_type": "application/json", + "method": "POST", + "path": "/api/v2/actions/execution-policies", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "{\"errors\":[{\"title\":\"Generic Error\",\"detail\":\"error creating execution policy\"}]}" + }, + "headers": { + "content-type": "application/vnd.api+json" + }, + "reason": "Bad Request", + "status": 400 + } + } + ], + "scenario": "Create a Slack execution policy with mismatched scope returns \"Bad Request\" response", + "version": "v2" + }, + { + "feature": "Execution Policy", + "frozen_at": "2026-10-28T14:08:56.739Z", + "interactions": [ + { + "request": { + "body": { + "type": "json", + "value": { + "data": { + "attributes": { + "action_pattern": { + "action_fqns": [ + "com.datadoghq.slack.*" + ], + "integration": "INTEGRATION_SLACK" + }, + "effect": "allow", + "name": "Cassette Execution Policy testcreateaslackexecutionpolicywithscopeandtargetsreturnscreatedresponse1793196536", + "scope": { + "slack": { + "rules": [ + { + "channel_name_selectors": [ + "incident-*" + ] + } + ] + } + }, + "targets": [ + { + "agent_tags": [ + "slack_workspace_id:T01234567" + ], + "name": "Incident workspace" + } + ] + }, + "type": "execution_policy" + } + } + }, + "content_type": "application/json", + "method": "POST", + "path": "/api/v2/actions/execution-policies", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "{\"data\":{\"id\":\"071e5ba3-ba19-4334-adf5-2da5298565f2\",\"type\":\"execution_policy\",\"attributes\":{\"action_pattern\":{\"integration\":\"INTEGRATION_SLACK\",\"action_fqns\":[\"com.datadoghq.slack.*\"]},\"created_at\":\"2026-10-28T14:08:56Z\",\"created_by\":\"028000b7-d90f-4d20-b4a9-6ff4a83b7950\",\"effect\":\"allow\",\"name\":\"Cassette Execution Policy testcreateaslackexecutionpolicywithscopeandtargetsreturnscreatedresponse1793196536\",\"scope\":{\"slack\":{\"rules\":[{\"channel_name_selectors\":[\"incident-*\"]}]}},\"targets\":[{\"agent_tags\":[\"slack_workspace_id:T01234567\"],\"name\":\"Incident workspace\"}],\"updated_at\":\"2026-10-28T14:08:56Z\",\"updated_by\":\"028000b7-d90f-4d20-b4a9-6ff4a83b7950\",\"version\":1}}}" + }, + "headers": { + "content-type": "application/vnd.api+json" + }, + "reason": "Created", + "status": 201 + } + }, + { + "request": { + "body": { + "type": "empty", + "value": null + }, + "content_type": "", + "method": "DELETE", + "path": "/api/v2/actions/execution-policies/071e5ba3-ba19-4334-adf5-2da5298565f2", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "" + }, + "headers": {}, + "reason": "No Content", + "status": 204 + } + } + ], + "scenario": "Create a Slack execution policy with scope and targets returns \"Created\" response", + "version": "v2" + }, { "feature": "Execution Policy", "frozen_at": "2026-08-14T09:13:38.368Z", @@ -437,6 +698,42 @@ "scenario": "Get an execution policy returns \"OK\" response", "version": "v2" }, + { + "feature": "Execution Policy", + "frozen_at": "2026-10-28T14:08:56.947Z", + "interactions": [ + { + "request": { + "body": { + "type": "empty", + "value": null + }, + "content_type": "", + "method": "GET", + "path": "/api/v2/actions/execution-policies", + "query": [ + [ + "filter[integration]", + "INTEGRATION_SLACK" + ] + ] + }, + "response": { + "body": { + "encoding": "text", + "value": "{\"data\":[],\"meta\":{\"page\":{\"total\":0}}}" + }, + "headers": { + "content-type": "application/vnd.api+json" + }, + "reason": "OK", + "status": 200 + } + } + ], + "scenario": "List execution policies filtered by Slack returns \"OK\" response", + "version": "v2" + }, { "feature": "Execution Policy", "frozen_at": "2026-08-14T09:13:43.018Z", @@ -937,6 +1234,129 @@ ], "scenario": "Update an execution policy returns \"OK\" response", "version": "v2" + }, + { + "feature": "Execution Policy", + "frozen_at": "2026-10-28T14:08:57.019Z", + "interactions": [ + { + "request": { + "body": { + "type": "json", + "value": { + "data": { + "attributes": { + "action_pattern": { + "action_fqns": [ + "com.datadoghq.script.*" + ], + "integration": "INTEGRATION_SCRIPT" + }, + "effect": "allow", + "name": "Cassette Execution Policy testupdateanexecutionpolicytoslackwithscopeandtargetsreturnsokresponse1793196537" + }, + "type": "execution_policy" + } + } + }, + "content_type": "application/json", + "method": "POST", + "path": "/api/v2/actions/execution-policies", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "{\"data\":{\"id\":\"010051ac-04d3-4852-8598-fc620a84ef45\",\"type\":\"execution_policy\",\"attributes\":{\"action_pattern\":{\"integration\":\"INTEGRATION_SCRIPT\",\"action_fqns\":[\"com.datadoghq.script.*\"]},\"created_at\":\"2026-10-28T14:08:57Z\",\"created_by\":\"028000b7-d90f-4d20-b4a9-6ff4a83b7950\",\"effect\":\"allow\",\"name\":\"Cassette Execution Policy testupdateanexecutionpolicytoslackwithscopeandtargetsreturnsokresponse1793196537\",\"targets\":[],\"updated_at\":\"2026-10-28T14:08:57Z\",\"updated_by\":\"028000b7-d90f-4d20-b4a9-6ff4a83b7950\",\"version\":1}}}" + }, + "headers": { + "content-type": "application/vnd.api+json" + }, + "reason": "Created", + "status": 201 + } + }, + { + "request": { + "body": { + "type": "json", + "value": { + "data": { + "attributes": { + "action_pattern": { + "action_fqns": [ + "*" + ], + "integration": "INTEGRATION_SLACK" + }, + "effect": "deny", + "name": "Cassette Execution Policy Updated", + "scope": { + "slack": { + "rules": [ + { + "channel_name_selectors": [ + "incident-denied" + ] + } + ] + } + }, + "targets": [ + { + "agent_tags": [ + "slack_workspace_id:T01234567" + ], + "name": "Incident workspace" + } + ] + }, + "id": "010051ac-04d3-4852-8598-fc620a84ef45", + "type": "execution_policy" + } + } + }, + "content_type": "application/json", + "method": "PUT", + "path": "/api/v2/actions/execution-policies/010051ac-04d3-4852-8598-fc620a84ef45", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "{\"data\":{\"id\":\"010051ac-04d3-4852-8598-fc620a84ef45\",\"type\":\"execution_policy\",\"attributes\":{\"action_pattern\":{\"integration\":\"INTEGRATION_SLACK\",\"action_fqns\":[\"*\"]},\"created_at\":\"2026-10-28T14:08:57Z\",\"created_by\":\"028000b7-d90f-4d20-b4a9-6ff4a83b7950\",\"effect\":\"deny\",\"name\":\"Cassette Execution Policy Updated\",\"scope\":{\"slack\":{\"rules\":[{\"channel_name_selectors\":[\"incident-denied\"]}]}},\"targets\":[{\"agent_tags\":[\"slack_workspace_id:T01234567\"],\"name\":\"Incident workspace\"}],\"updated_at\":\"2026-10-28T14:08:57Z\",\"updated_by\":\"028000b7-d90f-4d20-b4a9-6ff4a83b7950\",\"version\":2}}}" + }, + "headers": { + "content-type": "application/vnd.api+json" + }, + "reason": "OK", + "status": 200 + } + }, + { + "request": { + "body": { + "type": "empty", + "value": null + }, + "content_type": "", + "method": "DELETE", + "path": "/api/v2/actions/execution-policies/010051ac-04d3-4852-8598-fc620a84ef45", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "" + }, + "headers": {}, + "reason": "No Content", + "status": 204 + } + } + ], + "scenario": "Update an execution policy to Slack with scope and targets returns \"OK\" response", + "version": "v2" } ], "schema_version": 1, diff --git a/tests/v2/features/execution_policy.feature b/tests/v2/features/execution_policy.feature index 9b78c97c40..11ae23d763 100644 --- a/tests/v2/features/execution_policy.feature +++ b/tests/v2/features/execution_policy.feature @@ -1,16 +1,51 @@ @endpoint(execution-policy) @endpoint(execution-policy-v2) Feature: Execution Policy Execution policies control which actions Datadog Action Platform is - allowed to run against your infrastructure, and where. Each policy pairs - an effect (allow or deny) with a pattern of actions, and can scope that - decision to specific Kubernetes namespaces, scripts, or remote shell - paths. + allowed to run and where. Each policy pairs an effect (allow or deny) with + a pattern of actions, and can scope that decision to specific resources. Background: Given a valid "apiKeyAuth" key in the system And a valid "appKeyAuth" key in the system And an instance of "ExecutionPolicy" API + @team:ddoghq/action-platform + Scenario: Create a Slack execution policy returns "Created" response + Given operation "CreateExecutionPolicy" enabled + And new "CreateExecutionPolicy" request + And body with value {"data": {"type": "execution_policy", "attributes": {"name": "Cassette Execution Policy {{ unique_lower_alnum }}", "effect": "allow", "action_pattern": {"integration": "INTEGRATION_SLACK", "action_fqns": ["com.datadoghq.slack.*"]}}}} + When the request is sent + Then the response status is 201 Created + And the response "data.attributes.action_pattern.integration" is equal to "INTEGRATION_SLACK" + And the response "data.attributes.targets" is equal to [] + + @skip-python @skip-ruby @team:ddoghq/action-platform + Scenario: Create a Slack execution policy with empty channel selectors returns "Bad Request" response + Given operation "CreateExecutionPolicy" enabled + And new "CreateExecutionPolicy" request + And body with value {"data": {"type": "execution_policy", "attributes": {"name": "Cassette Execution Policy {{ unique_lower_alnum }}", "effect": "allow", "action_pattern": {"integration": "INTEGRATION_SLACK", "action_fqns": ["com.datadoghq.slack.*"]}, "scope": {"slack": {"rules": [{"channel_name_selectors": []}]}}}}} + When the request is sent + Then the response status is 400 Bad Request + + @team:ddoghq/action-platform + Scenario: Create a Slack execution policy with mismatched scope returns "Bad Request" response + Given operation "CreateExecutionPolicy" enabled + And new "CreateExecutionPolicy" request + And body with value {"data": {"type": "execution_policy", "attributes": {"name": "Cassette Execution Policy {{ unique_lower_alnum }}", "effect": "allow", "action_pattern": {"integration": "INTEGRATION_SLACK", "action_fqns": ["com.datadoghq.slack.*"]}, "scope": {"scripts": {"rules": [{"target_script_names": ["restart_service.sh"]}]}}}}} + When the request is sent + Then the response status is 400 Bad Request + + @team:ddoghq/action-platform + Scenario: Create a Slack execution policy with scope and targets returns "Created" response + Given operation "CreateExecutionPolicy" enabled + And new "CreateExecutionPolicy" request + And body with value {"data": {"type": "execution_policy", "attributes": {"name": "Cassette Execution Policy {{ unique_lower_alnum }}", "effect": "allow", "action_pattern": {"integration": "INTEGRATION_SLACK", "action_fqns": ["com.datadoghq.slack.*"]}, "scope": {"slack": {"rules": [{"channel_name_selectors": ["incident-*"]}]}}, "targets": [{"name": "Incident workspace", "agent_tags": ["slack_workspace_id:T01234567"]}]}}} + When the request is sent + Then the response status is 201 Created + And the response "data.attributes.action_pattern.integration" is equal to "INTEGRATION_SLACK" + And the response "data.attributes.scope.slack.rules" is equal to [{"channel_name_selectors": ["incident-*"]}] + And the response "data.attributes.targets" is equal to [{"name": "Incident workspace", "agent_tags": ["slack_workspace_id:T01234567"]}] + @team:ddoghq/action-platform Scenario: Create an execution policy returns "Bad Request" response Given operation "CreateExecutionPolicy" enabled @@ -69,6 +104,14 @@ Feature: Execution Policy When the request is sent Then the response status is 200 OK + @team:ddoghq/action-platform + Scenario: List execution policies filtered by Slack returns "OK" response + Given operation "ListExecutionPolicies" enabled + And new "ListExecutionPolicies" request + And request contains "filter[integration]" parameter with value ["INTEGRATION_SLACK"] + When the request is sent + Then the response status is 200 OK + @team:ddoghq/action-platform Scenario: List execution policies returns "Bad Request" response Given operation "ListExecutionPolicies" enabled @@ -129,3 +172,17 @@ Feature: Execution Policy And body with value {"data": {"id": "{{ execution_policy.data.id }}", "type": "execution_policy", "attributes": {"name": "Cassette Execution Policy Updated", "effect": "allow", "action_pattern": {"integration": "INTEGRATION_SCRIPT", "action_fqns": ["com.datadoghq.script.*"]}}}} When the request is sent Then the response status is 200 OK + + @team:ddoghq/action-platform + Scenario: Update an execution policy to Slack with scope and targets returns "OK" response + Given there is a valid "execution_policy" in the system + And operation "UpdateExecutionPolicy" enabled + And new "UpdateExecutionPolicy" request + And request contains "policy_id" parameter from "execution_policy.data.id" + And body with value {"data": {"id": "{{ execution_policy.data.id }}", "type": "execution_policy", "attributes": {"name": "Cassette Execution Policy Updated", "effect": "deny", "action_pattern": {"integration": "INTEGRATION_SLACK", "action_fqns": ["*"]}, "scope": {"slack": {"rules": [{"channel_name_selectors": ["incident-denied"]}]}}, "targets": [{"name": "Incident workspace", "agent_tags": ["slack_workspace_id:T01234567"]}]}}} + When the request is sent + Then the response status is 200 OK + And the response "data.attributes.effect" is equal to "deny" + And the response "data.attributes.action_pattern.integration" is equal to "INTEGRATION_SLACK" + And the response "data.attributes.scope.slack.rules" is equal to [{"channel_name_selectors": ["incident-denied"]}] + And the response "data.attributes.targets" is equal to [{"name": "Incident workspace", "agent_tags": ["slack_workspace_id:T01234567"]}]