A Kubernetes operator that automates the full lifecycle of disconnected (airgapped) OpenShift environments. It handles content collection from internet sources, supply chain signing via Red Hat Trusted Artifact Signer, physical transfer packaging, and import into airgapped registries -- replacing manual oc-mirror workflows with declarative, Kubernetes-native automation.
This operator is an implementation of the OCP Disconnected Pipeline reference architecture and consumes ImageSetConfiguration YAML generated by Airgap Architect.
graph TD
subgraph connected["Connected Environment"]
DP["DisconnectedPlatform CR<br/><i>Root orchestrator</i>"]
subgraph operators["Managed Operators"]
Tekton[Tekton Pipelines]
RHBK[Keycloak]
RHTAS["RHTAS<br/>(Fulcio, Rekor, TUF)"]
RHTPA["RHTPA<br/>(Trustify)"]
QuayOp[Quay Registry]
end
DP --> operators
DP --> Architect[Airgap Architect UI]
CP["CollectionPipeline CR"] --> PipelineRun[Tekton PipelineRun]
PipelineRun --> |"oc-mirror + sign + package"| Bundle["Signed Bundle<br/>(tar + signature + SBOM)"]
DP -. "pushes signing config" .-> CP
end
Bundle --> |"Physical media transfer"| Import
subgraph airgapped["Airgapped Environment"]
MI["MirrorImport CR"] --> Import[Import Job]
Import --> |"verify + oc-mirror import"| Registry[Airgapped Registry]
MI --> CatalogSource[CatalogSource]
MI --> IDMS[ImageDigestMirrorSet]
end
style DP fill:#326CE5,color:#fff
style CP fill:#4A90D9,color:#fff
style MI fill:#4A90D9,color:#fff
style connected fill:#f0f7ff,stroke:#326CE5
style airgapped fill:#fff5f5,stroke:#DC3545
Connected side -- Collection. A DisconnectedPlatform CR (mode: connected) installs the required operator ecosystem (Tekton, Keycloak, RHTAS, Quay) and deploys the Airgap Architect web UI. When a CollectionPipeline CR is created, the operator launches a Tekton PipelineRun that mirrors images from upstream registries using oc-mirror, signs them with Fulcio keyless certificates via RHTAS, generates an SBOM with Syft, and packages everything into a signed tar bundle uploaded to S3 storage.
Physical transfer. The bundle (tar archive, cosign signature, SBOM, and attestation document) is downloaded from the connected environment and transferred to the airgapped environment via physical media -- USB drive, DVD, or approved data transfer mechanism.
Airgapped side -- Import. A MirrorImport CR triggers an import Job that verifies the cosign signature and attestation hashes, then runs oc-mirror to import the bundle into the local registry. The operator can automatically create an OLM CatalogSource and ImageDigestMirrorSet so the cluster immediately sees the mirrored content.
Status aggregation. The DisconnectedPlatform controller aggregates collection and import history from all child resources, providing a centralized view of the entire mirror lifecycle.
| CRD | Scope | Description |
|---|---|---|
| DisconnectedPlatform | Cluster | Root orchestrator -- installs operators, deploys UI, manages signing infrastructure, aggregates history |
| CollectionPipeline | Namespace | Triggers Tekton pipelines to collect, sign, and package images from internet sources |
| MirrorImport | Namespace | Imports and verifies bundles into airgapped registries, publishes CatalogSource and IDMS |
| ClusterBootstrap | Namespace | Provisions new OpenShift clusters from mirrored content (planned) |
On the connected side, the operator installs and configures the following via OLM:
| Component | Purpose |
|---|---|
| Tekton Pipelines | Executes collection pipeline tasks (oc-mirror, signing, packaging) |
| Red Hat Build of Keycloak | Provides OIDC identity for Fulcio keyless signing |
| RHTAS (Fulcio, Rekor, CTLog, TUF) | Private Sigstore deployment for supply chain signing and verification |
| RHTPA (Trustify) | SBOM storage and vulnerability analysis |
| Quay | Intermediate registry for the three-phase signing workflow |
Each operator can be individually disabled or customized. See the Architecture Guide for details on how these components interact.
- OpenShift 4.14+ cluster with cluster-admin access
ocCLI installed and authenticated- OLM (Operator Lifecycle Manager) available on the cluster
Create a CatalogSource to make the operator available in the OpenShift OperatorHub:
oc apply -f - <<EOF
apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
name: mirror-operator-catalog
namespace: openshift-marketplace
spec:
sourceType: grpc
image: quay.io/mathianasj/mirror-operator-catalog:v0.0.1
displayName: Mirror Operator
publisher: mathianasj
updateStrategy:
registryPoll:
interval: 10m
EOFThen install from the OpenShift console:
- Navigate to Operators > OperatorHub
- Search for Mirror Operator
- Click Install and follow the prompts
Or install via CLI:
oc apply -f - <<EOF
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: mirror-operator
namespace: mirror-operator-system
spec:
channel: alpha
name: mirror-operator
source: mirror-operator-catalog
sourceNamespace: openshift-marketplace
installPlanApproval: Automatic
EOFFor airgapped clusters, mirror the catalog image to your local registry first:
oc image mirror quay.io/mathianasj/mirror-operator-catalog:v0.0.1 \
<your-registry>/mirror-operator-catalog:v0.0.1
oc apply -f - <<EOF
apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
name: mirror-operator-catalog
namespace: openshift-marketplace
spec:
sourceType: grpc
image: <your-registry>/mirror-operator-catalog:v0.0.1
displayName: Mirror Operator
publisher: mathianasj
updateStrategy:
registryPoll:
interval: 10m
EOF# Install CRDs
make install
# Deploy the operator
make deploy IMG=<your-registry>/mirror-operator:latest# Apply a connected-mode DisconnectedPlatform
oc apply -f config/samples/mirror_v1_disconnectedplatform_connected.yaml
# Watch the operator install prerequisites
oc get disconnectedplatform -o yaml# Create a CollectionPipeline with your ImageSetConfiguration
oc apply -f config/samples/mirror_v1_collectionpipeline.yaml
# Monitor the pipeline
oc get collectionpipeline -o wide# On the airgapped cluster, create a MirrorImport
oc apply -f config/samples/mirror_v1_mirrorimport.yaml
# Watch the import progress
oc get mirrorimport -o wideSee the Documentation Index for all available guides, including:
- Architecture Guide -- Detailed diagrams and component interactions
- CRD Reference -- Complete API field reference
- Integration Guide -- Programmatic integration examples
- RHTAS Integration -- Supply chain security setup
make docker-build docker-push IMG=<your-registry>/mirror-operator:tag# Run the operator against your current kubeconfig context
make run| Target | Description |
|---|---|
make manifests |
Generate CRD and RBAC YAML from Go types |
make generate |
Generate deepcopy code |
make install |
Install CRDs into the cluster |
make run |
Run the controller locally |
make test |
Run unit tests |
make deploy |
Deploy the operator to the cluster |
Run make help for the full list of targets.
Contributions are welcome. Please review existing issues before submitting a PR.
Copyright 2026.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.