Skip to content

Add a managed identity option to the Container Apps sample - #140

Merged
bryansan-local merged 2 commits into
mainfrom
container-apps-managed-identity
Oct 26, 2026
Merged

bryansan-local merged 2 commits into
mainfrom
container-apps-managed-identity

Conversation

@bryansan-local

Copy link
Copy Markdown
Contributor

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

  • New MANAGED_IDENTITY_TYPE (None by default, SystemAssigned or UserAssigned) for az CLI, Bicep and Terraform. The app's identity gets Storage Blob Data Contributor and replaces the storage-conn secret.
  • The app uses DefaultAzureCredential. validate.sh checks the identity and the role, and cleanup.sh deletes the user-assigned identity.
  • run-samples.sh runs the new variants.

Tests

  • Emulator: all nine deployments (az CLI, Bicep and Terraform, in each of the three modes) pass validate.sh. With LS_AZURE_ENFORCE_RBAC=1, removing the role makes the app's write fail.
  • Real Azure: az CLI SystemAssigned and UserAssigned, Terraform SystemAssigned and Bicep UserAssigned pass. The other variants are pending, since the subscription is at its limit of 50 Container App Environments.

Part of SMF-936

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Real-Azure verification remains incomplete for Bicep system-assigned and Terraform user-assigned deployments, warranting human review of provisioning and storage authorization.

No open issues 🎉

Review effort: Balanced

@paolosalvatori paolosalvatori left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.sh L281, L299: Round-trip retry gives up before the documented role propagation time
  • scripts/validate.sh L169: Role check resolves the principal through Microsoft Graph
  • run-samples.sh L84, L111: Terraform UserAssigned and Bicep SystemAssigned never run in CI
  • scripts/README.md L42: "No secret" is not true in managed-identity mode
  • terraform/main.tf L73, L211: Role name literal is repeated instead of kept in locals
  • src/blob_storage_client.py L60: from_env docstring 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.md
  • bicep/README.md
  • bicep/deploy.sh
  • bicep/main.bicep (builds and lints clean; the explicit dependsOn is justified, since nothing references the user-assigned role assignment by property)
  • scripts/cleanup.sh
  • scripts/deploy.sh (no findings of its own; its L358-359 comment shares the README wording above)
  • src/app.py
  • src/requirements.txt (azure-identity==1.25.3 was published 2026-03-13 and needs Python >= 3.9; the image is 3.12)
  • terraform/README.md
  • terraform/deploy.sh
  • terraform/outputs.tf
  • terraform/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.

Comment thread samples/container-apps-blob-storage/python/scripts/validate.sh Outdated
Comment thread samples/container-apps-blob-storage/python/scripts/validate.sh Outdated
Comment thread run-samples.sh
Comment thread samples/container-apps-blob-storage/python/scripts/README.md Outdated
Comment thread samples/container-apps-blob-storage/python/terraform/main.tf Outdated

This branch was previously deployed

1 inactive deployment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants