Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ checks: typecheck lint test

coverage: test coverage-report

test: test-cli test-python-executable test-pip test-pip-class test-poetry test-poetry-class test-npm test-npm-class test-verifiers
test: test-cli test-python-executable test-pip test-pip-class test-poetry test-poetry-class test-npm test-npm-class test-go test-go-class test-verifiers

typecheck:
mypy --install-types --non-interactive scfw
Expand Down Expand Up @@ -41,6 +41,12 @@ test-npm:
test-npm-class:
COVERAGE_FILE=.coverage.npm.class coverage run -m pytest tests/package_managers/test_npm_class.py

test-go:
COVERAGE_FILE=.coverage.go coverage run -m pytest tests/package_managers/test_go.py

test-go-class:
COVERAGE_FILE=.coverage.go.class coverage run -m pytest tests/package_managers/test_go_class.py

test-verifiers:
COVERAGE_FILE=.coverage.verifiers coverage run -m pytest tests/verifiers

Expand All @@ -49,6 +55,7 @@ coverage-report:
.coverage.python.executable .coverage.pip .coverage.pip.class \
.coverage.poetry .coverage.poetry.class \
.coverage.npm .coverage.npm.class \
.coverage.go .coverage.go.class \
.coverage.verifiers
coverage report

Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,12 @@ $ scfw configure

### Compatibility and limitations

| Package manager | Compatible versions | Inspected subcommands |
| :---------------: | :-------------------: | :--------------------------------: |
| npm | >= 7.0 | `install` (including aliases) |
| pip | >= 22.2 | `install` |
| poetry | >= 1.7 | `add`, `install`, `sync`, `update` |
| Package manager | Compatible versions | Inspected subcommands |
| :---------------: | :-------------------: | :-------------------------------------------------: |
| npm | >= 7.0 | `install` (including aliases) |
| pip | >= 22.2 | `install` |
| poetry | >= 1.7 | `add`, `install`, `sync`, `update` |
| go | >= 1.17.0 | `build`, `generate`, `get`, `install`, `mod`, `run` |

In keeping with its goal of blocking 100% of known-malicious package installations, `scfw` will refuse to run with an incompatible version of a supported package manager. Please upgrade to or verify that you are running a compatible version before using this tool.

Expand All @@ -89,6 +90,7 @@ To use Supply-Chain Firewall to inspect a package manager command, simply prepen
$ scfw run npm install react
$ scfw run pip install -r requirements.txt
$ scfw run poetry add git+https://github.com/DataDog/guarddog
$ scfw run go mod download
```

For `pip install` commands, packages will be installed in the same environment (virtual or global) in which the command was run.
Expand Down
7 changes: 7 additions & 0 deletions scfw/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ def _add_configure_cli(parser: ArgumentParser):
help="Add shell aliases to always run Poetry commands through Supply-Chain Firewall"
)

parser.add_argument(
"--alias-go",
action="store_true",
help="Add shell aliases to always run go commands through Supply-Chain Firewall"
)

parser.add_argument(
"--dd-agent-port",
type=str,
Expand Down Expand Up @@ -306,6 +312,7 @@ def _parse_command_line(argv: list[str]) -> tuple[Optional[Namespace], str]:
args.alias_npm,
args.alias_pip,
args.alias_poetry,
args.alias_go,
args.dd_agent_port,
args.dd_api_key,
args.dd_log_level,
Expand Down
2 changes: 2 additions & 0 deletions scfw/configure/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def run_configure(args: Namespace) -> int:
"alias_npm": False,
"alias_pip": False,
"alias_poetry": False,
"alias_go": False,
"dd_agent_port": None,
"dd_api_key": None,
"dd_log_level": None,
Expand All @@ -50,6 +51,7 @@ def run_configure(args: Namespace) -> int:
args.alias_npm,
args.alias_pip,
args.alias_poetry,
args.alias_go,
args.dd_agent_port,
args.dd_api_key,
args.dd_log_level,
Expand Down
2 changes: 2 additions & 0 deletions scfw/configure/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ def _format_answers(answers: dict) -> str:
config += '\nalias pip="scfw run pip"'
if answers.get("alias_poetry"):
config += '\nalias poetry="scfw run poetry"'
if answers.get("alias_go"):
config += '\nalias go="scfw run go"'
if (dd_agent_port := answers.get("dd_agent_port")):
config += f'\nexport {DD_AGENT_PORT_VAR}="{dd_agent_port}"'
if (dd_api_key := answers.get("dd_api_key")):
Expand Down
5 changes: 5 additions & 0 deletions scfw/configure/interactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ def get_answers() -> dict:
message="Would you like to set a shell alias to run all Poetry commands through the firewall?",
default=True
),
inquirer.Confirm(
name="alias_go",
message="Would you like to set a shell alias to run all go commands through the firewall?",
default=True
),
inquirer.Confirm(
name="dd_agent_logging",
message="If you have the Datadog Agent installed locally, would you like to forward firewall logs to it?",
Expand Down
1 change: 1 addition & 0 deletions scfw/ecosystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class ECOSYSTEM(Enum):
"""
Npm = "npm"
PyPI = "PyPI"
Go = "Go"

def __str__(self) -> str:
"""
Expand Down
3 changes: 2 additions & 1 deletion scfw/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ def __str__(self) -> str:
Returns:
A `str` with ecosystem-specific formatting describing the `Package` name and version.

`go` packages: `"{name}@{version}"`.
`npm` packages: `"{name}@{version}"`.
`PyPI` packages: `"{name}-{version}"`
"""
match self.ecosystem:
case ECOSYSTEM.Npm:
case ECOSYSTEM.Npm | ECOSYSTEM.Go:
return f"{self.name}@{self.version}"
case ECOSYSTEM.PyPI:
return f"{self.name}-{self.version}"
4 changes: 4 additions & 0 deletions scfw/package_managers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
from typing import Optional

from scfw.package_manager import PackageManager
from scfw.package_managers.go import Go
from scfw.package_managers.npm import Npm
from scfw.package_managers.pip import Pip
from scfw.package_managers.poetry import Poetry

SUPPORTED_PACKAGE_MANAGERS = [
Go.name(),
Npm.name(),
Pip.name(),
Poetry.name(),
Expand All @@ -37,6 +39,8 @@ def get_package_manager(name: str, executable: Optional[str] = None) -> PackageM
if not name:
raise ValueError("Missing package manager")

if name == Go.name():
return Go(executable)
if name == Npm.name():
return Npm(executable)
if name == Pip.name():
Expand Down
Loading