Skip to content

Commit 4e5da38

Browse files
Merge pull request #4925 from linuxfoundation/unicron-add-stage-filter-to-ddog-scan-tools-prod
Address vulns, add DDog env/stage filtering, collapse more API URLs into single templates, add branch sync script
2 parents cfce1ed + da99c56 commit 4e5da38

38 files changed

Lines changed: 1016 additions & 672 deletions

cla-backend-go/events/repository.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,10 @@ func (repo *repository) SearchEvents(params *eventOps.SearchEventsParams, pageSi
477477
case params.ProjectSFID != nil:
478478
// search by projectSFID
479479
indexName = EventProjectSFIDEventTypeIndex
480-
condition = expression.Key("event_project_sfid").Equal(expression.Value(params.ProjectSFID)).And(expression.Key("event_type").Equal(expression.Value(params.EventType)))
480+
condition = expression.Key("event_project_sfid").Equal(expression.Value(params.ProjectSFID))
481+
if params.EventType != nil {
482+
condition = condition.And(expression.Key("event_type").Equal(expression.Value(params.EventType)))
483+
}
481484
pk = "event_project_sfid"
482485
sk = "event_type"
483486
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.11

cla-backend-go/telemetry/datadog_otlp.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ func WrapHTTPHandler(next http.Handler) http.Handler {
191191
p = reUUIDLike.ReplaceAllString(p, "/{invalid-uuid}$1")
192192
p = reUUIDHexDash36.ReplaceAllString(p, "/{invalid-uuid}$1")
193193
p = reNumericID.ReplaceAllString(p, "/{id}$1")
194+
p = reNumericID.ReplaceAllString(p, "/{id}$1")
194195
// Salesforce IDs: valid vs invalid
195196
p = reSFIDValid.ReplaceAllString(p, "/{sfid}$1")
196197
p = reSFIDLike.ReplaceAllString(p, "/{invalid-sfid}$1")

cla-backend/cla/auth.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
import os
88

99
import requests
10-
from jose import jwt
10+
import json
11+
12+
import jwt
13+
from jwt.algorithms import RSAAlgorithm
14+
from jwt.exceptions import ExpiredSignatureError, InvalidTokenError, PyJWTError
1115

1216
import cla
1317

@@ -81,7 +85,7 @@ def authenticate_user(headers):
8185

8286
try:
8387
unverified_header = jwt.get_unverified_header(token)
84-
except jwt.JWTError as e:
88+
except PyJWTError as e:
8589
cla.log.error(e)
8690
raise AuthError('unable to decode claims')
8791

@@ -99,19 +103,20 @@ def authenticate_user(headers):
99103
# print("JWKS kids:", [key["kid"] for key in jwks["keys"]])
100104
if rsa_key:
101105
try:
106+
public_key = RSAAlgorithm.from_jwk(json.dumps(rsa_key))
107+
jwt_algorithms = algorithms if isinstance(algorithms, (list, tuple, set)) else [algorithms]
102108
payload = jwt.decode(
103109
token,
104-
rsa_key,
105-
algorithms=algorithms,
110+
public_key,
111+
algorithms=list(jwt_algorithms),
106112
options={
107-
'verify_at_hash': False,
108113
'verify_aud': False
109114
}
110115
)
111-
except jwt.ExpiredSignatureError as e:
116+
except ExpiredSignatureError as e:
112117
cla.log.error(e)
113118
raise AuthError('token is expired')
114-
except jwt.JWTClaimsError as e:
119+
except InvalidTokenError as e:
115120
cla.log.error(e)
116121
raise AuthError('incorrect claims')
117122
except Exception as e:

cla-backend/cla/controllers/github_application.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import requests
88
from github import BadCredentialsException, UnknownObjectException, GithubException, GithubIntegration, Github
9-
from jose import jwt
9+
import jwt
1010
from requests.exceptions import RequestException
1111

1212
import cla
@@ -30,9 +30,7 @@ def repos(self):
3030
def __init__(self, installation_id):
3131
self.installation_id = installation_id
3232

33-
cla.log.debug('Initializing github application - installation_id: {}, app id: {}, private key'
34-
' (minus header): {}...'.
35-
format(self.installation_id, self.app_id, self.private_key[32:38]))
33+
cla.log.debug('Initializing github application - installation_id: {}, app id: {}'.format(self.installation_id, self.app_id))
3634

3735
try:
3836
integration = GithubCLAIntegration(self.app_id, self.private_key)
@@ -77,15 +75,8 @@ def create_check_run(self, repository_name, data):
7775

7876

7977
class GithubCLAIntegration(GithubIntegration):
80-
"""
81-
Custom GithubIntegration using python-jose instead of pyjwt for token creation.
82-
"""
8378

8479
def create_jwt(self):
85-
"""
86-
Overloaded to use python-jose instead of pyjwt.
87-
Couldn't get it working with pyjwt.
88-
"""
8980
now = int(time.time())
9081
payload = {
9182
"iat": now,

cla-backend/cla/models/github_models.py

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import time
1515
import uuid
1616
from typing import List, Optional, Union, Tuple, Iterable
17+
from collections.abc import MutableMapping
1718

1819
import cla
1920
import falcon
@@ -207,7 +208,7 @@ def user_from_session(self, request, get_redirect_url):
207208
fn = "github_models.user_from_session"
208209
cla.log.debug(f"{fn} - loading session from request: {request}...")
209210
session = self._get_request_session(request)
210-
cla.log.debug(f"{fn} - session: {session}")
211+
cla.log.debug(f"{fn} - session loaded (keys={list(session.keys())})")
211212

212213
# We can already have token in the session
213214
if "github_oauth2_token" in session:
@@ -222,7 +223,7 @@ def user_from_session(self, request, get_redirect_url):
222223
authorization_url, csrf_token = self.get_authorization_url_and_state(None, None, None, ["user:email"], state='user-from-session')
223224
cla.log.debug(f"{fn} - obtained GitHub OAuth2 state from authorization - storing CSRF token in the session...")
224225
session["github_oauth2_state"] = csrf_token
225-
cla.log.debug(f"{fn} - GitHub OAuth2 request with CSRF token {csrf_token} - sending user to {authorization_url}")
226+
cla.log.debug(f"{fn} - redirecting user to GitHub OAuth2 authorization URL")
226227
# We must redirect to GitHub OAuth app for authentication, it will return you to /v2/github/installation which will handle returning user data
227228
if get_redirect_url:
228229
cla.log.debug(f"{fn} - sending redirect_url via 202 HTTP status JSON payload")
@@ -246,7 +247,7 @@ def sign_request(self, installation_id, github_repository_id, change_request_id,
246247
# Not sure if we need a different token for each installation ID...
247248
cla.log.debug(f"{fn} - Loading session from request: {request}...")
248249
session = self._get_request_session(request)
249-
cla.log.debug(f"{fn} - Adding github details to session: {session} which is type: {type(session)}...")
250+
cla.log.debug(f"{fn} - Adding github details to session: {list(session.keys())} which is type: {type(session)}...")
250251
session["github_installation_id"] = installation_id
251252
session["github_repository_id"] = github_repository_id
252253
session["github_change_request_id"] = change_request_id
@@ -267,7 +268,7 @@ def sign_request(self, installation_id, github_repository_id, change_request_id,
267268
)
268269
cla.log.debug(f"{fn} - Obtained GitHub OAuth2 state from authorization - storing state in the session...")
269270
session["github_oauth2_state"] = state
270-
cla.log.debug(f"{fn} - GitHub OAuth2 request with state {state} - sending user to {authorization_url}")
271+
cla.log.debug(f"{fn} - redirecting user to GitHub OAuth2 authorization URL")
271272
raise falcon.HTTPFound(authorization_url)
272273

273274
def _get_request_session(self, request) -> dict: # pylint: disable=no-self-use
@@ -277,17 +278,31 @@ def _get_request_session(self, request) -> dict: # pylint: disable=no-self-use
277278
fn = "cla.models.github_models._get_request_session"
278279
session = request.context.get("session")
279280
if session is None:
280-
cla.log.warning(f"Session is empty for request: {request}")
281-
cla.log.debug(f"{fn} - loaded session: {session}")
281+
cla.log.warning(f"{fn} - Session is empty for request: {request}")
282+
session = {}
283+
request.context["session"] = session
282284

283285
# Ensure session is a dict - getting issue where session is a string
284286
if isinstance(session, str):
285287
# convert string to a dict
286-
cla.log.debug(f"{fn} - session is type: {type(session)} - converting to dict...")
287-
session = json.loads(session)
288-
# Reset the session now that we have converted it to a dict
288+
cla.log.warning(f"{fn} - session context is a string; attempting to parse JSON")
289+
try:
290+
session = json.loads(session)
291+
except (ValueError, json.JSONDecodeError) as e:
292+
cla.log.warning(f"{fn} - unable to parse session string as JSON: {e}")
293+
session = {}
294+
295+
request.context["session"] = session
296+
297+
if not isinstance(session, MutableMapping):
298+
try:
299+
session = dict(session)
300+
except Exception:
301+
cla.log.warning(f"{fn} - session context has unsupported type {type(session)}; resetting to empty dict")
302+
session = {}
289303
request.context["session"] = session
290-
cla.log.debug(f"{fn} - session: {session} which is now type: {type(session)}...")
304+
305+
cla.log.debug(f"{fn} - loaded session (keys={list(session.keys())})")
291306

292307
return session
293308

@@ -342,7 +357,6 @@ def oauth2_redirect(self, state, code, request): # pylint: disable=too-many-arg
342357
fn = "github_models.oauth2_redirect"
343358
cla.log.debug(f"{fn} - handling GitHub OAuth2 redirect with request: {dir(request)}")
344359
session = self._get_request_session(request) # request.context['session']
345-
cla.log.debug(f"{fn} - state: {state}, code: {code}, session: {session}")
346360

347361
if "github_oauth2_state" in session:
348362
session_state = session["github_oauth2_state"]
@@ -353,29 +367,35 @@ def oauth2_redirect(self, state, code, request): # pylint: disable=too-many-arg
353367
if state != session_state:
354368
# Eventually handle user-from-session API callback
355369
try:
356-
state_data = json.loads(base64.urlsafe_b64decode(state.encode()).decode())
370+
padded_state = state + "=" * (-len(state) % 4)
371+
state_data = json.loads(base64.urlsafe_b64decode(padded_state.encode()).decode())
357372
except (ValueError, json.JSONDecodeError, binascii.Error) as err:
358-
cla.log.warning(f"{fn} - failed to decode state: {state}, error: {err}")
359-
raise falcon.HTTPBadRequest("Invalid OAuth2 state", state)
360-
state_token = state_data["csrf"]
361-
value = state_data["state"]
373+
cla.log.warning(f"{fn} - failed to decode state, error: {err}")
374+
raise falcon.HTTPBadRequest("Invalid OAuth2 state", "Invalid OAuth2 state")
375+
376+
state_token = state_data.get("csrf")
377+
value = state_data.get("state")
378+
if not state_token or not value:
379+
cla.log.warning(f"{fn} - invalid OAuth2 state payload while handling callback")
380+
raise falcon.HTTPBadRequest("Invalid OAuth2 state", "Invalid OAuth2 state")
381+
362382
if value != "user-from-session":
363-
cla.log.warning(f"{fn} - invalid GitHub OAuth2 state {session_state} expecting {state}, value: {value}")
364-
raise falcon.HTTPBadRequest("Invalid OAuth2 state", state)
383+
cla.log.warning(f"{fn} - invalid GitHub OAuth2 state while handling callback")
384+
raise falcon.HTTPBadRequest("Invalid OAuth2 state", "Invalid OAuth2 state")
365385
if state_token != session_state:
366-
cla.log.warning(f"{fn} - invalid GitHub OAuth2 state {session_state} expecting {state_token} while handling user-from-session callback")
367-
raise falcon.HTTPBadRequest(f"Invalid OAuth2 state")
386+
cla.log.warning(f"{fn} - invalid GitHub OAuth2 state while handling callback")
387+
raise falcon.HTTPBadRequest(f"Invalid OAuth2 state", "Invalid OAuth2 state")
368388
cla.log.debug(f"handling user-from-session callback")
369389
token_url = cla.conf["GITHUB_OAUTH_TOKEN_URL"]
370390
client_id = os.environ["GH_OAUTH_CLIENT_ID"]
371-
cla.log.debug(f"{fn} - using client ID {client_id}")
391+
cla.log.debug(f"{fn} - using client ID {client_id[0:5]}...")
372392
client_secret = os.environ["GH_OAUTH_SECRET"]
373393
try:
374394
token = self._fetch_token(client_id, state, token_url, client_secret, code)
375395
except Exception as err:
376396
cla.log.warning(f"{fn} - GitHub OAuth2 error: {err}. Likely bad or expired code, returning HTTP 404 state.")
377397
raise falcon.HTTPBadRequest("OAuth2 code is invalid or expired")
378-
cla.log.debug(f"{fn} - oauth2 token received for state {state}: {token} - storing token in session")
398+
cla.log.debug(f"{fn} - oauth2 token received - storing token in session")
379399
session["github_oauth2_token"] = token
380400
user = self.get_or_create_user(request)
381401
if user is None:
@@ -385,7 +405,7 @@ def oauth2_redirect(self, state, code, request): # pylint: disable=too-many-arg
385405
return user.to_dict()
386406

387407
# Get session information for this request.
388-
cla.log.debug(f"{fn} - attempting to fetch OAuth2 token for state {state}")
408+
cla.log.debug(f"{fn} - attempting to fetch OAuth2 token")
389409
installation_id = session.get("github_installation_id", None)
390410
github_repository_id = session.get("github_repository_id", None)
391411
change_request_id = session.get("github_change_request_id", None)
@@ -394,12 +414,9 @@ def oauth2_redirect(self, state, code, request): # pylint: disable=too-many-arg
394414
token_url = cla.conf["GITHUB_OAUTH_TOKEN_URL"]
395415
client_id = os.environ["GH_OAUTH_CLIENT_ID"]
396416
client_secret = os.environ["GH_OAUTH_SECRET"]
397-
cla.log.debug(
398-
f"{fn} - fetching token using {client_id[0:5]}... with state={state}, token_url={token_url}, "
399-
f"client_secret={client_secret[0:5]}, with code={code}"
400-
)
417+
cla.log.debug(f"{fn} - fetching oauth2 token with client ID: {client_id[0:5]}..., token_url: {token_url}")
401418
token = self._fetch_token(client_id, state, token_url, client_secret, code)
402-
cla.log.debug(f"{fn} - oauth2 token received for state {state}: {token} - storing token in session")
419+
cla.log.debug(f"{fn} - oauth2 token received - storing token in session")
403420
session["github_oauth2_token"] = token
404421
cla.log.debug(f"{fn} - redirecting the user back to the console: {origin_url}")
405422
return self.redirect_to_console(installation_id, github_repository_id, change_request_id, origin_url, request)
@@ -1498,7 +1515,7 @@ def get_user_data(self, session, client_id): # pylint: disable=no-self-use
14981515
fn = "cla.models.github_models.get_user_data"
14991516
token = session.get("github_oauth2_token")
15001517
if token is None:
1501-
cla.log.error(f"{fn} - unable to load github_oauth2_token from session, session is: {session}")
1518+
cla.log.error(f"{fn} - unable to load github_oauth2_token from session (keys={list(session.keys())})")
15021519
return {"error": "could not get user data from session"}
15031520

15041521
oauth2 = OAuth2Session(client_id, token=token)

cla-backend/cla/routes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ def _sanitize_api_path(path: str) -> str:
108108
p = _RE_UUID_LIKE.sub(r"/{invalid-uuid}\1", p)
109109
p = _RE_UUID_HEXDASH_36.sub(r"/{invalid-uuid}\1", p)
110110
p = _RE_NUMERIC_ID.sub(r"/{id}\1", p)
111+
p = _RE_NUMERIC_ID.sub(r"/{id}\1", p)
111112
p = _RE_SFID_VALID.sub(r"/{sfid}\1", p)
112113
p = _RE_SFID_LIKE.sub(r"/{invalid-sfid}\1", p)
113114
p = _RE_LFXID_VALID.sub(r"/{lfxid}\1", p)

0 commit comments

Comments
 (0)