Skip to content
Merged
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
68 changes: 1 addition & 67 deletions .govulncheck.yaml
Original file line number Diff line number Diff line change
@@ -1,67 +1 @@
ignored-vulnerabilities:
- id: GO-2026-4601
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-4601
- id: GO-2026-4602
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-4602
- id: GO-2026-4603
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-4603
- id: GO-2026-4865
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-4865
- id: GO-2026-4870
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-4870
- id: GO-2026-4918
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-4918
- id: GO-2026-4946
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-4946
- id: GO-2026-4947
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-4947
- id: GO-2026-4971
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-4971
- id: GO-2026-4977
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-4977
- id: GO-2026-4980
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-4980
- id: GO-2026-4982
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-4982
- id: GO-2026-4986
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-4986
- id: GO-2026-5026
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-5026
- id: GO-2026-5037
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-5037
- id: GO-2026-5038
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-5038
- id: GO-2026-5039
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-5039
- id: GO-2026-5856
silence-until: 2026-08-19
info: https://pkg.go.dev/vuln/GO-2026-5856
# Infinite loop on invalid input in golang.org/x/text
# Found in: golang.org/x/text/unicode/norm@v0.32.0
# Fixed in: golang.org/x/text/unicode/norm@v0.39.0
- id: GO-2026-5970
silence-until: 2026-08-28
info: https://pkg.go.dev/vuln/GO-2026-5970
# Vulnerabilities in the xDS RBAC authorization engine and the HTTP/2 transport server implementation in google.golang.org/grpc
# Found in: google.golang.org/grpc/internal/transport@v1.79.3
# Fixed in: google.golang.org/grpc/internal/transport@v1.82.1
- id: GO-2026-6061
silence-until: 2026-08-28
info: https://pkg.go.dev/vuln/GO-2026-6061
ignored-vulnerabilities: []
102 changes: 0 additions & 102 deletions README.adoc

This file was deleted.

102 changes: 102 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Host Operator

[![Go Report Card](https://goreportcard.com/badge/github.com/codeready-toolchain/host-operator)](https://goreportcard.com/report/github.com/codeready-toolchain/host-operator)
[![GoDoc](https://godoc.org/github.com/codeready-toolchain/host-operator?status.png)](https://godoc.org/github.com/codeready-toolchain/host-operator)
[![Codecov.io](https://codecov.io/gh/codeready-toolchain/host-operator/branch/master/graph/badge.svg)](https://codecov.io/gh/codeready-toolchain/host-operator)
[![Operator CD](https://github.com/codeready-toolchain/host-operator/actions/workflows/operator-cd.yml/badge.svg)](https://github.com/codeready-toolchain/host-operator/actions/workflows/operator-cd.yml)
[![Image Repository on Quay](https://quay.io/repository/codeready-toolchain/host-operator/status)](https://quay.io/repository/codeready-toolchain/host-operator)

This is the CodeReady Toolchain Host Operator repository. It contains the OpenShift Operator that is deployed on the "host" cluster in the SaaS.

## Build

Requires Go version 1.26.x (1.26.5 or higher) - download for your development environment [here](https://golang.org/dl/).

This repository uses [Go modules](https://github.com/golang/go/wiki/Modules).

## Development

The dev.mk targets in the toolchain-e2e repository can be used to build and deploy the host and member operators for development, or use the [guide](https://github.com/codeready-toolchain/toolchain-e2e/blob/master/dev_install.adoc).

## Releasing operator

The releases of the operator are automatically managed via GitHub Actions workflow defined in this repository.

### Broken release

If there is any broken release that cannot be built & pushed through the pipeline - for example because of this error:
```
Invalid bundle toolchain-host-operator.v0.0.321-147-commit-477c4b7-5e49228, bundle specifies a non-existent replacement toolchain-host-operator.v0.0.320-146-commit-f46a8aa-8f94bc0
```
then the release has to be fixed manually. In such a case, please follow these steps:

> **Note:** If the problem occurred when releasing registration-service, then don't do anything in the host-operator, but follow the steps in registration-service repo.

1. Log in to quay.io using an account that has the write permissions in quay.io/codeready-toolchain/host-operator repo.
2. Checkout to the problematic (missing) commit that failed in the pipeline and that has to be manually released.
3. Run `make podman-push QUAY_NAMESPACE=codeready-toolchain`
4. Run `make push-to-quay-staging QUAY_NAMESPACE=codeready-toolchain`

### End-to-End tests

#### Background & pairing

E2E tests are not located in this repository - all e2e tests are in [toolchain-e2e](https://github.com/codeready-toolchain/toolchain-e2e) repo, however, it's still possible to run them locally from this repo - see [Running End-to-End Tests](#running-end-to-end-tests).

When there is a change introduced in this repository that should be either covered by e2e tests or requires changes in the already existing tests, then all needed changes should go into the [toolchain-e2e](https://github.com/codeready-toolchain/toolchain-e2e) repo.
The logic that executes tests in openshift-ci automatically tries to pair PR opened for this (host-operator) repository with a branch that potentially exists in the developer's fork of the [toolchain-e2e](https://github.com/codeready-toolchain/toolchain-e2e) repo. This pairing is based on a branch name.

For example, if a developer with GH account `cooljohn` opens a PR (for host-operator repo) from a branch `fix-reconcile`, then the logic checks if there is a branch `fix-reconcile` also in the `cooljohn/toolchain-e2e` fork.
If there is, then the logic:

1. clones latest changes from [codeready-toolchain/toolchain-e2e](https://github.com/codeready-toolchain/toolchain-e2e)
2. fetches the `fix-reconcile` branch from `cooljohn/toolchain-e2e` fork
3. merges `master` branch with the changes from `fix-reconcile` branch
4. clones latest changes from [member-operator](https://github.com/codeready-toolchain/member-operator) repo and builds & deploys the `member-operator` image out of it
5. builds & deploys the `host-operator` image from the code that is in the PR
6. runs e2e tests against both operators from the merged branch of the `toolchain-e2e` repo
Comment on lines +47 to +57

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, examine the README.md file around the specified lines
head -80 README.md | tail -40

Repository: codeready-toolchain/host-operator

Length of output: 3960


🏁 Script executed:

#!/bin/bash
# Look for OpenShift CI configuration
find . -name ".ci" -o -name ".prow*" -o -name "Makefile*" | head -20

Repository: codeready-toolchain/host-operator

Length of output: 182


🏁 Script executed:

#!/bin/bash
# Check if there's a ci directory or configuration
ls -la | grep -i ci

Repository: codeready-toolchain/host-operator

Length of output: 300


🏁 Script executed:

#!/bin/bash
# Examine openshift-ci directory
ls -la openshift-ci/
cat openshift-ci/*

Repository: codeready-toolchain/host-operator

Length of output: 2318


🏁 Script executed:

#!/bin/bash
# Extract relevant sections from Makefile
grep -n "test-e2e\|toolchain-e2e\|member-operator\|clone\|fetch\|merge" Makefile | head -50

Repository: codeready-toolchain/host-operator

Length of output: 171


🏁 Script executed:

#!/bin/bash
# Look for any scripts that handle the pairing logic
find . -name "*.sh" -type f | head -20

Repository: codeready-toolchain/host-operator

Length of output: 171


🏁 Script executed:

#!/bin/bash
# Read the full Makefile
cat Makefile | head -150

Repository: codeready-toolchain/host-operator

Length of output: 310


🏁 Script executed:

#!/bin/bash
# Search for references to test-e2e without exact match
rg -i "test.*e2e\|e2e.*test" --type makefile

Repository: codeready-toolchain/host-operator

Length of output: 208


🏁 Script executed:

#!/bin/bash
# Look for OpenShift CI configuration in toolchain-e2e
find . -name ".ci" -o -name "*.prow*" -o -name "*prow*" -o -name "*.openshift*" 2>/dev/null | head -20

Repository: codeready-toolchain/toolchain-e2e

Length of output: 171


🏁 Script executed:

#!/bin/bash
# Search for pairing or branch logic
rg -i "pair\|fork\|developer.*fork" --type md --type sh --type yaml | head -30

Repository: codeready-toolchain/toolchain-e2e

Length of output: 171


🏁 Script executed:

#!/bin/bash
# Check the make directory structure
ls -la make/

Repository: codeready-toolchain/host-operator

Length of output: 1005


🏁 Script executed:

#!/bin/bash
# Search for e2e related content in make files
grep -r "e2e\|toolchain-e2e\|member-operator" make/

Repository: codeready-toolchain/host-operator

Length of output: 1814


🏁 Script executed:

#!/bin/bash
# Look for CI-related files more broadly
find . -type f \( -name ".github" -o -name "*.yml" -o -name "*.yaml" \) | grep -i "ci\|workflow\|action" | head -30

Repository: codeready-toolchain/host-operator

Length of output: 585


🏁 Script executed:

#!/bin/bash
# Look for the actual test setup and branch pairing logic
ls -la
find . -maxdepth 2 -name "*.sh" -o -name "Makefile*" -o -name "*.mk"

Repository: codeready-toolchain/toolchain-e2e

Length of output: 2131


🏁 Script executed:

#!/bin/bash
# Read the full test.mk file which contains the e2e logic
cat make/test.mk

Repository: codeready-toolchain/host-operator

Length of output: 5542


🏁 Script executed:

#!/bin/bash
# Read the full README to understand credential and registry requirements
cat README.md | head -200

Repository: codeready-toolchain/host-operator

Length of output: 8118


🏁 Script executed:

#!/antml:thinking
Let me check if there are GitHub Actions workflow files that show how the CI is actually configured and what protections exist around credentials.
`#/`
find .github -name "*.yml" -exec grep -l "e2e\|test-e2e\|openshift" {} \;

Repository: codeready-toolchain/host-operator

Length of output: 263


🏁 Script executed:

#!/bin/bash
# Check what the CI workflows do - especially the one related to E2E publishing
cat .github/workflows/publish-components-for-e2e-tests.yml

Repository: codeready-toolchain/host-operator

Length of output: 4089


🏁 Script executed:

#!/bin/bash
# Check the publish action from toolchain-cicd to understand what credentials it uses
curl -s https://api.github.com/repos/codeready-toolchain/toolchain-cicd/contents/publish-operators-for-e2e-tests | jq '.download_url' 2>/dev/null || echo "Check GitHub web interface"

Repository: codeready-toolchain/host-operator

Length of output: 176


🏁 Script executed:

#!/bin/bash
# Look for CLONEREFS_OPTIONS or other PROW configuration that shows the CI execution context
grep -r "CLONEREFS_OPTIONS\|PROW\|pull_request_target" .github/

Repository: codeready-toolchain/host-operator

Length of output: 590


Security (CWE-494): Download of Code Without Integrity Check

Reachability: External · Exploitability: Moderate

Address unpinned dependencies and unverified fork code in E2E pairing.

The E2E pairing logic in make/test.mk fetches and merges code from a developer's fork without commit pinning or signature verification. The workflow uses pull_request_target to run with repository credentials, though it publishes to a segregated test namespace (codeready-toolchain-test) via an explicit TEST_QUAY_TOKEN.

Add commit pinning for the cloned repositories (official toolchain-e2e and member-operator). If the developer's fork branch cannot be verified, document the trust boundary explicitly or require an approval step before merging unverified fork code. For local runs, document the commits that will be used before the merge step executes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 47 - 57, Update the E2E pairing workflow in
make/test.mk to pin the official toolchain-e2e and member-operator clones to
explicit commits rather than latest changes. Add verification or an approval
gate before merging code from a developer fork; otherwise document the trust
boundary clearly. Update the README to describe the pinned commits used locally
before the merge step.

Source: Path instructions


If the branch with the same name does not exist, then it only clones the latest changes from [toolchain-e2e](https://github.com/codeready-toolchain/toolchain-e2e) and runs e2e tests from the `master`.

If you still don't know what to do with e2e tests in some use-cases, go to [What to do](#what-to-do) section where all use-cases are covered.

#### Prerequisites if running locally

* Make sure you have set the `QUAY_NAMESPACE` variable: `export QUAY_NAMESPACE=<quay-username>`
* Log in to the target OpenShift cluster with cluster admin privileges
* The visibility of `host-operator` repository in quay is set to public (`https://quay.io/repository/<your-username>/host-operator?tab=settings`)
Comment on lines +65 to +67

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- README context ---'
sed -n '1,120p' README.md

printf '%s\n' '--- relevant files ---'
git ls-files | rg '(^|/)(Makefile|Dockerfile|.*e2e.*|.*rbac.*|.*role.*|.*clusterrole.*|.*quay.*|.*deploy.*|.*config.*|.*test.*)' | head -200

printf '%s\n' '--- privilege and image references ---'
rg -n -i 'cluster-admin|clusterrole|rolebinding|serviceaccount|quay|image:|imagePull|pull-secret|e2e|oc adm policy|kubectl auth' --glob '!vendor/**' --glob '!**/go.sum' . | head -400

Repository: codeready-toolchain/host-operator

Length of output: 50391


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- E2E entry points and setup references ---'
rg -n -i 'test-e2e|dev_install|cluster-admin|clusterrole|rolebinding|imagePull|pull-secret|quay|HOST_NS|MEMBER_NS|oc |kubectl ' \
  --glob '!vendor/**' --glob '!**/go.sum' . | head -500

printf '%s\n' '--- candidate Makefiles and manifests ---'
git ls-files | rg '(^|/)(Makefile|.*\.mk|.*\.yaml|.*\.yml|.*\.adoc|.*\.sh)$' | \
  rg -i 'make|e2e|dev|deploy|rbac|role|cluster|quay|registry' | head -300

Repository: codeready-toolchain/toolchain-e2e

Length of output: 50389


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- host Makefile E2E target ---'
sed -n '65,135p' make/test.mk

printf '%s\n' '--- generated host RBAC declarations ---'
sed -n '1,130p' config/rbac/role_binding.yaml
sed -n '1,180p' config/rbac/kustomization.yaml
sed -n '80,115p' cmd/main.go

printf '%s\n' '--- host deployment image and service account ---'
sed -n '1,115p' config/manager/manager.yaml

Repository: codeready-toolchain/host-operator

Length of output: 8783


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- E2E setup and deployment commands ---'
sed -n '270,470p' make/test.mk

printf '%s\n' '--- E2E RBAC and cluster-scoped resources ---'
rg -n -i '^(kind: (ClusterRole|ClusterRoleBinding|CustomResourceDefinition|Namespace|PriorityClass|MutatingWebhookConfiguration|ValidatingWebhookConfiguration)|apiVersion:|resources:|verbs:|roleRef:|subjects:)' \
  deploy setup --glob '*.yaml' --glob '*.yml' | head -500

printf '%s\n' '--- operator installation and image pull configuration ---'
sed -n '1,290p' scripts/ci/manage-operator.sh
sed -n '1,150p' scripts/ci/manage-host-operator.sh
sed -n '1,140p' scripts/ci/manage-member-operator.sh
sed -n '1,90p' quay.adoc

Repository: codeready-toolchain/toolchain-e2e

Length of output: 40375


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import re

root = Path(".")
files = list(root.glob("make/*.mk")) + list(root.glob("scripts/ci/*.sh"))
patterns = {
    "cluster_scope_commands": re.compile(
        r"\boc\s+(?:apply|create|delete|patch|get|wait|adm)\b[^\n]*"
        r"(?:--all-namespaces|ClusterRole|ClusterRoleBinding|crd|crds|projects|"
        r"PriorityClass|Webhook|oauths\.config|ingress\.config|must-gather)",
        re.I,
    ),
    "namespace_commands": re.compile(
        r"\boc\s+(?:new-project|project|apply|create|delete|patch|get|wait)\b[^\n]*"
        r"(?:-n\s+|\-\-namespace|PROJECT_NAME|HOST_NS|MEMBER_NS)",
        re.I,
    ),
    "pull_secret_configuration": re.compile(
        r"(?:imagePullSecrets|dockerconfigjson|pull-secret|secret\s+generic|"
        r"registry.*secret|oc\s+create\s+secret)",
        re.I,
    ),
}

for name, pattern in patterns.items():
    print(f"--- {name} ---")
    for path in files:
        try:
            text = path.read_text()
        except UnicodeDecodeError:
            continue
        for line_no, line in enumerate(text.splitlines(), 1):
            if pattern.search(line):
                print(f"{path}:{line_no}:{line.strip()}")
PY

Repository: codeready-toolchain/toolchain-e2e

Length of output: 14251


Security Misconfiguration (CWE-250)

Exploitability: Theoretical

Restrict local E2E tests to disposable clusters.

The workflow creates CRDs, projects, OLM resources, and cluster-scoped RBAC, and its cleanup removes cluster-scoped resources. Keep cluster-admin only for this workflow unless a tested custom role replaces it. Document the disposable-cluster requirement. The workflow also publishes images without configuring imagePullSecrets; document private-registry support or warn that all public images must contain no sensitive data.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 65 - 67, Update the local E2E setup documentation to
require a disposable OpenShift cluster, noting that cluster-admin access is
limited to this workflow unless a tested custom role replaces it. Document
private-registry support and imagePullSecrets configuration, or explicitly warn
that images published by the workflow must be public and contain no sensitive
data.

Source: Path instructions


#### Running End-to-End Tests

Although the e2e tests are in the separated repository, it's still possible to run them from this repo (host-operator) and also against the current code that is at HEAD.
There are two Makefile targets that will execute the e2e tests:

* `make test-e2e` - this target clones latest changes from [toolchain-e2e](https://github.com/codeready-toolchain/toolchain-e2e) and runs e2e tests for both operators from the master. As deployment for `host-operator` it uses the current code that is at HEAD.
* `make test-e2e-local` - this target doesn't clone anything, but it runs run e2e tests for both operators from the directory `../toolchain-e2e`. As deployment for `host-operator` it uses the current code that is at HEAD.

The tests executed within [toolchain-e2e](https://github.com/codeready-toolchain/toolchain-e2e) repo will take care of creating all needed namespaces with random names (or see below for enforcing some specific namespace names).
It will also create all required CRDs, role and role bindings for the service accounts, build the images for both operators and push them to the image registry. Finally, it will deploy the operators and run the tests.

> **Note:** you can override the default namespace names where the end-to-end tests are going to be executed - eg.: `make test-e2e HOST_NS=my-host MEMBER_NS=my-member`

##### What to do

If you are still confused by the e2e location, execution and branch pairing, see the following cases and needed steps:

* **Working locally:**
* **Need to test your code using the latest version of e2e tests from [toolchain-e2e](https://github.com/codeready-toolchain/toolchain-e2e) repo:**
* execute `make test-e2e`
* **Need to test your code using e2e tests located in `../toolchain-e2e` repo:**
* `make test-e2e-local`

* **Creating a PR:**
* **Your PR doesn't need any changes in [toolchain-e2e](https://github.com/codeready-toolchain/toolchain-e2e) repo:**
1. check the name of a branch you are going to create a PR for
2. make sure that your fork of [toolchain-e2e](https://github.com/codeready-toolchain/toolchain-e2e) repo doesn't contain branch with the same name
3. create a PR
* **Your PR requires changes in [toolchain-e2e](https://github.com/codeready-toolchain/toolchain-e2e) repo:**
1. check the name of a branch you are going to create a PR for
2. create a branch with the same name within your fork of [toolchain-e2e](https://github.com/codeready-toolchain/toolchain-e2e) repo and put all necessary changes there
3. push all changes into both forks of the repositories [toolchain-e2e](https://github.com/codeready-toolchain/toolchain-e2e) and [host-operator](https://github.com/codeready-toolchain/host-operator)
4. create a PR for [host-operator](https://github.com/codeready-toolchain/host-operator)
5. create a PR for [toolchain-e2e](https://github.com/codeready-toolchain/toolchain-e2e)
Loading
Loading