diff --git a/content/blog/amazon-ebs-csi-driver-terraform/index.md b/content/blog/amazon-ebs-csi-driver-terraform/index.md new file mode 100644 index 00000000..75a2497e --- /dev/null +++ b/content/blog/amazon-ebs-csi-driver-terraform/index.md @@ -0,0 +1,92 @@ +--- +title: "Amazon EBS CSI driver with terraform" +date: "2024-04-07T15:20:23-04:00" +draft: false +comments: true +toc: false +author: "Dave Gallant" +tags: ['aws', 'eks', 'ebs', 'aws-ebs-csi-driver', 'oidc'] +--- + +I recently configured the Amazon EBS CSI driver and found the setup with terraform to be more effort than expected. I wanted to avoid third-party modules and keep it as simple as possible, while remaining least privilege. + + + +The [Amazon EBS CSI driver docs](https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html) mention that the following are needed: +- an existing EKS cluster +- IAM role (that allows communication to the EC2 API) +- EKS add-on (aws-ebs-csi-driver) +- OIDC provider + +This sounded simple enough but I was unable to find a "grab-and-go" terraform example that followed the recommendations in the docs. I saw some suggestions about attaching an `AmazonEBSCSIDriverPolicy` policy to the node groups but did not think this was the best idea since this would allow many pods to potentially have access to the EC2 API. + +After a few minutes of prompting an LLM, I was unimpressed with the results. I began to piece together the config myself, and after some trial and error, this is the terraform that I came up with: + +```hcl + +# TLS needed for the thumbprint +provider "tls" {} + +data "tls_certificate" "oidc" { + url = aws_eks_cluster.main.identity[0].oidc[0].issuer +} + +# EKS addon +resource "aws_eks_addon" "ebs_csi_driver" { + cluster_name = aws_eks_cluster.main.name + addon_name = "aws-ebs-csi-driver" + addon_version = "v1.29.1-eksbuild.1" + service_account_role_arn = aws_iam_role.ebs_csi_driver.arn +} + +# AWS Identity and Access Management (IAM) OpenID Connect (OIDC) provider + +resource "aws_iam_openid_connect_provider" "eks" { + url = aws_eks_cluster.main.identity.0.oidc.0.issuer + client_id_list = ["sts.amazonaws.com"] + thumbprint_list = [data.tls_certificate.oidc.certificates[0].sha1_fingerprint] +} + +# IAM +resource "aws_iam_role" "ebs_csi_driver" { + name = "${var.environment_name}-ebs-csi-driver" + assume_role_policy = data.aws_iam_policy_document.ebs_csi_driver_assume_role.json +} + +data "aws_iam_policy_document" "ebs_csi_driver_assume_role" { + statement { + effect = "Allow" + + principals { + type = "Federated" + identifiers = [aws_iam_openid_connect_provider.eks.arn] + } + + actions = [ + "sts:AssumeRoleWithWebIdentity", + ] + + condition { + test = "StringEquals" + variable = "${aws_iam_openid_connect_provider.eks.url}:aud" + values = ["sts.amazonaws.com"] + } + + condition { + test = "StringEquals" + variable = "${aws_iam_openid_connect_provider.eks.url}:sub" + values = ["system:serviceaccount:kube-system:ebs-csi-controller-sa"] + } + + } +} + +resource "aws_iam_role_policy_attachment" "AmazonEBSCSIDriverPolicy" { + policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy" + role = aws_iam_role.ebs_csi_driver.name +} +``` + +The above configuration follows the docs, binding an IAM role to the service account _kube-system/ebs-csi-controller-sa_ using an OpenID connect provider. + +After applying the changes above, I deployed [the sample application](https://docs.aws.amazon.com/eks/latest/userguide/ebs-sample-app.html) and noticed that the persistent volume claims were bound to EBS volumes.