Skip to content

Commit

Permalink
feat: Implement support for KMS arguments (#288)
Browse files Browse the repository at this point in the history
* feat: Implement support for KMS arguments
  • Loading branch information
mkilchhofer authored Jan 29, 2023
1 parent 9fcf342 commit 5443398
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 52 deletions.
1 change: 1 addition & 0 deletions .checkov_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ quiet: true
secrets-scan-file-type: []
skip-check:
- CKV_GHA_3
- CKV_AZURE_112
- CKV_AZURE_168
- CKV_AZURE_170
skip-framework:
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,14 +242,14 @@ The following sections are generated by [terraform-docs](https://github.com/terr
| Name | Version |
|---------------------------------------------------------------------------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.2 |
| <a name="requirement_azurerm"></a> [azurerm](#requirement\_azurerm) | >= 3.27 |
| <a name="requirement_azurerm"></a> [azurerm](#requirement\_azurerm) | >= 3.40 |
| <a name="requirement_tls"></a> [tls](#requirement\_tls) | >= 3.1 |

## Providers

| Name | Version |
|---------------------------------------------------------------|---------|
| <a name="provider_azurerm"></a> [azurerm](#provider\_azurerm) | >= 3.27 |
| <a name="provider_azurerm"></a> [azurerm](#provider\_azurerm) | >= 3.40 |
| <a name="provider_tls"></a> [tls](#provider\_tls) | >= 3.1 |

## Modules
Expand Down Expand Up @@ -321,6 +321,9 @@ No modules.
| <a name="input_ingress_application_gateway_subnet_cidr"></a> [ingress\_application\_gateway\_subnet\_cidr](#input\_ingress\_application\_gateway\_subnet\_cidr) | The subnet CIDR to be used to create an Application Gateway, which in turn will be integrated with the ingress controller of this Kubernetes Cluster. | `string` | `null` | no |
| <a name="input_ingress_application_gateway_subnet_id"></a> [ingress\_application\_gateway\_subnet\_id](#input\_ingress\_application\_gateway\_subnet\_id) | The ID of the subnet on which to create an Application Gateway, which in turn will be integrated with the ingress controller of this Kubernetes Cluster. | `string` | `null` | no |
| <a name="input_key_vault_secrets_provider_enabled"></a> [key\_vault\_secrets\_provider\_enabled](#input\_key\_vault\_secrets\_provider\_enabled) | (Optional) Whether to use the Azure Key Vault Provider for Secrets Store CSI Driver in an AKS cluster. For more details: https://docs.microsoft.com/en-us/azure/aks/csi-secrets-store-driver | `bool` | `false` | no |
| <a name="input_kms_enabled"></a> [kms\_enabled](#input\_kms\_enabled) | (Optional) Enable Azure KeyVault Key Management Service. | `bool` | `false` | no |
| <a name="input_kms_key_vault_key_id"></a> [kms\_key\_vault\_key\_id](#input\_kms\_key\_vault\_key\_id) | (Optional) Identifier of Azure Key Vault key. When Azure Key Vault key management service is enabled, this field is required and must be a valid key identifier. | `string` | `null` | no |
| <a name="input_kms_key_vault_network_access"></a> [kms\_key\_vault\_network\_access](#input\_kms\_key\_vault\_network\_access) | (Optional) Network Access of Azure Key Vault. Possible values are: `Private` and `Public`. | `string` | `"Public"` | no |
| <a name="input_kubernetes_version"></a> [kubernetes\_version](#input\_kubernetes\_version) | Specify which Kubernetes release to use. The default used is the latest Kubernetes version available in the region | `string` | `null` | no |
| <a name="input_load_balancer_profile_enabled"></a> [load\_balancer\_profile\_enabled](#input\_load\_balancer\_profile\_enabled) | (Optional) Enable a load\_balancer\_profile block. This can only be used when load\_balancer\_sku is set to `standard`. | `bool` | `false` | no |
| <a name="input_load_balancer_profile_idle_timeout_in_minutes"></a> [load\_balancer\_profile\_idle\_timeout\_in\_minutes](#input\_load\_balancer\_profile\_idle\_timeout\_in\_minutes) | (Optional) Desired outbound flow idle timeout in minutes for the cluster load balancer. Must be between `4` and `120` inclusive. | `number` | `30` | no |
Expand Down
49 changes: 0 additions & 49 deletions examples/named_cluster/disk_encryption_set.tf
Original file line number Diff line number Diff line change
@@ -1,41 +1,3 @@
data "azurerm_client_config" "current" {}

resource "random_string" "key_vault_prefix" {
length = 6
special = false
upper = false
numeric = false
}

data "curl" "public_ip" {
count = var.key_vault_firewall_bypass_ip_cidr == null ? 1 : 0

http_method = "GET"
uri = "https://api.ipify.org?format=json"
}

locals {
# We cannot use coalesce here because it's not short-circuit and public_ip's index will cause error
public_ip = var.key_vault_firewall_bypass_ip_cidr == null ? jsondecode(data.curl.public_ip[0].response).ip : var.key_vault_firewall_bypass_ip_cidr
}

resource "azurerm_key_vault" "des_vault" {
location = local.resource_group.location
name = "${random_string.key_vault_prefix.result}-des-keyvault"
resource_group_name = local.resource_group.name
sku_name = "premium"
tenant_id = data.azurerm_client_config.current.tenant_id
enabled_for_disk_encryption = true
purge_protection_enabled = true
soft_delete_retention_days = 7

network_acls {
bypass = "AzureServices"
default_action = "Deny"
ip_rules = [local.public_ip]
}
}

resource "azurerm_key_vault_key" "des_key" {
key_opts = [
"decrypt",
Expand Down Expand Up @@ -81,14 +43,3 @@ resource "azurerm_key_vault_access_policy" "des" {
"UnwrapKey"
]
}

resource "azurerm_key_vault_access_policy" "current_user" {
key_vault_id = azurerm_key_vault.des_vault.id
object_id = coalesce(var.managed_identity_principal_id, data.azurerm_client_config.current.object_id)
tenant_id = data.azurerm_client_config.current.tenant_id
key_permissions = [
"Get",
"Create",
"Delete",
]
}
48 changes: 48 additions & 0 deletions examples/named_cluster/key_vault.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
data "azurerm_client_config" "current" {}

resource "random_string" "key_vault_prefix" {
length = 6
special = false
upper = false
numeric = false
}

data "curl" "public_ip" {
count = var.key_vault_firewall_bypass_ip_cidr == null ? 1 : 0

http_method = "GET"
uri = "https://api.ipify.org?format=json"
}

locals {
# We cannot use coalesce here because it's not short-circuit and public_ip's index will cause error
public_ip = var.key_vault_firewall_bypass_ip_cidr == null ? jsondecode(data.curl.public_ip[0].response).ip : var.key_vault_firewall_bypass_ip_cidr
}

resource "azurerm_key_vault" "des_vault" {
location = local.resource_group.location
name = "${random_string.key_vault_prefix.result}-des-keyvault"
resource_group_name = local.resource_group.name
sku_name = "premium"
tenant_id = data.azurerm_client_config.current.tenant_id
enabled_for_disk_encryption = true
purge_protection_enabled = true
soft_delete_retention_days = 7

network_acls {
bypass = "AzureServices"
default_action = "Deny"
ip_rules = [local.public_ip]
}
}

resource "azurerm_key_vault_access_policy" "current_user" {
key_vault_id = azurerm_key_vault.des_vault.id
object_id = coalesce(var.managed_identity_principal_id, data.azurerm_client_config.current.object_id)
tenant_id = data.azurerm_client_config.current.tenant_id
key_permissions = [
"Get",
"Create",
"Delete",
]
}
39 changes: 39 additions & 0 deletions examples/named_cluster/kms.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
resource "azurerm_key_vault_key" "kms" {
key_opts = [
"decrypt",
"encrypt",
"sign",
"unwrapKey",
"verify",
"wrapKey",
]
key_type = "RSA"
key_vault_id = azurerm_key_vault.des_vault.id
name = "etcd-encryption"
expiration_date = timeadd("${formatdate("YYYY-MM-DD", timestamp())}T00:00:00Z", "168h")
key_size = 2048

depends_on = [
azurerm_key_vault_access_policy.current_user
]

lifecycle {
ignore_changes = [expiration_date]
}
}

resource "azurerm_key_vault_access_policy" "kms" {
key_vault_id = azurerm_key_vault.des_vault.id
object_id = azurerm_user_assigned_identity.test.principal_id
tenant_id = azurerm_user_assigned_identity.test.tenant_id
key_permissions = [
"Decrypt",
"Encrypt",
]
}

resource "azurerm_role_assignment" "kms" {
principal_id = azurerm_user_assigned_identity.test.principal_id
scope = azurerm_key_vault.des_vault.id
role_definition_name = "Key Vault Contributor"
}
10 changes: 10 additions & 0 deletions examples/named_cluster/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,14 @@ module "aks_cluster_name" {
rbac_aad = true
rbac_aad_managed = true
role_based_access_control_enabled = true

# KMS etcd encryption
kms_enabled = true
kms_key_vault_key_id = azurerm_key_vault_key.kms.id
kms_key_vault_network_access = "Private"

depends_on = [
azurerm_key_vault_access_policy.kms,
azurerm_role_assignment.kms
]
}
12 changes: 12 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,14 @@ resource "azurerm_kubernetes_cluster" "main" {
subnet_id = var.ingress_application_gateway_subnet_id
}
}
dynamic "key_management_service" {
for_each = var.kms_enabled ? ["key_management_service"] : []

content {
key_vault_key_id = var.kms_key_vault_key_id
key_vault_network_access = var.kms_key_vault_network_access
}
}
dynamic "key_vault_secrets_provider" {
for_each = var.key_vault_secrets_provider_enabled ? ["key_vault_secrets_provider"] : []

Expand Down Expand Up @@ -283,6 +291,10 @@ resource "azurerm_kubernetes_cluster" "main" {
condition = var.role_based_access_control_enabled || !var.rbac_aad
error_message = "Enabling Azure Active Directory integration requires that `role_based_access_control_enabled` be set to true."
}
precondition {
condition = !(var.kms_enabled && var.identity_type != "UserAssigned")
error_message = "KMS etcd encryption doesn't work with system-assigned managed identity."
}
}
}

Expand Down
23 changes: 23 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,29 @@ variable "key_vault_secrets_provider_enabled" {
nullable = false
}

variable "kms_enabled" {
type = bool
description = "(Optional) Enable Azure KeyVault Key Management Service."
default = false
nullable = false
}

variable "kms_key_vault_key_id" {
type = string
description = "(Optional) Identifier of Azure Key Vault key. When Azure Key Vault key management service is enabled, this field is required and must be a valid key identifier."
default = null
}

variable "kms_key_vault_network_access" {
type = string
description = "(Optional) Network Access of Azure Key Vault. Possible values are: `Private` and `Public`."
default = "Public"
validation {
condition = contains(["Private", "Public"], var.kms_key_vault_network_access)
error_message = "Possible values are `Private` and `Public`"
}
}

variable "kubernetes_version" {
type = string
description = "Specify which Kubernetes release to use. The default used is the latest Kubernetes version available in the region"
Expand Down
2 changes: 1 addition & 1 deletion versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = ">= 3.27"
version = ">= 3.40"
}
tls = {
source = "hashicorp/tls"
Expand Down

0 comments on commit 5443398

Please sign in to comment.