-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add new IAM module iam-eks-role (#179)
- Loading branch information
1 parent
54f327b
commit 61cf542
Showing
12 changed files
with
416 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# IAM EKS role | ||
|
||
Configuration in this directory creates an IAM role that can be assumed by multiple EKS `ServiceAccount`. | ||
|
||
# Usage | ||
|
||
To run this example you need to execute: | ||
|
||
```bash | ||
$ terraform init | ||
$ terraform plan | ||
$ terraform apply | ||
``` | ||
|
||
Run `terraform destroy` when you don't need these resources. | ||
|
||
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK --> | ||
## Requirements | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.12.6 | | ||
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 2.23 | | ||
|
||
## Providers | ||
|
||
No providers. | ||
|
||
## Modules | ||
|
||
| Name | Source | Version | | ||
|------|--------|---------| | ||
| <a name="module_iam_eks_role"></a> [iam\_eks\_role](#module\_iam\_eks\_role) | ../../modules/iam-eks-role | n/a | | ||
|
||
## Resources | ||
|
||
No resources. | ||
|
||
## Inputs | ||
|
||
No inputs. | ||
|
||
## Outputs | ||
|
||
| Name | Description | | ||
|------|-------------| | ||
| <a name="output_iam_role_arn"></a> [iam\_role\_arn](#output\_iam\_role\_arn) | ARN of IAM role | | ||
| <a name="output_iam_role_name"></a> [iam\_role\_name](#output\_iam\_role\_name) | Name of IAM role | | ||
| <a name="output_iam_role_path"></a> [iam\_role\_path](#output\_iam\_role\_path) | Path of IAM role | | ||
| <a name="output_iam_role_unique_id"></a> [iam\_role\_unique\_id](#output\_iam\_role\_unique\_id) | Unique ID of IAM role | | ||
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
provider "aws" { | ||
region = "eu-west-1" | ||
} | ||
|
||
module "iam_eks_role" { | ||
source = "../../modules/iam-eks-role" | ||
role_name = "my-app" | ||
|
||
cluster_service_accounts = { | ||
"cluster1" = ["default:my-app"] | ||
"cluster2" = [ | ||
"default:my-app", | ||
"canary:my-app", | ||
] | ||
} | ||
|
||
provider_url_sa_pairs = { | ||
"oidc.eks.us-east-1.amazonaws.com/id/5C54DDF35ER19312844C7333374CC09D" = ["default:my-app2"] | ||
"oidc.eks.ap-southeast-1.amazonaws.com/id/5C54DDF35ER54476848E7333374FF09G" = [ | ||
"default:my-app2", | ||
"canary:my-app2", | ||
] | ||
} | ||
|
||
tags = { | ||
Name = "eks-role" | ||
} | ||
|
||
role_policy_arns = [ | ||
"arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
output "iam_role_arn" { | ||
description = "ARN of IAM role" | ||
value = module.iam_eks_role.iam_role_arn | ||
} | ||
|
||
output "iam_role_name" { | ||
description = "Name of IAM role" | ||
value = module.iam_eks_role.iam_role_name | ||
} | ||
|
||
output "iam_role_path" { | ||
description = "Path of IAM role" | ||
value = module.iam_eks_role.iam_role_path | ||
} | ||
|
||
output "iam_role_unique_id" { | ||
description = "Unique ID of IAM role" | ||
value = module.iam_eks_role.iam_role_unique_id | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
terraform { | ||
required_version = ">= 0.12.6" | ||
|
||
required_providers { | ||
aws = ">= 2.23" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
# iam-eks-role | ||
|
||
Creates single IAM role which can be assumed by one or more EKS `ServiceAccount` and optionally also OpenID Connect Federated Users. | ||
|
||
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). | ||
|
||
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: | ||
|
||
```hcl | ||
module "iam_eks_role" { | ||
source = "terraform-aws-modules/iam/aws//modules/iam-eks-role" | ||
cluster_service_accounts = { | ||
"<EKS cluster name>" = [ | ||
"<namespace>:<ServiceAccount name>", | ||
"<namespace>:<another ServiceAccount name>" | ||
] | ||
} | ||
provider_url_sa_pairs = { | ||
"<OIDC provider without protocol prefix>" = [ | ||
"<namespace>:<ServiceAccount name>", | ||
"<namespace>:<another ServiceAccount name>" | ||
] | ||
} | ||
``` | ||
|
||
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: | ||
|
||
```hcl | ||
module "iam_eks_role" { | ||
source = "terraform-aws-modules/iam/aws//modules/iam-eks-role" | ||
role_name = "my-app" | ||
cluster_service_accounts = { | ||
"cluster-main-1" = [ | ||
"default:my-app-staging", | ||
"canary:my-app-staging" | ||
] | ||
"cluster-backup-1" = [ | ||
"default:my-app-staging", | ||
] | ||
} | ||
``` | ||
|
||
Note: the EKS clusters must in the current AWS region and account as they use the default AWS provider. | ||
|
||
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK --> | ||
## Requirements | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.12.6 | | ||
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 2.23 | | ||
|
||
## Providers | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 2.23 | | ||
|
||
## Modules | ||
|
||
No modules. | ||
|
||
## Resources | ||
|
||
| Name | Type | | ||
|------|------| | ||
| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | ||
| [aws_iam_role_policy_attachment.custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | ||
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | ||
| [aws_eks_cluster.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/eks_cluster) | data source | | ||
| [aws_iam_policy_document.assume_role_with_oidc](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 | | ||
|
||
## Inputs | ||
|
||
| Name | Description | Type | Default | Required | | ||
|------|-------------|------|---------|:--------:| | ||
| <a name="input_cluster_service_accounts"></a> [cluster\_service\_accounts](#input\_cluster\_service\_accounts) | EKS cluster and k8s ServiceAccount pairs. Each EKS cluster can have multiple k8s ServiceAccount. See README for details | `map(list(string))` | `{}` | no | | ||
| <a name="input_create_role"></a> [create\_role](#input\_create\_role) | Whether to create a role | `bool` | `true` | no | | ||
| <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 | | ||
| <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 | | ||
| <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 | | ||
| <a name="input_role_description"></a> [role\_description](#input\_role\_description) | IAM Role description | `string` | `""` | no | | ||
| <a name="input_role_name"></a> [role\_name](#input\_role\_name) | Name of IAM role | `string` | `null` | no | | ||
| <a name="input_role_name_prefix"></a> [role\_name\_prefix](#input\_role\_name\_prefix) | IAM role name prefix | `string` | `null` | no | | ||
| <a name="input_role_path"></a> [role\_path](#input\_role\_path) | Path of IAM role | `string` | `"/"` | no | | ||
| <a name="input_role_permissions_boundary_arn"></a> [role\_permissions\_boundary\_arn](#input\_role\_permissions\_boundary\_arn) | Permissions boundary ARN to use for IAM role | `string` | `""` | no | | ||
| <a name="input_role_policy_arns"></a> [role\_policy\_arns](#input\_role\_policy\_arns) | ARNs of any policies to attach to the IAM role | `list(string)` | `[]` | no | | ||
| <a name="input_tags"></a> [tags](#input\_tags) | A map of tags to add the the IAM role | `map(any)` | `{}` | no | | ||
|
||
## Outputs | ||
|
||
| Name | Description | | ||
|------|-------------| | ||
| <a name="output_iam_role_arn"></a> [iam\_role\_arn](#output\_iam\_role\_arn) | ARN of IAM role | | ||
| <a name="output_iam_role_name"></a> [iam\_role\_name](#output\_iam\_role\_name) | Name of IAM role | | ||
| <a name="output_iam_role_path"></a> [iam\_role\_path](#output\_iam\_role\_path) | Path of IAM role | | ||
| <a name="output_iam_role_unique_id"></a> [iam\_role\_unique\_id](#output\_iam\_role\_unique\_id) | Unique ID of IAM role | | ||
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
data "aws_caller_identity" "current" {} | ||
|
||
data "aws_partition" "current" {} | ||
|
||
data "aws_eks_cluster" "main" { | ||
for_each = var.cluster_service_accounts | ||
|
||
name = each.key | ||
} | ||
|
||
data "aws_iam_policy_document" "assume_role_with_oidc" { | ||
dynamic "statement" { | ||
for_each = var.cluster_service_accounts | ||
|
||
content { | ||
effect = "Allow" | ||
|
||
actions = ["sts:AssumeRoleWithWebIdentity"] | ||
|
||
principals { | ||
type = "Federated" | ||
|
||
identifiers = [ | ||
"arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${replace(data.aws_eks_cluster.main[statement.key].identity[0].oidc[0].issuer, "https://", "")}" | ||
] | ||
} | ||
|
||
condition { | ||
test = "StringEquals" | ||
variable = "${replace(data.aws_eks_cluster.main[statement.key].identity[0].oidc[0].issuer, "https://", "")}:sub" | ||
values = [for s in statement.value : "system:serviceaccount:${s}"] | ||
} | ||
} | ||
} | ||
|
||
dynamic "statement" { | ||
for_each = var.provider_url_sa_pairs | ||
|
||
content { | ||
effect = "Allow" | ||
|
||
actions = ["sts:AssumeRoleWithWebIdentity"] | ||
|
||
principals { | ||
type = "Federated" | ||
|
||
identifiers = [ | ||
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${statement.key}" | ||
] | ||
} | ||
|
||
condition { | ||
test = "StringEquals" | ||
variable = "${statement.key}:sub" | ||
values = [for s in statement.value : "system:serviceaccount:${s}"] | ||
} | ||
} | ||
} | ||
} | ||
|
||
resource "aws_iam_role" "this" { | ||
count = var.create_role ? 1 : 0 | ||
|
||
assume_role_policy = data.aws_iam_policy_document.assume_role_with_oidc.json | ||
description = var.role_description | ||
force_detach_policies = var.force_detach_policies | ||
max_session_duration = var.max_session_duration | ||
name = var.role_name | ||
name_prefix = var.role_name_prefix | ||
path = var.role_path | ||
permissions_boundary = var.role_permissions_boundary_arn | ||
tags = var.tags | ||
} | ||
|
||
resource "aws_iam_role_policy_attachment" "custom" { | ||
for_each = var.create_role ? toset(var.role_policy_arns) : [] | ||
role = aws_iam_role.this[0].name | ||
policy_arn = each.key | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
output "iam_role_arn" { | ||
description = "ARN of IAM role" | ||
value = element(concat(aws_iam_role.this.*.arn, [""]), 0) | ||
} | ||
|
||
output "iam_role_name" { | ||
description = "Name of IAM role" | ||
value = element(concat(aws_iam_role.this.*.name, [""]), 0) | ||
} | ||
|
||
output "iam_role_path" { | ||
description = "Path of IAM role" | ||
value = element(concat(aws_iam_role.this.*.path, [""]), 0) | ||
} | ||
|
||
output "iam_role_unique_id" { | ||
description = "Unique ID of IAM role" | ||
value = element(concat(aws_iam_role.this.*.unique_id, [""]), 0) | ||
} |
Oops, something went wrong.