Repository navigation
Add a managed identity option to the Container Apps sample - #140
Conversation
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
paolosalvatori
left a comment
There was a problem hiding this comment.
Paths are under samples/container-apps-blob-storage/python/ unless shown in full.
1. Rules applied
All rule files below were read in full. They are path-scoped to localstack-pro-azure/**, and this repo has no CLAUDE.md or .claude/rules of its own, so they are applied here by analogy and only where they carry over to sample code; the emulator-only invariants (stores, fill(), parity markers) do not apply.
localstack-pro-azure/CLAUDE.md.claude/rules/azure/common/:coding-style.md,hooks.md,patterns.md,security.md,testing.md.claude/rules/azure/python/:cloud-pipeline.md,coding-style.md,hooks.md,patterns.md,security.md,testing.md.claude/rules/azure/bicep/:coding-style.md,hooks.md,patterns.md,security.md,testing.md.claude/rules/azure/terraform/:coding-style.md,hooks.md,patterns.md,security.md,testing.md.claude/rules/azure/scripts/:coding-style.md,hooks.md,patterns.md,security.md,testing.md.claude/rules/azure/emulator/: none applies; no file covers Container Apps, Storage or Managed Identity, and the PR changes no emulator code.
None missing or unreadable.
2. Existing comments
Copilot posted two quota notices (no review) and an overview with no inline issues. The overview flagged Bicep SystemAssigned and Terraform UserAssigned as not yet verified on real Azure, as the PR description says too. I traced both paths (identity wiring, principalType, the role-before-app ordering for user-assigned, the post-app grant for system-assigned) and found no defect; the CI side of the same two variants is the run-samples.sh finding. No human comments.
3. Findings
Six LOW findings, each inline with a fix:
scripts/validate.shL281, L299: Round-trip retry gives up before the documented role propagation timescripts/validate.shL169: Role check resolves the principal through Microsoft Graphrun-samples.shL84, L111: TerraformUserAssignedand BicepSystemAssignednever run in CIscripts/README.mdL42: "No secret" is not true in managed-identity modeterraform/main.tfL73, L211: Role name literal is repeated instead of kept inlocalssrc/blob_storage_client.pyL60:from_envdocstring still says the connection string is required
Out of scope (pre-existing): scripts/deploy.sh L151-160 tests $ENVIRONMENT, which neither the script nor the workflow sets, so the HTTPS-to-HTTP downgrade is dead code and the container already gets the HTTPS endpoint. Its comment ("containers don't have the LS TLS cert") now contradicts the managed-identity path at L356-359, which relies on HTTPS from inside the container and passes CI. Worth deleting in a follow-up, together with the same branch in samples/aci-blob-storage/python/scripts/deploy.sh:117.
4. Clean files
README.mdbicep/README.mdbicep/deploy.shbicep/main.bicep(builds and lints clean; the explicitdependsOnis justified, since nothing references the user-assigned role assignment by property)scripts/cleanup.shscripts/deploy.sh(no findings of its own; its L358-359 comment shares the README wording above)src/app.pysrc/requirements.txt(azure-identity==1.25.3was published 2026-03-13 and needs Python >= 3.9; the image is 3.12)terraform/README.mdterraform/deploy.shterraform/outputs.tfterraform/variables.tf
5. Verdict
Approve. The three identity modes are wired consistently across az CLI, Bicep and Terraform, and every new managed-identity CI job passed on its first attempt. Checked against the sources and correct: the Storage Blob Data Contributor id (ba92f5b4-2d11-453d-a403-e96b0029c9fe), the IDENTITY_ENDPOINT/IDENTITY_HEADER contract, DefaultAzureCredential picking the user-assigned identity from AZURE_CLIENT_ID, and the az CLI's idempotent role assignment create (so a re-run does not trip over the existing assignment). None of the six LOWs blocks; the two validate.sh ones matter most for runs against real Azure.
…y and update related documentation
Motivation
The Container Apps sample only reached Blob Storage with a connection string secret. Container apps can now run with a managed identity on the emulator, which is the usual way for an app on ACA to reach Azure services without secrets.
Changes
MANAGED_IDENTITY_TYPE(Noneby default,SystemAssignedorUserAssigned) for az CLI, Bicep and Terraform. The app's identity getsStorage Blob Data Contributorand replaces thestorage-connsecret.DefaultAzureCredential.validate.shchecks the identity and the role, andcleanup.shdeletes the user-assigned identity.run-samples.shruns the new variants.Tests
validate.sh. WithLS_AZURE_ENFORCE_RBAC=1, removing the role makes the app's write fail.SystemAssignedandUserAssigned, TerraformSystemAssignedand BicepUserAssignedpass. The other variants are pending, since the subscription is at its limit of 50 Container App Environments.Part of SMF-936