def insert_test_results(site_id: int, scan_id: int, tests: list, response_headers: dict, status_code: int = None) -> dict: with get_cursor() as cur: tests_failed = tests_passed = 0 score_with_extra_credit = uncurved_score = 100 for test in tests: name = test.pop('name') expectation = test.pop('expectation') passed = test.pop('pass') result = test.pop('result') score_modifier = test.pop('score_modifier') # Keep track of how many tests passed or failed if passed: tests_passed += 1 else: tests_failed += 1 # And keep track of the score score_with_extra_credit += score_modifier if score_modifier < 0: uncurved_score += score_modifier # Insert test result to the database cur.execute( """INSERT INTO tests (site_id, scan_id, name, expectation, result, pass, output, score_modifier) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)""", (site_id, scan_id, name, expectation, result, passed, dumps(test), score_modifier)) # Only record the full score if the uncurved score already receives an A score = score_with_extra_credit if uncurved_score >= MINIMUM_SCORE_FOR_EXTRA_CREDIT else uncurved_score # Now we need to update the scans table score, grade, likelihood_indicator = get_grade_and_likelihood_for_score( score) # Update the scans table cur.execute( """UPDATE scans SET (end_time, tests_failed, tests_passed, grade, score, likelihood_indicator, state, response_headers, status_code) = (NOW(), %s, %s, %s, %s, %s, %s, %s, %s) WHERE id = %s RETURNING *""", (tests_failed, tests_passed, grade, score, likelihood_indicator, STATE_FINISHED, dumps(response_headers), status_code, scan_id)) row = dict(cur.fetchone()) return row
def insert_test_results(site_id: int, scan_id: int, tests: list, response_headers: dict, status_code: int=None) -> dict: with get_cursor() as cur: tests_failed = tests_passed = 0 score_with_extra_credit = uncurved_score = 100 for test in tests: name = test.pop('name') expectation = test.pop('expectation') passed = test.pop('pass') result = test.pop('result') score_modifier = test.pop('score_modifier') # Keep track of how many tests passed or failed if passed: tests_passed += 1 else: tests_failed += 1 # And keep track of the score score_with_extra_credit += score_modifier if score_modifier < 0: uncurved_score += score_modifier # Insert test result to the database cur.execute("""INSERT INTO tests (site_id, scan_id, name, expectation, result, pass, output, score_modifier) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)""", (site_id, scan_id, name, expectation, result, passed, dumps(test), score_modifier)) # Only record the full score if the uncurved score already receives an A score = score_with_extra_credit if uncurved_score >= MINIMUM_SCORE_FOR_EXTRA_CREDIT else uncurved_score # Now we need to update the scans table score, grade, likelihood_indicator = get_grade_and_likelihood_for_score(score) # Update the scans table cur.execute("""UPDATE scans SET (end_time, tests_failed, tests_passed, grade, score, likelihood_indicator, state, response_headers, status_code) = (NOW(), %s, %s, %s, %s, %s, %s, %s, %s) WHERE id = %s RETURNING *""", (tests_failed, tests_passed, grade, score, likelihood_indicator, STATE_FINISHED, dumps(response_headers), status_code, scan_id)) row = dict(cur.fetchone()) return row
def insert_test_results(site_id: int, scan_id: int, tests: list, response_headers: dict) -> dict: with get_cursor() as cur: tests_failed = tests_passed = 0 score = 100 for test in tests: name = test.pop('name') expectation = test.pop('expectation') passed = test.pop('pass') result = test.pop('result') score_modifier = test.pop('score_modifier') # Keep track of how many tests passed or failed if passed: tests_passed += 1 else: tests_failed += 1 # And keep track of the score score += score_modifier # Insert test result to the database cur.execute( """INSERT INTO tests (site_id, scan_id, name, expectation, result, pass, output, score_modifier) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)""", (site_id, scan_id, name, expectation, result, passed, dumps(test), score_modifier)) # Now we need to update the scans table score, grade, likelihood_indicator = get_grade_and_likelihood_for_score( score) # Update the scans table cur.execute( """UPDATE scans SET (end_time, tests_failed, tests_passed, grade, score, likelihood_indicator, state, response_headers) = (NOW(), %s, %s, %s, %s, %s, %s, %s) WHERE id = %s RETURNING *""", (tests_failed, tests_passed, grade, score, likelihood_indicator, STATE_FINISHED, dumps(response_headers), scan_id)) row = dict(cur.fetchone()) return row
def insert_test_results(site_id: int, scan_id: int, tests: list, response_headers: dict) -> dict: with get_cursor() as cur: tests_failed = tests_passed = 0 score = 100 for test in tests: name = test.pop('name') expectation = test.pop('expectation') passed = test.pop('pass') result = test.pop('result') score_modifier = test.pop('score_modifier') # Keep track of how many tests passed or failed if passed: tests_passed += 1 else: tests_failed += 1 # And keep track of the score score += score_modifier # Insert test result to the database cur.execute("""INSERT INTO tests (site_id, scan_id, name, expectation, result, pass, output, score_modifier) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)""", (site_id, scan_id, name, expectation, result, passed, dumps(test), score_modifier)) # Now we need to update the scans table score, grade, likelihood_indicator = get_grade_and_likelihood_for_score(score) # Update the scans table cur.execute("""UPDATE scans SET (end_time, tests_failed, tests_passed, grade, score, likelihood_indicator, state, response_headers) = (NOW(), %s, %s, %s, %s, %s, %s, %s) WHERE id = %s RETURNING *""", (tests_failed, tests_passed, grade, score, likelihood_indicator, STATE_FINISHED, dumps(response_headers), scan_id)) row = dict(cur.fetchone()) return row
def scan(hostname, **kwargs): """Performs an Observatory scan, but doesn't require any database/redis backing. Given the lowered security concerns due to not being a public API, you can use this to scan arbitrary ports and paths. Args: hostname (str): domain name for host to be scanned Kwargs: http_port (int): port to scan for HTTP, instead of 80 https_port (int): port to be scanned for HTTPS, instead of 443 path (str): path to scan, instead of "/" verify (bool): whether to enable or disable certificate verification, enabled by default. This can allow tested sites to pass the HSTS and HPKP tests, even with self-signed certificates. cookies (dict): Cookies sent to the system being scanned. Matches the requests cookie dict. headers (dict): HTTP headers sent to the system being scanned. Format matches the requests headers dict. Returns: A dict representing the analyze (scan) and getScanResults (test) API call. Example: { 'scan': { 'grade': 'A' ... }, 'test': { 'content-security-policy': { 'pass': True ... } } } """ # Always allow localhost scans when run in this way httpobs.conf.SCANNER_ALLOW_LOCALHOST = True # Attempt to retrieve all the resources, not capturing exceptions reqs = retrieve_all(hostname, **kwargs) # If we can't connect at all, let's abort the test if reqs['responses']['auto'] is None: return {'error': 'site down'} # Get all the results results = [test(reqs) for test in tests] for result in results: result['score_description'] = get_score_description(result['result']) # Get the score, grade, etc. grades = get_grade_and_likelihood_for_score(100 + sum([result.get('score_modifier', 0) for result in results])) tests_passed = sum([1 if result.get('pass') else 0 for result in results]) # Return the results return({ 'scan': { 'grade': grades[1], 'likelihood_indicator': grades[2], 'response_headers': dict(reqs['responses']['auto'].headers), 'score': grades[0], 'tests_failed': NUM_TESTS - tests_passed, 'tests_passed': tests_passed, 'tests_quantity': NUM_TESTS, }, 'tests': {result.pop('name'): result for result in results} })
def scan(hostname, **kwargs): """Performs an Observatory scan, but doesn't require any database/redis backing. Given the lowered security concerns due to not being a public API, you can use this to scan arbitrary ports and paths. Args: hostname (str): domain name for host to be scanned. Must not include protocol (http://, https://) or port number (:80). Kwargs: http_port (int): port to scan for HTTP, instead of 80 https_port (int): port to be scanned for HTTPS, instead of 443 path (str): path to scan, instead of "/" verify (bool): whether to enable or disable certificate verification, enabled by default. This can allow tested sites to pass the HSTS and HPKP tests, even with self-signed certificates. cookies (dict): Cookies sent to the system being scanned. Matches the requests cookie dict. headers (dict): HTTP headers sent to the system being scanned. Format matches the requests headers dict. Returns: A dict representing the analyze (scan) and getScanResults (test) API call. Example: { 'scan': { 'grade': 'A' ... }, 'test': { 'content-security-policy': { 'pass': True ... } } } """ # Always allow localhost scans when run in this way httpobs.conf.SCANNER_ALLOW_LOCALHOST = True # Attempt to retrieve all the resources, not capturing exceptions reqs = retrieve_all(hostname, **kwargs) # If we can't connect at all, let's abort the test if reqs['responses']['auto'] is None: return {'error': 'site down'} # Get all the results results = [test(reqs) for test in tests] for result in results: result['score_description'] = get_score_description(result['result']) # Get the score, grade, etc. grades = get_grade_and_likelihood_for_score( 100 + sum([result.get('score_modifier', 0) for result in results])) tests_passed = sum([1 if result.get('pass') else 0 for result in results]) # Return the results return ({ 'scan': { 'grade': grades[1], 'likelihood_indicator': grades[2], 'response_headers': dict(reqs['responses']['auto'].headers), 'score': grades[0], 'tests_failed': NUM_TESTS - tests_passed, 'tests_passed': tests_passed, 'tests_quantity': NUM_TESTS, }, 'tests': {result.pop('name'): result for result in results} })
def scan(hostname, **kwargs): """Performs an Observatory scan, but doesn't require any database/redis backing. Given the lowered security concerns due to not being a public API, you can use this to scan arbitrary ports and paths. Args: hostname (str): domain name for host to be scanned. Must not include protocol (http://, https://) or port number (:80). Kwargs: http_port (int): port to scan for HTTP, instead of 80 https_port (int): port to be scanned for HTTPS, instead of 443 path (str): path to scan, instead of "/" verify (bool): whether to enable or disable certificate verification, enabled by default. This can allow tested sites to pass the HSTS and HPKP tests, even with self-signed certificates. cookies (dict): Cookies sent to the system being scanned. Matches the requests cookie dict. headers (dict): HTTP headers sent to the system being scanned. Format matches the requests headers dict. Returns: A dict representing the analyze (scan) and getScanResults (test) API call. Example: { 'scan': { 'grade': 'A' ... }, 'test': { 'content-security-policy': { 'pass': True ... } } } """ # Always allow localhost scans when run in this way httpobs.conf.SCANNER_ALLOW_LOCALHOST = True # Attempt to retrieve all the resources, not capturing exceptions reqs = retrieve_all(hostname, **kwargs) # If we can't connect at all, let's abort the test if reqs['responses']['auto'] is None: return {'error': 'site down'} # Code based on httpobs.database.insert_test_results tests_failed = tests_passed = 0 score_with_extra_credit = uncurved_score = 100 results = {} for test in tests: # Get result for this test result = test(reqs) # Add the result with a score_description result['score_description'] = get_score_description(result['result']) results[result.pop('name')] = result # Keep track of how many tests passed or failed if result.get('pass'): tests_passed += 1 else: tests_failed += 1 # And keep track of the score score_modifier = result.get('score_modifier') score_with_extra_credit += score_modifier if score_modifier < 0: uncurved_score += score_modifier # Only record the full score if the uncurved score already receives an A score = score_with_extra_credit if uncurved_score >= MINIMUM_SCORE_FOR_EXTRA_CREDIT else uncurved_score # Get the score, grade, etc. score, grade, likelihood_indicator = get_grade_and_likelihood_for_score( score) # Return the results return ({ 'scan': { 'grade': grade, 'likelihood_indicator': likelihood_indicator, 'response_headers': dict(reqs['responses']['auto'].headers), 'score': score, 'tests_failed': tests_failed, 'tests_passed': tests_passed, 'tests_quantity': NUM_TESTS, }, 'tests': results })