From f28fa51f0b6c68fc01899d33e8bcced2cf1b84a2 Mon Sep 17 00:00:00 2001 From: Jason Ingram <13699472+ExchMaster@users.noreply.github.com> Date: Tue, 30 Nov 2021 13:23:33 -0600 Subject: [PATCH] Example for Azure KeyVault (Premium, RBAC) (#544) --- src/bicep/examples/keyVault/README.md | 63 +++++++++ .../examples/keyVault/azureKeyVault.bicep | 33 +++++ .../examples/keyVault/azureKeyVault.json | 122 ++++++++++++++++++ .../examples/keyVault/modules/keyVault.bicep | 20 +++ 4 files changed, 238 insertions(+) create mode 100644 src/bicep/examples/keyVault/README.md create mode 100644 src/bicep/examples/keyVault/azureKeyVault.bicep create mode 100644 src/bicep/examples/keyVault/azureKeyVault.json create mode 100644 src/bicep/examples/keyVault/modules/keyVault.bicep diff --git a/src/bicep/examples/keyVault/README.md b/src/bicep/examples/keyVault/README.md new file mode 100644 index 000000000..de56524f4 --- /dev/null +++ b/src/bicep/examples/keyVault/README.md @@ -0,0 +1,63 @@ +# Azure Key Vault Example + +This example deploys a premium Azure Key Vault with RBAC enabled to support secret, key, and certificate management. A premium key vault utilizes hardware security modules to protect key material. Roles for use must be assigned post-deployment, review reference list below for detailed information. + +Read on to understand what this example does, and when you're ready, collect all of the pre-requisites, then deploy the example. + +## What this example does + +### Deploys Azure Key Vault + +The docs on Azure Key Vault: . This sample shows how to deploy using Bicep and utilizes the shared file variable pattern to support the deployment. By default, this template will deploy resources into standard default MLZ subscriptions and resource groups. + +The subscription and resource group can be changed by providing the resource group name (Param: targetResourceGroup) and ensuring that the Azure context is set the proper subscription. + +## Pre-requisites + +1. A Mission LZ deployment (a deployment of mlz.bicep) +2. The outputs from a deployment of mlz.bicep (./src/bicep/examples/deploymentVariables.json). + +See below for information on how to create the appropriate deployment variables file for use with this template. + +### Template Parameters + +Template Parameters Name | Description +-----------------------| ----------- +keyVaultName | The name of key vault. If not specified, the name will default to the MLZ default naming pattern. +targetResourceGroup | The name of the resource group where the key vault will be deployed. If not specified, the resource group name will default to the shared services MLZ resource group name and subscription. + +### Generate MLZ Variable File (deploymentVariables.json) + +For instructions on generating 'deploymentVariables.json' using both Azure PowerShell and Azure CLI, please see the [README at the root of the examples folder](../README.md). + +Place the resulting 'deploymentVariables.json' file within the ./src/bicep/examples folder. + +### Deploying Azure Key Vault + +Connect to the appropriate Azure Environment and set appropriate context, see getting started with Azure PowerShell for help if needed. The commands below assume you are deploying in Azure Commercial and show the entire process from deploying MLZ and then adding a key vault post-deployment. + +```PowerShell +cd .\src\bicep +Connect-AzAccount +New-AzSubscriptionDeployment -Name contoso -TemplateFile .\mlz.bicep -resourcePrefix 'contoso' -Location 'eastus' +cd .\examples +(Get-AzSubscriptionDeployment -Name contoso).outputs | ConvertTo-Json | Out-File -FilePath .\deploymentVariables.json +cd .\keyVault +New-AzSubscriptionDeployment -DeploymentName deployAzureKeyVault -TemplateFile .\azureKeyVault.bicep -Location 'eastus' +``` + +```Azure CLI +az login +cd src/bicep +az deployment sub create -n contoso -f mlz.bicep -l eastus --parameters resourcePrefix=contoso +cd examples +az deployment sub show -n contoso --query properties.outputs > ./deploymentVariables.json +cd keyVault +az deployment sub create -n deployAzureKeyVault -f azureKeyVault.bicep -l eastus +``` + +### References + +* [Azure Key Vault Documentation](https://docs.microsoft.com/en-us/azure/key-vault/) +* [Azure Key Vault Overview](https://docs.microsoft.com/en-us/azure/key-vault/general/overview) +* [Provide access to Key Vault via RBAC](https://docs.microsoft.com/en-us/azure/key-vault/general/rbac-guide?tabs=azure-cli) diff --git a/src/bicep/examples/keyVault/azureKeyVault.bicep b/src/bicep/examples/keyVault/azureKeyVault.bicep new file mode 100644 index 000000000..8962cbe59 --- /dev/null +++ b/src/bicep/examples/keyVault/azureKeyVault.bicep @@ -0,0 +1,33 @@ +/* +Deployes a premium Azure Key Vault to support hardware backed secrets and certificates storage +*/ +targetScope = 'subscription' + +param mlzDeploymentVariables object = json(loadTextContent('../deploymentVariables.json')) + +@description('The name of the key vault which will be created. Must be clobally unique, between 3 and 24 characters and only single hyphens permitted. If unchanged or not specified, the MLZ resource prefix + "-akv" will be utilized.') +param keyVaultName string = '${mlzDeploymentVariables.mlzResourcePrefix.Value}-akv' + +@description('The name of the resource group in which the key vault will be deployed. If unchanged or not specified, the MLZ shared services resource group is used.') +param targetResourceGroup string = '${mlzDeploymentVariables.spokes.Value[2].resourceGroupName}' + +var targetSubscriptionId_Var = targetResourceGroup == '${mlzDeploymentVariables.spokes.Value[2].resourceGroupName}' ? '${mlzDeploymentVariables.spokes.Value[2].subscriptionId}' : subscription().subscriptionId +var location = deployment().location + + +resource targetASPResourceGroup 'Microsoft.Resources/resourceGroups@2020-10-01' = { + name: targetResourceGroup + location: location +} + +module deployAzureKeyVault 'modules/keyVault.bicep' = { + scope: resourceGroup(targetSubscriptionId_Var, targetASPResourceGroup.name) + name: keyVaultName + params: { + keyVaultName: keyVaultName + tenantID: subscription().tenantId + } +} + +output azureKeyVaultName string = keyVaultName +output resourceGroupName string = targetResourceGroup diff --git a/src/bicep/examples/keyVault/azureKeyVault.json b/src/bicep/examples/keyVault/azureKeyVault.json new file mode 100644 index 000000000..096cce146 --- /dev/null +++ b/src/bicep/examples/keyVault/azureKeyVault.json @@ -0,0 +1,122 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1008.15138", + "templateHash": "6558428922943348549" + } + }, + "parameters": { + "mlzDeploymentVariables": { + "type": "object", + "defaultValue": "[json('{\r\n \"mlzResourcePrefix\": {\r\n \"Type\": \"String\",\r\n \"Value\": \"contoso\"\r\n },\r\n \"firewallPrivateIPAddress\": {\r\n \"Type\": \"String\",\r\n \"Value\": \"10.0.100.4\"\r\n },\r\n \"hub\": {\r\n \"Type\": \"Object\",\r\n \"Value\": {\r\n \"subscriptionId\": \"ddf87969-a498-4676-a488-1932fbc5a306\",\r\n \"resourceGroupName\": \"contoso-hub\",\r\n \"resourceGroupResourceId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-hub\",\r\n \"virtualNetworkName\": \"hub-vnet\",\r\n \"virtualNetworkResourceId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-hub/providers/Microsoft.Network/virtualNetworks/hub-vnet\",\r\n \"subnetName\": \"hub-vnet/hub-subnet\",\r\n \"subnetResourceId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-hub/providers/Microsoft.Network/virtualNetworks/hub-vnet/subnets/hub-subnet\",\r\n \"subnetAddressPrefix\": \"10.0.100.128/27\",\r\n \"networkSecurityGroupName\": \"hub-nsg\",\r\n \"networkSecurityGroupResourceId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-hub/providers/Microsoft.Network/networkSecurityGroups/hub-nsg\"\r\n }\r\n },\r\n \"logAnalyticsWorkspaceName\": {\r\n \"Type\": \"String\",\r\n \"Value\": \"contoso-laws\"\r\n },\r\n \"logAnalyticsWorkspaceResourceId\": {\r\n \"Type\": \"String\",\r\n \"Value\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-operations/providers/Microsoft.OperationalInsights/workspaces/contoso-laws\"\r\n },\r\n \"spokes\": {\r\n \"Type\": \"Array\",\r\n \"Value\": [\r\n {\r\n \"name\": \"operations\",\r\n \"subscriptionId\": \"ddf87969-a498-4676-a488-1932fbc5a306\",\r\n \"resourceGroupName\": \"contoso-operations\",\r\n \"resourceGroupId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-operations\",\r\n \"virtualNetworkName\": \"operations-vnet\",\r\n \"virtualNetworkResourceId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-operations/providers/Microsoft.Network/virtualNetworks/operations-vnet\",\r\n \"subnetName\": \"operations-subnet\",\r\n \"subnetResourceId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-operations/providers/Microsoft.Network/virtualNetworks/operations-vnet/subnets/operations-subnet\",\r\n \"subnetAddressPrefix\": \"10.0.115.0/27\",\r\n \"networkSecurityGroupName\": \"operations-nsg\",\r\n \"networkSecurityGroupResourceId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-operations/providers/Microsoft.Network/networkSecurityGroups/operations-nsg\"\r\n },\r\n {\r\n \"name\": \"identity\",\r\n \"subscriptionId\": \"ddf87969-a498-4676-a488-1932fbc5a306\",\r\n \"resourceGroupName\": \"contoso-identity\",\r\n \"resourceGroupId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-identity\",\r\n \"virtualNetworkName\": \"identity-vnet\",\r\n \"virtualNetworkResourceId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-identity/providers/Microsoft.Network/virtualNetworks/identity-vnet\",\r\n \"subnetName\": \"identity-subnet\",\r\n \"subnetResourceId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-identity/providers/Microsoft.Network/virtualNetworks/identity-vnet/subnets/identity-subnet\",\r\n \"subnetAddressPrefix\": \"10.0.110.0/27\",\r\n \"networkSecurityGroupName\": \"identity-nsg\",\r\n \"networkSecurityGroupResourceId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-identity/providers/Microsoft.Network/networkSecurityGroups/identity-nsg\"\r\n },\r\n {\r\n \"name\": \"sharedServices\",\r\n \"subscriptionId\": \"ddf87969-a498-4676-a488-1932fbc5a306\",\r\n \"resourceGroupName\": \"contoso-sharedServices\",\r\n \"resourceGroupId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-sharedServices\",\r\n \"virtualNetworkName\": \"sharedServices-vnet\",\r\n \"virtualNetworkResourceId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-sharedServices/providers/Microsoft.Network/virtualNetworks/sharedServices-vnet\",\r\n \"subnetName\": \"sharedServices-subnet\",\r\n \"subnetResourceId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-sharedServices/providers/Microsoft.Network/virtualNetworks/sharedServices-vnet/subnets/sharedServices-subnet\",\r\n \"subnetAddressPrefix\": \"10.0.120.0/27\",\r\n \"networkSecurityGroupName\": \"sharedServices-nsg\",\r\n \"networkSecurityGroupResourceId\": \"/subscriptions/ddf87969-a498-4676-a488-1932fbc5a306/resourceGroups/contoso-sharedServices/providers/Microsoft.Network/networkSecurityGroups/sharedServices-nsg\"\r\n }\r\n ]\r\n }\r\n}\r\n')]" + }, + "keyVaultName": { + "type": "string", + "defaultValue": "[format('{0}-akv', parameters('mlzDeploymentVariables').mlzResourcePrefix.Value)]", + "metadata": { + "description": "The name of the key vault which will be created. Must be clobally unique, between 3 and 24 characters and only single hyphens permitted. If unchanged or not specified, the MLZ resource prefix + \"-akv\" will be utilized." + } + }, + "targetResourceGroup": { + "type": "string", + "defaultValue": "[format('{0}', parameters('mlzDeploymentVariables').spokes.Value[2].resourceGroupName)]", + "metadata": { + "description": "The name of the resource group in which the key vault will be deployed. If unchanged or not specified, the MLZ shared services resource group is used." + } + } + }, + "functions": [], + "variables": { + "targetSubscriptionId_Var": "[if(equals(parameters('targetResourceGroup'), format('{0}', parameters('mlzDeploymentVariables').spokes.Value[2].resourceGroupName)), format('{0}', parameters('mlzDeploymentVariables').spokes.Value[2].subscriptionId), subscription().subscriptionId)]", + "location": "[deployment().location]" + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2020-10-01", + "name": "[parameters('targetResourceGroup')]", + "location": "[variables('location')]" + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-06-01", + "name": "[parameters('keyVaultName')]", + "subscriptionId": "[variables('targetSubscriptionId_Var')]", + "resourceGroup": "[parameters('targetResourceGroup')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "keyVaultName": { + "value": "[parameters('keyVaultName')]" + }, + "tenantID": { + "value": "[subscription().tenantId]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1008.15138", + "templateHash": "15112517158840559321" + } + }, + "parameters": { + "keyVaultName": { + "type": "string" + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]" + }, + "tenantID": { + "type": "string" + } + }, + "functions": [], + "resources": [ + { + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2019-09-01", + "name": "[parameters('keyVaultName')]", + "location": "[parameters('location')]", + "properties": { + "sku": { + "family": "A", + "name": "premium" + }, + "tenantId": "[parameters('tenantID')]", + "enabledForDeployment": true, + "enabledForTemplateDeployment": true, + "enableSoftDelete": true, + "softDeleteRetentionInDays": 7, + "enableRbacAuthorization": true + } + } + ] + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('targetResourceGroup'))]" + ] + } + ], + "outputs": { + "azureKeyVaultName": { + "type": "string", + "value": "[parameters('keyVaultName')]" + }, + "resourceGroupName": { + "type": "string", + "value": "[parameters('targetResourceGroup')]" + } + } +} \ No newline at end of file diff --git a/src/bicep/examples/keyVault/modules/keyVault.bicep b/src/bicep/examples/keyVault/modules/keyVault.bicep new file mode 100644 index 000000000..0958c915b --- /dev/null +++ b/src/bicep/examples/keyVault/modules/keyVault.bicep @@ -0,0 +1,20 @@ +param keyVaultName string +param location string = resourceGroup().location +param tenantID string + +resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'premium' + } + tenantId: tenantID + enabledForDeployment: true + enabledForTemplateDeployment: true + enableSoftDelete: true + softDeleteRetentionInDays: 7 + enableRbacAuthorization: true + } +}