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

User Story 60501: 101-databricks-cmk-dbfs #219

Merged
99 changes: 99 additions & 0 deletions quickstart/101-databricks-cmk-dbfs/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# 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" {
TomArcherMsft marked this conversation as resolved.
Show resolved Hide resolved
count = var.workspace_name == null ? 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 ? 1 : 0
prefix = var.key_vault_name_prefix
TomArcherMsft marked this conversation as resolved.
Show resolved Hide resolved
}

# 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

access_policy {
TomArcherMsft marked this conversation as resolved.
Show resolved Hide resolved
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
}
}

resource "random_pet" "azurerm_key_vault_key_name" {
count = var.key_name == null ? 1 : 0
Copy link
Member

@lonegunmanb lonegunmanb May 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In line 72:

resource "azurerm_key_vault_key" "key" {
  name         = coalesce(var.key_name, random_pet.azurerm_key_vault_key_name[0].id)

So when var.key_name equals to empty string("") it would lead to random_pet.azurerm_key_vault_key_name[0], but random_pet.azurerm_key_vault_key_name would be created only when var.key_name is null.

We can use the following toggle expression:

count = var.key_name == null || var.key_name == "" ? 1 : 0

prefix = var.key_name_prefix
TomArcherMsft marked this conversation as resolved.
Show resolved Hide resolved
}

# 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"
}
TomArcherMsft marked this conversation as resolved.
Show resolved Hide resolved
}

# 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
TomArcherMsft marked this conversation as resolved.
Show resolved Hide resolved
object_id = azurerm_databricks_workspace.databricks.storage_account_identity.0.principal_id
TomArcherMsft marked this conversation as resolved.
Show resolved Hide resolved
key_permissions = [
"Get",
"UnwrapKey",
"WrapKey",
]

depends_on = [azurerm_databricks_workspace.databricks]
TomArcherMsft marked this conversation as resolved.
Show resolved Hide resolved
}
19 changes: 19 additions & 0 deletions quickstart/101-databricks-cmk-dbfs/outputs.tf
Original file line number Diff line number Diff line change
@@ -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
}
16 changes: 16 additions & 0 deletions quickstart/101-databricks-cmk-dbfs/providers.tf
Original file line number Diff line number Diff line change
@@ -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 {}
}
39 changes: 39 additions & 0 deletions quickstart/101-databricks-cmk-dbfs/readme.md
Original file line number Diff line number Diff line change
@@ -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. If this value isn't null (the default), the Azure Key Vault Object ID will be set to this value. | 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).
116 changes: 116 additions & 0 deletions quickstart/101-databricks-cmk-dbfs/variables.tf
Original file line number Diff line number Diff line change
@@ -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. If this value isn't null (the default), the Azure Key Vault Object ID will be set to this value."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would the following description be better?:

description = "The Managed Service Identity ID, set this value if you're running this example by using Managed Identity as authentication method."

default = null
TomArcherMsft marked this conversation as resolved.
Show resolved Hide resolved
}