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

feat: Implement support for KMS arguments #288

Merged
merged 10 commits into from
Jan 29, 2023
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
lonegunmanb marked this conversation as resolved.
Show resolved Hide resolved
- 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`. If not set, defaults to type `Public`. | `string` | `null` | 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",
]
}
29 changes: 29 additions & 0 deletions examples/named_cluster/kms.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
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
]
}
mkilchhofer marked this conversation as resolved.
Show resolved Hide resolved

resource "azurerm_key_vault_access_policy" "kms" {
key_vault_id = azurerm_key_vault.des_vault.id
object_id = azurerm_user_assigned_identity.test.id
mkilchhofer marked this conversation as resolved.
Show resolved Hide resolved
tenant_id = azurerm_user_assigned_identity.test.tenant_id
key_permissions = [
"Decrypt",
"Encrypt",
]
}
mkilchhofer marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 4 additions & 0 deletions examples/named_cluster/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,8 @@ module "aks_cluster_name" {
rbac_aad = true
rbac_aad_managed = true
role_based_access_control_enabled = true

Copy link
Member

Choose a reason for hiding this comment

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

We need the following line below line 31:

service_endpoints                              = ["Microsoft.KeyVault"]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Service endpoint is not needed (at least in our scenario). I think its only needed if some part inside the VNET wants to access the keyvault.

# KMS etcd encryption
kms_enabled = true
kms_key_vault_key_id = azurerm_key_vault_key.kms.id
}
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"] : []
mkilchhofer marked this conversation as resolved.
Show resolved Hide resolved

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
19 changes: 19 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,25 @@ variable "key_vault_secrets_provider_enabled" {
nullable = false
}

variable "kms_enabled" {
type = bool
description = "(Optional) Enable Azure KeyVault Key Management Service."
default = false
mkilchhofer marked this conversation as resolved.
Show resolved Hide resolved
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`. If not set, defaults to type `Public`."
default = null
mkilchhofer marked this conversation as resolved.
Show resolved Hide resolved
}

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