Skip to content

Commit d014730

Browse files
feat: Improved iam-eks-role module (simplified, removed provider_url_sa_pairs, updated docs) (#236)
1 parent 2fb3c30 commit d014730

File tree

6 files changed

+52
-65
lines changed

6 files changed

+52
-65
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ Use [iam-read-only-policy module](https://github.com/terraform-aws-modules/terra
344344
- [iam-assumable-role-with-saml](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-assumable-role-with-saml) - Create individual IAM role which can be assumed by users with a SAML Identity Provider
345345
- [iam-assumable-roles](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-assumable-roles) - Create several IAM roles which can be assumed from specified ARNs (AWS accounts, IAM users, etc)
346346
- [iam-assumable-roles-with-saml](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-assumable-roles-with-saml) - Create several IAM roles which can be assumed by users with a SAML Identity Provider
347-
- [iam-eks-role](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-eks-role) - Create an IAM role which can be assumed by one or more EKS `ServiceAccount`
347+
- [iam-eks-role](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-eks-role) - Create an IAM role that can be assumed by one or more EKS `ServiceAccount`
348348
- [iam-group-complete](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-group-complete) - IAM group with users who are allowed to assume IAM roles in another AWS account and have access to specified IAM policies
349349
- [iam-group-with-assumable-roles-policy](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-group-with-assumable-roles-policy) - IAM group with users who are allowed to assume IAM roles in the same or in separate AWS account
350350
- [iam-group-with-policies](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-group-with-policies) - IAM group with users who are allowed specified IAM policies (eg, "manage their own IAM user")

examples/iam-eks-role/main.tf

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,7 @@ module "iam_eks_role" {
77
role_name = "my-app"
88

99
cluster_service_accounts = {
10-
(random_pet.this.id) = ["default:my-app", "canary:my-app"]
11-
}
12-
13-
provider_url_sa_pairs = {
14-
"oidc.eks.us-east-1.amazonaws.com/id/5C54DDF35ER19312844C7333374CC09D" = ["default:my-app2"]
15-
"oidc.eks.ap-southeast-1.amazonaws.com/id/5C54DDF35ER54476848E7333374FF09G" = [
16-
"default:my-app2",
17-
"canary:my-app2",
18-
]
10+
(random_pet.this.id) = ["default:my-app"]
1911
}
2012

2113
tags = {

modules/iam-eks-role/README.md

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,78 @@
11
# iam-eks-role
22

3-
Creates single IAM role which can be assumed by one or more EKS `ServiceAccount` and optionally also OpenID Connect Federated Users.
3+
Creates an IAM role that can be assumed by one or more EKS `ServiceAccount` in one or more EKS clusters. Unlike [iam-assumable-role-with-oidc](https://github.com/terraform-aws-modules/terraform-aws-iam/blob/master/modules/iam-assumable-role-with-oidc/), this module:
4+
5+
- Does not require any knowledge of cluster OIDC information as `data` resources are used
6+
- Supports assuming the role from multiple EKS clusters, for example used in DR or when a workload is spread across clusters
7+
- Support multiple `ServiceAccount` in the same cluster, for example when a workload runs in multiple namespaces
8+
- More suitable for non-cluster admins as implementation is simpler
9+
- More suitable for when the IAM role and cluster resources are in separate Terraform configurations
410

511
This module is for use with AWS EKS. For details of how a `ServiceAccount` in EKS can assume an IAM role, see the [EKS documentation](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html).
612

7-
This module supports multiple `ServiceAccount` in multiple clusters and/or namespaces. This allows for a single IAM role to be used when an application may span multiple clusters (e.g. for DR) or multiple namespaces (e.g. for canary deployments). The variables `cluster_service_accounts` and `provider_url_sa_pairs` are used for this as follows:
13+
Implementation notes:
14+
15+
- The EKS cluster needs to exist first, in the current AWS account and region
16+
- The key in the `cluster_service_accounts` is the exact name of the EKS cluster
17+
18+
## Basic example
19+
20+
To create an IAM role named `my-app` that can be assumed in EKS cluster `cluster1` by a `ServiceAccount` called `my-serviceaccount` in the `default` namespace:
821

922
```hcl
1023
module "iam_eks_role" {
1124
source = "terraform-aws-modules/iam/aws//modules/iam-eks-role"
1225
26+
role_name = "my-app"
27+
1328
cluster_service_accounts = {
14-
"<EKS cluster name>" = [
15-
"<namespace>:<ServiceAccount name>",
16-
"<namespace>:<another ServiceAccount name>"
17-
]
29+
"cluster1" = ["default:my-serviceaccount"]
1830
}
31+
}
32+
```
1933

20-
provider_url_sa_pairs = {
21-
"<OIDC provider without protocol prefix>" = [
22-
"<namespace>:<ServiceAccount name>",
23-
"<namespace>:<another ServiceAccount name>"
24-
]
34+
## Multi cluster example:
35+
36+
To create an IAM role named `my-app` that can be assumed from:
37+
38+
- EKS cluster `staging-main-1`, namespace `default`, `ServiceAccount` called `my-app-staging`
39+
- EKS cluster `staging-backup-1`, namespace `default`, `ServiceAccount` called `my-app-staging`
40+
41+
```hcl
42+
module "iam_eks_role" {
43+
source = "terraform-aws-modules/iam/aws//modules/iam-eks-role"
44+
45+
role_name = "my-app"
46+
47+
cluster_service_accounts = {
48+
"staging-main-1" = ["default:my-app-staging"]
49+
"staging-backup-1" = ["default:my-app-staging"]
2550
}
2651
}
2752
```
2853

29-
For example, to create an IAM role named `my-app` that can be assumed from the `ServiceAccount` named `my-app-staging` in the namespace `default` and `canary` in EKS cluster named `cluster-main-1`; and also the `ServiceAccount` name `my-app-staging` in the namespace `default` in EKS cluster named `cluster-backup-1`, the configuration would be:
54+
## Multi `ServiceAccount` example
55+
56+
To create an IAM role named `cloudwatch-exporter` that can be assumed in EKS cluster `production-main-1` from:
57+
58+
- namespace `kube-system`, `ServiceAccount` called `cloudwatch-exporter`
59+
- namespace `app1`, `ServiceAccount` called `cloudwatch-exporter`
3060

3161
```hcl
3262
module "iam_eks_role" {
3363
source = "terraform-aws-modules/iam/aws//modules/iam-eks-role"
64+
3465
role_name = "my-app"
3566
3667
cluster_service_accounts = {
37-
"cluster-main-1" = [
38-
"default:my-app-staging",
39-
"canary:my-app-staging"
40-
],
41-
"cluster-backup-1" = [
42-
"default:my-app-staging",
68+
"production-main-1" = [
69+
"kube-system:cloudwatch-exporter",
70+
"app1:cloudwatch-exporter",
4371
]
4472
}
4573
}
4674
```
4775

48-
Note: the EKS clusters must in the current AWS region and account as they use the default AWS provider.
49-
5076
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
5177
## Requirements
5278

@@ -84,7 +110,6 @@ No modules.
84110
| <a name="input_create_role"></a> [create\_role](#input\_create\_role) | Whether to create a role | `bool` | `true` | no |
85111
| <a name="input_force_detach_policies"></a> [force\_detach\_policies](#input\_force\_detach\_policies) | Whether policies should be detached from this role when destroying | `bool` | `false` | no |
86112
| <a name="input_max_session_duration"></a> [max\_session\_duration](#input\_max\_session\_duration) | Maximum CLI/API session duration in seconds between 3600 and 43200 | `number` | `43200` | no |
87-
| <a name="input_provider_url_sa_pairs"></a> [provider\_url\_sa\_pairs](#input\_provider\_url\_sa\_pairs) | OIDC provider URL and k8s ServiceAccount pairs. If the assume role policy requires a mix of EKS clusters and other OIDC providers then this can be used | `map(list(string))` | `{}` | no |
88113
| <a name="input_role_description"></a> [role\_description](#input\_role\_description) | IAM Role description | `string` | `""` | no |
89114
| <a name="input_role_name"></a> [role\_name](#input\_role\_name) | Name of IAM role | `string` | `null` | no |
90115
| <a name="input_role_name_prefix"></a> [role\_name\_prefix](#input\_role\_name\_prefix) | IAM role name prefix | `string` | `null` | no |

modules/iam-eks-role/main.tf

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,30 +32,6 @@ data "aws_iam_policy_document" "assume_role_with_oidc" {
3232
}
3333
}
3434
}
35-
36-
dynamic "statement" {
37-
for_each = var.provider_url_sa_pairs
38-
39-
content {
40-
effect = "Allow"
41-
42-
actions = ["sts:AssumeRoleWithWebIdentity"]
43-
44-
principals {
45-
type = "Federated"
46-
47-
identifiers = [
48-
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${statement.key}"
49-
]
50-
}
51-
52-
condition {
53-
test = "StringEquals"
54-
variable = "${statement.key}:sub"
55-
values = [for s in statement.value : "system:serviceaccount:${s}"]
56-
}
57-
}
58-
}
5935
}
6036

6137
resource "aws_iam_role" "this" {

modules/iam-eks-role/outputs.tf

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
output "iam_role_arn" {
22
description = "ARN of IAM role"
3-
value = element(concat(aws_iam_role.this.*.arn, [""]), 0)
3+
value = try(aws_iam_role.this[0].arn, "")
44
}
55

66
output "iam_role_name" {
77
description = "Name of IAM role"
8-
value = element(concat(aws_iam_role.this.*.name, [""]), 0)
8+
value = try(aws_iam_role.this[0].name, "")
99
}
1010

1111
output "iam_role_path" {
1212
description = "Path of IAM role"
13-
value = element(concat(aws_iam_role.this.*.path, [""]), 0)
13+
value = try(aws_iam_role.this[0].path, "")
1414
}
1515

1616
output "iam_role_unique_id" {
1717
description = "Unique ID of IAM role"
18-
value = element(concat(aws_iam_role.this.*.unique_id, [""]), 0)
18+
value = try(aws_iam_role.this[0].unique_id, "")
1919
}

modules/iam-eks-role/variables.tf

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,6 @@ variable "cluster_service_accounts" {
4646
default = {}
4747
}
4848

49-
variable "provider_url_sa_pairs" {
50-
description = "OIDC provider URL and k8s ServiceAccount pairs. If the assume role policy requires a mix of EKS clusters and other OIDC providers then this can be used"
51-
type = map(list(string))
52-
default = {}
53-
}
54-
5549
variable "tags" {
5650
description = "A map of tags to add the the IAM role"
5751
type = map(any)

0 commit comments

Comments
 (0)