mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 20:42:02 +00:00
feat(jira): add force accept language for requests (#8674)
This commit is contained in:
@@ -13,6 +13,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
- Support color for MANUAL finidngs in Jira tickets [(#8642)](https://github.com/prowler-cloud/prowler/pull/8642)
|
||||
- `--excluded-checks-file` flag [(#8301)](https://github.com/prowler-cloud/prowler/pull/8301)
|
||||
- Send finding in Jira integration with the needed values [(#8648)](https://github.com/prowler-cloud/prowler/pull/8648)
|
||||
- Add language enforcement for Jira requests [(#8674)](https://github.com/prowler-cloud/prowler/pull/8674)
|
||||
- MongoDB Atlas provider with 10 security checks [(#8312)](https://github.com/prowler-cloud/prowler/pull/8312)
|
||||
- `clusters_authentication_enabled` - Ensure clusters have authentication enabled
|
||||
- `clusters_backup_enabled` - Ensure clusters have backup enabled
|
||||
|
||||
@@ -136,6 +136,11 @@ class Jira:
|
||||
}
|
||||
TOKEN_URL = "https://auth.atlassian.com/oauth/token"
|
||||
API_TOKEN_URL = "https://api.atlassian.com/oauth/token/accessible-resources"
|
||||
HEADER_TEMPLATE = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Force-Accept-Language": "true",
|
||||
"Accept-Language": "en",
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -200,6 +205,31 @@ class Jira:
|
||||
def using_basic_auth(self):
|
||||
return self._using_basic_auth
|
||||
|
||||
def get_headers(
|
||||
self, access_token: str = None, content_type_json: bool = False
|
||||
) -> dict:
|
||||
"""Get headers for API requests
|
||||
|
||||
Args:
|
||||
access_token: The access token to use for authorization
|
||||
content_type_json: Whether to include Content-Type: application/json
|
||||
|
||||
Returns:
|
||||
dict: Headers for API requests
|
||||
"""
|
||||
headers = self.HEADER_TEMPLATE.copy()
|
||||
|
||||
if not content_type_json:
|
||||
headers.pop("Content-Type", None)
|
||||
|
||||
if access_token:
|
||||
if self._using_basic_auth:
|
||||
headers["Authorization"] = f"Basic {access_token}"
|
||||
else:
|
||||
headers["Authorization"] = f"Bearer {access_token}"
|
||||
|
||||
return headers
|
||||
|
||||
def get_params(self, state_encoded):
|
||||
return {
|
||||
**self.PARAMS_TEMPLATE,
|
||||
@@ -303,7 +333,7 @@ class Jira:
|
||||
"redirect_uri": self.redirect_uri,
|
||||
}
|
||||
|
||||
headers = {"Content-Type": "application/json"}
|
||||
headers = self.get_headers(content_type_json=True)
|
||||
response = requests.post(self.TOKEN_URL, json=body, headers=headers)
|
||||
|
||||
if response.status_code == 200:
|
||||
@@ -352,7 +382,7 @@ class Jira:
|
||||
"""
|
||||
try:
|
||||
if self._using_basic_auth:
|
||||
headers = {"Authorization": f"Basic {access_token}"}
|
||||
headers = self.get_headers(access_token)
|
||||
response = requests.get(
|
||||
f"https://{domain}.atlassian.net/_edge/tenant_info",
|
||||
headers=headers,
|
||||
@@ -360,7 +390,7 @@ class Jira:
|
||||
response = response.json()
|
||||
return response.get("cloudId")
|
||||
else:
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
headers = self.get_headers(access_token)
|
||||
response = requests.get(self.API_TOKEN_URL, headers=headers)
|
||||
|
||||
if response.status_code == 200:
|
||||
@@ -442,7 +472,7 @@ class Jira:
|
||||
"refresh_token": self._refresh_token,
|
||||
}
|
||||
|
||||
headers = {"Content-Type": "application/json"}
|
||||
headers = self.get_headers(content_type_json=True)
|
||||
response = requests.post(url, json=body, headers=headers)
|
||||
|
||||
if response.status_code == 200:
|
||||
@@ -582,10 +612,7 @@ class Jira:
|
||||
if not access_token:
|
||||
return ValueError("Failed to get access token")
|
||||
|
||||
if self._using_basic_auth:
|
||||
headers = {"Authorization": f"Basic {access_token}"}
|
||||
else:
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
headers = self.get_headers(access_token)
|
||||
|
||||
response = requests.get(
|
||||
f"https://api.atlassian.com/ex/jira/{self.cloud_id}/rest/api/3/project",
|
||||
@@ -652,10 +679,7 @@ class Jira:
|
||||
file=os.path.basename(__file__),
|
||||
)
|
||||
|
||||
if self._using_basic_auth:
|
||||
headers = {"Authorization": f"Basic {access_token}"}
|
||||
else:
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
headers = self.get_headers(access_token)
|
||||
|
||||
response = requests.get(
|
||||
f"https://api.atlassian.com/ex/jira/{self.cloud_id}/rest/api/3/issue/createmeta?projectKeys={project_key}&expand=projects.issuetypes.fields",
|
||||
@@ -700,10 +724,7 @@ class Jira:
|
||||
if not access_token:
|
||||
return ValueError("Failed to get access token")
|
||||
|
||||
if self._using_basic_auth:
|
||||
headers = {"Authorization": f"Basic {access_token}"}
|
||||
else:
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
headers = self.get_headers(access_token)
|
||||
|
||||
response = requests.get(
|
||||
f"https://api.atlassian.com/ex/jira/{self.cloud_id}/rest/api/3/project",
|
||||
@@ -1579,16 +1600,7 @@ class Jira:
|
||||
message="The issue type is invalid", file=os.path.basename(__file__)
|
||||
)
|
||||
|
||||
if self._using_basic_auth:
|
||||
headers = {
|
||||
"Authorization": f"Basic {access_token}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
else:
|
||||
headers = {
|
||||
"Authorization": f"Bearer {access_token}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
headers = self.get_headers(access_token, content_type_json=True)
|
||||
|
||||
for finding in findings:
|
||||
status_color = self.get_color_from_status(finding.status.value)
|
||||
@@ -1795,16 +1807,7 @@ class Jira:
|
||||
message="The issue type is invalid", file=os.path.basename(__file__)
|
||||
)
|
||||
|
||||
if self._using_basic_auth:
|
||||
headers = {
|
||||
"Authorization": f"Basic {access_token}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
else:
|
||||
headers = {
|
||||
"Authorization": f"Bearer {access_token}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
headers = self.get_headers(access_token, content_type_json=True)
|
||||
|
||||
status_color = self.get_color_from_status(status)
|
||||
severity_color = self.get_severity_color(severity.lower())
|
||||
|
||||
@@ -721,6 +721,8 @@ class TestJiraIntegration:
|
||||
expected_headers = {
|
||||
"Authorization": "Bearer valid_access_token",
|
||||
"Content-Type": "application/json",
|
||||
"X-Force-Accept-Language": "true",
|
||||
"Accept-Language": "en",
|
||||
}
|
||||
|
||||
assert call_args[0][0] == expected_url
|
||||
@@ -1418,3 +1420,103 @@ class TestJiraIntegration:
|
||||
|
||||
assert result is False
|
||||
mock_post.assert_called_once()
|
||||
|
||||
def test_get_headers_oauth_with_access_token(self):
|
||||
"""Test get_headers returns correct OAuth headers with access token."""
|
||||
self.jira_integration._using_basic_auth = False
|
||||
|
||||
headers = self.jira_integration.get_headers(
|
||||
access_token="test_oauth_token", content_type_json=True
|
||||
)
|
||||
|
||||
expected_headers = {
|
||||
"Authorization": "Bearer test_oauth_token",
|
||||
"Content-Type": "application/json",
|
||||
"X-Force-Accept-Language": "true",
|
||||
"Accept-Language": "en",
|
||||
}
|
||||
assert headers == expected_headers
|
||||
|
||||
def test_get_headers_oauth_without_content_type(self):
|
||||
"""Test get_headers returns OAuth headers without Content-Type when content_type_json=False."""
|
||||
self.jira_integration._using_basic_auth = False
|
||||
|
||||
headers = self.jira_integration.get_headers(
|
||||
access_token="test_oauth_token", content_type_json=False
|
||||
)
|
||||
|
||||
expected_headers = {
|
||||
"Authorization": "Bearer test_oauth_token",
|
||||
"X-Force-Accept-Language": "true",
|
||||
"Accept-Language": "en",
|
||||
}
|
||||
assert headers == expected_headers
|
||||
assert "Content-Type" not in headers
|
||||
|
||||
def test_get_headers_basic_auth_with_access_token(self):
|
||||
"""Test get_headers returns correct Basic Auth headers with access token."""
|
||||
self.jira_integration_basic_auth._using_basic_auth = True
|
||||
|
||||
headers = self.jira_integration_basic_auth.get_headers(
|
||||
access_token="test_basic_token", content_type_json=True
|
||||
)
|
||||
|
||||
expected_headers = {
|
||||
"Authorization": "Basic test_basic_token",
|
||||
"Content-Type": "application/json",
|
||||
"X-Force-Accept-Language": "true",
|
||||
"Accept-Language": "en",
|
||||
}
|
||||
assert headers == expected_headers
|
||||
|
||||
def test_get_headers_basic_auth_without_content_type(self):
|
||||
"""Test get_headers returns Basic Auth headers without Content-Type when content_type_json=False."""
|
||||
self.jira_integration_basic_auth._using_basic_auth = True
|
||||
|
||||
headers = self.jira_integration_basic_auth.get_headers(
|
||||
access_token="test_basic_token", content_type_json=False
|
||||
)
|
||||
|
||||
expected_headers = {
|
||||
"Authorization": "Basic test_basic_token",
|
||||
"X-Force-Accept-Language": "true",
|
||||
"Accept-Language": "en",
|
||||
}
|
||||
assert headers == expected_headers
|
||||
assert "Content-Type" not in headers
|
||||
|
||||
def test_get_headers_without_access_token_with_content_type(self):
|
||||
"""Test get_headers returns headers without Authorization when no access token provided."""
|
||||
headers = self.jira_integration.get_headers(content_type_json=True)
|
||||
|
||||
expected_headers = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Force-Accept-Language": "true",
|
||||
"Accept-Language": "en",
|
||||
}
|
||||
assert headers == expected_headers
|
||||
assert "Authorization" not in headers
|
||||
|
||||
def test_get_headers_without_access_token_without_content_type(self):
|
||||
"""Test get_headers returns minimal headers when no access token and no content type."""
|
||||
headers = self.jira_integration.get_headers(content_type_json=False)
|
||||
|
||||
expected_headers = {
|
||||
"X-Force-Accept-Language": "true",
|
||||
"Accept-Language": "en",
|
||||
}
|
||||
assert headers == expected_headers
|
||||
assert "Authorization" not in headers
|
||||
assert "Content-Type" not in headers
|
||||
|
||||
def test_get_headers_default_parameters(self):
|
||||
"""Test get_headers with default parameters (no access token, no content type)."""
|
||||
headers = self.jira_integration.get_headers()
|
||||
|
||||
expected_headers = {
|
||||
"X-Force-Accept-Language": "true",
|
||||
"Accept-Language": "en",
|
||||
}
|
||||
assert headers == expected_headers
|
||||
assert "Authorization" not in headers
|
||||
assert "Content-Type" not in headers
|
||||
|
||||
Reference in New Issue
Block a user