Skip to content

WIP: kms: reconcile sidecar containers and volumes to match encryption config - #2334

Open
bertinatto wants to merge 3 commits into
openshift:masterfrom
bertinatto:kms-plugin-lifecycle-postcondition-2
Open

WIP: kms: reconcile sidecar containers and volumes to match encryption config#2334
bertinatto wants to merge 3 commits into
openshift:masterfrom
bertinatto:kms-plugin-lifecycle-postcondition-2

Conversation

@bertinatto

@bertinatto bertinatto commented Jun 25, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Enhanced kube-apiserver static pod KMS sidecar handling, including the ability to customize which on-disk encryption-config Secret is referenced in static-pod mode.
  • Bug Fixes

    • Improved idempotent reconciliation by pruning previously injected KMS-managed init containers and volumes, and refreshing static-pod socket mounts before reapplying configuration.
    • More reliable updates to the KMS health-reporter sidecar to ensure correct container wiring.
  • Tests

    • Added and expanded tests to validate static-pod reconciliation and cleanup behavior.

@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jun 25, 2026
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The KMS plugin lifecycle now removes managed static-pod resources before rebuilding the sidecar, supports alternate disk Secret naming, and uses the shared health-reporter container name constant. Tests cover stale-provider cleanup and complete KMS removal.

Changes

KMS static-pod reconciliation

Layer / File(s) Summary
Builder configuration
pkg/operator/encryption/kms/pluginlifecycle/builder.go
The builder accepts an alternate disk Secret name for static-pod reference-data paths and uses kmsHealthReporterContainerName for the health-reporter container.
Static-pod cleanup and rebuild
pkg/operator/encryption/kms/pluginlifecycle/sidecar.go
The new reconciler removes KMS-managed init containers, volumes, and socket mounts, then rebuilds the desired configuration while preserving feature-gate and Secret checks.
Reconciliation validation
pkg/operator/encryption/kms/pluginlifecycle/sidecar_test.go
Tests cover stale-provider pruning and removal of all KMS resources when no KMS plugins are configured.

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

Suggested reviewers: ardaguclu, p0lyn0mial

Sequence Diagram(s)

sequenceDiagram
  participant EnsureKMSPluginSidecarInStaticPodSpec
  participant PodSpec
  participant KMSPluginBuilder
  EnsureKMSPluginSidecarInStaticPodSpec->>PodSpec: remove KMS-managed resources
  EnsureKMSPluginSidecarInStaticPodSpec->>KMSPluginBuilder: configure disk Secret and sidecar
  KMSPluginBuilder->>PodSpec: apply desired containers, volumes, and mounts
Loading
🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (14 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 main change: reconciling KMS sidecar containers and volumes with the encryption config.
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 new test titles are static table-driven names; no timestamps, generated IDs, or other dynamic values appear in titles.
Test Structure And Quality ✅ Passed The new unit test uses table-driven subtests, local fixture helpers, no cluster interactions, and matches existing test style in this package.
Microshift Test Compatibility ✅ Passed The added test is a plain Go unit test using fake clients and no Ginkgo/e2e cluster APIs.
Single Node Openshift (Sno) Test Compatibility ✅ Passed PASS: The added test is a plain testing.T unit test in sidecar_test.go, with no Ginkgo DSL or SNO/multi-node assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed Changes only reconcile KMS sidecars/volumes and a secret-path override; no affinity, nodeSelector, toleration, spread, or replica logic was added.
Ote Binary Stdout Contract ✅ Passed No process-level hooks or stdout writes were added; the touched code is library/test-only and sidecar_test.go has no TestMain/init/Suite setup.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the new coverage is a unit test using fake clients and static pod specs, with no IPv4-only or external connectivity assumptions.
No-Weak-Crypto ✅ Passed Touched code only reconciles KMS sidecars/volumes; no MD5/SHA1/DES/RC4/3DES/Blowfish/ECB, custom crypto, or secret/token comparisons were added.
Container-Privileges ✅ Passed No privileged flags were added; sidecars keep allowPrivilegeEscalation=false, drop ALL caps, and root UID is explicitly justified for static-pod resource access.
No-Sensitive-Data-In-Logs ✅ Passed No new logs expose secrets or PII; touched code only logs secret/resource names at debug level and no sensitive values.
✨ 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 requested review from ardaguclu and p0lyn0mial June 25, 2026 16:55
@openshift-ci

openshift-ci Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: bertinatto

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 Jun 25, 2026
@bertinatto
bertinatto force-pushed the kms-plugin-lifecycle-postcondition-2 branch from c573895 to 049d9ac Compare July 7, 2026 18:04

@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: 1

🧹 Nitpick comments (1)
pkg/operator/encryption/kms/pluginlifecycle/sidecar_test.go (1)

614-827: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Solid coverage for pruning behavior; consider adding a disabled-feature-gate subtest.

The two scenarios (stale provider pruned, full removal) validate the filtering logic well. Given the doc/behavior mismatch flagged in sidecar.go (removal happening even when the feature gate is disabled), a subtest asserting the podSpec is left untouched when FeatureGateKMSEncryption is disabled would catch regressions here.

🤖 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/operator/encryption/kms/pluginlifecycle/sidecar_test.go` around lines 614
- 827, Add a new subtest in TestEnsureKMSPluginSidecarInStaticPodSpec that
covers FeatureGateKMSEncryption being disabled, using
EnsureKMSPluginSidecarInStaticPodSpec with a hardcoded feature gate access that
omits the gate. The test should verify the input PodSpec is left unchanged,
unlike the current pruning cases, so the behavior around disabled gates is
covered and regression-proof.
🤖 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 `@pkg/operator/encryption/kms/pluginlifecycle/sidecar.go`:
- Around line 83-93: Ensure EnsureKMSPluginSidecarInStaticPodSpec does not
mutate podSpec before confirming the KMS sidecar should be reconciled. Move or
duplicate the same feature-gate and encryption-config existence checks used by
AddKMSPluginSidecarToStaticPodSpec so removeAllKMSManagedResources only runs
when those preconditions pass, and avoid leaving podSpec partially stripped on
any error path. If needed, extract the shared guard logic into a helper used by
both EnsureKMSPluginSidecarInStaticPodSpec and
AddKMSPluginSidecarToStaticPodSpec to keep the behavior consistent.

---

Nitpick comments:
In `@pkg/operator/encryption/kms/pluginlifecycle/sidecar_test.go`:
- Around line 614-827: Add a new subtest in
TestEnsureKMSPluginSidecarInStaticPodSpec that covers FeatureGateKMSEncryption
being disabled, using EnsureKMSPluginSidecarInStaticPodSpec with a hardcoded
feature gate access that omits the gate. The test should verify the input
PodSpec is left unchanged, unlike the current pruning cases, so the behavior
around disabled gates is covered and regression-proof.
🪄 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: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: bf748370-6b95-4e25-9e43-dfd8d893e261

📥 Commits

Reviewing files that changed from the base of the PR and between c573895 and 049d9ac.

📒 Files selected for processing (3)
  • pkg/operator/encryption/kms/pluginlifecycle/builder.go
  • pkg/operator/encryption/kms/pluginlifecycle/sidecar.go
  • pkg/operator/encryption/kms/pluginlifecycle/sidecar_test.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/operator/encryption/kms/pluginlifecycle/builder.go

Comment on lines +83 to +93
// EnsureKMSPluginSidecarInStaticPodSpec reconciles KMS plugin sidecar containers in a kube-apiserver static pod spec.
// It removes all KMS-managed resources (sidecars, volumes, volume mounts) and then re-adds exactly what the
// current encryption config requires, ensuring stale resources from a previous configuration are pruned.
//
// It is a no-op when the KMSEncryption feature gate is not enabled or the encryption-config secret does not exist.
// The secretClient should be uncached to avoid injecting sidecars based on a stale encryption configuration.
func EnsureKMSPluginSidecarInStaticPodSpec(ctx context.Context, podSpec *corev1.PodSpec, containerName string, encryptionConfigNamespace string, encryptionConfigSecretName string, operatorBinary string, operatorImage string, secretClient corev1client.SecretsGetter, featureGateAccessor featuregates.FeatureGateAccess) error {
removeAllKMSManagedResources(podSpec, containerName)
return AddKMSPluginSidecarToStaticPodSpec(ctx, podSpec, containerName, encryptionConfigNamespace, encryptionConfigSecretName, operatorBinary, operatorImage, secretClient, featureGateAccessor)
}

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

Doc comment contradicts actual behavior; destructive removal happens even on no-op/error paths.

The comment says this is "a no-op when the KMSEncryption feature gate is not enabled or the encryption-config secret does not exist," but removeAllKMSManagedResources (Line 90) runs unconditionally before AddKMSPluginSidecarToStaticPodSpec checks the feature gate (Lines 57-66) or config presence (Lines 72-74). So when those "no-op" conditions are true, the function still strips all KMS-managed init containers, volumes, and socket mounts from the podSpec — it's not a no-op at all.

Worse, if AddKMSPluginSidecarToStaticPodSpec returns an error (feature-gate fetch failure Line 61-63, or fetchEncryptionConfig error Line 69-71), the podSpec has already been destructively mutated by the time the error propagates to the caller, leaving it in a half-cleaned state that may still get applied.

🩹 Possible fix: gate the removal on the same preconditions
 func EnsureKMSPluginSidecarInStaticPodSpec(ctx context.Context, podSpec *corev1.PodSpec, containerName string, encryptionConfigNamespace string, encryptionConfigSecretName string, operatorBinary string, operatorImage string, secretClient corev1client.SecretsGetter, featureGateAccessor featuregates.FeatureGateAccess) error {
-	removeAllKMSManagedResources(podSpec, containerName)
-	return AddKMSPluginSidecarToStaticPodSpec(ctx, podSpec, containerName, encryptionConfigNamespace, encryptionConfigSecretName, operatorBinary, operatorImage, secretClient, featureGateAccessor)
+	if !featureGateAccessor.AreInitialFeatureGatesObserved() {
+		return nil
+	}
+	featureGates, err := featureGateAccessor.CurrentFeatureGates()
+	if err != nil {
+		return fmt.Errorf("failed to get feature gates: %w", err)
+	}
+	if !featureGates.Enabled(features.FeatureGateKMSEncryption) {
+		return nil
+	}
+
+	removeAllKMSManagedResources(podSpec, containerName)
+	return AddKMSPluginSidecarToStaticPodSpec(ctx, podSpec, containerName, encryptionConfigNamespace, encryptionConfigSecretName, operatorBinary, operatorImage, secretClient, featureGateAccessor)
 }

This duplicates the guard rather than restructuring AddKMSPluginSidecarToStaticPodSpec; consider extracting the guard checks into a shared helper instead.

🤖 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/operator/encryption/kms/pluginlifecycle/sidecar.go` around lines 83 - 93,
Ensure EnsureKMSPluginSidecarInStaticPodSpec does not mutate podSpec before
confirming the KMS sidecar should be reconciled. Move or duplicate the same
feature-gate and encryption-config existence checks used by
AddKMSPluginSidecarToStaticPodSpec so removeAllKMSManagedResources only runs
when those preconditions pass, and avoid leaving podSpec partially stripped on
any error path. If needed, extract the shared guard logic into a helper used by
both EnsureKMSPluginSidecarInStaticPodSpec and
AddKMSPluginSidecarToStaticPodSpec to keep the behavior consistent.

@bertinatto
bertinatto force-pushed the kms-plugin-lifecycle-postcondition-2 branch 2 times, most recently from 8a69ee8 to 4210bf5 Compare July 10, 2026 18:39
The existing Add* functions use upsert semantics, which leaves orphaned
KMS sidecar containers, health reporters, and volumes when a provider is
removed from the encryption configuration. Add
EnsureKMSPluginSidecarInStaticPodSpec, which removes all KMS-managed
resources before re-adding exactly what the current config requires.
@bertinatto
bertinatto force-pushed the kms-plugin-lifecycle-postcondition-2 branch from 4210bf5 to fed6abe Compare July 13, 2026 16:08
@bertinatto
bertinatto force-pushed the kms-plugin-lifecycle-postcondition-2 branch from 507ef12 to 91ba23e Compare July 14, 2026 00:29
@openshift-ci

openshift-ci Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

@bertinatto: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/unit 91ba23e link true /test unit

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. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant