Fix lab automation: 8 bugs blocking make lab-up + verified C2 boot#42
Merged
Conversation
Audit of the Makefile, requirements files, CI, and lab images uncovered eight bugs that prevented a clean checkout from booting the lab. All are fixed and verified by building images and curling the C2 operator API from the host. - tools/idol/01-credential-harvest.py: NameError on `targets` (out of scope after a refactor). Extracted _credential_targets() helper and wired tools/idol/tests/ into both CI workflows so a future regression is caught. - 5 mock-* Dockerfiles (mock-imds, mock-entra, mock-slack, mock-oauth, mock-graph) COPYed requirements.txt files that were deleted in the uv-workspace migration. Replaced with inline pip install matching the Dockerfile.beacon / c2-server pattern. - Dockerfile.c2-server and Dockerfile.exploit-server: `useradd operator` fails because python:*-slim has a Debian-legacy `operator:x:37` system group. Use `-g operator operator` to reuse it. - Dockerfile.c2-server was missing cryptography and pyjwt, both used by tools/c2/server.py at import time. - ContainmentGuard.assert_loopback rejected 0.0.0.0, blocking the server from binding inside the container. Allow 0.0.0.0 only when in_docker() is true; the host port mapping is still loopback-only. - docker-compose.lab.yml declared `internal: true` AND `ports:` on every service, which docker silently drops. Added a lab-bridge network for the user-facing services so host port publication works; beacons stay on lab-internal only. ContainmentGuard continues to enforce loopback/RFC1918 at the tool layer. - make lab-arc-up/down referenced infra/lab/mock-imds/Dockerfile and mock_imds.py, neither of which exists. The mock-imds server already serves the Azure Arc MSI endpoint unconditionally, so the target now just ensures the existing compose service is up. - The six ci/check_*.py gates were advertised in tool READMEs as CI gates but never invoked by either workflow. Wired all six into the Repo hygiene step. While here, bumped python:3.12-slim to python:3.14-slim across all nine Dockerfiles and the phishing compose fragment. Verified end-to-end: docker compose up -d c2-server publishes 127.0.0.1:8443, and `curl http://127.0.0.1:8443/api/status` from the host returns HTTP 401 {"error":"unauthorized"} — AuthGuard rejecting the unauthenticated operator API call, which is the expected behavior. Pytest 108 passed / 3 skipped, all 9 hygiene checks pass, Rust workspace builds and tests pass, dashboard builds. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Audit of the Makefile, requirements files, CI, and lab images turned up eight bugs that prevented a clean checkout from booting the lab. All are fixed and verified end-to-end by building images and hitting the C2 operator API from the host.
tools/idol/01-credential-harvest.py:134—NameError: name 'targets' is not defined. Extracted_credential_targets()helper. Hidden becausetools/idol/tests/was not wired into CI; now it is.mock-imds,mock-entra,mock-slack,mock-oauth,mock-graph)COPYedrequirements.txtfiles deleted in the uv-workspace migration (commit1bdeeeb). Replaced with inlinepip installmatching the existingDockerfile.beacon/Dockerfile.c2-serverpattern.Dockerfile.c2-serverandDockerfile.exploit-server—useradd operatorfailed becausepython:*-slimhas the Debian-legacyoperator:x:37system group. Use-g operator operatorto reuse it.Dockerfile.c2-servermissing deps —tools/c2/server.pyimportscryptographyandpyjwt; onlyflask requestswas installed.ContainmentGuard.assert_loopbackrejected0.0.0.0, blocking the server from binding inside the container. Now allowed only whenin_docker()is true; host port mapping remains loopback-only.docker-compose.lab.ymldeclaredinternal: trueandports:on every service — Docker silently drops the publication. Added alab-bridgenetwork for user-facing services; beacons stay onlab-internalonly.ContainmentGuardcontinues enforcing loopback/RFC1918 at the tool layer.make lab-arc-up/lab-arc-downreferencedinfra/lab/mock-imds/Dockerfileandmock_imds.py, neither of which exists. The existing mock-imds server already serves the Azure Arc MSI endpoint unconditionally — target now just ensures the compose service is up.ci/check_*.pygates were advertised in tool READMEs as CI gates but never invoked by either workflow. Wired all six into the Repo hygiene step.While here: bumped
python:3.12-slimtopython:3.14-slimacross the 9 Dockerfiles and the phishing compose fragment.Test plan
main, no merge conflictsuv sync --all-packagescleantools/ci/check_*.pyandci/check_*.py)pytest— 108 passed, 3 skipped (was 44;tools/idol/tests/adds 64)cargo test --workspace -- --test-threads=1)reports/databricks-apps-assessment/build.py)docker compose build)docker compose up -d c2-serverpublishes127.0.0.1:8443->8443/tcpcurl http://127.0.0.1:8443/api/statusfrom host returnsHTTP 401 {"error":"unauthorized"}(AuthGuard correctly rejecting unauthenticated call)Generated with Claude Code