This directory contains Bash scripts for deploying and validating the sample using the lstk CLI. For details about the sample application, see Azure Web App with Azure App Configuration and Azure Key Vault.
brew install localstack/tap/lstk # or: npm install -g @localstack/lstkdeploy.sh provisions the same resources as the Bicep and Terraform variants but with raw az commands. Every step is a get-or-create probe followed by the create, so the script can be re-run. It creates, in this order:
- Azure Resource Group.
- User-assigned managed identity
<prefix>-identity-<suffix>(az identity create), reading back itsclientId,principalIdand resource id. - Azure App Configuration store
<prefix>-appconfig-<suffix>(az appconfig create --sku Standard --enable-public-network true), after recovering a soft-deleted store of the same name (az appconfig list-deleted,az appconfig recover). Public network access is enabled explicitly because Azure disables it on a store that gets a private endpoint when the property was never set, and theaz appconfig kvcalls of this script run outside the virtual network. Its endpoint is read back withaz appconfig show --query endpoint. - Azure Key Vault
<prefix>-keyvault-<suffix>with the RBAC permission model (az keyvault create --enable-rbac-authorization true), after recovering a soft-deleted vault of the same name (az keyvault list-deleted,az keyvault recover). Its URI is read back withaz keyvault show --query properties.vaultUri. - The Key Vault Secrets Officer role assignment for the deploying principal on the vault, so the next step can write secrets on an RBAC vault. The principal's object id comes from
az ad signed-in-user show(users) oraz ad sp show --id <appId>(service principals); when it cannot be resolved the script warns and continues, and the role becomes a prerequisite. - The secrets
pg-userandpg-password(az keyvault secret set, retried while the role assignment propagates), holding the credentials of the PostgreSQL application role. The values are never printed. - The identity's role assignments: App Configuration Data Reader on the store and Key Vault Secrets User on the vault (
az role assignment create --assignee-object-id <principalId> --assignee-principal-type ServicePrincipal, checked first withaz role assignment list). - Azure Database for PostgreSQL flexible server: public-access mode,
Burstable / Standard_B1ms, version 16, 32 GiB, HA disabled, with the permissiveAllowAllIPsfirewall rule and thePlannerDBdatabase. The server FQDN is split into host and port: the emulator embeds its TCP-proxy port in the FQDN, Azure returns the bare host and the port defaults to5432. - The five key-values of the store:
PG_HOST,PG_PORTandPG_DATABASEas plain values (az appconfig kv set),PG_USERandPG_PASSWORDas Key Vault references to the two secrets (az appconfig kv set-keyvault --secret-identifier <vault URI>/secrets/<name>, versionless so the reference follows the latest version). Each write is skipped when the store already holds the same value. - Network Security Groups for both subnets.
- Azure NAT Gateway with its public IP prefix.
- Azure Virtual Network with:
- app-subnet: delegated to
Microsoft.Web/serverFarms(with NAT gateway). - pe-subnet: hosts the three Private Endpoints (no delegation; private endpoint network policies disabled).
- app-subnet: delegated to
- Three Azure Private DNS Zones,
privatelink.postgres.database.azure.com,privatelink.azconfig.ioandprivatelink.vaultcore.azure.net, each linked to the VNet aslink-to-vnet, and three Azure Private Endpoints,<prefix>-postgres-pe-<suffix>(grouppostgresqlServer),<prefix>-appconfig-pe-<suffix>(groupconfigurationStores) and<prefix>-keyvault-pe-<suffix>(groupvault), each with adefaultDNS zone group that registers its A record. - A separate application role (
testuser) created viapsql, with the minimum schema privileges onPlannerDB, theactivitiestable and the seeded rows. - Azure App Service Plan.
- Azure Web App with regional VNet integration into app-subnet, forced tunneling, the user-assigned managed identity (
az webapp create --assign-identity <identity id>), and the app settingsEndpoints__AppConfiguration(the store endpoint),AZURE_CLIENT_ID(the identity client id),LOGIN_NAME,WEBSITES_PORT,SCM_DO_BUILD_DURING_DEPLOYMENTandENABLE_ORYX_BUILD. NoPG_*setting: the app loads them from the store. - Azure Log Analytics Workspace and the diagnostic settings of the web app, the plan, the PostgreSQL server, the App Configuration store, the Key Vault, the VNet and the two NSGs.
- The zip deployment of the application code (
az webapp deploy --type zip).
The Web App uses testuser; neither the server-admin login nor the application credentials are written into the Web App's app settings. Use validate.sh after deploy.sh to inspect each Azure resource: it lists the store, its key-values with their content types, the vault and its secret names, the identity, the two role assignments, the three Private DNS Zones, links, Private Endpoints and zone groups, and it exits with a non-zero code if the Web App has any PG_* app setting or lacks Endpoints__AppConfiguration or AZURE_CLIENT_ID.
# default names and secrets
bash deploy.sh
# your own suffix (the store and vault names are globally unique on Azure) and secrets
SUFFIX='<unique>' \
PG_ADMIN_PASSWORD='<admin-password>' \
PG_APP_PASSWORD='<app-password>' \
bash deploy.sh
# inspect what was deployed
bash validate.shdeploy.sh and validate.sh accept the following environment overrides:
| Env var | Default | Description |
|---|---|---|
PREFIX |
local |
Prefix of every resource name (the resource group is <prefix>-rg) |
SUFFIX |
test |
Suffix of every resource name; pick your own on Azure |
LOCATION |
westeurope |
Azure region |
APP_CONFIG_SKU |
Standard |
App Configuration tier (private endpoints need Developer, Standard or Premium) |
PG_ADMIN_USER |
pgadmin |
Server administrator login |
PG_ADMIN_PASSWORD |
P@ssw0rd1234! |
Server administrator password (sensitive) |
PG_DATABASE_NAME |
PlannerDB |
Application database |
PG_APP_USER |
testuser |
Application role used by the Web App, stored as the pg-user secret |
PG_APP_PASSWORD |
TestP@ssw0rd123 |
Password for the application role, stored as the pg-password secret |
LOGIN_NAME |
paolo |
User whose activities the app shows |
DEPLOY_APP |
1 |
Set to 0 to skip the zip deployment step |
The script uses call-web-app.sh (unchanged from the source sample) to demonstrate four ways of hitting the Web App from outside the emulator.