feat: enhance sensor pipeline to build and scan only changed sensors, optimize Dockerfile for NetworkScanDetector

This commit is contained in:
andreicscs
2026-04-04 22:37:13 +02:00
parent abef96114a
commit 21b9fa3174
2 changed files with 62 additions and 45 deletions
+52 -32
View File
@@ -33,7 +33,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3 # Use v3, v4 is often still in beta/preview
uses: github/codeql-action/init@v3
with:
languages: python
- name: Perform CodeQL Analysis
@@ -51,12 +51,15 @@ jobs:
with:
files: Sensors/**
- name: Build and Scan Changed Sensors
if: steps.changed-files.outputs.any_changed == 'true'
run: |
for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
SENSOR_DIR=$(dirname "$file")
if [ -f "$SENSOR_DIR/Dockerfile" ]; then
# FIXED: Context set to '.' (repo root) so Docker can copy the SDKs
docker build -t test-sensor:latest -f "$SENSOR_DIR/Dockerfile" .
# Extract unique sensor directories (e.g., "Sensors/official/WebRouterDecoy") to prevent double-building
UNIQUE_DIRS=$(echo "${{ steps.changed-files.outputs.all_changed_files }}" | tr ' ' '\n' | awk -F/ '{print $1"/"$2"/"$3}' | sort -u)
for TARGET_DIR in $UNIQUE_DIRS; do
if [ -d "$TARGET_DIR" ] && [ -f "$TARGET_DIR/Dockerfile" ]; then
echo "🔒 Scanning: $TARGET_DIR"
docker build -t test-sensor:latest -f "$TARGET_DIR/Dockerfile" .
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 --no-progress test-sensor:latest
fi
@@ -78,28 +81,32 @@ jobs:
with:
files: Sensors/**
- name: Run Test Mode on Changed Sensors
if: steps.changed-files.outputs.any_changed == 'true'
run: |
for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
SENSOR_DIR=$(dirname "$file")
if [ -f "$SENSOR_DIR/Dockerfile" ]; then
# FIXED: Context set to '.' (repo root) so Docker can copy the SDKs
docker build -t test-sensor:latest -f "$SENSOR_DIR/Dockerfile" .
# Extract unique sensor directories to prevent double-testing
UNIQUE_DIRS=$(echo "${{ steps.changed-files.outputs.all_changed_files }}" | tr ' ' '\n' | awk -F/ '{print $1"/"$2"/"$3}' | sort -u)
for TARGET_DIR in $UNIQUE_DIRS; do
if [ -d "$TARGET_DIR" ] && [ -f "$TARGET_DIR/Dockerfile" ]; then
echo "🧪 Testing: $TARGET_DIR"
docker build -t test-sensor:latest -f "$TARGET_DIR/Dockerfile" .
docker run --rm \
-e HW_HUB_ENDPOINT="http://172.17.0.1:8080" \
-e HW_HUB_KEY="mock_key" \
-e HW_SENSOR_ID="ci-test-node" \
-e HW_TEST_MODE="true" \
test-sensor:latest
if [ -f /tmp/test_passed ]; then
rm /tmp/test_passed
else
echo "❌ Test failed for $TARGET_DIR"
exit 1
fi
fi
done
# --- PATH A: REVIEWING A COMMUNITY PR ---
# This only runs during a Pull Request. It finishes green when you merge.
review-community-pr:
name: "👀 Review: Community Contribution"
needs: [static-analysis, docker-security-scan, functional-test]
@@ -114,12 +121,11 @@ jobs:
run: echo "Tests passed. Manual review required for PR merge." >> $GITHUB_STEP_SUMMARY
# --- PATH B: PUBLISHING AN OFFICIAL RELEASE ---
# This only runs when you push a TAG (v1.0) or run it manually.
# Standard pushes to 'main' will now SKIP this and finish GREEN.
publish-official-main:
name: "🚀 Publish: Official Sensor Release"
needs: [static-analysis, docker-security-scan, functional-test]
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
# Triggers on tags OR standard push to main OR manual dispatch
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'push' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
environment:
name: production_registry
@@ -129,28 +135,42 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
with:
# We ONLY care about changes to OFFICIAL sensors for publishing
files: Sensors/official/**
- name: Log in to GHCR
if: steps.changed-files.outputs.any_changed == 'true' || github.event_name == 'workflow_dispatch'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and Push All Official Sensors
- name: Build and Push Changed Official Sensors
if: steps.changed-files.outputs.any_changed == 'true' || github.event_name == 'workflow_dispatch'
run: |
# Loop through every Dockerfile in the official sensors directory
for dockerfile in Sensors/official/*/Dockerfile; do
# Extract the folder name (e.g., "WebRouterDecoy")
SENSOR_DIR_NAME=$(basename $(dirname "$dockerfile"))
# Convert to lowercase because Docker registries reject uppercase names
LOWERCASE_NAME=$(echo "$SENSOR_DIR_NAME" | tr '[:upper:]' '[:lower:]')
# Construct the final GHCR image name
IMAGE_NAME="ghcr.io/${{ github.repository_owner }}/honeywire-${LOWERCASE_NAME}"
echo "🚀 Building and pushing: $IMAGE_NAME"
docker build -t $IMAGE_NAME:latest -f "$dockerfile" .
docker push $IMAGE_NAME:latest
# If triggered manually, build all. Otherwise, only build what changed.
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
UNIQUE_DIRS=$(ls -d Sensors/official/*)
else
UNIQUE_DIRS=$(echo "${{ steps.changed-files.outputs.all_changed_files }}" | tr ' ' '\n' | awk -F/ '{print $1"/"$2"/"$3}' | sort -u)
fi
for TARGET_DIR in $UNIQUE_DIRS; do
if [ -d "$TARGET_DIR" ] && [ -f "$TARGET_DIR/Dockerfile" ]; then
SENSOR_DIR_NAME=$(basename "$TARGET_DIR")
LOWERCASE_NAME=$(echo "$SENSOR_DIR_NAME" | tr '[:upper:]' '[:lower:]')
IMAGE_NAME="ghcr.io/${{ github.repository_owner }}/honeywire-${LOWERCASE_NAME}"
echo "🚀 Building and pushing: $IMAGE_NAME"
docker build -t $IMAGE_NAME:latest -f "$TARGET_DIR/Dockerfile" .
docker push $IMAGE_NAME:latest
fi
done
+10 -13
View File
@@ -2,12 +2,13 @@
FROM python:3.11-slim AS builder
WORKDIR /app
# 1. Install git and the libpcap library
RUN apt-get update && apt-get install -y git libpcap0.8 && rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -y git libpcap0.8 libpcap-dev && rm -rf /var/lib/apt/lists/*
# 2. Extract the compiled libpcap C-libraries into a staging folder
# We use wildcards so this works on both Intel/AMD (x86) and Apple Silicon (ARM)
RUN mkdir -p /app/clibs && cp /usr/lib/*-linux-gnu/libpcap.so.* /app/clibs/
# 1. Create the clibs folder and copy the versioned library
RUN mkdir -p /app/clibs && \
cp /usr/lib/*-linux-gnu/libpcap.so.0.8 /app/clibs/ && \
# 2. MANDATORY: Create the generic symlink Scapy expects
ln -s /app/clibs/libpcap.so.0.8 /app/clibs/libpcap.so
# 3. Copy SDK and build
COPY SDKs/python-honeywire /tmp/sdk_src
@@ -18,24 +19,20 @@ RUN pip install --no-cache-dir wheel && \
COPY Sensors/official/NetworkScanDetector/requirements.txt .
RUN pip install --no-cache-dir --target /app/lib /tmp/wheels/honeywire-*.whl -r requirements.txt
# --- Stage 2: Production (Distroless) ---
# --- Stage 2: Distroless ---
FROM gcr.io/distroless/python3-debian12
WORKDIR /app
# 5. Copy the smuggled C-libraries from the builder
# 3. Copy the clibs (including the symlink)
COPY --from=builder /app/clibs /app/clibs
# 6. Copy the Python dependencies
# 4. Same as before
COPY --from=builder /app/lib /app/lib
# 7. Copy your sensor logic
COPY Sensors/official/NetworkScanDetector/NetworkScanDetector.py .
# 8. Tell Python where your packages are, AND tell Linux where your smuggled C-libraries are
ENV PYTHONPATH="/app/lib"
# 5. Tell the system to look in /app/clibs for our stolen files
ENV LD_LIBRARY_PATH="/app/clibs"
ENV PYTHONUNBUFFERED=1
# Distroless has Python as the hardcoded ENTRYPOINT, so this works natively without throwing Error 127
CMD ["NetworkScanDetector.py"]