Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add CMK support for core resources #4149

Merged
merged 30 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9d185d4
added management key vault
Sep 9, 2024
3bab628
added cmk for vmss and storage accounts
Sep 11, 2024
dec4288
Merge branch 'main' of https://github.com/yuvalyaron/AzureTRE into 40…
yuvalyaron Nov 7, 2024
7388db5
Merge branch 'main' of https://github.com/yuvalyaron/AzureTRE into 40…
yuvalyaron Nov 11, 2024
036b90e
add default value for variables
yuvalyaron Nov 13, 2024
27212b4
add CMK for cosmos accounts
yuvalyaron Nov 14, 2024
50ec316
move tre-encryption key from mgmt to core
yuvalyaron Nov 17, 2024
df682d6
fix order of creation for encryption key
yuvalyaron Nov 17, 2024
9e66234
add cmk for the state store in mgmt
yuvalyaron Nov 17, 2024
fed7a16
add support for external KV
yuvalyaron Nov 18, 2024
7f24a23
revert CMK for cosmos - not working, need to redo this
yuvalyaron Nov 18, 2024
cd9271a
refine comments and files names
yuvalyaron Nov 19, 2024
f459a82
remove redundant space
yuvalyaron Nov 19, 2024
af53615
add space
yuvalyaron Nov 19, 2024
61d8e97
upper case in comment
yuvalyaron Nov 19, 2024
25322d7
revert cosmos tags
yuvalyaron Nov 19, 2024
e3e2d6c
Merge branch 'main' into 4002-cmk-support
yuvalyaron Nov 19, 2024
8ef0231
update changelog + core version
yuvalyaron Nov 19, 2024
70ddb6b
remove unused var
yuvalyaron Nov 19, 2024
ce953ea
remove redundant variable
yuvalyaron Nov 19, 2024
8a48a95
remove redundant variables
yuvalyaron Nov 19, 2024
b07871e
add check for enable_cmk_encryption for the key_store_id variable in tf
yuvalyaron Nov 19, 2024
0106748
bugfix: remove redundant data keyword
yuvalyaron Nov 19, 2024
18ce3fd
add enable_cmk_encryption check in module variables
yuvalyaron Nov 20, 2024
c05f752
remove redundant key_vault_id from ignore_changes for cmk
yuvalyaron Nov 21, 2024
c7f1413
remove redundant sign/verify
yuvalyaron Nov 24, 2024
6f9e0fd
update docs
yuvalyaron Nov 25, 2024
547528c
add documentation for cmks
yuvalyaron Nov 25, 2024
3e90900
refine cmk docs
yuvalyaron Nov 25, 2024
95c6b6a
Merge branch 'main' of https://github.com/microsoft/AzureTRE into 400…
yuvalyaron Nov 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,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))
Expand Down
7 changes: 7 additions & 0 deletions config.sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ management:
mgmt_storage_account_name: __CHANGE_ME__
terraform_state_container_name: tfstate
acr_name: __CHANGE_ME__
# ID of external Key Vault to store CMKs in (only required if enable_cmk_encryption is true)
yuvalyaron marked this conversation as resolved.
Show resolved Hide resolved
# 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
# encryption_kv_name: __CHANGE_ME__
# Azure Resource Manager credentials used for CI/CD pipelines
arm_subscription_id: __CHANGE_ME__

Expand Down Expand Up @@ -80,6 +84,9 @@ developer_settings:
# the base workspace.
# enable_local_debugging: true

# This setting enables customer-managed key encryption for all supported resources
# enable_cmk_encryption: true
yuvalyaron marked this conversation as resolved.
Show resolved Hide resolved

# Used by the API and Resource processor application to change log level
# Can be "ERROR", "WARNING", "INFO", "DEBUG"
# logging_level: "INFO"
Expand Down
16 changes: 16 additions & 0 deletions core/terraform/airlock/airlock_processor.tf
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,25 @@ resource "azurerm_storage_account" "sa_airlock_processor_func_app" {
cross_tenant_replication_enabled = 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 = var.key_store_id
key_name = var.kv_encryption_key_name
user_assigned_identity_id = var.encryption_identity_id
}

resource "azurerm_linux_function_app" "airlock_function_app" {
name = local.airlock_function_app_name
resource_group_name = var.resource_group_name
Expand Down
82 changes: 82 additions & 0 deletions core/terraform/airlock/storage_accounts.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@


# 'External' storage account - drop location for import
resource "azurerm_storage_account" "sa_import_external" {
name = local.import_external_storage_name
Expand All @@ -14,6 +16,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"
})
Expand Down Expand Up @@ -43,6 +53,14 @@ 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 = var.key_store_id
key_name = var.kv_encryption_key_name
user_assigned_identity_id = var.encryption_identity_id
}

# 'Approved' export
resource "azurerm_storage_account" "sa_export_approved" {
name = local.export_approved_storage_name
Expand All @@ -59,6 +77,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"
})
Expand Down Expand Up @@ -88,6 +114,14 @@ 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 = var.key_store_id
key_name = var.kv_encryption_key_name
user_assigned_identity_id = var.encryption_identity_id
}

# 'In-Progress' storage account
resource "azurerm_storage_account" "sa_import_in_progress" {
name = local.import_in_progress_storage_name
Expand All @@ -102,6 +136,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"
})
Expand All @@ -114,6 +156,14 @@ 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 = var.key_store_id
key_name = var.kv_encryption_key_name
user_assigned_identity_id = var.encryption_identity_id
}


# Enable Airlock Malware Scanning on Core TRE
resource "azapi_resource_action" "enable_defender_for_storage" {
Expand Down Expand Up @@ -177,6 +227,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"
})
Expand Down Expand Up @@ -212,6 +270,14 @@ 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 = var.key_store_id
key_name = var.kv_encryption_key_name
user_assigned_identity_id = var.encryption_identity_id
}

# 'Blocked' storage account
resource "azurerm_storage_account" "sa_import_blocked" {
name = local.import_blocked_storage_name
Expand All @@ -226,6 +292,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"
})
Expand Down Expand Up @@ -260,3 +334,11 @@ 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 = var.key_store_id
key_name = var.kv_encryption_key_name
user_assigned_identity_id = var.encryption_identity_id
}
21 changes: 21 additions & 0 deletions core/terraform/airlock/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,24 @@ 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 customer managed keys will be used for encryption of supporting resources"
}

variable "key_store_id" {
type = string
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" {
type = string
description = "Name of Key Vault Encryption Key (only used if enable_cmk_encryption is true)"
}
16 changes: 16 additions & 0 deletions core/terraform/appgateway/staticweb.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ 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 = var.key_store_id
key_name = var.kv_encryption_key_name
user_assigned_identity_id = var.encryption_identity_id
}

# Assign the "Storage Blob Data Contributor" role needed for uploading certificates to the storage account
Expand Down
18 changes: 18 additions & 0 deletions core/terraform/appgateway/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,21 @@ variable "log_analytics_workspace_id" {
variable "app_gateway_sku" {
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 customer managed keys will be used for encryption of supporting resources"
}
variable "key_store_id" {
type = string
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" {
type = string
description = "Name of Key Vault Encryption Key (only used if enable_cmk_encryption is true)"
}
16 changes: 16 additions & 0 deletions core/terraform/azure-monitor/azure-monitor.tf
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,25 @@ 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 = var.key_store_id
key_name = var.kv_encryption_key_name
user_assigned_identity_id = var.encryption_identity_id
}

resource "azurerm_log_analytics_linked_storage_account" "workspace_storage_ingestion" {
data_source_type = "Ingestion"
resource_group_name = var.resource_group_name
Expand Down
18 changes: 18 additions & 0 deletions core/terraform/azure-monitor/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,21 @@ variable "tre_core_tags" {
variable "enable_local_debugging" {
type = bool
}

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 customer managed keys will be used for encryption of supporting resources"
}
variable "key_store_id" {
type = string
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" {
type = string
description = "Name of Key Vault Encryption Key (only used if enable_cmk_encryption is true)"
}
38 changes: 38 additions & 0 deletions core/terraform/cmk_encryption.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
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 = local.key_store_id
role_definition_name = "Key Vault Crypto Service Encryption User"
principal_id = azurerm_user_assigned_identity.encryption[0].principal_id
}

# 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 = local.key_store_id
key_type = "RSA"
key_size = 2048

key_opts = [
"decrypt",
"encrypt",
"unwrapKey",
"wrapKey",
]

depends_on = [
azurerm_role_assignment.kv_encryption_key_user
]
}
6 changes: 6 additions & 0 deletions core/terraform/data.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
3 changes: 3 additions & 0 deletions core/terraform/locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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.enable_cmk_encryption ? (var.external_key_store_id != null ? var.external_key_store_id : data.azurerm_key_vault.encryption_kv[0].id) : null
}
Loading
Loading