fix(oracle): return NoSecretErr on a missing secret so deletionPolicy applies - #6830
fix(oracle): return NoSecretErr on a missing secret so deletionPolicy applies#6830somaz94 wants to merge 2 commits into
Conversation
… applies Signed-off-by: somaz <genius5711@gmail.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
WalkthroughOracle Vault retrieval now converts OCI 404 service errors into Possibly related issues
Possibly related PRs
Merge Risk: ⚪ Minimal · up to The PR makes missing Oracle secrets honor the configured deletion policy while preserving existing handling for other errors. No actionable merge-blocking risk remains after normal checks and review. 🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
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. Comment |
|
evrardj-roche
left a comment
There was a problem hiding this comment.
- I have not tested this on Oracle, someone else must approve.
- The title is misleading: it should be at least
fix(oracle)!:to highlight the breaking change. - I am not fond (no pun intended) of doing this breaking change for a provider who has decided to not clearly distinguish the two cases (not authorized/not found). If no distinction, why we consider all not authorized as not found?
| OCI answers with `NotAuthorizedOrNotFound` both when a secret does not exist and | ||
| when the caller is not allowed to read it, and the two cannot be told apart from | ||
| outside. Revoking read access on a secret therefore looks exactly like deleting it, | ||
| and with `deletionPolicy: Delete` the Kubernetes Secret is removed. Use the default |
There was a problem hiding this comment.
losing secrets on policy change is harsh, but fair.
This warning is more than welcomed. I would also mention deletionPolicy: Merge here and insist on the deletion:
| and with `deletionPolicy: Delete` the Kubernetes Secret is removed. Use the default | |
| and with `deletionPolicy: Delete` or `deletionPolicy: Merge` the Kubernetes Secrets WILL BE DELETED. Use the |
| if !matches || summary.TimeOfDeletion != nil { | ||
| continue | ||
| } | ||
| secret, err := vms.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{ |
There was a problem hiding this comment.
This will get impacted by the change. One missing member will return nil, instead of the secretMap.



Problem Statement
The Oracle provider returns the sanitised OCI SDK error when a secret is missing in the vault, not
esv1.NoSecretErr. The ExternalSecret controller only appliesspec.target.deletionPolicywhen the read error satisfieserrors.Is(err, esv1.NoSecretErr), so deleting a secret in OCI Vault never propagates to the Kubernetes Secret, even though the support matrix advertisesDeletionPolicy Merge/Deletefor Oracle.Related Issue
Fixes #6572
Proposed Changes
GetSecretnow returnsesv1.NoSecretErrwhen OCI answers 404, and keeps returning the sanitised error for anything else. The check lives in a newisSecretNotFoundErrhelper that assertscommon.ServiceErrorrather thancommon.ServiceErrorRichInfo, sinceServiceErroris the interface that declaresGetHTTPStatusCodeand a plain service error carries no rich info.getSecretBundleCodenow calls that same helper instead of repeating the assertion inline. That part is pure de-duplication:common.IsServiceErroris the same plain type assertion the inlined code was already doing (it is noterrors.As), so the PushSecret path is behaviourally unchanged.Dropped the redundant
sanitizeOCISDKErrinGetSecretMapas you suggested. It was a no-op in practice:GetSecretalready sanitises, and a sanitised error is a plainfmt.Errorfthat never satisfies theServiceErrorRichInfoassertion.On the trade-off you raised: OCI returns
NotAuthorizedOrNotFoundfor both "missing" and "not permitted", so mapping 404 makes a revoked IAM policy look identical to a deletion, and underdeletionPolicy: Deletethat removes a live Secret. I mapped it anyway, as you leaned, and documented the risk in two places: theGetSecretdoc comment, and a new "Deletion policy" section indocs/provider/oracle-vault.mdthat points at theRetaindefault for anyone who would rather keep the Secret when access is lost.Two things I left out on purpose. Happy to fold either one into this PR if you would rather have them here:
sanitizeOCISDKErrstill assertsServiceErrorRichInfo, so a plain non-rich service error passes through unsanitised. That is the separate bug your note points at, and fixing it also changes error text on the PushSecret, DeleteSecret, SecretExists and GetAllSecrets paths.GetSecretstill returnserrMissingKeywhenref.Propertyis absent from a secret that does exist. A missing field is not a missing secret, and mapping it would delete a Secret over a mistyped property.Format
fix(oracle): return NoSecretErr on a missing secret so deletionPolicy appliesAI Assistance disclosure
Did you use an script, LLM, or AI assisted development tool for this contribution?
AI assistance used: Yes
If yes provide details:
Tool(s) used: Claude Code (Opus 5)
Purpose of assistance: tracing the path from
GetSecretto the controller'sdeletionPolicygate, locating the in-repo precedents (the existing 404 check ingetSecretBundleCode, theNoSecretErrorshape used by the beyondtrust provider, and thefake.ServiceErrorstub already present in the oracle test fake), and drafting the two tests and the docs section.Parts of the contribution affected: the provider change, the two new test functions, and the docs section.
Human validation performed: ran
make check-diffon the committed tree. That runsmake reviewable(generate, docs, manifests, helm generate/schema/docs, lint, license check, helm tests, CRD snapshot tests, tf fmt) and then verifies the branch is clean, and it passes: golangci-lint reports 0 issues across every module includingproviders/v1/oracle, helm tests 62 passed, CRD snapshot tests 20 passed, and no generated file drifted.make testpasses too, 90 packages ok, withproviders/v1/oracleat 62.2% statement coverage. I also confirmed the new tests actually catch the bug rather than passing vacuously: neutralisingisSecretNotFoundErrmakes bothTestOracleVaultGetSecretNotFoundandTestIsSecretNotFoundErrfail, and they pass again once it is restored. Not exercised against a live OCI Vault, so the last box below is left unchecked.Checklist
git commit --signoffmake testmake reviewable