Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/build-and-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,34 @@ jobs:
image_name: "jira-issue-fetcher"
# tag: "staging"

build-and-push-redis-commander:
runs-on: ubuntu-latest
steps:
- name: Build and push redis-commander to quay.io registry
uses: sclorg/build-and-push-action@adf1dee2b786ccbb2e2a708c3510a90e2ab3392d # v4.1.5
with:
registry: "quay.io"
registry_namespace: "antbob/jotnar"
registry_username: ${{ secrets.REGISTRY_LOGIN }}
registry_token: ${{ secrets.REGISTRY_TOKEN }}
dockerfile: "Containerfile.redis-commander"
docker_context: "."
image_name: "redis-commander"

build-and-push-phoenix:
runs-on: ubuntu-latest
steps:
- name: Build and push phoenix to quay.io registry
uses: sclorg/build-and-push-action@adf1dee2b786ccbb2e2a708c3510a90e2ab3392d # v4.1.5
with:
registry: "quay.io"
registry_namespace: "antbob/jotnar"
registry_username: ${{ secrets.REGISTRY_LOGIN }}
registry_token: ${{ secrets.REGISTRY_TOKEN }}
dockerfile: "Containerfile.phoenix"
docker_context: "."
image_name: "phoenix"

build-and-push-supervisor:
runs-on: ubuntu-latest
steps:
Expand Down
44 changes: 44 additions & 0 deletions Containerfile.phoenix
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Rebuild Arize Phoenix 11.6.2 with patched dependencies:
# - SQLite >= 3.50.2 (CVE-2025-6965)
# - cryptography >= 46.0.7 (CVE-2026-39892)
#
# The upstream image (arizephoenix/phoenix:version-11.6.2) is based on
# gcr.io/distroless/python3-debian12 which ships SQLite 3.40.1 and
# cryptography 45.0.5. We compile SQLite from source and pip-install
# a fixed cryptography, then overlay both into the final image.

ARG PHOENIX_VERSION=version-11.6.2

# --- Stage 1: build SQLite from source ---
FROM docker.io/library/debian:bookworm-slim AS sqlite-builder

ARG SQLITE_VERSION=3500200
ARG SQLITE_YEAR=2025

RUN apt-get update && \
apt-get install -y --no-install-recommends gcc make wget ca-certificates libc6-dev && \
rm -rf /var/lib/apt/lists/*

RUN wget -q "https://www.sqlite.org/${SQLITE_YEAR}/sqlite-autoconf-${SQLITE_VERSION}.tar.gz" && \
tar xzf "sqlite-autoconf-${SQLITE_VERSION}.tar.gz" && \
cd "sqlite-autoconf-${SQLITE_VERSION}" && \
./configure --prefix=/usr/local && \
make -j"$(nproc)" && \
make install
Comment on lines +25 to +27
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The SQLite build configuration for Phoenix is minimal compared to the one used for redis-commander. To ensure no feature regressions (such as FTS5, RTree, or JSON support) and to optimize performance for observability workloads, it is recommended to align the build flags between the two images, including increasing the SQLITE_MAX_VARIABLE_NUMBER limit.

    CFLAGS="-O2 \
      -DSQLITE_ENABLE_FTS3_PARENTHESIS \
      -DSQLITE_ENABLE_COLUMN_METADATA \
      -DSQLITE_SECURE_DELETE \
      -DSQLITE_ENABLE_UNLOCK_NOTIFY \
      -DSQLITE_ENABLE_RTREE \
      -DSQLITE_ENABLE_GEOPOLY \
      -DSQLITE_USE_URI \
      -DSQLITE_ENABLE_DBSTAT_VTAB \
      -DSQLITE_MAX_VARIABLE_NUMBER=250000" \
    ./configure --prefix=/usr/local \
      --enable-threadsafe \
      --enable-session \
      --enable-fts3 \
      --enable-fts4 \
      --enable-fts5 && \
    make -j"$(nproc)" && \
    make install


# --- Stage 2: build updated cryptography wheel ---
FROM docker.io/library/python:3.11-slim-bookworm AS crypto-builder

RUN pip install --no-cache-dir --target=/tmp/packages "cryptography>=46.0.7"

# --- Stage 3: patch the upstream Phoenix image ---
FROM docker.io/arizephoenix/phoenix:${PHOENIX_VERSION}

# Copy the updated SQLite shared library over the system one.
# The distroless base has libsqlite3.so.0 at /usr/lib/x86_64-linux-gnu/.
COPY --from=sqlite-builder /usr/local/lib/libsqlite3.so.0* /usr/lib/x86_64-linux-gnu/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

security-high high

Hardcoding the path /usr/lib/x86_64-linux-gnu/ breaks multi-arch compatibility. On ARM64 architectures (e.g., Apple Silicon or AWS Graviton), system libraries are located in /usr/lib/aarch64-linux-gnu/. If this image is built for ARM64, the COPY will create a new directory that the system linker does not search, meaning the application will continue to use the old, vulnerable version of SQLite from the base image. This effectively bypasses the security patch on non-x86 platforms.


# Overlay upgraded cryptography package (upstream installs to /phoenix/env/).
COPY --from=crypto-builder /tmp/packages/cryptography/ /phoenix/env/cryptography/

CMD ["-m", "phoenix.server.main", "serve"]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The CMD instruction is redundant and will cause the container to fail on startup. The base image arizephoenix/phoenix already defines an ENTRYPOINT as ["python", "-m", "phoenix.server.main", "serve"]. When a CMD is provided in a child image, it is passed as arguments to the parent's ENTRYPOINT, resulting in an invalid command: python -m phoenix.server.main serve -m phoenix.server.main serve. You should remove this line to correctly inherit the parent's configuration.

55 changes: 55 additions & 0 deletions Containerfile.redis-commander
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Rebuild Redis Commander 0.9.0 with patched dependencies:
# - SQLite >= 3.50.2 (CVE-2025-6965)
# - Node.js >= 22.22.0 (CVE-2025-55130)
# - OpenSSL >= 3.3.7 (CVE-2026-31789)
#
# The upstream image (ghcr.io/joeferner/redis-commander:0.9.0) is based on
# Alpine 3.21 which ships SQLite 3.48.0.
# We compile SQLite from source and overlay the shared library.
# We also run apk upgrade to pull in patched Node.js and OpenSSL.

ARG REDIS_COMMANDER_VERSION=0.9.0

# --- Stage 1: build SQLite from source ---
FROM docker.io/library/alpine:3.21 AS sqlite-builder

ARG SQLITE_VERSION=3500200
ARG SQLITE_YEAR=2025

RUN apk add --no-cache gcc make musl-dev wget

RUN wget -q "https://www.sqlite.org/${SQLITE_YEAR}/sqlite-autoconf-${SQLITE_VERSION}.tar.gz" && \
tar xzf "sqlite-autoconf-${SQLITE_VERSION}.tar.gz" && \
cd "sqlite-autoconf-${SQLITE_VERSION}" && \
CFLAGS="-O2 \
-DSQLITE_ENABLE_FTS3_PARENTHESIS \
-DSQLITE_ENABLE_COLUMN_METADATA \
-DSQLITE_SECURE_DELETE \
-DSQLITE_ENABLE_UNLOCK_NOTIFY \
-DSQLITE_ENABLE_RTREE \
-DSQLITE_ENABLE_GEOPOLY \
-DSQLITE_USE_URI \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_MAX_VARIABLE_NUMBER=250000" \
./configure --prefix=/usr/local \
--enable-threadsafe \
--enable-session \
--enable-fts3 \
--enable-fts4 \
--enable-fts5 && \
make -j"$(nproc)" && \
make install

# --- Stage 2: patch the upstream Redis Commander image ---
FROM ghcr.io/joeferner/redis-commander:${REDIS_COMMANDER_VERSION}

# Upgrade system packages to pick up patched Node.js and OpenSSL.
USER root
RUN apk upgrade --no-cache
USER 10000

# Copy the updated SQLite shared library over the system one.
# Alpine keeps libsqlite3 at /usr/lib/.
COPY --from=sqlite-builder /usr/local/lib/libsqlite3.so.0* /usr/lib/

CMD ["/redis-commander/docker/entrypoint.sh"]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

This CMD instruction is redundant and likely breaks the application. The upstream image uses an ENTRYPOINT that executes /redis-commander/docker/entrypoint.sh. By redefining CMD with the same path, the script path is passed as an argument to itself. The entrypoint script typically passes all arguments to the Node.js process, which will then fail to parse the script path as a valid configuration or host. Remove this line to use the inherited configuration.

14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,24 @@ COMPOSE ?= $(shell if podman compose ls >/dev/null 2>&1; then echo "podman compo
COMPOSE_AGENTS=$(COMPOSE) -f $(COMPOSE_FILE) --profile=agents
COMPOSE_SUPERVISOR=$(COMPOSE) -f $(COMPOSE_FILE) --profile=supervisor

# Extract container tool (podman or docker) from COMPOSE
CONTAINER_TOOL ?= $(shell command -v podman >/dev/null 2>&1 && echo "podman" || echo "docker")
REGISTRY ?= quay.io/antbob/jotnar

.PHONY: build
build:
$(COMPOSE) -f $(COMPOSE_FILE) --profile=agents --profile=supervisor build

.PHONY: push
push:
@echo "Pushing images to $(REGISTRY)..."
$(CONTAINER_TOOL) push $(REGISTRY)/phoenix:latest
$(CONTAINER_TOOL) push $(REGISTRY)/redis-commander:latest
Comment on lines +25 to +26
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The push target only pushes the latest tag. In production environments like OpenShift, relying solely on latest can lead to non-deterministic deployments and makes rollbacks difficult. It is recommended to also tag and push images with specific version numbers or build identifiers to ensure traceability.

@echo "All images pushed successfully!"

.PHONY: build-and-push
build-and-push: build push

.PHONY: run-beeai-bash
run-beeai-bash:
$(COMPOSE_AGENTS) run --rm triage-agent /bin/bash
Expand Down
10 changes: 8 additions & 2 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,10 @@ services:
profiles: ["agents", "supervisor", "e2e-test"]

phoenix:
image: docker.io/arizephoenix/phoenix:version-11.6.2
image: quay.io/antbob/jotnar/phoenix:latest
build:
context: .
dockerfile: Containerfile.phoenix
ports:
- "0.0.0.0:6006:6006"
environment:
Expand All @@ -124,7 +127,10 @@ services:
profiles: ["agents", "supervisor", "e2e-test"]

redis-commander:
image: ghcr.io/joeferner/redis-commander:0.9.0
image: quay.io/antbob/jotnar/redis-commander:latest
build:
context: .
dockerfile: Containerfile.redis-commander
environment:
- REDIS_HOSTS=local:valkey:6379
ports:
Expand Down
13 changes: 12 additions & 1 deletion openshift/deployment-phoenix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: phoenix
annotations:
image.openshift.io/triggers: |
[
{
"from": {
"kind": "ImageStreamTag",
"name": "phoenix:prod"
},
"fieldPath": "spec.template.spec.containers[?(@.name==\"phoenix\")].image"
}
]
spec:
progressDeadlineSeconds: 600
replicas: 1
Expand All @@ -27,7 +38,7 @@ spec:
- name: PHOENIX_PORT
value: "6006"
image: phoenix:prod
imagePullPolicy: IfNotPresent
imagePullPolicy: Always
name: phoenix
ports:
- containerPort: 4317
Expand Down
13 changes: 12 additions & 1 deletion openshift/deployment-redis-commander.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-commander
annotations:
image.openshift.io/triggers: |
[
{
"from": {
"kind": "ImageStreamTag",
"name": "redis-commander:prod"
},
"fieldPath": "spec.template.spec.containers[?(@.name==\"redis-commander\")].image"
}
]
spec:
progressDeadlineSeconds: 600
replicas: 1
Expand All @@ -25,7 +36,7 @@ spec:
- name: REDIS_HOSTS
value: local:valkey:6379
image: redis-commander:prod
imagePullPolicy: IfNotPresent
imagePullPolicy: Always
name: redis-commander
ports:
- containerPort: 8081
Expand Down
2 changes: 1 addition & 1 deletion openshift/imagestream-redis-commander.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ spec:
- name: prod
from:
kind: DockerImage
name: ghcr.io/joeferner/redis-commander:0.9.0
name: quay.io/antbob/jotnar/redis-commander:latest
importPolicy:
# Periodically query registry to synchronize tag and image metadata.
scheduled: true
Expand Down
Loading