Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update app-configuration module to store connection strings in Key Vault #44

Merged
merged 5 commits into from
Oct 3, 2022
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
51 changes: 38 additions & 13 deletions modules/general/app-configuration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,24 @@ Azure App Configuration

## Description

{{ Add detailed description for the module. }}
Deploys an instance of Azure App Configuration, optionally storing the primary connection strings in Azure Key Vault.

## Parameters

| Name | Type | Required | Description |
| :-------------------------- | :------: | :------: | :----------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | `string` | Yes | The name of the app configuration store |
| `location` | `string` | Yes | The location of the app configuration store |
| `enablePublicNetworkAccess` | `bool` | No | When false, the app configuration store will be inaccessible via its public IP address |
| `sku` | `string` | No | SKU for the app configuration store |
| `useExisting` | `bool` | No | When true, the details of an existing app configuration store will be returned; When false, the app configuration store is created/updated |
| `resourceTags` | `object` | No | The resource tags applied to resources |
| Name | Type | Required | Description |
| :------------------------------------------- | :------: | :------: | :----------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | `string` | Yes | The name of the app configuration store |
| `location` | `string` | Yes | The location of the app configuration store |
| `enablePublicNetworkAccess` | `bool` | No | When false, the app configuration store will be inaccessible via its public IP address |
| `sku` | `string` | No | SKU for the app configuration store |
| `saveConnectionStringsToKeyVault` | `bool` | No | When true, the primary connection strings (read/write and read-only) will be written to the specified key vault |
| `keyVaultName` | `string` | No | The name of the key vault used to store the connection strings |
| `keyVaultResourceGroupName` | `string` | No | The resource group containing the key vault used to store the connection strings |
| `keyVaultSubscriptionId` | `string` | No | The ID of the subscription containing the key vault used to store the connection strings |
| `keyVaultConnectionStringSecretName` | `string` | No | The key vault secret name used to store the read/write connection string |
| `keyVaultReadOnlyConnectionStringSecretName` | `string` | No | The key vault secret name used to store the read-only connection string |
| `useExisting` | `bool` | No | When true, the details of an existing app configuration store will be returned; When false, the app configuration store is created/updated |
| `resourceTags` | `object` | No | The resource tags applied to resources |

## Outputs

Expand All @@ -27,14 +33,33 @@ Azure App Configuration

## Examples

Something here.

### Example 1
### Deploy a standard App Configuration instance

```bicep
module appconfig 'br:<registry-fqdn>/bicep/general/app-configuration:<version>' = {
name: 'appConfig'
params: {
name: 'myappconfig'
location: location
sku: 'Standard
}
}
```

### Example 2
### Deploy App Configuration and save connection strings in Key Vault

```bicep
module appconfig 'br:<registry-fqdn>/bicep/general/app-configuration:<version>' = {
name: 'appConfig'
params: {
name: 'myappconfig'
location: location
saveConnectionStringsToKeyVault: true
keyVaultSubscriptionId: subscription().subscriptionId
keyVaultResourceGroupName: 'my-key-vault-resource-group'
keyVaultName: 'mykeyvault'
keyVaultConnectionStringSecretName: 'AppConfigConnectionString'
keyVaultReadOnlyConnectionStringSecretName: 'AppConfigReadOnlyConnectionString'
}
}
```
42 changes: 42 additions & 0 deletions modules/general/app-configuration/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@ param enablePublicNetworkAccess bool = true
])
param sku string = 'Standard'

@description('When true, the primary connection strings (read/write and read-only) will be written to the specified key vault')
param saveConnectionStringsToKeyVault bool = false

@description('The name of the key vault used to store the connection strings')
param keyVaultName string = ''

@description('The resource group containing the key vault used to store the connection strings')
param keyVaultResourceGroupName string = resourceGroup().name

@description('The ID of the subscription containing the key vault used to store the connection strings')
param keyVaultSubscriptionId string = subscription().subscriptionId

@description('The key vault secret name used to store the read/write connection string')
param keyVaultConnectionStringSecretName string = ''

@description('The key vault secret name used to store the read-only connection string')
param keyVaultReadOnlyConnectionStringSecretName string = ''

@description('When true, the details of an existing app configuration store will be returned; When false, the app configuration store is created/updated')
param useExisting bool = false

Expand Down Expand Up @@ -45,6 +63,30 @@ resource app_config_store 'Microsoft.AppConfiguration/configurationStores@2020-0
tags: resourceTags
}

var acsConnectionString = useExisting ? existing_app_config_store.listKeys().value[0].connectionString : app_config_store.listKeys().value[0].connectionString

module connection_string_secret '../key-vault-secret/main.bicep' = if (saveConnectionStringsToKeyVault) {
name: 'appConfigConnStrSecretDeploy${name}'
scope: resourceGroup(keyVaultSubscriptionId, keyVaultResourceGroupName)
params: {
keyVaultName: keyVaultName
secretName: keyVaultConnectionStringSecretName
contentValue: acsConnectionString
}
}

var acsReadOnlyConnectionString = useExisting ? existing_app_config_store.listKeys().value[2].connectionString : app_config_store.listKeys().value[2].connectionString

module readonly_connection_string_secret '../key-vault-secret/main.bicep' = if (saveConnectionStringsToKeyVault) {
name: 'appConfigRoConnStrSecretDeploy${name}'
scope: resourceGroup(keyVaultSubscriptionId, keyVaultResourceGroupName)
params: {
keyVaultName: keyVaultName
secretName: keyVaultReadOnlyConnectionStringSecretName
contentValue: acsReadOnlyConnectionString
}
}

// Template outputs
@description('The resource ID of the app configuration store')
output id string = useExisting ? existing_app_config_store.id : app_config_store.id
Expand Down
234 changes: 233 additions & 1 deletion modules/general/app-configuration/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"_generator": {
"name": "bicep",
"version": "0.8.9.13224",
"templateHash": "1514586493810046853"
"templateHash": "10695924962515863488"
}
},
"parameters": {
Expand Down Expand Up @@ -39,6 +39,48 @@
"description": "SKU for the app configuration store"
}
},
"saveConnectionStringsToKeyVault": {
"type": "bool",
"defaultValue": false,
"metadata": {
"description": "When true, the primary connection strings (read/write and read-only) will be written to the specified key vault"
}
},
"keyVaultName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The name of the key vault used to store the connection strings"
}
},
"keyVaultResourceGroupName": {
"type": "string",
"defaultValue": "[resourceGroup().name]",
"metadata": {
"description": "The resource group containing the key vault used to store the connection strings"
}
},
"keyVaultSubscriptionId": {
"type": "string",
"defaultValue": "[subscription().subscriptionId]",
"metadata": {
"description": "The ID of the subscription containing the key vault used to store the connection strings"
}
},
"keyVaultConnectionStringSecretName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The key vault secret name used to store the read/write connection string"
}
},
"keyVaultReadOnlyConnectionStringSecretName": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "The key vault secret name used to store the read-only connection string"
}
},
"useExisting": {
"type": "bool",
"defaultValue": false,
Expand Down Expand Up @@ -71,6 +113,196 @@
"publicNetworkAccess": "[variables('publicNetworkAccess')]"
},
"tags": "[parameters('resourceTags')]"
},
{
"condition": "[parameters('saveConnectionStringsToKeyVault')]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-10-01",
"name": "[format('appConfigConnStrSecretDeploy{0}', parameters('name'))]",
"subscriptionId": "[parameters('keyVaultSubscriptionId')]",
"resourceGroup": "[parameters('keyVaultResourceGroupName')]",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"parameters": {
"keyVaultName": {
"value": "[parameters('keyVaultName')]"
},
"secretName": {
"value": "[parameters('keyVaultConnectionStringSecretName')]"
},
"contentValue": {
"value": "[if(parameters('useExisting'), listKeys(resourceId('Microsoft.AppConfiguration/configurationStores', parameters('name')), '2020-06-01').value[0].connectionString, listKeys(resourceId('Microsoft.AppConfiguration/configurationStores', parameters('name')), '2020-06-01').value[0].connectionString)]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.8.9.13224",
"templateHash": "12015994460177070841"
}
},
"parameters": {
"secretName": {
"type": "string",
"metadata": {
"description": "Enter the secret name."
}
},
"contentType": {
"type": "string",
"defaultValue": "text/plain",
"metadata": {
"description": "Type of the secret"
}
},
"contentValue": {
"type": "secureString",
"defaultValue": "",
"metadata": {
"description": "Value of the secret"
}
},
"keyVaultName": {
"type": "string",
"metadata": {
"description": "Name of the vault"
}
},
"useExisting": {
"type": "bool",
"defaultValue": false,
"metadata": {
"description": "When true, a pre-existing secret will be returned"
}
}
},
"resources": [
{
"condition": "[not(parameters('useExisting'))]",
"type": "Microsoft.KeyVault/vaults/secrets",
"apiVersion": "2021-06-01-preview",
"name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('secretName'))]",
"properties": {
"contentType": "[parameters('contentType')]",
"value": "[parameters('contentValue')]"
}
}
],
"outputs": {
"secretUriWithVersion": {
"type": "string",
"value": "[if(parameters('useExisting'), reference(resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('secretName')), '2021-06-01-preview').secretUriWithVersion, reference(resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('secretName')), '2021-06-01-preview').secretUriWithVersion)]",
"metadata": {
"description": "The key vault URI linking to the new/updated secret"
}
}
}
}
},
"dependsOn": [
"[resourceId('Microsoft.AppConfiguration/configurationStores', parameters('name'))]"
]
},
{
"condition": "[parameters('saveConnectionStringsToKeyVault')]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-10-01",
"name": "[format('appConfigRoConnStrSecretDeploy{0}', parameters('name'))]",
"subscriptionId": "[parameters('keyVaultSubscriptionId')]",
"resourceGroup": "[parameters('keyVaultResourceGroupName')]",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"parameters": {
"keyVaultName": {
"value": "[parameters('keyVaultName')]"
},
"secretName": {
"value": "[parameters('keyVaultReadOnlyConnectionStringSecretName')]"
},
"contentValue": {
"value": "[if(parameters('useExisting'), listKeys(resourceId('Microsoft.AppConfiguration/configurationStores', parameters('name')), '2020-06-01').value[2].connectionString, listKeys(resourceId('Microsoft.AppConfiguration/configurationStores', parameters('name')), '2020-06-01').value[2].connectionString)]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.8.9.13224",
"templateHash": "12015994460177070841"
}
},
"parameters": {
"secretName": {
"type": "string",
"metadata": {
"description": "Enter the secret name."
}
},
"contentType": {
"type": "string",
"defaultValue": "text/plain",
"metadata": {
"description": "Type of the secret"
}
},
"contentValue": {
"type": "secureString",
"defaultValue": "",
"metadata": {
"description": "Value of the secret"
}
},
"keyVaultName": {
"type": "string",
"metadata": {
"description": "Name of the vault"
}
},
"useExisting": {
"type": "bool",
"defaultValue": false,
"metadata": {
"description": "When true, a pre-existing secret will be returned"
}
}
},
"resources": [
{
"condition": "[not(parameters('useExisting'))]",
"type": "Microsoft.KeyVault/vaults/secrets",
"apiVersion": "2021-06-01-preview",
"name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('secretName'))]",
"properties": {
"contentType": "[parameters('contentType')]",
"value": "[parameters('contentValue')]"
}
}
],
"outputs": {
"secretUriWithVersion": {
"type": "string",
"value": "[if(parameters('useExisting'), reference(resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('secretName')), '2021-06-01-preview').secretUriWithVersion, reference(resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('secretName')), '2021-06-01-preview').secretUriWithVersion)]",
"metadata": {
"description": "The key vault URI linking to the new/updated secret"
}
}
}
}
},
"dependsOn": [
"[resourceId('Microsoft.AppConfiguration/configurationStores', parameters('name'))]"
]
}
],
"outputs": {
Expand Down
Loading