Skip to content

Commit 2f8a1aa

Browse files
committed
Improved test and added default exclude regexes from known web-tokens
1 parent 28c9b7b commit 2f8a1aa

File tree

2 files changed

+77
-13
lines changed

2 files changed

+77
-13
lines changed

easybuild/tools/testing.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"""
3838
import copy
3939
import os
40+
import re
4041
import sys
4142
from datetime import datetime
4243
from time import gmtime, strftime
@@ -59,6 +60,34 @@
5960
_log = fancylogger.getLogger('testing', fname=False)
6061

6162
_exclude_env_from_report = []
63+
DEFAULT_EXCLUDE_FROM_REPORT_RGX = [
64+
# From PR comments https://github.com/easybuilders/easybuild-framework/pull/4877
65+
r'AKIA[0-9A-Z]{16}', # AWS access key
66+
r'[A-Za-z0-9/+=]{40}', # AWS secret key
67+
r'eyJ[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+', # JWT token
68+
r'gh[pousr]_[A-Za-z0-9_]{36,}', # GitHub token
69+
r'xox[baprs]-[A-Za-z0-9-]+', # Slack token
70+
71+
# https://github.com/odomojuli/regextokens
72+
r'^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$', # Base64
73+
r'[1-9][0-9]+-[0-9a-zA-Z]{40}', # Twitter token
74+
r'EAACEdEose0cBA[0-9A-Za-z]+', # Facebook token
75+
r'[0-9a-fA-F]{7}.[0-9a-fA-F]{32}', # Instagram token
76+
r'AIza[0-9A-Za-z-_]{35}', # Google API key
77+
r'4/[0-9A-Za-z-_]+', # Google OAuth 2.0 Auth code
78+
r'ya29.[0-9A-Za-z-_]+', # Google OAuth 2.0 access token
79+
r'[rs]k_live_[0-9a-z]{32}', # Picatic/Stripe API key
80+
r'sqOatp-[0-9A-Za-z-_]{22}', # Square Access token
81+
r'access_token,production$[0-9a-z]{161[0-9a,]{32}', # PayPal token
82+
r'55[0-9a-fA-F]{32}', # Twilio token
83+
r'key-[0-9a-zA-Z]{32}', # Mailgun API key
84+
r'[0-9a-f]{32}-us[0-9]{1,2}', # Mailchimp API key
85+
r'[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}', # Google Cloud Oauth 2.0 token
86+
r'[A-Za-z0-9_]{21}--[A-Za-z0-9_]{8}', # Google Cloud API key
87+
r'[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}', # Heroku token
88+
r'sk-(.*-)?[A-Za-z0-9]{20}T3BlbkFJ[A-Za-z0-9]{20}', # OpenAI API key
89+
r'waka_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', # WakaTime API key
90+
]
6291

6392

6493
def regtest(easyconfig_paths, modtool, build_specs=None):
@@ -282,8 +311,10 @@ def create_test_report(msg, ecs_with_res, init_session_state, pr_nrs=None, gist_
282311
for key in sorted(environ_dump.keys()):
283312
if env_filter is not None and env_filter.search(key):
284313
continue
285-
else:
286-
environment += ["%s = %s" % (key, environ_dump[key])]
314+
value = environ_dump[key]
315+
if any(re.match(rgx, value) for rgx in DEFAULT_EXCLUDE_FROM_REPORT_RGX):
316+
continue
317+
environment += ["%s = %s" % (key, value)]
287318

288319
environment = list(filter(
289320
lambda x: not any(y in x.upper() for y in _exclude_env_from_report),

test/framework/github.py

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,42 +1318,75 @@ def test_github_create_test_report(self):
13181318
'log_file': logfile,
13191319
}),
13201320
]
1321-
test_remove_name = 'REMOVEME'
1322-
test_remove_val = 'test-abc'
1321+
environ = {
1322+
'USER': 'test',
1323+
'DONT_REMOVE_ME': 'test-123',
1324+
}
1325+
JWT_HDR = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9'
1326+
JWT_PLD = 'eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNzA4MzQ1MTIzLCJleHAiOjE3MDgzNTUxMjN9'
1327+
JWT_SIG = 'SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'
1328+
secret_environ = {
1329+
'REMOVEME': 'test-abc',
1330+
'ReMoVeMe2': 'TeSt-xyz',
1331+
1332+
'AWS_ACCESS_KEY': 'AKIAIOSFODNN7EXAMPLE',
1333+
'AWS_SECRET_KEY': 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
1334+
'JWT': '.'.join([JWT_HDR, JWT_PLD, JWT_SIG]),
1335+
'GH_TOKEN': 'ghp_123456789_ABCDEFGHIJKlmnopqrstuvwxyz',
1336+
'SLACK_TOKEN': 'xoxb-1234567890-1234567890123-ABCDEFabcdef',
1337+
}
13231338
init_session_state = {
13241339
'easybuild_configuration': ['EASYBUILD_DEBUG=1'],
1325-
'environment': {
1326-
'USER': 'test',
1327-
test_remove_name: test_remove_val,
1328-
},
1340+
'environment': {**environ, **secret_environ},
13291341
'module_list': [{'mod_name': 'test'}],
13301342
'system_info': {'name': 'test'},
13311343
'time': gmtime(0),
13321344
}
13331345

13341346
# Test exclude_env_from_report_add/clear
1335-
exclude_env_from_report_add(test_remove_name.lower()) # Also check that the name is uppercased in the check
1347+
exclude_env_from_report_add('REMOVEME'.lower()) # Also check that the name is uppercased in the check
13361348

13371349
res = create_test_report("just a test", ecs_with_res, init_session_state)
13381350
patterns = [
13391351
"**SUCCESS** _test.eb_",
13401352
"**FAIL (build issue)** _fail.eb_",
13411353
"01 Jan 1970 00:00:00",
13421354
"EASYBUILD_DEBUG=1",
1355+
"DONT_REMOVE_ME = test-123",
13431356
]
13441357
for pattern in patterns:
13451358
self.assertIn(pattern, res['full'])
1346-
self.assertNotIn(test_remove_name, res['full'])
1359+
1360+
# Test that excluded patterns works by matching also partial strings
1361+
exclude_patterns1 = [
1362+
'REMOVEME',
1363+
'ReMoVeMe2',
1364+
]
1365+
# Test that known token regexes for ENV vars are excluded by default
1366+
exclude_patterns2 = [
1367+
'AWS_ACCESS_KEY',
1368+
'AWS_SECRET_KEY',
1369+
'JWT',
1370+
'GH_TOKEN',
1371+
'SLACK_TOKEN',
1372+
]
1373+
for pattern in exclude_patterns1 + exclude_patterns2:
1374+
# .lower() test that variable name is not case sensitive for excluding
1375+
self.assertNotIn(pattern.lower(), res['full'])
13471376

13481377
exclude_env_from_report_clear()
1378+
patterns += exclude_patterns1
13491379

13501380
res = create_test_report("just a test", ecs_with_res, init_session_state)
1351-
patterns.append(f"{test_remove_name} = {test_remove_val}")
13521381
for pattern in patterns:
13531382
self.assertIn(pattern, res['full'])
13541383

13551384
for pattern in patterns[:2]:
1356-
self.assertIn(pattern, res['full'])
1385+
self.assertIn(pattern, res['overview'])
1386+
1387+
for pattern in exclude_patterns2:
1388+
# .lower() test that variable name is not case sensitive for excluding
1389+
self.assertNotIn(pattern.lower(), res['full'])
13571390

13581391
# mock create_gist function, we don't want to actually create a gist every time we run this test...
13591392
def fake_create_gist(*args, **kwargs):
@@ -1371,7 +1404,7 @@ def fake_create_gist(*args, **kwargs):
13711404
self.assertIn(pattern, res['full'])
13721405

13731406
for pattern in patterns[:3]:
1374-
self.assertIn(pattern, res['full'])
1407+
self.assertIn(pattern, res['overview'])
13751408

13761409
self.assertIn("**SUCCESS** _test.eb_", res['overview'])
13771410

0 commit comments

Comments
 (0)