Skip to content

Commit c3d4a77

Browse files
authored
Doug/add reach params and fix unverified flag (#130)
* feat: enhance reachability analysis with additional CLI parameters and SSL support - Add --reach-concurrency flag to control parallel analysis execution (must be >= 1) - Add --reach-additional-params flag to pass custom parameters to coana CLI - Fix --allow-unverified flag to properly disable SSL verification for reachability analysis - Update socketdev dependency to version 3.0.19 for latest features - Reorganize argument parser groups for better help organization - Add proper SSL warning suppression when using --allow-unverified - Improve reachability analyzer to support NODE_TLS_REJECT_UNAUTHORIZED environment variable - Bump version to 2.2.28 * Adding additional ecosystem binaries to the container to support reachability * Added new params to readme * Add support for choosing version of Go, Java, and Dotnet * Remove typo
1 parent 55ebf3d commit c3d4a77

File tree

8 files changed

+292
-19
lines changed

8 files changed

+292
-19
lines changed

Dockerfile

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,72 @@
11
FROM python:3-alpine
22
LABEL org.opencontainers.image.authors="socket.dev"
3+
4+
# Language version arguments with defaults
5+
ARG GO_VERSION=system
6+
ARG JAVA_VERSION=17
7+
ARG DOTNET_VERSION=8
8+
9+
# CLI and SDK arguments
310
ARG CLI_VERSION
411
ARG SDK_VERSION
512
ARG PIP_INDEX_URL=https://pypi.org/simple
613
ARG PIP_EXTRA_INDEX_URL=https://pypi.org/simple
714
ARG USE_LOCAL_INSTALL=false
815

9-
RUN apk update \
10-
&& apk add --no-cache git nodejs npm yarn curl \
11-
&& npm install @coana-tech/cli -g
16+
# Install base packages first
17+
RUN apk update && apk add --no-cache \
18+
git nodejs npm yarn curl wget \
19+
ruby ruby-dev build-base
20+
21+
# Install Go with version control
22+
RUN if [ "$GO_VERSION" = "system" ]; then \
23+
apk add --no-cache go; \
24+
else \
25+
cd /tmp && \
26+
ARCH=$(uname -m) && \
27+
case $ARCH in \
28+
x86_64) GOARCH=amd64 ;; \
29+
aarch64) GOARCH=arm64 ;; \
30+
*) echo "Unsupported architecture: $ARCH" && exit 1 ;; \
31+
esac && \
32+
wget https://golang.org/dl/go${GO_VERSION}.linux-${GOARCH}.tar.gz && \
33+
tar -C /usr/local -xzf go${GO_VERSION}.linux-${GOARCH}.tar.gz && \
34+
rm go${GO_VERSION}.linux-${GOARCH}.tar.gz; \
35+
fi
36+
37+
# Install Java with version control
38+
RUN if [ "$JAVA_VERSION" = "8" ]; then \
39+
apk add --no-cache openjdk8-jdk; \
40+
elif [ "$JAVA_VERSION" = "11" ]; then \
41+
apk add --no-cache openjdk11-jdk; \
42+
elif [ "$JAVA_VERSION" = "17" ]; then \
43+
apk add --no-cache openjdk17-jdk; \
44+
elif [ "$JAVA_VERSION" = "21" ]; then \
45+
apk add --no-cache openjdk21-jdk; \
46+
else \
47+
echo "Unsupported Java version: $JAVA_VERSION. Supported: 8, 11, 17, 21" && exit 1; \
48+
fi
49+
50+
# Install .NET with version control
51+
RUN if [ "$DOTNET_VERSION" = "6" ]; then \
52+
apk add --no-cache dotnet6-sdk; \
53+
elif [ "$DOTNET_VERSION" = "8" ]; then \
54+
apk add --no-cache dotnet8-sdk; \
55+
else \
56+
echo "Unsupported .NET version: $DOTNET_VERSION. Supported: 6, 8" && exit 1; \
57+
fi
58+
59+
# Install additional tools
60+
RUN npm install @coana-tech/cli -g && \
61+
gem install bundler && \
62+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && \
63+
. ~/.cargo/env && \
64+
rustup component add rustfmt clippy
65+
66+
# Set environment paths
67+
ENV PATH="/usr/local/go/bin:/root/.cargo/bin:${PATH}"
68+
ENV GOROOT="/usr/local/go"
69+
ENV GOPATH="/go"
1270

1371
# Install uv
1472
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
@@ -38,4 +96,7 @@ RUN if [ "$USE_LOCAL_INSTALL" = "true" ]; then \
3896
pip install --upgrade socketdev; \
3997
fi
4098

41-
# ENTRYPOINT ["socketcli"]
99+
# Create workspace directory with proper permissions
100+
RUN mkdir -p /go/src && chmod -R 777 /go
101+
102+
ENTRYPOINT ["socketcli"]

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ If you don't want to provide the Socket API Token every time then you can use th
171171
| --reach-version | False | latest | Version of @coana-tech/cli to use for analysis |
172172
| --reach-analysis-timeout | False | 1200 | Timeout in seconds for the reachability analysis (default: 1200 seconds / 20 minutes) |
173173
| --reach-analysis-memory-limit | False | 4096 | Memory limit in MB for the reachability analysis (default: 4096 MB / 4 GB) |
174+
| --reach-concurrency | False | | Control parallel analysis execution (must be >= 1) |
175+
| --reach-additional-params | False | | Pass custom parameters to the coana CLI tool |
174176
| --reach-ecosystems | False | | Comma-separated list of ecosystems to analyze (e.g., "npm,pypi"). If not specified, all supported ecosystems are analyzed |
175177
| --reach-exclude-paths | False | | Comma-separated list of file paths or patterns to exclude from reachability analysis |
176178
| --reach-min-severity | False | | Minimum severity level for reporting reachability results (low, medium, high, critical) |

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
66

77
[project]
88
name = "socketsecurity"
9-
version = "2.2.27"
9+
version = "2.2.32"
1010
requires-python = ">= 3.10"
1111
license = {"file" = "LICENSE"}
1212
dependencies = [
@@ -16,7 +16,7 @@ dependencies = [
1616
'GitPython',
1717
'packaging',
1818
'python-dotenv',
19-
'socketdev>=3.0.17,<4.0.0',
19+
'socketdev>=3.0.19,<4.0.0',
2020
"bs4>=0.0.2",
2121
]
2222
readme = "README.md"
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#!/bin/sh
2+
VERSION=$(grep -o "__version__.*" socketsecurity/__init__.py | awk '{print $3}' | tr -d "'")
3+
ENABLE_PYPI_BUILD=$1
4+
STABLE_VERSION=$2
5+
GO_VERSION=${GO_VERSION:-"1.21"}
6+
JAVA_VERSION=${JAVA_VERSION:-"17"}
7+
DOTNET_VERSION=${DOTNET_VERSION:-"8"}
8+
9+
verify_package() {
10+
local version=$1
11+
local pip_index=$2
12+
echo "Verifying package availability..."
13+
14+
for i in $(seq 1 30); do
15+
if pip install --index-url $pip_index socketsecurity==$version; then
16+
echo "Package $version is now available and installable"
17+
pip uninstall -y socketsecurity
18+
return 0
19+
fi
20+
echo "Attempt $i: Package not yet installable, waiting 20s... ($i/30)"
21+
sleep 20
22+
done
23+
24+
echo "Package verification failed after 30 attempts"
25+
return 1
26+
}
27+
28+
# Function to build Docker image with language versions
29+
build_docker_image() {
30+
local cli_version=$1
31+
local tag=$2
32+
local pip_index=${3:-"https://pypi.org/simple"}
33+
local pip_extra_index=${4:-"https://pypi.org/simple"}
34+
local use_local=${5:-"false"}
35+
local dockerfile=${6:-"Dockerfile"}
36+
37+
echo "Building with Go $GO_VERSION, Java $JAVA_VERSION, .NET $DOTNET_VERSION"
38+
39+
local build_args="--build-arg CLI_VERSION=$cli_version"
40+
build_args="$build_args --build-arg GO_VERSION=$GO_VERSION"
41+
build_args="$build_args --build-arg JAVA_VERSION=$JAVA_VERSION"
42+
build_args="$build_args --build-arg DOTNET_VERSION=$DOTNET_VERSION"
43+
build_args="$build_args --build-arg PIP_INDEX_URL=$pip_index"
44+
build_args="$build_args --build-arg PIP_EXTRA_INDEX_URL=$pip_extra_index"
45+
build_args="$build_args --build-arg USE_LOCAL_INSTALL=$use_local"
46+
47+
docker build --no-cache $build_args --platform linux/amd64,linux/arm64 -t $tag -f $dockerfile .
48+
}
49+
50+
echo "Socket CLI version: $VERSION"
51+
echo "Language versions: Go $GO_VERSION, Java $JAVA_VERSION, .NET $DOTNET_VERSION"
52+
53+
if [ -z $ENABLE_PYPI_BUILD ] || [ -z $STABLE_VERSION ]; then
54+
echo "$0 pypi-build=<option> stable=<true|false|prod|test>"
55+
echo "\tpypi-build: Options are prod, test, or local"
56+
echo "\t - prod: Build and publish to production PyPI, then build Docker images"
57+
echo "\t - test: Build and publish to test PyPI, then build Docker images"
58+
echo "\t - local: Build Docker images only using existing PyPI package (specify prod or test via stable parameter)"
59+
echo "\tstable: true/false/prod/test - Also tag as stable; for local builds:"
60+
echo "\t - stable=prod: Use production PyPI package"
61+
echo "\t - stable=test: Use test PyPI package"
62+
echo "\t - stable=false: Use local development install (pip install -e .)"
63+
echo ""
64+
echo "Environment variables for language versions:"
65+
echo "\tGO_VERSION: Go version to install (default: 1.21, or 'system' for Alpine package)"
66+
echo "\tJAVA_VERSION: Java version to install (default: 17, options: 8, 11, 17, 21)"
67+
echo "\tDOTNET_VERSION: .NET version to install (default: 8, options: 6, 8)"
68+
echo ""
69+
echo "Examples:"
70+
echo "\tGO_VERSION=1.19 JAVA_VERSION=11 $0 pypi-build=local stable=prod"
71+
echo "\tGO_VERSION=system JAVA_VERSION=8 $0 pypi-build=local stable=false"
72+
exit
73+
fi
74+
75+
if [ $ENABLE_PYPI_BUILD = "pypi-build=prod" ]; then
76+
echo "Doing production build"
77+
78+
build_docker_image $VERSION "socketdev/cli:$VERSION"
79+
docker push socketdev/cli:$VERSION
80+
81+
build_docker_image $VERSION "socketdev/cli:latest"
82+
docker push socketdev/cli:latest
83+
fi
84+
85+
if [ $ENABLE_PYPI_BUILD = "pypi-build=test" ]; then
86+
echo "Doing test build"
87+
if ! python -m build --wheel --sdist; then
88+
echo "Build failed"
89+
exit 1
90+
fi
91+
92+
if ! twine upload --repository testpypi dist/*$VERSION*; then
93+
echo "Upload to TestPyPI failed"
94+
exit 1
95+
fi
96+
97+
if ! verify_package $VERSION "https://test.pypi.org/simple"; then
98+
echo "Failed to verify package on TestPyPI"
99+
exit 1
100+
fi
101+
102+
build_docker_image $VERSION "socketdev/cli:$VERSION-test" "https://test.pypi.org/simple" "https://pypi.org/simple"
103+
docker push socketdev/cli:$VERSION-test
104+
105+
build_docker_image $VERSION "socketdev/cli:test" "https://test.pypi.org/simple" "https://pypi.org/simple"
106+
docker push socketdev/cli:test
107+
fi
108+
109+
if [ $STABLE_VERSION = "stable=true" ]; then
110+
if [ $ENABLE_PYPI_BUILD = "pypi-build=enable" ]; then
111+
if ! verify_package $VERSION "https://pypi.org/simple"; then
112+
echo "Failed to verify package on PyPI"
113+
exit 1
114+
fi
115+
fi
116+
117+
build_docker_image $VERSION "socketdev/cli:stable"
118+
docker push socketdev/cli:stable
119+
fi
120+
121+
if [ $ENABLE_PYPI_BUILD = "pypi-build=local" ]; then
122+
echo "Building local version without publishing to PyPI"
123+
124+
# Determine PyPI source and build parameters
125+
if [ $STABLE_VERSION = "stable=prod" ]; then
126+
echo "Using production PyPI"
127+
PIP_INDEX_URL="https://pypi.org/simple"
128+
PIP_EXTRA_INDEX_URL="https://pypi.org/simple"
129+
TAG_SUFFIX="local"
130+
USE_LOCAL_INSTALL="false"
131+
elif [ $STABLE_VERSION = "stable=test" ]; then
132+
echo "Using test PyPI"
133+
PIP_INDEX_URL="https://test.pypi.org/simple"
134+
PIP_EXTRA_INDEX_URL="https://pypi.org/simple"
135+
TAG_SUFFIX="local-test"
136+
USE_LOCAL_INSTALL="false"
137+
elif [ $STABLE_VERSION = "stable=false" ]; then
138+
echo "Using local development install (pip install -e .)"
139+
TAG_SUFFIX="local-dev"
140+
USE_LOCAL_INSTALL="true"
141+
PIP_INDEX_URL="https://pypi.org/simple"
142+
PIP_EXTRA_INDEX_URL="https://pypi.org/simple"
143+
else
144+
echo "For local builds, use stable=prod, stable=test, or stable=false"
145+
exit 1
146+
fi
147+
148+
# Create language-specific tag if non-default versions are used
149+
LANG_TAG=""
150+
if [ "$GO_VERSION" != "1.21" ] || [ "$JAVA_VERSION" != "17" ] || [ "$DOTNET_VERSION" != "8" ]; then
151+
LANG_TAG="-go${GO_VERSION}-java${JAVA_VERSION}-dotnet${DOTNET_VERSION}"
152+
fi
153+
154+
build_docker_image $VERSION "socketdev/cli:$VERSION-$TAG_SUFFIX$LANG_TAG" $PIP_INDEX_URL $PIP_EXTRA_INDEX_URL $USE_LOCAL_INSTALL "Dockerfile.flexible"
155+
156+
build_docker_image $VERSION "socketdev/cli:$TAG_SUFFIX$LANG_TAG" $PIP_INDEX_URL $PIP_EXTRA_INDEX_URL $USE_LOCAL_INSTALL "Dockerfile.flexible"
157+
158+
echo "Local build complete. Tagged as:"
159+
echo " - socketdev/cli:$VERSION-$TAG_SUFFIX$LANG_TAG"
160+
echo " - socketdev/cli:$TAG_SUFFIX$LANG_TAG"
161+
fi

socketsecurity/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
__author__ = 'socket.dev'
2-
__version__ = '2.2.27'
2+
__version__ = '2.2.32'
33
USER_AGENT = f'SocketPythonCLI/{__version__}'

socketsecurity/config.py

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ class CliConfig:
7373
reach_skip_cache: bool = False
7474
reach_min_severity: Optional[str] = None
7575
reach_output_file: Optional[str] = None
76+
reach_concurrency: Optional[int] = None
77+
reach_additional_params: Optional[List[str]] = None
7678
only_facts_file: bool = False
7779

7880
@classmethod
@@ -132,6 +134,8 @@ def from_args(cls, args_list: Optional[List[str]] = None) -> 'CliConfig':
132134
'reach_skip_cache': args.reach_skip_cache,
133135
'reach_min_severity': args.reach_min_severity,
134136
'reach_output_file': args.reach_output_file,
137+
'reach_concurrency': args.reach_concurrency,
138+
'reach_additional_params': args.reach_additional_params,
135139
'only_facts_file': args.only_facts_file,
136140
'version': __version__
137141
}
@@ -169,6 +173,11 @@ def from_args(cls, args_list: Optional[List[str]] = None) -> 'CliConfig':
169173
logging.error("--only-facts-file requires --reach to be specified")
170174
exit(1)
171175

176+
# Validate reach_concurrency is >= 1 if provided
177+
if args.reach_concurrency is not None and args.reach_concurrency < 1:
178+
logging.error("--reach-concurrency must be >= 1")
179+
exit(1)
180+
172181
return cls(**config_args)
173182

174183
def to_dict(self) -> dict:
@@ -429,20 +438,13 @@ def create_argument_parser() -> argparse.ArgumentParser:
429438
help="Exclude license details from the diff report (boosts performance for large repos)"
430439
)
431440

432-
# Security Configuration
433-
security_group = parser.add_argument_group('Security Configuration')
434-
security_group.add_argument(
435-
"--allow-unverified",
436-
action="store_true",
437-
help="Allow unverified packages"
438-
)
439-
security_group.add_argument(
441+
output_group.add_argument(
440442
"--disable-security-issue",
441443
dest="disable_security_issue",
442444
action="store_true",
443445
help="Disable security issue checks"
444446
)
445-
security_group.add_argument(
447+
output_group.add_argument(
446448
"--disable_security_issue",
447449
dest="disable_security_issue",
448450
action="store_true",
@@ -494,6 +496,11 @@ def create_argument_parser() -> argparse.ArgumentParser:
494496
help="Timeout in seconds for API requests",
495497
required=False
496498
)
499+
advanced_group.add_argument(
500+
"--allow-unverified",
501+
action="store_true",
502+
help="Disable SSL certificate verification for API requests"
503+
)
497504
config_group.add_argument(
498505
"--include-module-folders",
499506
dest="include_module_folders",
@@ -567,6 +574,20 @@ def create_argument_parser() -> argparse.ArgumentParser:
567574
default=".socket.facts.json",
568575
help="Output file path for reachability analysis results (default: .socket.facts.json)"
569576
)
577+
reachability_group.add_argument(
578+
"--reach-concurrency",
579+
dest="reach_concurrency",
580+
type=int,
581+
metavar="<number>",
582+
help="Concurrency level for reachability analysis (must be >= 1)"
583+
)
584+
reachability_group.add_argument(
585+
"--reach-additional-params",
586+
dest="reach_additional_params",
587+
nargs='+',
588+
metavar="<param>",
589+
help="Additional parameters to pass to the coana CLI (e.g., --reach-additional-params --other-param value --another-param value2)"
590+
)
570591
reachability_group.add_argument(
571592
"--only-facts-file",
572593
dest="only_facts_file",

0 commit comments

Comments
 (0)