Repository navigation
🤖 fix: a CoderProvisioner deletes keys at earlier targets while the current target fails its checks - #431
Conversation
…rrent target is not ready (#416) Change-Id: Id023e1f2a68b9c6bd89a56688f7f746c79ae4f37 Signed-off-by: Thomas Kosiewski <tk@coder.com>
…rent target fails its checks (#416) Change-Id: I6e4a5a65a893bba9aaf5ea07a96bae54b72ba0c9 Signed-off-by: Thomas Kosiewski <tk@coder.com>
…es (#416) Change-Id: I4d64a8d50d711e7b0e88c6dec948126e54d0db62 Signed-off-by: Thomas Kosiewski <tk@coder.com>
… changed (#416) Change-Id: Ib83d7afcd7fc9a5800d42fec3197ab3f7900f05d Signed-off-by: Thomas Kosiewski <tk@coder.com>
…dentials (#416) Change-Id: I433401d5e847d6251ed48ae6592d28b7d5e4650c Signed-off-by: Thomas Kosiewski <tk@coder.com>
Change-Id: Iee9b78897e948fc5e62bda77fd7f992ce1d4421b Signed-off-by: Thomas Kosiewski <tk@coder.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1554c176d1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…e retry interval runs (#416) Change-Id: I6c50d1eabcdf1ee836f2bdcf86fd52c6584d1832 Signed-off-by: Thomas Kosiewski <tk@coder.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. 🚀 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex security review |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
Summary
A
CoderProvisionernow deletes the keys thatstatus.pendingKeysrecords at earlier targets even while the current target fails its operator-token or entitlement checks. Each key is deleted by its recorded ID, at its recorded Coder URL, with the operator token of its own UID-bound control plane. A failed credential check still sends nothing to Coder. Entries withunpublished: trueand the key in the Secret still wait for the current target.Fixes #416
Background
The user goal for this run: fix the follow-up issues from the last run and land them on
main.Since #413, the cleanup of earlier-target keys ran only after the current target passed every check (control plane fetch, credential checks, operator token, entitlement). While the current target failed one of them, every retry returned before the cleanup, so a key at an older endpoint stayed valid in Coder. #416 records why #413 left it, and proposes this direction.
Implementation
All changes are in
internal/controller/coderprovisioner_controller.go.revokeEarlierTargetKeysruns right after the credential checks and before the operator-token and entitlement checks of the current target. It tries everystatus.pendingKeysrecord outside the target slot that is not in use. A record is in use when it isunpublished: trueor namesstatus.provisionerKeyID. Deletes go through the existingrevokeKey, so 🤖 CoderProvisioner: bind each key record's operator token to the control plane UID #417/🤖 fix: a CoderProvisioner replaces only keys it recorded and binds key records to the control plane UID #420 token binding and 🤖 fix: a CoderProvisioner keeps every key record with IDs until Coder confirms its key gone #425 record retention are unchanged. When it drops a record, it writes status at once.sync.Map. After a try leaves a record that Coder did not confirm gone, the next try waitsprovisionerPendingKeyRetryInterval(2 minutes, the existing pending-key requeue). The operator-token wait requeues every 15 s, so without this a dead old endpoint got a request every 15 s.keptKeyReport). Records that a pass holds back are reported without a Coder request: a changed control plane from the Kubernetes read, an ID-less record with the note "the operator checks Coder for it at the next key replacement". The replacement pass merges its reports with the early pass reports, so neither pass hides the other's entries. While the throttle runs, the merge uses the reports of the last try, so a replacement that drops a reported record also drops its report.docs/tutorials/deploy-coderprovisioner.mddescribes the new behavior.Validation
TestCoderProvisionerKey_EarlierTargetRevokedWhileTargetNotReady(key A at control plane A, rotation to B whose delete of A failed, then a move to C):main(commit b402b4b alone) these fail withkey A must be deleted at A with the operator token of A(actual: no deletes).mainthe not-ready case fails with 0 tries.TestCoderProvisionerKey_EarlierTargetReportsBesideUnpublishedKey: beside a held-back unpublished record,ControlPlaneChangedKeyKeptnames a recreated control plane (published and unpublished), andUnverifiedKeyKeptdrops an ID-less record once Coder has no key with its name.record.Unpublishedfrom the in-use rule fails the unpublished case andTestCoderProvisionerKey_RevertAfterFailedRotation. Removing the throttle store fails the retry case. Letting the replacement pass retry early-pass records fails the ready-target case. Skipping the held-back control plane check fails the report test.TestCoderProvisionerKey_IDLessRecordKeepsOtherProvisionersKeynow elapses the retry interval (ElapseEarlierKeyRetryIntervalinexport_test.go) before it expects a retry right after a failed lookup.make verify-vendor,make test,make build,make lint,make test-integration,make docs-check.Risks
main.main, without the throttle. A rotation that keeps failing retries them with controller-runtime's error backoff, as before.Generated with
xum• Model:anthropic:claude-opus-5-5• Thinking:high