diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index fc21bc9c25..b73ed98715 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.92.1
+ rev: v1.92.2
hooks:
- id: terraform_fmt
- id: terraform_docs
diff --git a/examples/karpenter/main.tf b/examples/karpenter/main.tf
index 14435b6354..72ceff275a 100644
--- a/examples/karpenter/main.tf
+++ b/examples/karpenter/main.tf
@@ -126,6 +126,8 @@ module "karpenter" {
cluster_name = module.eks.cluster_name
+ enable_v1_permissions = true
+
enable_pod_identity = true
create_pod_identity_association = true
@@ -155,7 +157,7 @@ resource "helm_release" "karpenter" {
repository_username = data.aws_ecrpublic_authorization_token.token.user_name
repository_password = data.aws_ecrpublic_authorization_token.token.password
chart = "karpenter"
- version = "0.37.0"
+ version = "1.0.0"
wait = false
values = [
diff --git a/modules/karpenter/README.md b/modules/karpenter/README.md
index 1bcf514f47..6810d0fa0c 100644
--- a/modules/karpenter/README.md
+++ b/modules/karpenter/README.md
@@ -121,6 +121,8 @@ No modules.
| [aws_iam_policy_document.controller_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.node_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.queue](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_iam_policy_document.v033](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_iam_policy_document.v1](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source |
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
@@ -141,6 +143,7 @@ No modules.
| [enable\_irsa](#input\_enable\_irsa) | Determines whether to enable support for IAM role for service accounts | `bool` | `false` | no |
| [enable\_pod\_identity](#input\_enable\_pod\_identity) | Determines whether to enable support for EKS pod identity | `bool` | `true` | no |
| [enable\_spot\_termination](#input\_enable\_spot\_termination) | Determines whether to enable native spot termination handling | `bool` | `true` | no |
+| [enable\_v1\_permissions](#input\_enable\_v1\_permissions) | Determines whether to enable permissions suitable for v1+ (`true`) or for v0.33.x-v0.37.x (`false`) | `bool` | `false` | no |
| [iam\_policy\_description](#input\_iam\_policy\_description) | IAM policy description | `string` | `"Karpenter controller IAM policy"` | no |
| [iam\_policy\_name](#input\_iam\_policy\_name) | Name of the IAM policy | `string` | `"KarpenterController"` | no |
| [iam\_policy\_path](#input\_iam\_policy\_path) | Path of the IAM policy | `string` | `"/"` | no |
diff --git a/modules/karpenter/main.tf b/modules/karpenter/main.tf
index fee75db43a..fc4a5dca57 100644
--- a/modules/karpenter/main.tf
+++ b/modules/karpenter/main.tf
@@ -84,346 +84,7 @@ resource "aws_iam_role" "controller" {
data "aws_iam_policy_document" "controller" {
count = local.create_iam_role ? 1 : 0
- statement {
- sid = "AllowScopedEC2InstanceActions"
- resources = [
- "arn:${local.partition}:ec2:*::image/*",
- "arn:${local.partition}:ec2:*::snapshot/*",
- "arn:${local.partition}:ec2:*:*:spot-instances-request/*",
- "arn:${local.partition}:ec2:*:*:security-group/*",
- "arn:${local.partition}:ec2:*:*:subnet/*",
- "arn:${local.partition}:ec2:*:*:launch-template/*",
- ]
-
- actions = [
- "ec2:RunInstances",
- "ec2:CreateFleet"
- ]
- }
-
- statement {
- sid = "AllowScopedEC2InstanceActionsWithTags"
- resources = [
- "arn:${local.partition}:ec2:*:*:fleet/*",
- "arn:${local.partition}:ec2:*:*:instance/*",
- "arn:${local.partition}:ec2:*:*:volume/*",
- "arn:${local.partition}:ec2:*:*:network-interface/*",
- "arn:${local.partition}:ec2:*:*:launch-template/*",
- "arn:${local.partition}:ec2:*:*:spot-instances-request/*",
- ]
- actions = [
- "ec2:RunInstances",
- "ec2:CreateFleet",
- "ec2:CreateLaunchTemplate"
- ]
-
- condition {
- test = "StringEquals"
- variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
- values = ["owned"]
- }
-
- condition {
- test = "StringLike"
- variable = "aws:RequestTag/karpenter.sh/nodepool"
- values = ["*"]
- }
- }
-
- statement {
- sid = "AllowScopedResourceCreationTagging"
- resources = [
- "arn:${local.partition}:ec2:*:*:fleet/*",
- "arn:${local.partition}:ec2:*:*:instance/*",
- "arn:${local.partition}:ec2:*:*:volume/*",
- "arn:${local.partition}:ec2:*:*:network-interface/*",
- "arn:${local.partition}:ec2:*:*:launch-template/*",
- "arn:${local.partition}:ec2:*:*:spot-instances-request/*",
- ]
- actions = ["ec2:CreateTags"]
-
- condition {
- test = "StringEquals"
- variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
- values = ["owned"]
- }
-
- condition {
- test = "StringEquals"
- variable = "ec2:CreateAction"
- values = [
- "RunInstances",
- "CreateFleet",
- "CreateLaunchTemplate",
- ]
- }
-
- condition {
- test = "StringLike"
- variable = "aws:RequestTag/karpenter.sh/nodepool"
- values = ["*"]
- }
- }
-
- statement {
- sid = "AllowScopedResourceTagging"
- resources = ["arn:${local.partition}:ec2:*:*:instance/*"]
- actions = ["ec2:CreateTags"]
-
- condition {
- test = "StringEquals"
- variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
- values = ["owned"]
- }
-
- condition {
- test = "StringLike"
- variable = "aws:ResourceTag/karpenter.sh/nodepool"
- values = ["*"]
- }
-
- condition {
- test = "ForAllValues:StringEquals"
- variable = "aws:TagKeys"
- values = [
- "karpenter.sh/nodeclaim",
- "Name",
- ]
- }
- }
-
- statement {
- sid = "AllowScopedDeletion"
- resources = [
- "arn:${local.partition}:ec2:*:*:instance/*",
- "arn:${local.partition}:ec2:*:*:launch-template/*"
- ]
-
- actions = [
- "ec2:TerminateInstances",
- "ec2:DeleteLaunchTemplate"
- ]
-
- condition {
- test = "StringEquals"
- variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
- values = ["owned"]
- }
-
- condition {
- test = "StringLike"
- variable = "aws:ResourceTag/karpenter.sh/nodepool"
- values = ["*"]
- }
- }
-
- statement {
- sid = "AllowRegionalReadActions"
- resources = ["*"]
- actions = [
- "ec2:DescribeAvailabilityZones",
- "ec2:DescribeImages",
- "ec2:DescribeInstances",
- "ec2:DescribeInstanceTypeOfferings",
- "ec2:DescribeInstanceTypes",
- "ec2:DescribeLaunchTemplates",
- "ec2:DescribeSecurityGroups",
- "ec2:DescribeSpotPriceHistory",
- "ec2:DescribeSubnets"
- ]
-
- condition {
- test = "StringEquals"
- variable = "aws:RequestedRegion"
- values = [local.region]
- }
- }
-
- statement {
- sid = "AllowSSMReadActions"
- resources = coalescelist(var.ami_id_ssm_parameter_arns, ["arn:${local.partition}:ssm:${local.region}::parameter/aws/service/*"])
- actions = ["ssm:GetParameter"]
- }
-
- statement {
- sid = "AllowPricingReadActions"
- resources = ["*"]
- actions = ["pricing:GetProducts"]
- }
-
- dynamic "statement" {
- for_each = local.enable_spot_termination ? [1] : []
-
- content {
- sid = "AllowInterruptionQueueActions"
- resources = [try(aws_sqs_queue.this[0].arn, null)]
- actions = [
- "sqs:DeleteMessage",
- "sqs:GetQueueAttributes",
- "sqs:GetQueueUrl",
- "sqs:ReceiveMessage"
- ]
- }
- }
-
- statement {
- sid = "AllowPassingInstanceRole"
- resources = var.create_node_iam_role ? [aws_iam_role.node[0].arn] : [var.node_iam_role_arn]
- actions = ["iam:PassRole"]
-
- condition {
- test = "StringEquals"
- variable = "iam:PassedToService"
- values = ["ec2.amazonaws.com"]
- }
- }
-
- statement {
- sid = "AllowScopedInstanceProfileCreationActions"
- resources = ["*"]
- actions = ["iam:CreateInstanceProfile"]
-
- condition {
- test = "StringEquals"
- variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
- values = ["owned"]
- }
-
- condition {
- test = "StringEquals"
- variable = "aws:RequestTag/topology.kubernetes.io/region"
- values = [local.region]
- }
-
- condition {
- test = "StringLike"
- variable = "aws:RequestTag/karpenter.k8s.aws/ec2nodeclass"
- values = ["*"]
- }
- }
-
- statement {
- sid = "AllowScopedInstanceProfileTagActions"
- resources = ["*"]
- actions = ["iam:TagInstanceProfile"]
-
- condition {
- test = "StringEquals"
- variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
- values = ["owned"]
- }
-
- condition {
- test = "StringEquals"
- variable = "aws:ResourceTag/topology.kubernetes.io/region"
- values = [local.region]
- }
-
- condition {
- test = "StringEquals"
- variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
- values = ["owned"]
- }
-
- condition {
- test = "StringEquals"
- variable = "aws:ResourceTag/topology.kubernetes.io/region"
- values = [local.region]
- }
-
- condition {
- test = "StringLike"
- variable = "aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass"
- values = ["*"]
- }
-
- condition {
- test = "StringLike"
- variable = "aws:RequestTag/karpenter.k8s.aws/ec2nodeclass"
- values = ["*"]
- }
- }
-
- statement {
- sid = "AllowScopedInstanceProfileActions"
- resources = ["*"]
- actions = [
- "iam:AddRoleToInstanceProfile",
- "iam:RemoveRoleFromInstanceProfile",
- "iam:DeleteInstanceProfile"
- ]
-
- condition {
- test = "StringEquals"
- variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
- values = ["owned"]
- }
-
- condition {
- test = "StringEquals"
- variable = "aws:ResourceTag/topology.kubernetes.io/region"
- values = [local.region]
- }
-
- condition {
- test = "StringLike"
- variable = "aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass"
- values = ["*"]
- }
- }
-
- statement {
- sid = "AllowInstanceProfileReadActions"
- resources = ["*"]
- actions = ["iam:GetInstanceProfile"]
- }
-
- statement {
- sid = "AllowAPIServerEndpointDiscovery"
- resources = ["arn:${local.partition}:eks:${local.region}:${local.account_id}:cluster/${var.cluster_name}"]
- actions = ["eks:DescribeCluster"]
- }
-
- dynamic "statement" {
- for_each = var.iam_policy_statements
-
- content {
- sid = try(statement.value.sid, null)
- actions = try(statement.value.actions, null)
- not_actions = try(statement.value.not_actions, null)
- effect = try(statement.value.effect, null)
- resources = try(statement.value.resources, null)
- not_resources = try(statement.value.not_resources, null)
-
- dynamic "principals" {
- for_each = try(statement.value.principals, [])
-
- content {
- type = principals.value.type
- identifiers = principals.value.identifiers
- }
- }
-
- dynamic "not_principals" {
- for_each = try(statement.value.not_principals, [])
-
- content {
- type = not_principals.value.type
- identifiers = not_principals.value.identifiers
- }
- }
-
- dynamic "condition" {
- for_each = try(statement.value.conditions, [])
-
- content {
- test = condition.value.test
- values = condition.value.values
- variable = condition.value.variable
- }
- }
- }
- }
+ source_policy_documents = var.enable_v1_permissions ? [data.aws_iam_policy_document.v1[0].json] : [data.aws_iam_policy_document.v033[0].json]
}
resource "aws_iam_policy" "controller" {
diff --git a/modules/karpenter/policy.tf b/modules/karpenter/policy.tf
new file mode 100644
index 0000000000..456a27f417
--- /dev/null
+++ b/modules/karpenter/policy.tf
@@ -0,0 +1,749 @@
+################################################################################
+# v0.33.x - v0.37.x Controller IAM Policy
+################################################################################
+
+data "aws_iam_policy_document" "v033" {
+ count = local.create_iam_role ? 1 : 0
+
+ statement {
+ sid = "AllowScopedEC2InstanceActions"
+ resources = [
+ "arn:${local.partition}:ec2:*::image/*",
+ "arn:${local.partition}:ec2:*::snapshot/*",
+ "arn:${local.partition}:ec2:*:*:spot-instances-request/*",
+ "arn:${local.partition}:ec2:*:*:security-group/*",
+ "arn:${local.partition}:ec2:*:*:subnet/*",
+ "arn:${local.partition}:ec2:*:*:launch-template/*",
+ ]
+
+ actions = [
+ "ec2:RunInstances",
+ "ec2:CreateFleet"
+ ]
+ }
+
+ statement {
+ sid = "AllowScopedEC2InstanceActionsWithTags"
+ resources = [
+ "arn:${local.partition}:ec2:*:*:fleet/*",
+ "arn:${local.partition}:ec2:*:*:instance/*",
+ "arn:${local.partition}:ec2:*:*:volume/*",
+ "arn:${local.partition}:ec2:*:*:network-interface/*",
+ "arn:${local.partition}:ec2:*:*:launch-template/*",
+ "arn:${local.partition}:ec2:*:*:spot-instances-request/*",
+ ]
+ actions = [
+ "ec2:RunInstances",
+ "ec2:CreateFleet",
+ "ec2:CreateLaunchTemplate"
+ ]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:RequestTag/karpenter.sh/nodepool"
+ values = ["*"]
+ }
+ }
+
+ statement {
+ sid = "AllowScopedResourceCreationTagging"
+ resources = [
+ "arn:${local.partition}:ec2:*:*:fleet/*",
+ "arn:${local.partition}:ec2:*:*:instance/*",
+ "arn:${local.partition}:ec2:*:*:volume/*",
+ "arn:${local.partition}:ec2:*:*:network-interface/*",
+ "arn:${local.partition}:ec2:*:*:launch-template/*",
+ "arn:${local.partition}:ec2:*:*:spot-instances-request/*",
+ ]
+ actions = ["ec2:CreateTags"]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "ec2:CreateAction"
+ values = [
+ "RunInstances",
+ "CreateFleet",
+ "CreateLaunchTemplate",
+ ]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:RequestTag/karpenter.sh/nodepool"
+ values = ["*"]
+ }
+ }
+
+ statement {
+ sid = "AllowScopedResourceTagging"
+ resources = ["arn:${local.partition}:ec2:*:*:instance/*"]
+ actions = ["ec2:CreateTags"]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:ResourceTag/karpenter.sh/nodepool"
+ values = ["*"]
+ }
+
+ condition {
+ test = "ForAllValues:StringEquals"
+ variable = "aws:TagKeys"
+ values = [
+ "karpenter.sh/nodeclaim",
+ "Name",
+ ]
+ }
+ }
+
+ statement {
+ sid = "AllowScopedDeletion"
+ resources = [
+ "arn:${local.partition}:ec2:*:*:instance/*",
+ "arn:${local.partition}:ec2:*:*:launch-template/*"
+ ]
+
+ actions = [
+ "ec2:TerminateInstances",
+ "ec2:DeleteLaunchTemplate"
+ ]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:ResourceTag/karpenter.sh/nodepool"
+ values = ["*"]
+ }
+ }
+
+ statement {
+ sid = "AllowRegionalReadActions"
+ resources = ["*"]
+ actions = [
+ "ec2:DescribeAvailabilityZones",
+ "ec2:DescribeImages",
+ "ec2:DescribeInstances",
+ "ec2:DescribeInstanceTypeOfferings",
+ "ec2:DescribeInstanceTypes",
+ "ec2:DescribeLaunchTemplates",
+ "ec2:DescribeSecurityGroups",
+ "ec2:DescribeSpotPriceHistory",
+ "ec2:DescribeSubnets"
+ ]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestedRegion"
+ values = [local.region]
+ }
+ }
+
+ statement {
+ sid = "AllowSSMReadActions"
+ resources = coalescelist(var.ami_id_ssm_parameter_arns, ["arn:${local.partition}:ssm:${local.region}::parameter/aws/service/*"])
+ actions = ["ssm:GetParameter"]
+ }
+
+ statement {
+ sid = "AllowPricingReadActions"
+ resources = ["*"]
+ actions = ["pricing:GetProducts"]
+ }
+
+ dynamic "statement" {
+ for_each = local.enable_spot_termination ? [1] : []
+
+ content {
+ sid = "AllowInterruptionQueueActions"
+ resources = [try(aws_sqs_queue.this[0].arn, null)]
+ actions = [
+ "sqs:DeleteMessage",
+ "sqs:GetQueueAttributes",
+ "sqs:GetQueueUrl",
+ "sqs:ReceiveMessage"
+ ]
+ }
+ }
+
+ statement {
+ sid = "AllowPassingInstanceRole"
+ resources = var.create_node_iam_role ? [aws_iam_role.node[0].arn] : [var.node_iam_role_arn]
+ actions = ["iam:PassRole"]
+
+ condition {
+ test = "StringEquals"
+ variable = "iam:PassedToService"
+ values = ["ec2.amazonaws.com"]
+ }
+ }
+
+ statement {
+ sid = "AllowScopedInstanceProfileCreationActions"
+ resources = ["*"]
+ actions = ["iam:CreateInstanceProfile"]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/topology.kubernetes.io/region"
+ values = [local.region]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:RequestTag/karpenter.k8s.aws/ec2nodeclass"
+ values = ["*"]
+ }
+ }
+
+ statement {
+ sid = "AllowScopedInstanceProfileTagActions"
+ resources = ["*"]
+ actions = ["iam:TagInstanceProfile"]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:ResourceTag/topology.kubernetes.io/region"
+ values = [local.region]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:ResourceTag/topology.kubernetes.io/region"
+ values = [local.region]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass"
+ values = ["*"]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:RequestTag/karpenter.k8s.aws/ec2nodeclass"
+ values = ["*"]
+ }
+ }
+
+ statement {
+ sid = "AllowScopedInstanceProfileActions"
+ resources = ["*"]
+ actions = [
+ "iam:AddRoleToInstanceProfile",
+ "iam:RemoveRoleFromInstanceProfile",
+ "iam:DeleteInstanceProfile"
+ ]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:ResourceTag/topology.kubernetes.io/region"
+ values = [local.region]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass"
+ values = ["*"]
+ }
+ }
+
+ statement {
+ sid = "AllowInstanceProfileReadActions"
+ resources = ["*"]
+ actions = ["iam:GetInstanceProfile"]
+ }
+
+ statement {
+ sid = "AllowAPIServerEndpointDiscovery"
+ resources = ["arn:${local.partition}:eks:${local.region}:${local.account_id}:cluster/${var.cluster_name}"]
+ actions = ["eks:DescribeCluster"]
+ }
+
+ dynamic "statement" {
+ for_each = var.iam_policy_statements
+
+ content {
+ sid = try(statement.value.sid, null)
+ actions = try(statement.value.actions, null)
+ not_actions = try(statement.value.not_actions, null)
+ effect = try(statement.value.effect, null)
+ resources = try(statement.value.resources, null)
+ not_resources = try(statement.value.not_resources, null)
+
+ dynamic "principals" {
+ for_each = try(statement.value.principals, [])
+
+ content {
+ type = principals.value.type
+ identifiers = principals.value.identifiers
+ }
+ }
+
+ dynamic "not_principals" {
+ for_each = try(statement.value.not_principals, [])
+
+ content {
+ type = not_principals.value.type
+ identifiers = not_principals.value.identifiers
+ }
+ }
+
+ dynamic "condition" {
+ for_each = try(statement.value.conditions, [])
+
+ content {
+ test = condition.value.test
+ values = condition.value.values
+ variable = condition.value.variable
+ }
+ }
+ }
+ }
+}
+
+################################################################################
+# v1.0.x Controller IAM Policy
+################################################################################
+
+data "aws_iam_policy_document" "v1" {
+ count = local.create_iam_role ? 1 : 0
+
+ statement {
+ sid = "AllowScopedEC2InstanceAccessActions"
+ resources = [
+ "arn:${local.partition}:ec2:${local.region}::image/*",
+ "arn:${local.partition}:ec2:${local.region}::snapshot/*",
+ "arn:${local.partition}:ec2:${local.region}:*:security-group/*",
+ "arn:${local.partition}:ec2:${local.region}:*:subnet/*",
+ ]
+
+ actions = [
+ "ec2:RunInstances",
+ "ec2:CreateFleet"
+ ]
+ }
+
+ statement {
+ sid = "AllowScopedEC2LaunchTemplateAccessActions"
+ resources = [
+ "arn:${local.partition}:ec2:${local.region}:*:launch-template/*"
+ ]
+
+ actions = [
+ "ec2:RunInstances",
+ "ec2:CreateFleet"
+ ]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:ResourceTag/karpenter.sh/nodepool"
+ values = ["*"]
+ }
+ }
+
+ statement {
+ sid = "AllowScopedEC2InstanceActionsWithTags"
+ resources = [
+ "arn:${local.partition}:ec2:${local.region}:*:fleet/*",
+ "arn:${local.partition}:ec2:${local.region}:*:instance/*",
+ "arn:${local.partition}:ec2:${local.region}:*:volume/*",
+ "arn:${local.partition}:ec2:${local.region}:*:network-interface/*",
+ "arn:${local.partition}:ec2:${local.region}:*:launch-template/*",
+ "arn:${local.partition}:ec2:${local.region}:*:spot-instances-request/*",
+ ]
+ actions = [
+ "ec2:RunInstances",
+ "ec2:CreateFleet",
+ "ec2:CreateLaunchTemplate"
+ ]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/eks:eks-cluster-name"
+ values = [var.cluster_name]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:RequestTag/karpenter.sh/nodepool"
+ values = ["*"]
+ }
+ }
+
+ statement {
+ sid = "AllowScopedResourceCreationTagging"
+ resources = [
+ "arn:${local.partition}:ec2:${local.region}:*:fleet/*",
+ "arn:${local.partition}:ec2:${local.region}:*:instance/*",
+ "arn:${local.partition}:ec2:${local.region}:*:volume/*",
+ "arn:${local.partition}:ec2:${local.region}:*:network-interface/*",
+ "arn:${local.partition}:ec2:${local.region}:*:launch-template/*",
+ "arn:${local.partition}:ec2:${local.region}:*:spot-instances-request/*",
+ ]
+ actions = ["ec2:CreateTags"]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/eks:eks-cluster-name"
+ values = [var.cluster_name]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "ec2:CreateAction"
+ values = [
+ "RunInstances",
+ "CreateFleet",
+ "CreateLaunchTemplate",
+ ]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:RequestTag/karpenter.sh/nodepool"
+ values = ["*"]
+ }
+ }
+
+ statement {
+ sid = "AllowScopedResourceTagging"
+ resources = ["arn:${local.partition}:ec2:${local.region}:*:instance/*"]
+ actions = ["ec2:CreateTags"]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:ResourceTag/karpenter.sh/nodepool"
+ values = ["*"]
+ }
+
+ condition {
+ test = "StringEqualsIfExists"
+ variable = "aws:RequestTag/eks:eks-cluster-name"
+ values = [var.cluster_name]
+ }
+
+ condition {
+ test = "ForAllValues:StringEquals"
+ variable = "aws:TagKeys"
+ values = [
+ "eks:eks-cluster-name",
+ "karpenter.sh/nodeclaim",
+ "Name",
+ ]
+ }
+ }
+
+ statement {
+ sid = "AllowScopedDeletion"
+ resources = [
+ "arn:${local.partition}:ec2:${local.region}:*:instance/*",
+ "arn:${local.partition}:ec2:${local.region}:*:launch-template/*"
+ ]
+
+ actions = [
+ "ec2:TerminateInstances",
+ "ec2:DeleteLaunchTemplate"
+ ]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:ResourceTag/karpenter.sh/nodepool"
+ values = ["*"]
+ }
+ }
+
+ statement {
+ sid = "AllowRegionalReadActions"
+ resources = ["*"]
+ actions = [
+ "ec2:DescribeAvailabilityZones",
+ "ec2:DescribeImages",
+ "ec2:DescribeInstances",
+ "ec2:DescribeInstanceTypeOfferings",
+ "ec2:DescribeInstanceTypes",
+ "ec2:DescribeLaunchTemplates",
+ "ec2:DescribeSecurityGroups",
+ "ec2:DescribeSpotPriceHistory",
+ "ec2:DescribeSubnets"
+ ]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestedRegion"
+ values = [local.region]
+ }
+ }
+
+ statement {
+ sid = "AllowSSMReadActions"
+ resources = coalescelist(var.ami_id_ssm_parameter_arns, ["arn:${local.partition}:ssm:${local.region}::parameter/aws/service/*"])
+ actions = ["ssm:GetParameter"]
+ }
+
+ statement {
+ sid = "AllowPricingReadActions"
+ resources = ["*"]
+ actions = ["pricing:GetProducts"]
+ }
+
+ dynamic "statement" {
+ for_each = local.enable_spot_termination ? [1] : []
+
+ content {
+ sid = "AllowInterruptionQueueActions"
+ resources = [try(aws_sqs_queue.this[0].arn, null)]
+ actions = [
+ "sqs:DeleteMessage",
+ "sqs:GetQueueUrl",
+ "sqs:ReceiveMessage"
+ ]
+ }
+ }
+
+ statement {
+ sid = "AllowPassingInstanceRole"
+ resources = var.create_node_iam_role ? [aws_iam_role.node[0].arn] : [var.node_iam_role_arn]
+ actions = ["iam:PassRole"]
+
+ condition {
+ test = "StringEquals"
+ variable = "iam:PassedToService"
+ values = ["ec2.amazonaws.com"]
+ }
+ }
+
+ statement {
+ sid = "AllowScopedInstanceProfileCreationActions"
+ resources = ["arn:${local.partition}:iam::${local.account_id}:instance-profile/*"]
+ actions = ["iam:CreateInstanceProfile"]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/eks:eks-cluster-name"
+ values = [var.cluster_name]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/topology.kubernetes.io/region"
+ values = [local.region]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:RequestTag/karpenter.k8s.aws/ec2nodeclass"
+ values = ["*"]
+ }
+ }
+
+ statement {
+ sid = "AllowScopedInstanceProfileTagActions"
+ resources = ["arn:${local.partition}:iam::${local.account_id}:instance-profile/*"]
+ actions = ["iam:TagInstanceProfile"]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:ResourceTag/topology.kubernetes.io/region"
+ values = [local.region]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/eks:eks-cluster-name"
+ values = [var.cluster_name]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:RequestTag/topology.kubernetes.io/region"
+ values = [local.region]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass"
+ values = ["*"]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:RequestTag/karpenter.k8s.aws/ec2nodeclass"
+ values = ["*"]
+ }
+ }
+
+ statement {
+ sid = "AllowScopedInstanceProfileActions"
+ resources = ["arn:${local.partition}:iam::${local.account_id}:instance-profile/*"]
+ actions = [
+ "iam:AddRoleToInstanceProfile",
+ "iam:RemoveRoleFromInstanceProfile",
+ "iam:DeleteInstanceProfile"
+ ]
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
+ values = ["owned"]
+ }
+
+ condition {
+ test = "StringEquals"
+ variable = "aws:ResourceTag/topology.kubernetes.io/region"
+ values = [local.region]
+ }
+
+ condition {
+ test = "StringLike"
+ variable = "aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass"
+ values = ["*"]
+ }
+ }
+
+ statement {
+ sid = "AllowInstanceProfileReadActions"
+ resources = ["arn:${local.partition}:iam::${local.account_id}:instance-profile/*"]
+ actions = ["iam:GetInstanceProfile"]
+ }
+
+ statement {
+ sid = "AllowAPIServerEndpointDiscovery"
+ resources = ["arn:${local.partition}:eks:${local.region}:${local.account_id}:cluster/${var.cluster_name}"]
+ actions = ["eks:DescribeCluster"]
+ }
+
+ dynamic "statement" {
+ for_each = var.iam_policy_statements
+
+ content {
+ sid = try(statement.value.sid, null)
+ actions = try(statement.value.actions, null)
+ not_actions = try(statement.value.not_actions, null)
+ effect = try(statement.value.effect, null)
+ resources = try(statement.value.resources, null)
+ not_resources = try(statement.value.not_resources, null)
+
+ dynamic "principals" {
+ for_each = try(statement.value.principals, [])
+
+ content {
+ type = principals.value.type
+ identifiers = principals.value.identifiers
+ }
+ }
+
+ dynamic "not_principals" {
+ for_each = try(statement.value.not_principals, [])
+
+ content {
+ type = not_principals.value.type
+ identifiers = not_principals.value.identifiers
+ }
+ }
+
+ dynamic "condition" {
+ for_each = try(statement.value.conditions, [])
+
+ content {
+ test = condition.value.test
+ values = condition.value.values
+ variable = condition.value.variable
+ }
+ }
+ }
+ }
+}
diff --git a/modules/karpenter/variables.tf b/modules/karpenter/variables.tf
index 96d898b245..a2c307fc05 100644
--- a/modules/karpenter/variables.tf
+++ b/modules/karpenter/variables.tf
@@ -116,6 +116,13 @@ variable "enable_pod_identity" {
default = true
}
+# TODO - make v1 permssions the default policy at next breaking change
+variable "enable_v1_permissions" {
+ description = "Determines whether to enable permissions suitable for v1+ (`true`) or for v0.33.x-v0.37.x (`false`)"
+ type = bool
+ default = false
+}
+
################################################################################
# IAM Role for Service Account (IRSA)
################################################################################