Skip to content

Added labels support for ci-secret-bootstrap#5189

Open
hector-vido wants to merge 1 commit into
openshift:mainfrom
hector-vido:labels-support-secret-bootstrap
Open

Added labels support for ci-secret-bootstrap#5189
hector-vido wants to merge 1 commit into
openshift:mainfrom
hector-vido:labels-support-secret-bootstrap

Conversation

@hector-vido
Copy link
Copy Markdown
Contributor

@hector-vido hector-vido commented May 19, 2026

Since we are using ci-secret-bootstrap to manage ArgoCD cluster secrets we need a way specify labels inside the secret stored on vault to avoid manual work.

ArgoCD identify cluster secrets based on the label argocd.argoproj.io/secret-type: cluster added to the secrets that maps a ServiceAccount and a token from other clusters inside openshift-gitops.

This PR add this possibility.

@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: automatic mode

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

📝 Walkthrough

Walkthrough

This PR adds support for Kubernetes secret labels controlled by Vault. A new sync target labels key is defined, validated in the Vault proxy, parsed from Vault in the bootstrap tool, and used to update secrets when labels differ from the stored state.

Changes

Secret sync target labels support

Layer / File(s) Summary
Define secret sync target labels key
pkg/api/vault/vault.go
New exported constant SecretSyncTargetLabelsKey defines the Vault key secretsync/target-labels for label data.
Skip labels key in Vault request validation
cmd/vault-subpath-proxy/kv_update_transport.go
Validation loop now treats SecretSyncTargetLabelsKey as a reserved sync key, bypassing regex checks alongside the cluster target key.
Parse and apply sync labels from Vault
cmd/ci-secret-bootstrap/main.go
fetchUserSecrets extracts and parses comma-separated label pairs from Vault, applies labels to new and existing secrets, and extends reserved-key handling to exclude sync-related keys from secret data.
Detect and apply label changes
cmd/ci-secret-bootstrap/main.go
updateSecrets now compares desired and existing secret labels via deep equality and includes label drift in the update decision, forcing updates when labels change.

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 11 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Go Error Handling ⚠️ Warning Panic risk on line 679: accessing label[1] without bounds check. Input "foo" or " " causes crash. No error collection for malformed labels, missing array length validation. Add bounds checking, collect errors instead of panicking, validate label format before array access, and reject reserved keys per review comments.
Test Coverage For New Features ⚠️ Warning New label parsing and comparison functionality has no test coverage. Label parsing (lines 674-682) and label comparison (line 820) lack unit tests for normal cases and malformed inputs. Add tests for label parsing (valid/invalid inputs), label-only updates, key exclusion, and error handling for malformed label entries.
✅ Passed checks (11 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding labels support to ci-secret-bootstrap, which is the core feature across all modified files.
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 PR modifies only production code (main.go and vault.go). No Ginkgo test files added or modified. Check is not applicable.
Test Structure And Quality ✅ Passed No Ginkgo test files were modified in this PR. The changes are limited to production code in main.go, kv_update_transport.go, and vault.go. The check is not applicable.
Microshift Test Compatibility ✅ Passed This PR contains no new Ginkgo e2e tests. It modifies only production code files (ci-secret-bootstrap, vault-subpath-proxy, vault API). The MicroShift test compatibility check is not applicable.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No new Ginkgo e2e tests were added in this PR. All changes are to application code (CI secret bootstrap controller and Vault transport layer), not test code. SNO compatibility check is not applicable.
Topology-Aware Scheduling Compatibility ✅ Passed PR modifies only Go source code for secret utilities with no deployment manifests, pod specs, or scheduling constraints. Topology-aware scheduling check not applicable.
Ote Binary Stdout Contract ✅ Passed No stdout contract violations. Both binaries use logrusutil.ComponentInit() for stderr logging. No direct stdout writes in process-level code.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed Check is not applicable. This PR modifies bootstrap commands and Vault transport logic, not Ginkgo e2e tests. The custom check specifically applies only when new Ginkgo e2e tests are added.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci openshift-ci Bot requested review from danilo-gemoli and smg247 May 19, 2026 00:29
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 19, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: hector-vido

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

The pull request process is described 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

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label May 19, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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/ci-secret-bootstrap/main.go`:
- Around line 674-680: User-provided labels parsed from
secretKeys[vaultapi.SecretSyncTargetLabelsKey] can overwrite the seeded
controller label api.DPTPRequesterLabel in the labels map; update the parsing
logic (the block that builds labels from vaultValue in
cmd/ci-secret-bootstrap/main.go) to reject or ignore any entry whose key equals
api.DPTPRequesterLabel so the initially-seeded labels map entry is never
replaced (ensure the same behavior is enforced before updateSecrets is called).
- Around line 675-680: The current Vault label parsing loop can panic on
malformed entries; update the block that handles
secretKeys[vaultapi.SecretSyncTargetLabelsKey] (variables vaultValue and labels)
to robustly parse each label: use strings.SplitN(entry, ":", 2),
strings.TrimSpace on both key and value, validate that you got exactly 2
non-empty parts, and either skip invalid entries or return a contextual error
(with which entry failed) instead of letting label[1] panic; ensure the final
parsed key/value are stored into labels only after trimming and validation.

In `@cmd/vault-subpath-proxy/kv_update_transport.go`:
- Around line 125-126: The branch only updated the regex but you must treat
SecretSyncTargetLabelsKey as a reserved key throughout this transport: update
validateKeysDontConflict to ignore vault.SecretSyncTargetLabelsKey when checking
for claimed keys, change syncSecret so it does not include
vault.SecretSyncTargetLabelsKey in Secret.Data or write it as normal secret
data, and update any cache builder routines that enumerate keys (e.g., functions
building the local cache or mapping keys to clusters) to skip
vault.SecretSyncTargetLabelsKey so it is never persisted or compared in conflict
checks; keep the same logic/guard used for vault.SecretSyncTargetClusterKey for
consistency.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 1b2b4634-8cfc-4261-99af-ce14c9e57856

📥 Commits

Reviewing files that changed from the base of the PR and between e3ac258 and f93da75.

📒 Files selected for processing (3)
  • cmd/ci-secret-bootstrap/main.go
  • cmd/vault-subpath-proxy/kv_update_transport.go
  • pkg/api/vault/vault.go

Comment on lines +674 to +680
labels := map[string]string{api.DPTPRequesterLabel: "ci-secret-bootstrap"}
if vaultValue, ok := secretKeys[vaultapi.SecretSyncTargetLabelsKey]; ok {
if vaultValue != "" {
for _, label := range strings.Split(vaultValue, ",") {
label := strings.Split(label, ":")
labels[strings.Trim(label[0], " ")] = strings.Trim(label[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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep api.DPTPRequesterLabel reserved.

User-supplied labels are applied after the controller label is seeded, so a Vault entry can overwrite api.DPTPRequesterLabel. That breaks the ownership marker used later in updateSecrets and lets external input change controller-managed metadata. Reject or ignore that key when applying custom labels. As per coding guidelines, "Review whether APIs could be abused and ensure proper security measures".

🤖 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/ci-secret-bootstrap/main.go` around lines 674 - 680, User-provided labels
parsed from secretKeys[vaultapi.SecretSyncTargetLabelsKey] can overwrite the
seeded controller label api.DPTPRequesterLabel in the labels map; update the
parsing logic (the block that builds labels from vaultValue in
cmd/ci-secret-bootstrap/main.go) to reject or ignore any entry whose key equals
api.DPTPRequesterLabel so the initially-seeded labels map entry is never
replaced (ensure the same behavior is enforced before updateSecrets is called).

Comment on lines +675 to +680
if vaultValue, ok := secretKeys[vaultapi.SecretSyncTargetLabelsKey]; ok {
if vaultValue != "" {
for _, label := range strings.Split(vaultValue, ",") {
label := strings.Split(label, ":")
labels[strings.Trim(label[0], " ")] = strings.Trim(label[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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Harden the Vault label parser.

A malformed value like foo, foo:bar,, or a whitespace-only entry will panic on label[1]. strings.Split here also discards everything after the first :. Parse with a bounded split, trim both sides, and return a contextual error instead of crashing the bootstrap.

Suggested fix
 			labels := map[string]string{api.DPTPRequesterLabel: "ci-secret-bootstrap"}
 			if vaultValue, ok := secretKeys[vaultapi.SecretSyncTargetLabelsKey]; ok {
 				if vaultValue != "" {
-					for _, label := range strings.Split(vaultValue, ",") {
-						label := strings.Split(label, ":")
-						labels[strings.Trim(label[0], " ")] = strings.Trim(label[1], " ")
+					for _, raw := range strings.Split(vaultValue, ",") {
+						raw = strings.TrimSpace(raw)
+						if raw == "" {
+							continue
+						}
+						parts := strings.SplitN(raw, ":", 2)
+						if len(parts) != 2 {
+							errs = append(errs, fmt.Errorf("secret %s has invalid %s entry %q: expected key: value", secretName.String(), vaultapi.SecretSyncTargetLabelsKey, raw))
+							continue
+						}
+						key := strings.TrimSpace(parts[0])
+						value := strings.TrimSpace(parts[1])
+						if key == "" {
+							errs = append(errs, fmt.Errorf("secret %s has invalid %s entry %q: empty label key", secretName.String(), vaultapi.SecretSyncTargetLabelsKey, raw))
+							continue
+						}
+						labels[key] = value
 					}
 				}
 			}
🤖 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/ci-secret-bootstrap/main.go` around lines 675 - 680, The current Vault
label parsing loop can panic on malformed entries; update the block that handles
secretKeys[vaultapi.SecretSyncTargetLabelsKey] (variables vaultValue and labels)
to robustly parse each label: use strings.SplitN(entry, ":", 2),
strings.TrimSpace on both key and value, validate that you got exactly 2
non-empty parts, and either skip invalid entries or return a contextual error
(with which entry failed) instead of letting label[1] panic; ensure the final
parsed key/value are stored into labels only after trimming and validation.

Comment on lines +125 to 126
if key == vault.SecretSyncTargetClusterKey || key == vault.SecretSyncTargetLabelsKey {
continue
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Treat SecretSyncTargetLabelsKey as reserved everywhere in this transport.

This branch only fixes the regex check. validateKeysDontConflict and syncSecret still treat the new key as normal secret data, so a Vault write can both raise false "key ... is already claimed" conflicts and persist secretsync/target-labels into Secret.Data. Please extend the same reserved-key handling there as well, and keep the cache builders aligned too.

🤖 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/vault-subpath-proxy/kv_update_transport.go` around lines 125 - 126, The
branch only updated the regex but you must treat SecretSyncTargetLabelsKey as a
reserved key throughout this transport: update validateKeysDontConflict to
ignore vault.SecretSyncTargetLabelsKey when checking for claimed keys, change
syncSecret so it does not include vault.SecretSyncTargetLabelsKey in Secret.Data
or write it as normal secret data, and update any cache builder routines that
enumerate keys (e.g., functions building the local cache or mapping keys to
clusters) to skip vault.SecretSyncTargetLabelsKey so it is never persisted or
compared in conflict checks; keep the same logic/guard used for
vault.SecretSyncTargetClusterKey for consistency.

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 19, 2026

@hector-vido: 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.

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant