Skip to content

Commit e317651

Browse files
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 f0e5c79. * fix: Add support for both v1 and prior to v1 controller permission policy --------- Co-authored-by: Bryant Biggs <[email protected]>
1 parent 1360e3d commit e317651

File tree

6 files changed

+764
-342
lines changed

6 files changed

+764
-342
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/antonbabenko/pre-commit-terraform
3-
rev: v1.92.1
3+
rev: v1.92.2
44
hooks:
55
- id: terraform_fmt
66
- id: terraform_docs

examples/karpenter/main.tf

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ module "karpenter" {
126126

127127
cluster_name = module.eks.cluster_name
128128

129+
enable_v1_permissions = true
130+
129131
enable_pod_identity = true
130132
create_pod_identity_association = true
131133

@@ -155,7 +157,7 @@ resource "helm_release" "karpenter" {
155157
repository_username = data.aws_ecrpublic_authorization_token.token.user_name
156158
repository_password = data.aws_ecrpublic_authorization_token.token.password
157159
chart = "karpenter"
158-
version = "0.37.0"
160+
version = "1.0.0"
159161
wait = false
160162

161163
values = [

modules/karpenter/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ No modules.
121121
| [aws_iam_policy_document.controller_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
122122
| [aws_iam_policy_document.node_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
123123
| [aws_iam_policy_document.queue](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
124+
| [aws_iam_policy_document.v033](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
125+
| [aws_iam_policy_document.v1](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
124126
| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source |
125127
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
126128

@@ -141,6 +143,7 @@ No modules.
141143
| <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 |
142144
| <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 |
143145
| <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 |
146+
| <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 |
144147
| <a name="input_iam_policy_description"></a> [iam\_policy\_description](#input\_iam\_policy\_description) | IAM policy description | `string` | `"Karpenter controller IAM policy"` | no |
145148
| <a name="input_iam_policy_name"></a> [iam\_policy\_name](#input\_iam\_policy\_name) | Name of the IAM policy | `string` | `"KarpenterController"` | no |
146149
| <a name="input_iam_policy_path"></a> [iam\_policy\_path](#input\_iam\_policy\_path) | Path of the IAM policy | `string` | `"/"` | no |

modules/karpenter/main.tf

Lines changed: 1 addition & 340 deletions
Original file line numberDiff line numberDiff line change
@@ -84,346 +84,7 @@ resource "aws_iam_role" "controller" {
8484
data "aws_iam_policy_document" "controller" {
8585
count = local.create_iam_role ? 1 : 0
8686

87-
statement {
88-
sid = "AllowScopedEC2InstanceActions"
89-
resources = [
90-
"arn:${local.partition}:ec2:*::image/*",
91-
"arn:${local.partition}:ec2:*::snapshot/*",
92-
"arn:${local.partition}:ec2:*:*:spot-instances-request/*",
93-
"arn:${local.partition}:ec2:*:*:security-group/*",
94-
"arn:${local.partition}:ec2:*:*:subnet/*",
95-
"arn:${local.partition}:ec2:*:*:launch-template/*",
96-
]
97-
98-
actions = [
99-
"ec2:RunInstances",
100-
"ec2:CreateFleet"
101-
]
102-
}
103-
104-
statement {
105-
sid = "AllowScopedEC2InstanceActionsWithTags"
106-
resources = [
107-
"arn:${local.partition}:ec2:*:*:fleet/*",
108-
"arn:${local.partition}:ec2:*:*:instance/*",
109-
"arn:${local.partition}:ec2:*:*:volume/*",
110-
"arn:${local.partition}:ec2:*:*:network-interface/*",
111-
"arn:${local.partition}:ec2:*:*:launch-template/*",
112-
"arn:${local.partition}:ec2:*:*:spot-instances-request/*",
113-
]
114-
actions = [
115-
"ec2:RunInstances",
116-
"ec2:CreateFleet",
117-
"ec2:CreateLaunchTemplate"
118-
]
119-
120-
condition {
121-
test = "StringEquals"
122-
variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
123-
values = ["owned"]
124-
}
125-
126-
condition {
127-
test = "StringLike"
128-
variable = "aws:RequestTag/karpenter.sh/nodepool"
129-
values = ["*"]
130-
}
131-
}
132-
133-
statement {
134-
sid = "AllowScopedResourceCreationTagging"
135-
resources = [
136-
"arn:${local.partition}:ec2:*:*:fleet/*",
137-
"arn:${local.partition}:ec2:*:*:instance/*",
138-
"arn:${local.partition}:ec2:*:*:volume/*",
139-
"arn:${local.partition}:ec2:*:*:network-interface/*",
140-
"arn:${local.partition}:ec2:*:*:launch-template/*",
141-
"arn:${local.partition}:ec2:*:*:spot-instances-request/*",
142-
]
143-
actions = ["ec2:CreateTags"]
144-
145-
condition {
146-
test = "StringEquals"
147-
variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
148-
values = ["owned"]
149-
}
150-
151-
condition {
152-
test = "StringEquals"
153-
variable = "ec2:CreateAction"
154-
values = [
155-
"RunInstances",
156-
"CreateFleet",
157-
"CreateLaunchTemplate",
158-
]
159-
}
160-
161-
condition {
162-
test = "StringLike"
163-
variable = "aws:RequestTag/karpenter.sh/nodepool"
164-
values = ["*"]
165-
}
166-
}
167-
168-
statement {
169-
sid = "AllowScopedResourceTagging"
170-
resources = ["arn:${local.partition}:ec2:*:*:instance/*"]
171-
actions = ["ec2:CreateTags"]
172-
173-
condition {
174-
test = "StringEquals"
175-
variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
176-
values = ["owned"]
177-
}
178-
179-
condition {
180-
test = "StringLike"
181-
variable = "aws:ResourceTag/karpenter.sh/nodepool"
182-
values = ["*"]
183-
}
184-
185-
condition {
186-
test = "ForAllValues:StringEquals"
187-
variable = "aws:TagKeys"
188-
values = [
189-
"karpenter.sh/nodeclaim",
190-
"Name",
191-
]
192-
}
193-
}
194-
195-
statement {
196-
sid = "AllowScopedDeletion"
197-
resources = [
198-
"arn:${local.partition}:ec2:*:*:instance/*",
199-
"arn:${local.partition}:ec2:*:*:launch-template/*"
200-
]
201-
202-
actions = [
203-
"ec2:TerminateInstances",
204-
"ec2:DeleteLaunchTemplate"
205-
]
206-
207-
condition {
208-
test = "StringEquals"
209-
variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
210-
values = ["owned"]
211-
}
212-
213-
condition {
214-
test = "StringLike"
215-
variable = "aws:ResourceTag/karpenter.sh/nodepool"
216-
values = ["*"]
217-
}
218-
}
219-
220-
statement {
221-
sid = "AllowRegionalReadActions"
222-
resources = ["*"]
223-
actions = [
224-
"ec2:DescribeAvailabilityZones",
225-
"ec2:DescribeImages",
226-
"ec2:DescribeInstances",
227-
"ec2:DescribeInstanceTypeOfferings",
228-
"ec2:DescribeInstanceTypes",
229-
"ec2:DescribeLaunchTemplates",
230-
"ec2:DescribeSecurityGroups",
231-
"ec2:DescribeSpotPriceHistory",
232-
"ec2:DescribeSubnets"
233-
]
234-
235-
condition {
236-
test = "StringEquals"
237-
variable = "aws:RequestedRegion"
238-
values = [local.region]
239-
}
240-
}
241-
242-
statement {
243-
sid = "AllowSSMReadActions"
244-
resources = coalescelist(var.ami_id_ssm_parameter_arns, ["arn:${local.partition}:ssm:${local.region}::parameter/aws/service/*"])
245-
actions = ["ssm:GetParameter"]
246-
}
247-
248-
statement {
249-
sid = "AllowPricingReadActions"
250-
resources = ["*"]
251-
actions = ["pricing:GetProducts"]
252-
}
253-
254-
dynamic "statement" {
255-
for_each = local.enable_spot_termination ? [1] : []
256-
257-
content {
258-
sid = "AllowInterruptionQueueActions"
259-
resources = [try(aws_sqs_queue.this[0].arn, null)]
260-
actions = [
261-
"sqs:DeleteMessage",
262-
"sqs:GetQueueAttributes",
263-
"sqs:GetQueueUrl",
264-
"sqs:ReceiveMessage"
265-
]
266-
}
267-
}
268-
269-
statement {
270-
sid = "AllowPassingInstanceRole"
271-
resources = var.create_node_iam_role ? [aws_iam_role.node[0].arn] : [var.node_iam_role_arn]
272-
actions = ["iam:PassRole"]
273-
274-
condition {
275-
test = "StringEquals"
276-
variable = "iam:PassedToService"
277-
values = ["ec2.amazonaws.com"]
278-
}
279-
}
280-
281-
statement {
282-
sid = "AllowScopedInstanceProfileCreationActions"
283-
resources = ["*"]
284-
actions = ["iam:CreateInstanceProfile"]
285-
286-
condition {
287-
test = "StringEquals"
288-
variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
289-
values = ["owned"]
290-
}
291-
292-
condition {
293-
test = "StringEquals"
294-
variable = "aws:RequestTag/topology.kubernetes.io/region"
295-
values = [local.region]
296-
}
297-
298-
condition {
299-
test = "StringLike"
300-
variable = "aws:RequestTag/karpenter.k8s.aws/ec2nodeclass"
301-
values = ["*"]
302-
}
303-
}
304-
305-
statement {
306-
sid = "AllowScopedInstanceProfileTagActions"
307-
resources = ["*"]
308-
actions = ["iam:TagInstanceProfile"]
309-
310-
condition {
311-
test = "StringEquals"
312-
variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
313-
values = ["owned"]
314-
}
315-
316-
condition {
317-
test = "StringEquals"
318-
variable = "aws:ResourceTag/topology.kubernetes.io/region"
319-
values = [local.region]
320-
}
321-
322-
condition {
323-
test = "StringEquals"
324-
variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_name}"
325-
values = ["owned"]
326-
}
327-
328-
condition {
329-
test = "StringEquals"
330-
variable = "aws:ResourceTag/topology.kubernetes.io/region"
331-
values = [local.region]
332-
}
333-
334-
condition {
335-
test = "StringLike"
336-
variable = "aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass"
337-
values = ["*"]
338-
}
339-
340-
condition {
341-
test = "StringLike"
342-
variable = "aws:RequestTag/karpenter.k8s.aws/ec2nodeclass"
343-
values = ["*"]
344-
}
345-
}
346-
347-
statement {
348-
sid = "AllowScopedInstanceProfileActions"
349-
resources = ["*"]
350-
actions = [
351-
"iam:AddRoleToInstanceProfile",
352-
"iam:RemoveRoleFromInstanceProfile",
353-
"iam:DeleteInstanceProfile"
354-
]
355-
356-
condition {
357-
test = "StringEquals"
358-
variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
359-
values = ["owned"]
360-
}
361-
362-
condition {
363-
test = "StringEquals"
364-
variable = "aws:ResourceTag/topology.kubernetes.io/region"
365-
values = [local.region]
366-
}
367-
368-
condition {
369-
test = "StringLike"
370-
variable = "aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass"
371-
values = ["*"]
372-
}
373-
}
374-
375-
statement {
376-
sid = "AllowInstanceProfileReadActions"
377-
resources = ["*"]
378-
actions = ["iam:GetInstanceProfile"]
379-
}
380-
381-
statement {
382-
sid = "AllowAPIServerEndpointDiscovery"
383-
resources = ["arn:${local.partition}:eks:${local.region}:${local.account_id}:cluster/${var.cluster_name}"]
384-
actions = ["eks:DescribeCluster"]
385-
}
386-
387-
dynamic "statement" {
388-
for_each = var.iam_policy_statements
389-
390-
content {
391-
sid = try(statement.value.sid, null)
392-
actions = try(statement.value.actions, null)
393-
not_actions = try(statement.value.not_actions, null)
394-
effect = try(statement.value.effect, null)
395-
resources = try(statement.value.resources, null)
396-
not_resources = try(statement.value.not_resources, null)
397-
398-
dynamic "principals" {
399-
for_each = try(statement.value.principals, [])
400-
401-
content {
402-
type = principals.value.type
403-
identifiers = principals.value.identifiers
404-
}
405-
}
406-
407-
dynamic "not_principals" {
408-
for_each = try(statement.value.not_principals, [])
409-
410-
content {
411-
type = not_principals.value.type
412-
identifiers = not_principals.value.identifiers
413-
}
414-
}
415-
416-
dynamic "condition" {
417-
for_each = try(statement.value.conditions, [])
418-
419-
content {
420-
test = condition.value.test
421-
values = condition.value.values
422-
variable = condition.value.variable
423-
}
424-
}
425-
}
426-
}
87+
source_policy_documents = var.enable_v1_permissions ? [data.aws_iam_policy_document.v1[0].json] : [data.aws_iam_policy_document.v033[0].json]
42788
}
42889

42990
resource "aws_iam_policy" "controller" {

0 commit comments

Comments
 (0)