Skip to content

Commit e6a0455

Browse files
authored
Merge pull request #36 from OPPIDA/feat/docker
2 parents 0f8f252 + 774aee8 commit e6a0455

File tree

14 files changed

+514
-204
lines changed

14 files changed

+514
-204
lines changed

Dockerfile

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# =========================== Build stage ===========================
2+
FROM astral/uv:python3.12-bookworm-slim AS builder
3+
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy UV_PYTHON_DOWNLOADS=0
4+
5+
WORKDIR /app
6+
COPY pyproject.toml /app/pyproject.toml
7+
COPY uv.lock /app/uv.lock
8+
RUN --mount=type=cache,target=/root/.cache/uv \
9+
uv sync --locked --no-install-project --no-dev --extra test
10+
11+
COPY codesectools /app/codesectools
12+
RUN --mount=type=cache,target=/root/.cache/uv \
13+
uv sync --locked --no-dev --extra test
14+
15+
# =========================== Base ===========================
16+
FROM python:3.12-slim-bookworm
17+
18+
ARG UID=1000
19+
ARG GID=1000
20+
21+
SHELL ["/bin/bash", "-c"]
22+
23+
RUN apt update -qq && \
24+
DEBIAN_FRONTEND=noninteractive \
25+
apt install \
26+
sudo \
27+
curl git \
28+
cloc \
29+
openjdk-17-jdk-headless maven \
30+
build-essential bear \
31+
-y -qq --no-install-recommends && \
32+
rm -rf /var/lib/apt/lists/*
33+
34+
RUN groupadd -g $GID codesectools && \
35+
useradd -l -u $UID -g codesectools -m codesectools -s /bin/bash && \
36+
echo "codesectools ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/codesectools && \
37+
chmod 0440 /etc/sudoers.d/codesectools
38+
39+
USER codesectools
40+
WORKDIR /home/codesectools
41+
42+
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
43+
ENV PATH="/home/codesectools/.local/bin:$PATH"
44+
45+
# =========================== SAST tools ===========================
46+
RUN uv venv sasts
47+
ENV PATH="/home/codesectools/sasts:$PATH"
48+
ENV PATH="/home/codesectools/sasts/bin:$PATH"
49+
50+
# Semgrep Community Edition
51+
RUN uv pip install --no-cache semgrep
52+
53+
# Bearer
54+
RUN curl -sfL https://raw.githubusercontent.com/Bearer/bearer/main/contrib/install.sh | BINDIR=/home/codesectools/sasts sh
55+
56+
# SpotBugs
57+
RUN curl -sL https://github.com/spotbugs/spotbugs/releases/download/4.9.8/spotbugs-4.9.8.tgz | tar -xzvf - && \
58+
mv spotbugs-* /home/codesectools/sasts/spotbugs && \
59+
curl -sL https://search.maven.org/remotecontent?filepath=com/h3xstream/findsecbugs/findsecbugs-plugin/1.14.0/findsecbugs-plugin-1.14.0.jar > /home/codesectools/sasts/spotbugs/plugin/findsecbugs-plugin-1.14.0.jar
60+
ENV PATH="/home/codesectools/sasts/spotbugs/bin:$PATH"
61+
62+
# Cppcheck
63+
RUN sudo apt update -qq && \
64+
DEBIAN_FRONTEND=noninteractive sudo apt install cppcheck -y -qq --no-install-recommends && \
65+
sudo rm -rf /var/lib/apt/lists/*
66+
67+
# =========================== CodeSecTools ===========================
68+
COPY --from=builder --chown=codesectools:codesectools /app /app
69+
ENV PATH="/app/.venv/bin:$PATH"
70+
71+
# https://github.com/sarugaku/shellingham/issues/87
72+
RUN find /app -path "*/shellingham/__init__.py" -exec sed -i 's#raise ShellDetectionFailure()#return ("bash", "/bin/bash")#g' {} \; && \
73+
cstools --install-completion

Makefile

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Export variables
2+
export UID := $(shell id -u)
3+
export GID := $(shell id -g)
4+
15
# Add a help target to a Makefile that will allow all targets to be self documenting
26
# https://gist.github.com/prwhite/8168133
37
all:
@@ -17,19 +21,17 @@ profile: ## Run profiling
1721

1822
test: ## Run tests in a Docker container
1923
@docker compose build 1>/dev/null
20-
@docker compose run --rm no-sast
21-
@docker compose run --rm with-sast
24+
@docker compose run --rm test
2225

2326
test-force: ## Run tests in a Docker container while ignoring any stored state
2427
@docker volume rm codesectools_pytest-cache 2>&1 1>/dev/null || true
2528
@docker volume rm codesectools_cstools-cache 2>&1 1>/dev/null || true
2629
@docker compose build 1>/dev/null
27-
@docker compose run --rm no-sast
28-
@docker compose run --rm with-sast
30+
@docker compose run --rm test
2931

3032
test-debug: ## Spawn an interactive shell in the test container to debug
3133
@docker compose build
32-
@docker compose run --rm with-sast /bin/bash
34+
@docker compose run --rm test /bin/bash
3335

3436
docs-serve: ## Serve the documentation locally
3537
@mkdocs serve --livereload

README.md

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ A framework for code security that provides abstractions for static analysis too
1414
- [SAST Tool Integration Status](#sast-tool-integration-status)
1515
- [Usage](#usage)
1616
- [Command-line interface](#command-line-interface)
17+
- [Docker](#docker)
1718
- [Python API](#python-api)
1819

1920
<!--start-include-->
@@ -59,28 +60,58 @@ For more details on the design and integration of SAST tools and datasets in Cod
5960

6061
```bash
6162
$ cstools
62-
63-
Usage: cstools [OPTIONS] COMMAND [ARGS]...
64-
65-
CodeSecTools: A framework for code security that provides abstractions for static analysis tools and datasets to support their integration,
66-
testing, and evaluation.
67-
68-
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
69-
│ --debug -d Show debugging messages and disable pretty exceptions. │
70-
│ --version -v Show the tool's version. │
71-
│ --install-completion Install completion for the current shell. │
72-
│ --show-completion Show completion for the current shell, to copy it or customize the installation. │
73-
│ --help Show this message and exit. │
74-
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
75-
╭─ Commands ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
76-
│ status Display the availability of SAST tools and datasets. │
77-
│ allsast Run all available SAST tools together. │
78-
│ bearer Bearer SAST │
79-
│ coverity Coverity Static Analysis │
80-
│ semgrepce Semgrep Community Edition Engine │
81-
│ snykcode Snyk Code │
82-
│ spotbugs SpotBugs │
83-
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
63+
64+
Usage: cstools [OPTIONS] COMMAND [ARGS]...
65+
66+
CodeSecTools CLI.
67+
68+
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
69+
│ --debug -d Show debugging messages and disable pretty exceptions. │
70+
│ --version -v Show the tool's version. │
71+
│ --install-completion Install completion for the current shell. │
72+
│ --show-completion Show completion for the current shell, to copy it or customize the installation. │
73+
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
74+
╭─ Commands ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
75+
│ status Display the availability of SAST tools and datasets. │
76+
│ allsast Run all available SAST tools together. │
77+
│ bearer Bearer SAST │
78+
│ coverity Coverity Static Analysis │
79+
│ cppcheck Cppcheck │
80+
│ semgrepce Semgrep Community Edition Engine │
81+
│ snykcode Snyk Code │
82+
│ spotbugs SpotBugs │
83+
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
84+
```
85+
86+
#### Docker
87+
88+
A Docker image is available with only free and offline SAST tools pre-installed.
89+
90+
```bash
91+
UID=$(id -u) GID=$(id -g) docker compose build main
92+
docker run -it -v $HOME/.codesectools:/home/codesectools/.codesectools codesectools /bin/bash
93+
```
94+
95+
Mount necessary directories if you want to include:
96+
97+
- a target (`-v ./myproject:/home/codesectools/myproject`)
98+
- existing CodeSecTools data (`-v $HOME/.codesectools:/home/codesectools/.codesectools`)
99+
100+
A better way is to use the CLI:
101+
102+
```bash
103+
$ cstools -d docker --help
104+
105+
Usage: cstools docker [OPTIONS]
106+
107+
Start the Docker environment for the specified target (current directory by default).
108+
109+
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
110+
│ --target PATH The directory to mount inside the container. [default: .] │
111+
│ --isolation --no-isolation Enable network isolation for the container (disables host network sharing). [default: no-isolation] │
112+
│ --help Show this message and exit. │
113+
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
114+
84115
```
85116
86117
#### Python API

codesectools/cli.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"""
66

77
import os
8+
import shutil
89
from pathlib import Path
910
from typing import Optional
1011

@@ -201,5 +202,26 @@ def download(
201202

202203
cli.add_typer(build_all_sast_cli())
203204

205+
if shutil.which("docker"):
206+
207+
@cli.command()
208+
def docker(
209+
target: Annotated[
210+
Path, typer.Option(help="The directory to mount inside the container.")
211+
] = Path("."),
212+
isolation: Annotated[
213+
bool,
214+
typer.Option(
215+
help="Enable network isolation for the container (disables host network sharing)."
216+
),
217+
] = False,
218+
) -> None:
219+
"""Start the Docker environment for the specified target (current directory by default)."""
220+
from codesectools.shared.docker import AnalysisEnvironment
221+
222+
env = AnalysisEnvironment(isolation=isolation)
223+
env.start(target=target.resolve())
224+
225+
204226
for _, sast_data in SASTS_ALL.items():
205227
cli.add_typer(sast_data["cli_factory"].build_cli())

0 commit comments

Comments
 (0)