Skip to content

Repository files navigation

mirror-operator

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.

Architecture Overview

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
Loading

How It Works

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.

Custom Resources

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)

Managed Components

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.

Quick Start

Prerequisites

  • OpenShift 4.14+ cluster with cluster-admin access
  • oc CLI installed and authenticated
  • OLM (Operator Lifecycle Manager) available on the cluster

Install via OLM (Recommended)

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
EOF

Then install from the OpenShift console:

  1. Navigate to Operators > OperatorHub
  2. Search for Mirror Operator
  3. 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
EOF

For 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 from Source (Development)

# Install CRDs
make install

# Deploy the operator
make deploy IMG=<your-registry>/mirror-operator:latest

Create a Connected Platform

# 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

Trigger a Collection

# Create a CollectionPipeline with your ImageSetConfiguration
oc apply -f config/samples/mirror_v1_collectionpipeline.yaml

# Monitor the pipeline
oc get collectionpipeline -o wide

Import on the Airgapped Side

# On the airgapped cluster, create a MirrorImport
oc apply -f config/samples/mirror_v1_mirrorimport.yaml

# Watch the import progress
oc get mirrorimport -o wide

Documentation

See the Documentation Index for all available guides, including:

Development

Building from Source

make docker-build docker-push IMG=<your-registry>/mirror-operator:tag

Running Locally

# Run the operator against your current kubeconfig context
make run

Key Makefile Targets

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.

Contributing

Contributions are welcome. Please review existing issues before submitting a PR.

License

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.

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages