diff --git a/docs/snippets/providers/jiraonprem-snippet-autogenerated.mdx b/docs/snippets/providers/jiraonprem-snippet-autogenerated.mdx index 29b1b6166d..16bed6ded8 100644 --- a/docs/snippets/providers/jiraonprem-snippet-autogenerated.mdx +++ b/docs/snippets/providers/jiraonprem-snippet-autogenerated.mdx @@ -6,6 +6,7 @@ This provider requires authentication. - **host**: Jira Host (required: True, sensitive: False) - **personal_access_token**: Jira PAT (required: True, sensitive: True) - **ticket_creation_url**: URL for creating new tickets (required: False, sensitive: False) +- **verify**: Verify the Jira server's TLS certificate (required: False, sensitive: False) Certain scopes may be required to perform specific actions or queries via the provider. Below is a summary of relevant scopes and their use cases: - **BROWSE_PROJECTS**: Browse Jira Projects (mandatory) diff --git a/keep/providers/jiraonprem_provider/jiraonprem_provider.py b/keep/providers/jiraonprem_provider/jiraonprem_provider.py index 0fabe536e7..febccca89e 100644 --- a/keep/providers/jiraonprem_provider/jiraonprem_provider.py +++ b/keep/providers/jiraonprem_provider/jiraonprem_provider.py @@ -50,6 +50,17 @@ class JiraonpremProviderAuthConfig: default="", ) + verify: bool = dataclasses.field( + default=False, + metadata={ + "required": False, + "description": "Verify the Jira server's TLS certificate", + "hint": "Disabled by default; enable if the server uses a trusted certificate", + "type": "switch", + "config_main_group": "authentication", + }, + ) + class JiraonpremProvider(BaseProvider): """Enrich alerts with Jira tickets.""" @@ -118,7 +129,7 @@ def validate_scopes(self): resp = requests.get( f"{self.jira_host}/rest/api/2/myself", headers=headers, - verify=False, + verify=self.authentication_config.verify, timeout=10, ) try: @@ -139,7 +150,7 @@ def validate_scopes(self): f"{self.jira_host}/rest/api/2/mypermissions", headers=headers, params=params, - verify=False, + verify=self.authentication_config.verify, timeout=10, ) try: @@ -178,7 +189,9 @@ def jira_host(self): # otherwise, try to use https: try: requests.get( - f"https://{self.authentication_config.host}", verify=False, timeout=10 + f"https://{self.authentication_config.host}", + verify=self.authentication_config.verify, + timeout=10, ) self.logger.debug("Using https") self._host = f"https://{self.authentication_config.host}" @@ -239,7 +252,12 @@ def __get_createmeta(self, project_key: str): query_params={"projectKeys": project_key}, ) headers = self.__get_auth_header() - response = requests.get(url=url, headers=headers, verify=False, timeout=10) + response = requests.get( + url=url, + headers=headers, + verify=self.authentication_config.verify, + timeout=10, + ) response.raise_for_status() @@ -322,7 +340,7 @@ def __create_issue( url=url, json=request_body, headers=self.__get_auth_header(), - verify=False, + verify=self.authentication_config.verify, timeout=10, ) try: @@ -387,7 +405,7 @@ def __update_issue( url=url, json=request_body, headers=self.__get_auth_header(), - verify=False, + verify=self.authentication_config.verify, timeout=10, ) @@ -421,7 +439,7 @@ def _extract_project_key_from_board_name(self, board_name: str): boards_response = requests.get( f"{self.jira_host}/rest/agile/1.0/board", headers=headers, - verify=False, + verify=self.authentication_config.verify, timeout=10, ) if boards_response.status_code == 200: @@ -434,7 +452,7 @@ def _extract_project_key_from_board_name(self, board_name: str): board_configuration = requests.get( f"{self.jira_host}/rest/agile/1.0/board/{board_id}/configuration", headers=headers, - verify=False, + verify=self.authentication_config.verify, timeout=10, ) if board_configuration.status_code != 200: @@ -447,7 +465,7 @@ def _extract_project_key_from_board_name(self, board_name: str): filter_response = requests.get( f"{self.jira_host}/rest/api/2/filter/{filter_id}", headers=headers, - verify=False, + verify=self.authentication_config.verify, timeout=10, ) if filter_response.status_code != 200: @@ -483,7 +501,7 @@ def _extract_issue_key_from_issue_id(self, issue_id: str): issue_key = requests.get( f"{self.jira_host}/rest/api/2/issue/{issue_id}", headers=headers, - verify=False, + verify=self.authentication_config.verify, timeout=10, ) @@ -586,7 +604,10 @@ def _query(self, ticket_id="", board_id="", **kwargs: dict): f"https://{self.jira_host}/rest/agile/1.0/board/{board_id}/issue" ) response = requests.get( - request_url, headers=self.__get_auth_header(), verify=False, timeout=10 + request_url, + headers=self.__get_auth_header(), + verify=self.authentication_config.verify, + timeout=10, ) if not response.ok: raise ProviderException( @@ -597,7 +618,10 @@ def _query(self, ticket_id="", board_id="", **kwargs: dict): else: request_url = self.__get_url(paths=["issue", ticket_id]) response = requests.get( - request_url, headers=self.__get_auth_header(), verify=False, timeout=10 + request_url, + headers=self.__get_auth_header(), + verify=self.authentication_config.verify, + timeout=10, ) if not response.ok: raise ProviderException( diff --git a/tests/test_jira_provider.py b/tests/test_jira_provider.py index 1d84726db5..19ba15e78f 100644 --- a/tests/test_jira_provider.py +++ b/tests/test_jira_provider.py @@ -126,6 +126,51 @@ def test_create_issue_with_custom_fields_jira_onprem( # Verify the result assert result["issue"]["key"] == "TEST-123" + @patch("requests.post") + @patch("requests.get") + def test_jiraonprem_ssl_verification_disabled_by_default( + self, mock_get, mock_post, jiraonprem_provider + ): + mock_get.return_value.status_code = 200 + mock_get.return_value.json.return_value = { + "projects": [{"issuetypes": [{"name": "Task"}]}] + } + mock_post.return_value.status_code = 201 + mock_post.return_value.json.return_value = {"key": "TEST-1", "id": "1"} + + jiraonprem_provider._JiraonpremProvider__create_issue( + project_key="TEST", summary="Test Summary" + ) + + assert mock_post.call_args[1]["verify"] is False + + @patch("requests.post") + @patch("requests.get") + def test_jiraonprem_ssl_verification_enabled_via_config( + self, mock_get, mock_post, context_manager + ): + config = ProviderConfig( + description="Test Jira On-Prem Provider", + authentication={ + "host": "https://test-jira.com", + "personal_access_token": "test_token", + "verify": True, + }, + ) + provider = JiraonpremProvider(context_manager, "test_jiraonprem_verify", config) + mock_get.return_value.status_code = 200 + mock_get.return_value.json.return_value = { + "projects": [{"issuetypes": [{"name": "Task"}]}] + } + mock_post.return_value.status_code = 201 + mock_post.return_value.json.return_value = {"key": "TEST-1", "id": "1"} + + provider._JiraonpremProvider__create_issue( + project_key="TEST", summary="Test Summary" + ) + + assert mock_post.call_args[1]["verify"] is True + @patch("requests.put") @patch("requests.get") def test_update_issue_with_custom_fields_jira_cloud(