From 21fb8d9ce7c88cc782789a81db720cc9b320e7a8 Mon Sep 17 00:00:00 2001 From: Joachim Hill-Grannec Date: Sat, 2 Mar 2024 19:19:42 -0600 Subject: [PATCH] feat: Add support for Mountpoint S3 CSI driver to EKS IRSA (#459) Co-authored-by: Bryant Biggs --- .github/workflows/pre-commit.yml | 16 +++++++ .pre-commit-config.yaml | 2 +- .../README.md | 1 + .../iam-role-for-service-accounts-eks/main.tf | 18 ++++++++ .../README.md | 11 ++++- .../policies.tf | 44 +++++++++++++++++++ .../variables.tf | 19 ++++++++ .../iam-role-for-service-accounts-eks/main.tf | 3 ++ 8 files changed, 111 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index cb826713..e98f25e5 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -32,6 +32,14 @@ jobs: matrix: directory: ${{ fromJson(needs.collectInputs.outputs.directories) }} steps: + # https://github.com/orgs/community/discussions/25678#discussioncomment-5242449 + - name: Delete huge unnecessary tools folder + run: | + rm -rf /opt/hostedtoolcache/CodeQL + rm -rf /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk + rm -rf /opt/hostedtoolcache/Ruby + rm -rf /opt/hostedtoolcache/go + - name: Checkout uses: actions/checkout@v3 @@ -64,6 +72,14 @@ jobs: runs-on: ubuntu-latest needs: collectInputs steps: + # https://github.com/orgs/community/discussions/25678#discussioncomment-5242449 + - name: Delete huge unnecessary tools folder + run: | + rm -rf /opt/hostedtoolcache/CodeQL + rm -rf /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk + rm -rf /opt/hostedtoolcache/Ruby + rm -rf /opt/hostedtoolcache/go + - name: Checkout uses: actions/checkout@v3 with: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 06eef70c..9de96089 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.85.0 + rev: v1.88.0 hooks: - id: terraform_fmt - id: terraform_wrapper_module_for_each diff --git a/examples/iam-role-for-service-accounts-eks/README.md b/examples/iam-role-for-service-accounts-eks/README.md index 73bc0ea7..0224fb43 100644 --- a/examples/iam-role-for-service-accounts-eks/README.md +++ b/examples/iam-role-for-service-accounts-eks/README.md @@ -52,6 +52,7 @@ Run `terraform destroy` when you don't need these resources. | [karpenter\_controller\_irsa\_role](#module\_karpenter\_controller\_irsa\_role) | ../../modules/iam-role-for-service-accounts-eks | n/a | | [load\_balancer\_controller\_irsa\_role](#module\_load\_balancer\_controller\_irsa\_role) | ../../modules/iam-role-for-service-accounts-eks | n/a | | [load\_balancer\_controller\_targetgroup\_binding\_only\_irsa\_role](#module\_load\_balancer\_controller\_targetgroup\_binding\_only\_irsa\_role) | ../../modules/iam-role-for-service-accounts-eks | n/a | +| [mountpoint\_s3\_csi\_irsa\_role](#module\_mountpoint\_s3\_csi\_irsa\_role) | ../../modules/iam-role-for-service-accounts-eks | n/a | | [node\_termination\_handler\_irsa\_role](#module\_node\_termination\_handler\_irsa\_role) | ../../modules/iam-role-for-service-accounts-eks | n/a | | [velero\_irsa\_role](#module\_velero\_irsa\_role) | ../../modules/iam-role-for-service-accounts-eks | n/a | | [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | diff --git a/examples/iam-role-for-service-accounts-eks/main.tf b/examples/iam-role-for-service-accounts-eks/main.tf index 649a9ed1..454d8f13 100644 --- a/examples/iam-role-for-service-accounts-eks/main.tf +++ b/examples/iam-role-for-service-accounts-eks/main.tf @@ -136,6 +136,24 @@ module "efs_csi_irsa_role" { tags = local.tags } +module "mountpoint_s3_csi_irsa_role" { + source = "../../modules/iam-role-for-service-accounts-eks" + + role_name = "mountpoint-s3-csi" + attach_mountpoint_s3_csi_policy = true + mountpoint_s3_csi_bucket_arns = ["arn:aws:s3:::mountpoint-s3-csi-bucket"] + mountpoint_s3_csi_path_arns = ["arn:aws:s3:::mountpoint-s3-csi-bucket/example/*"] + + oidc_providers = { + ex = { + provider_arn = module.eks.oidc_provider_arn + namespace_service_accounts = ["kube-system:s3-csi-driver-sa"] + } + } + + tags = local.tags +} + module "external_dns_irsa_role" { source = "../../modules/iam-role-for-service-accounts-eks" diff --git a/modules/iam-role-for-service-accounts-eks/README.md b/modules/iam-role-for-service-accounts-eks/README.md index a2d04d33..a59b2277 100644 --- a/modules/iam-role-for-service-accounts-eks/README.md +++ b/modules/iam-role-for-service-accounts-eks/README.md @@ -1,6 +1,7 @@ # IAM Role for Service Accounts in EKS Creates an IAM role which can be assumed by AWS EKS `ServiceAccount`s with optional policies for commonly used controllers/custom resources within EKS. The optional policies supported include: + - [Cert-Manager](https://cert-manager.io/docs/configuration/acme/dns01/route53/#set-up-an-iam-role) - [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md) - [EBS CSI Driver](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/blob/master/docs/example-iam-policy.json) @@ -85,10 +86,10 @@ module "karpenter_irsa_role" { module "eks" { source = "terraform-aws-modules/eks/aws" - version = "~> 18.6" + version = "~> 20.4" cluster_name = "my-cluster" - cluster_version = "1.21" + cluster_version = "1.29" vpc_id = module.vpc.vpc_id subnet_ids = module.vpc.private_subnets @@ -135,6 +136,7 @@ No modules. | [aws_iam_policy.karpenter_controller](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.load_balancer_controller](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.load_balancer_controller_targetgroup_only](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.mountpoint_s3_csi](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.node_termination_handler](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.velero](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_policy.vpc_cni](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | @@ -154,6 +156,7 @@ No modules. | [aws_iam_role_policy_attachment.karpenter_controller](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.load_balancer_controller](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.load_balancer_controller_targetgroup_only](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.mountpoint_s3_csi](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.node_termination_handler](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_iam_role_policy_attachment.velero](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | @@ -173,6 +176,7 @@ No modules. | [aws_iam_policy_document.karpenter_controller](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.load_balancer_controller](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.load_balancer_controller_targetgroup_only](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.mountpoint_s3_csi](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.node_termination_handler](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.velero](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | @@ -202,6 +206,7 @@ No modules. | [attach\_karpenter\_controller\_policy](#input\_attach\_karpenter\_controller\_policy) | Determines whether to attach the Karpenter Controller policy to the role | `bool` | `false` | no | | [attach\_load\_balancer\_controller\_policy](#input\_attach\_load\_balancer\_controller\_policy) | Determines whether to attach the Load Balancer Controller policy to the role | `bool` | `false` | no | | [attach\_load\_balancer\_controller\_targetgroup\_binding\_only\_policy](#input\_attach\_load\_balancer\_controller\_targetgroup\_binding\_only\_policy) | Determines whether to attach the Load Balancer Controller policy for the TargetGroupBinding only | `bool` | `false` | no | +| [attach\_mountpoint\_s3\_csi\_policy](#input\_attach\_mountpoint\_s3\_csi\_policy) | Determines whether to attach the Mountpoint S3 CSI IAM policy to the role | `bool` | `false` | no | | [attach\_node\_termination\_handler\_policy](#input\_attach\_node\_termination\_handler\_policy) | Determines whether to attach the Node Termination Handler policy to the role | `bool` | `false` | no | | [attach\_velero\_policy](#input\_attach\_velero\_policy) | Determines whether to attach the Velero IAM policy to the role | `bool` | `false` | no | | [attach\_vpc\_cni\_policy](#input\_attach\_vpc\_cni\_policy) | Determines whether to attach the VPC CNI IAM policy to the role | `bool` | `false` | no | @@ -227,6 +232,8 @@ No modules. | [karpenter\_tag\_key](#input\_karpenter\_tag\_key) | Tag key (`{key = value}`) applied to resources launched by Karpenter through the Karpenter provisioner | `string` | `"karpenter.sh/discovery"` | no | | [load\_balancer\_controller\_targetgroup\_arns](#input\_load\_balancer\_controller\_targetgroup\_arns) | List of Target groups ARNs using Load Balancer Controller | `list(string)` |
[
"arn:aws:elasticloadbalancing:*:*:targetgroup/*/*"
]
| no | | [max\_session\_duration](#input\_max\_session\_duration) | Maximum CLI/API session duration in seconds between 3600 and 43200 | `number` | `null` | no | +| [mountpoint\_s3\_csi\_bucket\_arns](#input\_mountpoint\_s3\_csi\_bucket\_arns) | S3 bucket ARNs to allow Mountpoint S3 CSI to list buckets | `list(string)` | `[]` | no | +| [mountpoint\_s3\_csi\_path\_arns](#input\_mountpoint\_s3\_csi\_path\_arns) | S3 path ARNs to allow Mountpoint S3 CSI driver to manage items at the provided path(s). This is required if `attach_mountpoint_s3_csi_policy = true` | `list(string)` | `[]` | no | | [node\_termination\_handler\_sqs\_queue\_arns](#input\_node\_termination\_handler\_sqs\_queue\_arns) | List of SQS ARNs that contain node termination events | `list(string)` |
[
"*"
]
| no | | [oidc\_providers](#input\_oidc\_providers) | Map of OIDC providers where each provider map should contain the `provider_arn` and `namespace_service_accounts` | `any` | `{}` | no | | [policy\_name\_prefix](#input\_policy\_name\_prefix) | IAM policy name prefix | `string` | `"AmazonEKS_"` | no | diff --git a/modules/iam-role-for-service-accounts-eks/policies.tf b/modules/iam-role-for-service-accounts-eks/policies.tf index 7ac1a38b..8ec3dcee 100644 --- a/modules/iam-role-for-service-accounts-eks/policies.tf +++ b/modules/iam-role-for-service-accounts-eks/policies.tf @@ -422,6 +422,50 @@ resource "aws_iam_role_policy_attachment" "efs_csi" { policy_arn = aws_iam_policy.efs_csi[0].arn } +################################################################################ +# Mountpoint S3 CSI Driver Policy +################################################################################ + +#https://github.com/awslabs/mountpoint-s3/blob/main/doc/CONFIGURATION.md#iam-permissions +data "aws_iam_policy_document" "mountpoint_s3_csi" { + count = var.create_role && var.attach_mountpoint_s3_csi_policy ? 1 : 0 + + statement { + sid = "MountpointFullBucketAccess" + actions = ["s3:ListBucket"] + resources = coalescelist(var.mountpoint_s3_csi_bucket_arns, ["arn:${local.partition}:s3:::*"]) + } + + statement { + sid = "MountpointFullObjectAccess" + actions = [ + "s3:GetObject", + "s3:PutObject", + "s3:AbortMultipartUpload", + "s3:DeleteObject" + ] + resources = var.mountpoint_s3_csi_path_arns + } +} + +resource "aws_iam_policy" "mountpoint_s3_csi" { + count = var.create_role && var.attach_mountpoint_s3_csi_policy ? 1 : 0 + + name_prefix = "${var.policy_name_prefix}Mountpoint_S3_CSI-" + path = var.role_path + description = "Mountpoint S3 CSI driver policy to allow management of S3" + policy = data.aws_iam_policy_document.mountpoint_s3_csi[0].json + + tags = var.tags +} + +resource "aws_iam_role_policy_attachment" "mountpoint_s3_csi" { + count = var.create_role && var.attach_mountpoint_s3_csi_policy ? 1 : 0 + + role = aws_iam_role.this[0].name + policy_arn = aws_iam_policy.mountpoint_s3_csi[0].arn +} + ################################################################################ # External DNS Policy ################################################################################ diff --git a/modules/iam-role-for-service-accounts-eks/variables.tf b/modules/iam-role-for-service-accounts-eks/variables.tf index 5eb66e9b..dc73fd33 100644 --- a/modules/iam-role-for-service-accounts-eks/variables.tf +++ b/modules/iam-role-for-service-accounts-eks/variables.tf @@ -145,6 +145,25 @@ variable "attach_efs_csi_policy" { default = false } +# S3 CSI +variable "attach_mountpoint_s3_csi_policy" { + description = "Determines whether to attach the Mountpoint S3 CSI IAM policy to the role" + type = bool + default = false +} + +variable "mountpoint_s3_csi_bucket_arns" { + description = "S3 bucket ARNs to allow Mountpoint S3 CSI to list buckets" + type = list(string) + default = [] +} + +variable "mountpoint_s3_csi_path_arns" { + description = "S3 path ARNs to allow Mountpoint S3 CSI driver to manage items at the provided path(s). This is required if `attach_mountpoint_s3_csi_policy = true`" + type = list(string) + default = [] +} + # External DNS variable "attach_external_dns_policy" { description = "Determines whether to attach the External DNS IAM policy to the role" diff --git a/wrappers/iam-role-for-service-accounts-eks/main.tf b/wrappers/iam-role-for-service-accounts-eks/main.tf index 5f9a468d..291e570e 100644 --- a/wrappers/iam-role-for-service-accounts-eks/main.tf +++ b/wrappers/iam-role-for-service-accounts-eks/main.tf @@ -21,6 +21,7 @@ module "wrapper" { attach_karpenter_controller_policy = try(each.value.attach_karpenter_controller_policy, var.defaults.attach_karpenter_controller_policy, false) attach_load_balancer_controller_policy = try(each.value.attach_load_balancer_controller_policy, var.defaults.attach_load_balancer_controller_policy, false) attach_load_balancer_controller_targetgroup_binding_only_policy = try(each.value.attach_load_balancer_controller_targetgroup_binding_only_policy, var.defaults.attach_load_balancer_controller_targetgroup_binding_only_policy, false) + attach_mountpoint_s3_csi_policy = try(each.value.attach_mountpoint_s3_csi_policy, var.defaults.attach_mountpoint_s3_csi_policy, false) attach_node_termination_handler_policy = try(each.value.attach_node_termination_handler_policy, var.defaults.attach_node_termination_handler_policy, false) attach_velero_policy = try(each.value.attach_velero_policy, var.defaults.attach_velero_policy, false) attach_vpc_cni_policy = try(each.value.attach_vpc_cni_policy, var.defaults.attach_vpc_cni_policy, false) @@ -46,6 +47,8 @@ module "wrapper" { karpenter_tag_key = try(each.value.karpenter_tag_key, var.defaults.karpenter_tag_key, "karpenter.sh/discovery") load_balancer_controller_targetgroup_arns = try(each.value.load_balancer_controller_targetgroup_arns, var.defaults.load_balancer_controller_targetgroup_arns, ["arn:aws:elasticloadbalancing:*:*:targetgroup/*/*"]) max_session_duration = try(each.value.max_session_duration, var.defaults.max_session_duration, null) + mountpoint_s3_csi_bucket_arns = try(each.value.mountpoint_s3_csi_bucket_arns, var.defaults.mountpoint_s3_csi_bucket_arns, []) + mountpoint_s3_csi_path_arns = try(each.value.mountpoint_s3_csi_path_arns, var.defaults.mountpoint_s3_csi_path_arns, []) node_termination_handler_sqs_queue_arns = try(each.value.node_termination_handler_sqs_queue_arns, var.defaults.node_termination_handler_sqs_queue_arns, ["*"]) oidc_providers = try(each.value.oidc_providers, var.defaults.oidc_providers, {}) policy_name_prefix = try(each.value.policy_name_prefix, var.defaults.policy_name_prefix, "AmazonEKS_")