From 9d185d495f9fba3230b79a05a26c5a57bc6a8cf6 Mon Sep 17 00:00:00 2001 From: Matthew Fortunka <mafortun@microsoft.com> Date: Mon, 9 Sep 2024 11:04:37 +0000 Subject: [PATCH 01/26] added management key vault --- config.sample.yaml | 2 ++ devops/terraform/main.tf | 13 +++++++++++++ devops/terraform/variables.tf | 5 +++++ 3 files changed, 20 insertions(+) diff --git a/config.sample.yaml b/config.sample.yaml index 77ce40d68c..43869ca74f 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -8,6 +8,8 @@ management: mgmt_storage_account_name: __CHANGE_ME__ terraform_state_container_name: tfstate acr_name: __CHANGE_ME__ + # Key Vault for encryption keys + keyvault_name: __CHANGE_ME__ # Azure Resource Manager credentials used for CI/CD pipelines arm_subscription_id: __CHANGE_ME__ diff --git a/devops/terraform/main.tf b/devops/terraform/main.tf index 2504e790ca..2e7ac8b272 100644 --- a/devops/terraform/main.tf +++ b/devops/terraform/main.tf @@ -2,6 +2,8 @@ provider "azurerm" { features {} } +data "azurerm_client_config" "current" {} + # Resource group for TRE core management resource "azurerm_resource_group" "mgmt" { name = var.mgmt_resource_group_name @@ -64,3 +66,14 @@ EOF enabled = true } } + +# Key Vault for encryption keys + +resource "azurerm_key_vault" "shared_kv" { + name = var.keyvault_name + resource_group_name = azurerm_resource_group.mgmt.name + location = azurerm_resource_group.mgmt.location + enabled_for_disk_encryption = true + sku_name = "standard" + tenant_id = data.azurerm_client_config.current.tenant_id +} \ No newline at end of file diff --git a/devops/terraform/variables.tf b/devops/terraform/variables.tf index 155193098c..c5221ec339 100644 --- a/devops/terraform/variables.tf +++ b/devops/terraform/variables.tf @@ -23,3 +23,8 @@ variable "acr_name" { type = string description = "Name of ACR" } + +variable "keyvault_name" { + type = string + description = "Name of Key Vault" +} From 3bab6282dc6c79c648ea1931abf68bc5d0d83cf2 Mon Sep 17 00:00:00 2001 From: Matthew Fortunka <mafortun@microsoft.com> Date: Wed, 11 Sep 2024 15:29:34 +0000 Subject: [PATCH 02/26] added cmk for vmss and storage accounts --- config.sample.yaml | 9 +- core/terraform/airlock/airlock_processor.tf | 22 ++++ core/terraform/airlock/data.tf | 5 + core/terraform/airlock/storage_accounts.tf | 112 ++++++++++++++++++ core/terraform/airlock/variables.tf | 20 ++++ core/terraform/appgateway/data.tf | 6 + core/terraform/appgateway/staticweb.tf | 22 ++++ core/terraform/appgateway/variables.tf | 19 +++ core/terraform/azure-monitor/azure-monitor.tf | 22 ++++ core/terraform/azure-monitor/data.tf | 5 + core/terraform/azure-monitor/variables.tf | 19 +++ core/terraform/data.tf | 6 + core/terraform/encryption_identity.tf | 17 +++ core/terraform/main.tf | 27 ++++- .../resource_processor/vmss_porter/data.tf | 12 ++ .../resource_processor/vmss_porter/main.tf | 33 +++++- .../vmss_porter/variables.tf | 15 +++ core/terraform/storage.tf | 31 ++++- core/terraform/variables.tf | 18 +++ devops/terraform/main.tf | 43 ++++++- devops/terraform/variables.tf | 24 +++- 21 files changed, 471 insertions(+), 16 deletions(-) create mode 100644 core/terraform/airlock/data.tf create mode 100644 core/terraform/azure-monitor/data.tf create mode 100644 core/terraform/encryption_identity.tf diff --git a/config.sample.yaml b/config.sample.yaml index 43869ca74f..f0828eb13c 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -8,8 +8,8 @@ management: mgmt_storage_account_name: __CHANGE_ME__ terraform_state_container_name: tfstate acr_name: __CHANGE_ME__ - # Key Vault for encryption keys - keyvault_name: __CHANGE_ME__ + # Key Vault for encryption keys (will only be used when enable_cmk_encryption is true) + kv_name: __CHANGE_ME__ # Azure Resource Manager credentials used for CI/CD pipelines arm_subscription_id: __CHANGE_ME__ @@ -79,7 +79,10 @@ developer_settings: # This setting will enable your local machine to be able to # communicate with Service Bus and Cosmos. It will also allow deploying # the base workspace. -# enable_local_debugging: true +# enable_local_debugging: true + +# This setting will enable customer managed key encryption for all resources +# enable_cmk_encryption: true # Used by the API and Resource processor application to change log level # Can be "ERROR", "WARNING", "INFO", "DEBUG" diff --git a/core/terraform/airlock/airlock_processor.tf b/core/terraform/airlock/airlock_processor.tf index 1c4ad35130..c97c010840 100644 --- a/core/terraform/airlock/airlock_processor.tf +++ b/core/terraform/airlock/airlock_processor.tf @@ -27,9 +27,31 @@ resource "azurerm_storage_account" "sa_airlock_processor_func_app" { allow_nested_items_to_be_public = false tags = var.tre_core_tags + dynamic "identity" { + for_each = var.enable_cmk_encryption ? [1] : [] + content { + type = "UserAssigned" + identity_ids = [var.encryption_identity_id] + } + } + lifecycle { ignore_changes = [tags] } } +resource "azurerm_storage_account_customer_managed_key" "sa_airlock_processor_func_app_encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + storage_account_id = azurerm_storage_account.sa_airlock_processor_func_app.id + key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_name = var.kv_encryption_key_name + user_assigned_identity_id = var.encryption_identity_id + + lifecycle { + ignore_changes = [ + key_vault_id + ] + } +} + resource "azurerm_linux_function_app" "airlock_function_app" { name = local.airlock_function_app_name resource_group_name = var.resource_group_name diff --git a/core/terraform/airlock/data.tf b/core/terraform/airlock/data.tf new file mode 100644 index 0000000000..d19ec72f50 --- /dev/null +++ b/core/terraform/airlock/data.tf @@ -0,0 +1,5 @@ +data "azurerm_key_vault" "mgmt_kv" { + count = var.enable_cmk_encryption ? 1 : 0 + name = var.kv_name + resource_group_name = var.mgmt_resource_group_name +} \ No newline at end of file diff --git a/core/terraform/airlock/storage_accounts.tf b/core/terraform/airlock/storage_accounts.tf index 6a76b97f02..59383e3791 100644 --- a/core/terraform/airlock/storage_accounts.tf +++ b/core/terraform/airlock/storage_accounts.tf @@ -1,3 +1,5 @@ + + # 'External' storage account - drop location for import resource "azurerm_storage_account" "sa_import_external" { name = local.import_external_storage_name @@ -13,6 +15,14 @@ resource "azurerm_storage_account" "sa_import_external" { # This is true ONLY when Hierarchical Namespace is DISABLED is_hns_enabled = false + dynamic "identity" { + for_each = var.enable_cmk_encryption ? [1] : [] + content { + type = "UserAssigned" + identity_ids = [var.encryption_identity_id] + } + } + tags = merge(var.tre_core_tags, { description = "airlock;import;external" }) @@ -42,6 +52,20 @@ resource "azurerm_private_endpoint" "stg_import_external_pe" { } } +resource "azurerm_storage_account_customer_managed_key" "sa_import_external_encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + storage_account_id = azurerm_storage_account.sa_import_external.id + key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_name = var.kv_encryption_key_name + user_assigned_identity_id = var.encryption_identity_id + + lifecycle { + ignore_changes = [ + key_vault_id + ] + } +} + # 'Approved' export resource "azurerm_storage_account" "sa_export_approved" { name = local.export_approved_storage_name @@ -57,6 +81,14 @@ resource "azurerm_storage_account" "sa_export_approved" { # This is true ONLY when Hierarchical Namespace is DISABLED is_hns_enabled = false + dynamic "identity" { + for_each = var.enable_cmk_encryption ? [1] : [] + content { + type = "UserAssigned" + identity_ids = [var.encryption_identity_id] + } + } + tags = merge(var.tre_core_tags, { description = "airlock;export;approved" }) @@ -86,6 +118,20 @@ resource "azurerm_private_endpoint" "stg_export_approved_pe" { } } +resource "azurerm_storage_account_customer_managed_key" "sa_export_approved_encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + storage_account_id = azurerm_storage_account.sa_export_approved.id + key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_name = var.kv_encryption_key_name + user_assigned_identity_id = var.encryption_identity_id + + lifecycle { + ignore_changes = [ + key_vault_id + ] + } +} + # 'In-Progress' storage account resource "azurerm_storage_account" "sa_import_in_progress" { name = local.import_in_progress_storage_name @@ -99,6 +145,14 @@ resource "azurerm_storage_account" "sa_import_in_progress" { # This is true ONLY when Hierarchical Namespace is DISABLED is_hns_enabled = false + dynamic "identity" { + for_each = var.enable_cmk_encryption ? [1] : [] + content { + type = "UserAssigned" + identity_ids = [var.encryption_identity_id] + } + } + tags = merge(var.tre_core_tags, { description = "airlock;import;in-progress" }) @@ -111,6 +165,20 @@ resource "azurerm_storage_account" "sa_import_in_progress" { lifecycle { ignore_changes = [tags] } } +resource "azurerm_storage_account_customer_managed_key" "sa_import_in_progress_encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + storage_account_id = azurerm_storage_account.sa_import_in_progress.id + key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_name = var.kv_encryption_key_name + user_assigned_identity_id = var.encryption_identity_id + + lifecycle { + ignore_changes = [ + key_vault_id + ] + } +} + # Enable Airlock Malware Scanning on Core TRE resource "azapi_resource_action" "enable_defender_for_storage" { @@ -173,6 +241,14 @@ resource "azurerm_storage_account" "sa_import_rejected" { # This is true ONLY when Hierarchical Namespace is DISABLED is_hns_enabled = false + dynamic "identity" { + for_each = var.enable_cmk_encryption ? [1] : [] + content { + type = "UserAssigned" + identity_ids = [var.encryption_identity_id] + } + } + tags = merge(var.tre_core_tags, { description = "airlock;import;rejected" }) @@ -208,6 +284,20 @@ resource "azurerm_private_endpoint" "stg_import_rejected_pe" { lifecycle { ignore_changes = [tags] } } +resource "azurerm_storage_account_customer_managed_key" "sa_import_rejected_encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + storage_account_id = azurerm_storage_account.sa_import_rejected.id + key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_name = var.kv_encryption_key_name + user_assigned_identity_id = var.encryption_identity_id + + lifecycle { + ignore_changes = [ + key_vault_id + ] + } +} + # 'Blocked' storage account resource "azurerm_storage_account" "sa_import_blocked" { name = local.import_blocked_storage_name @@ -221,6 +311,14 @@ resource "azurerm_storage_account" "sa_import_blocked" { # This is true ONLY when Hierarchical Namespace is DISABLED is_hns_enabled = false + dynamic "identity" { + for_each = var.enable_cmk_encryption ? [1] : [] + content { + type = "UserAssigned" + identity_ids = [var.encryption_identity_id] + } + } + tags = merge(var.tre_core_tags, { description = "airlock;import;blocked" }) @@ -255,3 +353,17 @@ resource "azurerm_private_endpoint" "stg_import_blocked_pe" { lifecycle { ignore_changes = [tags] } } + +resource "azurerm_storage_account_customer_managed_key" "sa_import_blocked_encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + storage_account_id = azurerm_storage_account.sa_import_blocked.id + key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_name = var.kv_encryption_key_name + user_assigned_identity_id = var.encryption_identity_id + + lifecycle { + ignore_changes = [ + key_vault_id + ] + } +} diff --git a/core/terraform/airlock/variables.tf b/core/terraform/airlock/variables.tf index 3cf167705a..a37b7e4b76 100644 --- a/core/terraform/airlock/variables.tf +++ b/core/terraform/airlock/variables.tf @@ -91,3 +91,23 @@ variable "queue_core_dns_zone_id" { variable "table_core_dns_zone_id" { type = string } + +variable "encryption_identity_id" { + type = string + description = "User Managed Identity with permissions to get encryption keys from key vault" +} + +variable "enable_cmk_encryption" { + type = bool + description = "A boolean indicating if key vault will be deployed for customer managed key encryption" +} + +variable "kv_name" { + type = string + description = "Name of Key Vault (only used if enable_cmk_encryption is true)" +} + +variable "kv_encryption_key_name" { + type = string + description = "Name of Key Vault Encryption Key (only used if enable_cmk_encryption is true)" +} diff --git a/core/terraform/appgateway/data.tf b/core/terraform/appgateway/data.tf index 702f013a59..b606dd2603 100644 --- a/core/terraform/appgateway/data.tf +++ b/core/terraform/appgateway/data.tf @@ -6,3 +6,9 @@ data "azurerm_monitor_diagnostic_categories" "agw" { azurerm_application_gateway.agw ] } + +data "azurerm_key_vault" "mgmt_kv" { + count = var.enable_cmk_encryption ? 1 : 0 + name = var.kv_name + resource_group_name = var.mgmt_resource_group_name +} diff --git a/core/terraform/appgateway/staticweb.tf b/core/terraform/appgateway/staticweb.tf index 98a2977855..cbceaf626e 100644 --- a/core/terraform/appgateway/staticweb.tf +++ b/core/terraform/appgateway/staticweb.tf @@ -21,6 +21,28 @@ resource "azurerm_storage_account" "staticweb" { bypass = ["AzureServices"] default_action = "Deny" } + + dynamic "identity" { + for_each = var.enable_cmk_encryption ? [1] : [] + content { + type = "UserAssigned" + identity_ids = [var.encryption_identity_id] + } + } +} + +resource "azurerm_storage_account_customer_managed_key" "staticweb_encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + storage_account_id = azurerm_storage_account.staticweb.id + key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_name = var.kv_encryption_key_name + user_assigned_identity_id = var.encryption_identity_id + + lifecycle { + ignore_changes = [ + key_vault_id + ] + } } # Assign the "Storage Blob Data Contributor" role needed for uploading certificates to the storage account diff --git a/core/terraform/appgateway/variables.tf b/core/terraform/appgateway/variables.tf index 1df1087e88..7a9ff1cab0 100644 --- a/core/terraform/appgateway/variables.tf +++ b/core/terraform/appgateway/variables.tf @@ -26,3 +26,22 @@ variable "static_web_dns_zone_id" { variable "log_analytics_workspace_id" { type = string } +variable "mgmt_resource_group_name" { + type = string +} +variable "encryption_identity_id" { + type = string + description = "User Managed Identity with permissions to get encryption keys from key vault" +} +variable "enable_cmk_encryption" { + type = bool + description = "A boolean indicating if key vault will be deployed for customer managed key encryption" +} +variable "kv_name" { + type = string + description = "Name of Key Vault (only used if enable_cmk_encryption is true)" +} +variable "kv_encryption_key_name" { + type = string + description = "Name of Key Vault Encryption Key (only used if enable_cmk_encryption is true)" +} diff --git a/core/terraform/azure-monitor/azure-monitor.tf b/core/terraform/azure-monitor/azure-monitor.tf index d3ba5b411c..0456202abd 100644 --- a/core/terraform/azure-monitor/azure-monitor.tf +++ b/core/terraform/azure-monitor/azure-monitor.tf @@ -28,9 +28,31 @@ resource "azurerm_storage_account" "az_monitor" { bypass = ["AzureServices"] } + dynamic "identity" { + for_each = var.enable_cmk_encryption ? [1] : [] + content { + type = "UserAssigned" + identity_ids = [var.encryption_identity_id] + } + } + lifecycle { ignore_changes = [tags] } } +resource "azurerm_storage_account_customer_managed_key" "az_monitor_encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + storage_account_id = azurerm_storage_account.az_monitor.id + key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_name = var.kv_encryption_key_name + user_assigned_identity_id = var.encryption_identity_id + + lifecycle { + ignore_changes = [ + key_vault_id + ] + } +} + resource "azurerm_log_analytics_linked_storage_account" "workspace_storage_ingestion" { data_source_type = "Ingestion" resource_group_name = var.resource_group_name diff --git a/core/terraform/azure-monitor/data.tf b/core/terraform/azure-monitor/data.tf new file mode 100644 index 0000000000..d19ec72f50 --- /dev/null +++ b/core/terraform/azure-monitor/data.tf @@ -0,0 +1,5 @@ +data "azurerm_key_vault" "mgmt_kv" { + count = var.enable_cmk_encryption ? 1 : 0 + name = var.kv_name + resource_group_name = var.mgmt_resource_group_name +} \ No newline at end of file diff --git a/core/terraform/azure-monitor/variables.tf b/core/terraform/azure-monitor/variables.tf index 6debd34f29..34ff39e752 100644 --- a/core/terraform/azure-monitor/variables.tf +++ b/core/terraform/azure-monitor/variables.tf @@ -31,3 +31,22 @@ variable "tre_core_tags" { variable "enable_local_debugging" { type = bool } +variable "mgmt_resource_group_name" { + type = string +} +variable "encryption_identity_id" { + type = string + description = "User Managed Identity with permissions to get encryption keys from key vault" +} +variable "enable_cmk_encryption" { + type = bool + description = "A boolean indicating if key vault will be deployed for customer managed key encryption" +} +variable "kv_name" { + type = string + description = "Name of Key Vault (only used if enable_cmk_encryption is true)" +} +variable "kv_encryption_key_name" { + type = string + description = "Name of Key Vault Encryption Key (only used if enable_cmk_encryption is true)" +} diff --git a/core/terraform/data.tf b/core/terraform/data.tf index f2dd4630e1..3fcfccab6f 100644 --- a/core/terraform/data.tf +++ b/core/terraform/data.tf @@ -32,3 +32,9 @@ data "azurerm_monitor_diagnostic_categories" "sb" { azurerm_servicebus_namespace.sb ] } + +data "azurerm_key_vault" "mgmt_kv" { + count = var.enable_cmk_encryption ? 1 : 0 + name = var.kv_name + resource_group_name = var.mgmt_resource_group_name +} \ No newline at end of file diff --git a/core/terraform/encryption_identity.tf b/core/terraform/encryption_identity.tf new file mode 100644 index 0000000000..af643d5f08 --- /dev/null +++ b/core/terraform/encryption_identity.tf @@ -0,0 +1,17 @@ +resource "azurerm_user_assigned_identity" "encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + resource_group_name = azurerm_resource_group.core.name + location = azurerm_resource_group.core.location + tags = local.tre_core_tags + + name = "id-encryption-${var.tre_id}" + + lifecycle { ignore_changes = [tags] } +} + +resource "azurerm_role_assignment" "kv_encryption_key_user" { + count = var.enable_cmk_encryption ? 1 : 0 + scope = data.azurerm_key_vault.mgmt_kv[0].id + role_definition_name = "Key Vault Crypto Service Encryption User" + principal_id = azurerm_user_assigned_identity.encryption[0].principal_id +} \ No newline at end of file diff --git a/core/terraform/main.tf b/core/terraform/main.tf index 4e8fa6932f..50b5a3a9b2 100644 --- a/core/terraform/main.tf +++ b/core/terraform/main.tf @@ -73,9 +73,15 @@ module "azure_monitor" { blob_core_dns_zone_id = module.network.blob_core_dns_zone_id tre_core_tags = local.tre_core_tags enable_local_debugging = var.enable_local_debugging + enable_cmk_encryption = var.enable_cmk_encryption + kv_name = var.kv_name + kv_encryption_key_name = var.kv_encryption_key_name + encryption_identity_id = azurerm_user_assigned_identity.encryption[0].id + mgmt_resource_group_name = var.mgmt_resource_group_name depends_on = [ - module.network + module.network, + azurerm_role_assignment.kv_encryption_key_user[0] ] } @@ -99,12 +105,17 @@ module "appgateway" { keyvault_id = azurerm_key_vault.kv.id static_web_dns_zone_id = module.network.static_web_dns_zone_id log_analytics_workspace_id = module.azure_monitor.log_analytics_workspace_id - + enable_cmk_encryption = var.enable_cmk_encryption + kv_name = var.kv_name + kv_encryption_key_name = var.kv_encryption_key_name + encryption_identity_id = azurerm_user_assigned_identity.encryption[0].id + mgmt_resource_group_name = var.mgmt_resource_group_name depends_on = [ module.network, azurerm_key_vault.kv, azurerm_key_vault_access_policy.deployer, - azurerm_private_endpoint.api_private_endpoint + azurerm_private_endpoint.api_private_endpoint, + azurerm_role_assignment.kv_encryption_key_user[0] ] } @@ -134,10 +145,15 @@ module "airlock_resources" { enable_local_debugging = var.enable_local_debugging myip = local.myip + enable_cmk_encryption = var.enable_cmk_encryption + kv_name = var.kv_name + kv_encryption_key_name = var.kv_encryption_key_name + encryption_identity_id = azurerm_user_assigned_identity.encryption[0].id depends_on = [ azurerm_servicebus_namespace.sb, - module.network + module.network, + azurerm_role_assignment.kv_encryption_key_user[0] ] } @@ -169,6 +185,9 @@ module "resource_processor_vmss_porter" { logging_level = var.logging_level firewall_sku = var.firewall_sku rp_bundle_values = var.rp_bundle_values + enable_cmk_encryption = var.enable_cmk_encryption + kv_name = var.kv_name + kv_encryption_key_name = var.kv_encryption_key_name depends_on = [ module.network, diff --git a/core/terraform/resource_processor/vmss_porter/data.tf b/core/terraform/resource_processor/vmss_porter/data.tf index 8f2f2d3ccd..788fa7c78c 100644 --- a/core/terraform/resource_processor/vmss_porter/data.tf +++ b/core/terraform/resource_processor/vmss_porter/data.tf @@ -45,3 +45,15 @@ data "template_cloudinit_config" "config" { } } +data "azurerm_key_vault" "mgmt_kv" { + count = var.enable_cmk_encryption ? 1 : 0 + name = var.kv_name + resource_group_name = var.mgmt_resource_group_name +} + +data "azurerm_key_vault_key" "encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + name = var.kv_encryption_key_name + key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id +} + diff --git a/core/terraform/resource_processor/vmss_porter/main.tf b/core/terraform/resource_processor/vmss_porter/main.tf index a361a42faa..7d265b4920 100644 --- a/core/terraform/resource_processor/vmss_porter/main.tf +++ b/core/terraform/resource_processor/vmss_porter/main.tf @@ -50,6 +50,25 @@ resource "azurerm_user_assigned_identity" "vmss_msi" { lifecycle { ignore_changes = [tags] } } +resource "azurerm_disk_encryption_set" "vmss_disk_encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + name = "vmss-disk-encryption-rp-porter-${var.tre_id}" + location = var.location + resource_group_name = var.resource_group_name + key_vault_key_id = data.azurerm_key_vault_key.encryption[0].versionless_id + encryption_type = "EncryptionAtRestWithPlatformAndCustomerKeys" + auto_key_rotation_enabled = true + + identity { + type = "UserAssigned" + identity_ids = [azurerm_user_assigned_identity.vmss_msi.id] + } + + depends_on = [ + azurerm_role_assignment.vmss_kv_encryption_key_user + ] +} + resource "azurerm_linux_virtual_machine_scale_set" "vm_linux" { name = "vmss-rp-porter-${var.tre_id}" location = var.location @@ -113,9 +132,10 @@ resource "azurerm_linux_virtual_machine_scale_set" "vm_linux" { } os_disk { - storage_account_type = "Standard_LRS" - caching = "ReadWrite" - disk_size_gb = 64 + storage_account_type = "Standard_LRS" + caching = "ReadWrite" + disk_size_gb = 64 + disk_encryption_set_id = var.enable_cmk_encryption ? azurerm_disk_encryption_set.vmss_disk_encryption[0].id : null } network_interface { @@ -192,6 +212,13 @@ resource "azurerm_key_vault_access_policy" "resource_processor" { certificate_permissions = ["Get", "Recover", "Import", "Delete", "Purge"] } +resource "azurerm_role_assignment" "vmss_kv_encryption_key_user" { + count = var.enable_cmk_encryption ? 1 : 0 + scope = data.azurerm_key_vault.mgmt_kv[0].id + role_definition_name = "Key Vault Crypto Service Encryption User" + principal_id = azurerm_user_assigned_identity.vmss_msi.principal_id +} + module "terraform_azurerm_environment_configuration" { source = "git::https://github.com/microsoft/terraform-azurerm-environment-configuration.git?ref=0.2.0" arm_environment = var.arm_environment diff --git a/core/terraform/resource_processor/vmss_porter/variables.tf b/core/terraform/resource_processor/vmss_porter/variables.tf index 8c2b835fa0..fb7cd3b11b 100644 --- a/core/terraform/resource_processor/vmss_porter/variables.tf +++ b/core/terraform/resource_processor/vmss_porter/variables.tf @@ -79,3 +79,18 @@ variable "rp_bundle_values" { locals { rp_bundle_values_formatted = join("\n ", [for key in keys(var.rp_bundle_values) : "RP_BUNDLE_${key}=${var.rp_bundle_values[key]}"]) } + +variable "enable_cmk_encryption" { + type = bool + description = "A boolean indicating if key vault will be deployed for customer managed key encryption" +} + +variable "kv_name" { + type = string + description = "Name of Key Vault (only used if enable_cmk_encryption is true)" +} + +variable "kv_encryption_key_name" { + type = string + description = "Name of Key Vault Encryption Key (only used if enable_cmk_encryption is true)" +} diff --git a/core/terraform/storage.tf b/core/terraform/storage.tf index 5b5d425cb8..26ca4f6457 100644 --- a/core/terraform/storage.tf +++ b/core/terraform/storage.tf @@ -5,7 +5,18 @@ resource "azurerm_storage_account" "stg" { account_tier = "Standard" account_replication_type = "LRS" allow_nested_items_to_be_public = false - tags = local.tre_core_tags + + dynamic "identity" { + for_each = var.enable_cmk_encryption ? [1] : [] + content { + type = "UserAssigned" + identity_ids = [azurerm_user_assigned_identity.encryption[0].id] + } + } + + tags = local.tre_core_tags + + lifecycle { ignore_changes = [tags] } } @@ -67,3 +78,21 @@ resource "azurerm_private_endpoint" "filepe" { azurerm_private_endpoint.blobpe ] } + +resource "azurerm_storage_account_customer_managed_key" "encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + storage_account_id = azurerm_storage_account.stg.id + key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_name = var.kv_encryption_key_name + user_assigned_identity_id = azurerm_user_assigned_identity.encryption[0].id + + depends_on = [ + azurerm_role_assignment.kv_encryption_key_user[0] + ] + + lifecycle { + ignore_changes = [ + key_vault_id + ] + } +} diff --git a/core/terraform/variables.tf b/core/terraform/variables.tf index 478325be7a..168bba3a94 100644 --- a/core/terraform/variables.tf +++ b/core/terraform/variables.tf @@ -212,3 +212,21 @@ variable "logging_level" { error_message = "logging_level must be one of ERROR, WARNING, INFO, DEBUG" } } + +variable "enable_cmk_encryption" { + type = bool + description = "A boolean indicating if key vault will be deployed for customer managed key encryption" + default = false +} + +variable "kv_name" { + type = string + description = "Name of Key Vault (only used if enable_cmk_encryption is true)" +} + +variable "kv_encryption_key_name" { + type = string + description = "Name of Key Vault Encryption Key (only used if enable_cmk_encryption is true)" + default = "tre-encryption" +} + diff --git a/devops/terraform/main.tf b/devops/terraform/main.tf index 2e7ac8b272..ffef4f369a 100644 --- a/devops/terraform/main.tf +++ b/devops/terraform/main.tf @@ -68,12 +68,49 @@ EOF } # Key Vault for encryption keys - resource "azurerm_key_vault" "shared_kv" { - name = var.keyvault_name + count = var.enable_cmk_encryption ? 1 : 0 + name = var.kv_name resource_group_name = azurerm_resource_group.mgmt.name location = azurerm_resource_group.mgmt.location enabled_for_disk_encryption = true sku_name = "standard" tenant_id = data.azurerm_client_config.current.tenant_id -} \ No newline at end of file + enable_rbac_authorization = true + + # Purge protection needs to be enabled for customer managed key encryption + purge_protection_enabled = true + + lifecycle { ignore_changes = [tags] } +} + +resource "azurerm_role_assignment" "current_user_to_key_vault_crypto_officer" { + count = var.enable_cmk_encryption ? 1 : 0 + scope = azurerm_key_vault.shared_kv[0].id + role_definition_name = "Key Vault Crypto Officer" + principal_id = data.azurerm_client_config.current.object_id +} + +# Key used to encrypt resources +resource "azurerm_key_vault_key" "encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + + name = var.kv_encryption_key_name + key_vault_id = azurerm_key_vault.shared_kv[0].id + key_type = "RSA" + key_size = 2048 + + key_opts = [ + "decrypt", + "encrypt", + "sign", + "unwrapKey", + "verify", + "wrapKey", + ] + + depends_on = [ + azurerm_role_assignment.current_user_to_key_vault_crypto_officer + ] +} + diff --git a/devops/terraform/variables.tf b/devops/terraform/variables.tf index c5221ec339..e324ea1342 100644 --- a/devops/terraform/variables.tf +++ b/devops/terraform/variables.tf @@ -24,7 +24,27 @@ variable "acr_name" { description = "Name of ACR" } -variable "keyvault_name" { +variable "kv_purge_protection_enabled" { + type = bool + description = "A boolean indicating if the purge protection will be enabled on the core keyvault." + default = true +} + +variable "enable_cmk_encryption" { + type = bool + description = "A boolean indicating if key vault will be deployed for customer managed key encryption" + default = false +} + +variable "kv_name" { type = string - description = "Name of Key Vault" + description = "Name of Key Vault (only used if enable_cmk_encryption is true)" } + +variable "kv_encryption_key_name" { + type = string + description = "Name of Key Vault Encryption Key (only used if enable_cmk_encryption is true)" + default = "tre-encryption" +} + + From 036b90e07d6f885556654eaf3d3e730f57a0a659 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Wed, 13 Nov 2024 14:27:30 +0000 Subject: [PATCH 03/26] add default value for variables --- config.sample.yaml | 4 ++-- core/terraform/.terraform.lock.hcl | 3 ++- core/terraform/airlock/variables.tf | 1 + core/terraform/appgateway/variables.tf | 1 + core/terraform/azure-monitor/variables.tf | 1 + core/terraform/resource_processor/vmss_porter/variables.tf | 1 + core/terraform/variables.tf | 1 + devops/terraform/main.tf | 2 +- devops/terraform/variables.tf | 1 + 9 files changed, 11 insertions(+), 4 deletions(-) diff --git a/config.sample.yaml b/config.sample.yaml index acfbc9f00f..73ba09020e 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -8,7 +8,7 @@ management: mgmt_storage_account_name: __CHANGE_ME__ terraform_state_container_name: tfstate acr_name: __CHANGE_ME__ - # Key Vault for encryption keys (will only be used when enable_cmk_encryption is true) + # Key Vault for encryption keys (only required if enable_cmk_encryption is true) kv_name: __CHANGE_ME__ # Azure Resource Manager credentials used for CI/CD pipelines arm_subscription_id: __CHANGE_ME__ @@ -82,7 +82,7 @@ developer_settings: # the base workspace. # enable_local_debugging: true -# This setting will enable customer managed key encryption for all resources +# This setting enables customer-managed key encryption for all supported resources # enable_cmk_encryption: true # Used by the API and Resource processor application to change log level diff --git a/core/terraform/.terraform.lock.hcl b/core/terraform/.terraform.lock.hcl index 0539020952..bc7c2d0508 100644 --- a/core/terraform/.terraform.lock.hcl +++ b/core/terraform/.terraform.lock.hcl @@ -3,8 +3,9 @@ provider "registry.terraform.io/azure/azapi" { version = "1.15.0" - constraints = "1.15.0" + constraints = ">= 1.15.0, ~> 1.15.0" hashes = [ + "h1:Y7ruMuPh8UJRTRl4rm+cdpGtmURx2taqiuqfYaH3o48=", "h1:gIOgxVmFSxHrR+XOzgUEA+ybOmp8kxZlZH3eYeB/eFI=", "zh:0627a8bc77254debc25dc0c7b62e055138217c97b03221e593c3c56dc7550671", "zh:2fe045f07070ef75d0bec4b0595a74c14394daa838ddb964e2fd23cc98c40c34", diff --git a/core/terraform/airlock/variables.tf b/core/terraform/airlock/variables.tf index a37b7e4b76..bf18922db8 100644 --- a/core/terraform/airlock/variables.tf +++ b/core/terraform/airlock/variables.tf @@ -105,6 +105,7 @@ variable "enable_cmk_encryption" { variable "kv_name" { type = string description = "Name of Key Vault (only used if enable_cmk_encryption is true)" + default = null } variable "kv_encryption_key_name" { diff --git a/core/terraform/appgateway/variables.tf b/core/terraform/appgateway/variables.tf index 9870e9027b..69dc58d4f1 100644 --- a/core/terraform/appgateway/variables.tf +++ b/core/terraform/appgateway/variables.tf @@ -43,6 +43,7 @@ variable "enable_cmk_encryption" { variable "kv_name" { type = string description = "Name of Key Vault (only used if enable_cmk_encryption is true)" + default = null } variable "kv_encryption_key_name" { type = string diff --git a/core/terraform/azure-monitor/variables.tf b/core/terraform/azure-monitor/variables.tf index 34ff39e752..b2d227644d 100644 --- a/core/terraform/azure-monitor/variables.tf +++ b/core/terraform/azure-monitor/variables.tf @@ -45,6 +45,7 @@ variable "enable_cmk_encryption" { variable "kv_name" { type = string description = "Name of Key Vault (only used if enable_cmk_encryption is true)" + default = null } variable "kv_encryption_key_name" { type = string diff --git a/core/terraform/resource_processor/vmss_porter/variables.tf b/core/terraform/resource_processor/vmss_porter/variables.tf index fb7cd3b11b..ddf6e15336 100644 --- a/core/terraform/resource_processor/vmss_porter/variables.tf +++ b/core/terraform/resource_processor/vmss_porter/variables.tf @@ -88,6 +88,7 @@ variable "enable_cmk_encryption" { variable "kv_name" { type = string description = "Name of Key Vault (only used if enable_cmk_encryption is true)" + default = null } variable "kv_encryption_key_name" { diff --git a/core/terraform/variables.tf b/core/terraform/variables.tf index 7e0934633d..bb1a27007d 100644 --- a/core/terraform/variables.tf +++ b/core/terraform/variables.tf @@ -233,6 +233,7 @@ variable "enable_cmk_encryption" { variable "kv_name" { type = string description = "Name of Key Vault (only used if enable_cmk_encryption is true)" + default = null } variable "kv_encryption_key_name" { diff --git a/devops/terraform/main.tf b/devops/terraform/main.tf index 0dfbd5f517..385662030d 100644 --- a/devops/terraform/main.tf +++ b/devops/terraform/main.tf @@ -97,7 +97,7 @@ resource "azurerm_role_assignment" "current_user_to_key_vault_crypto_officer" { # Key used to encrypt resources resource "azurerm_key_vault_key" "encryption" { count = var.enable_cmk_encryption ? 1 : 0 - + name = var.kv_encryption_key_name key_vault_id = azurerm_key_vault.shared_kv[0].id key_type = "RSA" diff --git a/devops/terraform/variables.tf b/devops/terraform/variables.tf index e324ea1342..0453d45945 100644 --- a/devops/terraform/variables.tf +++ b/devops/terraform/variables.tf @@ -39,6 +39,7 @@ variable "enable_cmk_encryption" { variable "kv_name" { type = string description = "Name of Key Vault (only used if enable_cmk_encryption is true)" + default = null } variable "kv_encryption_key_name" { From 27212b4e9c88bfe9ef2aabf17ae1fd95211f73af Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Thu, 14 Nov 2024 18:10:29 +0000 Subject: [PATCH 04/26] add CMK for cosmos accounts --- core/terraform/cosmos_mongo.tf | 12 +++++++++++- core/terraform/data.tf | 8 +++++++- core/terraform/statestore.tf | 11 ++++++++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/core/terraform/cosmos_mongo.tf b/core/terraform/cosmos_mongo.tf index 6b4f386d09..cc7622d6ba 100644 --- a/core/terraform/cosmos_mongo.tf +++ b/core/terraform/cosmos_mongo.tf @@ -7,6 +7,7 @@ resource "azurerm_cosmosdb_account" "mongo" { enable_automatic_failover = false mongo_server_version = 4.2 ip_range_filter = "${local.azure_portal_cosmos_ips}${var.enable_local_debugging ? ",${local.myip}" : ""}" + key_vault_key_id = var.enable_cmk_encryption ? data.azurerm_key_vault_key.encryption[0].versionless_id : null capabilities { name = "EnableServerless" @@ -35,9 +36,18 @@ resource "azurerm_cosmosdb_account" "mongo" { failover_priority = 0 } + dynamic "identity" { + for_each = var.enable_cmk_encryption ? [1] : [] + content { + type = "UserAssigned" + identity_ids = [azurerm_user_assigned_identity.encryption[0].id] + } + } + + tags = local.tre_core_tags - lifecycle { ignore_changes = [tags] } + lifecycle { ignore_changes = [tags, key_vault_key_id] } } resource "azurerm_cosmosdb_mongo_database" "mongo" { diff --git a/core/terraform/data.tf b/core/terraform/data.tf index 3fcfccab6f..4452afb562 100644 --- a/core/terraform/data.tf +++ b/core/terraform/data.tf @@ -37,4 +37,10 @@ data "azurerm_key_vault" "mgmt_kv" { count = var.enable_cmk_encryption ? 1 : 0 name = var.kv_name resource_group_name = var.mgmt_resource_group_name -} \ No newline at end of file +} + +data "azurerm_key_vault_key" "encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + name = var.kv_encryption_key_name + key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id +} diff --git a/core/terraform/statestore.tf b/core/terraform/statestore.tf index 4fc50f2c20..b3462d6112 100644 --- a/core/terraform/statestore.tf +++ b/core/terraform/statestore.tf @@ -6,6 +6,7 @@ resource "azurerm_cosmosdb_account" "tre_db_account" { kind = "GlobalDocumentDB" enable_automatic_failover = false ip_range_filter = "${local.azure_portal_cosmos_ips}${var.enable_local_debugging ? ",${local.myip}" : ""}" + key_vault_key_id = var.enable_cmk_encryption ? data.azurerm_key_vault_key.encryption[0].versionless_id : null tags = local.tre_core_tags dynamic "capabilities" { @@ -27,7 +28,15 @@ resource "azurerm_cosmosdb_account" "tre_db_account" { failover_priority = 0 } - lifecycle { ignore_changes = [tags] } + dynamic "identity" { + for_each = var.enable_cmk_encryption ? [1] : [] + content { + type = "UserAssigned" + identity_ids = [azurerm_user_assigned_identity.encryption[0].id] + } + } + + lifecycle { ignore_changes = [tags, key_vault_key_id] } } moved { From 50ec3160d3a1135f3f4304a1da161a26d1c0ecc1 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Sun, 17 Nov 2024 12:58:14 +0000 Subject: [PATCH 05/26] move tre-encryption key from mgmt to core --- core/terraform/cosmos_mongo.tf | 2 +- core/terraform/data.tf | 6 ----- .../{encryption_identity.tf => encryption.tf} | 21 ++++++++++++++++- .../resource_processor/vmss_porter/data.tf | 2 +- .../resource_processor/vmss_porter/main.tf | 2 +- core/terraform/statestore.tf | 2 +- devops/terraform/main.tf | 23 ------------------- 7 files changed, 24 insertions(+), 34 deletions(-) rename core/terraform/{encryption_identity.tf => encryption.tf} (64%) diff --git a/core/terraform/cosmos_mongo.tf b/core/terraform/cosmos_mongo.tf index cc7622d6ba..10d18beeb1 100644 --- a/core/terraform/cosmos_mongo.tf +++ b/core/terraform/cosmos_mongo.tf @@ -7,7 +7,7 @@ resource "azurerm_cosmosdb_account" "mongo" { enable_automatic_failover = false mongo_server_version = 4.2 ip_range_filter = "${local.azure_portal_cosmos_ips}${var.enable_local_debugging ? ",${local.myip}" : ""}" - key_vault_key_id = var.enable_cmk_encryption ? data.azurerm_key_vault_key.encryption[0].versionless_id : null + key_vault_key_id = var.enable_cmk_encryption ? azurerm_key_vault_key.tre_encryption[0].versionless_id : null capabilities { name = "EnableServerless" diff --git a/core/terraform/data.tf b/core/terraform/data.tf index 4452afb562..ce26d296c7 100644 --- a/core/terraform/data.tf +++ b/core/terraform/data.tf @@ -38,9 +38,3 @@ data "azurerm_key_vault" "mgmt_kv" { name = var.kv_name resource_group_name = var.mgmt_resource_group_name } - -data "azurerm_key_vault_key" "encryption" { - count = var.enable_cmk_encryption ? 1 : 0 - name = var.kv_encryption_key_name - key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id -} diff --git a/core/terraform/encryption_identity.tf b/core/terraform/encryption.tf similarity index 64% rename from core/terraform/encryption_identity.tf rename to core/terraform/encryption.tf index af643d5f08..cbabe07e03 100644 --- a/core/terraform/encryption_identity.tf +++ b/core/terraform/encryption.tf @@ -14,4 +14,23 @@ resource "azurerm_role_assignment" "kv_encryption_key_user" { scope = data.azurerm_key_vault.mgmt_kv[0].id role_definition_name = "Key Vault Crypto Service Encryption User" principal_id = azurerm_user_assigned_identity.encryption[0].principal_id -} \ No newline at end of file +} + +# Key used to encrypt resources +resource "azurerm_key_vault_key" "tre_encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + + name = var.kv_encryption_key_name + key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_type = "RSA" + key_size = 2048 + + key_opts = [ + "decrypt", + "encrypt", + "sign", + "unwrapKey", + "verify", + "wrapKey", + ] +} diff --git a/core/terraform/resource_processor/vmss_porter/data.tf b/core/terraform/resource_processor/vmss_porter/data.tf index 415ddec1bc..65c682dd89 100644 --- a/core/terraform/resource_processor/vmss_porter/data.tf +++ b/core/terraform/resource_processor/vmss_porter/data.tf @@ -51,7 +51,7 @@ data "azurerm_key_vault" "mgmt_kv" { resource_group_name = var.mgmt_resource_group_name } -data "azurerm_key_vault_key" "encryption" { +data "azurerm_key_vault_key" "tre_encryption" { count = var.enable_cmk_encryption ? 1 : 0 name = var.kv_encryption_key_name key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id diff --git a/core/terraform/resource_processor/vmss_porter/main.tf b/core/terraform/resource_processor/vmss_porter/main.tf index f0d50d0c04..fc56de0528 100644 --- a/core/terraform/resource_processor/vmss_porter/main.tf +++ b/core/terraform/resource_processor/vmss_porter/main.tf @@ -55,7 +55,7 @@ resource "azurerm_disk_encryption_set" "vmss_disk_encryption" { name = "vmss-disk-encryption-rp-porter-${var.tre_id}" location = var.location resource_group_name = var.resource_group_name - key_vault_key_id = data.azurerm_key_vault_key.encryption[0].versionless_id + key_vault_key_id = data.azurerm_key_vault_key.tre_encryption[0].versionless_id encryption_type = "EncryptionAtRestWithPlatformAndCustomerKeys" auto_key_rotation_enabled = true diff --git a/core/terraform/statestore.tf b/core/terraform/statestore.tf index b3462d6112..85420229ce 100644 --- a/core/terraform/statestore.tf +++ b/core/terraform/statestore.tf @@ -6,7 +6,7 @@ resource "azurerm_cosmosdb_account" "tre_db_account" { kind = "GlobalDocumentDB" enable_automatic_failover = false ip_range_filter = "${local.azure_portal_cosmos_ips}${var.enable_local_debugging ? ",${local.myip}" : ""}" - key_vault_key_id = var.enable_cmk_encryption ? data.azurerm_key_vault_key.encryption[0].versionless_id : null + key_vault_key_id = var.enable_cmk_encryption ? azurerm_key_vault_key.tre_encryption[0].versionless_id : null tags = local.tre_core_tags dynamic "capabilities" { diff --git a/devops/terraform/main.tf b/devops/terraform/main.tf index 385662030d..82a1ca9629 100644 --- a/devops/terraform/main.tf +++ b/devops/terraform/main.tf @@ -94,26 +94,3 @@ resource "azurerm_role_assignment" "current_user_to_key_vault_crypto_officer" { principal_id = data.azurerm_client_config.current.object_id } -# Key used to encrypt resources -resource "azurerm_key_vault_key" "encryption" { - count = var.enable_cmk_encryption ? 1 : 0 - - name = var.kv_encryption_key_name - key_vault_id = azurerm_key_vault.shared_kv[0].id - key_type = "RSA" - key_size = 2048 - - key_opts = [ - "decrypt", - "encrypt", - "sign", - "unwrapKey", - "verify", - "wrapKey", - ] - - depends_on = [ - azurerm_role_assignment.current_user_to_key_vault_crypto_officer - ] -} - From df682d6608d44fdb289a9b54ab3968703c81bc33 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Sun, 17 Nov 2024 15:22:20 +0000 Subject: [PATCH 06/26] fix order of creation for encryption key --- core/terraform/encryption.tf | 4 ++++ core/terraform/main.tf | 9 +++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/core/terraform/encryption.tf b/core/terraform/encryption.tf index cbabe07e03..47a3081308 100644 --- a/core/terraform/encryption.tf +++ b/core/terraform/encryption.tf @@ -33,4 +33,8 @@ resource "azurerm_key_vault_key" "tre_encryption" { "verify", "wrapKey", ] + + depends_on = [ + azurerm_role_assignment.kv_encryption_key_user + ] } diff --git a/core/terraform/main.tf b/core/terraform/main.tf index ec62001b39..c33b15f511 100644 --- a/core/terraform/main.tf +++ b/core/terraform/main.tf @@ -81,7 +81,7 @@ module "azure_monitor" { depends_on = [ module.network, - azurerm_role_assignment.kv_encryption_key_user[0] + azurerm_key_vault_key.tre_encryption[0] ] } @@ -118,7 +118,7 @@ module "appgateway" { azurerm_key_vault.kv, azurerm_role_assignment.keyvault_deployer_role, azurerm_private_endpoint.api_private_endpoint, - azurerm_role_assignment.kv_encryption_key_user[0] + azurerm_key_vault_key.tre_encryption[0] ] } @@ -156,7 +156,7 @@ module "airlock_resources" { depends_on = [ azurerm_servicebus_namespace.sb, module.network, - azurerm_role_assignment.kv_encryption_key_user[0] + azurerm_key_vault_key.tre_encryption[0] ] } @@ -196,7 +196,8 @@ module "resource_processor_vmss_porter" { module.network, module.azure_monitor, azurerm_key_vault.kv, - azurerm_role_assignment.keyvault_deployer_role + azurerm_role_assignment.keyvault_deployer_role, + azurerm_key_vault_key.tre_encryption[0] ] } From 9e662343d4a33977430659088479821feaaec3f0 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Sun, 17 Nov 2024 15:22:56 +0000 Subject: [PATCH 07/26] add cmk for the state store in mgmt --- devops/terraform/encryption.tf | 39 ++++++++++++++++++++++++++++++++++ devops/terraform/main.tf | 29 +++++++++++++++++++++++++ devops/terraform/variables.tf | 6 +++++- 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 devops/terraform/encryption.tf diff --git a/devops/terraform/encryption.tf b/devops/terraform/encryption.tf new file mode 100644 index 0000000000..9003e58c2a --- /dev/null +++ b/devops/terraform/encryption.tf @@ -0,0 +1,39 @@ +resource "azurerm_user_assigned_identity" "tre_mgmt_encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + resource_group_name = azurerm_resource_group.mgmt.name + location = azurerm_resource_group.mgmt.location + + name = "id-tre-mgmt-encryption" + + lifecycle { ignore_changes = [tags] } +} + +resource "azurerm_role_assignment" "kv_mgmt_encryption_key_user" { + count = var.enable_cmk_encryption ? 1 : 0 + scope = azurerm_key_vault.shared_kv[0].id + role_definition_name = "Key Vault Crypto Service Encryption User" + principal_id = azurerm_user_assigned_identity.tre_mgmt_encryption[0].principal_id +} + +# Key used to encrypt management resources +resource "azurerm_key_vault_key" "tre_mgmt_encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + + name = var.kv_mgmt_encryption_key_name + key_vault_id = azurerm_key_vault.shared_kv[0].id + key_type = "RSA" + key_size = 2048 + + key_opts = [ + "decrypt", + "encrypt", + "sign", + "unwrapKey", + "verify", + "wrapKey", + ] + + depends_on = [ + azurerm_role_assignment.current_user_to_key_vault_crypto_officer + ] +} diff --git a/devops/terraform/main.tf b/devops/terraform/main.tf index 82a1ca9629..0c4a5728f1 100644 --- a/devops/terraform/main.tf +++ b/devops/terraform/main.tf @@ -30,9 +30,38 @@ resource "azurerm_storage_account" "state_storage" { allow_nested_items_to_be_public = false shared_access_key_enabled = false + dynamic "identity" { + for_each = var.enable_cmk_encryption ? [1] : [] + content { + type = "UserAssigned" + identity_ids = [azurerm_user_assigned_identity.tre_mgmt_encryption[0].id] + } + } + lifecycle { ignore_changes = [tags] } } +# CMK encryption for state storage account +resource "azurerm_storage_account_customer_managed_key" "state_storage_encryption" { + count = var.enable_cmk_encryption ? 1 : 0 + storage_account_id = azurerm_storage_account.state_storage.id + key_vault_id = azurerm_key_vault.shared_kv[0].id + key_name = var.kv_mgmt_encryption_key_name + user_assigned_identity_id = azurerm_user_assigned_identity.tre_mgmt_encryption[0].id + + depends_on = [ + azurerm_role_assignment.kv_mgmt_encryption_key_user + ] + + lifecycle { + ignore_changes = [ + key_vault_id + ] + } +} + + + # Shared container registry resource "azurerm_container_registry" "shared_acr" { name = var.acr_name diff --git a/devops/terraform/variables.tf b/devops/terraform/variables.tf index 0453d45945..76784307ab 100644 --- a/devops/terraform/variables.tf +++ b/devops/terraform/variables.tf @@ -48,4 +48,8 @@ variable "kv_encryption_key_name" { default = "tre-encryption" } - +variable "kv_mgmt_encryption_key_name" { + type = string + description = "Name of Key Vault Encryption Key for management resources (only used if enable_cmk_encryption is true)" + default = "tre-mgmt-encryption" +} From fed7a169109d89d14fd18d8f815ea69f42b66281 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Mon, 18 Nov 2024 23:34:42 +0000 Subject: [PATCH 08/26] add support for external KV --- config.sample.yaml | 6 ++++-- core/terraform/airlock/airlock_processor.tf | 2 +- core/terraform/airlock/data.tf | 5 ----- core/terraform/airlock/storage_accounts.tf | 10 +++++----- core/terraform/airlock/variables.tf | 4 ++-- core/terraform/appgateway/data.tf | 6 ------ core/terraform/appgateway/staticweb.tf | 2 +- core/terraform/appgateway/variables.tf | 4 ++-- core/terraform/azure-monitor/azure-monitor.tf | 2 +- core/terraform/azure-monitor/data.tf | 5 ----- core/terraform/azure-monitor/variables.tf | 4 ++-- core/terraform/data.tf | 12 ++++++------ core/terraform/encryption.tf | 4 ++-- core/terraform/locals.tf | 3 +++ core/terraform/main.tf | 16 ++++++++-------- .../resource_processor/vmss_porter/data.tf | 8 +------- .../resource_processor/vmss_porter/main.tf | 2 +- .../resource_processor/vmss_porter/variables.tf | 4 ++-- core/terraform/storage.tf | 2 +- core/terraform/variables.tf | 10 ++++++++-- devops/terraform/encryption.tf | 4 ++-- devops/terraform/locals.tf | 4 ++++ devops/terraform/main.tf | 15 ++++++++------- devops/terraform/variables.tf | 10 ++++++++-- 24 files changed, 72 insertions(+), 72 deletions(-) delete mode 100644 core/terraform/airlock/data.tf delete mode 100644 core/terraform/azure-monitor/data.tf create mode 100644 devops/terraform/locals.tf diff --git a/config.sample.yaml b/config.sample.yaml index 73ba09020e..be243e8968 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -8,8 +8,10 @@ management: mgmt_storage_account_name: __CHANGE_ME__ terraform_state_container_name: tfstate acr_name: __CHANGE_ME__ - # Key Vault for encryption keys (only required if enable_cmk_encryption is true) - kv_name: __CHANGE_ME__ + # ID of external Key Vault/HSM to store CMKs in (only required if enable_cmk_encryption is true) + # external_key_store_id: __CHANGE_ME__ + # name of Key Vault for encryption keys, required only if enable_cmk_encryption is true and not using an external Key Vault/HSM + # encryption_kv_name: __CHANGE_ME__ # Azure Resource Manager credentials used for CI/CD pipelines arm_subscription_id: __CHANGE_ME__ diff --git a/core/terraform/airlock/airlock_processor.tf b/core/terraform/airlock/airlock_processor.tf index c97c010840..028567c561 100644 --- a/core/terraform/airlock/airlock_processor.tf +++ b/core/terraform/airlock/airlock_processor.tf @@ -41,7 +41,7 @@ resource "azurerm_storage_account" "sa_airlock_processor_func_app" { resource "azurerm_storage_account_customer_managed_key" "sa_airlock_processor_func_app_encryption" { count = var.enable_cmk_encryption ? 1 : 0 storage_account_id = azurerm_storage_account.sa_airlock_processor_func_app.id - key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id diff --git a/core/terraform/airlock/data.tf b/core/terraform/airlock/data.tf deleted file mode 100644 index d19ec72f50..0000000000 --- a/core/terraform/airlock/data.tf +++ /dev/null @@ -1,5 +0,0 @@ -data "azurerm_key_vault" "mgmt_kv" { - count = var.enable_cmk_encryption ? 1 : 0 - name = var.kv_name - resource_group_name = var.mgmt_resource_group_name -} \ No newline at end of file diff --git a/core/terraform/airlock/storage_accounts.tf b/core/terraform/airlock/storage_accounts.tf index 59383e3791..4daacfbf0a 100644 --- a/core/terraform/airlock/storage_accounts.tf +++ b/core/terraform/airlock/storage_accounts.tf @@ -55,7 +55,7 @@ resource "azurerm_private_endpoint" "stg_import_external_pe" { resource "azurerm_storage_account_customer_managed_key" "sa_import_external_encryption" { count = var.enable_cmk_encryption ? 1 : 0 storage_account_id = azurerm_storage_account.sa_import_external.id - key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id @@ -121,7 +121,7 @@ resource "azurerm_private_endpoint" "stg_export_approved_pe" { resource "azurerm_storage_account_customer_managed_key" "sa_export_approved_encryption" { count = var.enable_cmk_encryption ? 1 : 0 storage_account_id = azurerm_storage_account.sa_export_approved.id - key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id @@ -168,7 +168,7 @@ resource "azurerm_storage_account" "sa_import_in_progress" { resource "azurerm_storage_account_customer_managed_key" "sa_import_in_progress_encryption" { count = var.enable_cmk_encryption ? 1 : 0 storage_account_id = azurerm_storage_account.sa_import_in_progress.id - key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id @@ -287,7 +287,7 @@ resource "azurerm_private_endpoint" "stg_import_rejected_pe" { resource "azurerm_storage_account_customer_managed_key" "sa_import_rejected_encryption" { count = var.enable_cmk_encryption ? 1 : 0 storage_account_id = azurerm_storage_account.sa_import_rejected.id - key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id @@ -357,7 +357,7 @@ resource "azurerm_private_endpoint" "stg_import_blocked_pe" { resource "azurerm_storage_account_customer_managed_key" "sa_import_blocked_encryption" { count = var.enable_cmk_encryption ? 1 : 0 storage_account_id = azurerm_storage_account.sa_import_blocked.id - key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id diff --git a/core/terraform/airlock/variables.tf b/core/terraform/airlock/variables.tf index bf18922db8..dcf630a4ac 100644 --- a/core/terraform/airlock/variables.tf +++ b/core/terraform/airlock/variables.tf @@ -102,9 +102,9 @@ variable "enable_cmk_encryption" { description = "A boolean indicating if key vault will be deployed for customer managed key encryption" } -variable "kv_name" { +variable "key_store_id" { type = string - description = "Name of Key Vault (only used if enable_cmk_encryption is true)" + description = "ID of the Key Vault/HSM to store CMKs in (only used if enable_cmk_encryption is true)" default = null } diff --git a/core/terraform/appgateway/data.tf b/core/terraform/appgateway/data.tf index b606dd2603..702f013a59 100644 --- a/core/terraform/appgateway/data.tf +++ b/core/terraform/appgateway/data.tf @@ -6,9 +6,3 @@ data "azurerm_monitor_diagnostic_categories" "agw" { azurerm_application_gateway.agw ] } - -data "azurerm_key_vault" "mgmt_kv" { - count = var.enable_cmk_encryption ? 1 : 0 - name = var.kv_name - resource_group_name = var.mgmt_resource_group_name -} diff --git a/core/terraform/appgateway/staticweb.tf b/core/terraform/appgateway/staticweb.tf index cbceaf626e..35d603dc00 100644 --- a/core/terraform/appgateway/staticweb.tf +++ b/core/terraform/appgateway/staticweb.tf @@ -34,7 +34,7 @@ resource "azurerm_storage_account" "staticweb" { resource "azurerm_storage_account_customer_managed_key" "staticweb_encryption" { count = var.enable_cmk_encryption ? 1 : 0 storage_account_id = azurerm_storage_account.staticweb.id - key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id diff --git a/core/terraform/appgateway/variables.tf b/core/terraform/appgateway/variables.tf index 69dc58d4f1..7cdeda8747 100644 --- a/core/terraform/appgateway/variables.tf +++ b/core/terraform/appgateway/variables.tf @@ -40,9 +40,9 @@ variable "enable_cmk_encryption" { type = bool description = "A boolean indicating if key vault will be deployed for customer managed key encryption" } -variable "kv_name" { +variable "key_store_id" { type = string - description = "Name of Key Vault (only used if enable_cmk_encryption is true)" + description = "ID of the Key Vault/HSM to store CMKs in (only used if enable_cmk_encryption is true)" default = null } variable "kv_encryption_key_name" { diff --git a/core/terraform/azure-monitor/azure-monitor.tf b/core/terraform/azure-monitor/azure-monitor.tf index 0456202abd..a74e5f0fc8 100644 --- a/core/terraform/azure-monitor/azure-monitor.tf +++ b/core/terraform/azure-monitor/azure-monitor.tf @@ -42,7 +42,7 @@ resource "azurerm_storage_account" "az_monitor" { resource "azurerm_storage_account_customer_managed_key" "az_monitor_encryption" { count = var.enable_cmk_encryption ? 1 : 0 storage_account_id = azurerm_storage_account.az_monitor.id - key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id diff --git a/core/terraform/azure-monitor/data.tf b/core/terraform/azure-monitor/data.tf deleted file mode 100644 index d19ec72f50..0000000000 --- a/core/terraform/azure-monitor/data.tf +++ /dev/null @@ -1,5 +0,0 @@ -data "azurerm_key_vault" "mgmt_kv" { - count = var.enable_cmk_encryption ? 1 : 0 - name = var.kv_name - resource_group_name = var.mgmt_resource_group_name -} \ No newline at end of file diff --git a/core/terraform/azure-monitor/variables.tf b/core/terraform/azure-monitor/variables.tf index b2d227644d..6ce7a31cf9 100644 --- a/core/terraform/azure-monitor/variables.tf +++ b/core/terraform/azure-monitor/variables.tf @@ -42,9 +42,9 @@ variable "enable_cmk_encryption" { type = bool description = "A boolean indicating if key vault will be deployed for customer managed key encryption" } -variable "kv_name" { +variable "key_store_id" { type = string - description = "Name of Key Vault (only used if enable_cmk_encryption is true)" + description = "ID of the Key Vault/HSM to store CMKs in (only used if enable_cmk_encryption is true)" default = null } variable "kv_encryption_key_name" { diff --git a/core/terraform/data.tf b/core/terraform/data.tf index ce26d296c7..ec18987993 100644 --- a/core/terraform/data.tf +++ b/core/terraform/data.tf @@ -13,6 +13,12 @@ data "azurerm_container_registry" "mgmt_acr" { resource_group_name = var.mgmt_resource_group_name } +data "azurerm_key_vault" "encryption_kv" { + count = var.enable_cmk_encryption && var.external_key_store_id == null ? 1 : 0 + name = var.encryption_kv_name + resource_group_name = var.mgmt_resource_group_name +} + data "http" "myip" { count = var.public_deployment_ip_address == "" ? 1 : 0 url = "https://ipecho.net/plain" @@ -32,9 +38,3 @@ data "azurerm_monitor_diagnostic_categories" "sb" { azurerm_servicebus_namespace.sb ] } - -data "azurerm_key_vault" "mgmt_kv" { - count = var.enable_cmk_encryption ? 1 : 0 - name = var.kv_name - resource_group_name = var.mgmt_resource_group_name -} diff --git a/core/terraform/encryption.tf b/core/terraform/encryption.tf index 47a3081308..ec9484664a 100644 --- a/core/terraform/encryption.tf +++ b/core/terraform/encryption.tf @@ -11,7 +11,7 @@ resource "azurerm_user_assigned_identity" "encryption" { resource "azurerm_role_assignment" "kv_encryption_key_user" { count = var.enable_cmk_encryption ? 1 : 0 - scope = data.azurerm_key_vault.mgmt_kv[0].id + scope = local.key_store_id role_definition_name = "Key Vault Crypto Service Encryption User" principal_id = azurerm_user_assigned_identity.encryption[0].principal_id } @@ -21,7 +21,7 @@ resource "azurerm_key_vault_key" "tre_encryption" { count = var.enable_cmk_encryption ? 1 : 0 name = var.kv_encryption_key_name - key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_vault_id = local.key_store_id key_type = "RSA" key_size = 2048 diff --git a/core/terraform/locals.tf b/core/terraform/locals.tf index c3539c9fb3..bc2cafa922 100644 --- a/core/terraform/locals.tf +++ b/core/terraform/locals.tf @@ -40,4 +40,7 @@ locals { # The followig regex extracts different parts of the service bus endpoint: scheme, fqdn, port, path, query and fragment. This allows us to extract the needed fqdn part. service_bus_namespace_fqdn = regex("(?:(?P<scheme>[^:/?#]+):)?(?://(?P<fqdn>[^/?#:]*))?(?::(?P<port>[0-9]+))?(?P<path>[^?#]*)(?:\\?(?P<query>[^#]*))?(?:#(?P<fragment>.*))?", azurerm_servicebus_namespace.sb.endpoint).fqdn + + # The key store for encryption keys could either be external or created by terraform + key_store_id = var.external_key_store_id != null ? var.external_key_store_id : data.azurerm_key_vault.encryption_kv[0].id } diff --git a/core/terraform/main.tf b/core/terraform/main.tf index c33b15f511..18b94b69cf 100644 --- a/core/terraform/main.tf +++ b/core/terraform/main.tf @@ -74,7 +74,7 @@ module "azure_monitor" { tre_core_tags = local.tre_core_tags enable_local_debugging = var.enable_local_debugging enable_cmk_encryption = var.enable_cmk_encryption - kv_name = var.kv_name + key_store_id = local.key_store_id kv_encryption_key_name = var.kv_encryption_key_name encryption_identity_id = azurerm_user_assigned_identity.encryption[0].id mgmt_resource_group_name = var.mgmt_resource_group_name @@ -107,11 +107,11 @@ module "appgateway" { log_analytics_workspace_id = module.azure_monitor.log_analytics_workspace_id app_gateway_sku = var.app_gateway_sku - enable_cmk_encryption = var.enable_cmk_encryption - kv_name = var.kv_name - kv_encryption_key_name = var.kv_encryption_key_name - encryption_identity_id = azurerm_user_assigned_identity.encryption[0].id - mgmt_resource_group_name = var.mgmt_resource_group_name + enable_cmk_encryption = var.enable_cmk_encryption + key_store_id = local.key_store_id + kv_encryption_key_name = var.kv_encryption_key_name + encryption_identity_id = azurerm_user_assigned_identity.encryption[0].id + mgmt_resource_group_name = var.mgmt_resource_group_name depends_on = [ module.network, @@ -149,7 +149,7 @@ module "airlock_resources" { enable_local_debugging = var.enable_local_debugging myip = local.myip enable_cmk_encryption = var.enable_cmk_encryption - kv_name = var.kv_name + key_store_id = local.key_store_id kv_encryption_key_name = var.kv_encryption_key_name encryption_identity_id = azurerm_user_assigned_identity.encryption[0].id @@ -189,7 +189,7 @@ module "resource_processor_vmss_porter" { firewall_sku = var.firewall_sku rp_bundle_values = var.rp_bundle_values enable_cmk_encryption = var.enable_cmk_encryption - kv_name = var.kv_name + key_store_id = local.key_store_id kv_encryption_key_name = var.kv_encryption_key_name depends_on = [ diff --git a/core/terraform/resource_processor/vmss_porter/data.tf b/core/terraform/resource_processor/vmss_porter/data.tf index 65c682dd89..8ae856343f 100644 --- a/core/terraform/resource_processor/vmss_porter/data.tf +++ b/core/terraform/resource_processor/vmss_porter/data.tf @@ -45,16 +45,10 @@ data "template_cloudinit_config" "config" { } } -data "azurerm_key_vault" "mgmt_kv" { - count = var.enable_cmk_encryption ? 1 : 0 - name = var.kv_name - resource_group_name = var.mgmt_resource_group_name -} - data "azurerm_key_vault_key" "tre_encryption" { count = var.enable_cmk_encryption ? 1 : 0 name = var.kv_encryption_key_name - key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_vault_id = var.key_store_id } data "azurerm_storage_account" "mgmt_storage" { diff --git a/core/terraform/resource_processor/vmss_porter/main.tf b/core/terraform/resource_processor/vmss_porter/main.tf index fc56de0528..7b51a4fd34 100644 --- a/core/terraform/resource_processor/vmss_porter/main.tf +++ b/core/terraform/resource_processor/vmss_porter/main.tf @@ -217,7 +217,7 @@ resource "azurerm_role_assignment" "keyvault_vmss_role" { resource "azurerm_role_assignment" "vmss_kv_encryption_key_user" { count = var.enable_cmk_encryption ? 1 : 0 - scope = data.azurerm_key_vault.mgmt_kv[0].id + scope = var.key_store_id role_definition_name = "Key Vault Crypto Service Encryption User" principal_id = azurerm_user_assigned_identity.vmss_msi.principal_id } diff --git a/core/terraform/resource_processor/vmss_porter/variables.tf b/core/terraform/resource_processor/vmss_porter/variables.tf index ddf6e15336..e956865a43 100644 --- a/core/terraform/resource_processor/vmss_porter/variables.tf +++ b/core/terraform/resource_processor/vmss_porter/variables.tf @@ -85,9 +85,9 @@ variable "enable_cmk_encryption" { description = "A boolean indicating if key vault will be deployed for customer managed key encryption" } -variable "kv_name" { +variable "key_store_id" { type = string - description = "Name of Key Vault (only used if enable_cmk_encryption is true)" + description = "ID of the Key Vault/HSM to store CMKs in (only used if enable_cmk_encryption is true)" default = null } diff --git a/core/terraform/storage.tf b/core/terraform/storage.tf index bb79153fd6..55937fe55d 100644 --- a/core/terraform/storage.tf +++ b/core/terraform/storage.tf @@ -76,7 +76,7 @@ resource "azurerm_private_endpoint" "filepe" { resource "azurerm_storage_account_customer_managed_key" "encryption" { count = var.enable_cmk_encryption ? 1 : 0 storage_account_id = azurerm_storage_account.stg.id - key_vault_id = data.azurerm_key_vault.mgmt_kv[0].id + key_vault_id = local.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = azurerm_user_assigned_identity.encryption[0].id diff --git a/core/terraform/variables.tf b/core/terraform/variables.tf index bb1a27007d..5b567f604b 100644 --- a/core/terraform/variables.tf +++ b/core/terraform/variables.tf @@ -230,9 +230,15 @@ variable "enable_cmk_encryption" { default = false } -variable "kv_name" { +variable "external_key_store_id" { type = string - description = "Name of Key Vault (only used if enable_cmk_encryption is true)" + description = "ID of external Key Vault/HSM to store CMKs in (only required if enable_cmk_encryption is true)" + default = null +} + +variable "encryption_kv_name" { + type = string + description = "Name of Key Vault for encryption keys, required only if external_key_store_id is not set (only used if enable_cmk_encryption is true)" default = null } diff --git a/devops/terraform/encryption.tf b/devops/terraform/encryption.tf index 9003e58c2a..6f9d87bd3c 100644 --- a/devops/terraform/encryption.tf +++ b/devops/terraform/encryption.tf @@ -10,7 +10,7 @@ resource "azurerm_user_assigned_identity" "tre_mgmt_encryption" { resource "azurerm_role_assignment" "kv_mgmt_encryption_key_user" { count = var.enable_cmk_encryption ? 1 : 0 - scope = azurerm_key_vault.shared_kv[0].id + scope = local.key_store_id role_definition_name = "Key Vault Crypto Service Encryption User" principal_id = azurerm_user_assigned_identity.tre_mgmt_encryption[0].principal_id } @@ -20,7 +20,7 @@ resource "azurerm_key_vault_key" "tre_mgmt_encryption" { count = var.enable_cmk_encryption ? 1 : 0 name = var.kv_mgmt_encryption_key_name - key_vault_id = azurerm_key_vault.shared_kv[0].id + key_vault_id = local.key_store_id key_type = "RSA" key_size = 2048 diff --git a/devops/terraform/locals.tf b/devops/terraform/locals.tf new file mode 100644 index 0000000000..2466ca2fa0 --- /dev/null +++ b/devops/terraform/locals.tf @@ -0,0 +1,4 @@ +locals { + # The key store for encryption keys could either be external or created by terraform + key_store_id = var.external_key_store_id != null ? var.external_key_store_id : azurerm_key_vault.encryption_kv[0].id +} diff --git a/devops/terraform/main.tf b/devops/terraform/main.tf index 0c4a5728f1..8a812fe841 100644 --- a/devops/terraform/main.tf +++ b/devops/terraform/main.tf @@ -45,12 +45,13 @@ resource "azurerm_storage_account" "state_storage" { resource "azurerm_storage_account_customer_managed_key" "state_storage_encryption" { count = var.enable_cmk_encryption ? 1 : 0 storage_account_id = azurerm_storage_account.state_storage.id - key_vault_id = azurerm_key_vault.shared_kv[0].id + key_vault_id = local.key_store_id key_name = var.kv_mgmt_encryption_key_name user_assigned_identity_id = azurerm_user_assigned_identity.tre_mgmt_encryption[0].id depends_on = [ - azurerm_role_assignment.kv_mgmt_encryption_key_user + azurerm_role_assignment.kv_mgmt_encryption_key_user, + azurerm_key_vault_key.tre_mgmt_encryption[0] ] lifecycle { @@ -100,9 +101,9 @@ EOF } # Key Vault for encryption keys -resource "azurerm_key_vault" "shared_kv" { - count = var.enable_cmk_encryption ? 1 : 0 - name = var.kv_name +resource "azurerm_key_vault" "encryption_kv" { + count = var.enable_cmk_encryption && var.external_key_store_id == null ? 1 : 0 + name = var.encryption_kv_name resource_group_name = azurerm_resource_group.mgmt.name location = azurerm_resource_group.mgmt.location enabled_for_disk_encryption = true @@ -117,8 +118,8 @@ resource "azurerm_key_vault" "shared_kv" { } resource "azurerm_role_assignment" "current_user_to_key_vault_crypto_officer" { - count = var.enable_cmk_encryption ? 1 : 0 - scope = azurerm_key_vault.shared_kv[0].id + count = var.enable_cmk_encryption && var.external_key_store_id == null ? 1 : 0 + scope = azurerm_key_vault.encryption_kv[0].id role_definition_name = "Key Vault Crypto Officer" principal_id = data.azurerm_client_config.current.object_id } diff --git a/devops/terraform/variables.tf b/devops/terraform/variables.tf index 76784307ab..469df96533 100644 --- a/devops/terraform/variables.tf +++ b/devops/terraform/variables.tf @@ -36,9 +36,15 @@ variable "enable_cmk_encryption" { default = false } -variable "kv_name" { +variable "external_key_store_id" { type = string - description = "Name of Key Vault (only used if enable_cmk_encryption is true)" + description = "ID of external Key Vault/HSM to store CMKs in (only required if enable_cmk_encryption is true)" + default = null +} + +variable "encryption_kv_name" { + type = string + description = "Name of Key Vault for encryption keys, required only if external_key_store_id is not set (only used if enable_cmk_encryption is true)" default = null } From 7f24a23995f64a8f8662f4c9a5d049aafaee9fd6 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Mon, 18 Nov 2024 23:35:30 +0000 Subject: [PATCH 09/26] revert CMK for cosmos - not working, need to redo this --- core/terraform/cosmos_mongo.tf | 10 ---------- core/terraform/statestore.tf | 9 --------- 2 files changed, 19 deletions(-) diff --git a/core/terraform/cosmos_mongo.tf b/core/terraform/cosmos_mongo.tf index 10d18beeb1..a020807c9c 100644 --- a/core/terraform/cosmos_mongo.tf +++ b/core/terraform/cosmos_mongo.tf @@ -7,7 +7,6 @@ resource "azurerm_cosmosdb_account" "mongo" { enable_automatic_failover = false mongo_server_version = 4.2 ip_range_filter = "${local.azure_portal_cosmos_ips}${var.enable_local_debugging ? ",${local.myip}" : ""}" - key_vault_key_id = var.enable_cmk_encryption ? azurerm_key_vault_key.tre_encryption[0].versionless_id : null capabilities { name = "EnableServerless" @@ -36,15 +35,6 @@ resource "azurerm_cosmosdb_account" "mongo" { failover_priority = 0 } - dynamic "identity" { - for_each = var.enable_cmk_encryption ? [1] : [] - content { - type = "UserAssigned" - identity_ids = [azurerm_user_assigned_identity.encryption[0].id] - } - } - - tags = local.tre_core_tags lifecycle { ignore_changes = [tags, key_vault_key_id] } diff --git a/core/terraform/statestore.tf b/core/terraform/statestore.tf index 85420229ce..d31cd1a784 100644 --- a/core/terraform/statestore.tf +++ b/core/terraform/statestore.tf @@ -6,7 +6,6 @@ resource "azurerm_cosmosdb_account" "tre_db_account" { kind = "GlobalDocumentDB" enable_automatic_failover = false ip_range_filter = "${local.azure_portal_cosmos_ips}${var.enable_local_debugging ? ",${local.myip}" : ""}" - key_vault_key_id = var.enable_cmk_encryption ? azurerm_key_vault_key.tre_encryption[0].versionless_id : null tags = local.tre_core_tags dynamic "capabilities" { @@ -28,14 +27,6 @@ resource "azurerm_cosmosdb_account" "tre_db_account" { failover_priority = 0 } - dynamic "identity" { - for_each = var.enable_cmk_encryption ? [1] : [] - content { - type = "UserAssigned" - identity_ids = [azurerm_user_assigned_identity.encryption[0].id] - } - } - lifecycle { ignore_changes = [tags, key_vault_key_id] } } From cd9271ae381e3ada076df273cf0c5e2e870bd002 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Tue, 19 Nov 2024 10:29:04 +0000 Subject: [PATCH 10/26] refine comments and files names --- config.sample.yaml | 4 ++-- core/terraform/airlock/variables.tf | 4 ++-- core/terraform/appgateway/variables.tf | 4 ++-- core/terraform/azure-monitor/variables.tf | 4 ++-- core/terraform/{encryption.tf => cmk_encryption.tf} | 0 core/terraform/resource_processor/vmss_porter/variables.tf | 4 ++-- core/terraform/statestore.tf | 2 +- core/terraform/variables.tf | 4 ++-- devops/terraform/{encryption.tf => cmk_encryption.tf} | 0 devops/terraform/main.tf | 3 --- devops/terraform/variables.tf | 4 ++-- 11 files changed, 15 insertions(+), 18 deletions(-) rename core/terraform/{encryption.tf => cmk_encryption.tf} (100%) rename devops/terraform/{encryption.tf => cmk_encryption.tf} (100%) diff --git a/config.sample.yaml b/config.sample.yaml index be243e8968..0665ecd23c 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -8,9 +8,9 @@ management: mgmt_storage_account_name: __CHANGE_ME__ terraform_state_container_name: tfstate acr_name: __CHANGE_ME__ - # ID of external Key Vault/HSM to store CMKs in (only required if enable_cmk_encryption is true) + # ID of external Key Vault to store CMKs in (only required if enable_cmk_encryption is true) # external_key_store_id: __CHANGE_ME__ - # name of Key Vault for encryption keys, required only if enable_cmk_encryption is true and not using an external Key Vault/HSM + # name of Key Vault for encryption keys, required only if enable_cmk_encryption is true and not using external_key_store_id # encryption_kv_name: __CHANGE_ME__ # Azure Resource Manager credentials used for CI/CD pipelines arm_subscription_id: __CHANGE_ME__ diff --git a/core/terraform/airlock/variables.tf b/core/terraform/airlock/variables.tf index dcf630a4ac..f88f1fc50f 100644 --- a/core/terraform/airlock/variables.tf +++ b/core/terraform/airlock/variables.tf @@ -99,12 +99,12 @@ variable "encryption_identity_id" { variable "enable_cmk_encryption" { type = bool - description = "A boolean indicating if key vault will be deployed for customer managed key encryption" + description = "A boolean indicating if customer managed keys will be used for encryption of supporting resources" } variable "key_store_id" { type = string - description = "ID of the Key Vault/HSM to store CMKs in (only used if enable_cmk_encryption is true)" + description = "ID of the Key Vault to store CMKs in (only used if enable_cmk_encryption is true)" default = null } diff --git a/core/terraform/appgateway/variables.tf b/core/terraform/appgateway/variables.tf index 7cdeda8747..710315cb9e 100644 --- a/core/terraform/appgateway/variables.tf +++ b/core/terraform/appgateway/variables.tf @@ -38,11 +38,11 @@ variable "encryption_identity_id" { } variable "enable_cmk_encryption" { type = bool - description = "A boolean indicating if key vault will be deployed for customer managed key encryption" + description = "A boolean indicating if customer managed keys will be used for encryption of supporting resources" } variable "key_store_id" { type = string - description = "ID of the Key Vault/HSM to store CMKs in (only used if enable_cmk_encryption is true)" + description = "ID of the Key Vault to store CMKs in (only used if enable_cmk_encryption is true)" default = null } variable "kv_encryption_key_name" { diff --git a/core/terraform/azure-monitor/variables.tf b/core/terraform/azure-monitor/variables.tf index 6ce7a31cf9..244477363f 100644 --- a/core/terraform/azure-monitor/variables.tf +++ b/core/terraform/azure-monitor/variables.tf @@ -40,11 +40,11 @@ variable "encryption_identity_id" { } variable "enable_cmk_encryption" { type = bool - description = "A boolean indicating if key vault will be deployed for customer managed key encryption" + description = "A boolean indicating if customer managed keys will be used for encryption of supporting resources" } variable "key_store_id" { type = string - description = "ID of the Key Vault/HSM to store CMKs in (only used if enable_cmk_encryption is true)" + description = "ID of the Key Vault to store CMKs in (only used if enable_cmk_encryption is true)" default = null } variable "kv_encryption_key_name" { diff --git a/core/terraform/encryption.tf b/core/terraform/cmk_encryption.tf similarity index 100% rename from core/terraform/encryption.tf rename to core/terraform/cmk_encryption.tf diff --git a/core/terraform/resource_processor/vmss_porter/variables.tf b/core/terraform/resource_processor/vmss_porter/variables.tf index e956865a43..9537cd79c5 100644 --- a/core/terraform/resource_processor/vmss_porter/variables.tf +++ b/core/terraform/resource_processor/vmss_porter/variables.tf @@ -82,12 +82,12 @@ locals { variable "enable_cmk_encryption" { type = bool - description = "A boolean indicating if key vault will be deployed for customer managed key encryption" + description = "A boolean indicating if customer managed keys will be used for encryption of supporting resources" } variable "key_store_id" { type = string - description = "ID of the Key Vault/HSM to store CMKs in (only used if enable_cmk_encryption is true)" + description = "ID of the Key Vault to store CMKs in (only used if enable_cmk_encryption is true)" default = null } diff --git a/core/terraform/statestore.tf b/core/terraform/statestore.tf index d31cd1a784..4fc50f2c20 100644 --- a/core/terraform/statestore.tf +++ b/core/terraform/statestore.tf @@ -27,7 +27,7 @@ resource "azurerm_cosmosdb_account" "tre_db_account" { failover_priority = 0 } - lifecycle { ignore_changes = [tags, key_vault_key_id] } + lifecycle { ignore_changes = [tags] } } moved { diff --git a/core/terraform/variables.tf b/core/terraform/variables.tf index 5b567f604b..d364d027b8 100644 --- a/core/terraform/variables.tf +++ b/core/terraform/variables.tf @@ -226,13 +226,13 @@ variable "logging_level" { variable "enable_cmk_encryption" { type = bool - description = "A boolean indicating if key vault will be deployed for customer managed key encryption" + description = "A boolean indicating if customer managed keys will be used for encryption of supporting resources" default = false } variable "external_key_store_id" { type = string - description = "ID of external Key Vault/HSM to store CMKs in (only required if enable_cmk_encryption is true)" + description = "ID of external Key Vault to store CMKs in (only required if enable_cmk_encryption is true)" default = null } diff --git a/devops/terraform/encryption.tf b/devops/terraform/cmk_encryption.tf similarity index 100% rename from devops/terraform/encryption.tf rename to devops/terraform/cmk_encryption.tf diff --git a/devops/terraform/main.tf b/devops/terraform/main.tf index 8a812fe841..195d768e03 100644 --- a/devops/terraform/main.tf +++ b/devops/terraform/main.tf @@ -41,7 +41,6 @@ resource "azurerm_storage_account" "state_storage" { lifecycle { ignore_changes = [tags] } } -# CMK encryption for state storage account resource "azurerm_storage_account_customer_managed_key" "state_storage_encryption" { count = var.enable_cmk_encryption ? 1 : 0 storage_account_id = azurerm_storage_account.state_storage.id @@ -110,8 +109,6 @@ resource "azurerm_key_vault" "encryption_kv" { sku_name = "standard" tenant_id = data.azurerm_client_config.current.tenant_id enable_rbac_authorization = true - - # Purge protection needs to be enabled for customer managed key encryption purge_protection_enabled = true lifecycle { ignore_changes = [tags] } diff --git a/devops/terraform/variables.tf b/devops/terraform/variables.tf index 469df96533..45c314fd61 100644 --- a/devops/terraform/variables.tf +++ b/devops/terraform/variables.tf @@ -32,13 +32,13 @@ variable "kv_purge_protection_enabled" { variable "enable_cmk_encryption" { type = bool - description = "A boolean indicating if key vault will be deployed for customer managed key encryption" + description = "A boolean indicating if customer managed keys will be used for encryption of supporting resources" default = false } variable "external_key_store_id" { type = string - description = "ID of external Key Vault/HSM to store CMKs in (only required if enable_cmk_encryption is true)" + description = "ID of external Key Vault to store CMKs in (only required if enable_cmk_encryption is true)" default = null } From f459a82278d15561180f0e9a09ec3e798863f01c Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Tue, 19 Nov 2024 10:33:51 +0000 Subject: [PATCH 11/26] remove redundant space --- config.sample.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.sample.yaml b/config.sample.yaml index 0665ecd23c..a6d59bedf8 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -82,7 +82,7 @@ developer_settings: # This setting will enable your local machine to be able to # communicate with Service Bus and Cosmos. It will also allow deploying # the base workspace. -# enable_local_debugging: true +# enable_local_debugging: true # This setting enables customer-managed key encryption for all supported resources # enable_cmk_encryption: true From af5361522b31b0c1ef8330b5f6e2a8a035fdd5e1 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Tue, 19 Nov 2024 10:34:21 +0000 Subject: [PATCH 12/26] add space --- config.sample.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.sample.yaml b/config.sample.yaml index a6d59bedf8..c44daae69b 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -85,7 +85,7 @@ developer_settings: # enable_local_debugging: true # This setting enables customer-managed key encryption for all supported resources -# enable_cmk_encryption: true +# enable_cmk_encryption: true # Used by the API and Resource processor application to change log level # Can be "ERROR", "WARNING", "INFO", "DEBUG" From 61d8e976bf20b9c77adb373ced6499644ef5cf05 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Tue, 19 Nov 2024 12:25:12 +0000 Subject: [PATCH 13/26] upper case in comment --- config.sample.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.sample.yaml b/config.sample.yaml index c44daae69b..44777e89a3 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -10,7 +10,7 @@ management: acr_name: __CHANGE_ME__ # ID of external Key Vault to store CMKs in (only required if enable_cmk_encryption is true) # external_key_store_id: __CHANGE_ME__ - # name of Key Vault for encryption keys, required only if enable_cmk_encryption is true and not using external_key_store_id + # Name of Key Vault for encryption keys, required only if enable_cmk_encryption is true and not using external_key_store_id # encryption_kv_name: __CHANGE_ME__ # Azure Resource Manager credentials used for CI/CD pipelines arm_subscription_id: __CHANGE_ME__ From 25322d75ae470c9b90990f94f0db572c1a9fc1b5 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Tue, 19 Nov 2024 12:30:01 +0000 Subject: [PATCH 14/26] revert cosmos tags --- core/terraform/cosmos_mongo.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/terraform/cosmos_mongo.tf b/core/terraform/cosmos_mongo.tf index a020807c9c..6b4f386d09 100644 --- a/core/terraform/cosmos_mongo.tf +++ b/core/terraform/cosmos_mongo.tf @@ -37,7 +37,7 @@ resource "azurerm_cosmosdb_account" "mongo" { tags = local.tre_core_tags - lifecycle { ignore_changes = [tags, key_vault_key_id] } + lifecycle { ignore_changes = [tags] } } resource "azurerm_cosmosdb_mongo_database" "mongo" { From 8ef02312b344ecfc46f165232758b009c71ab88c Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Tue, 19 Nov 2024 15:22:38 +0000 Subject: [PATCH 15/26] update changelog + core version --- CHANGELOG.md | 1 + core/version.txt | 2 +- devops/terraform/main.tf | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc53cbd568..5a5167889c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ ENHANCEMENTS: * Update Terraform to use Azure AD authentication rather than storage account keys ([#4103](https://github.com/microsoft/AzureTRE/issues/4103)) * Update obsolete Terraform properties ([#4136](https://github.com/microsoft/AzureTRE/issues/4136)) * Update Guacamole version and dependencies ([#4140](https://github.com/microsoft/AzureTRE/issues/4140)) +* Add partial (core resources only) support for customer managed keys ([#4141](https://github.com/microsoft/AzureTRE/issues/4142)) BUG FIXES: - Update KeyVault references in API to use the version so Terraform cascades the update ([#4112](https://github.com/microsoft/AzureTRE/pull/4112)) diff --git a/core/version.txt b/core/version.txt index fee46bd8ce..e2bd0728a9 100644 --- a/core/version.txt +++ b/core/version.txt @@ -1 +1 @@ -__version__ = "0.11.1" +__version__ = "0.11.2" diff --git a/devops/terraform/main.tf b/devops/terraform/main.tf index 195d768e03..5e42d5e491 100644 --- a/devops/terraform/main.tf +++ b/devops/terraform/main.tf @@ -109,7 +109,7 @@ resource "azurerm_key_vault" "encryption_kv" { sku_name = "standard" tenant_id = data.azurerm_client_config.current.tenant_id enable_rbac_authorization = true - purge_protection_enabled = true + purge_protection_enabled = true lifecycle { ignore_changes = [tags] } } From 70ddb6bfa092eb2b35641b945d9f5ab4d45d4bb2 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Tue, 19 Nov 2024 15:32:33 +0000 Subject: [PATCH 16/26] remove unused var --- devops/terraform/variables.tf | 6 ------ 1 file changed, 6 deletions(-) diff --git a/devops/terraform/variables.tf b/devops/terraform/variables.tf index 45c314fd61..ff151f43b1 100644 --- a/devops/terraform/variables.tf +++ b/devops/terraform/variables.tf @@ -24,12 +24,6 @@ variable "acr_name" { description = "Name of ACR" } -variable "kv_purge_protection_enabled" { - type = bool - description = "A boolean indicating if the purge protection will be enabled on the core keyvault." - default = true -} - variable "enable_cmk_encryption" { type = bool description = "A boolean indicating if customer managed keys will be used for encryption of supporting resources" From ce953ea27ef2ae8db54cc621000791f9bd560b09 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Tue, 19 Nov 2024 15:39:36 +0000 Subject: [PATCH 17/26] remove redundant variable --- devops/terraform/variables.tf | 6 ------ 1 file changed, 6 deletions(-) diff --git a/devops/terraform/variables.tf b/devops/terraform/variables.tf index ff151f43b1..238bc2f26e 100644 --- a/devops/terraform/variables.tf +++ b/devops/terraform/variables.tf @@ -42,12 +42,6 @@ variable "encryption_kv_name" { default = null } -variable "kv_encryption_key_name" { - type = string - description = "Name of Key Vault Encryption Key (only used if enable_cmk_encryption is true)" - default = "tre-encryption" -} - variable "kv_mgmt_encryption_key_name" { type = string description = "Name of Key Vault Encryption Key for management resources (only used if enable_cmk_encryption is true)" From 8a48a9510f3b67a31cd1077ce5bcb3932a90f5cb Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Tue, 19 Nov 2024 15:49:09 +0000 Subject: [PATCH 18/26] remove redundant variables --- core/terraform/appgateway/variables.tf | 4 +--- core/terraform/azure-monitor/variables.tf | 4 +--- core/terraform/main.tf | 10 ++++------ 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/core/terraform/appgateway/variables.tf b/core/terraform/appgateway/variables.tf index 710315cb9e..21d50f61b6 100644 --- a/core/terraform/appgateway/variables.tf +++ b/core/terraform/appgateway/variables.tf @@ -29,9 +29,7 @@ variable "log_analytics_workspace_id" { variable "app_gateway_sku" { type = string } -variable "mgmt_resource_group_name" { - type = string -} + variable "encryption_identity_id" { type = string description = "User Managed Identity with permissions to get encryption keys from key vault" diff --git a/core/terraform/azure-monitor/variables.tf b/core/terraform/azure-monitor/variables.tf index 244477363f..30b99dc0a7 100644 --- a/core/terraform/azure-monitor/variables.tf +++ b/core/terraform/azure-monitor/variables.tf @@ -31,9 +31,7 @@ variable "tre_core_tags" { variable "enable_local_debugging" { type = bool } -variable "mgmt_resource_group_name" { - type = string -} + variable "encryption_identity_id" { type = string description = "User Managed Identity with permissions to get encryption keys from key vault" diff --git a/core/terraform/main.tf b/core/terraform/main.tf index 18b94b69cf..4170cc35d6 100644 --- a/core/terraform/main.tf +++ b/core/terraform/main.tf @@ -77,7 +77,6 @@ module "azure_monitor" { key_store_id = local.key_store_id kv_encryption_key_name = var.kv_encryption_key_name encryption_identity_id = azurerm_user_assigned_identity.encryption[0].id - mgmt_resource_group_name = var.mgmt_resource_group_name depends_on = [ module.network, @@ -107,11 +106,10 @@ module "appgateway" { log_analytics_workspace_id = module.azure_monitor.log_analytics_workspace_id app_gateway_sku = var.app_gateway_sku - enable_cmk_encryption = var.enable_cmk_encryption - key_store_id = local.key_store_id - kv_encryption_key_name = var.kv_encryption_key_name - encryption_identity_id = azurerm_user_assigned_identity.encryption[0].id - mgmt_resource_group_name = var.mgmt_resource_group_name + enable_cmk_encryption = var.enable_cmk_encryption + key_store_id = local.key_store_id + kv_encryption_key_name = var.kv_encryption_key_name + encryption_identity_id = azurerm_user_assigned_identity.encryption[0].id depends_on = [ module.network, From b07871ec7f1d3beef33cfa3a7960a955b32eb564 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Tue, 19 Nov 2024 23:14:27 +0000 Subject: [PATCH 19/26] add check for enable_cmk_encryption for the key_store_id variable in tf --- core/terraform/locals.tf | 2 +- devops/terraform/locals.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/terraform/locals.tf b/core/terraform/locals.tf index bc2cafa922..0b8bc5dfc7 100644 --- a/core/terraform/locals.tf +++ b/core/terraform/locals.tf @@ -42,5 +42,5 @@ locals { service_bus_namespace_fqdn = regex("(?:(?P<scheme>[^:/?#]+):)?(?://(?P<fqdn>[^/?#:]*))?(?::(?P<port>[0-9]+))?(?P<path>[^?#]*)(?:\\?(?P<query>[^#]*))?(?:#(?P<fragment>.*))?", azurerm_servicebus_namespace.sb.endpoint).fqdn # The key store for encryption keys could either be external or created by terraform - key_store_id = var.external_key_store_id != null ? var.external_key_store_id : data.azurerm_key_vault.encryption_kv[0].id + key_store_id = var.enable_cmk_encryption ? (var.external_key_store_id != null ? var.external_key_store_id : data.azurerm_key_vault.encryption_kv[0].id) : null } diff --git a/devops/terraform/locals.tf b/devops/terraform/locals.tf index 2466ca2fa0..3f4e6efaee 100644 --- a/devops/terraform/locals.tf +++ b/devops/terraform/locals.tf @@ -1,4 +1,4 @@ locals { # The key store for encryption keys could either be external or created by terraform - key_store_id = var.external_key_store_id != null ? var.external_key_store_id : azurerm_key_vault.encryption_kv[0].id + key_store_id = var.enable_cmk_encryption ? (var.external_key_store_id != null ? var.external_key_store_id : data.azurerm_key_vault.encryption_kv[0].id) : null } From 01067485dc2f7f72b9a72efbafb859531d8cc878 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Tue, 19 Nov 2024 23:32:27 +0000 Subject: [PATCH 20/26] bugfix: remove redundant data keyword --- devops/terraform/locals.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devops/terraform/locals.tf b/devops/terraform/locals.tf index 3f4e6efaee..3beb01d417 100644 --- a/devops/terraform/locals.tf +++ b/devops/terraform/locals.tf @@ -1,4 +1,4 @@ locals { # The key store for encryption keys could either be external or created by terraform - key_store_id = var.enable_cmk_encryption ? (var.external_key_store_id != null ? var.external_key_store_id : data.azurerm_key_vault.encryption_kv[0].id) : null + key_store_id = var.enable_cmk_encryption ? (var.external_key_store_id != null ? var.external_key_store_id : azurerm_key_vault.encryption_kv[0].id) : null } From 18ce3fde84cf16241e35590ecbb0240f6600a4ef Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Wed, 20 Nov 2024 09:46:45 +0000 Subject: [PATCH 21/26] add enable_cmk_encryption check in module variables --- core/terraform/main.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/terraform/main.tf b/core/terraform/main.tf index 4170cc35d6..bfdf5e168a 100644 --- a/core/terraform/main.tf +++ b/core/terraform/main.tf @@ -76,7 +76,7 @@ module "azure_monitor" { enable_cmk_encryption = var.enable_cmk_encryption key_store_id = local.key_store_id kv_encryption_key_name = var.kv_encryption_key_name - encryption_identity_id = azurerm_user_assigned_identity.encryption[0].id + encryption_identity_id = var.enable_cmk_encryption ? azurerm_user_assigned_identity.encryption[0].id : null depends_on = [ module.network, @@ -109,7 +109,7 @@ module "appgateway" { enable_cmk_encryption = var.enable_cmk_encryption key_store_id = local.key_store_id kv_encryption_key_name = var.kv_encryption_key_name - encryption_identity_id = azurerm_user_assigned_identity.encryption[0].id + encryption_identity_id = var.enable_cmk_encryption ? azurerm_user_assigned_identity.encryption[0].id : null depends_on = [ module.network, @@ -149,7 +149,7 @@ module "airlock_resources" { enable_cmk_encryption = var.enable_cmk_encryption key_store_id = local.key_store_id kv_encryption_key_name = var.kv_encryption_key_name - encryption_identity_id = azurerm_user_assigned_identity.encryption[0].id + encryption_identity_id = var.enable_cmk_encryption ? azurerm_user_assigned_identity.encryption[0].id : null depends_on = [ azurerm_servicebus_namespace.sb, From c05f752b8b6a78cdca8f23a0777974053833d3b6 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Thu, 21 Nov 2024 15:49:34 +0000 Subject: [PATCH 22/26] remove redundant key_vault_id from ignore_changes for cmk --- core/terraform/airlock/airlock_processor.tf | 6 ---- core/terraform/airlock/storage_accounts.tf | 30 ------------------- core/terraform/appgateway/staticweb.tf | 6 ---- core/terraform/azure-monitor/azure-monitor.tf | 6 ---- core/terraform/storage.tf | 6 ---- devops/terraform/main.tf | 6 ---- 6 files changed, 60 deletions(-) diff --git a/core/terraform/airlock/airlock_processor.tf b/core/terraform/airlock/airlock_processor.tf index 028567c561..1af44f067c 100644 --- a/core/terraform/airlock/airlock_processor.tf +++ b/core/terraform/airlock/airlock_processor.tf @@ -44,12 +44,6 @@ resource "azurerm_storage_account_customer_managed_key" "sa_airlock_processor_fu key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id - - lifecycle { - ignore_changes = [ - key_vault_id - ] - } } resource "azurerm_linux_function_app" "airlock_function_app" { diff --git a/core/terraform/airlock/storage_accounts.tf b/core/terraform/airlock/storage_accounts.tf index 4daacfbf0a..adb6604cc8 100644 --- a/core/terraform/airlock/storage_accounts.tf +++ b/core/terraform/airlock/storage_accounts.tf @@ -58,12 +58,6 @@ resource "azurerm_storage_account_customer_managed_key" "sa_import_external_encr key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id - - lifecycle { - ignore_changes = [ - key_vault_id - ] - } } # 'Approved' export @@ -124,12 +118,6 @@ resource "azurerm_storage_account_customer_managed_key" "sa_export_approved_encr key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id - - lifecycle { - ignore_changes = [ - key_vault_id - ] - } } # 'In-Progress' storage account @@ -171,12 +159,6 @@ resource "azurerm_storage_account_customer_managed_key" "sa_import_in_progress_e key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id - - lifecycle { - ignore_changes = [ - key_vault_id - ] - } } @@ -290,12 +272,6 @@ resource "azurerm_storage_account_customer_managed_key" "sa_import_rejected_encr key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id - - lifecycle { - ignore_changes = [ - key_vault_id - ] - } } # 'Blocked' storage account @@ -360,10 +336,4 @@ resource "azurerm_storage_account_customer_managed_key" "sa_import_blocked_encry key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id - - lifecycle { - ignore_changes = [ - key_vault_id - ] - } } diff --git a/core/terraform/appgateway/staticweb.tf b/core/terraform/appgateway/staticweb.tf index 35d603dc00..e00745e45e 100644 --- a/core/terraform/appgateway/staticweb.tf +++ b/core/terraform/appgateway/staticweb.tf @@ -37,12 +37,6 @@ resource "azurerm_storage_account_customer_managed_key" "staticweb_encryption" { key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id - - lifecycle { - ignore_changes = [ - key_vault_id - ] - } } # Assign the "Storage Blob Data Contributor" role needed for uploading certificates to the storage account diff --git a/core/terraform/azure-monitor/azure-monitor.tf b/core/terraform/azure-monitor/azure-monitor.tf index a74e5f0fc8..36528ec2b2 100644 --- a/core/terraform/azure-monitor/azure-monitor.tf +++ b/core/terraform/azure-monitor/azure-monitor.tf @@ -45,12 +45,6 @@ resource "azurerm_storage_account_customer_managed_key" "az_monitor_encryption" key_vault_id = var.key_store_id key_name = var.kv_encryption_key_name user_assigned_identity_id = var.encryption_identity_id - - lifecycle { - ignore_changes = [ - key_vault_id - ] - } } resource "azurerm_log_analytics_linked_storage_account" "workspace_storage_ingestion" { diff --git a/core/terraform/storage.tf b/core/terraform/storage.tf index 55937fe55d..145b51f522 100644 --- a/core/terraform/storage.tf +++ b/core/terraform/storage.tf @@ -83,10 +83,4 @@ resource "azurerm_storage_account_customer_managed_key" "encryption" { depends_on = [ azurerm_role_assignment.kv_encryption_key_user[0] ] - - lifecycle { - ignore_changes = [ - key_vault_id - ] - } } diff --git a/devops/terraform/main.tf b/devops/terraform/main.tf index 5e42d5e491..92637c1a6d 100644 --- a/devops/terraform/main.tf +++ b/devops/terraform/main.tf @@ -52,12 +52,6 @@ resource "azurerm_storage_account_customer_managed_key" "state_storage_encryptio azurerm_role_assignment.kv_mgmt_encryption_key_user, azurerm_key_vault_key.tre_mgmt_encryption[0] ] - - lifecycle { - ignore_changes = [ - key_vault_id - ] - } } From c7f141387dd28a79f8626ab07805cd4eb36394af Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Sun, 24 Nov 2024 11:21:56 +0000 Subject: [PATCH 23/26] remove redundant sign/verify --- core/terraform/cmk_encryption.tf | 2 -- devops/terraform/cmk_encryption.tf | 2 -- 2 files changed, 4 deletions(-) diff --git a/core/terraform/cmk_encryption.tf b/core/terraform/cmk_encryption.tf index ec9484664a..c8b4b9a483 100644 --- a/core/terraform/cmk_encryption.tf +++ b/core/terraform/cmk_encryption.tf @@ -28,9 +28,7 @@ resource "azurerm_key_vault_key" "tre_encryption" { key_opts = [ "decrypt", "encrypt", - "sign", "unwrapKey", - "verify", "wrapKey", ] diff --git a/devops/terraform/cmk_encryption.tf b/devops/terraform/cmk_encryption.tf index 6f9d87bd3c..bd9af71a7f 100644 --- a/devops/terraform/cmk_encryption.tf +++ b/devops/terraform/cmk_encryption.tf @@ -27,9 +27,7 @@ resource "azurerm_key_vault_key" "tre_mgmt_encryption" { key_opts = [ "decrypt", "encrypt", - "sign", "unwrapKey", - "verify", "wrapKey", ] From 6f9e0fd35c29a82120b92579e7950e435d137750 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Mon, 25 Nov 2024 10:00:08 +0000 Subject: [PATCH 24/26] update docs --- docs/tre-admins/environment-variables.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/tre-admins/environment-variables.md b/docs/tre-admins/environment-variables.md index c35b945b46..04395b9ec9 100644 --- a/docs/tre-admins/environment-variables.md +++ b/docs/tre-admins/environment-variables.md @@ -12,6 +12,8 @@ | `MGMT_STORAGE_ACCOUNT_NAME` | The name of the storage account to hold the Terraform state and other deployment artifacts. | | `TERRAFORM_STATE_CONTAINER_NAME` | The name of the blob container to hold the Terraform state *Default value is `tfstate`.* | | `ACR_NAME` | A globally unique name for the Azure Container Registry (ACR) that will be created to store deployment images. | +| `EXTERNAL_KEY_STORE_ID` | The ID of the external Key Vault to store CMKs in. Should not be set if `ENCRYPTION_KV_NAME` is set and only required if `ENABLE_CMK_ENCRYPTION` is true. | +| `ENCRYPTION_KV_NAME` | The name of the Key Vault for encryption keys. Should not be set if `EXTERNAL_KEY_STORE_ID` is set and only required if `ENABLE_CMK_ENCRYPTION` is true. | | `ARM_SUBSCRIPTION_ID` | *Optional for manual deployment. If not specified the `az cli` selected subscription will be used.* The Azure subscription ID for all resources. | | `ARM_CLIENT_ID` | *Optional for manual deployment without logged-in credentials.* The client whose azure identity will be used to deploy the solution. | | `ARM_CLIENT_SECRET` | *Optional for manual deployment without logged-in credentials.* The password of the client defined in `ARM_CLIENT_ID`. | @@ -42,7 +44,7 @@ | `FIREWALL_SKU` | Optional. The SKU of the Azure Firewall instance. Default value is `Standard`. Allowed values [`Basic`, `Standard`, `Premium`]. See [Azure Firewall SKU feature comparison](https://learn.microsoft.com/en-us/azure/firewall/choose-firewall-sku). | | `APP_GATEWAY_SKU` | Optional. The SKU of the Application Gateway. Default value is `Standard_v2`. Allowed values [`Standard_v2`, `WAF_v2`] | | `CUSTOM_DOMAIN` | Optional. Custom domain name to access the Azure TRE portal. See [Custom domain name](custom-domain.md). | - +| `ENABLE_CMK_ENCRYPTION` | If set to `true`, customer-managed key encryption will be enabled for all supported resources. | ## For authentication in `/config.yaml` | Variable | Description | From 547528c8c0adcae3c9f44a14027a43e8ccb6b371 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Mon, 25 Nov 2024 18:59:21 +0000 Subject: [PATCH 25/26] add documentation for cmks --- docs/tre-admins/customer-managed-keys.md | 20 ++++++++++++++++++++ mkdocs.yml | 1 + 2 files changed, 21 insertions(+) create mode 100644 docs/tre-admins/customer-managed-keys.md diff --git a/docs/tre-admins/customer-managed-keys.md b/docs/tre-admins/customer-managed-keys.md new file mode 100644 index 0000000000..95392fb338 --- /dev/null +++ b/docs/tre-admins/customer-managed-keys.md @@ -0,0 +1,20 @@ +# Enabling Customer-managed keys for TRE resources + +You can enable customer-managed keys (CMK) for supporting resources in Azure TRE. + +When enabled, CMK provides an additional layer of encryption control for supported Azure resources within the TRE by allowing you to manage and control the encryption keys used to protect your data. With CMK enabled, TRE will create encryption keys in the specified Key Vault that are then used to encrypt the data in these resources, giving you full control over the encryption keys. + +To enable CMK encryption, set `enable_cmk_encryption: true` in the developer settings section of your `config.yaml` file. + + +## Key Vault configuration +The customer-managed keys for Azure TRE can be stored in either a Key Vault deployed by TRE itself, or in an external Key Vault provided by the user. +To have TRE create and manage its own Key Vault for storing CMKs, specify the `ENCRYPTION_KV_NAME` parameter in the `config.yaml` file. +Alternatively, to use your own existing Key Vault, provide the `EXTERNAL_KEY_STORE_ID` parameter pointing to your Key Vault resource ID. + +!!! warning + Currently Azure TRE only supports CMK encryption for resources in the TRE core. CMK encryption is not supported for the rest of the resources such as those deployed by a TRE workspace. + +# +For more information about customer-managed keys, see [Use customer-managed keys with Azure Storage encryption](https://learn.microsoft.com/azure/storage/common/customer-managed-keys-overview). + diff --git a/mkdocs.yml b/mkdocs.yml index edd9c4da74..4526800b85 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -140,6 +140,7 @@ nav: - Upgrading Resources Version: tre-admins/upgrading-resources.md - Configuring Airlock Reviews: tre-admins/configure-airlock-review.md - Supported Clouds: tre-admins/supported-clouds.md + - Customer Managed Keys: tre-admins/customer-managed-keys.md - Custom Domain Name: tre-admins/custom-domain.md - Development: # Docs related to the developing code for the AzureTRE From 3e909009e6cb5239c768a8316983e18b750771d2 Mon Sep 17 00:00:00 2001 From: Yuval Yaron <yuvalyaron@microsoft.com> Date: Mon, 25 Nov 2024 19:17:39 +0000 Subject: [PATCH 26/26] refine cmk docs --- docs/tre-admins/customer-managed-keys.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/tre-admins/customer-managed-keys.md b/docs/tre-admins/customer-managed-keys.md index 95392fb338..414bf0870a 100644 --- a/docs/tre-admins/customer-managed-keys.md +++ b/docs/tre-admins/customer-managed-keys.md @@ -2,19 +2,20 @@ You can enable customer-managed keys (CMK) for supporting resources in Azure TRE. -When enabled, CMK provides an additional layer of encryption control for supported Azure resources within the TRE by allowing you to manage and control the encryption keys used to protect your data. With CMK enabled, TRE will create encryption keys in the specified Key Vault that are then used to encrypt the data in these resources, giving you full control over the encryption keys. +!!! warning + Currently Azure TRE only supports CMK encryption for resources in the TRE core. + CMK encryption is not supported for the rest of the resources such as those deployed by a TRE workspace. + + +When enabled, CMK encryption provides an additional layer of encryption control for supported Azure resources within the TRE by allowing you to manage and control the encryption keys used to protect your data. To enable CMK encryption, set `enable_cmk_encryption: true` in the developer settings section of your `config.yaml` file. +For more information about CMKs, see [Use customer-managed keys with Azure Storage encryption](https://learn.microsoft.com/azure/storage/common/customer-managed-keys-overview). ## Key Vault configuration -The customer-managed keys for Azure TRE can be stored in either a Key Vault deployed by TRE itself, or in an external Key Vault provided by the user. -To have TRE create and manage its own Key Vault for storing CMKs, specify the `ENCRYPTION_KV_NAME` parameter in the `config.yaml` file. -Alternatively, to use your own existing Key Vault, provide the `EXTERNAL_KEY_STORE_ID` parameter pointing to your Key Vault resource ID. +The CMKs for Azure TRE can be stored in either a Key Vault deployed by TRE itself, or in an external Key Vault provided by the user. -!!! warning - Currently Azure TRE only supports CMK encryption for resources in the TRE core. CMK encryption is not supported for the rest of the resources such as those deployed by a TRE workspace. - -# -For more information about customer-managed keys, see [Use customer-managed keys with Azure Storage encryption](https://learn.microsoft.com/azure/storage/common/customer-managed-keys-overview). +To have TRE create and manage its own Key Vault for storing CMKs, specify the `ENCRYPTION_KV_NAME` parameter in the `config.yaml` file. +Alternatively, to use your own existing Key Vault, provide the `EXTERNAL_KEY_STORE_ID` parameter pointing to your Key Vault resource ID.