From 81756c88bcdc4ecfa41e6300e5ce8e702714f8d4 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Thu, 11 Jul 2024 14:25:02 +1000 Subject: [PATCH] Use AVM for Keyvault --- .cruft.json | 2 +- README.md | 4 +- infra/core/security/keyvault-access.bicep | 22 ------ infra/core/security/keyvault-secret.bicep | 31 --------- infra/core/security/keyvault.bicep | 55 --------------- infra/main.bicep | 85 +++++++++++++++-------- infra/web.bicep | 5 +- 7 files changed, 62 insertions(+), 142 deletions(-) delete mode 100644 infra/core/security/keyvault-access.bicep delete mode 100644 infra/core/security/keyvault-secret.bicep delete mode 100644 infra/core/security/keyvault.bicep diff --git a/.cruft.json b/.cruft.json index 7f691cc..d2a2dd7 100644 --- a/.cruft.json +++ b/.cruft.json @@ -1,6 +1,6 @@ { "template": "https://github.com/Azure-Samples/Azure-Python-Standardization-Template-Generator", - "commit": "619a6b29afba8ca26c528526bc313294d5c414a4", + "commit": "e4c1b9fbb6a7e438ffa4ed1c877a89e2ffc564d8", "checkout": null, "context": { "cookiecutter": { diff --git a/README.md b/README.md index 0b169b1..8b71981 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,10 @@ languages: - python - bicep - html -- css -- scss products: - azure - azure-app-service -- azure-postgresql +- azure-database-postgresql urlFragment: azure-flask-postgres-flexible-appservice name: Deploy Flask Application with PostgreSQL on Azure App Service (Python) description: This project deploys a web application for a space travel agency using Flask with Python, and is set up for easy deployment with the Azure Developer CLI. diff --git a/infra/core/security/keyvault-access.bicep b/infra/core/security/keyvault-access.bicep deleted file mode 100644 index 316775f..0000000 --- a/infra/core/security/keyvault-access.bicep +++ /dev/null @@ -1,22 +0,0 @@ -metadata description = 'Assigns an Azure Key Vault access policy.' -param name string = 'add' - -param keyVaultName string -param permissions object = { secrets: [ 'get', 'list' ] } -param principalId string - -resource keyVaultAccessPolicies 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = { - parent: keyVault - name: name - properties: { - accessPolicies: [ { - objectId: principalId - tenantId: subscription().tenantId - permissions: permissions - } ] - } -} - -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { - name: keyVaultName -} diff --git a/infra/core/security/keyvault-secret.bicep b/infra/core/security/keyvault-secret.bicep deleted file mode 100644 index 7441b29..0000000 --- a/infra/core/security/keyvault-secret.bicep +++ /dev/null @@ -1,31 +0,0 @@ -metadata description = 'Creates or updates a secret in an Azure Key Vault.' -param name string -param tags object = {} -param keyVaultName string -param contentType string = 'string' -@description('The value of the secret. Provide only derived values like blob storage access, but do not hard code any secrets in your templates') -@secure() -param secretValue string - -param enabled bool = true -param exp int = 0 -param nbf int = 0 - -resource keyVaultSecret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = { - name: name - tags: tags - parent: keyVault - properties: { - attributes: { - enabled: enabled - exp: exp - nbf: nbf - } - contentType: contentType - value: secretValue - } -} - -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { - name: keyVaultName -} diff --git a/infra/core/security/keyvault.bicep b/infra/core/security/keyvault.bicep deleted file mode 100644 index 8b8ff75..0000000 --- a/infra/core/security/keyvault.bicep +++ /dev/null @@ -1,55 +0,0 @@ -metadata description = 'Creates an Azure Key Vault.' -param name string -param location string = resourceGroup().location -param logAnalyticsWorkspaceId string -param tags object = {} - -param principalId string = '' - -@description('List of IP addresses or IP address ranges in CIDR format that are allowed to access the key vault.') -param ipRules array = [] - -// Allow all Azure services to bypass Key Vault network rules -param allowAzureServicesAccess bool = true - -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: name - location: location - tags: tags - properties: { - tenantId: subscription().tenantId - sku: { family: 'A', name: 'standard' } - networkAcls: { - bypass: allowAzureServicesAccess ? 'AzureServices' : 'None' - defaultAction: 'Deny' - ipRules: ipRules - virtualNetworkRules: [] - } - enableRbacAuthorization: true - accessPolicies: !empty(principalId) ? [ - { - objectId: principalId - permissions: { secrets: [ 'get', 'list' ] } - tenantId: subscription().tenantId - } - ] : [] - } -} - -resource logs 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { - name: 'logs' - scope: keyVault - properties: { - workspaceId: logAnalyticsWorkspaceId - logs: [ - { - category: 'AuditEvent' - enabled: true - } - ] - } -} - -output endpoint string = keyVault.properties.vaultUri -output id string = keyVault.id -output name string = keyVault.name diff --git a/infra/main.bicep b/infra/main.bicep index 2795f3b..1025741 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -24,6 +24,17 @@ var resourceToken = toLower(uniqueString(subscription().id, name, location)) var prefix = '${name}-${resourceToken}' var tags = { 'azd-env-name': name } +var secrets = [ + { + name: 'DBSERVERPASSWORD' + value: dbserverPassword + } + { + name: 'SECRETKEY' + value: secretKey + } +] + resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { name: '${name}-rg' location: location @@ -31,15 +42,57 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { } // Store secrets in a keyvault -module keyVault './core/security/keyvault.bicep' = { +module keyVault 'br/public:avm/res/key-vault/vault:0.6.2' = { name: 'keyvault' scope: resourceGroup params: { name: '${take(replace(prefix, '-', ''), 17)}-vault' location: location tags: tags - principalId: principalId - logAnalyticsWorkspaceId: monitoring.outputs.logAnalyticsWorkspaceId + sku: 'standard' + enableRbacAuthorization: true + accessPolicies: [ + { + objectId: principalId + permissions: { secrets: ['get', 'list'] } + tenantId: subscription().tenantId + } + ] + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + } + diagnosticSettings: [ + { + logCategoriesAndGroups: [ + { + category: 'AuditEvent' + } + ] + name: 'auditEventLogging' + workspaceResourceId: monitoring.outputs.logAnalyticsWorkspaceId + } + ] + secrets: [ + for secret in secrets: { + name: secret.name + value: secret.value + tags: tags + attributes: { + exp: 0 + nbf: 0 + } + } + ] + } +} + +module roleAssignment 'core/security/role.bicep' = { + name: 'webRoleAssignment' + scope: resourceGroup + params: { + principalId: web.outputs.SERVICE_WEB_IDENTITY_PRINCIPAL_ID + roleDefinitionId: '4633458b-17de-408a-b874-0445c86b69e6' // Key Vault Secrets User } } @@ -87,32 +140,8 @@ module web 'web.bicep' = { } } -var secrets = [ - { - name: 'DBSERVERPASSWORD' - value: dbserverPassword - } - { - name: 'SECRETKEY' - value: secretKey - } -] - -@batchSize(1) -module keyVaultSecrets './core/security/keyvault-secret.bicep' = [ - for secret in secrets: { - name: 'keyvault-secret-${secret.name}' - scope: resourceGroup - params: { - keyVaultName: keyVault.outputs.name - name: secret.name - secretValue: secret.value - } - } -] - output AZURE_LOCATION string = location -output AZURE_KEY_VAULT_ENDPOINT string = keyVault.outputs.endpoint +output AZURE_KEY_VAULT_ENDPOINT string = keyVault.outputs.uri output AZURE_KEY_VAULT_NAME string = keyVault.outputs.name output APPLICATIONINSIGHTS_NAME string = monitoring.outputs.applicationInsightsName diff --git a/infra/web.bicep b/infra/web.bicep index 5fd8b9d..cc84d39 100644 --- a/infra/web.bicep +++ b/infra/web.bicep @@ -54,11 +54,12 @@ module web 'core/host/appservice.bicep' = { } // Give the app access to KeyVault -module webKeyVaultAccess './core/security/keyvault-access.bicep' = { +module webKeyVaultAccess './core/security/role.bicep' = { name: 'web-keyvault-access' params: { - keyVaultName: keyVaultName principalId: web.outputs.identityPrincipalId + principalType: 'ServicePrincipal' + roleDefinitionId: '00482a5a-887f-4fb3-b363-3b7fe8e74483' } }