Skip to content

Commit d552504

Browse files
Align series 5 articles with Key Vault strategy: update 5.5, 5.6, 5.8
1 parent 2940d39 commit d552504

3 files changed

Lines changed: 51 additions & 17 deletions

File tree

blogs/series-5-devops-data/5.5-azure-oidc-github-actions.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,8 @@ The output should include a row with `Contributor` assigned to `github-actions-t
300300

301301
**`SQL_ADMIN_PASSWORD` added manually.** The SQL admin password is a genuine secret — a value that must remain confidential. The three OIDC values (`AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, `AZURE_SUBSCRIPTION_ID`) are not sensitive in the same way: knowing them without the federated credential is harmless. The SQL password is kept separate and typed interactively, never written to a file or echoed in a terminal.
302302

303+
**GitHub Secrets vs Azure Key Vault — the clear split.** `SQL_ADMIN_PASSWORD` is the only runtime-sensitive value in GitHub Secrets for this project — and it is only used once, during the Bicep infrastructure deployment (Article 5.4). It is not used by the application itself. Database connection strings, JWT signing keys, and other **application runtime secrets** are stored in Azure Key Vault (`kv-talent-dev`), not in GitHub Secrets. The deploy workflows in Articles 5.6 and 5.7 inject `@Microsoft.KeyVault(SecretUri=...)` references into App Service settings rather than raw values. The Web App's managed identity resolves those references at runtime — the actual secret never passes through GitHub Actions at all.
304+
303305
---
304306

305307
## 🌟 Why This Matters

blogs/series-5-devops-data/5.6-azure-deploy-dotnet-apps.md

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ This article is part of the **AngularNetTutorial** series. The full-stack tutori
2323
* **`dotnet publish`** — what the publish output contains and why it differs from the build output
2424
* **`azure/webapps-deploy`** — the action that uploads and hot-swaps the deployment
2525
* **App Service settings** — how connection strings and URLs reach the running app without touching `appsettings.json`
26+
* **Key Vault references** — why connection strings go into Key Vault, not GitHub Secrets, and how `@Microsoft.KeyVault(SecretUri=...)` wires them into App Service settings
27+
* **GitHub Secrets vs Key Vault** — the split: CI/CD auth credentials in GitHub Secrets, runtime secrets in Key Vault
2628
* **Deployment order** — why IdentityServer must be deployed and running before the API
2729

2830
---
@@ -41,6 +43,8 @@ This article is part of the **AngularNetTutorial** series. The full-stack tutori
4143

4244
The .NET API and IdentityServer each need several environment-specific values at runtime: the database connection string, the URL of IdentityServer (which the API uses to validate tokens), and the URL of the API itself (which IdentityServer uses to register the audience). These values differ between local development and Azure. Hardcoding them in `appsettings.json` would commit environment-specific secrets to source control and break the principle that the same build artifact runs in every environment.
4345

46+
Even storing connection strings in GitHub Secrets is not production-grade — the raw value gets injected into App Service settings where it is visible in plain text in the Portal to anyone with Contributor access. The correct approach is to store secrets in **Azure Key Vault** (provisioned in Article 5.4) and reference them from App Service settings via `@Microsoft.KeyVault(SecretUri=...)`. The App Service resolves the reference at runtime using its managed identity — the actual connection string is never visible anywhere.
47+
4448
Manual deployment — `dotnet publish`, zip the output, upload via the Portal — is error-prone and produces no audit trail. Running it inconsistently across developers produces inconsistent results.
4549

4650
---
@@ -51,28 +55,33 @@ GitHub Actions workflows are triggered by pushes to specific paths. When code ch
5155

5256
App Service application settings are the Azure equivalent of environment variables. They override values in `appsettings.json` at runtime without touching the committed file. The same published binary runs locally (using `appsettings.json`) and in Azure (using App Service settings that override the file).
5357

58+
For **non-sensitive settings** (URLs, feature flags, audience names), the workflow injects plain values directly. For **secrets** (connection strings, JWT signing key), the workflow injects a `@Microsoft.KeyVault(SecretUri=...)` reference instead of the raw value. App Service resolves these references at startup using the Web App's system-assigned managed identity — the actual secret is retrieved from Key Vault and injected into the app's environment without ever appearing in the Portal or in logs. See Article 5.9 for full detail on this pattern.
59+
5460
---
5561

5662
## 🚀 How It Works
5763

5864
### Step 1: Add the Remaining GitHub Secrets
5965

60-
Articles 5.5 set up four secrets. Two workflows need several more:
66+
Article 5.5 set up four secrets (`AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, `AZURE_SUBSCRIPTION_ID`, `SQL_ADMIN_PASSWORD`). The deploy workflows need several more.
6167

6268
**Navigate to:** GitHub → Repository → Settings → Secrets and variables → Actions → New repository secret
6369

64-
**Secrets to add:**
70+
**GitHub Secrets vs Azure Key Vault — the split:**
6571

66-
* **`API_DB_CONNECTION_STRING`** — the Azure SQL connection string for the API database
72+
| Secret type | Where it lives | Why |
73+
|---|---|---|
74+
| CI/CD auth credentials (`AZURE_*`) | GitHub Secrets | Needed by the runner to log in to Azure |
75+
| Infrastructure deploy password (`SQL_ADMIN_PASSWORD`) | GitHub Secrets | One-time use for Bicep provisioning only |
76+
| Runtime secrets (connection strings, JWT key) | **Azure Key Vault** | Never exposed as plain text; resolved by managed identity at runtime |
77+
| Non-sensitive URLs and config | GitHub Secrets | Not sensitive — just convenient to store here |
6778

68-
```
69-
Server=tcp:sql-talent-dev.database.windows.net,1433;Initial Catalog=sqldb-talent-api-dev;Persist Security Info=False;User ID=sqladmin;Password=<your-password>;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;
70-
```
79+
**Secrets to add to GitHub:**
7180

72-
* **`IDS_DB_CONNECTION_STRING`** — the Azure SQL connection string for the IdentityServer database
81+
* **`KEY_VAULT_URI`** — the URI of the Key Vault provisioned in Article 5.4
7382

7483
```
75-
Server=tcp:sql-talent-dev.database.windows.net,1433;Initial Catalog=sqldb-talent-ids-dev;Persist Security Info=False;User ID=sqladmin;Password=<your-password>;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;
84+
https://kv-talent-dev.vault.azure.net/
7685
```
7786

7887
* **`IDENTITY_SERVER_URL`** — the HTTPS URL of the deployed IdentityServer App Service
@@ -81,20 +90,41 @@ Server=tcp:sql-talent-dev.database.windows.net,1433;Initial Catalog=sqldb-talent
8190
https://app-talent-ids-dev.azurewebsites.net
8291
```
8392

84-
* **`JWT_KEY`** — the symmetric key used by the API's local JWT authentication (copy from `appsettings.json``JWTSettings.Key`)
85-
* **`ANGULAR_APP_URL`** — the Azure Static Web App URL (e.g. `https://mango-flower-0ced4011e.4.azurestaticapps.net`) — added to API CORS allowed origins
86-
* **`IDENTITY_ADMIN_URL`** — the IdentityServer Admin UI URL (e.g. `https://app-talent-admin-dev.azurewebsites.net`) — used by STS and Admin app configuration
93+
* **`ANGULAR_APP_URL`** — the Azure Static Web App URL
94+
95+
```
96+
https://mango-flower-0ced4011e.4.azurestaticapps.net
97+
```
98+
99+
* **`IDENTITY_ADMIN_URL`** — the IdentityServer Admin UI URL
100+
101+
```
102+
https://app-talent-admin-dev.azurewebsites.net
103+
```
87104

88-
**Retrieve the connection strings from the Bicep outputs:**
105+
**Secrets to add to Key Vault** (not GitHub — these contain sensitive values):
89106

90107
```bash
91-
az deployment group show \
92-
--resource-group rg-talent-dev \
93-
--name main \
94-
--query properties.outputs \
95-
--output table
108+
KV="kv-talent-dev"
109+
110+
# API database connection string
111+
az keyvault secret set --vault-name $KV \
112+
--name "ConnectionStrings--DefaultConnection" \
113+
--value "Server=tcp:sql-talent-dev.database.windows.net,1433;Initial Catalog=sqldb-talent-api-dev;Persist Security Info=False;User ID=sqladmin;Password=<your-password>;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
114+
115+
# IdentityServer database connection string
116+
az keyvault secret set --vault-name $KV \
117+
--name "ConnectionStrings--IdsDbConnection" \
118+
--value "Server=tcp:sql-talent-dev.database.windows.net,1433;Initial Catalog=sqldb-talent-ids-dev;Persist Security Info=False;User ID=sqladmin;Password=<your-password>;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
119+
120+
# JWT signing key
121+
az keyvault secret set --vault-name $KV \
122+
--name "JWTSettings--Key" \
123+
--value "<your-jwt-signing-key>"
96124
```
97125

126+
**⚠️ One-time prerequisite:** Your local Azure CLI identity needs the **Key Vault Secrets Officer** role on `kv-talent-dev` to run `az keyvault secret set`. Grant it in the Portal: **Key Vault → kv-talent-dev → Access control (IAM) → Add role assignment → Key Vault Secrets Officer → your account**.
127+
98128
### Step 2: Understand the Workflow File Structure
99129

100130
Both workflows live in `.github/workflows/` in the parent repository. They follow the same pattern:

blogs/series-5-devops-data/5.8-azure-post-deployment-config.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ These two configurations — IdentityServer redirect URIs and API CORS origins
6868

6969
## 💡 The Solution
7070

71+
**Note on connection strings:** Database connection strings were stored in Azure Key Vault in Article 5.4 and wired into App Service settings as `@Microsoft.KeyVault(...)` references by the deploy workflows in Article 5.6. No `appsettings.json` changes are needed for connection strings — this article focuses only on IdentityServer redirect URIs and API CORS origins, which are URLs (not secrets) and are set by the deploy workflows as plain values.
72+
7173
Add the production Static Web App URL to three lists in `identityserverdata.json` (the file that seeds IdentityServer's database):
7274

7375
* `RedirectUris` — where IdentityServer may send authorization codes after login

0 commit comments

Comments
 (0)