Skip to content

Commit af7091b

Browse files
committed
require kid
1 parent 4e0e5a3 commit af7091b

File tree

2 files changed

+12
-45
lines changed

2 files changed

+12
-45
lines changed

src/sentry/integrations/jira/webhooks/installed.py

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import sentry_sdk
22
from django.db import router, transaction
3-
from jwt import DecodeError, ExpiredSignatureError, InvalidAlgorithmError, InvalidSignatureError
3+
from jwt import (
4+
InvalidKeyError,
5+
)
46
from rest_framework import status
57
from rest_framework.request import Request
68
from rest_framework.response import Response
@@ -21,9 +23,6 @@
2123
)
2224
from sentry.utils import jwt
2325

24-
# Atlassian sends scanner bots to "test" Atlassian apps and they often hit this endpoint with a bad kid causing errors
25-
INVALID_KEY_IDS = ["fake-kid"]
26-
2726

2827
@control_silo_endpoint
2928
class JiraSentryInstalledWebhook(JiraWebhookBase):
@@ -57,36 +56,17 @@ def post(self, request: Request, *args, **kwargs) -> Response:
5756
}
5857
)
5958

60-
if key_id:
61-
if key_id in INVALID_KEY_IDS:
62-
lifecycle.record_halt(halt_reason="JWT contained invalid key_id (kid)")
63-
return self.respond(
64-
{"detail": "Invalid key id"}, status=status.HTTP_400_BAD_REQUEST
65-
)
59+
if not key_id:
60+
lifecycle.record_halt(halt_reason="Missing key_id (kid)")
61+
return self.respond(
62+
{"detail": "Missing key id"}, status=status.HTTP_400_BAD_REQUEST
63+
)
64+
try:
6665
decoded_claims = authenticate_asymmetric_jwt(token, key_id)
67-
else:
68-
shared_secret = state.get("sharedSecret")
69-
if not shared_secret:
70-
return self.respond(
71-
{"detail": "Missing shared secret"}, status=status.HTTP_400_BAD_REQUEST
72-
)
73-
try:
74-
decoded_claims = jwt.decode(token, shared_secret, audience=False)
75-
except (
76-
InvalidSignatureError,
77-
ExpiredSignatureError,
78-
DecodeError,
79-
InvalidAlgorithmError,
80-
):
81-
return self.respond(
82-
{"detail": "Invalid JWT"}, status=status.HTTP_400_BAD_REQUEST
83-
)
84-
85-
if decoded_claims.get("iss") != state.get("clientKey"):
86-
lifecycle.record_halt(halt_reason="JWT issuer does not match client key")
66+
except InvalidKeyError:
67+
lifecycle.record_halt(halt_reason="JWT contained invalid key_id (kid)")
8768
return self.respond(
88-
{"detail": "JWT issuer does not match client key"},
89-
status=status.HTTP_400_BAD_REQUEST,
69+
{"detail": "Invalid key id"}, status=status.HTTP_400_BAD_REQUEST
9070
)
9171

9272
verify_claims(decoded_claims, request.path, request.GET, method="POST")

tests/sentry/integrations/jira/test_installed.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -111,19 +111,6 @@ def test_no_claims(self, mock_authenticate_asymmetric_jwt: MagicMock) -> None:
111111
status_code=status.HTTP_409_CONFLICT,
112112
)
113113

114-
@patch("sentry.integrations.utils.metrics.EventLifecycle.record_event")
115-
@patch("sentry_sdk.set_tag")
116-
def test_with_shared_secret(self, mock_set_tag: MagicMock, mock_record_event) -> None:
117-
self.get_success_response(
118-
**self.body(),
119-
extra_headers=dict(HTTP_AUTHORIZATION="JWT " + self.jwt_token_secret()),
120-
)
121-
integration = Integration.objects.get(provider="jira", external_id=self.external_id)
122-
123-
mock_set_tag.assert_any_call("integration_id", integration.id)
124-
assert integration.status == ObjectStatus.ACTIVE
125-
mock_record_event.assert_called_with(EventLifecycleOutcome.SUCCESS, None, False, None)
126-
127114
@patch("sentry_sdk.set_tag")
128115
@responses.activate
129116
def test_with_key_id(self, mock_set_tag: MagicMock) -> None:

0 commit comments

Comments
 (0)