From 7644952131a466ca22ba5b3e62cd988e01eff716 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Wed, 2 Mar 2022 12:29:35 -0500 Subject: [PATCH] feat: Add additional IAM policy to allow cluster role to use KMS key provided for cluster encryption (#1915) --- README.md | 3 ++ examples/eks_managed_node_group/main.tf | 8 ++++++ main.tf | 38 +++++++++++++++++++++++-- variables.tf | 6 ++++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 62ccb3d..1a78ba0 100644 --- a/README.md +++ b/README.md @@ -830,8 +830,10 @@ Full contributing [guidelines are covered here](https://github.com/terraform-aws | [aws_eks_cluster.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster) | resource | | [aws_eks_identity_provider_config.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_identity_provider_config) | resource | | [aws_iam_openid_connect_provider.oidc_provider](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_openid_connect_provider) | resource | +| [aws_iam_policy.cluster_encryption](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.cni_ipv6_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachment.cluster_encryption](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_security_group.cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | | [aws_security_group.node](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | @@ -846,6 +848,7 @@ Full contributing [guidelines are covered here](https://github.com/terraform-aws | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [attach\_cluster\_encryption\_policy](#input\_attach\_cluster\_encryption\_policy) | Indicates whether or not to attach an additional policy for the cluster IAM role to utilize the encryption key provided | `bool` | `true` | no | | [cloudwatch\_log\_group\_kms\_key\_id](#input\_cloudwatch\_log\_group\_kms\_key\_id) | If a KMS Key ARN is set, this key will be used to encrypt the corresponding log group. Please be sure that the KMS Key has an appropriate key policy (https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/encrypt-log-data-kms.html) | `string` | `null` | no | | [cloudwatch\_log\_group\_retention\_in\_days](#input\_cloudwatch\_log\_group\_retention\_in\_days) | Number of days to retain log events. Default retention - 90 days | `number` | `90` | no | | [cluster\_additional\_security\_group\_ids](#input\_cluster\_additional\_security\_group\_ids) | List of additional, externally created security group IDs to attach to the cluster control plane | `list(string)` | `[]` | no | diff --git a/examples/eks_managed_node_group/main.tf b/examples/eks_managed_node_group/main.tf index 45251ff..639a56f 100644 --- a/examples/eks_managed_node_group/main.tf +++ b/examples/eks_managed_node_group/main.tf @@ -31,6 +31,14 @@ module "eks" { # IPV6 cluster_ip_family = "ipv6" + # We are using the IRSA created below for permissions + # However, we have to deploy with the policy attached FIRST (when creating a fresh cluster) + # and then turn this off after the cluster/node group is created. Without this initial policy, + # the VPC CNI fails to assign IPs and nodes cannot join the cluster + # See https://github.com/aws/containers-roadmap/issues/1666 for more context + # TODO - remove this policy once AWS releases a managed version similar to AmazonEKS_CNI_Policy (IPv4) + create_cni_ipv6_iam_policy = true + cluster_addons = { coredns = { resolve_conflicts = "OVERWRITE" diff --git a/main.tf b/main.tf index 918f11f..450ab6c 100644 --- a/main.tf +++ b/main.tf @@ -30,9 +30,9 @@ resource "aws_eks_cluster" "this" { content { provider { - key_arn = encryption_config.value["provider_key_arn"] + key_arn = encryption_config.value.provider_key_arn } - resources = encryption_config.value["resources"] + resources = encryption_config.value.resources } } @@ -218,6 +218,40 @@ resource "aws_iam_role_policy_attachment" "this" { role = aws_iam_role.this[0].name } +# Using separate attachment due to `The "for_each" value depends on resource attributes that cannot be determined until apply` +resource "aws_iam_role_policy_attachment" "cluster_encryption" { + count = var.create && var.attach_cluster_encryption_policy && length(var.cluster_encryption_config) > 0 ? 1 : 0 + + policy_arn = aws_iam_policy.cluster_encryption[0].arn + role = aws_iam_role.this[0].name +} + +resource "aws_iam_policy" "cluster_encryption" { + count = var.create && var.attach_cluster_encryption_policy && length(var.cluster_encryption_config) > 0 ? 1 : 0 + + name_prefix = "${local.iam_role_name}-ClusterEncryption-" + description = "Cluster encryption policy to allow cluster role to utilize CMK provided" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = [ + "kms:Encrypt", + "kms:Decrypt", + "kms:ListGrants", + "kms:DescribeKey", + ] + Effect = "Allow" + # TODO - does cluster_encryption_config need to be a list?! + Resource = [for config in var.cluster_encryption_config : config.provider_key_arn] + }, + ] + }) + + tags = var.tags +} + ################################################################################ # EKS Addons ################################################################################ diff --git a/variables.tf b/variables.tf index 8c221a3..2e479ac 100644 --- a/variables.tf +++ b/variables.tf @@ -89,6 +89,12 @@ variable "cluster_encryption_config" { default = [] } +variable "attach_cluster_encryption_policy" { + description = "Indicates whether or not to attach an additional policy for the cluster IAM role to utilize the encryption key provided" + type = bool + default = true +} + variable "cluster_tags" { description = "A map of additional tags to add to the cluster" type = map(string)