diff --git a/test/requirements.txt b/test/requirements.txt new file mode 100644 index 0000000..c4188f7 --- /dev/null +++ b/test/requirements.txt @@ -0,0 +1,3 @@ +selenium==3.141.0 + +pytest==6.2.5 diff --git a/test/unit/conftest.py b/test/unit/conftest.py new file mode 100644 index 0000000..7f1798a --- /dev/null +++ b/test/unit/conftest.py @@ -0,0 +1,105 @@ +import hashlib +import json +import os +import re + +import pytest + +from selenium import webdriver +from selenium.webdriver.chrome.options import Options + +from selenium.webdriver.common.desired_capabilities import DesiredCapabilities + +class Data: + + def process_browser_log_entry(self, entry): + response = json.loads(entry['message'])['message'] + return response + + def __init__(self): + + caps = DesiredCapabilities.CHROME + caps['goog:loggingPrefs'] = {'performance': 'ALL'} + + + chrome_options = Options() + chrome_options.add_argument("no-sandbox") + chrome_options.add_argument("headless") + chrome_options.add_argument("start-maximized") + chrome_options.add_argument("window-size=1900,1080"); + + self.driver = webdriver.Chrome(desired_capabilities=caps, options=chrome_options) + + self.urls = [] + self.suffux_path = os.path.realpath('./build') + self.urls += [os.path.join(dp, f) for dp, dn, fn in os.walk(os.path.expanduser('./build')) for f in fn if f.endswith('.html')] + + + data = { + 'page_load_resource_links': {}, + 'source_files': [], + 'hyperlinks': {} + } + + + for check_file in self.urls: + + check_url = 'file://' + self.suffux_path + check_file.replace('./build','') + source_file = check_file.replace('./build','')[1:] + + if source_file not in data['source_files']: + data['source_files'].append(source_file) + + self.driver.get(check_url) + + events = [self.process_browser_log_entry(entry) for entry in self.driver.get_log('performance')] + + for entry in events: + + if entry['method'] == 'Network.requestWillBeSent': + + http_status = str([response['params']['response']['status'] for response in events if response['method'] == 'Network.responseReceived' and response['params']['requestId'] == entry['params']['requestId']]).replace('[', '').replace(']', '') + + url = str(entry['params']['request']['url']) + + + url_id = hashlib.md5(bytes(url, 'utf-8')).hexdigest() + + + if re.match("^http|file.*", url) is not None: + + source_file_line_number = '' + + if 'lineNumber' in entry['params']['initiator']: + + source_file_line_number = str(entry['params']['initiator']['lineNumber']) + + request_protocol = re.match("^[http|file]+s?", url).group(0) + + if re.match("^http.*", url) is not None: + + domain = re.match(r'^([a-z]+[\.|a-z|]+)',url.replace(request_protocol + '://', '')).group(0) + + request_path = url.replace(request_protocol + '://','').replace(domain, '')[1:] + + + elif re.match("^file.*", url) is not None: + + domain = 'file' + + request_path = url.replace(request_protocol + '://','')[1:] + + if url_id in data['page_load_resource_links']: + + data['page_load_resource_links'][url_id]['source_files'].append({'name': source_file, 'line_number': source_file_line_number, 'http_status': http_status}) + + else: + + data['page_load_resource_links'][url_id] = {'url': url, 'request_protocol': request_protocol, 'domain': domain, 'request_path': request_path, 'source_files': [ {'name': source_file, 'line_number': source_file_line_number, 'http_status': http_status} ]} + + self.test_data = data + + +print("\n"+'Creating test data') +print("\n\ntest data:\n" + json.dumps(Data().test_data, indent=2, default=str)) + diff --git a/test/unit/privacy_test.py b/test/unit/privacy_test.py new file mode 100644 index 0000000..4fd5997 --- /dev/null +++ b/test/unit/privacy_test.py @@ -0,0 +1,38 @@ +import pytest + +from conftest import Data + +class Test: + + data = Data() + + def setup_method(self): + + self.approved_external_requests = { + 'gitlab.com': [ + 'api/v4/projects/nofusscomputing%2Finfrastructure%2Fwebsite', + 'uploads/-/system/user/avatar/4125177/avatar.png' + ] + } + + + @pytest.mark.parametrize( + argnames='data', + argvalues=[link for url_id, link in data.test_data['page_load_resource_links'].items() if link['request_protocol'][0:4] =='http'], + ids=[url_id for url_id, link in data.test_data['page_load_resource_links'].items() if link['request_protocol'][0:4] =='http'] + ) + def test_page_external_requests(self, data): + + check_url = data['url'] + + assert data['request_protocol'] == 'https', f"Insecure Request to domain [{data['request_path']}] in source files [{data['source_files']}]" + + assert data['domain'] in self.approved_external_requests, f"A request is being made to a non-approved domain [{data['domain']}] path [{data['request_path']}] in source files [{data['source_files']}]" + + assert data['request_path'] in self.approved_external_requests[data['domain']], f"A request is being made to a non-approved path [{data['request_path']}] on domain [{data['domain']}] in source files [{data['source_files']}]" + + + + def teardown_method(self): + pass +