Skip to content

ESO-511:Add TLS profile for the operator from openshift API - #178

Open
siddhibhor-56 wants to merge 2 commits into
openshift:mainfrom
siddhibhor-56:tls-new-main
Open

ESO-511:Add TLS profile for the operator from openshift API#178
siddhibhor-56 wants to merge 2 commits into
openshift:mainfrom
siddhibhor-56:tls-new-main

Conversation

@siddhibhor-56

@siddhibhor-56 siddhibhor-56 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor
  • Adds cluster-wide TLS profile enforcement to the external-secrets operator by reading apiserver.config.openshift.io/cluster and honoring the configured tlsSecurityProfile and tlsAdherence settings.
  • This ensures the operator's own serving endpoints (metrics, webhooks) and — in the future — the external-secrets operand deployments adhere to the platform's TLS security posture (Old, Intermediate, Modern, or Custom profiles).

Summary by CodeRabbit

  • New Features

    • The operator now honors the cluster’s configured TLS security profile.
    • Metrics and webhook endpoints automatically apply the cluster’s minimum TLS version, cipher suites, and curve preferences.
    • TLS settings are translated consistently for operator-managed components.
  • Bug Fixes

    • Invalid or unsupported TLS profiles are detected and reported instead of being silently applied.
    • TLS 1.3 configurations avoid unnecessary cipher-suite settings.
  • Tests

    • Added coverage for built-in, custom, invalid, and cluster-resolved TLS profiles, including TLS 1.2 and TLS 1.3 behavior.

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@siddhibhor-56 siddhibhor-56 changed the title Add TLS profile for the operator from openshift API ESO-511:Add TLS profile for the operator from openshift API Aug 11, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Aug 11, 2026
@openshift-ci-robot

openshift-ci-robot commented Aug 11, 2026

Copy link
Copy Markdown

@siddhibhor-56: This pull request references ESO-511 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9a9592c0-a711-46c0-83a8-e301e854b10a

📥 Commits

Reviewing files that changed from the base of the PR and between a0d6be4 and 181fe7b.

📒 Files selected for processing (1)
  • bundle/manifests/openshift-external-secrets-operator.clusterserviceversion.yaml

Walkthrough

The operator now resolves OpenShift TLS profiles, configures metrics and webhook TLS settings, watches cluster API server changes, and adds TLS argument helpers with validation and tests. RBAC, manifests, and Go dependencies were updated to support the integration.

Changes

TLS profile integration

Layer / File(s) Summary
TLS profile resolution and conversion
pkg/tlsprofile/*
The new package resolves built-in and custom profiles, validates TLS settings, converts cipher suites, and generates client and deployment arguments. Tests cover profile resolution, TLS 1.2, TLS 1.3, errors, and curve preferences.
Operator startup TLS configuration
cmd/external-secrets-operator/main.go
The operator registers OpenShift API types, resolves the cluster TLS profile before manager creation, and applies the resulting settings to metrics and webhook servers.
Reconciliation and API server watch
pkg/controller/external_secrets/*, config/rbac/role.yaml, bundle/manifests/*
The reconciler resolves and logs the honored profile. The controller caches and watches the cluster APIServer resource. RBAC and CSV permissions allow API server reads.
Dependency and release alignment
go.mod, cmd/external-secrets-operator/go.mod, test/go.mod, tools/go.mod, bundle/manifests/openshift-external-secrets-operator.clusterserviceversion.yaml
OpenShift, Kubernetes, controller-runtime, OpenAPI, testing, tooling, and transitive dependencies were updated. The CSV creation timestamp was updated.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant APIServer
  participant TLSProfileResolver
  participant MetricsAndWebhook
  Operator->>APIServer: Fetch cluster APIServer resource
  APIServer-->>TLSProfileResolver: Return honored TLS profile
  TLSProfileResolver-->>Operator: Return TLS configuration
  Operator->>MetricsAndWebhook: Apply TLS settings
Loading

Suggested reviewers: trilokgeer, bharath-b-rh


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
No-Weak-Crypto ❌ Error The new Old-profile path can apply DES-CBC3-SHA: OpenShift lists it in TLSProfiles[Old], and the new code maps it to Go's TLS_RSA_WITH_3DES_EDE_CBC_SHA. Reject or filter DES/3DES, SHA-1, RC4, and other weak suites before assigning tls.Config.CipherSuites or generating operand TLS arguments.
Docstring Coverage ⚠️ Warning Docstring coverage is 31.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (13 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: adding operator TLS profile support from the OpenShift API.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed The PR adds only Go Test... tests with static function names; it adds no Ginkgo titles or dynamic test-title construction.
Test Structure And Quality ✅ Passed The PR adds only standard-library testing tests in pkg/tlsprofile; no changed test file contains Ginkgo It, BeforeEach, AfterEach, Eventually, or Consistently code.
Microshift Test Compatibility ✅ Passed The PR adds no Ginkgo e2e tests. Its three new test files use Go's testing package and contain no MicroShift-incompatible API or feature references.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The pull request adds only standard Go unit tests in pkg/tlsprofile; no new Ginkgo e2e tests or multi-node assumptions are present.
Topology-Aware Scheduling Compatibility ✅ Passed The patch adds TLS handling, APIServer RBAC, cache, and watch logic, but no replicas, affinity, topology spread, node selectors, tolerations, or PDB constraints.
Ote Binary Stdout Contract ✅ Passed The patch adds no process-level stdout writes. Vendored klog and textlogger default to os.Stderr, and no OTE suite setup code changed.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The commit adds only standard Go unit tests under pkg/tlsprofile; it adds no Ginkgo e2e tests or changed test/e2e paths requiring IPv4 or external connectivity.
Container-Privileges ✅ Passed The diff adds only read-only API-server RBAC and a timestamp. No prohibited privilege settings were added; operator manifests use non-root, dropped capabilities, and privileged: false.
No-Sensitive-Data-In-Logs ✅ Passed New logs contain TLS metadata (version, cipher count, adherence), fixed component names, or operational errors; no passwords, tokens, API keys, PII, or customer-data fields are logged.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@openshift-ci

openshift-ci Bot commented Aug 11, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: siddhibhor-56
Once this PR has been reviewed and has the lgtm label, please assign bharath-b-rh for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with 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.

Inline comments:
In `@cmd/external-secrets-operator/main.go`:
- Around line 211-243: Move the construction of server options involving
webhook.NewServer and metricsServerOptions.TLSOpts until after the cluster TLS
profile block completes. Ensure the applyClusterTLS append operations update the
final slices assigned to both server options, while preserving the existing TLS
resolution and application behavior.

In `@go.mod`:
- Around line 8-18: Resolve the OSV findings by updating or removing the
affected dependencies declared or selected by go.mod, including
k8s.io/kubernetes, google.golang.org/grpc, OpenTelemetry, cel-go,
golang.org/x/net, and golang.org/x/text, ensuring the listed vulnerable versions
are no longer selected. Regenerate go.sum and vendor, run go mod verify for all
four modules, and rerun the OSV scan to confirm no findings remain.

In `@pkg/controller/external_secrets/install_external_secrets.go`:
- Around line 38-56: Remove the unused TLS profile resolution and logging around
tlsprofile.ResolveHonoredTLSProfile in the external-secrets reconciliation flow,
and remove the corresponding APIServer watch in the controller. Do not fail
reconciliation based on a profile that createOrApplyDeployments does not
consume; defer TLS handling until deployment rendering supports the required
arguments.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

Comment on lines +211 to +243
// Resolve cluster TLS profile for the operator's own serving endpoints.
// This uses an uncached client because the manager cache is not started yet.
uncachedClient, err := client.New(restConfig, client.Options{Scheme: scheme})
if err != nil {
setupLog.Error(err, "failed to create uncached client for TLS profile resolution")
os.Exit(1)
}
tlsSpec, err := tlsprofile.ResolveHonoredTLSProfile(
ctx,
tlsprofile.NewClientReaderAPIServerFetch(tlsprofile.NewClientReaderObjectGetter(uncachedClient)),
"external-secrets-operator",
tlsprofile.FetchErrorPropagateExceptNotFound,
)
if err != nil {
setupLog.Error(err, "failed to resolve cluster TLS profile")
os.Exit(1)
}
if tlsSpec != nil {
tlsCfg, err := tlsprofile.ClientTLSConfig(tlsSpec, nil)
if err != nil {
setupLog.Error(err, "failed to build TLS config from cluster profile")
os.Exit(1)
}
setupLog.Info("applying cluster TLS profile to operator serving endpoints",
"minTLSVersion", tlsSpec.MinTLSVersion)
applyClusterTLS := func(c *tls.Config) {
c.MinVersion = tlsCfg.MinVersion
c.CipherSuites = tlsCfg.CipherSuites
c.CurvePreferences = tlsCfg.CurvePreferences
}
metricsTLSOpts = append(metricsTLSOpts, applyClusterTLS)
webhookTLSOpts = append(webhookTLSOpts, applyClusterTLS)
}

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

rg -n -C4 'webhook.NewServer|metricsServerOptions\.TLSOpts|append\(metricsTLSOpts|append\(webhookTLSOpts' cmd/external-secrets-operator/main.go

Repository: openshift/external-secrets-operator

Length of output: 1491


Apply TLS options before constructing the server options.

webhook.NewServer and metricsServerOptions.TLSOpts capture the current slice headers. The later append calls do not update those stored headers. The resolved TLS profile therefore does not reach either server.

Assign both option slices after all TLS option appends complete.

🤖 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 `@cmd/external-secrets-operator/main.go` around lines 211 - 243, Move the
construction of server options involving webhook.NewServer and
metricsServerOptions.TLSOpts until after the cluster TLS profile block
completes. Ensure the applyClusterTLS append operations update the final slices
assigned to both server options, while preserving the existing TLS resolution
and application behavior.

Comment thread go.mod
Comment on lines +8 to +18
github.com/openshift/api v0.0.0-20260807110950-72ae4424ef35
github.com/openshift/library-go v0.0.0-20260807194649-ee0a87843dda
go.uber.org/zap v1.27.1
k8s.io/api v0.35.6
k8s.io/apiextensions-apiserver v0.35.0
k8s.io/apimachinery v0.35.6
k8s.io/client-go v0.35.6
k8s.io/kubernetes v1.35.6
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2
sigs.k8s.io/controller-runtime v0.23.3
k8s.io/api v0.36.3
k8s.io/apiextensions-apiserver v0.36.2
k8s.io/apimachinery v0.36.3
k8s.io/client-go v0.36.2
k8s.io/klog/v2 v2.140.0
k8s.io/kubernetes v1.36.3
k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3
sigs.k8s.io/controller-runtime v0.24.1

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 | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

for module in . cmd/external-secrets-operator test tools; do
  echo "== $module =="
  (
    cd "$module"
    go mod tidy -diff
    go mod verify
    go list -m -json all
  ) |
  jq -c 'select(.Path != null and .Version != null) |
    {package: {name: .Path, ecosystem: "Go"}, version: .Version}' |
  while IFS= read -r query; do
    curl -fsS https://api.osv.dev/v1/query \
      -H 'Content-Type: application/json' \
      --data "$query" |
    jq -c --arg module "$module" \
      'select((.vulns // []) | length > 0) |
       {module: $module, vulns: .vulns}'
  done
done

Repository: openshift/external-secrets-operator

Length of output: 1260


🏁 Script executed:

#!/usr/bin/env bash
set -u

printf '%s\n' '== module files =='
git ls-files '*go.mod' '*go.sum' | sort

printf '%s\n' '== repository layout =='
git ls-files | rg '(^|/)(vendor/|go\.work$|go\.mod$|go\.sum$)' | sed -n '1,240p'

printf '%s\n' '== root go.mod =='
cat -n go.mod

printf '%s\n' '== root go.sum status =='
if test -f go.sum; then
  wc -l go.sum
  git status --short -- go.sum
else
  echo 'go.sum not found'
fi

Repository: openshift/external-secrets-operator

Length of output: 18031


🏁 Script executed:

#!/usr/bin/env bash
set -u

printf '%s\n' '== go.work =='
cat -n go.work

for file in cmd/external-secrets-operator/go.mod test/go.mod tools/go.mod; do
  printf '\n== %s ==\n' "$file"
  cat -n "$file"
done

printf '\n== vendored module metadata ==\n'
if test -f vendor/modules.txt; then
  sed -n '1,80p' vendor/modules.txt
  printf '%s\n' '...'
  tail -80 vendor/modules.txt
else
  echo 'vendor/modules.txt not found'
fi

printf '\n== module versions declared in go.mod files ==\n'
python3 - <<'PY'
from pathlib import Path
import re

for path in sorted(Path(".").glob("**/go.mod")):
    print(f"== {path} ==")
    for line in path.read_text().splitlines():
        match = re.match(r"^\s*(\S+)\s+(v\S+)(?:\s+//.*)?$", line)
        if match:
            print(f"{match.group(1)} {match.group(2)}")
PY

Repository: openshift/external-secrets-operator

Length of output: 50391


🏁 Script executed:

#!/usr/bin/env bash
set +e

for module in . cmd/external-secrets-operator test tools; do
  printf '\n== %s: go mod verify ==\n' "$module"
  (
    cd "$module" || exit 1
    GOWORK=off go mod verify
  )
  printf 'status=%s\n' "$?"

  printf '== %s: go list -m -json all with module mode ==\n' "$module"
  (
    cd "$module" || exit 1
    GOWORK=off go list -mod=mod -m -json all >/tmp/module-list.json
    status=$?
    printf 'status=%s modules=%s\n' "$status" "$(wc -l </tmp/module-list.json)"
    if test "$status" -eq 0; then
      jq -s 'length' /tmp/module-list.json
    else
      sed -n '1,12p' /tmp/module-list.json
    fi
    exit "$status"
  )
done

Repository: openshift/external-secrets-operator

Length of output: 165


🏁 Script executed:

#!/usr/bin/env bash
set -u

python3 - <<'PY'
import json
import re
import urllib.request
from pathlib import Path

header = re.compile(r"^# (\S+) (\S+)$")
modules = {}

for line in Path("vendor/modules.txt").read_text().splitlines():
    match = header.match(line)
    if match and "=>" not in line:
        modules[match.group(1)] = match.group(2)

sum_entries = set()
for sum_path in sorted(Path(".").glob("**/go.sum")):
    for line in sum_path.read_text().splitlines():
        fields = line.split()
        if len(fields) >= 2:
            name, version = fields[0], fields[1]
            if name.endswith("/go.mod"):
                name = name[:-len("/go.mod")]
            sum_entries.add((name, version))

missing = sorted(
    (name, version)
    for name, version in modules.items()
    if (name, version) not in sum_entries
    or (name, version + "/go.mod") not in {
        (n, v) for n, v in sum_entries
    }
)

print(f"vendored_modules={len(modules)}")
print(f"go_sum_files={len(list(Path('.').glob('**/go.sum')))}")
print(f"modules_missing_a_sum_entry={len(missing)}")
for name, version in missing[:80]:
    print(f"MISSING {name} {version}")

items = [
    {"package": {"name": name, "ecosystem": "Go"}, "version": version}
    for name, version in sorted(modules.items())
]
vulnerabilities = []
errors = []

for start in range(0, len(items), 100):
    payload = json.dumps({"queries": items[start:start + 100]}).encode()
    request = urllib.request.Request(
        "https://api.osv.dev/v1/querybatch",
        data=payload,
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    try:
        with urllib.request.urlopen(request, timeout=30) as response:
            result = json.load(response)
    except Exception as exc:
        errors.append(f"batch {start}:{start + 100}: {exc}")
        continue

    for item, result_item in zip(items[start:start + 100], result.get("results", [])):
        for vuln in result_item.get("vulns", []):
            vulnerabilities.append({
                "module": item["package"]["name"],
                "version": item["version"],
                "id": vuln.get("id"),
                "summary": vuln.get("summary"),
            })

print(f"osv_queries={len(items)}")
print(f"osv_vulnerabilities={len(vulnerabilities)}")
for vuln in vulnerabilities:
    print("VULN " + json.dumps(vuln, sort_keys=True))
print(f"osv_errors={len(errors)}")
for error in errors:
    print("OSV_ERROR " + error)
PY

Repository: openshift/external-secrets-operator

Length of output: 928


🏁 Script executed:

#!/usr/bin/env bash
set -u

python3 - <<'PY' >/tmp/osv-querybatch.json
import json
import re
from pathlib import Path

modules = {}
for line in Path("vendor/modules.txt").read_text().splitlines():
    match = re.match(r"^# (\S+) (\S+)$", line)
    if match and "=>" not in line:
        modules[match.group(1)] = match.group(2)

items = [
    {"package": {"name": name, "ecosystem": "Go"}, "version": version}
    for name, version in sorted(modules.items())
]
for start in range(0, len(items), 100):
    print(json.dumps({"queries": items[start:start + 100]}))
PY

: > /tmp/osv-results.jsonl
status=0
while IFS= read -r query; do
  response=$(curl -fsS -k \
    https://api.osv.dev/v1/querybatch \
    -H 'Content-Type: application/json' \
    --data "$query") || {
      echo 'OSV request failed' >&2
      status=1
      continue
    }
  printf '%s\n' "$response" >> /tmp/osv-results.jsonl
done </tmp/osv-querybatch.json

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

batches = [json.loads(line) for line in Path("/tmp/osv-results.jsonl").read_text().splitlines()]
vulnerabilities = []
for batch in batches:
    for result in batch.get("results", []):
        for vuln in result.get("vulns", []):
            vulnerabilities.append((vuln.get("id"), vuln.get("summary")))

print(f"osv_batches={len(batches)}")
print(f"osv_vulnerabilities={len(vulnerabilities)}")
for vuln_id, summary in vulnerabilities:
    print(f"VULN {vuln_id}: {summary}")
PY

exit "$status"

Repository: openshift/external-secrets-operator

Length of output: 543


🏁 Script executed:

#!/usr/bin/env bash
set -u

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

for line in Path("/tmp/osv-results.jsonl").read_text().splitlines():
    batch = json.loads(line)
    for result in batch.get("results", []):
        vulns = result.get("vulns", [])
        if not vulns:
            continue
        # querybatch preserves query order, so identify the package from the
        # corresponding query payload when available in the saved request file.
        print(json.dumps(result, sort_keys=True))
PY

Repository: openshift/external-secrets-operator

Length of output: 1173


🏁 Script executed:

#!/usr/bin/env bash
set -u

python3 - <<'PY'
import json
import re
import urllib.request
from pathlib import Path

modules = {}
for line in Path("vendor/modules.txt").read_text().splitlines():
    match = re.match(r"^# (\S+) (\S+)$", line)
    if match and "=>" not in line:
        modules[match.group(1)] = match.group(2)

items = [
    (name, version)
    for name, version in sorted(modules.items())
]

vulnerability_ids = set()
for batch_index, line in enumerate(Path("/tmp/osv-results.jsonl").read_text().splitlines()):
    results = json.loads(line).get("results", [])
    for offset, result in enumerate(results):
        ids = [v["id"] for v in result.get("vulns", [])]
        if ids:
            name, version = items[batch_index * 100 + offset]
            print(f"{name} {version}: {', '.join(ids)}")
            vulnerability_ids.update(ids)

print("\n== OSV details ==")
for vuln_id in sorted(vulnerability_ids):
    request = urllib.request.Request(
        f"https://api.osv.dev/v1/vulns/{vuln_id}",
        headers={"Accept": "application/json"},
    )
    try:
        with urllib.request.urlopen(request, timeout=30) as response:
            vuln = json.load(response)
    except Exception as exc:
        print(f"{vuln_id}: ERROR {exc}")
        continue

    affected = []
    for entry in vuln.get("affected", []):
        ranges = []
        for item in entry.get("ranges", []):
            ranges.append({
                "type": item.get("type"),
                "events": item.get("events"),
            })
        affected.append({
            "package": entry.get("package"),
            "ranges": ranges,
        })
    print(json.dumps({
        "id": vuln_id,
        "summary": vuln.get("summary"),
        "affected": affected,
    }, sort_keys=True))
PY

Repository: openshift/external-secrets-operator

Length of output: 2734


🏁 Script executed:

#!/usr/bin/env bash
set -u

for id in \
  GO-2022-0635 GO-2022-0646 GHSA-gcjh-h69q-9w9g GO-2026-5158 \
  GHSA-hfvc-g4fc-pqh GO-2026-5426 GO-2026-5932 GO-2026-5942 \
  GO-2026-5970 GHSA-hrxh-6v49-42gf GO-2026-6061 GO-2025-3521 \
  GO-2025-3547
do
  curl -fsS -k "https://api.osv.dev/v1/vulns/$id" |
    jq -c '{
      id,
      summary,
      database_specific,
      affected: [
        .affected[] |
        {
          package: .package,
          ranges: [.ranges[] | {type, events}]
        }
      ]
    }'
done

Repository: openshift/external-secrets-operator

Length of output: 5306


🏁 Script executed:

#!/usr/bin/env bash
set -u

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

targets = {
    "github.com/aws/aws-sdk-go",
    "github.com/google/cel-go",
    "go.opentelemetry.io/otel",
    "go.opentelemetry.io/otel/sdk",
    "golang.org/x/crypto",
    "golang.org/x/net",
    "golang.org/x/text",
    "google.golang.org/grpc",
    "k8s.io/kubernetes",
}

for path in sorted(Path(".").glob("**/go.mod")):
    matches = []
    for line in path.read_text().splitlines():
        fields = line.split()
        if len(fields) >= 2 and fields[0] in targets:
            matches.append((fields[0], fields[1], "indirect" in line))
    if matches:
        print(path)
        for name, version, indirect in matches:
            print(f"  {name} {version} ({'indirect' if indirect else 'direct'})")
PY

Repository: openshift/external-secrets-operator

Length of output: 1149


Resolve the OSV findings before merge.

OSV flags these selected versions: k8s.io/kubernetes v1.36.3, google.golang.org/grpc v1.79.3, go.opentelemetry.io/otel v1.41.0, go.opentelemetry.io/otel/sdk v1.40.0, github.com/google/cel-go v0.26.0, golang.org/x/net before v0.56.0, and golang.org/x/text before v0.39.0. Update or remove the affected modules, regenerate go.sum and vendor, then run go mod verify for all four modules and repeat the OSV scan.

🤖 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 `@go.mod` around lines 8 - 18, Resolve the OSV findings by updating or removing
the affected dependencies declared or selected by go.mod, including
k8s.io/kubernetes, google.golang.org/grpc, OpenTelemetry, cel-go,
golang.org/x/net, and golang.org/x/text, ensuring the listed vulnerable versions
are no longer selected. Regenerate go.sum and vendor, run go mod verify for all
four modules, and rerun the OSV scan to confirm no findings remain.

Source: Path instructions

Comment on lines +38 to +56
// Resolve cluster TLS profile for operand deployments.
// TODO: once the upstream external-secrets operand supports --tls-min-version,
// --tls-ciphers, and --tls-curve-preferences flags, pass tlsSpec to
// createOrApplyDeployments and inject the flags into container args.
tlsSpec, err := tlsprofile.ResolveHonoredTLSProfile(
r.ctx,
tlsprofile.NewClientReaderAPIServerFetch(r.CtrlClient),
"external-secrets",
tlsprofile.FetchErrorPropagateExceptNotFound,
)
if err != nil {
r.log.Error(err, "failed to resolve cluster TLS profile")
return err
}
if tlsSpec != nil {
r.log.V(2).Info("resolved cluster TLS profile for operand deployments",
"minTLSVersion", tlsSpec.MinTLSVersion,
"cipherCount", len(tlsSpec.Ciphers))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Do not fail reconciliation for a profile that deployments do not consume.

tlsSpec is only logged. Lines 104-107 still call createOrApplyDeployments without TLS arguments. The APIServer watch in pkg/controller/external_secrets/controller.go therefore causes reconciliations that cannot update operand TLS settings.

Until the upstream operand supports these flags, remove this resolution path and its watch. Otherwise, pass the resolved profile into deployment rendering and add the generated TLS arguments.

🤖 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 `@pkg/controller/external_secrets/install_external_secrets.go` around lines 38
- 56, Remove the unused TLS profile resolution and logging around
tlsprofile.ResolveHonoredTLSProfile in the external-secrets reconciliation flow,
and remove the corresponding APIServer watch in the controller. Do not fail
reconciliation based on a profile that createOrApplyDeployments does not
consume; defer TLS handling until deployment rendering supports the required
arguments.

@openshift-ci

openshift-ci Bot commented Aug 11, 2026

Copy link
Copy Markdown

@siddhibhor-56: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Aug 13, 2026
@openshift-ci

openshift-ci Bot commented Aug 13, 2026

Copy link
Copy Markdown

PR needs rebase.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants