Skip to content

fix(docker): adopt Azure Linux base + remove EOL packaging tools to clear S360 SCA findings#50

Merged
colombod merged 2 commits into
mainfrom
fix/dockerfile-azurelinux-sca
Jul 9, 2026
Merged

fix(docker): adopt Azure Linux base + remove EOL packaging tools to clear S360 SCA findings#50
colombod merged 2 commits into
mainfrom
fix/dockerfile-azurelinux-sca

Conversation

@payneio

@payneio payneio commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

What

Fixes the 4 Qualys SCA (S360) container-image findings on the context-intelligence-server image, all inherited from the base image's Python packaging tools.

  • Base swap: python:3.11-slimmcr.microsoft.com/azurelinux/base/python:3.12.9-13-azl3.0.20260706. Matches the amplifier-online provisioner pattern and the AzureLinux 3.0 AKS nodes this service runs on. Azure Linux is continuously patched via a fix-only feed, so a build-time tdnf update clears reported CRITICAL/HIGH without suppression lists.
  • apttdnf for the curl / ca-certificates install.
  • Security step: removes the vulnerable EOL packaging rpms (pip, setuptools, wheel) and their leftover files, then reinstalls only a patched setuptools.

Why the removal approach

In-place upgrades (pip install --upgrade / uv pip install) do not clear these findings: the rpm-installed dist-info has no RECORD, so pip/uv leave the old metadata orphaned next to the new. Scanners key on the dist-info METADATA, so the vulnerable version keeps getting reported. This app builds with hatchling and imports none of pip/setuptools/wheel at runtime, so the cleanest durable fix is to remove the OS rpms outright. A patched setuptools is reinstalled because some transitive deps still import pkg_resources.

Findings cleared

QID CVE Package Resolution
5011855 CVE-2026-6357 pip removed
5005553 CVE-2025-8869 pip removed
5007163 CVE-2026-24049 wheel removed
5006986 CVE-2026-23949 jaraco.context setuptools 83.0.0 (vendored jaraco_context 6.1.0 ≥ 4.3.0)

Notes

  • Python 3.11 → 3.12, within requires-python >= 3.11.
  • Verified locally: image builds; scan surface shows only setuptools-83.0.0.dist-info (no orphaned old metadata; pip/wheel fully gone); import context_intelligence_server.main succeeds with auth disabled.

Suggested CI

uv run pytest tests/ -q

payneio and others added 2 commits July 9, 2026 13:32
…lear S360 SCA findings

Swap the runtime base from python:3.11-slim to Microsoft Azure Linux 3.0
(mcr.microsoft.com/azurelinux/base/python:3.12.9-13-azl3.0.20260706), matching the
amplifier-online provisioner pattern and the AzureLinux 3.0 AKS nodes this service
runs on. Azure Linux is continuously patched via a fix-only feed, so a build-time
`tdnf update` clears reported CRITICAL/HIGH without suppression lists.

The base ships EOL Python packaging tools (pip/setuptools/wheel) that Qualys SCA
(S360) flags. In-place upgrades don't clear the findings: the rpm-installed
dist-info has no RECORD, so pip/uv leave the old metadata orphaned next to the new,
and scanners key on the dist-info METADATA. Since this app builds with hatchling and
imports none of these at runtime, remove the vulnerable OS rpms outright (and their
leftover files) and reinstall only a patched setuptools (some transitive deps still
import pkg_resources).

Clears:
  - QID 5011855 (CVE-2026-6357) / 5005553 (CVE-2025-8869) — pip   -> removed
  - QID 5007163 (CVE-2026-24049)                          — wheel -> removed
  - QID 5006986 (CVE-2026-23949)                          — setuptools 83.0.0
    (vendored jaraco_context 6.1.0 >= 4.3.0)

Notes:
  - Python 3.11 -> 3.12, within requires-python >= 3.11.
  - apt-get -> tdnf for curl/ca-certificates.

Verified locally: image builds; scan surface shows only setuptools-83.0.0.dist-info
(no orphaned old metadata; pip/wheel fully gone); `import context_intelligence_server.main`
succeeds.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…d image string

The test_dockerfile_base_image() assertion was brittle — it hardcoded
an exact image string (FROM python:3.11-slim) and broke whenever the base
image legitimately changed for security, Python version, or platform reasons.

Paul's Azure Linux base swap is a valid security-driven change that cleared
four Qualys SCA findings. This commit replaces the implementation-detail test
with a capability-based check: the Dockerfile's FROM line must declare a Python
base at version >= 3.11 (matching requires-python). The test now parses the
FROM line using regex and enforces the real contract instead of a literal string.

All 25 tests in the suite now pass against both the old and new base images.

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
@colombod colombod force-pushed the fix/dockerfile-azurelinux-sca branch from 4c119cb to 2784c95 Compare July 9, 2026 13:37
@colombod colombod merged commit 731187c into main Jul 9, 2026
2 checks passed
@colombod colombod deleted the fix/dockerfile-azurelinux-sca branch July 9, 2026 13:57
colombod added a commit that referenced this pull request Jul 9, 2026
…al build-run-curl integration test

Replace text-match tests that break on legitimate changes (false red) and pass while the
real thing is broken (false green) with a single integration test that builds the image,
runs the container, and curls the /status endpoint — proven end-to-end locally (~82s).

The suite had ~25 brittle string-echo tests (assert "curl" in content, etc). This change:

- ADDS tests/integration/test_docker_image.py: Builds the Dockerfile, runs the container
  with ALLOW_UNAUTHENTICATED=true (documented dev/test opt-out), and curls /status,
  asserting a real 200 with neo4j_connected=False (soft-fail, proving the endpoint
  probed). Uses existing house docker-SDK pattern (docker, httpx already dev deps),
  skips cleanly when Docker unavailable, overrides 30s pytest-timeout. Auto-marks
  integration, so runs in existing non-blocking integration-tests CI job — no workflow
  change needed. Verified locally: passes in ~82s real build + run + curl.

- SLIMS tests/test_docker_infrastructure.py from ~25 string-echo tests to 2 that encode
  real contracts and stay fast + blocking in unit job:
  (1) base image must be Python >= 3.11 (requires-python floor, parsed from FROM — not
      a hardcoded string); and
  (2) Neo4j credentials must not be inlined in compose (security policy; auth via env_file).

Closes brittle-test anti-pattern exposed by PR #50 (Azure Linux base swap broke CI
because test hardcoded python:3.11-slim).

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
colombod added a commit that referenced this pull request Jul 11, 2026
…st Docker-for-Neo4j workflow

Remove maintained Docker artifacts from the repo (keeping ONLY the
S360-compliant server Dockerfile) and rewrite documentation/setup around a
local-first workflow that runs Neo4j in a documented Docker container.

Removed:
- docker-compose.yml, docker-compose.airgap.yml (unused Compose stack)
- start.sh (Compose wrapper)
- neo4j.Dockerfile (Neo4j no longer shipped as a container image)
- test/airgap/ (README.md, dtu-profile.yaml, verify-airgap-apoc.sh)
- tests/test_docker_compose_simplified.py, tests/test_docker_infrastructure.py,
  tests/test_start_sh.py (now-subjectless tests)

Kept intentionally: the server Dockerfile (S360/Qualys-compliant Azure Linux
base, PR #50), .dockerignore, docker-entrypoint.sh, tests/neo4j/ fixtures and
the docker dev-dependency.

Added:
- scripts/prime-local-config.py — stdlib-only local key-priming helper that
  replaces the old Docker credential bootstrap (generates the API token, prints
  it once, stores only the sha256 digest, writes server-config.yaml with
  bolt://localhost:7687 and a local writable data tree).
- docs/local-development.md — canonical "Running Locally" guide: Neo4j via a
  single documented `docker run` (NEO4J_PLUGINS auto-installs APOC + GDS,
  --restart unless-stopped for boot persistence), key priming, run the server,
  plus ask-Amplifier prompts.

Changed:
- README.md — removed the Docker Compose / single-container run sections and all
  references to deleted files; local-first is now the primary path.
- docs/azure-deployment.md — rewritten into a generic, compliant "deploy via
  amplifier-online" guide (no as-built specifics/secrets/IPs): S360 base-image
  policy (PR #50), a Neo4j VM build section (capacity, APOC+GDS, persistent
  disk, private VNet/NSG), Key Vault secret wiring with the declarative-redeploy
  rule, dual-client config keyed to the Neo4j Community single-account reality,
  and a Neo4j-safe version-bump runbook.
- docs/service-setup.md — local Neo4j guidance; removed the docker-compose Caddy
  HTTPS section.
- docs/managing-api-keys.md — local prime-local-config.py bootstrap.
- docs/remote-access-sharing.md — standalone/local host-binding + backup/restore.
- docs/designs/per-user-api-keys.md — bootstrap references off deleted start.sh.
- AGENTS.md — keep/remove policy and the S360 base-image compliance anchor.
- amplifier-online.yaml — deployed image tag reference v6.0.0 -> v6.6.6.

Validation: `pytest tests/` collects 1881 tests with no errors;
scripts/prime-local-config.py passes ruff + pyright and was tested end-to-end;
repo-wide grep confirms zero broken references to any deleted file.

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
colombod added a commit that referenced this pull request Jul 11, 2026
…st Docker-for-Neo4j workflow

Remove maintained Docker artifacts from the repo (keeping ONLY the
S360-compliant server Dockerfile) and rewrite documentation/setup around a
local-first workflow that runs Neo4j in a documented Docker container.

Removed:
- docker-compose.yml, docker-compose.airgap.yml (unused Compose stack)
- start.sh (Compose wrapper)
- neo4j.Dockerfile (Neo4j no longer shipped as a container image)
- test/airgap/ (README.md, dtu-profile.yaml, verify-airgap-apoc.sh)
- tests/test_docker_compose_simplified.py, tests/test_docker_infrastructure.py,
  tests/test_start_sh.py (now-subjectless tests)

Kept intentionally: the server Dockerfile (S360/Qualys-compliant Azure Linux
base, PR #50), .dockerignore, docker-entrypoint.sh, tests/neo4j/ fixtures and
the docker dev-dependency.

Added:
- scripts/prime-local-config.py — stdlib-only local key-priming helper that
  replaces the old Docker credential bootstrap (generates the API token, prints
  it once, stores only the sha256 digest, writes server-config.yaml with
  bolt://localhost:7687 and a local writable data tree).
- docs/local-development.md — canonical "Running Locally" guide: Neo4j via a
  single documented `docker run` (NEO4J_PLUGINS auto-installs APOC + GDS,
  --restart unless-stopped for boot persistence), key priming, run the server,
  plus ask-Amplifier prompts.

Changed:
- README.md — removed the Docker Compose / single-container run sections and all
  references to deleted files; local-first is now the primary path.
- docs/azure-deployment.md — rewritten into a generic, compliant "deploy via
  amplifier-online" guide (no as-built specifics/secrets/IPs): S360 base-image
  policy (PR #50), a Neo4j VM build section (capacity, APOC+GDS, persistent
  disk, private VNet/NSG), Key Vault secret wiring with the declarative-redeploy
  rule, dual-client config keyed to the Neo4j Community single-account reality,
  and a Neo4j-safe version-bump runbook.
- docs/service-setup.md — local Neo4j guidance; removed the docker-compose Caddy
  HTTPS section.
- docs/managing-api-keys.md — local prime-local-config.py bootstrap.
- docs/remote-access-sharing.md — standalone/local host-binding + backup/restore.
- docs/designs/per-user-api-keys.md — bootstrap references off deleted start.sh.
- AGENTS.md — keep/remove policy and the S360 base-image compliance anchor.
- amplifier-online.yaml — deployed image tag reference v6.0.0 -> v6.6.6.

Validation: `pytest tests/` collects 1881 tests with no errors;
scripts/prime-local-config.py passes ruff + pyright and was tested end-to-end;
repo-wide grep confirms zero broken references to any deleted file.

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
colombod added a commit that referenced this pull request Jul 13, 2026
…st Docker-for-Neo4j workflow

Remove maintained Docker artifacts from the repo (keeping ONLY the
S360-compliant server Dockerfile) and rewrite documentation/setup around a
local-first workflow that runs Neo4j in a documented Docker container.

Removed:
- docker-compose.yml, docker-compose.airgap.yml (unused Compose stack)
- start.sh (Compose wrapper)
- neo4j.Dockerfile (Neo4j no longer shipped as a container image)
- test/airgap/ (README.md, dtu-profile.yaml, verify-airgap-apoc.sh)
- tests/test_docker_compose_simplified.py, tests/test_docker_infrastructure.py,
  tests/test_start_sh.py (now-subjectless tests)

Kept intentionally: the server Dockerfile (S360/Qualys-compliant Azure Linux
base, PR #50), .dockerignore, docker-entrypoint.sh, tests/neo4j/ fixtures and
the docker dev-dependency.

Added:
- scripts/prime-local-config.py — stdlib-only local key-priming helper that
  replaces the old Docker credential bootstrap (generates the API token, prints
  it once, stores only the sha256 digest, writes server-config.yaml with
  bolt://localhost:7687 and a local writable data tree).
- docs/local-development.md — canonical "Running Locally" guide: Neo4j via a
  single documented `docker run` (NEO4J_PLUGINS auto-installs APOC + GDS,
  --restart unless-stopped for boot persistence), key priming, run the server,
  plus ask-Amplifier prompts.

Changed:
- README.md — removed the Docker Compose / single-container run sections and all
  references to deleted files; local-first is now the primary path.
- docs/azure-deployment.md — rewritten into a generic, compliant "deploy via
  amplifier-online" guide (no as-built specifics/secrets/IPs): S360 base-image
  policy (PR #50), a Neo4j VM build section (capacity, APOC+GDS, persistent
  disk, private VNet/NSG), Key Vault secret wiring with the declarative-redeploy
  rule, dual-client config keyed to the Neo4j Community single-account reality,
  and a Neo4j-safe version-bump runbook.
- docs/service-setup.md — local Neo4j guidance; removed the docker-compose Caddy
  HTTPS section.
- docs/managing-api-keys.md — local prime-local-config.py bootstrap.
- docs/remote-access-sharing.md — standalone/local host-binding + backup/restore.
- docs/designs/per-user-api-keys.md — bootstrap references off deleted start.sh.
- AGENTS.md — keep/remove policy and the S360 base-image compliance anchor.
- amplifier-online.yaml — deployed image tag reference v6.0.0 -> v6.6.6.

Validation: `pytest tests/` collects 1881 tests with no errors;
scripts/prime-local-config.py passes ruff + pyright and was tested end-to-end;
repo-wide grep confirms zero broken references to any deleted file.

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants