fix(secret): resolve remaining secrets when one getSecretValues value cannot be decrypted - #19363
Open
yjyspree wants to merge 6 commits into
Open
Conversation
… cannot be decrypted Previously a single undecryptable secret value (e.g. encrypted with a different SECRET_SERVICE_ENCRYPTION_KEY after a DB migration, or corrupted Base64) failed the entire getSecretValues batch, so every other secret referenced by the same ingestion recipe also resolved to an empty string and runs failed with misleading downstream auth errors. Catch decryption failures per secret: log an error naming the failing secret with remediation guidance and omit only that secret from the response, letting healthy secrets in the batch keep resolving. Fixes datahub-project#19362 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
|
Linear: CAT-3036 Thanks for your contribution! We have created an internal ticket to track this PR. A member of the core DataHub team will be assigned to review it within the next few business days - you will get a follow-up comment once a reviewer is assigned. |
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 2 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Bundle ReportBundle size has no change ✅ |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Covers the aspect == null branch flagged by codecov: an entity returned without the dataHubSecretValue aspect is omitted while the rest of the batch still resolves. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…yptable Review follow-ups: - A batch where every stored value fails decryption points at a systemic problem (typically a SECRET_SERVICE_ENCRYPTION_KEY change) rather than one bad secret. Throw IllegalStateException naming the failed secrets instead of returning an empty list that reads as "no secrets exist". Partial failures still resolve the healthy secrets. - Log the decryption exception itself instead of e.getMessage(), which only carried the generic wrapper text; the actual cause (bad Base64, GCM tag mismatch) lives in the cause chain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #19362
Problem
GetSecretValuesResolverdecrypts all requested secrets inside a single stream wrapped in one try/catch. A single undecryptable stored value — e.g. a secret encrypted under a previousSECRET_SERVICE_ENCRYPTION_KEYbefore a DB migration, or corrupted Base64 — fails the entiregetSecretValuesbatch.For managed ingestion this means every secret referenced by the recipe (including perfectly healthy ones) resolves to an empty string, and the run fails with a misleading downstream auth error (
OAuthError: invalid_client,Access denied ... (using password: NO)) that never mentions secrets. Deleting and re-creating the suspected secret doesn't help while any other secret in the same recipe is still undecryptable.Change
GetSecretValuesResolver: log an error naming the failing secret (with guidance that the value is likely encrypted with a different key and should be re-created) and omit only that secret from the response.Secret 'X' not found in secret stores or environment, using empty string) then points at the actual broken secret.IllegalStateExceptionlisting the failed secrets, so a systemic issue (e.g. a rotatedSECRET_SERVICE_ENCRYPTION_KEY) surfaces loudly instead of returning an empty list.Before / after
Before — the executor log never mentions secrets; the only visible symptom is a downstream auth error:
After — GMS names the broken secret and how to fix it, and the executor's per-secret warning identifies it on the ingestion side:
Healthy secrets in the same recipe keep working. When every stored value in the batch is undecryptable, the call fails loudly instead:
Testing
testGetPartialDecryptionFailure: a batch with one healthy and one undecryptable secret returns the healthy secret and does not throw.GetSecretValuesResolverTestcases pass.SECRET_SERVICE_ENCRYPTION_KEY: the executor-side log lines quoted above are taken from that environment's execution reports.SECRET_SERVICE_ENCRYPTION_KEYand restarted GMS, re-created one secret under the new key. The healthy secret keeps resolving while the broken one is omitted with the GMS error log naming it; when both are broken, the call fails loudly with the secret names instead of returning an empty list.Checklist