Skip to content

chore(examples): move Docker images to bases with fixed ca-certificates - #1602

Merged
mwbrooks merged 5 commits into
slackapi:mainfrom
davidmreed:emudhra-53119/docker
Oct 27, 2026
Merged

mwbrooks merged 5 commits into
slackapi:mainfrom
davidmreed:emudhra-53119/docker

Conversation

@davidmreed

@davidmreed davidmreed commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Opened as draft because it moves the example images to a different base distro (Debian buster -> bookworm, Alpine 3.17 -> 3.20).

What changes
The current buster and Alpine 3.17 bases cannot get the fixed ca-certificates package (Alpine 3.17's latest is 20240226-r0). Each Dockerfile moves to the nearest base that has a fixed package, staying on its current Python line. The shipped stage gets a gate: ARG CA_CERTIFICATES_REFRESH=2026-10-21, refresh ca-certificates, and fail the build if the package is older than the fixed version.

  • python:3.8.5-slim-buster -> python:3.8-slim-bookworm (still Python 3.8). The final stage gets a Debian dpkg --compare-versions gate. The gate keys on VERSION_CODENAME (bookworm 20250419~deb12u2, trixie 20250419+deb13u1) and fails on any other codename. Files:
    • examples/docker/aiohttp/Dockerfile (builder :4, final :10, ENTRYPOINT :15)
    • examples/docker/flask-gunicorn/Dockerfile (:4,9, ENTRYPOINT :14)
    • examples/docker/flask-uwsgi/Dockerfile (:4,12, ENTRYPOINT :18)
      • The builder's libpcre3-dev becomes libpcre2-dev.
      • A uWSGI built against libpcre3 fails at start on bookworm-slim (libpcre.so.3: cannot open shared object file), because the runtime image ships only libpcre2-8.
    • examples/docker/sanic/Dockerfile (:4,9, ENTRYPOINT :14)
    • examples/google_cloud_run/aiohttp/Dockerfile, flask-gunicorn/Dockerfile and sanic/Dockerfile (single stage :14, ENTRYPOINT :28)
  • python:3.11-alpine3.17 -> python:3.11-alpine3.20 (still Python 3.11), with an apk add --no-cache --upgrade ca-certificates ca-certificates-bundle gate in the final stage.
    • The gate checks both packages with apk version -t. It accepts only = or > against 20261020-r0 and treats a missing version as a failure.
    • 3.20 is the oldest Alpine whose repo carries 20261020-r0; the 3.18 repo has 20241121-r1 and the 3.19 repo has 20250911-r0.
    • File: examples/docker/asgi/Dockerfile (:4,9, ENTRYPOINT :14).
  • tiangolo/uvicorn-gunicorn:python3.8-slim is already Debian bookworm, so it keeps its base and only gets the Debian gate, before WORKDIR (examples/docker/fastapi-gunicorn/Dockerfile:4). It runs as root, so the refresh works in place.
  • No requirements files change. Each image already runs pip install -U pip (pip 25.0.1 on 3.8), so pip is >= 24.2 and PIP_CERT is not needed.

Where it ships

  • These are user templates. Nothing in this repo builds or deploys them; the published package is the PyPI wheel (.github/workflows/pypi-release.yml:62,86).
  • At runtime, slack_sdk and aiohttp use the OS trust store, which is what the gate protects. In the smoke runs, every app's TLS call to https://slack.com completed against the refreshed store.

Not covered by this PR

  • This PR does not address EOL status. Python 3.8 (all images except asgi), the frozen tiangolo/uvicorn-gunicorn:python3.8-slim image and Alpine 3.20 are all EOL. Moving the examples to a supported Python (3.13 needs sanic >= 25 and an explicit gunicorn/uvicorn-worker setup for FastAPI) is an owner follow-up.
  • examples/aws_lambda/*_config.yaml:6 still use python3.8 on Amazon Linux 2. There is no fixed package to gate on, and the fix depends on AWS. Owner follow-up.
  • The App Engine runtime move and the Cloud Functions certifi floor are in separate PRs.

Verification

  • docker build --no-cache succeeded for all 9 edited Dockerfiles (linux/arm64 host; the bases are multi-arch). Gate output:
    • Debian (8 images): ca-certificates gate OK: bookworm 20250419~deb12u2 >= 20250419~deb12u2
    • Alpine (docker/asgi): ca-certificates gate OK: ca-certificates 20261020-r0 >= 20261020-r0 and ca-certificates gate OK: ca-certificates-bundle 20261020-r0 >= 20261020-r0
  • Smoke run of each image with dummy SLACK_BOT_TOKEN/SLACK_SIGNING_SECRET:
    • aiohttp, sanic and Cloud Run aiohttp/sanic keep running: "Bolt app is running" and "Goin' Fast".
    • fastapi-gunicorn (-e VARIABLE_NAME=api) answers POST /slack/events with 401 (bad signature). urllib inside it fetches https://slack.com/api/api.test -> {"ok":true}.
    • asgi, flask-gunicorn (both) and flask-uwsgi call https://slack.com/api/auth.test at startup. TLS succeeds and the call returns invalid_auth because the token is a dummy.
  • Negative builds (the gate must fail):
    • Old base python:3.8.5-slim-buster (flask-gunicorn Dockerfile): ca-certificates gate: no fixed package known for 'buster', exit 1.
    • Old base python:3.11-alpine3.17: ca-certificates gate FAILED: ca-certificates 20240226-r0 < 20261020-r0, exit 1. With python:3.11-alpine3.19: ca-certificates gate FAILED: ca-certificates 20250911-r0 < 20261020-r0, exit 1.
    • python:3.8-slim-bookworm (Cloud Run flask-gunicorn) and tiangolo/uvicorn-gunicorn:python3.8-slim, built with --network=none so no refresh is possible: ca-certificates gate FAILED: bookworm 20230311 < 20250419~deb12u2, exit 1.
  • CI: the Python CI workflow is waiting for maintainer approval (fork PR), and it does not build the examples.
  • Not verified: Cloud Run deploys.

🤖 Generated with Claude Code
Part of the eMudhra 53119 CA-distrust remediation (CVE-2026-111943).

davidmreed and others added 2 commits October 22, 2026 10:53
…-certificates

The example Dockerfiles used python:3.8.5-slim-buster, python:3.11-alpine3.17
and tiangolo/uvicorn-gunicorn:python3.8-slim, none of which can get the fixed
ca-certificates package. Move them to python:3.13-slim-trixie /
python:3.13-alpine3.24 and add a ca-certificates version gate to the shipped
stage. Adjust what the new bases need: libpcre2-dev for uWSGI, sanic 25.12
(sanic 20 does not build on 3.13), and gunicorn + uvicorn-worker for the
FastAPI example that used to get them from the tiangolo image.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
…gi example

Accept only "=" or ">" from `apk version -t` and treat an empty version as a
failure, matching the incident's Alpine gate snippet.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
…bases

Move the buster images to python:3.8-slim-bookworm (same Python line)
instead of python:3.13-slim-trixie, and the asgi image to
python:3.11-alpine3.20 (the oldest Alpine whose repo carries
20261020-r0) instead of python:3.13-alpine3.24. The tiangolo FastAPI
image is already bookworm, so it keeps its base and only gets the gate.
This drops the sanic 20 -> 25 bump, the FastAPI gunicorn/uvicorn-worker
requirements and CMD, and the AS casing change. libpcre2-dev stays,
since bookworm-slim ships libpcre2-8 but not libpcre3 at runtime.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
@davidmreed davidmreed changed the title [eMudhra 53119][Docker] Move example images off EOL bases and gate ca-certificates [eMudhra 53119][Docker] Move example images to the nearest bases with fixed ca-certificates and gate them Oct 22, 2026
@davidmreed
davidmreed marked this pull request as ready for review October 22, 2026 19:57
@davidmreed
davidmreed requested a review from a team as a code owner October 22, 2026 19:57
@codecov

codecov Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.57%. Comparing base (d1bd954) to head (2caad5f).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1602   +/-   ##
=======================================
  Coverage   91.57%   91.57%           
=======================================
  Files         228      228           
  Lines        7285     7285           
=======================================
  Hits         6671     6671           
  Misses        614      614           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@zimeg zimeg added area:examples issues related to example or sample code semver:patch labels Oct 26, 2026
@zimeg zimeg added this to the next milestone Oct 26, 2026
@zimeg zimeg changed the title [eMudhra 53119][Docker] Move example images to the nearest bases with fixed ca-certificates and gate them chore(examples): move Docker images to bases with fixed ca-certificates Oct 26, 2026
zimeg and others added 2 commits October 26, 2026 16:31
… Debian suites

The version gate hard-coded the bookworm and trixie package versions and failed the build on any other release. A plain refresh still installs the fixed ca-certificates on today's bases.

@mwbrooks mwbrooks left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: Simplified the ca-certificates gate to a plain refresh so the examples don't hard-code Debian suites or fail on the next release.

@mwbrooks
mwbrooks merged commit b915daa into slackapi:main Oct 27, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:examples issues related to example or sample code cla:signed semver:patch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants