Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.

Commit 5b40741

Browse files
authored
fix: token retrieval error when config is not setup (#1121)
1 parent 8f444ba commit 5b40741

File tree

4 files changed

+66
-6
lines changed

4 files changed

+66
-6
lines changed

codecov_auth/authentication/repo_auth.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from django.utils import timezone
1010
from jwt import PyJWTError
1111
from rest_framework import authentication, exceptions, serializers
12-
from rest_framework.exceptions import NotAuthenticated
12+
from rest_framework.exceptions import NotAuthenticated, ValidationError
1313
from rest_framework.response import Response
1414
from rest_framework.views import exception_handler
1515
from shared.django_apps.codecov_auth.models import Owner
@@ -200,7 +200,7 @@ def authenticate(
200200
if not using_global_token:
201201
return None # continue to next auth class
202202

203-
service = global_tokens[token]
203+
service = global_tokens.get(token, "")
204204
upload_info = get_upload_info_from_request_path(request)
205205
if upload_info is None:
206206
return None # continue to next auth class
@@ -257,7 +257,7 @@ def authenticate_credentials(
257257

258258
try:
259259
repository = get_repo_with_github_actions_oidc_token(token)
260-
except (ObjectDoesNotExist, PyJWTError):
260+
except (ObjectDoesNotExist, PyJWTError, ValidationError):
261261
return None # continue to next auth class
262262

263263
log.info(

upload/helpers.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import re
33
from json import dumps
44
from typing import Any, Dict, Optional
5+
from urllib.parse import urlparse
56

67
import jwt
78
from asgiref.sync import async_to_sync
@@ -237,12 +238,15 @@ def parse_params(data: Dict[str, Any]) -> Dict[str, Any]:
237238
def get_repo_with_github_actions_oidc_token(token: str) -> Repository:
238239
unverified_contents = jwt.decode(token, options={"verify_signature": False})
239240
token_issuer = str(unverified_contents.get("iss"))
240-
if token_issuer == "https://token.actions.githubusercontent.com":
241+
parsed_url = urlparse(token_issuer)
242+
if parsed_url.hostname == "token.actions.githubusercontent.com":
241243
service = "github"
242244
jwks_url = "https://token.actions.githubusercontent.com/.well-known/jwks"
243245
else:
244246
service = "github_enterprise"
245247
github_enterprise_url = get_config("github_enterprise", "url")
248+
if not github_enterprise_url:
249+
raise ValidationError("GitHub Enterprise URL configuration is not set")
246250
# remove trailing slashes if present
247251
github_enterprise_url = re.sub(r"/+$", "", github_enterprise_url)
248252
jwks_url = f"{github_enterprise_url}/_services/token/.well-known/jwks"
@@ -525,7 +529,7 @@ def insert_commit(
525529
return commit
526530

527531

528-
def get_global_tokens() -> Dict[str, Any]:
532+
def get_global_tokens() -> Dict[str | None, Any]:
529533
"""
530534
Enterprise only: check the config to see if global tokens were set for this organization's uploads.
531535

upload/tests/test_helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ def test_determine_repo_for_upload_github_actions(codecov_vcr):
335335
repository = RepositoryFactory.create()
336336
token = jwt.encode(
337337
{
338-
"iss": "https://token.actions.githubusercontent.com",
338+
"iss": "https://token.actions.githubusercontent.com/abcdefg",
339339
"aud": [f"{settings.CODECOV_API_URL}"],
340340
"repository": f"{repository.author.username}/{repository.name}",
341341
"repository_owner": repository.author.username,

upload/tests/views/test_uploads.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,3 +929,59 @@ def test_uploads_post_github_enterprise_oidc_auth_jwks_url(
929929
mock_jwks_client.assert_called_with(
930930
"https://example.com/_services/token/.well-known/jwks"
931931
)
932+
933+
@patch("upload.views.uploads.AnalyticsService")
934+
@patch("upload.helpers.jwt.decode")
935+
@patch("upload.helpers.PyJWKClient")
936+
def test_uploads_post_github_enterprise_oidc_auth_no_url(
937+
self,
938+
mock_jwks_client,
939+
mock_jwt_decode,
940+
analytics_service_mock,
941+
):
942+
mock_config_helper(self.mocker, configs={"github_enterprise.url": None})
943+
self.mocker.patch(
944+
"shared.api_archive.archive.StorageService.create_presigned_put",
945+
return_value="presigned put",
946+
)
947+
self.mocker.patch("upload.views.uploads.trigger_upload_task", return_value=True)
948+
949+
repository = RepositoryFactory(
950+
name="the_repo",
951+
author__username="codecov",
952+
author__service="github_enterprise",
953+
author__upload_token_required_for_public_repos=True,
954+
private=False,
955+
)
956+
mock_jwt_decode.return_value = {
957+
"repository": f"url/{repository.name}",
958+
"repository_owner": repository.author.username,
959+
"iss": "https://enterprise-client.actions.githubusercontent.com",
960+
"audience": [settings.CODECOV_API_URL],
961+
}
962+
token = "ThisValueDoesNotMatterBecauseOf_mock_jwt_decode"
963+
964+
commit = CommitFactory(repository=repository)
965+
commit_report = CommitReport.objects.create(commit=commit, code="code")
966+
967+
client = APIClient()
968+
url = reverse(
969+
"new_upload.uploads",
970+
args=[
971+
"github_enterprise",
972+
"codecov::::the_repo",
973+
commit.commitid,
974+
commit_report.code,
975+
],
976+
)
977+
response = client.post(
978+
url,
979+
{
980+
"state": "uploaded",
981+
"flags": ["flag1", "flag2"],
982+
"version": "version",
983+
},
984+
headers={"Authorization": f"token {token}"},
985+
)
986+
assert response.status_code == 401
987+
assert response.json().get("detail") == "Not valid tokenless upload"

0 commit comments

Comments
 (0)