Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
48 changes: 36 additions & 12 deletions keep/providers/jiraonprem_provider/jiraonprem_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -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}"
Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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,
)

Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -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,
)

Expand Down Expand Up @@ -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(
Expand All @@ -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(
Expand Down
45 changes: 45 additions & 0 deletions tests/test_jira_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Loading