Skip to content

Update to latest version of mudcerts #129

Update to latest version of mudcerts

Update to latest version of mudcerts #129

Workflow file for this run

name: ci
on:
push:
branches: [main]
paths-ignore:
- '**.md'
- 'images/**'
- 'LICENSE'
- 'CODE_OF_CONDUCT.md'
- 'CONTRIBUTING.md'
pull_request:
paths-ignore:
- '**.md'
- 'images/**'
- 'LICENSE'
- 'CODE_OF_CONDUCT.md'
- 'CONTRIBUTING.md'
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
lint-and-unit:
name: Lint + unit
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
- name: Dockerfile guard rail — no secrets in image layers
# T-05/T-18 defence-in-depth: fail the build if the Dockerfile
# ever tries to bake a secret into an image layer. Secrets
# must arrive at container start via a compose `secrets:`
# block, a runtime bind-mount, or an external secret manager
# -- never via COPY, ENV, or ARG. The bind-mounted
# `config.ini` handled by docker-compose.yml is fine; this
# check only fires on `COPY .../config.ini` lines in
# Dockerfile itself.
run: |
set -e
bad=$(grep -nEi \
-e '^[[:space:]]*COPY[[:space:]].*config\.ini' \
-e '^[[:space:]]*ENV[[:space:]].*(SECRET|CLIENT_SECRET|TOKEN|PASSWORD|PASSPHRASE|API_?KEY|CREDENTIAL|PRIVATE_KEY)([[:space:]=]|$)' \
-e '^[[:space:]]*ARG[[:space:]].*(SECRET|CLIENT_SECRET|TOKEN|PASSWORD|PASSPHRASE|API_?KEY|CREDENTIAL|PRIVATE_KEY)([[:space:]=]|$)' \
Dockerfile || true)
if [ -n "$bad" ]; then
echo "::error title=Dockerfile secret leak::Secrets must not be baked into image layers." >&2
echo "Offending lines:" >&2
echo "$bad" >&2
echo "" >&2
echo "Fix: inject secrets at container start via a compose" >&2
echo "'secrets:' block, a runtime bind-mount, or an external" >&2
echo "secret manager. See GITHUB_REMEDIATION_PLAN.md and the" >&2
echo "discussion in the security notes for details." >&2
exit 1
fi
echo "OK: no secret-shaped tokens or config.ini COPYs in Dockerfile."
- uses: actions/setup-python@v7
with:
python-version: '3.12'
cache: pip
cache-dependency-path: gitmud/requirements.txt
- uses: actions/setup-node@v7
with:
node-version: '20'
- name: Install Python deps
run: |
python -m pip install --upgrade pip
pip install -r gitmud/requirements.txt
- name: Python syntax check
run: python -m compileall -q gitmud/gitmud mudgen_pcap.py
- name: JS syntax sanity
run: |
for f in assets/js/dom-safe.js \
assets/js/mudmaker.js \
assets/js/mudmaker-reload.js \
assets/js/mudmaker-visualizer.js \
assets/js/omud.js \
assets/js/tabs.js \
assets/js/util.js; do
node --check "$f"
done
- name: Unit tests
env:
GITMUD_CONFIG: ${{ github.workspace }}/gitmud/config.ini
run: |
set -e
mkdir -p gitmud
cat > "$GITMUD_CONFIG" <<'CFG'
[github]
client_id = ci-stub
client_secret = ci-stub
[flask]
secret_key = ci-only-not-secret
[storage]
db_path = /tmp/gitmud-ci.sqlite
[security]
allowed_origins =
session_ttl_seconds = 3600
janitor_interval_seconds = 3600
legacy_mudurl_fallback = true
CFG
python tests/test_pcap_sanitise.py
python tests/test_publish_multi.py
python tests/test_acl_dedupe.py
python tests/test_pcap_merge.py
python tests/test_ref_sanitise.py
python tests/test_session_bearer.py
python tests/test_oauth_complete.py
docker-build:
name: Build docker images
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- uses: docker/setup-buildx-action@v4
- name: Validate docker-compose
run: docker compose config --quiet
- name: Verify MUDCERTS_REF is pinned to a commit SHA (T-28)
# Phase 5: reject non-SHA pins so a future accidental
# ``ARG MUDCERTS_REF=main`` cannot silently ship. A 40-char
# lowercase hex string is the only accepted form.
run: |
ref=$(awk '/^ARG MUDCERTS_REF=/{sub(/^ARG MUDCERTS_REF=/,"",$0); print; exit}' Dockerfile)
echo "MUDCERTS_REF = $ref"
if ! echo "$ref" | grep -Eq '^[0-9a-f]{40}$'; then
echo "MUDCERTS_REF must be a 40-char lowercase hex commit SHA" >&2
exit 1
fi
- name: Build mudzipserver
uses: docker/build-push-action@v7
with:
context: .
target: mudzipserver
tags: mudmaker-mudzipserver:ci
outputs: type=docker,dest=/tmp/mudzipserver.tar
cache-from: type=gha,scope=mudzipserver
cache-to: type=gha,scope=mudzipserver,mode=max
- name: Build gitmud
uses: docker/build-push-action@v7
with:
context: .
target: gitmud
tags: mudmaker-gitmud:ci
outputs: type=docker,dest=/tmp/gitmud.tar
cache-from: type=gha,scope=gitmud
cache-to: type=gha,scope=gitmud,mode=max
- name: Build mudmaker (httpd)
uses: docker/build-push-action@v7
with:
context: .
tags: mudmaker:ci
outputs: type=docker,dest=/tmp/mudmaker.tar
cache-from: type=gha,scope=mudmaker
cache-to: type=gha,scope=mudmaker,mode=max
- name: Upload image tarballs
uses: actions/upload-artifact@v7
with:
name: docker-images-${{ github.sha }}
path: /tmp/*.tar
retention-days: 1
if-no-files-found: error
integration:
name: Integration (live stack)
runs-on: ubuntu-latest
needs: docker-build
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: '3.12'
cache: pip
cache-dependency-path: gitmud/requirements.txt
- name: Install Python deps
run: |
python -m pip install --upgrade pip
pip install -r gitmud/requirements.txt
pip install playwright
- name: Download docker image tarballs
uses: actions/download-artifact@v8
with:
name: docker-images-${{ github.sha }}
path: /tmp/
- name: Load images and retag as :latest
run: |
set -e
for t in /tmp/*.tar; do
docker load -i "$t"
done
docker tag mudmaker-mudzipserver:ci mudmaker-mudzipserver:latest
docker tag mudmaker-gitmud:ci mudmaker-gitmud:latest
docker tag mudmaker:ci mudmaker:latest
docker image ls
- name: Stub gitmud config
run: |
mkdir -p gitmud
cat > gitmud/config.ini <<'CFG'
[github]
client_id = ci-stub
client_secret = ci-stub
[flask]
secret_key = ci-only-not-secret
[storage]
db_path = /var/lib/gitmud/tokens.sqlite
[security]
allowed_origins =
session_ttl_seconds = 3600
janitor_interval_seconds = 3600
legacy_mudurl_fallback = true
CFG
- name: Stage SmarterCoffee pcap fixtures
run: |
mkdir -p tmp/captures_IoT-Sentinel
cp -r tests/fixtures/SmarterCoffee tmp/captures_IoT-Sentinel/
- name: Bring up stack
run: |
docker compose up -d
# wait up to 60 s for mudmaker.html (httpd) to be served
for i in $(seq 1 30); do
if curl -fsS -o /dev/null http://127.0.0.1:8081/mudmaker.html; then
echo "mudmaker up after ${i} attempts"
break
fi
sleep 2
done
# wait up to 60 s for /pcap2mud (gitmud, via the proxy) to answer.
# A bare GET should return 405 once the route is registered.
for i in $(seq 1 30); do
code=$(curl -sS -o /dev/null -w '%{http_code}' http://127.0.0.1:8081/pcap2mud || true)
if [ "$code" = "405" ] || [ "$code" = "400" ]; then
echo "gitmud up after ${i} attempts (code ${code})"
exit 0
fi
sleep 2
done
echo "stack did not come up in time"
docker compose ps
docker compose logs --no-color
exit 1
- name: pcap2mud smoke (SmarterCoffee)
run: python tests/smoke_smartercoffee.py
- name: Signing smoke (Chrome, headless)
env:
MUDMAKER_HEADLESS: '1'
MUDMAKER_ARTIFACT_DIR: ${{ github.workspace }}/_artifacts
run: python tests/test_signing_chrome.py
- name: Drag-drop smoke (Chrome, headless)
env:
MUDMAKER_HEADLESS: '1'
run: python tests/test_dragdrop_chrome.py
- name: Capture compose logs
if: always()
run: |
mkdir -p _artifacts
docker compose logs --no-color > _artifacts/compose.log || true
docker compose ps > _artifacts/compose-ps.txt || true
- name: Upload artifacts on failure
if: failure()
uses: actions/upload-artifact@v7
with:
name: integration-artifacts-${{ github.sha }}
path: _artifacts/
retention-days: 7
if-no-files-found: ignore
- name: Tear down
if: always()
run: docker compose down -v