diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 6cd7c2ab9e..ac902f638a 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -13758,7 +13758,8 @@ components: description: Attributes of the Jira issue to create. properties: assignee_id: - description: Unique identifier of the user assigned to the Jira issue. + description: Unique identifier of the Datadog user assigned to the Jira + issue. example: f315bdaf-9ee7-4808-a9c1-99c15bf0f4d0 type: string description: @@ -13779,8 +13780,9 @@ components: type: object priority: $ref: '#/components/schemas/CasePriority' - description: Priority of the Jira issue. If not provided, the priority will - be automatically set to "NOT_DEFINED". + description: Datadog case priority mapped to the Jira issue priority. If + not provided, the priority will be automatically set to "NOT_DEFINED". + To configure the mapping, see [Bidirectional ticket syncing with Jira](https://docs.datadoghq.com/security/ticketing_integrations/#bidirectional-ticket-syncing-with-jira). example: P4 title: description: Title of the Jira issue. If not provided, the title will be @@ -87136,9 +87138,6 @@ paths: permissions: - security_monitoring_findings_write - appsec_vm_write - x-unstable: '**Note**: This endpoint is in beta and is subject to change. - - Please check the documentation regularly for updates.' post: description: 'Create Jira issues for security findings. @@ -87182,9 +87181,6 @@ paths: permissions: - security_monitoring_findings_write - appsec_vm_write - x-unstable: '**Note**: This endpoint is in beta and is subject to change. - - Please check the documentation regularly for updates.' /api/v2/security/findings/search: post: description: 'Get a list of security findings that match a search query. [See diff --git a/examples/v2/security-monitoring/CreateJiraIssues.py b/examples/v2/security-monitoring/CreateJiraIssues.py index e4529c66c5..f389861d89 100644 --- a/examples/v2/security-monitoring/CreateJiraIssues.py +++ b/examples/v2/security-monitoring/CreateJiraIssues.py @@ -7,7 +7,6 @@ from datadog_api_client.v2.model.case_management_project import CaseManagementProject from datadog_api_client.v2.model.case_management_project_data import CaseManagementProjectData from datadog_api_client.v2.model.case_management_project_data_type import CaseManagementProjectDataType -from datadog_api_client.v2.model.case_priority import CasePriority from datadog_api_client.v2.model.create_jira_issue_request_array import CreateJiraIssueRequestArray from datadog_api_client.v2.model.create_jira_issue_request_data import CreateJiraIssueRequestData from datadog_api_client.v2.model.create_jira_issue_request_data_attributes import CreateJiraIssueRequestDataAttributes @@ -23,24 +22,44 @@ data=[ CreateJiraIssueRequestData( attributes=CreateJiraIssueRequestDataAttributes( - assignee_id="f315bdaf-9ee7-4808-a9c1-99c15bf0f4d0", - description="A description of the Jira issue.", - fields=dict([("key1", "value"), ("key2", "['value']"), ("key3", "{'key4': 'value'}")]), - priority=CasePriority.NOT_DEFINED, - title="A title for the Jira issue.", + title="A title", + description="A description", ), relationships=CreateJiraIssueRequestDataRelationships( findings=Findings( data=[ FindingData( - id="ZGVmLTAwcC1pZXJ-aS0wZjhjNjMyZDNmMzRlZTgzNw==", + id="eWswLWJsdC1hZm5-aS0wMjRlYTgwMzVkZTU1MGIwYQ==", type=FindingDataType.FINDINGS, ), ], ), project=CaseManagementProject( data=CaseManagementProjectData( - id="aeadc05e-98a8-11ec-ac2c-da7ad0900001", + id="959a6f71-bac8-4027-b1d3-2264f569296f", + type=CaseManagementProjectDataType.PROJECTS, + ), + ), + ), + type=JiraIssuesDataType.JIRA_ISSUES, + ), + CreateJiraIssueRequestData( + attributes=CreateJiraIssueRequestDataAttributes( + title="A title", + description="A description", + ), + relationships=CreateJiraIssueRequestDataRelationships( + findings=Findings( + data=[ + FindingData( + id="a3ZoLXNjbS14eXV-aS0wNWY5MGYwMGE4NDg2ODdlOA==", + type=FindingDataType.FINDINGS, + ), + ], + ), + project=CaseManagementProject( + data=CaseManagementProjectData( + id="959a6f71-bac8-4027-b1d3-2264f569296f", type=CaseManagementProjectDataType.PROJECTS, ), ), @@ -51,7 +70,6 @@ ) configuration = Configuration() -configuration.unstable_operations["create_jira_issues"] = True with ApiClient(configuration) as api_client: api_instance = SecurityMonitoringApi(api_client) response = api_instance.create_jira_issues(body=body) diff --git a/examples/v2/security-monitoring/CreateJiraIssues_379590688.py b/examples/v2/security-monitoring/CreateJiraIssues_379590688.py new file mode 100644 index 0000000000..bd49a4d374 --- /dev/null +++ b/examples/v2/security-monitoring/CreateJiraIssues_379590688.py @@ -0,0 +1,54 @@ +""" +Create Jira issue for security finding returns "Created" response +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.security_monitoring_api import SecurityMonitoringApi +from datadog_api_client.v2.model.case_management_project import CaseManagementProject +from datadog_api_client.v2.model.case_management_project_data import CaseManagementProjectData +from datadog_api_client.v2.model.case_management_project_data_type import CaseManagementProjectDataType +from datadog_api_client.v2.model.create_jira_issue_request_array import CreateJiraIssueRequestArray +from datadog_api_client.v2.model.create_jira_issue_request_data import CreateJiraIssueRequestData +from datadog_api_client.v2.model.create_jira_issue_request_data_attributes import CreateJiraIssueRequestDataAttributes +from datadog_api_client.v2.model.create_jira_issue_request_data_relationships import ( + CreateJiraIssueRequestDataRelationships, +) +from datadog_api_client.v2.model.finding_data import FindingData +from datadog_api_client.v2.model.finding_data_type import FindingDataType +from datadog_api_client.v2.model.findings import Findings +from datadog_api_client.v2.model.jira_issues_data_type import JiraIssuesDataType + +body = CreateJiraIssueRequestArray( + data=[ + CreateJiraIssueRequestData( + attributes=CreateJiraIssueRequestDataAttributes( + title="A title", + description="A description", + ), + relationships=CreateJiraIssueRequestDataRelationships( + findings=Findings( + data=[ + FindingData( + id="YmNlZmJhYTcyMDU5ZDk0ZDhiNjRmNGI0NDk4MDdiNzN-MDJlMjg0NzNmYzJiODY2MzJkNjU0OTI4NmVhZTUyY2U=", + type=FindingDataType.FINDINGS, + ), + ], + ), + project=CaseManagementProject( + data=CaseManagementProjectData( + id="959a6f71-bac8-4027-b1d3-2264f569296f", + type=CaseManagementProjectDataType.PROJECTS, + ), + ), + ), + type=JiraIssuesDataType.JIRA_ISSUES, + ), + ], +) + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = SecurityMonitoringApi(api_client) + response = api_instance.create_jira_issues(body=body) + + print(response) diff --git a/examples/v2/security-monitoring/CreateJiraIssues_829823123.py b/examples/v2/security-monitoring/CreateJiraIssues_829823123.py new file mode 100644 index 0000000000..8e9e77a52b --- /dev/null +++ b/examples/v2/security-monitoring/CreateJiraIssues_829823123.py @@ -0,0 +1,58 @@ +""" +Create Jira issue for security findings returns "Created" response +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.security_monitoring_api import SecurityMonitoringApi +from datadog_api_client.v2.model.case_management_project import CaseManagementProject +from datadog_api_client.v2.model.case_management_project_data import CaseManagementProjectData +from datadog_api_client.v2.model.case_management_project_data_type import CaseManagementProjectDataType +from datadog_api_client.v2.model.create_jira_issue_request_array import CreateJiraIssueRequestArray +from datadog_api_client.v2.model.create_jira_issue_request_data import CreateJiraIssueRequestData +from datadog_api_client.v2.model.create_jira_issue_request_data_attributes import CreateJiraIssueRequestDataAttributes +from datadog_api_client.v2.model.create_jira_issue_request_data_relationships import ( + CreateJiraIssueRequestDataRelationships, +) +from datadog_api_client.v2.model.finding_data import FindingData +from datadog_api_client.v2.model.finding_data_type import FindingDataType +from datadog_api_client.v2.model.findings import Findings +from datadog_api_client.v2.model.jira_issues_data_type import JiraIssuesDataType + +body = CreateJiraIssueRequestArray( + data=[ + CreateJiraIssueRequestData( + attributes=CreateJiraIssueRequestDataAttributes( + title="A title", + description="A description", + ), + relationships=CreateJiraIssueRequestDataRelationships( + findings=Findings( + data=[ + FindingData( + id="a3ZoLXNjbS14eXV-aS0wNWY5MGYwMGE4NDg2ODdlOA==", + type=FindingDataType.FINDINGS, + ), + FindingData( + id="eWswLWJsdC1hZm5-aS0wMjRlYTgwMzVkZTU1MGIwYQ==", + type=FindingDataType.FINDINGS, + ), + ], + ), + project=CaseManagementProject( + data=CaseManagementProjectData( + id="959a6f71-bac8-4027-b1d3-2264f569296f", + type=CaseManagementProjectDataType.PROJECTS, + ), + ), + ), + type=JiraIssuesDataType.JIRA_ISSUES, + ), + ], +) + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = SecurityMonitoringApi(api_client) + response = api_instance.create_jira_issues(body=body) + + print(response) diff --git a/src/datadog_api_client/configuration.py b/src/datadog_api_client/configuration.py index 0bb7b63ec1..9004223880 100644 --- a/src/datadog_api_client/configuration.py +++ b/src/datadog_api_client/configuration.py @@ -266,10 +266,8 @@ def __init__( "v2.get_open_api": False, "v2.list_apis": False, "v2.update_open_api": False, - "v2.attach_jira_issue": False, "v2.cancel_threat_hunting_job": False, "v2.convert_job_result_to_signal": False, - "v2.create_jira_issues": False, "v2.delete_threat_hunting_job": False, "v2.get_finding": False, "v2.get_rule_version_history": False, diff --git a/src/datadog_api_client/v2/model/create_jira_issue_request_data_attributes.py b/src/datadog_api_client/v2/model/create_jira_issue_request_data_attributes.py index 58571e8fbf..e4b070f0d8 100644 --- a/src/datadog_api_client/v2/model/create_jira_issue_request_data_attributes.py +++ b/src/datadog_api_client/v2/model/create_jira_issue_request_data_attributes.py @@ -69,7 +69,7 @@ def __init__( """ Attributes of the Jira issue to create. - :param assignee_id: Unique identifier of the user assigned to the Jira issue. + :param assignee_id: Unique identifier of the Datadog user assigned to the Jira issue. :type assignee_id: str, optional :param description: Description of the Jira issue. If not provided, the description will be automatically generated. diff --git a/tests/v2/cassettes/test_scenarios/test_create_jira_issue_for_security_finding_returns_created_response.frozen b/tests/v2/cassettes/test_scenarios/test_create_jira_issue_for_security_finding_returns_created_response.frozen new file mode 100644 index 0000000000..a96661d790 --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_create_jira_issue_for_security_finding_returns_created_response.frozen @@ -0,0 +1 @@ +2026-01-02T17:04:07.979Z \ No newline at end of file diff --git a/tests/v2/cassettes/test_scenarios/test_create_jira_issue_for_security_finding_returns_created_response.yaml b/tests/v2/cassettes/test_scenarios/test_create_jira_issue_for_security_finding_returns_created_response.yaml new file mode 100644 index 0000000000..e7dba5654c --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_create_jira_issue_for_security_finding_returns_created_response.yaml @@ -0,0 +1,38 @@ +interactions: +- request: + body: '{"data":[{"attributes":{"description":"A description","title":"A title"},"relationships":{"findings":{"data":[{"id":"YmNlZmJhYTcyMDU5ZDk0ZDhiNjRmNGI0NDk4MDdiNzN-MDJlMjg0NzNmYzJiODY2MzJkNjU0OTI4NmVhZTUyY2U=","type":"findings"}]},"project":{"data":{"id":"959a6f71-bac8-4027-b1d3-2264f569296f","type":"projects"}}},"type":"jira_issues"}]}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/security/findings/jira_issues + response: + body: + string: '{"data":[{"id":"b5b9ee39-29f8-4b84-a878-28e597e2a33f","type":"cases","attributes":{"created_at":"2026-01-02T17:04:10.514692Z","creation_source":"CS_SECURITY_FINDING","description":"A + description","insights":[{"type":"SECURITY_FINDING","ref":"/security/csm/vm?query=%40workflow.integrations.cases.id%3A%2A\u0026vulnerability=bcefbaa72059d94d8b64f4b449807b73","resource_id":"YmNlZmJhYTcyMDU5ZDk0ZDhiNjRmNGI0NDk4MDdiNzN-MDJlMjg0NzNmYzJiODY2MzJkNjU0OTI4NmVhZTUyY2U="}],"jira_issue":{"status":"COMPLETED","result":{"issue_id":"2523546","issue_key":"CSMSEC-105847","issue_url":"https://datadoghq-sandbox-538.atlassian.net/browse/CSMSEC-105847","account_id":"fdcffa62-24ab-4914-a195-a22bdc607030"}},"key":"CSMINV-521","modified_at":"2026-01-02T17:04:11.504549Z","priority":"P4","status":"OPEN","status_group":"SG_OPEN","status_name":"Open","title":"A + title","type":"SECURITY"},"relationships":{"created_by":{"data":{"id":"dc09afab-6ae7-11ef-92b1-828dac1b0195","type":"users"}},"project":{"data":{"id":"959a6f71-bac8-4027-b1d3-2264f569296f","type":"projects"}}}}]}' + headers: + content-type: + - application/vnd.api+json + status: + code: 201 + message: Created +- request: + body: '{"data":{"relationships":{"findings":{"data":[{"id":"YmNlZmJhYTcyMDU5ZDk0ZDhiNjRmNGI0NDk4MDdiNzN-MDJlMjg0NzNmYzJiODY2MzJkNjU0OTI4NmVhZTUyY2U=","type":"findings"}]}},"type":"cases"}}' + headers: + accept: + - '*/*' + content-type: + - application/json + method: DELETE + uri: https://api.datadoghq.com/api/v2/security/findings/cases + response: + body: + string: '' + headers: {} + status: + code: 204 + message: No Content +version: 1 diff --git a/tests/v2/cassettes/test_scenarios/test_create_jira_issue_for_security_findings_returns_created_response.frozen b/tests/v2/cassettes/test_scenarios/test_create_jira_issue_for_security_findings_returns_created_response.frozen new file mode 100644 index 0000000000..536270faa5 --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_create_jira_issue_for_security_findings_returns_created_response.frozen @@ -0,0 +1 @@ +2026-01-02T17:21:33.080Z \ No newline at end of file diff --git a/tests/v2/cassettes/test_scenarios/test_create_jira_issue_for_security_findings_returns_created_response.yaml b/tests/v2/cassettes/test_scenarios/test_create_jira_issue_for_security_findings_returns_created_response.yaml new file mode 100644 index 0000000000..f73d4e1049 --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_create_jira_issue_for_security_findings_returns_created_response.yaml @@ -0,0 +1,38 @@ +interactions: +- request: + body: '{"data":[{"attributes":{"description":"A description","title":"A title"},"relationships":{"findings":{"data":[{"id":"a3ZoLXNjbS14eXV-aS0wNWY5MGYwMGE4NDg2ODdlOA==","type":"findings"},{"id":"eWswLWJsdC1hZm5-aS0wMjRlYTgwMzVkZTU1MGIwYQ==","type":"findings"}]},"project":{"data":{"id":"959a6f71-bac8-4027-b1d3-2264f569296f","type":"projects"}}},"type":"jira_issues"}]}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/security/findings/jira_issues + response: + body: + string: '{"data":[{"id":"527aa591-d40e-4445-be80-9d012ba8397e","type":"cases","attributes":{"created_at":"2026-01-02T17:21:34.65318Z","creation_source":"CS_SECURITY_FINDING","description":"A + description","insights":[{"type":"SECURITY_FINDING","ref":"/security/compliance?panels=cpfinding%7Cevent%7CruleId%3Akvh-scm-xyu%7CresourceId%3Ai-05f90f00a848687e8\u0026query=%40finding_id%3Aa3ZoLXNjbS14eXV-aS0wNWY5MGYwMGE4NDg2ODdlOA%3D%3D","resource_id":"a3ZoLXNjbS14eXV-aS0wNWY5MGYwMGE4NDg2ODdlOA=="},{"type":"SECURITY_FINDING","ref":"/security/compliance?panels=cpfinding%7Cevent%7CruleId%3Ayk0-blt-afn%7CresourceId%3Ai-024ea8035de550b0a\u0026query=%40finding_id%3AeWswLWJsdC1hZm5-aS0wMjRlYTgwMzVkZTU1MGIwYQ%3D%3D","resource_id":"eWswLWJsdC1hZm5-aS0wMjRlYTgwMzVkZTU1MGIwYQ=="}],"jira_issue":{"status":"COMPLETED","result":{"issue_id":"2523579","issue_key":"CSMSEC-105849","issue_url":"https://datadoghq-sandbox-538.atlassian.net/browse/CSMSEC-105849","account_id":"fdcffa62-24ab-4914-a195-a22bdc607030"}},"key":"CSMINV-523","modified_at":"2026-01-02T17:21:35.836445Z","priority":"P3","status":"OPEN","status_group":"SG_OPEN","status_name":"Open","title":"A + title","type":"SECURITY"},"relationships":{"created_by":{"data":{"id":"dc09afab-6ae7-11ef-92b1-828dac1b0195","type":"users"}},"project":{"data":{"id":"959a6f71-bac8-4027-b1d3-2264f569296f","type":"projects"}}}}]}' + headers: + content-type: + - application/vnd.api+json + status: + code: 201 + message: Created +- request: + body: '{"data":{"relationships":{"findings":{"data":[{"id":"a3ZoLXNjbS14eXV-aS0wNWY5MGYwMGE4NDg2ODdlOA==","type":"findings"}]}},"type":"cases"}}' + headers: + accept: + - '*/*' + content-type: + - application/json + method: DELETE + uri: https://api.datadoghq.com/api/v2/security/findings/cases + response: + body: + string: '' + headers: {} + status: + code: 204 + message: No Content +version: 1 diff --git a/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_bad_request_response.frozen b/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_bad_request_response.frozen new file mode 100644 index 0000000000..6b40b01ad6 --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_bad_request_response.frozen @@ -0,0 +1 @@ +2026-01-02T16:54:04.434Z \ No newline at end of file diff --git a/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_bad_request_response.yaml b/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_bad_request_response.yaml new file mode 100644 index 0000000000..6ed5483e62 --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_bad_request_response.yaml @@ -0,0 +1,21 @@ +interactions: +- request: + body: '{"data":[{"attributes":{},"relationships":{"findings":{"data":[]},"project":{"data":{"id":"7f198869-c7ef-4afc-97cf-da5cdc13b5c3","type":"projects"}}},"type":"jira_issues"}]}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/security/findings/jira_issues + response: + body: + string: '{"errors":[{"status":"400","title":"Bad Request","detail":"no finding + provided"}]}' + headers: + content-type: + - application/vnd.api+json + status: + code: 400 + message: Bad Request +version: 1 diff --git a/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_created_response.frozen b/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_created_response.frozen new file mode 100644 index 0000000000..0a903f8222 --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_created_response.frozen @@ -0,0 +1 @@ +2026-01-02T17:23:28.665Z \ No newline at end of file diff --git a/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_created_response.yaml b/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_created_response.yaml new file mode 100644 index 0000000000..25963229db --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_created_response.yaml @@ -0,0 +1,41 @@ +interactions: +- request: + body: '{"data":[{"attributes":{"description":"A description","title":"A title"},"relationships":{"findings":{"data":[{"id":"eWswLWJsdC1hZm5-aS0wMjRlYTgwMzVkZTU1MGIwYQ==","type":"findings"}]},"project":{"data":{"id":"959a6f71-bac8-4027-b1d3-2264f569296f","type":"projects"}}},"type":"jira_issues"},{"attributes":{"description":"A + description","title":"A title"},"relationships":{"findings":{"data":[{"id":"a3ZoLXNjbS14eXV-aS0wNWY5MGYwMGE4NDg2ODdlOA==","type":"findings"}]},"project":{"data":{"id":"959a6f71-bac8-4027-b1d3-2264f569296f","type":"projects"}}},"type":"jira_issues"}]}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/security/findings/jira_issues + response: + body: + string: '{"data":[{"id":"3f234879-c155-4104-8605-a956c6157fa2","type":"cases","attributes":{"created_at":"2026-01-02T17:23:30.862128Z","creation_source":"CS_SECURITY_FINDING","description":"A + description","insights":[{"type":"SECURITY_FINDING","ref":"/security/compliance?panels=cpfinding%7Cevent%7CruleId%3Ayk0-blt-afn%7CresourceId%3Ai-024ea8035de550b0a\u0026query=%40finding_id%3AeWswLWJsdC1hZm5-aS0wMjRlYTgwMzVkZTU1MGIwYQ%3D%3D","resource_id":"eWswLWJsdC1hZm5-aS0wMjRlYTgwMzVkZTU1MGIwYQ=="}],"jira_issue":{"status":"COMPLETED","result":{"issue_id":"2523584","issue_key":"CSMSEC-105851","issue_url":"https://datadoghq-sandbox-538.atlassian.net/browse/CSMSEC-105851","account_id":"fdcffa62-24ab-4914-a195-a22bdc607030"}},"key":"CSMINV-524","modified_at":"2026-01-02T17:23:32.188706Z","priority":"P3","status":"OPEN","status_group":"SG_OPEN","status_name":"Open","title":"A + title","type":"SECURITY"},"relationships":{"created_by":{"data":{"id":"dc09afab-6ae7-11ef-92b1-828dac1b0195","type":"users"}},"project":{"data":{"id":"959a6f71-bac8-4027-b1d3-2264f569296f","type":"projects"}}}},{"id":"55b8c3c1-7080-4e13-b5fc-6bb658609fb7","type":"cases","attributes":{"created_at":"2026-01-02T17:23:30.862076Z","creation_source":"CS_SECURITY_FINDING","description":"A + description","insights":[{"type":"SECURITY_FINDING","ref":"/security/compliance?panels=cpfinding%7Cevent%7CruleId%3Akvh-scm-xyu%7CresourceId%3Ai-05f90f00a848687e8\u0026query=%40finding_id%3Aa3ZoLXNjbS14eXV-aS0wNWY5MGYwMGE4NDg2ODdlOA%3D%3D","resource_id":"a3ZoLXNjbS14eXV-aS0wNWY5MGYwMGE4NDg2ODdlOA=="}],"jira_issue":{"status":"COMPLETED","result":{"issue_id":"2523583","issue_key":"CSMSEC-105850","issue_url":"https://datadoghq-sandbox-538.atlassian.net/browse/CSMSEC-105850","account_id":"fdcffa62-24ab-4914-a195-a22bdc607030"}},"key":"CSMINV-525","modified_at":"2026-01-02T17:23:31.898339Z","priority":"P3","status":"OPEN","status_group":"SG_OPEN","status_name":"Open","title":"A + title","type":"SECURITY"},"relationships":{"created_by":{"data":{"id":"dc09afab-6ae7-11ef-92b1-828dac1b0195","type":"users"}},"project":{"data":{"id":"959a6f71-bac8-4027-b1d3-2264f569296f","type":"projects"}}}}]}' + headers: + content-type: + - application/vnd.api+json + status: + code: 201 + message: Created +- request: + body: '{"data":{"relationships":{"findings":{"data":[{"id":"eWswLWJsdC1hZm5-aS0wMjRlYTgwMzVkZTU1MGIwYQ==","type":"findings"}]}},"type":"cases"}}' + headers: + accept: + - '*/*' + content-type: + - application/json + method: DELETE + uri: https://api.datadoghq.com/api/v2/security/findings/cases + response: + body: + string: '' + headers: {} + status: + code: 204 + message: No Content +version: 1 diff --git a/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_not_found_response.frozen b/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_not_found_response.frozen new file mode 100644 index 0000000000..9fd2d2504e --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_not_found_response.frozen @@ -0,0 +1 @@ +2026-01-02T16:58:53.646Z \ No newline at end of file diff --git a/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_not_found_response.yaml b/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_not_found_response.yaml new file mode 100644 index 0000000000..d3ff5295fd --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_create_jira_issues_for_security_findings_returns_not_found_response.yaml @@ -0,0 +1,21 @@ +interactions: +- request: + body: '{"data":[{"attributes":{},"relationships":{"findings":{"data":[{"id":"ZGZhMDI3ZjdjMDM3YjJmNzcxNTlhZGMwMjdmZWNiNTZ-MTVlYTNmYWU3NjNlOTNlYTE2YjM4N2JmZmI4Yjk5N2Y=","type":"findings"}]},"project":{"data":{"id":"00000000-0000-0000-0000-000000000000","type":"projects"}}},"type":"jira_issues"}]}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/security/findings/jira_issues + response: + body: + string: '{"errors":[{"status":"404","title":"Not Found","detail":"finding not + found"}]}' + headers: + content-type: + - application/vnd.api+json + status: + code: 404 + message: Not Found +version: 1 diff --git a/tests/v2/features/security_monitoring.feature b/tests/v2/features/security_monitoring.feature index 1a620afb10..ccc027734e 100644 --- a/tests/v2/features/security_monitoring.feature +++ b/tests/v2/features/security_monitoring.feature @@ -9,7 +9,7 @@ Feature: Security Monitoring And a valid "appKeyAuth" key in the system And an instance of "SecurityMonitoring" API - @skip @team:DataDog/k9-investigation + @team:DataDog/k9-investigation Scenario: Attach security finding to a Jira issue returns "OK" response Given new "AttachJiraIssue" request And body with value {"data": {"attributes": {"jira_issue_url": "https://datadoghq-sandbox-538.atlassian.net/browse/CSMSEC-105476"}, "relationships": {"findings": {"data": [{"id": "OTQ3NjJkMmYwMTIzMzMxNTc1Y2Q4MTA5NWU0NTBmMDl-ZjE3NjMxZWVkYzBjZGI1NDY2NWY2OGQxZDk4MDY4MmI=", "type": "findings"}]}, "project": {"data": {"id": "959a6f71-bac8-4027-b1d3-2264f569296f", "type": "projects"}}}, "type": "jira_issues"}} @@ -30,21 +30,21 @@ Feature: Security Monitoring And the response "data.attributes.status_group" is equal to "SG_OPEN" And the response "data.attributes.insights" has item with field "resource_id" with value "ZGZhMDI3ZjdjMDM3YjJmNzcxNTlhZGMwMjdmZWNiNTZ-MTVlYTNmYWU3NjNlOTNlYTE2YjM4N2JmZmI4Yjk5N2Y=" - @skip @team:DataDog/k9-investigation + @team:DataDog/k9-investigation Scenario: Attach security findings to a Jira issue returns "Bad Request" response Given new "AttachJiraIssue" request And body with value {"data": {"attributes": {"jira_issue_url": "https://datadoghq-sandbox-538.atlassian.net/browse/CSMSEC-105476"}, "relationships": {"findings": {"data": []}, "project": {"data": {"id": "959a6f71-bac8-4027-b1d3-2264f569296f", "type": "projects"}}}, "type": "jira_issues"}} When the request is sent Then the response status is 400 Bad Request - @skip @team:DataDog/k9-investigation + @team:DataDog/k9-investigation Scenario: Attach security findings to a Jira issue returns "Not Found" response Given new "AttachJiraIssue" request And body with value {"data": {"attributes": {"jira_issue_url": "https://datadoghq-sandbox-538.atlassian.net/browse/CSMSEC-105476"}, "relationships": {"findings": {"data": [{"id": "wrong-finding-id", "type": "findings"}]}, "project": {"data": {"id": "959a6f71-bac8-4027-b1d3-2264f569296f", "type": "projects"}}}, "type": "jira_issues"}} When the request is sent Then the response status is 404 Not Found - @skip @team:DataDog/k9-investigation + @team:DataDog/k9-investigation Scenario: Attach security findings to a Jira issue returns "OK" response Given new "AttachJiraIssue" request And body with value {"data": {"attributes": {"jira_issue_url": "https://datadoghq-sandbox-538.atlassian.net/browse/CSMSEC-105476"}, "relationships": {"findings": {"data": [{"id": "OTQ3NjJkMmYwMTIzMzMxNTc1Y2Q4MTA5NWU0NTBmMDl-ZjE3NjMxZWVkYzBjZGI1NDY2NWY2OGQxZDk4MDY4MmI=", "type": "findings"}, {"id": "MTNjN2ZmYWMzMDIxYmU1ZDFiZDRjNWUwN2I1NzVmY2F-YTA3MzllMTUzNWM3NmEyZjdiNzEzOWM5YmViZTMzOGM=", "type": "findings"}]}, "project": {"data": {"id": "959a6f71-bac8-4027-b1d3-2264f569296f", "type": "projects"}}}, "type": "jira_issues"}} @@ -280,27 +280,75 @@ Feature: Security Monitoring Then the response status is 200 OK And the response "terraformContent" is equal to "resource \"datadog_security_monitoring_rule\" \"_{{ unique_hash }}\" {\n\tname = \"_{{ unique_hash }}\"\n\tenabled = true\n\tquery {\n\t\tquery = \"@test:true\"\n\t\tgroup_by_fields = []\n\t\thas_optional_group_by_fields = false\n\t\tdistinct_fields = []\n\t\taggregation = \"count\"\n\t\tname = \"\"\n\t\tdata_source = \"logs\"\n\t}\n\toptions {\n\t\tkeep_alive = 3600\n\t\tmax_signal_duration = 86400\n\t\tdetection_method = \"threshold\"\n\t\tevaluation_window = 900\n\t}\n\tcase {\n\t\tname = \"\"\n\t\tstatus = \"info\"\n\t\tnotifications = []\n\t\tcondition = \"a > 0\"\n\t}\n\tmessage = \"Test rule\"\n\ttags = []\n\thas_extended_title = false\n\ttype = \"log_detection\"\n}\n" - @generated @skip @team:DataDog/k9-investigation + @team:DataDog/k9-investigation + Scenario: Create Jira issue for security finding returns "Created" response + Given new "CreateJiraIssues" request + And body with value {"data": [{"attributes": {"title": "A title", "description": "A description"}, "relationships": {"findings": {"data": [{"id": "YmNlZmJhYTcyMDU5ZDk0ZDhiNjRmNGI0NDk4MDdiNzN-MDJlMjg0NzNmYzJiODY2MzJkNjU0OTI4NmVhZTUyY2U=", "type": "findings"}]}, "project": {"data": {"id": "959a6f71-bac8-4027-b1d3-2264f569296f", "type": "projects"}}}, "type": "jira_issues"}]} + When the request is sent + Then the response status is 201 Created + And the response "data" has length 1 + And the response "data[0]" has field "id" + And the response "data[0].attributes.title" is equal to "A title" + And the response "data[0].attributes.description" is equal to "A description" + And the response "data[0].attributes.type" is equal to "SECURITY" + And the response "data[0].attributes.insights" has length 1 + And the response "data[0].attributes.insights[0].resource_id" is equal to "YmNlZmJhYTcyMDU5ZDk0ZDhiNjRmNGI0NDk4MDdiNzN-MDJlMjg0NzNmYzJiODY2MzJkNjU0OTI4NmVhZTUyY2U=" + And the response "data[0].attributes.insights[0].type" is equal to "SECURITY_FINDING" + And the response "data[0].attributes.jira_issue.status" is equal to "COMPLETED" + + @team:DataDog/k9-investigation + Scenario: Create Jira issue for security findings returns "Created" response + Given new "CreateJiraIssues" request + And body with value {"data": [{"attributes": {"title": "A title", "description": "A description"}, "relationships": {"findings": {"data": [{"id": "a3ZoLXNjbS14eXV-aS0wNWY5MGYwMGE4NDg2ODdlOA==", "type": "findings"}, {"id": "eWswLWJsdC1hZm5-aS0wMjRlYTgwMzVkZTU1MGIwYQ==", "type": "findings"}]}, "project": {"data": {"id": "959a6f71-bac8-4027-b1d3-2264f569296f", "type": "projects"}}}, "type": "jira_issues"}]} + When the request is sent + Then the response status is 201 Created + And the response "data" has length 1 + And the response "data[0]" has field "id" + And the response "data[0].attributes.title" is equal to "A title" + And the response "data[0].attributes.description" is equal to "A description" + And the response "data[0].attributes.type" is equal to "SECURITY" + And the response "data[0].attributes.insights" has length 2 + And the response "data[0].attributes.insights[1].resource_id" is equal to "eWswLWJsdC1hZm5-aS0wMjRlYTgwMzVkZTU1MGIwYQ==" + And the response "data[0].attributes.insights[1].type" is equal to "SECURITY_FINDING" + And the response "data[0].attributes.insights[0].resource_id" is equal to "a3ZoLXNjbS14eXV-aS0wNWY5MGYwMGE4NDg2ODdlOA==" + And the response "data[0].attributes.insights[0].type" is equal to "SECURITY_FINDING" + And the response "data[0].attributes.jira_issue.status" is equal to "COMPLETED" + + @team:DataDog/k9-investigation Scenario: Create Jira issues for security findings returns "Bad Request" response - Given operation "CreateJiraIssues" enabled - And new "CreateJiraIssues" request - And body with value {"data": [{"attributes": {"assignee_id": "f315bdaf-9ee7-4808-a9c1-99c15bf0f4d0", "description": "A description of the Jira issue.", "fields": {"key1": "value", "key2": ["value"], "key3": {"key4": "value"}}, "priority": "NOT_DEFINED", "title": "A title for the Jira issue."}, "relationships": {"findings": {"data": [{"id": "ZGVmLTAwcC1pZXJ-aS0wZjhjNjMyZDNmMzRlZTgzNw==", "type": "findings"}]}, "project": {"data": {"id": "aeadc05e-98a8-11ec-ac2c-da7ad0900001", "type": "projects"}}}, "type": "jira_issues"}]} + Given new "CreateJiraIssues" request + And body with value {"data": [{"attributes": {}, "relationships": {"findings": {"data": []}, "project": {"data": {"id": "7f198869-c7ef-4afc-97cf-da5cdc13b5c3", "type": "projects"}}}, "type": "jira_issues"}]} When the request is sent Then the response status is 400 Bad Request - @generated @skip @team:DataDog/k9-investigation + @team:DataDog/k9-investigation Scenario: Create Jira issues for security findings returns "Created" response - Given operation "CreateJiraIssues" enabled - And new "CreateJiraIssues" request - And body with value {"data": [{"attributes": {"assignee_id": "f315bdaf-9ee7-4808-a9c1-99c15bf0f4d0", "description": "A description of the Jira issue.", "fields": {"key1": "value", "key2": ["value"], "key3": {"key4": "value"}}, "priority": "NOT_DEFINED", "title": "A title for the Jira issue."}, "relationships": {"findings": {"data": [{"id": "ZGVmLTAwcC1pZXJ-aS0wZjhjNjMyZDNmMzRlZTgzNw==", "type": "findings"}]}, "project": {"data": {"id": "aeadc05e-98a8-11ec-ac2c-da7ad0900001", "type": "projects"}}}, "type": "jira_issues"}]} + Given new "CreateJiraIssues" request + And body with value {"data": [{"attributes": {"title": "A title", "description": "A description"}, "relationships": {"findings": {"data": [{"id": "eWswLWJsdC1hZm5-aS0wMjRlYTgwMzVkZTU1MGIwYQ==", "type": "findings"}]}, "project": {"data": {"id": "959a6f71-bac8-4027-b1d3-2264f569296f", "type": "projects"}}}, "type": "jira_issues"}, {"attributes": {"title": "A title", "description": "A description"}, "relationships": {"findings": {"data": [{"id": "a3ZoLXNjbS14eXV-aS0wNWY5MGYwMGE4NDg2ODdlOA==", "type": "findings"}]}, "project": {"data": {"id": "959a6f71-bac8-4027-b1d3-2264f569296f", "type": "projects"}}}, "type": "jira_issues"}]} When the request is sent Then the response status is 201 Created + And the response "data" has length 2 + And the response "data[0]" has field "id" + And the response "data[0].attributes.title" is equal to "A title" + And the response "data[0].attributes.description" is equal to "A description" + And the response "data[0].attributes.type" is equal to "SECURITY" + And the response "data[0].attributes.insights" has length 1 + And the response "data[0].attributes.insights[0].resource_id" is equal to "eWswLWJsdC1hZm5-aS0wMjRlYTgwMzVkZTU1MGIwYQ==" + And the response "data[0].attributes.insights[0].type" is equal to "SECURITY_FINDING" + And the response "data[0].attributes.jira_issue.status" is equal to "COMPLETED" + And the response "data[1]" has field "id" + And the response "data[1].attributes.title" is equal to "A title" + And the response "data[1].attributes.description" is equal to "A description" + And the response "data[1].attributes.type" is equal to "SECURITY" + And the response "data[1].attributes.insights" has length 1 + And the response "data[1].attributes.insights[0].resource_id" is equal to "a3ZoLXNjbS14eXV-aS0wNWY5MGYwMGE4NDg2ODdlOA==" + And the response "data[1].attributes.insights[0].type" is equal to "SECURITY_FINDING" + And the response "data[1].attributes.jira_issue.status" is equal to "COMPLETED" - @generated @skip @team:DataDog/k9-investigation + @team:DataDog/k9-investigation Scenario: Create Jira issues for security findings returns "Not Found" response - Given operation "CreateJiraIssues" enabled - And new "CreateJiraIssues" request - And body with value {"data": [{"attributes": {"assignee_id": "f315bdaf-9ee7-4808-a9c1-99c15bf0f4d0", "description": "A description of the Jira issue.", "fields": {"key1": "value", "key2": ["value"], "key3": {"key4": "value"}}, "priority": "NOT_DEFINED", "title": "A title for the Jira issue."}, "relationships": {"findings": {"data": [{"id": "ZGVmLTAwcC1pZXJ-aS0wZjhjNjMyZDNmMzRlZTgzNw==", "type": "findings"}]}, "project": {"data": {"id": "aeadc05e-98a8-11ec-ac2c-da7ad0900001", "type": "projects"}}}, "type": "jira_issues"}]} + Given new "CreateJiraIssues" request + And body with value {"data": [{"attributes": {}, "relationships": {"findings": {"data": [{"id": "ZGZhMDI3ZjdjMDM3YjJmNzcxNTlhZGMwMjdmZWNiNTZ-MTVlYTNmYWU3NjNlOTNlYTE2YjM4N2JmZmI4Yjk5N2Y=", "type": "findings"}]}, "project": {"data": {"id": "00000000-0000-0000-0000-000000000000", "type": "projects"}}}, "type": "jira_issues"}]} When the request is sent Then the response status is 404 Not Found