Exemplo n.º 1
0
    def test_get_announcements_wrong_json_response_handling(
            self, requests_session, get_used_options):
        # wrong JSON structure
        announcements = {
            "type":
            "notice",
            "message":
            "You are using an outdated version of Safety. Please upgrade to Safety version 1.2.3"
        }

        mock = Mock()
        mock.status_code = HTTPStatus.OK.value
        mock.json.return_value = announcements
        requests_session.get.return_value = mock

        self.assertEqual(safety.get_announcements('somekey', {}), [])

        # JSONDecodeError

        mock = Mock()
        mock.status_code = HTTPStatus.OK.value
        mock.json.side_effect = JSONDecodeError(msg='Expecting value',
                                                doc='',
                                                pos=0)
        requests_session.get.return_value = mock

        self.assertEqual(safety.get_announcements('somekey', {}), [])
Exemplo n.º 2
0
    def test_get_announcements_http_ok(self, requests_session,
                                       get_used_options):

        announcements = {
            "announcements": [{
                "type":
                "notice",
                "message":
                "You are using an outdated version of Safety. Please upgrade to Safety version 1.2.3"
            }, {
                "type":
                "error",
                "message":
                "You are using an vulnerable version of Safety. Please upgrade now"
            }]
        }

        expected = announcements.get('announcements')

        mock = Mock()
        mock.status_code = HTTPStatus.OK.value
        mock.json.return_value = announcements
        requests_session.post.return_value = mock

        self.assertEqual(safety.get_announcements('somekey', {}), expected)
Exemplo n.º 3
0
def review(ctx, full_report, output, file):
    """
    Show an output from a previous exported JSON report.
    """
    LOG.info('Running check command')
    announcements = safety.get_announcements(key=None,
                                             proxy=None,
                                             telemetry=ctx.parent.telemetry)
    report = {}

    try:
        report = read_vulnerabilities(file)
    except SafetyError as e:
        LOG.exception('Expected SafetyError happened: %s', e)
        output_exception(e, exit_code_output=True)
    except Exception as e:
        LOG.exception('Unexpected Exception happened: %s', e)
        exception = e if isinstance(e, SafetyException) else SafetyException(
            info=e)
        output_exception(exception, exit_code_output=True)

    params = {'file': file}
    vulns, remediations, packages = safety.review(report, params=params)

    output_report = SafetyFormatter(output=output).render_vulnerabilities(
        announcements, vulns, remediations, full_report, packages)

    found_vulns = list(filter(lambda v: not v.ignored, vulns))
    click.secho(output_report,
                nl=should_add_nl(output, found_vulns),
                file=sys.stdout)
    sys.exit(EXIT_CODE_OK)
Exemplo n.º 4
0
 def test_get_announcements_catch_request_exceptions(
         self, requests_session, get_used_options):
     get_used_options.return_value = {
         'key': {
             '--key': 1
         },
         'output': {
             '--output': 1
         }
     }
     requests_session.get.side_effect = RequestException()
     self.assertEqual(safety.get_announcements('somekey', {}), [])
Exemplo n.º 5
0
    def test_get_announcements_catch_unhandled_http_codes(
            self, requests_session, get_used_options):
        get_used_options.return_value = {
            'key': {
                '--key': 1
            },
            'output': {
                '--output': 1
            }
        }

        unhandled_status = [
            status for status in HTTPStatus if status != HTTPStatus.OK
        ]

        for http_status in unhandled_status:
            mock = Mock()
            mock.status_code = http_status.value
            requests_session.get.return_value = mock

            self.assertEqual(safety.get_announcements('somekey', {}), [])
Exemplo n.º 6
0
def license(ctx, key, db, output, cache, files, proxyprotocol, proxyhost,
            proxyport):
    """
    Find the open source licenses used by your Python dependencies.
    """
    LOG.info('Running license command')
    packages = get_packages(files, False)
    ctx.obj = packages

    proxy_dictionary = get_proxy_dict(proxyprotocol, proxyhost, proxyport)
    announcements = []
    if not db:
        announcements = safety.get_announcements(
            key=key, proxy=proxy_dictionary, telemetry=ctx.parent.telemetry)

    licenses_db = {}

    try:
        licenses_db = safety.get_licenses(key,
                                          db,
                                          cache,
                                          proxy_dictionary,
                                          telemetry=ctx.parent.telemetry)
    except SafetyError as e:
        LOG.exception('Expected SafetyError happened: %s', e)
        output_exception(e, exit_code_output=False)
    except Exception as e:
        LOG.exception('Unexpected Exception happened: %s', e)
        exception = e if isinstance(e, SafetyException) else SafetyException(
            info=e)
        output_exception(exception, exit_code_output=False)

    filtered_packages_licenses = get_packages_licenses(packages, licenses_db)

    output_report = SafetyFormatter(output=output).render_licenses(
        announcements, filtered_packages_licenses)

    click.secho(output_report, nl=True)
Exemplo n.º 7
0
def check(ctx, key, db, full_report, stdin, files, cache, ignore, output, json,
          bare, proxy_protocol, proxy_host, proxy_port, exit_code, policy_file,
          save_json):
    """
    Find vulnerabilities in Python dependencies at the target provided.

    """
    LOG.info('Running check command')

    try:
        packages = get_packages(files, stdin)
        proxy_dictionary = get_proxy_dict(proxy_protocol, proxy_host,
                                          proxy_port)

        announcements = []
        if not db:
            LOG.info('Not local DB used, Getting announcements')
            announcements = safety.get_announcements(
                key=key,
                proxy=proxy_dictionary,
                telemetry=ctx.parent.telemetry)

        ignore_severity_rules = None
        ignore, ignore_severity_rules, exit_code = get_processed_options(
            policy_file, ignore, ignore_severity_rules, exit_code)

        is_env_scan = not stdin and not files
        params = {
            'stdin': stdin,
            'files': files,
            'policy_file': policy_file,
            'continue_on_error': not exit_code,
            'ignore_severity_rules': ignore_severity_rules
        }
        LOG.info('Calling the check function')
        vulns, db_full = safety.check(
            packages=packages,
            key=key,
            db_mirror=db,
            cached=cache,
            ignore_vulns=ignore,
            ignore_severity_rules=ignore_severity_rules,
            proxy=proxy_dictionary,
            include_ignored=True,
            is_env_scan=is_env_scan,
            telemetry=ctx.parent.telemetry,
            params=params)
        LOG.debug('Vulnerabilities returned: %s', vulns)
        LOG.debug('full database returned is None: %s', db_full is None)

        LOG.info('Safety is going to calculate remediations')
        remediations = safety.calculate_remediations(vulns, db_full)

        LOG.info(
            'Safety is going to render the vulnerabilities report using %s output',
            output)
        output_report = SafetyFormatter(output=output).render_vulnerabilities(
            announcements, vulns, remediations, full_report, packages)

        # Announcements are send to stderr if not terminal, it doesn't depend on "exit_code" value
        if announcements and (not sys.stdout.isatty() and os.environ.get(
                "SAFETY_OS_DESCRIPTION", None) != 'run'):
            LOG.info(
                'sys.stdout is not a tty, announcements are going to be send to stderr'
            )
            click.secho(SafetyFormatter(
                output='text').render_announcements(announcements),
                        fg="red",
                        file=sys.stderr)

        found_vulns = list(filter(lambda v: not v.ignored, vulns))
        LOG.info('Vulnerabilities found (Not ignored): %s', len(found_vulns))
        LOG.info('All vulnerabilities found (ignored and Not ignored): %s',
                 len(vulns))

        if save_json:
            default_name = 'safety-report.json'
            json_report = output_report

            if output != 'json':
                json_report = SafetyFormatter(
                    output='json').render_vulnerabilities(
                        announcements, vulns, remediations, full_report,
                        packages)
            if os.path.isdir(save_json):
                save_json = os.path.join(save_json, default_name)

            with open(save_json, 'w+') as output_json_file:
                output_json_file.write(json_report)

        click.secho(output_report,
                    nl=should_add_nl(output, found_vulns),
                    file=sys.stdout)

        if exit_code and found_vulns:
            LOG.info('Exiting with default code for vulnerabilities found')
            sys.exit(EXIT_CODE_VULNERABILITIES_FOUND)

        sys.exit(EXIT_CODE_OK)

    except SafetyError as e:
        LOG.exception('Expected SafetyError happened: %s', e)
        output_exception(e, exit_code_output=exit_code)
    except Exception as e:
        LOG.exception('Unexpected Exception happened: %s', e)
        exception = e if isinstance(e, SafetyException) else SafetyException(
            info=e)
        output_exception(exception, exit_code_output=exit_code)