Skip to content

Commit a878c0c

Browse files
authored
Fix the App Config + Key Vault sample (#22919)
* Apply previous PR feedback Made previous changes but forgot to push. Found this in my reflog. * Resolve Key Vault samples issues Fixes #22913 * Resolve feedback
1 parent fc99fde commit a878c0c

File tree

4 files changed

+228
-14
lines changed

4 files changed

+228
-14
lines changed

samples/AppSecretsConfig/README.md

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
page_type: sample
33
languages:
4+
- aspx-csharp
45
- csharp
56
products:
67
- azure
@@ -35,22 +36,31 @@ Examples of secrets that should be stored in Key Vault:
3536

3637
To build and run this sample you will need:
3738

39+
Software:
40+
41+
* [.NET][dotnet_install]
42+
* [Azure CLI][azure_cli]
43+
44+
Azure services:
45+
3846
* [App Configuration][appconfig_overview]
3947
* [Key Vault][keyvault_overview]
48+
* (Optional) [App Service][appservice_overview] - needed to deploy the web application to Azure, which is provisioned in the [Bicep][bicep_overview] [template][sample_template].
4049

41-
To deploy this sample you will also need:
50+
> [!NOTE]
51+
> App Service has [support for referencing Key Vault secrets][appservice_secrets] directly, but is used only as an example how to configure a web site to use App Configuration.
52+
> If you choose to deploy your web application to another service, the same principles to configure the App Configuration connection string still apply.
4253
43-
* [App Service][appservice_overview]
54+
* (Optional) [Application Insights][appinsights_overview] - to monitor web traffic and application traces, which is *not* provisioned in the Bicep template.
4455

45-
Optionally, you may configure the App Service to use [Application Insights][appinsights_overview] to monitor traffic.
46-
47-
[![Deploy to Azure](https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/1-CONTRIBUTION-GUIDE/images/deploytoazure.svg?sanitize=true)][sample_deploy]
56+
[![Deploy to Azure](https://aka.ms/deploytoazurebutton)][sample_deploy]
4857

4958
To deploy the template manually, make sure your [Azure CLI][azure_cli] is up to date and run:
5059

5160
```bash
61+
az bicep install # if deploying azuredeploy.bicep
5262
az group create --location {location} --resource-group {group-name}
53-
az deployment group create --resource-group {group-name} --template-file azuredeploy.bicep
63+
az deployment group create --resource-group {group-name} --template-file azuredeploy.bicep # or azuredeploy.json
5464
```
5565

5666
There are a number of parameters you can optional set. [View the template][sample_template] for details.
@@ -104,7 +114,9 @@ If you're logged in as a service principal, the `user.type` will be `servicePrin
104114
az keyvault set-policy -n {vault-host-name} --spn {spn} --secret-permissions get
105115
```
106116

107-
#### Visual Studio
117+
Next you'll need to add the App Configuration connection string from the template deployment outputs to your local user secrets:
118+
119+
#### [Visual Studio](#tab/visualstudio)
108120

109121
1. Right-click on the project
110122
2. Click **Managed User Secrets**
@@ -118,7 +130,7 @@ az keyvault set-policy -n {vault-host-name} --spn {spn} --secret-permissions get
118130

119131
4. Click **Debug -> Start debugging (F5)** to run.
120132

121-
#### Visual Studio Code
133+
#### [Visual Studio Code](#tab/visualstudiocode)
122134

123135
1. In the project folder, run the following to add a variable named `ConnectionStrings:AppConfig` with the `value` of the `appConfigurationConnectionString` output variable:
124136

@@ -129,7 +141,7 @@ az keyvault set-policy -n {vault-host-name} --spn {spn} --secret-permissions get
129141
2. With a *.cs* file open the command palette and run `Debug: Start debugging` or press `F5` (default binding).
130142
3. If prompted, select ".NET Core" to create a launch configuration and start debugging.
131143

132-
#### dotnet CLI
144+
#### [.NET CLI](#tab/dotnet_cli)
133145

134146
1. In the project folder, run the following to add a variable named `ConnectionStrings:AppConfig` with the `value` of the `appConfigurationConnectionString` output variable:
135147

@@ -145,7 +157,7 @@ az keyvault set-policy -n {vault-host-name} --spn {spn} --secret-permissions get
145157

146158
#### Deploying the sample
147159

148-
See the [ASP.NET quickstart][aspnet_quickstart] for instructions to deploy for Visual Studio, Visual Studio Code, and the `dotnet` CLI. For Visual Studio and Visual Studio Code, make sure you select your existing resource if you deployed the Bicep template above; otherwise, for the `dotnet` CLI you can deploy to an existing resource by [configuring Local Git support][aspnet_deploy_localgit].
160+
See the [ASP.NET quickstart][aspnet_quickstart] for instructions to deploy for Visual Studio, Visual Studio Code, and the `dotnet` CLI. For Visual Studio and Visual Studio Code, make sure you select your existing resource if you deployed the Bicep template above; otherwise, for the `dotnet` CLI you can deploy to an existing resource by [configuring Git support][aspnet_deploy_localgit] and pushing source, which will be built automatically on the host.
149161

150162
## Configuring App Configuration with Key Vault references
151163

@@ -230,12 +242,15 @@ In [ASP.NET Razor pages][aspnet_razor] as an example, you can then inject them i
230242
[appconfig_overview]: https://docs.microsoft.com/azure/azure-app-configuration/overview
231243
[appinsights_overview]: https://docs.microsoft.com/azure/azure-monitor/app/app-insights-overview
232244
[appservice_overview]: https://docs.microsoft.com/azure/app-service/overview
245+
[appservice_secrets]: https://docs.microsoft.com/azure/app-service/app-service-key-vault-references#rotation
233246
[aspnet_config]: https://docs.microsoft.com/aspnet/core/fundamentals/configuration
234247
[aspnet_deploy_localgit]: https://docs.microsoft.com/azure/app-service/deploy-local-git
235248
[aspnet_quickstart]: https://docs.microsoft.com/azure/app-service/quickstart-dotnetcore
236249
[aspnet_razor]: https://docs.microsoft.com/aspnet/core/razor-pages/
237250
[azure_cli]: https://docs.microsoft.com/cli/azure/
251+
[bicep_overview]: https://docs.microsoft.com/azure/azure-resource-manager/bicep/overview
238252
[dotnet_cli]: https://docs.microsoft.com/dotnet/core/tools/
253+
[dotnet_install]: https://dotnet.microsoft.com/download
239254
[identity_defaultazurecredential]: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/README.md#defaultazurecredential
240255
[identity_troubleshooting]: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/README.md#troubleshooting
241256
[keyvault_injection]: https://docs.microsoft.com/dotnet/api/overview/azure/microsoft.extensions.azure-readme-pre
@@ -245,7 +260,7 @@ In [ASP.NET Razor pages][aspnet_razor] as an example, you can then inject them i
245260
[keyvault_secretclient]: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/keyvault/Azure.Security.KeyVault.Secrets/README.md#secretclient
246261
[nuget_azureappconfig]: https://nuget.org/packages/Microsoft.Extensions.Configuration.AzureAppConfiguration
247262
[nuget_azureextensions]: https://nuget.org/packages/Microsoft.Extensions.Azure
248-
[sample_deploy]: https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-sdk-for-net%2Fmain%2Fsamples%2FAppSecretsConfig%2Fazuredeploy.bicep
263+
[sample_deploy]: https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-sdk-for-net%2Fmain%2Fsamples%2FAppSecretsConfig%2Fazuredeploy.json
249264
[sample_template]: https://github.com/Azure/azure-sdk-for-net/blob/main/samples/AppSecretsConfig/azuredeploy.bicep
250265
[visualstudio]: https://visualstudio.microsoft.com/
251266
[visualstudiocode]: https://code.visualstudio.com/

samples/AppSecretsConfig/Startup.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
4242
app.UseStaticFiles();
4343

4444
app.UseRouting();
45-
46-
app.UseAuthorization();
47-
4845
app.UseEndpoints(endpoints =>
4946
{
5047
endpoints.MapRazorPages();
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
{
2+
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
3+
"contentVersion": "1.0.0.0",
4+
"metadata": {
5+
"_generator": {
6+
"name": "bicep",
7+
"version": "0.4.451.19169",
8+
"templateHash": "9923986087503436347"
9+
}
10+
},
11+
"parameters": {
12+
"name": {
13+
"type": "string",
14+
"defaultValue": "[uniqueString(resourceGroup().id)]",
15+
"metadata": {
16+
"description": "The base name for resources"
17+
}
18+
},
19+
"location": {
20+
"type": "string",
21+
"defaultValue": "[resourceGroup().location]",
22+
"metadata": {
23+
"description": "The location for resources"
24+
}
25+
},
26+
"secret": {
27+
"type": "secureString",
28+
"defaultValue": "[newGuid()]",
29+
"metadata": {
30+
"description": "A secret to use in the web application"
31+
}
32+
},
33+
"sku": {
34+
"type": "string",
35+
"defaultValue": "F1",
36+
"metadata": {
37+
"description": "The web site hosting plan"
38+
}
39+
},
40+
"configSku": {
41+
"type": "string",
42+
"defaultValue": "standard",
43+
"allowedValues": [
44+
"free",
45+
"standard"
46+
],
47+
"metadata": {
48+
"description": "The App Configuration SKU. Only \"standard\" supports customer-managed keys from Key Vault"
49+
}
50+
}
51+
},
52+
"functions": [],
53+
"resources": [
54+
{
55+
"type": "Microsoft.AppConfiguration/configurationStores/keyValues",
56+
"apiVersion": "2020-07-01-preview",
57+
"name": "[format('{0}/{1}', format('{0}config', parameters('name')), 'APPCONFIG_VALUE')]",
58+
"properties": {
59+
"contentType": "text/plain",
60+
"value": "not a secret"
61+
},
62+
"dependsOn": [
63+
"[resourceId('Microsoft.AppConfiguration/configurationStores', format('{0}config', parameters('name')))]"
64+
]
65+
},
66+
{
67+
"type": "Microsoft.AppConfiguration/configurationStores/keyValues",
68+
"apiVersion": "2020-07-01-preview",
69+
"name": "[format('{0}/{1}', format('{0}config', parameters('name')), 'KEYVAULT_SECRET')]",
70+
"properties": {
71+
"contentType": "application/vnd.microsoft.appconfig.keyvaultref+json;charset=utf-8",
72+
"value": "[format('{{\"uri\":\"{0}\"}}', reference(resourceId('Microsoft.KeyVault/vaults/secrets', split(format('{0}/{1}secret', format('kv{0}', parameters('name')), parameters('name')), '/')[0], split(format('{0}/{1}secret', format('kv{0}', parameters('name')), parameters('name')), '/')[1])).secretUri)]"
73+
},
74+
"dependsOn": [
75+
"[resourceId('Microsoft.AppConfiguration/configurationStores', format('{0}config', parameters('name')))]",
76+
"[resourceId('Microsoft.KeyVault/vaults/secrets', split(format('{0}/{1}secret', format('kv{0}', parameters('name')), parameters('name')), '/')[0], split(format('{0}/{1}secret', format('kv{0}', parameters('name')), parameters('name')), '/')[1])]"
77+
]
78+
},
79+
{
80+
"type": "Microsoft.AppConfiguration/configurationStores",
81+
"apiVersion": "2020-06-01",
82+
"name": "[format('{0}config', parameters('name'))]",
83+
"location": "[parameters('location')]",
84+
"sku": {
85+
"name": "[parameters('configSku')]"
86+
}
87+
},
88+
{
89+
"type": "Microsoft.KeyVault/vaults",
90+
"apiVersion": "2019-09-01",
91+
"name": "[format('kv{0}', parameters('name'))]",
92+
"location": "[parameters('location')]",
93+
"properties": {
94+
"sku": {
95+
"family": "A",
96+
"name": "standard"
97+
},
98+
"tenantId": "[subscription().tenantId]",
99+
"accessPolicies": [
100+
{
101+
"tenantId": "[subscription().tenantId]",
102+
"objectId": "[reference(resourceId('Microsoft.Web/sites', format('{0}web', parameters('name'))), '2020-12-01', 'full').identity.principalId]",
103+
"permissions": {
104+
"secrets": [
105+
"get"
106+
]
107+
}
108+
}
109+
]
110+
},
111+
"dependsOn": [
112+
"[resourceId('Microsoft.Web/sites', format('{0}web', parameters('name')))]"
113+
]
114+
},
115+
{
116+
"type": "Microsoft.KeyVault/vaults/secrets",
117+
"apiVersion": "2019-09-01",
118+
"name": "[format('{0}/{1}secret', format('kv{0}', parameters('name')), parameters('name'))]",
119+
"properties": {
120+
"contentType": "text/plain",
121+
"value": "[parameters('secret')]"
122+
},
123+
"dependsOn": [
124+
"[resourceId('Microsoft.KeyVault/vaults', format('kv{0}', parameters('name')))]"
125+
]
126+
},
127+
{
128+
"type": "Microsoft.Web/serverfarms",
129+
"apiVersion": "2020-12-01",
130+
"name": "[format('{0}plan', parameters('name'))]",
131+
"location": "[parameters('location')]",
132+
"sku": {
133+
"name": "[parameters('sku')]"
134+
},
135+
"kind": "linux",
136+
"properties": {
137+
"reserved": true
138+
}
139+
},
140+
{
141+
"type": "Microsoft.Web/sites",
142+
"apiVersion": "2020-12-01",
143+
"name": "[format('{0}web', parameters('name'))]",
144+
"location": "[parameters('location')]",
145+
"identity": {
146+
"type": "SystemAssigned"
147+
},
148+
"properties": {
149+
"httpsOnly": true,
150+
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', format('{0}plan', parameters('name')))]",
151+
"siteConfig": {
152+
"linuxFxVersion": "DOTNETCORE|3.1",
153+
"connectionStrings": [
154+
{
155+
"name": "AppConfig",
156+
"connectionString": "[listKeys(resourceId('Microsoft.AppConfiguration/configurationStores', format('{0}config', parameters('name'))), '2020-06-01').value[0].connectionString]"
157+
}
158+
]
159+
}
160+
},
161+
"dependsOn": [
162+
"[resourceId('Microsoft.AppConfiguration/configurationStores', format('{0}config', parameters('name')))]",
163+
"[resourceId('Microsoft.Web/serverfarms', format('{0}plan', parameters('name')))]"
164+
]
165+
}
166+
],
167+
"outputs": {
168+
"appConfigConnectionString": {
169+
"type": "string",
170+
"value": "[listKeys(resourceId('Microsoft.AppConfiguration/configurationStores', format('{0}config', parameters('name'))), '2020-06-01').value[0].connectionString]"
171+
},
172+
"siteUrl": {
173+
"type": "string",
174+
"value": "[format('https://{0}/', reference(resourceId('Microsoft.Web/sites', format('{0}web', parameters('name')))).defaultHostName)]"
175+
},
176+
"vaultUrl": {
177+
"type": "string",
178+
"value": "[reference(resourceId('Microsoft.KeyVault/vaults', format('kv{0}', parameters('name')))).vaultUri]"
179+
}
180+
}
181+
}

samples/Directory.Build.targets

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2+
3+
<Target Name="_GetBicepTemplates">
4+
<ItemGroup>
5+
<_BicepTemplate Include="@(None)" Condition="'%(Extension)' == '.bicep'" />
6+
</ItemGroup>
7+
</Target>
8+
9+
<Target Name="_BuildBicepTemplates"
10+
Condition="'$(BuildBicepTemplates)' != 'false'"
11+
DependsOnTargets="_GetBicepTemplates"
12+
BeforeTargets="CoreCompile"
13+
Inputs="@(_BicepTemplate)"
14+
Outputs="@(_BicepTemplate->'%(RelativeDir)%(Filename).json')">
15+
<Exec Command="az bicep build --file &quot;@(_BicepTemplate)&quot; --outfile &quot;@(_BicepTemplate->'%(RelativeDir)%(Filename).json')&quot;">
16+
<Output TaskParameter="Outputs" ItemName="@(_BicepTemplate->'%(RelativeDir)%(Filename).json')" />
17+
</Exec>
18+
<Message Text="@(_BicepTemplate) -> @(_BicepTemplate->'%(RelativeDir)%(Filename).json')" Importance="high" />
19+
</Target>
20+
21+
</Project>

0 commit comments

Comments
 (0)