Repository navigation
fix(recipes): delete Key Vault secrets through managed parent vaults - #13342
Conversation
Wait for parent vault deletion instead of sending unsupported ARM secret deletes when both resources are in the same deletion batch. Preserve direct deletion and errors when the vault is retained or unmanaged. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: nicolejms <nicolej@microsoft.com>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
There was a problem hiding this comment.
🟢 Approval recommended
The narrow change preserves deletion waiting and error propagation, with regression coverage and no unresolved findings.
No open issues 🎉
What changed in this PR
Fixes Bicep recipe deletion so Azure Key Vault secrets are deleted through their Radius-managed parent vault when both appear in the same deletion batch.
Changes:
- Skips separate secret DELETE requests while preserving vault completion and error handling.
- Adds regression tests for ownership, scope, parent failures, and retained vaults.
- Documents the deletion rule and unchanged soft-delete retention.
| File | Description |
|---|---|
pkg/recipes/driver/bicep/keyvault_test.go |
Tests parent-vault deletion and excluded cases. |
pkg/recipes/driver/bicep/bicep.go |
Adds narrowly scoped parent-vault matching. |
docs/architecture/extensibility.md |
Documents deletion behavior and limitations. |
Review effort: Balanced
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #13342 +/- ##
==========================================
+ Coverage 60.27% 60.29% +0.01%
==========================================
Files 748 748
Lines 44255 44272 +17
==========================================
+ Hits 26676 26692 +16
- Misses 17579 17580 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
nithyatsu
left a comment
There was a problem hiding this comment.
LGTM, this fixes the Azure Bicep app-delete hang seen in resource-types-contrib (radius-project/resource-types-contrib#396). There, RADIUS.SECURITY/SECRETS|DELETE retried DELETE .../vaults/kv-app-sec-*/secrets/{apikey,username,password} and got 405 DeleteNotSupported every 60 seconds until the 30-minute job timed out (run 39051743295, dynamic-rp.log). The skip applies only to Azure Key Vault secrets whose Radius-managed parent vault is in the same batch, and vault errors are still reported. CI is green.
Notes:
- This doesn't address the Azure Terraform secrets delete failure (#13330), so the resource-types-contrib workaround for that stays.
- I'd still like to see the end-to-end Azure check from the PR description run against an image that includes this change.
- Three advisory comments are inline; none of them block.
Compare parent vaults using the same ARM-form path as Azure resource deletion. Keep non-Azure planes and resource scopes distinct, and clarify that the child secret DELETE is skipped. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: nicolejms <nicolej@microsoft.com>
Radius functional test overviewClick here to see the test run details
Test Status⌛ Building Radius and pushing container images for functional tests... |
<!-- Thank you for contributing to Radius! Please fill out each section below so reviewers have the context they need. Sections marked optional can be removed if they do not apply. --> ## Summary <!-- Provide a concise description of what this PR does. --> Fix the Azure Terraform secret recipe so destroy can run when Radius redacts secret values, with focused regression coverage in CI. - Supply an empty value to keep the destroy configuration valid. Destroy does not write that value. - Reject missing/null data and values on create/update through a lifecycle precondition, preserving valid deployment behavior. - Grant Purge/Recover permissions needed by the Azure provider's secret lifecycle. - Run all eleven input tests through `make test-azure-secret-inputs`, locally and in CI. The target uses a temporary recipe copy so provider downloads and lock files cannot enter the source recipe package. No leftover-resource cleanup, Azure workflow overrides, or scheduled monitoring is included. The Bicep recipe is unchanged. ## Reason for change <!-- Explain why this change is needed. If it addresses a GitHub issue, link it below so it is automatically closed when this PR merges (optional). --> Refs radius-project#400 <!-- issue number (optional) --> The provider requires `value` or `value_wo` even when Terraform evaluates a destroy configuration. Radius supplies null for sensitive values, causing destroy to fail before deletion. Keep this workaround for older Terraform state while radius-project/radius#13330 fixes saved-input handling in the runtime. The separate Bicep HTTP 405 problem needs radius-project/radius#13342, not a recipe rewrite. Neither a secret migration nor a vault URI change is introduced here. The focused tests must run automatically: a green deployment test alone does not cover invalid create/update inputs. The resource-type workflow now installs Terraform 1.16.6 using SHA-pinned `hashicorp/setup-terraform` v3.1.2 and calls the make target without Azure credentials. The README uses that same target rather than initializing Terraform in the packaged source folder. ## How to test <!-- Describe the steps a reviewer can take to verify these changes. --> | Command or check | Result | | --- | --- | | `make test-azure-secret-inputs` | Passed locally and in [current-head CI](https://github.com/radius-project/resource-types-contrib/actions/runs/39321579100/job/118296687907): 11 passed, 0 failed | | Source recipe hashes and generated-file checks before/after the make target | Passed: source unchanged; no `.terraform/` or `.terraform.lock.hcl` left in the recipe folder | | Deliberate Terraform init failure | Passed: the target failed and removed its temporary copy | | `make -n test-azure-secret-inputs \| tr -d '\r' \| shellcheck --shell=bash -` | Passed locally; carriage-return normalization is for Windows make output | | `go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.7 -shellcheck= -pyflakes= .github/workflows/validate-resource-types.yaml` | Passed locally | | `git diff --check` | Passed locally | | `RECIPE_PLATFORM_FILTER=azure make test ENVIRONMENT="$AZURE_ENVIRONMENT_NAME" RECIPE_TYPE=terraform` | Passed live at bb3c7b8: [Azure Terraform job](https://github.com/radius-project/resource-types-contrib/actions/runs/39311104096/job/118261214269), including secret deploy and application delete | Current head is `f9b66e04d3fc2ba96fda50dae387a8a42f5004b1`. Production recipe code and its eleven test cases are unchanged from the passing live Azure revision; this follow-up restores CI execution and corrects the README command. Native mock-provider tests require Terraform 1.7 or later. The separate Bicep runtime problem is not claimed fixed by this PR. ## File change summary <!-- Summarize the change made in each file that was modified. --> | File | Summary of change | | ---- | ----------------- | | `Security/secrets/recipes/azure/terraform/main.tf` | Allow redacted destroy inputs, guard create/update values, and grant secret lifecycle permissions. | | `Security/secrets/recipes/azure/terraform/tests/inputs.tftest.hcl` | Add eleven regression tests for input guards and preserved valid values. | | `.github/build/test.mk` | Add the temporary-copy test target, with failure propagation and cleanup. | | `.github/workflows/validate-resource-types.yaml` | Install pinned Terraform and run the focused tests on PRs. | | `Security/secrets/README.md` | Explain the workaround and document the safe make target. | --------- Signed-off-by: nicolejms <nicolej@microsoft.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Summary
Delete Azure Key Vault secrets through their parent vault when the same Bicep recipe deletion batch contains that Radius-managed vault. Do not send unsupported ARM DELETE requests for those secret IDs. Wait for the vault delete to finish and report its errors.
Keep direct deletion unchanged when the vault is retained, unmanaged, or absent from the batch. Restrict the rule to Azure
Microsoft.KeyVault/vaults/secrets, not extension resources, other child types, or other planes. No HTTP 405 errors are ignored.Reason for change
Refs radius-project/resource-types-contrib#400 and radius-project/resource-types-contrib#401.
The declarative Azure secrets recipe tracks both a vault and its secrets. Azure ARM rejects secret DELETE with
405 DeleteNotSupported; Radius retries those requests even while deleting the vault. The vault delete already removes the active secrets, so separate child DELETE requests make app deletion fail without removing more resources.This fix requires no secret migration, new vault, URI change, deployment script, data-plane credential, or ownership transfer. Azure soft-delete retention remains in effect; nothing is purged. Removing a single tracked secret while keeping its vault is a separate, pre-existing limitation and is not changed here.
How to test
With the repository Go toolchain installed, run
go test ./pkg/recipes/driver/bicep -run 'Test_Bicep_Delete|Test_GetGCOutputResources' -count=1. Expect all tests to pass. The new tests check multiple declarative secret IDs, waiting for parent deletion, parent errors, unmanaged parents, exact scope matching, other planes/types, and retained-vault updates that must still report the direct-delete error.For Azure end-to-end validation, install a control-plane build that contains this commit, deploy the declarative Azure Key Vault secrets recipe, and delete the Radius app. Expect vault deletion to finish without separate ARM secret DELETE retries. Confirm the vault and secrets are not available as active resources. Soft-deleted resources can remain under Azure retention rules. This Azure check was not run locally because no test subscription is available.
Local results:
go test ./pkg/recipes/driver/bicep -run 'KeyVault' -count=25go test ./pkg/recipes/driver/bicep -count=1Test_WriteDockerConfig_ReadsDecodedSecretFromTargetCluster: Windows reports directory mode 0777, but the test expects 0700go test ./pkg/recipes/driver/bicep -skip '^Test_WriteDockerConfig_ReadsDecodedSecretFromTargetCluster$' -count=1go vet ./pkg/recipes/driver/bicepnpm exec --yes --package=markdownlint-cli2@0.23.3 -- markdownlint-cli2 docs\architecture\extensibility.md --config .github\linters\.markdownlint-cli2.yamlnpm exec --yes --package=markdown-table-formatter@1.7.0 -- markdown-table-formatter docs\architecture\extensibility.md --checkThe documented pnpm commands could not start because local pnpm rejected the pinned package-manager resolution. The checks above use the same pinned tool versions through npm. ShellCheck is not applicable: no shell scripts changed.
File change summary
pkg/recipes/driver/bicep/bicep.gopkg/recipes/driver/bicep/keyvault_test.godocs/architecture/extensibility.md