diff --git a/quickstart/101-databricks-cmk-dbfs/main.tf b/quickstart/101-databricks-cmk-dbfs/main.tf new file mode 100644 index 000000000..a4c7186cb --- /dev/null +++ b/quickstart/101-databricks-cmk-dbfs/main.tf @@ -0,0 +1,101 @@ +# Create resource group. +resource "random_pet" "rg_name" { + prefix = var.resource_group_name_prefix +} + +resource "azurerm_resource_group" "rg" { + name = random_pet.rg_name.id + location = var.resource_group_location +} + +data "azurerm_client_config" "current" {} + +locals { + current_user_id = coalesce(var.msi_id, data.azurerm_client_config.current.object_id) +} + +resource "random_pet" "azurerm_databricks_workspace_name" { + count = var.workspace_name == null || var.workspace_name == "" ? 1 : 0 + prefix = var.workspace_name_prefix +} + +# Create workspace. +resource "azurerm_databricks_workspace" "databricks" { + name = coalesce(var.workspace_name, random_pet.azurerm_databricks_workspace_name[0].id) + resource_group_name = azurerm_resource_group.rg.name + location = azurerm_resource_group.rg.location + sku = var.wssku + customer_managed_key_enabled = true +} + +# Configure CMK. +resource "azurerm_databricks_workspace_customer_managed_key" "cmk" { + workspace_id = azurerm_databricks_workspace.databricks.id + key_vault_key_id = azurerm_key_vault_key.key.id + + depends_on = [azurerm_key_vault_access_policy.databricks] +} + +resource "random_pet" "azurerm_key_vault_name" { + count = var.key_vault_name == null || var.key_vault_name == "" ? 1 : 0 + prefix = var.key_vault_name_prefix +} + +# Create Key Vault. +resource "azurerm_key_vault" "vault" { + name = coalesce(var.key_vault_name, random_pet.azurerm_key_vault_name[0].id) + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + tenant_id = data.azurerm_client_config.current.tenant_id + sku_name = var.sku_name + purge_protection_enabled = true + soft_delete_retention_days = 7 +} + +resource "random_pet" "azurerm_key_vault_key_name" { + count = var.key_name == null || var.key_name == "" ? 1 : 0 + prefix = var.key_name_prefix +} + +# Create Key Vault access policy. +resource "azurerm_key_vault_access_policy" "current_user" { + key_vault_id = azurerm_key_vault.vault.id + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = local.current_user_id + + key_permissions = var.key_permissions + secret_permissions = var.secret_permissions +} + +# Create Key Vault key. +resource "azurerm_key_vault_key" "key" { + name = coalesce(var.key_name, random_pet.azurerm_key_vault_key_name[0].id) + key_vault_id = azurerm_key_vault.vault.id + key_type = var.key_type + key_size = var.key_size + + key_opts = var.key_opts + + rotation_policy { + automatic { + time_before_expiry = "P30D" + } + + expire_after = "P90D" + notify_before_expiry = "P29D" + } + + depends_on = [azurerm_key_vault_access_policy.current_user] +} + +# Create access policy. +resource "azurerm_key_vault_access_policy" "databricks" { + key_vault_id = azurerm_key_vault.vault.id + tenant_id = azurerm_databricks_workspace.databricks.storage_account_identity[0].tenant_id + object_id = azurerm_databricks_workspace.databricks.storage_account_identity[0].principal_id + key_permissions = [ + "Get", + "UnwrapKey", + "WrapKey", + ] +} \ No newline at end of file diff --git a/quickstart/101-databricks-cmk-dbfs/outputs.tf b/quickstart/101-databricks-cmk-dbfs/outputs.tf new file mode 100644 index 000000000..b456b9674 --- /dev/null +++ b/quickstart/101-databricks-cmk-dbfs/outputs.tf @@ -0,0 +1,19 @@ +output "resource_group_name" { + value = azurerm_resource_group.rg.name +} + +output "azurerm_key_vault_name" { + value = azurerm_key_vault.vault.name +} + +output "azurerm_key_vault_id" { + value = azurerm_key_vault.vault.id +} + +output "azurerm_databricks_workspace_name" { + value = azurerm_databricks_workspace.databricks.name +} + +output "azurerm_databricks_workspace_id" { + value = azurerm_databricks_workspace.databricks.id +} \ No newline at end of file diff --git a/quickstart/101-databricks-cmk-dbfs/providers.tf b/quickstart/101-databricks-cmk-dbfs/providers.tf new file mode 100644 index 000000000..4fd5f6ba7 --- /dev/null +++ b/quickstart/101-databricks-cmk-dbfs/providers.tf @@ -0,0 +1,16 @@ +terraform { + required_version = ">=1.0" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~>3.0" + } + random = { + source = "hashicorp/random" + version = "~>3.0" + } + } +} +provider "azurerm" { + features {} +} \ No newline at end of file diff --git a/quickstart/101-databricks-cmk-dbfs/readme.md b/quickstart/101-databricks-cmk-dbfs/readme.md new file mode 100644 index 000000000..d5202385c --- /dev/null +++ b/quickstart/101-databricks-cmk-dbfs/readme.md @@ -0,0 +1,39 @@ +# Azure Databricks CMK for DBFS + +This template configures customer managed keys (CMK) for DBFS. + +## Terraform resource types + +- [random_pet](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) +- [azurerm_resource_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) +- [azurerm_client_config](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config.html) +- [azurerm_databricks_workspace](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/databricks_workspace) +- [azurerm_databricks_workspace_customer_managed_key](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/databricks_workspace_customer_managed_key) +- [azurerm_key_vault](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault) +- [azurerm_key_vault_key](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_key) +- [azurerm_key_vault_access_policy](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_access_policy) + +## Variables + +| Name | Description | Default | +|-|-|-| +| `resource_group_location` | Location of the resource group. | East US 2 | +| `resource_group_name_prefix` | Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription. | rg | +| `workspace_name_prefix` | Prefix of the Azure Databricks Workspace name that's combined with a random ID so name is unique in your Azure subscription. | db | +| `workspace_name` | Azure Databricks workspace name. The value is randomly generated if null. | null | +| `wssku` | Pricing Tier of the Azure Databricks workspace. | premium | +| `key_vault_name_prefix` | Prefix of the Azure Key Vault name that's combined with a random ID so name is unique in your Azure subscription. | vault | +| `key_vault_name` | Name of new key vault. The value is randomly generated if null. | null | +| `sku_name` | SKU tier of Azure Key Vault | premium | +| `key_name_prefix` | Prefix of the Key Vault key name that's combined with a random ID so name is unique in your Azure subscription. | key | +| `key_name` | The name of the key to be created. The value is randomly generated if null. | null | +| `key_permissions` | List of key permissions. Choose from: Backup, Create, Decrypt, Delete, Encrypt, Get, GetRotationPolicy, Import, List, Purge, Recover, Release, Restore, Rotate, SetRotationPolicy, Sign, UnwrapKey, Update, Verify, WrapKey | ["Create", "Decrypt", "Delete", "Encrypt", "Get", "GetRotationPolicy", "List", "Purge", "Recover", "Restore", "SetRotationPolicy", "Sign", "UnwrapKey", "Update", "Verify", "WrapKey"] | +| `secret_permissions` | List of secret permissions. Choose from: Backup, Delete, Get, List, Purge, Recover, Restore, Set. | ["Set"] | +| `key_type` | The JsonWebKeyType of the key to be created. Choose from: EC, EC-HSM, RSA, RSA-HSM | RSA | +| `key_opts` | The permitted JSON web key operations of the key to be created. Choose from: decrypt, encrypt, sign, unwrapKey, verify, wrapKey. | ["decrypt", "encrypt", "sign", "unwrapKey", "verify", "wrapKey"] | +| `key_size` | The size (in bytes) of the key to be created. | 2048 | +| `msi_id` | The Managed Service Identity ID. Set this value if you're running this example using Managed Identity as the authentication method. | null | + +## Example + +To see how to run this example, see [Configure customer-managed keys for DBFS using Terraform](https://learn.microsoft.com/en-us/azure/databricks/security/keys/customer-managed-keys-dbfs/cmk-dbfs-terraform). diff --git a/quickstart/101-databricks-cmk-dbfs/variables.tf b/quickstart/101-databricks-cmk-dbfs/variables.tf new file mode 100644 index 000000000..d612ac2d6 --- /dev/null +++ b/quickstart/101-databricks-cmk-dbfs/variables.tf @@ -0,0 +1,116 @@ +variable "resource_group_location" { + type = string + description = "Location for creating resource." + default = "East US 2" +} + +variable "resource_group_name_prefix" { + type = string + description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription." + default = "rg" +} + +variable "workspace_name_prefix" { + type = string + description = "Prefix of the Azure Databricks workspace name that's combined with a random ID so name is unique in your Azure subscription." + default = "db" +} + +variable "workspace_name" { + type = string + description = "Azure Databricks workspace name." + default = null +} + +variable "wssku" { + type = string + description = "Pricing Tier of the Azure Databricks workspace." + default = "premium" +} + +variable "key_vault_name_prefix" { + type = string + description = "Prefix of the Azure Key Vault name that's combined with a random ID so name is unique in your Azure subscription." + default = "vault" +} + +variable "key_vault_name" { + type = string + description = "The name of the key vault to be created. The value will be randomly generated if blank." + default = null +} + +variable "sku_name" { + type = string + description = "SKU tier of Azure Key Vault" + default = "premium" +} + +variable "key_name_prefix" { + type = string + description = "Prefix of the Key Vault key name that's combined with a random ID so name is unique in your Azure subscription." + default = "key" +} + +variable "key_name" { + type = string + description = "The name of the key to be created. The value will be randomly generated if blank." + default = null +} + +variable "key_permissions" { + type = list(string) + description = "List of key permissions." + default = [ + "Create", + "Decrypt", + "Delete", + "Encrypt", + "Get", + "GetRotationPolicy", + "List", + "Purge", + "Recover", + "Restore", + "SetRotationPolicy", + "Sign", + "UnwrapKey", + "Update", + "Verify", + "WrapKey" + ] +} + +variable "secret_permissions" { + type = list(string) + description = "List of secret permissions." + default = ["Set"] +} + +variable "key_type" { + type = string + description = "The JsonWebKeyType of the key to be created." + default = "RSA" + validation { + condition = contains(["EC", "EC-HSM", "RSA", "RSA-HSM"], var.key_type) + error_message = "The key_type must be one of the following: EC, EC-HSM, RSA, RSA-HSM." + } +} + +variable "key_opts" { + type = list(string) + description = "The permitted JSON web key operations of the key to be created." + default = ["decrypt", "encrypt", "sign", "unwrapKey", "verify", "wrapKey"] +} + +variable "key_size" { + type = number + description = "The size in bits of the key to be created." + default = 2048 +} + +variable "msi_id" { + type = string + description = "The Managed Service Identity ID. Set this value if you're running this example using Managed Identity as the authentication method." + default = null +} \ No newline at end of file