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

Missing IAM role path in KMS Key Policy #1077

Closed
1 task done
mkkatica opened this issue Oct 24, 2022 · 3 comments · Fixed by #979
Closed
1 task done

Missing IAM role path in KMS Key Policy #1077

mkkatica opened this issue Oct 24, 2022 · 3 comments · Fixed by #979
Labels
bug Something isn't working

Comments

@mkkatica
Copy link
Contributor

Description

When using var.iam_role_path, that path is not respected in the KMS key policy granting that role the required permissions.

  • ✋ I have searched the open/closed issues and my issue is not listed.

⚠️ Note

Before you submit an issue, please perform the following first:

  1. Remove the local .terraform directory (! ONLY if state is stored remotely, which hopefully you are following that best practice!): rm -rf .terraform/
  2. Re-initialize the project root to pull down modules: terraform init
  3. Re-attempt your terraform plan or apply and check if the issue still persists

Versions

  • Module version: 4.13.1 (latest from main)

  • Terraform version: v1.2.9

  • Provider version(s):

+ provider registry.terraform.io/gavinbunney/kubectl v1.14.0
+ provider registry.terraform.io/hashicorp/aws v4.36.1
+ provider registry.terraform.io/hashicorp/cloudinit v2.2.0
+ provider registry.terraform.io/hashicorp/external v2.2.2
+ provider registry.terraform.io/hashicorp/helm v2.7.1
+ provider registry.terraform.io/hashicorp/kubernetes v2.14.0
+ provider registry.terraform.io/hashicorp/local v2.2.3
+ provider registry.terraform.io/hashicorp/null v3.1.1
+ provider registry.terraform.io/hashicorp/random v3.4.3
+ provider registry.terraform.io/hashicorp/time v0.9.0
+ provider registry.terraform.io/hashicorp/tls v3.4.0
+ provider registry.terraform.io/terraform-aws-modules/http v2.4.1

Reproduction Code

Steps to reproduce the behavior:

  1. set var.iam_role_path to an arbitrary value, for example "my_security_path"
  2. run terraform plan.

Expected behaviour

The ARN of the EKS cluster role used in the KMS key policy should include the path specified in var.iam_role_path.

Actual behaviour

The ARN of the EKS cluster role in the KMS key policy does not include the path. Therefore, the KMS key creation fails with "invalid principal" errors.

Terminal Output Screenshot(s)

This example uses a module that wraps the eks_blueprints module (module.platform). The module uses the following to invoke the eks_blueprints:

module "eks_blueprints" {
  source = "github.com/aws-ia/terraform-aws-eks-blueprints"

  cluster_name    = local.name

  # EKS Cluster VPC and Subnet mandatory config
  vpc_id             = data.aws_vpc.vpc.id
  private_subnet_ids = local.eks_deployment_subnet_ids

  cluster_endpoint_public_access  = false
  cluster_endpoint_private_access = true

  # EKS CONTROL PLANE VARIABLES
  cluster_version = local.cluster_version

  cluster_kms_key_additional_admin_arns = [local.aws_sso_admin_role_arn_pathed, local.aws_sso_appdev_role_arn_pathed]

  cluster_additional_security_group_ids = [aws_security_group.node_to_proxy_sg.id]

  create_cluster_security_group = false
  create_node_security_group = false

  iam_role_permissions_boundary = "arn:aws:iam::aws:policy/PowerUserAccess"
  iam_role_path = "/github-deployed/" <----

  worker_additional_security_group_ids = [aws_security_group.node_security_group.id]

  map_roles = [
    {
      rolearn  = local.aws_sso_admin_role_arn
      username = "admin-user"
      groups   = ["system:masters"]
    },
    {
      rolearn  = local.aws_sso_appdev_role_arn
      username = "admin-user"
      groups   = ["system:masters"]
    },
    {
      rolearn  = "arn:${local.aws_partition}:iam::${local.aws_account_number}:role/${module.iam_assumable_role.iam_role_name}"
      username = "system:node:{{EC2PrivateDNSName}}"
      groups   = ["system:bootstrappers", "system:nodes"]
    },
    {
      rolearn  = module.iam_assumable_role.iam_role_arn
      username = "system:node:{{EC2PrivateDNSName}}"
      groups   = ["system:bootstrappers", "system:nodes"]
    }
  ]

  tags = local.tags
}

Console Output:

➜ tf plan -target='module.platform.module.eks_blueprints.module.kms'
module.platform.module.eks_blueprints.data.aws_partition.current: Reading...
module.platform.module.eks_blueprints.data.aws_region.current: Reading...
module.platform.data.aws_partition.current: Reading...
module.platform.data.aws_caller_identity.current: Reading...
module.platform.module.eks_blueprints.data.aws_caller_identity.current: Reading...
module.platform.data.aws_partition.current: Read complete after 0s [id=aws]
module.platform.module.eks_blueprints.data.aws_partition.current: Read complete after 0s [id=aws]
module.platform.module.eks_blueprints.data.aws_region.current: Read complete after 0s [id=us-east-1]
module.platform.module.eks_blueprints.data.aws_caller_identity.current: Read complete after 1s [id=607961205183]
module.platform.module.eks_blueprints.data.aws_iam_session_context.current: Reading...
module.platform.data.aws_caller_identity.current: Read complete after 1s [id=607961205183]
module.platform.module.eks_blueprints.data.aws_iam_session_context.current: Read complete after 2s 
module.platform.module.eks_blueprints.data.aws_iam_policy_document.eks_key: Reading...
module.platform.module.eks_blueprints.data.aws_iam_policy_document.eks_key: Read complete after 0s [id=1140959782]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.platform.module.eks_blueprints.module.kms[0].aws_kms_alias.this will be created
  + resource "aws_kms_alias" "this" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + name           = "alias/sandbox2"
      + name_prefix    = (known after apply)
      + target_key_arn = (known after apply)
      + target_key_id  = (known after apply)
    }

  # module.platform.module.eks_blueprints.module.kms[0].aws_kms_key.this will be created
  + resource "aws_kms_key" "this" {
      + arn                                = (known after apply)
      + bypass_policy_lockout_safety_check = false
      + customer_master_key_spec           = "SYMMETRIC_DEFAULT"
      + deletion_window_in_days            = 30
      + description                        = "sandbox2 EKS cluster secret encryption key"
      + enable_key_rotation                = true
      + id                                 = (known after apply)
      + is_enabled                         = true
      + key_id                             = (known after apply)
      + key_usage                          = "ENCRYPT_DECRYPT"
      + multi_region                       = (known after apply)
      + policy                             = jsonencode(
            {
              + Statement = [
...
                  + {
                      + Action    = [
                          + "kms:ReEncrypt*",
                          + "kms:GenerateDataKey*",
                          + "kms:Encrypt",
                          + "kms:DescribeKey",
                          + "kms:Decrypt",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + AWS = "arn:aws:iam::xxxxxx:role/sandbox2-cluster-role" <--- Should be "arn:aws:iam::xxxxxx:role/github-deployed/sandbox2-cluster-role"
                        }
                      + Resource  = "*"
                      + Sid       = "Allow use of the key"
                    },
                  + {
                      + Action    = [
                          + "kms:RevokeGrant",
                          + "kms:ListGrants",
                          + "kms:CreateGrant",
                        ]
                      + Condition = {
                          + Bool = {
                              + "kms:GrantIsForAWSResource" = "true"
                            }
                        }
                      + Effect    = "Allow"
                      + Principal = {
                          + AWS = "arn:aws:iam::xxxxxx:role/sandbox2-cluster-role" <--- Should be "arn:aws:iam::xxxxxx:role/github-deployed/sandbox2-cluster-role"
                        }
                      + Resource  = "*"
                      + Sid       = "Allow attachment of persistent resources"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Additional context

This is helpful for any organizations implementing IAM self service and use the IAM role path as a guardrail to prevent privilege escalation.

@bryantbiggs
Copy link
Contributor

this is not recommended because the aws-iam-authenticator does not respect role paths kubernetes-sigs/aws-iam-authenticator#268

@mkkatica
Copy link
Contributor Author

Recommended or not, the path here should be respected if passed. KMS does support the path, and the authenticator does work (if you strip the path out when passing it).

@mkkatica
Copy link
Contributor Author

See comment here.

@bryantbiggs bryantbiggs added the bug Something isn't working label Oct 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants