Skip to main content

🔄 openshift-update-proxy

CI Release PyPI License

A small Flask based service which forwards HTTP requests to api.openshift.com, mirror.openshift.com, catalog.redhat.com and access.redhat.com. Built for restricted networks where OpenShift clusters have no direct internet access, but a central egress proxy (or a single host with internet access) exists.

Features

  • 🔀 Update Graph Proxy - forwards Cincinnati update graph requests (/api/upgrades_info/v1/graph) to api.openshift.com
  • 📦 Mirror Proxy - forwards requests for clients and release artifacts to mirror.openshift.com/pub
  • 🔏 Signature Store - forwards release image signature requests to the public signature store on mirror.openshift.com
  • 🗺️ ConfigMap Generator - renders ready-to-apply signature ConfigMaps for the classic disconnected verification workflow
  • 🎛️ Operator Catalog API - serves operator channels and versions from the Red Hat Pyxis API (catalog.redhat.com), ready to use as a Renovate custom datasource
  • 📅 Supported Versions API - combines the Red Hat product lifecycle API with the update graph to list supported OpenShift minor versions and their latest release
  • 🚦 Egress Proxy Aware - honors HTTPS_PROXY / NO_PROXY for all upstream requests
  • 🐳 Hardened Container - UBI9 based, rootless (UID 1001), digest-pinned base image, Cosign signed
  • ⛵ Helm Chart - deploy to Kubernetes/OpenShift with probes and sane security defaults
  • 🩺 Health Endpoint - /healthz for liveness and readiness probes
  • 🪵 Request Logging - logs source, method, path and status for every request (health probes excluded)

How it works

flowchart LR
    subgraph restricted["Restricted network"]
        CVO["Cluster Version Operator"]
        ADMIN["Admin (oc / curl)"]
        RENOVATE["Renovate"]
        PROXY["openshift-update-proxy"]
    end

    subgraph internet["Internet"]
        API["api.openshift.com"]
        MIRROR["mirror.openshift.com"]
        PYXIS["catalog.redhat.com"]
        LIFECYCLE["access.redhat.com"]
    end

    CVO -- "/api/upgrades_info/v1/graph" --> PROXY
    CVO -- "/signatures/sha256=…" --> PROXY
    ADMIN -- "/configmaps/sha256=…" --> PROXY
    ADMIN -- "/pub/…" --> PROXY
    RENOVATE -- "/operators/v1/…" --> PROXY

    PROXY -- "optional egress proxy (HTTPS_PROXY)" --> EGRESS["Egress Proxy"]
    EGRESS --> API
    EGRESS --> MIRROR
    EGRESS --> PYXIS
    EGRESS --> LIFECYCLE

Endpoints

Endpoint Upstream Purpose
/api/<path> https://api.openshift.com/api/ Cincinnati update graph (/api/upgrades_info/v1/graph)
/pub/<path> https://mirror.openshift.com/pub/ OpenShift mirror (clients, release artifacts)
/signatures/<path> https://mirror.openshift.com/pub/openshift-v4/signatures/openshift/release/ Release image signature store
/configmaps/<version or sha256=digest> derived from signature store Ready-to-apply signature ConfigMap (YAML)
/catalog/<path> https://catalog.redhat.com/api/containers/v1/ Red Hat Pyxis API (operator catalog metadata)
/operators/v1/<catalog>/<package>/channels derived from Pyxis Channels, default channel and latest CSV per channel
/operators/v1/<catalog>/<package>/<channel>/releases derived from Pyxis Version feed in Renovate custom datasource format
/lifecycle/<path> https://access.redhat.com/product-life-cycles/api/v1/ Red Hat product lifecycle API
/versions/v1/supported derived from lifecycle API + update graph Supported OpenShift minors with latest release per channel
/healthz - Health check for liveness/readiness probes

Configuration

All configuration is done via environment variables:

Variable Default Description
HTTPS_PROXY - Egress proxy for upstream requests (standard requests behaviour, NO_PROXY is honored)
INSECURE_SKIP_TLS_VERIFY false Skip TLS certificate verification for upstream requests (true/1/yes)
API_UPSTREAM https://api.openshift.com/api/ Cincinnati API base URL
MIRROR_UPSTREAM https://mirror.openshift.com/pub/ Mirror base URL
SIGNATURE_UPSTREAM https://mirror.openshift.com/pub/openshift-v4/signatures/openshift/release/ Signature store base URL
CATALOG_UPSTREAM https://catalog.redhat.com/api/containers/v1/ Red Hat Pyxis API base URL
CATALOG_CACHE_TTL 600 Cache TTL in seconds for operator catalog lookups (0 disables caching)
LIFECYCLE_UPSTREAM https://access.redhat.com/product-life-cycles/api/v1/ Red Hat product lifecycle API base URL
LIFECYCLE_CACHE_TTL 3600 Cache TTL in seconds for lifecycle and latest-release lookups (0 disables caching)
REQUEST_TIMEOUT 30 Upstream request timeout in seconds
LISTEN_HOST 0.0.0.0 Listen address
LISTEN_PORT 5000 Listen port

Quick Start

Container

docker run --rm -p 5000:5000 \
  -e HTTPS_PROXY=http://proxy.example.com:3128 \
  ghcr.io/slauger/openshift-update-proxy:latest

The image is based on registry.access.redhat.com/ubi9/python-314, runs as UID 1001 and is built from the Containerfile in this repository.

Helm

The chart is published as an OCI artifact to ghcr.io on every release:

helm install update-proxy oci://ghcr.io/slauger/charts/openshift-update-proxy \
  --set env[0].name=HTTPS_PROXY,env[0].value=http://proxy.example.com:3128

Or from a git checkout: helm install update-proxy ./chart

PyPI

python3 -m venv .venv && source .venv/bin/activate
pip install openshift-update-proxy
openshift-update-proxy

For running as a service on a plain Linux host, see the systemd unit example in examples/update-proxy.service.

Cluster integration

Update graph

Point the ClusterVersion upstream at the proxy:

apiVersion: config.openshift.io/v1
kind: ClusterVersion
metadata:
  name: version
spec:
  upstream: http://update-proxy.example.com:5000/api/upgrades_info/v1/graph

Release signatures

For updates by digest (oc adm upgrade --to-image ...@sha256:...) the CVO must verify the release image signature.

The /configmaps/ endpoint fetches all signatures for a release and renders a ready-to-apply ConfigMap (same format as oc adm release mirror / oc-mirror produces). It accepts a release version directly - the digest is resolved via the update graph:

curl -s "http://update-proxy.example.com:5000/configmaps/4.16.8" | oc apply -f -

The optional arch (default amd64) and channel_prefix (default stable) query parameters select the architecture and the update channel used for the lookup, e.g. /configmaps/4.16.8?arch=arm64. Version lookups name the ConfigMap release-signature-<version>-<arch> - the signed digest differs per architecture, so the name has to carry it. Digest lookups use signature-sha256-<digest prefix> (first 16 characters) as neither version nor architecture are known there.

Alternatively, a release digest can be passed directly:

DIGEST=$(oc adm release info quay.io/openshift-release-dev/ocp-release:4.16.8-x86_64 -o jsonpath='{.digest}')
curl -s "http://update-proxy.example.com:5000/configmaps/${DIGEST/:/=}" | oc apply -f -

The ConfigMap is created in openshift-config-managed with the release.openshift.io/verification-signatures label, where the CVO picks it up.

Note: The ClusterVersion API also has a spec.signatureStores field, but it is gated behind the TechPreview-only SignatureStores feature gate and will not be promoted to GA (OTA-1118). The ConfigMap above is the supported way to provide signatures.

Operator catalog and Renovate

The /operators/v1/ endpoints answer "which operator versions exist in which channel?" without pulling the multi-hundred-MB catalog index images and without any registry credentials. The data comes from the public Red Hat Pyxis API and covers all four default catalogs: redhat-operators, certified-operators, community-operators and redhat-marketplace.

List channels, default channel and the latest CSV per channel:

curl -s "http://update-proxy.example.com:5000/operators/v1/redhat-operators/openshift-gitops-operator/channels?ocp_version=4.16"
{
  "package": "openshift-gitops-operator",
  "organization": "redhat-operators",
  "default_channel": "latest",
  "channels": [
    {"name": "gitops-1.21", "latest_version": "1.21.4", "latest_csv": "openshift-gitops-operator.v1.21.4"}
  ]
}

List all versions of a channel in the format Renovate expects from a custom datasource:

curl -s "http://update-proxy.example.com:5000/operators/v1/redhat-operators/openshift-gitops-operator/gitops-1.21/releases?ocp_version=4.16"
{
  "releases": [
    {"version": "1.21.3", "releaseTimestamp": "2026-08-14T23:45:28.177000+00:00"},
    {"version": "1.21.4", "releaseTimestamp": "2026-09-03T12:13:37.391000+00:00"}
  ]
}

The optional ocp_version query parameter limits results to bundles shipped in the catalog for that OpenShift minor version. Responses are cached in memory for CATALOG_CACHE_TTL seconds. The raw Pyxis API is available under /catalog/, e.g. /catalog/operators/indices?filter=organization==redhat-operators lists all index image tags with their end-of-life dates.

With this feed, Renovate can bump pinned operator versions (startingCSV in OLM Subscription manifests, whether managed directly via Argo CD or embedded in ACM policies) just like any other dependency - merging the PR rolls out the operator update. See examples/renovate/ for a complete working setup: a renovate.json with the custom datasource and regex manager, plus matching Subscription and ACM Policy manifests.

Supported OpenShift versions

/versions/v1/supported combines the Red Hat product lifecycle API with the Cincinnati update graph: all OpenShift minor versions that are not end-of-life, together with the latest release in the corresponding update channel.

curl -s "http://update-proxy.example.com:5000/versions/v1/supported"
{
  "product": "OpenShift Container Platform",
  "architecture": "amd64",
  "versions": [
    {"version": "4.22", "support_phase": "Full Support", "channel": "stable-4.22", "latest_release": "4.22.11"},
    {"version": "4.20", "support_phase": "Maintenance Support", "channel": "stable-4.20", "latest_release": "4.20.35"}
  ]
}

The optional channel_prefix (default stable, e.g. eus, fast, candidate) and arch (default amd64) query parameters select the channel and architecture; latest_release is null when the channel has no published releases yet. The raw lifecycle API is available under /lifecycle/, e.g. /lifecycle/products?name=OpenShift Container Platform.

examples/create-configmaps/ combines this with the /configmaps/ endpoint: it fetches the release signatures for a set of update channels through the proxy and writes one manifest per release (manifests/release-signature-<version>-<arch>.yaml), ready to be committed to a GitOps repository. The directory also contains a scheduled GitHub Actions workflow that keeps the manifests up to date.

Local Development

python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
openshift-update-proxy

Run tests and linting:

make test
make lint

Build the container image:

make build

Supply Chain Security

  • The UBI9 base image is pinned by digest and kept up to date by Renovate; remaining CVEs are patched at build time via dnf upgrade.
  • Python and GitHub Actions dependencies are also managed by Renovate (with automerge for non-major updates).
  • Releases are fully automated with python-semantic-release based on Conventional Commits and published to PyPI.
  • Container images are signed with Cosign (keyless, GitHub Actions OIDC). Verify with:
cosign verify \
  --certificate-identity-regexp 'https://github.com/slauger/openshift-update-proxy/.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  ghcr.io/slauger/openshift-update-proxy:latest

License

Apache License 2.0

Metadata

Release files for openshift-update-proxy 1.4.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for openshift-update-proxy 1.4.7
File Size Uploaded
openshift_update_proxy-1.4.7.tar.gz 25.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for openshift-update-proxy 1.4.7
File Interpreter ABI Platform
openshift_update_proxy-1.4.7-py3-none-any.whl Python 3 none any Details

Total release size: 45.3 kB

Release files / openshift_update_proxy-1.4.7.tar.gz

Download URL openshift_update_proxy-1.4.7.tar.gz
Size 25.7 kB
Tags Source
SHA-256 checksum
How to use checksums
4a336e54dd2db22f1cbe87517de1e8672db5093088886b0b6f5072cc5ecf94bc
BLAKE2b-256 checksum
How to use checksums
68e49fca012545537a7680f3cf8d6571dad0e788832816a2483623411dc1ffdf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / openshift_update_proxy-1.4.7-py3-none-any.whl

Download URL openshift_update_proxy-1.4.7-py3-none-any.whl
Size 19.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
45187717dc0f9422fee76ce500ef73f5db941f082c6aebd0ebb029df19a09c87
BLAKE2b-256 checksum
How to use checksums
f1c0a60c3407668c70349559157ee2c0e7c434afe30e6bc5f1ebe7063b645369
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.4.7 This release

2 release files

1.4.6

2 release files

1.4.5

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page