コード例 #1
0
ファイル: test_cli.py プロジェクト: twu/skjold
def test_cli_configuration_used_by_default(
    runner: click.testing.CliRunner,
    cache_dir: str,
    monkeypatch: MonkeyPatch,
) -> None:
    """Ensure that we use options set in the configuration file if not overridden by passing CLI options."""
    monkeypatch.setenv("SKJOLD_CACHE_DIR", cache_dir)
    config = Configuration()
    config.use({
        "report_only": True,
        "report_format": "json",
        "sources": ["gemnasium"]
    })

    result = runner.invoke(cli, args=["config"], obj=config)
    assert "report_only: True" in result.stderr
    assert "report_format: json" in result.stderr

    # TODO(twu): Figure out how to do this right.
    input_ = make_input_stream("urllib3==1.23\nrequests==22.2.2\n", "utf-8")
    setattr(input_, "name", "<stdin>")

    result = runner.invoke(
        cli,
        args=["audit", "-"],
        env={"SKJOLD_CACHE_DIR": cache_dir},
        input=input_,
        obj=config,
    )
    assert result.exit_code == 0

    json_ = json.loads(result.stdout)
    assert len(json_) > 0
    assert json_[0]["name"] == "urllib3"
    assert json_[0]["source"] == "gemnasium"
コード例 #2
0
ファイル: test_cli.py プロジェクト: twu/skjold
def test_vulnerable_package_with_ignore_list_via_cli(
        runner: click.testing.CliRunner, cache_dir: str,
        monkeypatch: MonkeyPatch) -> None:
    """Ensure that using a .skjoldignore file ignores marked findings and can be set via '-i/--ignore-file'."""
    monkeypatch.setenv("SKJOLD_CACHE_DIR", cache_dir)
    ignore_path = os.path.join(os.path.dirname(__file__), "fixtures",
                               "formats", "ignore", "all")
    assert os.path.exists(ignore_path)

    config = Configuration()
    config.use({
        "report_only": False,
        "report_format": "cli",
        "sources": ["pypa"]
    })
    assert config.ignore_file == ".skjoldignore"

    # TODO(twu): Figure out how to do this right.
    input_ = make_input_stream("urllib3==1.23", "utf-8")
    setattr(input_, "name", "<stdin>")

    result = runner.invoke(cli,
                           args=["audit", "-i", ignore_path, "-"],
                           input=input_,
                           obj=config)

    assert "Ignored 6 finding(s)!" in result.stderr
    assert "No vulnerable packages found!" in result.stderr
    assert result.exit_code == 0
コード例 #3
0
ファイル: test_cli.py プロジェクト: twu/skjold
def test_cli_ensure_formats_are_handled_properly(
    folder: str,
    filename: str,
    runner: click.testing.CliRunner,
    cache_dir: str,
    monkeypatch: MonkeyPatch,
) -> None:
    monkeypatch.setenv("SKJOLD_CACHE_DIR", cache_dir)
    config = Configuration()
    config.use({
        "report_only": False,
        "report_format": "cli",
        "sources": ["pyup"]
    })

    path = format_fixture_path_for(filename)

    result = runner.invoke(
        cli,
        args=["audit", "-r", "-o", "json", "-s", "github", path],
        env={"SKJOLD_CACHE_DIR": cache_dir},
    )

    assert not result.exception
    assert result.exit_code == 0

    json_ = json.loads(result.stdout)

    assert len(json_) > 0
    assert json_[0]["name"] == "urllib3"
    assert json_[0]["source"] == "github"
コード例 #4
0
ファイル: test_cli.py プロジェクト: twu/skjold
def test_cli_configuration_override_via_cli(
    runner: click.testing.CliRunner,
    cache_dir: str,
    monkeypatch: MonkeyPatch,
) -> None:
    """Ensure that overriding configured values via CLI is possible."""
    monkeypatch.setenv("SKJOLD_CACHE_DIR", cache_dir)
    config = Configuration()
    config.use({
        "report_only": True,
        "report_format": "json",
        "sources": ["pyup"],
        "cache_dir": cache_dir,
    })
    result = runner.invoke(cli, args=["config"], obj=config)
    assert "report_only: True" in result.stderr
    assert "report_format: json" in result.stderr

    # TODO(twu): Figure out how to do this right.
    input_ = make_input_stream("urllib3==1.23\nrequests==22.2.2\n", "utf-8")
    setattr(input_, "name", "<stdin>")

    result = runner.invoke(
        cli,
        args=["audit", "-r", "-s", "github", "-o", "cli", "-"],
        input=input_,
        env={"SKJOLD_CACHE_DIR": cache_dir},
        obj=config,
    )
    assert result.exit_code == 0
    assert "urllib3" in result.stdout
    assert "via github" in result.stdout
コード例 #5
0
def cli(
    config: Configuration,
    configuration_file: click.Path,
    verbose: bool,
) -> None:
    """ Check a given Python dependency file against a set of advisory databases."""
    config.verbose = verbose

    file_ = str(configuration_file)
    skip_configuration = not os.environ.get("SKJOLD_SKIP_RC", None) is None

    if os.path.exists(file_) and not skip_configuration:
        settings = get_configuration_from_toml(file_)
        config.use(config=settings)
    else:
        click.secho("Warning: No 'pyproject.toml' found!", err=True, fg="yellow")

    if config.verbose:
        print_configuration(config)
        click.secho(f"Using {config.cache_dir} as cache location", err=True)

    # Cache Directory
    # Check for cache directory and create it if necessary.
    if not os.path.isdir(config.cache_dir):
        os.makedirs(config.cache_dir, exist_ok=True)
        if config.verbose:
            click.secho(
                f"Cache '{config.cache_dir}' does not exist! Creating it.",
                err=True,
            )

    if not os.path.isdir(config.cache_dir):
        raise click.ClickException(
            f"Unable to create cache directory '{config.cache_dir}'!"
        )
コード例 #6
0
ファイル: test_cli.py プロジェクト: twu/skjold
def test_cli_json_report_with_package_list_via_stdin(
    runner: click.testing.CliRunner,
    cache_dir: str,
    monkeypatch: MonkeyPatch,
) -> None:
    """Ensure request json output with packages via stdin results in parsable stdout."""
    monkeypatch.setenv("SKJOLD_CACHE_DIR", cache_dir)
    config = Configuration()
    config.use({
        "report_only": False,
        "report_format": "cli",
        "sources": ["pyup"]
    })

    # TODO(twu): Figure out how to do this right.
    input_ = make_input_stream("urllib3==1.23\nrequests==22.2.2\n", "utf-8")
    setattr(input_, "name", "<stdin>")

    result = runner.invoke(
        cli,
        args=["audit", "-r", "-o", "json", "-s", "github", "-"],
        input=input_)
    assert not result.exception
    assert result.exit_code == 0

    json_ = json.loads(result.stdout)

    assert len(json_) > 0
    assert json_[0]["name"] == "urllib3"
コード例 #7
0
def audit_(
    config: Configuration,
    report_only: bool,
    report_format: str,
    file_format: str,
    sources: List[str],
    file: TextIO,
) -> None:
    """
    Checks a given dependency file against advisory databases.

    \b
    FILE is the path to the dependency file to audit.
    """
    config.report_only = report_only
    config.report_format = report_format
    # Only override sources if at least once --source is passed.
    if len(sources) > 0:
        config.sources = list(set(sources))

    if len(config.sources) == 0:
        raise click.ClickException(
            "Please specify or configure at least one advisory source."
        )

    packages = extract_package_list_from(config, file, file_format)

    if config.verbose:
        click.secho("Checking ", nl=False, err=True)
        click.secho(f"{len(packages)}", fg="green", nl=False, err=True)
        click.secho(" package(s).", err=True)

        click.secho("Using ", nl=False, err=True)
        click.secho(f"{config.sources}", fg="green", nl=False, err=True)
        click.secho(" as source(s).", err=True)

    results, vulnerable = audit(config, packages)

    report(config, results)

    if len(vulnerable) > 0 and config.verbose:
        click.secho("", err=True)
        click.secho(
            f"  Found {len(vulnerable)} vulnerable packages!",
            fg="red",
            blink=True,
            err=True,
        )
        click.secho("", err=True)
    elif config.verbose:
        click.secho("", err=True)
        click.secho(f"  No vulnerable packages found!", fg="green", err=True)

    # By default we want to exit with a non-zero exit-code when we encounter
    # any findings.
    if not config.report_only and len(vulnerable) > 0:
        sys.exit(1)
コード例 #8
0
def test_cli_run_config(
    runner: click.testing.CliRunner, cache_dir: str, monkeypatch: MonkeyPatch
) -> None:
    monkeypatch.setenv("SKJOLD_CACHE_DIR", cache_dir)
    config = Configuration()
    config.use({"report_only": False, "report_format": "cli", "sources": ["pyup"]})

    result = runner.invoke(cli, args=["config"])
    assert result.exit_code == 0
コード例 #9
0
ファイル: test_sources.py プロジェクト: tbjers/skjold
def test_register_source() -> None:
    DummyAdvisorySource._name = "dummy2"
    register_source("dummy2", DummyAdvisorySource)

    assert is_registered_source("dummy2")
    _config = Configuration()
    assert "dummy2" in _config.available_sources
コード例 #10
0
ファイル: test_formats.py プロジェクト: tbjers/skjold
def test_extract_package_versions_from_with_poetry_lock(
        folder: str, filename: str, format_: Optional[str]) -> None:

    with open(format_fixture_path_for(folder, filename)) as fh:
        packages = list(extract_package_list_from(Configuration(), fh,
                                                  format_))
        assert len(packages) > 0
コード例 #11
0
def test_vulnerable_package_via_cli(
    runner: click.testing.CliRunner, cache_dir: str, monkeypatch: MonkeyPatch
) -> None:
    """Ensure that passing a vulnerable package via stdin produces the expected
    output."""
    monkeypatch.setenv("SKJOLD_CACHE_DIR", cache_dir)
    config = Configuration()
    config.use({"report_only": False, "report_format": "cli", "sources": ["pyup"]})

    # TODO(twu): Figure out how to do this right.
    input_ = make_input_stream("urllib3==1.23\nrequests==22.2.2\n", "utf-8")
    setattr(input_, "name", "<stdin>")

    result = runner.invoke(cli, args=["audit", "-s", "github", "-"], input=input_)
    assert result.exception
    assert result.exit_code == 1
    assert "via github" in result.stdout
コード例 #12
0
def cli(config: Configuration, configuration_file: click.Path,
        verbose: bool) -> None:
    """ Check a given Python dependency file against a set of advisory databases."""

    doc = {}
    if os.path.exists(str(configuration_file)):
        with open(str(configuration_file)) as fh:
            doc = tomlkit.parse(fh.read())
    else:
        click.secho("Warning: No 'pyproject.toml' found!",
                    err=True,
                    fg="yellow")

    _config = doc.get("tool", {}).get("skjold", {})

    # Configuration file
    config.report_only = _config.get("report_only", config.report_only)
    config.report_format = _config.get("report_format", config.report_format)
    config.cache_dir = _config.get("cache_dir", config.cache_dir)
    config.cache_expires = _config.get("cache_expires", config.cache_expires)
    config.verbose = verbose

    # Configure cache_dir selection: ENV > pyproject.toml > default(posix).
    app_home = click.get_app_dir("skjold", roaming=False, force_posix=True)
    default_cache_dir = os.path.join(app_home, "cache")
    config.cache_dir = os.environ.get(
        "SKJOLD_CACHE_DIR", _config.get("cache_dir", default_cache_dir))
    if config.verbose:
        click.secho(f"Using {config.cache_dir} as cache location", err=True)

    # Check for cache directory and create it if necessary.
    if not os.path.isdir(config.cache_dir):
        os.makedirs(config.cache_dir, exist_ok=True)
        if config.verbose:
            click.secho(
                f"Cache '{config.cache_dir}' does not exist! Creating it.",
                err=True)

    if not os.path.isdir(config.cache_dir):
        raise click.ClickException(
            f"Unable to create cache directory '{config.cache_dir}'!")

    # Configure and validate sources.
    config.sources = _config.get("sources", [])
    if not len(config.sources):
        click.secho("Warning: No advisory sources configured!",
                    err=True,
                    fg="yellow")

    for source_name in config.sources:
        if not is_registered_source(source_name):
            raise click.ClickException(
                f"Source with name '{source_name}' does not exist!")

    if config.verbose:
        print_configuration(config)
コード例 #13
0
ファイル: test_formats.py プロジェクト: tbjers/skjold
def test_extract_dependencies_using_minimal_examples(folder: str,
                                                     filename: str) -> None:
    with open(format_fixture_path_for(folder, filename)) as fh:
        packages = list(extract_package_list_from(Configuration(), fh, None))
        assert len(packages) > 0