def collect_and_output(client, config): # last phase, delete PID file on exit atexit.register(write_to_disk, constants.pidfile, delete=True) # --compliance was called if config.compliance: config.payload, config.content_type = ComplianceClient(config).oscap_scan() if config.payload: insights_archive = config.payload else: try: insights_archive = client.collect() except RuntimeError as e: logger.error(e) sys.exit(constants.sig_kill_bad) config.content_type = 'application/vnd.redhat.advisor.collection+tgz' if not insights_archive: sys.exit(constants.sig_kill_bad) if config.to_stdout: with open(insights_archive, 'rb') as tar_content: if six.PY3: sys.stdout.buffer.write(tar_content.read()) else: shutil.copyfileobj(tar_content, sys.stdout) else: resp = None if not config.no_upload: try: resp = client.upload(payload=insights_archive, content_type=config.content_type) except IOError as e: logger.error(str(e)) sys.exit(constants.sig_kill_bad) except ValueError as e: logger.error(str(e)) sys.exit(constants.sig_kill_bad) else: logger.info('Archive saved at %s', insights_archive) if resp: if config.to_json: print(json.dumps(resp)) if not config.payload: # delete the archive if config.keep_archive: logger.info('Insights archive retained in ' + insights_archive) else: client.delete_archive(insights_archive, delete_parent_dir=True) client.delete_cached_branch_info() # rotate eggs once client completes all work successfully try: client.rotate_eggs() except IOError: message = ("Failed to rotate %s to %s" % (constants.insights_core_newest, constants.insights_core_last_stable)) logger.debug(message) raise IOError(message)
def test_errored_rpm_call(config, call): compliance_client = ComplianceClient(config) compliance_client.get_policies = lambda: [{'ref_id': 'foo'}] compliance_client.find_scap_policy = lambda ref_id: '/usr/share/xml/scap/foo.xml' compliance_client.run_scan = lambda ref_id, policy_xml: None with raises(SystemExit): compliance_client.oscap_scan()
def test_run_scan(config, call): compliance_client = ComplianceClient(config) output_path = '/tmp/oscap_results-ref_id.xml' env = os.environ env.update({'TZ': 'UTC'}) compliance_client.run_scan('ref_id', '/nonexistent', output_path) if six.PY3: call.assert_called_with( ("oscap xccdf eval --profile ref_id --results " + output_path + ' /nonexistent'), keep_rc=True, env=env) else: call.assert_called_with( ("oscap xccdf eval --profile ref_id --results " + output_path + ' /nonexistent').encode(), keep_rc=True, env=env)
def collect_and_output(client, config): # last phase, delete PID file on exit atexit.register(write_to_disk, constants.pidfile, delete=True) # register cloud (aws) if config.portal_access or config.portal_access_no_insights: if aws_main(config): sys.exit(constants.sig_kill_ok) else: sys.exit(constants.sig_kill_bad) # --compliance was called if config.compliance: config.payload, config.content_type = ComplianceClient(config).oscap_scan() # default (below) if config.payload: insights_archive = config.payload else: try: insights_archive = client.collect() except RuntimeError as e: logger.error(e) sys.exit(constants.sig_kill_bad) config.content_type = 'application/vnd.redhat.advisor.collection+tgz' if config.no_upload: # output options for which upload is not performed if config.output_dir: client.copy_to_output_dir(insights_archive) elif config.output_file: client.copy_to_output_file(insights_archive) else: # upload the archive if not insights_archive: # no archive to upload, something went wrong sys.exit(constants.sig_kill_bad) resp = None try: resp = client.upload(payload=insights_archive, content_type=config.content_type) except (IOError, ValueError, RuntimeError) as e: logger.error(str(e)) sys.exit(constants.sig_kill_bad) if resp: if config.to_json: print(json.dumps(resp)) client.delete_cached_branch_info() # rotate eggs once client completes all work successfully try: client.rotate_eggs() except IOError: message = ("Failed to rotate %s to %s" % (constants.insights_core_newest, constants.insights_core_last_stable)) logger.debug(message) raise IOError(message)
def test_get_profiles_matching_os(config, os_release_info_mock): compliance_client = ComplianceClient(config) compliance_client.inventory_id = '068040f1-08c8-43e4-949f-7d6470e9111c' compliance_client.conn.session.get = Mock( return_value=Mock(status_code=200, json=Mock( return_value={'data': [{ 'attributes': 'data' }]}))) assert compliance_client.get_profiles_matching_os() == [{ 'attributes': 'data' }] compliance_client.conn.session.get.assert_called_with( 'https://localhost/app/compliance/profiles', params={ 'search': 'system_ids=068040f1-08c8-43e4-949f-7d6470e9111c canonical=false os_minor_version=5' })
def test_oscap_scan(config, assert_rpms): compliance_client = ComplianceClient(config) compliance_client._get_inventory_id = lambda: '' compliance_client.get_initial_profiles = lambda: [{'attributes': {'ref_id': 'foo', 'tailored': False}}] compliance_client.get_profiles_matching_os = lambda: [] compliance_client.find_scap_policy = lambda ref_id: '/usr/share/xml/scap/foo.xml' compliance_client.run_scan = lambda ref_id, policy_xml, output_path, tailoring_file_path: None compliance_client.archive.archive_tmp_dir = '/tmp' compliance_client.archive.archive_name = 'insights-compliance-test' archive, content_type = compliance_client.oscap_scan() assert archive == '/tmp/insights-compliance-test.tar.gz' assert content_type == COMPLIANCE_CONTENT_TYPE
def test_missing_packages(config, call): compliance_client = ComplianceClient(config) compliance_client.get_policies = lambda: [{ 'attributes': { 'ref_id': 'foo' } }] compliance_client.find_scap_policy = lambda ref_id: '/usr/share/xml/scap/foo.xml' compliance_client.run_scan = lambda ref_id, policy_xml: None with raises(SystemExit): compliance_client.oscap_scan()
def test__get_inventory_id(config): compliance_client = ComplianceClient(config) compliance_client.conn._fetch_system_by_machine_id = lambda: [] with raises(SystemExit): compliance_client._get_inventory_id() compliance_client.conn._fetch_system_by_machine_id = lambda: [{}] with raises(SystemExit): compliance_client._get_inventory_id() compliance_client.conn._fetch_system_by_machine_id = lambda: [{'id': '12345'}] assert compliance_client._get_inventory_id() == '12345'
def test_oscap_scan_with_results_repaired(config, assert_rpms, tmpdir): results_file = tmpdir.mkdir('results').join('result.xml') results_file.write(""" <xml> <version>0.9</version> </xml> """) compliance_client = ComplianceClient(config) compliance_client._ssg_version = '0.1.25' compliance_client._get_inventory_id = lambda: '' compliance_client.get_initial_profiles = lambda: [{'attributes': {'ref_id': 'foo', 'tailored': False}}] compliance_client.get_profiles_matching_os = lambda: [] compliance_client.find_scap_policy = lambda ref_id: '/usr/share/xml/scap/foo.xml' compliance_client._results_file = lambda archive_dir, profile: str(results_file) compliance_client.run_scan = lambda ref_id, policy_xml, output_path, tailoring_file_path: None compliance_client.archive.archive_tmp_dir = '/tmp' compliance_client.archive.archive_name = 'insights-compliance-test' archive, content_type = compliance_client.oscap_scan() assert archive == '/tmp/insights-compliance-test.tar.gz' assert content_type == COMPLIANCE_CONTENT_TYPE repaired_results = open(str(results_file)).read() assert '<version>0.1.25</version>' in repaired_results
def test_oscap_scan(config, assert_rpms): compliance_client = ComplianceClient(config) compliance_client.get_policies = lambda: [{'ref_id': 'foo'}] compliance_client.find_scap_policy = lambda ref_id: '/usr/share/xml/scap/foo.xml' compliance_client.run_scan = lambda ref_id, policy_xml, output_path: None compliance_client.archive.archive_tmp_dir = '/tmp' compliance_client.archive.archive_name = 'insights-compliance-test' archive, content_type = compliance_client.oscap_scan() assert archive == '/tmp/insights-compliance-test.tar.gz' assert content_type == COMPLIANCE_CONTENT_TYPE
def test_oscap_scan(config): compliance_client = ComplianceClient(config) compliance_client.get_policies = lambda: [{ 'attributes': { 'ref_id': 'foo' } }] compliance_client.find_scap_policy = lambda ref_id: '/usr/share/xml/scap/foo.xml' compliance_client.run_scan = lambda ref_id, policy_xml: None payload, content_type = compliance_client.oscap_scan() assert payload == OSCAP_RESULTS_OUTPUT assert content_type == COMPLIANCE_CONTENT_TYPE
def test_get_profiles(config): compliance_client = ComplianceClient(config) compliance_client.inventory_id = '068040f1-08c8-43e4-949f-7d6470e9111c' compliance_client.conn.session.get = Mock(return_value=Mock(status_code=200, json=Mock(return_value={'data': [{'attributes': 'data'}]}))) assert compliance_client.get_profiles('search string') == [{'attributes': 'data'}] compliance_client.conn.session.get.assert_called_with('https://localhost/app/compliance/profiles', params={'search': 'search string', 'relationships': 'false'})
def test_os_release(config, os_release_info_mock): compliance_client = ComplianceClient(config) assert compliance_client.os_release() == '6.5'
def test_build_oscap_command_append_tailoring_path(config): compliance_client = ComplianceClient(config) expected_command = 'oscap xccdf eval --profile aaaaa --tailoring-file tailoring_path --results output_path xml_sample' assert expected_command == compliance_client.build_oscap_command( 'aaaaa', 'xml_sample', 'output_path', 'tailoring_path')
def test_tailored_file_is_not_downloaded_if_not_needed(config): compliance_client = ComplianceClient(config) assert compliance_client.download_tailoring_file( {'attributes': { 'tailored': False }}) is None
def test_os_major_version(config, os_release_info_mock): compliance_client = ComplianceClient(config) assert compliance_client.os_major_version() == '6'
def test_os_major_version(config, linux_distro_mock): compliance_client = ComplianceClient(config) assert compliance_client.os_major_version() == '6'
def test_find_scap_policy(config, call): compliance_client = ComplianceClient(config) compliance_client.profile_files = lambda: ['/something'] assert compliance_client.find_scap_policy('ref_id') == PATH
def test_get_profiles_error(config): compliance_client = ComplianceClient(config) compliance_client.hostname = 'foo' compliance_client.conn.session.get = Mock(return_value=Mock(status_code=500)) assert compliance_client.get_profiles('search string') == [] compliance_client.conn.session.get.assert_called_with('https://localhost/app/compliance/profiles', params={'search': 'search string'})
def test_get_profiles(config): compliance_client = ComplianceClient(config) compliance_client.hostname = 'foo' compliance_client.conn.session.get = Mock(return_value=Mock(status_code=200, json=Mock(return_value={'data': [{'attributes': 'data'}]}))) assert compliance_client.get_profiles('search string') == [{'attributes': 'data'}] compliance_client.conn.session.get.assert_called_with('https://localhost/app/compliance/profiles', params={'search': 'search string'})
def test_tailored_file_is_downloaded_if_needed(config, call, linux_distro_mock): compliance_client = ComplianceClient(config) compliance_client.conn.session.get = Mock(return_value=Mock(status_code=200, json=Mock(return_value={'data': [{'attributes': 'data'}]}))) tailoring_file_path = "/var/tmp/oscap_tailoring_file-aaaaa.xml" assert tailoring_file_path == compliance_client.download_tailoring_file({'id': 'foo', 'attributes': {'tailored': True, 'ref_id': 'aaaaa', 'os_minor_version': '5'}}) assert compliance_client.download_tailoring_file({'id': 'foo', 'attributes': {'tailored': False, 'ref_id': 'aaaaa', 'os_minor_version': '5'}}) is None
def test_tailored_file_is_not_downloaded_if_os_minor_version_mismatches(config, linux_distro_mock): compliance_client = ComplianceClient(config) compliance_client.conn.session.get = Mock(return_value=Mock(status_code=200, json=Mock(return_value={'data': [{'attributes': 'data'}]}))) assert compliance_client.download_tailoring_file({'id': 'foo', 'attributes': {'tailored': True, 'ref_id': 'aaaaa', 'os_minor_version': '2'}}) is None assert compliance_client.download_tailoring_file({'id': 'foo', 'attributes': {'tailored': False, 'ref_id': 'aaaaa', 'os_minor_version': '2'}}) is None
def test_tailored_file_is_not_downloaded_if_tailored_is_missing(config): compliance_client = ComplianceClient(config) assert compliance_client.download_tailoring_file({'id': 'foo', 'attributes': {'ref_id': 'aaaaa'}}) is None
def test_os_release(config, linux_distro_mock): compliance_client = ComplianceClient(config) assert compliance_client.os_release() == '6'
def test_profile_files(config): compliance_client = ComplianceClient(config) compliance_client.os_release = lambda: '7' assert compliance_client.profile_files() == []
def collect_and_output(client, config): # run a specified module if config.module: try: runpy.run_module(config.module) except ImportError as e: logger.error(e) sys.exit(constants.sig_kill_bad) sys.exit(constants.sig_kill_ok) # --compliance was called if config.compliance: config.payload, config.content_type = ComplianceClient( config).oscap_scan() # default (below) if config.payload: insights_archive = config.payload else: try: insights_archive = client.collect() except RuntimeError as e: logger.error(e) sys.exit(constants.sig_kill_bad) if not config.content_type: config.content_type = 'application/vnd.redhat.advisor.collection+tgz' if config.no_upload: # output options for which upload is not performed if config.output_dir: client.copy_to_output_dir(insights_archive) elif config.output_file: client.copy_to_output_file(insights_archive) else: # upload the archive if not insights_archive: # no archive to upload, something went wrong sys.exit(constants.sig_kill_bad) resp = None try: resp = client.upload(payload=insights_archive, content_type=config.content_type) except (IOError, ValueError, RuntimeError) as e: logger.error(str(e)) sys.exit(constants.sig_kill_bad) if resp: if config.to_json: print(json.dumps(resp)) client.show_inventory_deep_link() client.delete_cached_branch_info() # rotate eggs once client completes all work successfully try: client.rotate_eggs() except IOError: message = ("Failed to rotate %s to %s" % (constants.insights_core_newest, constants.insights_core_last_stable)) logger.debug(message) raise IOError(message)
def test_find_scap_policy_not_found(config, call): compliance_client = ComplianceClient(config) compliance_client.profile_files = lambda: ['/something'] with raises(SystemExit): compliance_client.find_scap_policy('ref_id')
def test_run_scan(config, call): compliance_client = ComplianceClient(config) compliance_client.run_scan('ref_id', '/nonexistent') call.assert_called_with("oscap xccdf eval --profile ref_id --results " + OSCAP_RESULTS_OUTPUT + ' /nonexistent', keep_rc=True)
def test_get_initial_profiles(config): compliance_client = ComplianceClient(config) compliance_client.hostname = 'foo' compliance_client.conn.session.get = Mock(return_value=Mock(status_code=200, json=Mock(return_value={'data': [{'attributes': 'data'}]}))) assert compliance_client.get_initial_profiles() == [{'attributes': 'data'}] compliance_client.conn.session.get.assert_called_with('https://localhost/app/compliance/profiles', params={'search': 'system_names=foo canonical=false external=false'})
def test_get_profiles_matching_os(config, linux_distro_mock): compliance_client = ComplianceClient(config) compliance_client.hostname = 'foo' compliance_client.conn.session.get = Mock(return_value=Mock(status_code=200, json=Mock(return_value={'data': [{'attributes': 'data'}]}))) assert compliance_client.get_profiles_matching_os() == [{'attributes': 'data'}] compliance_client.conn.session.get.assert_called_with('https://localhost/app/compliance/profiles', params={'search': 'system_names=foo canonical=false os_minor_version=5'})