Skip to content

About

ExploitIQ Operator File-Based Catalog (FBC)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

ExploitIQ Operator FBC

File-Based Catalog (FBC) for the ExploitIQ Operator.

Structure

v4.19/                          # OCP version directory
├── catalog.Dockerfile          # FBC image build
├── graph.yaml                  # OLM template (channels, bundles)
├── licenses/license.txt        # Apache 2.0
└── catalog/exploit-iq-operator/
    └── catalog.json            # Rendered FBC (generated — do not edit)

Requirements

Use Python 3.10 or newer and install the YAML dependency in a virtual environment:

python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt

Automatic sources also need:

  • Authenticated gh for GitHub PR metadata and immutable source files.
  • oc with access to the Konflux tenant.
  • skopeo and access to the selected build/source image. Direct destination credentials are needed only for explicit destination checks or a released source.
  • opm when using --render. Set OPM_CMD to a binary path if it is not on PATH. Unchanged bundle metadata is reused from existing catalogs; uncached images require normal registry access.

Check cluster access without changing your current context:

oc --kubeconfig ./kubeconfig whoami

Pass --kubeconfig and, if needed, --context to the script. The same settings are used for cluster queries, archive authentication, and image extraction. The script does not log in, change contexts, publish images, merge PRs, or start releases.

Archived PipelineRuns, Snapshots, and Releases are retrieved from KubeArchive after a genuine live NotFound. The archive URL comes from the cluster's product-kubearchive/kubearchive-api-url ConfigMap. No archive plugin is required. Permission, authentication, network, and TLS failures stop the operation.

Updating the bundle

Choose exactly one source: --pr, --snapshot, --release, or --new-sha. Start with --dry-run; it resolves and validates the source and prints proposed diffs without writing files. Add --render to prepare and validate catalogs from the verified build image, including before stage/prod publication.

PR input: merged bundle-only nudge

Pass the final bundle nudge PR, such as #291, rather than the original operator PR, such as #293.

The PR must:

  • Be merged into the configured operator repository.
  • Have the expected Konflux operator-to-bundle nudge metadata.
  • Change only operator image-digest pins in the bundle CSV. Version, image repository, RBAC, and other fields must remain unchanged.
  • Have a supported bundle-only push trigger configuration at the merge commit.
  • Produce a successful bundle push build for that exact commit.

The script verifies the build results, its linked Snapshot, and the actual image contents. It never searches for a different nudge PR. Different successful rerun digests require an explicit Snapshot selection.

Adding a new operator version

The operator's version-update PR sets the new CSV version first. Its subsequent bundle nudge PR updates the operator digest. Use that merged nudge PR to add the version to the FBC.

.venv/bin/python update-fbc.py \
  --pr 291 \
  --new-version 3.2.0 \
  --prod \
  --channel stable-v3 \
  --kubeconfig ./kubeconfig \
  --render \
  --dry-run

Omit --update-existing when adding a version. The script reads the actual bundle CSV name and version; --new-version is an optional assertion for automatic sources. A mismatch fails.

Each selected graph receives one new bundle reference and one entry in the selected channel, replacing that channel's head. Other channels, old bundles, the package default, and deprecations are preserved. If the version already exists, the script stops and asks for --update-existing.

Updating an existing version

Use --update-existing when the resolved version already exists in every selected graph:

.venv/bin/python update-fbc.py \
  --pr 291 \
  --prod \
  --update-existing \
  --kubeconfig ./kubeconfig \
  --render \
  --dry-run

Only that version's image is replaced. Its channel entries and upgrade edges remain unchanged. The image-to-CSV association comes from exact rendered catalog metadata or image inspection, never bundle ordering.

Explicit Snapshot input

.venv/bin/python update-fbc.py \
  --snapshot exploit-intelligence-operator-3-2-0-20261026-044456-000 \
  --prod \
  --channel stable-v3 \
  --kubeconfig ./kubeconfig \
  --render \
  --dry-run

The selected bundle component must point to an eligible merged nudge PR and its successful push PipelineRun. The script verifies the bundle component's own source revision and image; sibling components may legitimately have different revisions. An original operator PR's stale bundle Snapshot does not bypass PR eligibility.

Use --bundle-component NAME if the Snapshot contains multiple bundle components. Explicit Snapshot selection pins a rerun without choosing the latest artifact.

Release input

The existing Release source remains available:

.venv/bin/python update-fbc.py \
  --release RELEASE_NAME \
  --prod \
  --channel stable-v3 \
  --kubeconfig ./kubeconfig \
  --dry-run

The Release must have completed successfully and contain an operator bundle artifact. An operator-only Release is rejected. Use --bundle-component NAME to select among multiple bundle artifacts. The version comes from the actual bundle CSV rather than its component name.

Add --update-existing for a re-release of a version already in the graphs.

Logical references, IDMS, and publication checks

--stage (the default) and --prod choose the logical bundle repository written into the FBC. They do not require that repository to contain the digest yet. PR and Snapshot sources still verify the actual Quay bundle, its provenance, CSV version, and operator pins.

This supports building the FBC before releasing the bundle. At installation time, your IDMS must cover any logical bundle, operator, or operand repositories whose images are not directly available, using mirrors containing the exact referenced digests. The script does not create, apply, or validate IDMS, and it leaves the CSV's operator and operand references unchanged.

For pre-release installation, use .tekton/images-mirror-set.yaml. It maps the 3.2.0 bundle, operator, and operands to their Quay build repositories while retaining legacy mirrors. This is a cluster-wide policy: apply it to the installation cluster using that cluster's kubeconfig, not the Konflux lookup kubeconfig. The installation cluster's global pull secret must allow access to both Quay tenants. Wait for node registry configuration updates before installing.

For direct access after publication, opt into the stricter checks:

.venv/bin/python update-fbc.py --pr 291 --prod \
  --kubeconfig ./kubeconfig --verify-destination --dry-run

--verify-destination checks the exact destination bundle and its CSV, plus the operator manifest in the selected Red Hat registry (or its declared location for other registries). Missing images fail before any writes. A Release source always inspects its selected released bundle to determine its actual metadata.

IDMS preserves digest identity; it cannot substitute different image contents under the same digest. If promotion changes the digest, retain a mirror with the original digest or update the FBC from the corresponding --release. None of these checks replace release approval, signing, or Enterprise Contract policies.

Rendering before publication

Use --render with the PR or Snapshot update. The renderer:

  • Fetches the selected bundle's metadata from its verified, digest-pinned build image.
  • Writes the chosen logical reference into the bundle's image and its bundle-self relatedImages entry. Other operator and operand references remain unchanged.
  • Reuses existing catalog metadata only for unchanged image identities. Uncached older bundles are rendered from their declared references.
  • Validates every resulting catalog with opm validate before applying any graph or catalog writes.

--render --dry-run prints both graph and catalog diffs without creating output directories or lock files in the repository. Remove --dry-run to apply the validated plans together. The updated catalogs can then be used for the normal FBC image build.

Cluster IDMS does not automatically configure local opm pulls. For independently rendering existing graphs, generate-fbc.sh now uses the same metadata renderer: it reuses exact-image catalog metadata and reads the repository's IDMS file as local mirror mappings for uncached bundles. This does not apply or inspect cluster policy. Use generate-fbc.sh --validate-all to validate existing catalogs without pulling images.

Manual SHA override

Replace DIGEST with a complete 64-character lowercase hexadecimal digest:

.venv/bin/python update-fbc.py \
  --new-sha "sha256:DIGEST" \
  --new-version 3.2.0 \
  --prod \
  --channel stable-v3 \
  --dry-run

Manual mode requires --new-version and skips nudge provenance checks. Without optional verification or rendering, it remains usable offline. --verify-destination also works in manual mode and checks the actual version and image availability. Manual --render needs metadata from the declared image or an existing catalog; it cannot infer a Quay source from a raw digest. Prefer PR or Snapshot input for pre-release rendering. The targeted graph-editing and write-safety checks still apply. Add --update-existing when replacing an existing version.

The separate replace.sh helper remains an unvalidated bulk SHA replacement tool; it does not provide these version-specific checks.

Graph selection and write safety

  • EI 3.2.0 supports OCP 4.19 through 5.0 only. The OCP 4.18 catalog retains EI 3.1.1 and older bundles.
  • --ocp v4.20 selects one OCP graph. For EI 3.2.0, the updater selects only existing graphs within OCP 4.19 through 5.0 and rejects an explicit selection outside that range. Other EI versions continue to select all existing OCP graphs by default.
  • --channel NAME chooses the channel for a new version. Without it, each graph's existing defaultChannel is used. Updating an existing image leaves channels unchanged.
  • All selected graphs are planned before any writes. Missing versions, version downgrades within the selected channel, ambiguous image mappings, cycles, multiple heads, and unsupported skipRange head selection fail rather than guess.
  • With --render, all graph and catalog plans are validated before any writes. New catalog files and directories can be created; owned new outputs are removed if a later write fails.
  • Successful writes use per-file atomic replacement and rollback on later write failures. Existing output contents are checked before replacement.
  • .graph.yaml.update-fbc.lock and .catalog.json.update-fbc.lock files coordinate concurrent instances of this script. External editors do not honor these locks, so avoid editing graphs during an update. After an interrupted run, check the recorded PID has exited before removing a stale lock.
  • If an external edit prevents rollback, the original content is retained in a reported recovery file.

After reviewing a successful dry run, repeat the command without --dry-run. With --render, the catalogs are already rendered and validated. Otherwise, render the existing graphs with generate-fbc.sh, using cached metadata, configured mirrors, or direct registry access.

Tests

The offline suite uses real validation and graph-editing functions with mocked external services. It does not need registry or cluster access:

PYTHONDONTWRITEBYTECODE=1 .venv/bin/python -m unittest discover -s tests -v

pyrightconfig.json points development type checking at the local .venv.

Rendering and validating catalogs

generate-fbc.sh resolves paths relative to its own repository and shares the metadata renderer with update-fbc.py. Existing metadata is reused only for exact digest-pinned image identities. Uncached bundles are rendered from the local mirror mappings in .tekton/images-mirror-set.yaml, with the logical origin as fallback unless NeverContactSource is set. Catalog bundle references and bundle-self references stay logical; operator and operand references remain unchanged.

Rendering plans and validates every selected catalog before any writes, then uses atomic replacements with rollback and concurrent-change guards. A failed pull or validation leaves existing catalogs intact. Graph files are never changed. Render-only mode trusts the digest-pinned graphs; use the PR/Snapshot update workflow to establish provenance when changing those graphs.

./generate-fbc.sh --render v4.19 --dry-run  # plan + validate without writes
./generate-fbc.sh --render v4.19            # render + validate one OCP version
./generate-fbc.sh --render-all              # validate all plans before writing
./generate-fbc.sh --validate v4.19          # validate existing catalog only
./generate-fbc.sh --validate-all

Use --mirror-set PATH to select another local IDMS file or --no-mirrors to disable mappings. Literal registry, namespace, and repository prefixes use the longest matching boundary; unmatched suffixes and digests are preserved. Wildcard sources and duplicate source entries are rejected rather than guessed. Only the selected local file is read; policies installed on a cluster are not queried or changed.

Install the Python dependency from requirements.txt for rendering. The shell entrypoint prefers the repository's .venv/bin/python, then python3; override it with PYTHON_CMD if needed. OPM_CMD selects the OPM executable. Both variables are single executable paths, not shell commands. Validation-only mode needs Python and OPM but does not load the YAML dependency or pull images.

Adding a New OCP Version

To add support for a new OCP minor version, copy an existing version directory and update the Dockerfile reference:

NEW=22  # new OCP minor version
cp -r v4.19 v4.${NEW}
sed -i "s|:v4\.[0-9]*|:v4.${NEW}|" v4.${NEW}/catalog.Dockerfile
./generate-fbc.sh --render v4.${NEW}

This creates v4.${NEW}/ with the same structure as v4.19/ and renders the catalog for the new version.

About

ExploitIQ Operator File-Based Catalog (FBC)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages