Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Both scripts are idempotent: they check whether each resource already exists bef

- A resource group and a Log Analytics workspace (wired to the cluster through the monitoring add-on / Azure Monitor for containers).
- A dedicated virtual network (`10.0.0.0/8`) with three subnets: `SystemSubnet` (system node pool), `UserSubnet` (user node pool), and `AzureBastionSubnet`.
- An [Azure Bastion](https://learn.microsoft.com/en-us/azure/bastion/bastion-overview) host in `AzureBastionSubnet`, with the Standard SKU static public IP it requires, for reaching the nodes without exposing SSH to the internet. Creating it takes several minutes.
- An [Azure Container Registry (ACR)](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-intro) that is attached to the cluster (via `--attach-acr`) so nodes can pull images without extra credentials.
- The AKS cluster itself, configured with:
- An Azure CNI Overlay network plugin with the Azure network policy and data plane (pod CIDR `192.168.0.0/16`, service CIDR `172.16.0.0/16`).
Expand Down Expand Up @@ -114,6 +115,7 @@ To run any sample you must first create the AKS cluster with one of the two scri
| web-app-blob-storage ([Python](samples/web-app-blob-storage/python/README.md), [.NET](samples/web-app-blob-storage/dotnet/README.md)) | Stores activities in an [Azure Blob Storage](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction) container, using a connection string. |
| web-app-file-storage ([Python](samples/web-app-file-storage/python/README.md), [.NET](samples/web-app-file-storage/dotnet/README.md)) | Stores activities as text files on an [Azure Files](https://learn.microsoft.com/en-us/azure/storage/files/storage-files-introduction) share mounted into the pods by the [Azure Files CSI driver](https://learn.microsoft.com/en-us/azure/aks/azure-files-csi), over either SMB or NFS, with either a pre-created share or one provisioned on demand. The only sample whose app uses no Azure SDK at all. |
| web-app-managed-identity ([Python](samples/web-app-managed-identity/python/README.md), [.NET](samples/web-app-managed-identity/dotnet/README.md)) | Stores activities in an Azure Blob Storage container, authenticating with [Microsoft Entra Workload ID](https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview) (federated credential plus workload identity) instead of a secret, and optionally exposes the app through the Gateway API with a managed TLS certificate. |
| web-app-app-configuration ([Python](samples/web-app-app-configuration/python/README.md), [.NET](samples/web-app-app-configuration/dotnet/README.md)) | Stores activities in an Azure Database for PostgreSQL flexible server but reads every connection setting from an [Azure App Configuration](https://learn.microsoft.com/en-us/azure/azure-app-configuration/overview) store, with the credentials kept in [Azure Key Vault](https://learn.microsoft.com/en-us/azure/key-vault/general/overview) and exposed as Key Vault references. The [Azure App Configuration Kubernetes Provider](https://learn.microsoft.com/en-us/azure/azure-app-configuration/reference-kubernetes-provider), installed as the `Microsoft.AppConfiguration` cluster extension, turns them into a ConfigMap and a Secret, authenticating with [Microsoft Entra Workload ID](https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview). |

Each sample folder follows the same layout:

Expand Down
201 changes: 201 additions & 0 deletions samples/web-app-app-configuration/dotnet/README.md

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
101 changes: 101 additions & 0 deletions samples/web-app-app-configuration/dotnet/scripts/00-variables.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Variables

# Azure Resources
# Every name below can be overridden from the environment. The App Configuration store, the key vault, the
# container registry and the PostgreSQL server all take globally unique names, so a run against a real
# subscription normally needs its own SUFFIX (or PREFIX); the defaults match the cluster created by
# ../../../scripts/01-user-assigned-managed-identity.sh, so on the emulator nothing has to be set.
# SUFFIX=contoso01 LOCATION=westeurope ./01-deploy-resources.sh
PREFIX="${PREFIX:-local}"
SUFFIX="${SUFFIX:-test}"
LOCATION="${LOCATION:-italynorth}"
RESOURCE_GROUP_NAME="${RESOURCE_GROUP_NAME:-${PREFIX}-rg}"
AKS_CLUSTER_NAME="${AKS_CLUSTER_NAME:-${PREFIX}-aks-${SUFFIX}}"
ACR_NAME="${ACR_NAME:-${PREFIX,,}acr${SUFFIX,,}}"
ACR_SKU="${ACR_SKU:-Standard}"
SUBSCRIPTION_NAME=$(az account show --query name --output tsv)
SUBSCRIPTION_ID=$(az account show --query id --output tsv)
TENANT_ID=$(az account show --query tenantId --output tsv)
CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)"

# User-assigned managed identity. The App Configuration Kubernetes Provider authenticates as this identity
# through a federated credential on the cluster's OIDC issuer, so no secret is stored anywhere.
MANAGED_IDENTITY_NAME="${PREFIX}-appconfig-identity-${SUFFIX}"
FEDERATED_IDENTITY_NAME="${PREFIX}-appconfig-federated-identity-${SUFFIX}"

# Azure App Configuration. Holds every setting the app needs: the non-secret values as plain key-values and
# the credentials as Key Vault references.
APP_CONFIG_NAME="${PREFIX}-aks-appconfig-${SUFFIX}"
APP_CONFIG_SKU='Standard'

# Azure Key Vault. Uses the Azure RBAC permission model, which the Key Vault Secrets User role requires.
KEY_VAULT_NAME="${PREFIX}-aks-kv-${SUFFIX}"
KEY_VAULT_RETENTION_DAYS=7

# Key Vault secret names, and the content type that marks an App Configuration key-value as a reference to one.
PG_USER_SECRET_NAME='pg-user'
PG_PASSWORD_SECRET_NAME='pg-password'
SECRET_KEY_SECRET_NAME='secret-key'
KEY_VAULT_REFERENCE_CONTENT_TYPE='application/vnd.microsoft.appconfig.keyvaultref+json;charset=utf-8'

# Role assignments
APP_CONFIG_DATA_READER_ROLE='App Configuration Data Reader'
KEY_VAULT_SECRETS_USER_ROLE='Key Vault Secrets User'
KEY_VAULT_SECRETS_OFFICER_ROLE='Key Vault Secrets Officer'
ROLE_ASSIGNMENT_RETRY_COUNT=10
ROLE_ASSIGNMENT_RETRY_SLEEP=15
SECRET_RETRY_COUNT=10
SECRET_RETRY_SLEEP=15

# Azure Database for PostgreSQL flexible server. Its own server, so this sample and
# web-app-postgresql-flexible-server never share data.
PG_SERVER_NAME="${PREFIX}-pgflex-appconfig-${SUFFIX}"
PG_VERSION='16'
PG_SKU_TIER='Burstable'
PG_SKU_NAME='Standard_B1ms'
PG_STORAGE_SIZE_GB=32
PG_BACKUP_RETENTION_DAYS=7
PG_PORT='5432'
FIREWALL_RULE_NAME='AllowAllIPs'
PG_ADMIN_USER='pgadmin'
PG_ADMIN_PASSWORD='P@ssw0rd1234!'
PG_USER_NAME='testuser'
PG_USER_PASSWORD='TestP@ssw0rd123'
PG_DATABASE_NAME='PlannerDB'

# Application config — must match the seed-row `username` in 01-deploy-resources.sh.
# PostgreSQL `=` is case-sensitive (unlike SQL Server), so this stays lowercase.
LOGIN_NAME='paolo'

# The refresh sentinel. The provider watches this single key and re-reads the whole selection when it
# changes, which is cheaper than polling every key. 01-deploy-resources.sh seeds it to 1 and never
# overwrites it, so a manual bump survives a re-run.
SENTINEL_KEY='CONFIG_VERSION'
SENTINEL_INITIAL_VALUE='1'
REFRESH_INTERVAL='30s'

# AKS App Configuration extension. No version is pinned: the Azure CLI refuses --version unless the
# auto-upgrade mode is `none`, and both Azure and the emulator install their current release (2.6.7 at the
# time of writing) and report it as `currentVersion`.
APP_CONFIG_EXTENSION_NAME='appconfigurationkubernetesprovider'
APP_CONFIG_EXTENSION_TYPE='Microsoft.AppConfiguration'
APP_CONFIG_EXTENSION_NAMESPACE='azappconfig-system'
APP_CONFIG_PROVIDER_DEPLOYMENT='az-appconfig-k8s-provider'
APP_CONFIG_PROVIDER_CRD='azureappconfigurationproviders.azconfig.io'

# Docker Image
IMAGE_NAME="vacation-planner-appconfig-dotnet"
IMAGE_PULL_POLICY="Always"
IMAGE_TAG="v1"
PORT="8080"

# Kubernetes
NAMESPACE="vacation-planner-appconfig"
DEPLOYMENT_NAME="vacation-planner-appconfig"
SERVICE_NAME="vacation-planner-appconfig"
PROVIDER_NAME="vacation-planner-appconfig"
SERVICE_ACCOUNT_NAME="vacation-planner-appconfig-sa"

# Generated by the App Configuration Kubernetes Provider, not by these scripts.
CONFIGMAP_NAME="vacation-planner-appconfig-config"
K8S_SECRET_NAME="vacation-planner-appconfig-secrets"
Loading