Skip to content

🐛 fixed stale secret whiteout and SA reference - #147

Merged
stillalearner merged 2 commits into
migtools:mainfrom
stillalearner:fix_484
Jul 27, 2026
Merged

🐛 fixed stale secret whiteout and SA reference#147
stillalearner merged 2 commits into
migtools:mainfrom
stillalearner:fix_484

Conversation

@stillalearner

@stillalearner stillalearner commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Whiteout auto-generated SA token Secrets (kubernetes.io/service-account-token) and OCP dockercfg Secrets (kubernetes.io/dockercfg) by Secret type, regardless of ownerReferences. Also strip the secrets field from
ServiceAccounts to remove dangling references to source-cluster token Secrets.

Problem

When migrating from Kubernetes < 1.24, auto-generated ServiceAccount token Secrets have no ownerReferences. The KubernetesPlugin only whiteouts resources that have ownerReferences, so these Secrets pass through the
entire pipeline and are applied to the target with stale source-cluster credentials (JWT signed by the wrong key, wrong CA cert, wrong SA UID).

On the target:

  • K8s >= 1.24: Secret is created then silently deleted by the token controller (UID mismatch). No error surfaced, but the SA has a dangling secrets reference.
  • K8s < 1.24: Secret persists with invalid credentials. Pods get a JWT token signed by the source cluster's key. All API calls fail with "Unauthorized".

Same issue applies to OCP dockercfg Secrets on older OCP versions where they lack ownerReferences.

Changes

1. Whiteout Secrets by type (getWhiteOuts())

Added a type-based check before the ownerReferences check. Secrets of type kubernetes.io/service-account-token and kubernetes.io/dockercfg are always whiteout-ed. These are cluster-generated credentials that are
never valid on a different cluster. The target's controllers regenerate them automatically.

User-created Secrets (Opaque, kubernetes.io/tls, etc.) are unaffected.

2. Strip SA secrets field (getKubernetesTransforms())

Added a JSONPatch remove /secrets for ServiceAccounts that have a secrets field. This field carries source-specific token Secret names that don't exist on the target. The target cluster's token controller
repopulates it with fresh references.

Migration matrix

Scenario Before After
Old K8s → Old K8s Stale token Secret persists, pods get invalid JWT Fixed — whiteout-ed, target generates fresh one
Old OCP → Old OCP Stale token + dockercfg Secrets persist Fixed — both whiteout-ed, target regenerates
New K8s → New K8s No issue (no token Secret to export) No change
New OCP → New OCP No issue (ownerRef check already works) No change
Old K8s → New K8s Secret silently created and deleted, dangling SA ref Fixed — whiteout-ed, target uses projected tokens
Old OCP → New OCP Same as above + dockercfg Fixed — both whiteout-ed

Fixes: crane#484

Summary by CodeRabbit

  • Bug Fixes
    • Improved Kubernetes resource cleanup by correctly handling service-account-token and dockercfg Secrets.
    • Prevented unrelated Opaque and TLS Secrets from being removed.
    • Removed legacy Secret references from ServiceAccounts when present.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@stillalearner, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 38 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fd522dc7-0747-4fa8-af4c-d704bbf8b3ec

📥 Commits

Reviewing files that changed from the base of the PR and between f0f8579 and 26220d7.

📒 Files selected for processing (2)
  • transform/kubernetes/kubernetes.go
  • transform/kubernetes/kubernetes_test.go
📝 Walkthrough

Walkthrough

The Kubernetes plugin now whiteouts service-account-token and dockercfg Secrets and removes existing secrets fields from ServiceAccounts. Tests cover supported and unsupported Secret types and ServiceAccount patch behavior.

Changes

Kubernetes resource handling

Layer / File(s) Summary
Selected Secret whiteouts
transform/kubernetes/kubernetes.go
Service-account-token and dockercfg Secret resources are marked as whiteout targets before existing ownership and RBAC filtering.
ServiceAccount secret removal and validation
transform/kubernetes/kubernetes.go, transform/kubernetes/kubernetes_test.go
ServiceAccount resources with a secrets array receive a removal patch, while absent fields remain unchanged; tests cover the new Secret and ServiceAccount cases.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related issues

  • migtools/crane#484 — The changes implement the issue’s requested Secret whiteout and ServiceAccount secret-reference handling.

Suggested reviewers: aufi

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main changes: stale Secret whiteout handling and ServiceAccount secret reference cleanup.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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)
transform/kubernetes/kubernetes_test.go (1)

1024-1104: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Cover the DisableWhiteoutOwned override path.

These cases use ownerless Secrets and leave DisableWhiteoutOwned disabled, so they do not lock in the “always whiteout” behavior. Add a case with owner references and DisableWhiteoutOwned: true, expecting IsWhiteOut: true.

🤖 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 `@transform/kubernetes/kubernetes_test.go` around lines 1024 - 1104, Add a
table-driven test case alongside the existing Secret cases, using an owner
reference and setting DisableWhiteoutOwned to true, with the expected
PluginResponse asserting IsWhiteOut: true. Ensure the test exercises the
override path rather than the ownerless-secret behavior covered by the existing
cases.
🤖 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 `@transform/kubernetes/kubernetes_test.go`:
- Around line 1128-1144: Update the table-driven test runner around the
ServiceAccount case to assert that resp.Patches is empty whenever
PatchResponseJson is unspecified or empty. Preserve the existing expected-patch
comparison for cases that provide PatchResponseJson, and ensure
ServiceAccountWithoutSecretsFieldUntouched fails if any patch is emitted.

---

Nitpick comments:
In `@transform/kubernetes/kubernetes_test.go`:
- Around line 1024-1104: Add a table-driven test case alongside the existing
Secret cases, using an owner reference and setting DisableWhiteoutOwned to true,
with the expected PluginResponse asserting IsWhiteOut: true. Ensure the test
exercises the override path rather than the ownerless-secret behavior covered by
the existing cases.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d05b7ab7-506f-4734-9d52-a24985111bf0

📥 Commits

Reviewing files that changed from the base of the PR and between 0e33157 and f0f8579.

📒 Files selected for processing (2)
  • transform/kubernetes/kubernetes.go
  • transform/kubernetes/kubernetes_test.go

Comment thread transform/kubernetes/kubernetes_test.go
@stillalearner

Copy link
Copy Markdown
Contributor Author

Tested with OCP successfully

@aufi aufi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@stillalearner
stillalearner merged commit 8c6ef32 into migtools:main Jul 27, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants