Skip to content

Commit

Permalink
make token slice safer
Browse files Browse the repository at this point in the history
  • Loading branch information
nora-codecov committed May 6, 2024
1 parent fcf331a commit 3c7ce5f
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 14 deletions.
27 changes: 22 additions & 5 deletions codecov_auth/authentication/repo_auth.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import random
import re
from datetime import datetime
from typing import List
Expand Down Expand Up @@ -231,38 +232,54 @@ def authenticate_credentials(self, key):
)


def get_token_slice_for_logging(token):
"""
temporary - for troubleshooting OIDC auth
"""
random_int = random.randint(0, 999999999)
if token is None:
return f"Token is None, here is a random int {random_int}"
if len(str(token)) > 49:
# preferred
return str(token)[39:49]
return f"Token is short, here is a random int {random_int}"


class GitHubOIDCTokenAuthentication(authentication.TokenAuthentication):
def authenticate_credentials(self, token):
token_slice_for_logging = get_token_slice_for_logging(token=token)
log.info(
"In GitHubOIDCTokenAuthentication 1",
extra=dict(
token_slice=str(token)[39:49] if token else None,
token_slice=token_slice_for_logging,
),
)
if not token or is_uuid(token):
log.info(
"In GitHubOIDCTokenAuthentication 2",
extra=dict(
token_slice=str(token)[39:49] if token else None,
token_slice=token_slice_for_logging,
is_uuid=is_uuid(token),
),
)
return None # continue to next auth class
try:
repository = get_repo_with_github_actions_oidc_token(token)
repository = get_repo_with_github_actions_oidc_token(
token, token_slice=token_slice_for_logging
)
except (ObjectDoesNotExist, PyJWTError) as e:
log.info(
"In GitHubOIDCTokenAuthentication 10",
extra=dict(
token_slice=str(token)[39:49],
token_slice=token_slice_for_logging,
error_message=f"{e}",
),
)
return None # continue to next auth class

log.info(
"In GitHubOIDCTokenAuthentication Success",
extra=dict(token_slice=str(token)[39:49], repository=str(repository)),
extra=dict(token_slice=token_slice_for_logging, repository=str(repository)),
)

return (
Expand Down
24 changes: 24 additions & 0 deletions codecov_auth/tests/unit/test_repo_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
RepositoryTokenAuthentication,
TokenlessAuth,
TokenlessAuthentication,
get_token_slice_for_logging,
)
from codecov_auth.models import SERVICE_GITHUB, OrganizationLevelToken, RepositoryToken
from codecov_auth.tests.factories import OwnerFactory
Expand Down Expand Up @@ -272,6 +273,29 @@ def test_authenticate_credentials_oidc_valid(self, mocked_get_repo_with_token, d
assert user._repository == repository
assert auth.get_scopes() == ["upload"]

@patch("codecov_auth.authentication.repo_auth.random.randint")
def test_get_token_slice_for_logging(self, rand_mock, _):
rand_mock.return_value = "0000"
result = get_token_slice_for_logging(token=None)
assert result == "Token is None, here is a random int 0000"

result = get_token_slice_for_logging(token=False)
assert result == "Token is short, here is a random int 0000"

result = get_token_slice_for_logging(token=uuid.uuid4())
assert result == "Token is short, here is a random int 0000"

result = get_token_slice_for_logging(token=123)
assert result == "Token is short, here is a random int 0000"

result = get_token_slice_for_logging(token="123")
assert result == "Token is short, here is a random int 0000"

jwt_like_str = "01234567890123456789012345678901234567890123456789"
result = get_token_slice_for_logging(token=jwt_like_str)
assert len(jwt_like_str) == 50
assert result == "9012345678"


class TestOrgLevelTokenAuthentication(object):
@override_settings(IS_ENTERPRISE=True)
Expand Down
16 changes: 7 additions & 9 deletions upload/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,13 +222,13 @@ def parse_params(data):
return v.document


def get_repo_with_github_actions_oidc_token(token):
def get_repo_with_github_actions_oidc_token(token, token_slice=None):
unverified_contents = jwt.decode(token, options={"verify_signature": False})
token_issuer = str(unverified_contents.get("iss"))
log.info(
"In GitHubOIDCTokenAuthentication 3",
extra=dict(
token_slice=str(token)[39:49],
token_slice=token_slice,
unverified_contents=unverified_contents,
token_issuer=token_issuer,
),
Expand All @@ -239,7 +239,7 @@ def get_repo_with_github_actions_oidc_token(token):
log.info(
"In GitHubOIDCTokenAuthentication 4",
extra=dict(
token_slice=str(token)[39:49],
token_slice=token_slice,
token_issuer=token_issuer,
service=service,
jwks_url=jwks_url,
Expand All @@ -251,9 +251,7 @@ def get_repo_with_github_actions_oidc_token(token):
jwks_url = f"{github_enterprise_url}/_services/token/.well-known/jwks"
log.info(

Check warning on line 252 in upload/helpers.py

View check run for this annotation

Codecov Public QA / codecov/patch

upload/helpers.py#L252

Added line #L252 was not covered by tests

Check warning on line 252 in upload/helpers.py

View check run for this annotation

Codecov - QA / codecov/patch

upload/helpers.py#L252

Added line #L252 was not covered by tests

Check warning on line 252 in upload/helpers.py

View check run for this annotation

Codecov / codecov/patch

upload/helpers.py#L252

Added line #L252 was not covered by tests
"In GitHubOIDCTokenAuthentication 5",
extra=dict(
token_slice=str(token)[39:49], service=service, jwks_url=jwks_url
),
extra=dict(token_slice=token_slice, service=service, jwks_url=jwks_url),
)
jwks_client = PyJWKClient(jwks_url)
signing_key = jwks_client.get_signing_key_from_jwt(token)
Expand All @@ -267,7 +265,7 @@ def get_repo_with_github_actions_oidc_token(token):
log.info(
"In GitHubOIDCTokenAuthentication 6",
extra=dict(
token_slice=str(token)[39:49],
token_slice=token_slice,
signing_key=signing_key,
decoded_token=data,
repo=repo,
Expand All @@ -281,12 +279,12 @@ def get_repo_with_github_actions_oidc_token(token):
log.info(
"In GitHubOIDCTokenAuthentication 7",
extra=dict(
token_slice=str(token)[39:49],
token_slice=token_slice,
author__service=service,
repo=repo,
author__username=data.get("repository_owner"),
repoid=repository.repoid,
repo_obj=str(repository),
repo_obj=str(repository), # Repo<author/name>
),
)
return repository
Expand Down

0 comments on commit 3c7ce5f

Please sign in to comment.