feat: Add support for Karpenter v1 controller IAM role permissions (#3126)

* chore: update controller IAM role permissions to support karpenter v1

* Update versions.tf

* Revert "Update versions.tf"

This reverts commit f0e5c791443301ef7f802c627efe7f7226b95046.

* fix: Add support for both v1 and prior to v1 controller permission policy

---------

Co-authored-by: Bryant Biggs <bryantbiggs@gmail.com>
This commit is contained in:
Andy Townsend
2024-08-19 20:31:36 +01:00
committed by GitHub
parent 1360e3de68
commit e317651535
6 changed files with 764 additions and 342 deletions

View File

@@ -1,6 +1,6 @@
repos: repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform - repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.92.1 rev: v1.92.2
hooks: hooks:
- id: terraform_fmt - id: terraform_fmt
- id: terraform_docs - id: terraform_docs

View File

@@ -126,6 +126,8 @@ module "karpenter" {
cluster_name = module.eks.cluster_name cluster_name = module.eks.cluster_name
enable_v1_permissions = true
enable_pod_identity = true enable_pod_identity = true
create_pod_identity_association = 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_username = data.aws_ecrpublic_authorization_token.token.user_name
repository_password = data.aws_ecrpublic_authorization_token.token.password repository_password = data.aws_ecrpublic_authorization_token.token.password
chart = "karpenter" chart = "karpenter"
version = "0.37.0" version = "1.0.0"
wait = false wait = false
values = [ values = [

View File

@@ -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.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.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.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_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 | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
@@ -141,6 +143,7 @@ No modules.
| <a name="input_enable_irsa"></a> [enable\_irsa](#input\_enable\_irsa) | Determines whether to enable support for IAM role for service accounts | `bool` | `false` | no | | <a name="input_enable_irsa"></a> [enable\_irsa](#input\_enable\_irsa) | Determines whether to enable support for IAM role for service accounts | `bool` | `false` | no |
| <a name="input_enable_pod_identity"></a> [enable\_pod\_identity](#input\_enable\_pod\_identity) | Determines whether to enable support for EKS pod identity | `bool` | `true` | no | | <a name="input_enable_pod_identity"></a> [enable\_pod\_identity](#input\_enable\_pod\_identity) | Determines whether to enable support for EKS pod identity | `bool` | `true` | no |
| <a name="input_enable_spot_termination"></a> [enable\_spot\_termination](#input\_enable\_spot\_termination) | Determines whether to enable native spot termination handling | `bool` | `true` | no | | <a name="input_enable_spot_termination"></a> [enable\_spot\_termination](#input\_enable\_spot\_termination) | Determines whether to enable native spot termination handling | `bool` | `true` | no |
| <a name="input_enable_v1_permissions"></a> [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 |
| <a name="input_iam_policy_description"></a> [iam\_policy\_description](#input\_iam\_policy\_description) | IAM policy description | `string` | `"Karpenter controller IAM policy"` | no | | <a name="input_iam_policy_description"></a> [iam\_policy\_description](#input\_iam\_policy\_description) | IAM policy description | `string` | `"Karpenter controller IAM policy"` | no |
| <a name="input_iam_policy_name"></a> [iam\_policy\_name](#input\_iam\_policy\_name) | Name of the IAM policy | `string` | `"KarpenterController"` | no | | <a name="input_iam_policy_name"></a> [iam\_policy\_name](#input\_iam\_policy\_name) | Name of the IAM policy | `string` | `"KarpenterController"` | no |
| <a name="input_iam_policy_path"></a> [iam\_policy\_path](#input\_iam\_policy\_path) | Path of the IAM policy | `string` | `"/"` | no | | <a name="input_iam_policy_path"></a> [iam\_policy\_path](#input\_iam\_policy\_path) | Path of the IAM policy | `string` | `"/"` | no |

View File

@@ -84,346 +84,7 @@ resource "aws_iam_role" "controller" {
data "aws_iam_policy_document" "controller" { data "aws_iam_policy_document" "controller" {
count = local.create_iam_role ? 1 : 0 count = local.create_iam_role ? 1 : 0
statement { source_policy_documents = var.enable_v1_permissions ? [data.aws_iam_policy_document.v1[0].json] : [data.aws_iam_policy_document.v033[0].json]
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
}
}
}
}
} }
resource "aws_iam_policy" "controller" { resource "aws_iam_policy" "controller" {

749
modules/karpenter/policy.tf Normal file
View File

@@ -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
}
}
}
}
}

View File

@@ -116,6 +116,13 @@ variable "enable_pod_identity" {
default = true 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) # IAM Role for Service Account (IRSA)
################################################################################ ################################################################################