aws-samples / eks-workshop-v2

Hands-on labs for Amazon EKS
https://www.eksworkshop.com
Apache License 2.0
409 stars 424 forks source link

[Bug]: Incorrect permission boundaries in base.yaml IAM policy causes terraform apply error creating KMS alias #1091

Closed snypher closed 2 weeks ago

snypher commented 2 weeks ago

Installation method

Own AWS account

What happened?

Some permission boundaries (e.i. Resource and StringLike condition) in lab/iam/policies/base.yaml IAM managed policy statements causes KMS’ API CreateAlias error while creating the workshop environment with terraform, as detailed here

Detailed error as below (sensitive information has been replaced):

╷
│ Error: creating KMS Alias (alias/eks/eks-workshop): operation error KMS: CreateAlias, https response error StatusCode: 400, RequestID: 7511818b-09fd-4a3c-a4ea-0681309ccb56, api error AccessDeniedException: User: arn:aws:sts::XXXXXXXXXXXX:assumed-role/eks-workshop-ide-EksWorkshopIdeRole-Ly8RGbBztvHE/i-XXXXXXXXXXXXXXXXX is not authorized to perform: kms:CreateAlias on resource: arn:aws:kms:us-west-2: XXXXXXXXXXXX:alias/eks/eks-workshop because no identity-based policy allows the kms:CreateAlias action
│ 
│   with module.eks.module.kms.aws_kms_alias.this["cluster"],
│   on .terraform/modules/eks.kms/main.tf line 452, in resource "aws_kms_alias" "this":
│  452: resource "aws_kms_alias" "this" {
│ 
╵

The default KMS key eks-workshop is created but the key alias isn’t. Also, the EKS cluster and managed node group are deployed, but further cluster operations where the KMS key is referenced by key alias could fail.

What did you expect to happen?

Default behavior for terraform-aws-eks module is to create a KMS key for cluster encryption. Here is the permalink for the corresponding variable.

Also, the EKS module uses a default computed alias when creating KMS resources through terraform-aws-kms module. The computed alias has a name prefix in the form eks/${var.cluster_name}. Here is the permalink for the corresponding module definition.

Neither of above behaviors are changed by the terraform manifest provided in the workshop, so the expected result should be that any IAM policy statement referencing the KMS resources have the correct name prefix aliases

Below is a patch for base.yaml file

diff --git a/lab/iam/policies/base.yaml b/lab/iam/policies/base.yaml
index 5261d3e0..c962068d 100644
--- a/lab/iam/policies/base.yaml
+++ b/lab/iam/policies/base.yaml
@@ -71,13 +71,13 @@ Statement:
     Resource: ["*"]
     Condition:
       StringLike:
-        kms:RequestAlias: "alias/${Env}*"
+        kms:RequestAlias: "alias/eks/${Env}*"
   - Effect: Allow
     Action:
       - kms:CreateAlias
       - kms:DeleteAlias
     Resource:
-      - !Sub arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/${Env}*
+      - !Sub arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/eks/${Env}*
       - !Sub arn:aws:kms:${AWS::Region}:${AWS::AccountId}:key/*
   - Effect: Allow
     Action:

Same patch can be applied to the final unified YAML eks-workshop-vscode-cfn.yaml

--- eks-workshop-vscode-cfn.yaml        2024-08-31 05:15:24.000000000 +0000
+++ eks-workshop-ide-cfn/eks-workshop-vscode-cfn.yaml   2024-09-11 18:05:03.512812826 +0000
@@ -495,13 +495,13 @@
             Resource: ["*"]
             Condition:
               StringLike:
-                kms:RequestAlias: "alias/eks-workshop*"
+                kms:RequestAlias: "alias/eks/eks-workshop*"
           - Effect: Allow
             Action:
               - kms:CreateAlias
               - kms:DeleteAlias
             Resource:
-              - !Sub arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/eks-workshop*
+              - !Sub arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/eks/eks-workshop*
               - !Sub arn:aws:kms:${AWS::Region}:${AWS::AccountId}:key/*
           - Effect: Allow
             Action:

How can we reproduce it?

Following the steps detailed in the public EKS workshop site as below:

  1. Deploy the AWS CloudFormation stack to create the VSCode IDE environment (a.k.a. eks-workshop-ide). Quick-create link: launch
  2. Follow the steps to create the workshop environment with terraform, as detailed here

Anything else we need to know?

Take into account that terraform-aws-kms module adds up the name prefix alias/ to any computed aliases received from downstream modules. So, the resulting name property for the KMS key alias will be as below:

alias/eks/<any_provided_value>

We can confirm this by looking into terraform plan -var="cluster_name=$EKS_CLUSTER_NAME" before the apply step

# module.eks.module.kms.aws_kms_alias.this["cluster"] will be created
  + resource "aws_kms_alias" "this" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + name           = "alias/eks/eks-workshop"
      + name_prefix    = (known after apply)
      + target_key_arn = (known after apply)
      + target_key_id  = (known after apply)
    }

EKS version

Same versions as deployed by default in the public EKS workshop

EKS cluster version = 1.30
“hashicorp/aws” >= 4.67.0
“terraform-aws-modules/eks/aws“ ~> 20.0 
niallthomson commented 2 weeks ago

@snypher thanks for the very detailed report. It looks like we'll need to add an additional condition to the IAM policy since the KMS alias in other parts of the workshop use the existing pattern.