Create a Key Vault, populate it with the .env secret as a backup/audit snapshot, then apply the SFI network lockdown. The Container App does NOT read this secret at runtime — the .env contents are passed inline to the Container App via the Bicep `envFileContents` @secure() para
(
*,
resource_group: str,
location: str,
vault_name: str,
env_content: str,
tags: list[str] | None = None,
)
| 613 | |
| 614 | |
| 615 | def create_key_vault( |
| 616 | *, |
| 617 | resource_group: str, |
| 618 | location: str, |
| 619 | vault_name: str, |
| 620 | env_content: str, |
| 621 | tags: list[str] | None = None, |
| 622 | ) -> str: |
| 623 | """ |
| 624 | Create a Key Vault, populate it with the .env secret as a backup/audit |
| 625 | snapshot, then apply the SFI network lockdown. |
| 626 | |
| 627 | The Container App does NOT read this secret at runtime — the .env contents |
| 628 | are passed inline to the Container App via the Bicep `envFileContents` |
| 629 | @secure() parameter. Azure Container Apps is not on Key Vault's |
| 630 | "trusted services" list, so a locked-down KV would block runtime secret |
| 631 | references. By passing the secret inline, we keep the runtime path |
| 632 | independent of KV network access. |
| 633 | |
| 634 | The vault still receives the .env content as `env-global` to: |
| 635 | - Provide a backup snapshot if the Container App is recreated. |
| 636 | - Preserve the audit trail for the deployed configuration. |
| 637 | |
| 638 | The vault is created with public network access enabled so that the |
| 639 | deployer (running from a corp network or dev container) can write the |
| 640 | initial secret. After the secret is uploaded, the vault is locked down |
| 641 | to publicNetworkAccess=Disabled + defaultAction=Deny + bypass=AzureServices |
| 642 | to satisfy the S360 / NS221 Secure PaaS alert. |
| 643 | |
| 644 | Args: |
| 645 | resource_group (str): The resource group name. |
| 646 | location (str): The Azure region. |
| 647 | vault_name (str): The Key Vault name. |
| 648 | env_content (str): The prepared .env content to upload (with SQL connection string injected). |
| 649 | tags (list[str] | None): Tags in 'Key=Value' format. |
| 650 | |
| 651 | Returns: |
| 652 | str: The Key Vault resource ID. |
| 653 | """ |
| 654 | logger.info("Creating Key Vault: %s", vault_name) |
| 655 | kv_cmd = [ |
| 656 | "keyvault", |
| 657 | "create", |
| 658 | "--name", |
| 659 | vault_name, |
| 660 | "--resource-group", |
| 661 | resource_group, |
| 662 | "--location", |
| 663 | location, |
| 664 | "--enable-rbac-authorization", |
| 665 | "true", |
| 666 | "--enable-purge-protection", |
| 667 | "true", |
| 668 | ] |
| 669 | if tags: |
| 670 | kv_cmd += ["--tags"] + tags |
| 671 | run_az(args=kv_cmd) |
| 672 |
no test coverage detected