mirror of
https://github.com/andreicscs/HoneyWire
synced 2026-06-26 12:39:53 +00:00
feat: enhance sensor pipeline to build and scan only changed sensors, optimize Dockerfile for NetworkScanDetector
This commit is contained in:
@@ -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
|
||||
@@ -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"]
|
||||
Reference in New Issue
Block a user