From d6248e669eed4da38422b1e32babc4cfaae9cc6b Mon Sep 17 00:00:00 2001 From: "Byungjin Park (Claud)" Date: Tue, 6 Jun 2023 00:43:32 +0900 Subject: [PATCH] Improve iam-role module (#69) --- examples/github-trusted-iam-roles/main.tf | 2 +- modules/iam-role/README.md | 60 ++-- modules/iam-role/main.tf | 8 +- modules/iam-role/outputs.tf | 30 -- ...ties.tf => trusted-iam-entity-policies.tf} | 55 ++-- ...s.tf => trusted-oidc-provider-policies.tf} | 34 +-- ...s.tf => trusted-saml-provider-policies.tf} | 34 +-- ...ervices.tf => trusted-service-policies.tf} | 47 ++-- modules/iam-role/variables.tf | 261 ++++++++++++------ 9 files changed, 302 insertions(+), 229 deletions(-) rename modules/iam-role/{trusted-iam-entities.tf => trusted-iam-entity-policies.tf} (64%) rename modules/iam-role/{trusted-oidc-providers.tf => trusted-oidc-provider-policies.tf} (81%) rename modules/iam-role/{trusted-saml-providers.tf => trusted-saml-provider-policies.tf} (79%) rename modules/iam-role/{trusted-services.tf => trusted-service-policies.tf} (66%) diff --git a/examples/github-trusted-iam-roles/main.tf b/examples/github-trusted-iam-roles/main.tf index e9f7ea7..3b324bf 100644 --- a/examples/github-trusted-iam-roles/main.tf +++ b/examples/github-trusted-iam-roles/main.tf @@ -65,7 +65,7 @@ module "role" { description = try(each.value.description, "Managed by Terraform.") path = try(each.value.path, "/") - trusted_oidc_providers = [ + trusted_oidc_provider_policies = [ { url = "token.actions.githubusercontent.com" conditions = [ diff --git a/modules/iam-role/README.md b/modules/iam-role/README.md index 432e472..ed475ea 100644 --- a/modules/iam-role/README.md +++ b/modules/iam-role/README.md @@ -47,42 +47,36 @@ When `pgp_key` is specified as `keybase:username`, make sure that that user has | [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.trusted_entities](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.trusted_iam_entities](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.trusted_oidc_providers](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.trusted_saml_providers](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.trusted_services](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.trusted_iam_entity_policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.trusted_oidc_provider_policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.trusted_saml_provider_policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.trusted_service_policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_partition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [name](#input\_name) | Desired name for the IAM role. | `string` | n/a | yes | -| [assumable\_roles](#input\_assumable\_roles) | List of IAM roles ARNs which can be assumed by the role. | `list(string)` | `[]` | no | -| [conditions](#input\_conditions) | Required conditions to assume the role. |
list(object({
key = string
condition = string
values = list(string)
}))
| `[]` | no | -| [description](#input\_description) | The description of the role. | `string` | `"Managed by Terraform."` | no | -| [effective\_date](#input\_effective\_date) | Allow to assume IAM role only after a specific date and time. | `string` | `null` | no | -| [expiration\_date](#input\_expiration\_date) | Allow to assume IAM role only before a specific date and time. | `string` | `null` | no | -| [force\_detach\_policies](#input\_force\_detach\_policies) | Specifies to force detaching any policies the role has before destroying it. | `bool` | `false` | no | -| [inline\_policies](#input\_inline\_policies) | Map of inline IAM policies to attach to IAM role. (`name` => `policy`). | `map(string)` | `{}` | no | -| [instance\_profile\_enabled](#input\_instance\_profile\_enabled) | Controls if Instance Profile should be created. | `bool` | `false` | no | -| [max\_session\_duration](#input\_max\_session\_duration) | Maximum CLI/API session duration in seconds between 3600 and 43200. | `number` | `3600` | no | -| [mfa\_required](#input\_mfa\_required) | Whether MFA should be required to assume the role. | `bool` | `false` | no | -| [mfa\_ttl](#input\_mfa\_ttl) | Max age of valid MFA (in seconds) for roles which require MFA. | `number` | `86400` | no | -| [module\_tags\_enabled](#input\_module\_tags\_enabled) | Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | -| [path](#input\_path) | Desired path for the IAM role. | `string` | `"/"` | no | -| [permissions\_boundary](#input\_permissions\_boundary) | The ARN of the policy that is used to set the permissions boundary for the role. | `string` | `null` | no | -| [policies](#input\_policies) | List of IAM policies ARNs to attach to IAM role. | `list(string)` | `[]` | no | -| [resource\_group\_description](#input\_resource\_group\_description) | The description of Resource Group. | `string` | `"Managed by Terraform."` | no | -| [resource\_group\_enabled](#input\_resource\_group\_enabled) | Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | -| [resource\_group\_name](#input\_resource\_group\_name) | The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | -| [source\_ip\_blacklist](#input\_source\_ip\_blacklist) | A list of source IP addresses or CIDRs denied to assume IAM role from. | `list(string)` | `[]` | no | -| [source\_ip\_whitelist](#input\_source\_ip\_whitelist) | A list of source IP addresses or CIDRs allowed to assume IAM role from. | `list(string)` | `[]` | no | -| [tags](#input\_tags) | A map of tags to add to all resources. | `map(string)` | `{}` | no | -| [trusted\_iam\_entities](#input\_trusted\_iam\_entities) | A list of ARNs of AWS IAM entities who can assume the role. | `list(string)` | `[]` | no | -| [trusted\_oidc\_providers](#input\_trusted\_oidc\_providers) | (Optional) A list of configurations of OIDC identity providers. Each value of `trusted_oidc_providers` as defined below.
(Required) `url` - The URL of the OIDC identity provider. If the provider is not common, the corresponding IAM OIDC Provider should be created before. Supported common OIDC providers are `accounts.google.com`, `cognito-identity.amazonaws.com`, `graph.facebook.com`, `www.amazon.com`.
(Optional) `conditions` - A list of required conditions to assume the role via OIDC providers.
(Required) `key` - The OIDC key to match a condition for when a policy is in effect.
(Required) `condition` - The condition operator to match the condition keys and values in the policy against keys and values in the request context. Examples: `StringEquals`, `StringLike`.
(Optional) `values` - A list of allowed values of OIDC key to match a condition with condition operator. |
list(object({
url = string
conditions = optional(list(object({
key = string
condition = string
values = list(string)
})), [])
}))
| `[]` | no | -| [trusted\_saml\_providers](#input\_trusted\_saml\_providers) | (Optional) A list of configurations of SAML identity providers. Each value of `trusted_saml_providers` as defined below.
(Required) `name` - The name of the SAML identity provider.
(Optional) `conditions` - A list of required conditions to assume the role via SAML providers.
(Required) `key` - The SAML key to match a condition for when a policy is in effect.
(Required) `condition` - The condition operator to match the condition keys and values in the policy against keys and values in the request context. Examples: `StringEquals`, `StringLike`.
(Optional) `values` - A list of allowed values of SAML key to match a condition with condition operator. |
list(object({
name = string
conditions = optional(list(object({
key = string
condition = string
values = list(string)
})), [])
}))
| `[]` | no | -| [trusted\_services](#input\_trusted\_services) | AWS Services that can assume the role. | `list(string)` | `[]` | no | +| [name](#input\_name) | (Required) Desired name for the IAM role. | `string` | n/a | yes | +| [assumable\_roles](#input\_assumable\_roles) | (Optional) List of IAM roles ARNs which can be assumed by the role. | `list(string)` | `[]` | no | +| [conditions](#input\_conditions) | (Required) A list of required conditions to assume the role. Each item of `conditions` is defined below.
(Required) `key` - The key to match a condition for when a policy is in effect.
(Required) `condition` - The condition operator to match the condition keys and values in the policy against keys and values in the request context. Examples: `StringEquals`, `StringLike`.
(Required) `values` - A list of allowed values of the key to match a condition with condition operator. |
list(object({
key = string
condition = string
values = list(string)
}))
| `[]` | no | +| [description](#input\_description) | (Optional) The description of the role. | `string` | `"Managed by Terraform."` | no | +| [force\_detach\_policies](#input\_force\_detach\_policies) | (Optional) Specifies to force detaching any policies the role has before destroying it. Defaults to `false`. | `bool` | `false` | no | +| [inline\_policies](#input\_inline\_policies) | (Optional) Map of inline IAM policies to attach to IAM role. (`name` => `policy`). | `map(string)` | `{}` | no | +| [instance\_profile\_enabled](#input\_instance\_profile\_enabled) | (Optional) Controls if Instance Profile should be created. | `bool` | `false` | no | +| [max\_session\_duration](#input\_max\_session\_duration) | (Optional) Maximum session duration (in seconds) that you want to set for the specified role. Valid value is from 1 hour (`3600`) to 12 hours (`43200`). Defaults to `3600`. | `number` | `3600` | no | +| [module\_tags\_enabled](#input\_module\_tags\_enabled) | (Optional) Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | +| [path](#input\_path) | (Optional) Desired path for the IAM role. | `string` | `"/"` | no | +| [permissions\_boundary](#input\_permissions\_boundary) | (Optional) The ARN of the policy that is used to set the permissions boundary for the role. | `string` | `null` | no | +| [policies](#input\_policies) | (Optional) List of IAM policies ARNs to attach to IAM role. | `list(string)` | `[]` | no | +| [resource\_group\_description](#input\_resource\_group\_description) | (Optional) The description of Resource Groupolicy. | `string` | `"Managed by Terraform."` | no | +| [resource\_group\_enabled](#input\_resource\_group\_enabled) | (Optional) Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | +| [resource\_group\_name](#input\_resource\_group\_name) | (Optional) The name of Resource Groupolicy. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | +| [tags](#input\_tags) | (Optional) A map of tags to add to all resources. | `map(string)` | `{}` | no | +| [trusted\_iam\_entity\_policies](#input\_trusted\_iam\_entity\_policies) | (Optional) A configuration for trusted iam entity policies. Each item of `trusted_iam_entity_policies` is defined below.
(Required) `iam_entities` - A list of ARNs of AWS IAM entities who can assume the role.
(Optional) `conditions` - A list of required conditions to assume the role via IAM entities.
(Required) `key` - The key to match a condition for when a policy is in effect.
(Required) `condition` - The condition operator to match the condition keys and values in the policy against keys and values in the request context. Examples: `StringEquals`, `StringLike`.
(Required) `values` - A list of allowed values of the key to match a condition with condition operator.
(Optional) `mfa` - A configuration of MFA requirement.
(Optional) `required` - Whether to require MFA to assume role. Defaults to `false`.
(Optional) `ttl` - Max age of valid MFA (in seconds) for roles which require MFA. Defaults to `86400` (24 hours).
(Optional) `effective_date` - Allow to assume IAM role only after a specific date and time.
(Optional) `expiration_date` - Allow to assume IAM role only before a specific date and time.
(Optional) `source_ip_whitelist` - A list of source IP addresses or CIDRs allowed to assume IAM role from.
(Optional) `source_ip_blacklist` - A list of source IP addresses or CIDRs not allowed to assume IAM role from. |
list(object({
iam_entities = list(string)
conditions = optional(list(object({
key = string
condition = string
values = list(string)
})), [])
mfa = optional(object({
required = optional(bool, false)
ttl = optional(number, 24 * 60 * 60)
}), {})
effective_date = optional(string)
expiration_date = optional(string)
source_ip_whitelist = optional(list(string), [])
source_ip_blacklist = optional(list(string), [])
}))
| `[]` | no | +| [trusted\_oidc\_provider\_policies](#input\_trusted\_oidc\_provider\_policies) | (Optional) A configuration for trusted OIDC identity provider policies. Each item of `trusted_oidc_provider_policies` is defined below.
(Required) `url` - The URL of the OIDC identity provider. If the provider is not common, the corresponding IAM OIDC Provider should be created before. Supported common OIDC providers are `accounts.google.com`, `cognito-identity.amazonaws.com`, `graph.facebook.com`, `www.amazon.com`.
(Optional) `conditions` - A list of required conditions to assume the role via OIDC providers.
(Required) `key` - The OIDC key to match a condition for when a policy is in effect.
(Required) `condition` - The condition operator to match the condition keys and values in the policy against keys and values in the request context. Examples: `StringEquals`, `StringLike`.
(Required) `values` - A list of allowed values of OIDC key to match a condition with condition operator.
(Optional) `effective_date` - Allow to assume IAM role only after a specific date and time.
(Optional) `expiration_date` - Allow to assume IAM role only before a specific date and time.
(Optional) `source_ip_whitelist` - A list of source IP addresses or CIDRs allowed to assume IAM role from.
(Optional) `source_ip_blacklist` - A list of source IP addresses or CIDRs not allowed to assume IAM role from. |
list(object({
url = string
conditions = optional(list(object({
key = string
condition = string
values = list(string)
})), [])
effective_date = optional(string)
expiration_date = optional(string)
source_ip_whitelist = optional(list(string), [])
source_ip_blacklist = optional(list(string), [])
}))
| `[]` | no | +| [trusted\_saml\_provider\_policies](#input\_trusted\_saml\_provider\_policies) | (Optional) A configuration for trusted SAML identity provider policies. Each item of `trusted_saml_provider_policies` is defined below.
(Required) `name` - The name of the SAML identity provider.
(Optional) `conditions` - A list of required conditions to assume the role via SAML providers.
(Required) `key` - The SAML key to match a condition for when a policy is in effect.
(Required) `condition` - The condition operator to match the condition keys and values in the policy against keys and values in the request context. Examples: `StringEquals`, `StringLike`.
(Required) `values` - A list of allowed values of SAML key to match a condition with condition operator.
(Optional) `effective_date` - Allow to assume IAM role only after a specific date and time.
(Optional) `expiration_date` - Allow to assume IAM role only before a specific date and time.
(Optional) `source_ip_whitelist` - A list of source IP addresses or CIDRs allowed to assume IAM role from.
(Optional) `source_ip_blacklist` - A list of source IP addresses or CIDRs not allowed to assume IAM role from. |
list(object({
name = string
conditions = optional(list(object({
key = string
condition = string
values = list(string)
})), [])
effective_date = optional(string)
expiration_date = optional(string)
source_ip_whitelist = optional(list(string), [])
source_ip_blacklist = optional(list(string), [])
}))
| `[]` | no | +| [trusted\_service\_policies](#input\_trusted\_service\_policies) | (Optional) A configuration for trusted service policies. Each item of `trusted_service_policies` is defined below.
(Required) `services` - A list of AWS services that can assume the role.
(Optional) `conditions` - A list of required conditions to assume the role via AWS services.
(Required) `key` - The key to match a condition for when a policy is in effect.
(Required) `condition` - The condition operator to match the condition keys and values in the policy against keys and values in the request context. Examples: `StringEquals`, `StringLike`.
(Required) `values` - A list of allowed values of the key to match a condition with condition operator.
(Optional) `effective_date` - Allow to assume IAM role only after a specific date and time.
(Optional) `expiration_date` - Allow to assume IAM role only before a specific date and time.
(Optional) `source_ip_whitelist` - A list of source IP addresses or CIDRs allowed to assume IAM role from.
(Optional) `source_ip_blacklist` - A list of source IP addresses or CIDRs not allowed to assume IAM role from. |
list(object({
services = list(string)
conditions = optional(list(object({
key = string
condition = string
values = list(string)
})), [])
effective_date = optional(string)
expiration_date = optional(string)
source_ip_whitelist = optional(list(string), [])
source_ip_blacklist = optional(list(string), [])
}))
| `[]` | no | | [trusted\_session\_tagging](#input\_trusted\_session\_tagging) | (Optional) A configurations of session tags in AWS STS. `trusted_session_tagging` block as defined below.
(Optional) `enabled` - Indicate whether you want to enable session tagging. Defaults to `true`.
(Optional) `allowed_tags` - A map of tag key/values pairs to limit the tag keys and values that can be used as session tags.
(Optional) `allowed_transitive_tag_keys` - A set of tag keys to limit the maximum set of transitive tags. |
object({
enabled = optional(bool, true)
allowed_tags = optional(map(set(string)), {})
allowed_transitive_tag_keys = optional(set(string), [])
})
| `{}` | no | | [trusted\_source\_identity](#input\_trusted\_source\_identity) | (Optional) A configurations of source identity in AWS STS. `trusted_source_identity` block as defined below.
(Optional) `enabled` - Indicate whether you want to enable source identity configuration. Defaults to `true`.
(Optional) `allowed_identities` - A set of identities to limit the maximum set of source identities. |
object({
enabled = optional(bool, true)
allowed_identities = optional(set(string), [])
})
| `{}` | no | @@ -93,17 +87,11 @@ When `pgp_key` is specified as `keybase:username`, make sure that that user has | [arn](#output\_arn) | The ARN assigned by AWS for this role. | | [assumable\_roles](#output\_assumable\_roles) | List of ARNs of IAM roles which members of IAM role can assume. | | [description](#output\_description) | The description of the role. | -| [effective\_date](#output\_effective\_date) | Allow to assume IAM role only after this date and time. | -| [expiration\_date](#output\_expiration\_date) | Allow to assume IAM role only before this date and time. | | [inline\_policies](#output\_inline\_policies) | List of names of inline IAM polices which are attached to IAM role. | | [instance\_profile\_arn](#output\_instance\_profile\_arn) | The ARN assigned by AWS for the Instance Profile. | | [instance\_profile\_name](#output\_instance\_profile\_name) | IAM Instance Profile name. | | [instance\_profile\_unique\_id](#output\_instance\_profile\_unique\_id) | The unique ID assigned by AWS for the Instance Profile. | -| [mfa\_required](#output\_mfa\_required) | Whether MFA should be required to assume the role. | -| [mfa\_ttl](#output\_mfa\_ttl) | Max age of valid MFA (in seconds) for roles which require MFA. | | [name](#output\_name) | IAM Role name. | | [policies](#output\_policies) | List of ARNs of IAM policies which are atached to IAM role. | -| [source\_ip\_blacklist](#output\_source\_ip\_blacklist) | A list of source IP addresses or CIDRs denied to assume IAM role from. | -| [source\_ip\_whitelist](#output\_source\_ip\_whitelist) | A list of source IP addresses or CIDRs allowed to assume IAM role from. | | [unique\_id](#output\_unique\_id) | The unique ID assigned by AWS. | diff --git a/modules/iam-role/main.tf b/modules/iam-role/main.tf index 5d39327..8e895d3 100644 --- a/modules/iam-role/main.tf +++ b/modules/iam-role/main.tf @@ -40,10 +40,10 @@ resource "aws_iam_role" "this" { data "aws_iam_policy_document" "trusted_entities" { source_policy_documents = concat( - values(data.aws_iam_policy_document.trusted_iam_entities)[*].json, - values(data.aws_iam_policy_document.trusted_services)[*].json, - values(data.aws_iam_policy_document.trusted_oidc_providers)[*].json, - values(data.aws_iam_policy_document.trusted_saml_providers)[*].json, + values(data.aws_iam_policy_document.trusted_iam_entity_policies)[*].json, + values(data.aws_iam_policy_document.trusted_service_policies)[*].json, + values(data.aws_iam_policy_document.trusted_oidc_provider_policies)[*].json, + values(data.aws_iam_policy_document.trusted_saml_provider_policies)[*].json, ) } diff --git a/modules/iam-role/outputs.tf b/modules/iam-role/outputs.tf index df90363..79b0d3c 100644 --- a/modules/iam-role/outputs.tf +++ b/modules/iam-role/outputs.tf @@ -18,36 +18,6 @@ output "description" { value = aws_iam_role.this.description } -output "mfa_required" { - description = "Whether MFA should be required to assume the role." - value = var.mfa_required -} - -output "mfa_ttl" { - description = "Max age of valid MFA (in seconds) for roles which require MFA." - value = var.mfa_ttl -} - -output "effective_date" { - description = "Allow to assume IAM role only after this date and time." - value = var.effective_date -} - -output "expiration_date" { - description = "Allow to assume IAM role only before this date and time." - value = var.expiration_date -} - -output "source_ip_whitelist" { - description = "A list of source IP addresses or CIDRs allowed to assume IAM role from." - value = var.source_ip_whitelist -} - -output "source_ip_blacklist" { - description = "A list of source IP addresses or CIDRs denied to assume IAM role from." - value = var.source_ip_blacklist -} - output "assumable_roles" { description = "List of ARNs of IAM roles which members of IAM role can assume." value = var.assumable_roles diff --git a/modules/iam-role/trusted-iam-entities.tf b/modules/iam-role/trusted-iam-entity-policies.tf similarity index 64% rename from modules/iam-role/trusted-iam-entities.tf rename to modules/iam-role/trusted-iam-entity-policies.tf index 9a19ae8..a37e635 100644 --- a/modules/iam-role/trusted-iam-entities.tf +++ b/modules/iam-role/trusted-iam-entity-policies.tf @@ -1,16 +1,17 @@ -data "aws_iam_policy_document" "trusted_iam_entities" { - for_each = toset( - length(var.trusted_iam_entities) > 0 ? ["this"] : [] - ) +data "aws_iam_policy_document" "trusted_iam_entity_policies" { + for_each = { + for idx, policy in var.trusted_iam_entity_policies : + idx => policy + } statement { - sid = "TrustedIamEntities" + sid = "TrustedIamEntities${each.key}" effect = "Allow" actions = ["sts:AssumeRole"] principals { type = "AWS" - identifiers = var.trusted_iam_entities + identifiers = each.value.iam_entities } dynamic "condition" { @@ -24,62 +25,72 @@ data "aws_iam_policy_document" "trusted_iam_entities" { } dynamic "condition" { - for_each = var.mfa_required ? ["go"] : [] + for_each = each.value.conditions + + content { + variable = condition.value.key + test = condition.value.condition + values = condition.value.values + } + } + + dynamic "condition" { + for_each = each.value.mfa.required ? ["go"] : [] content { test = "Bool" variable = "aws:MultiFactorAuthPresent" - values = [tostring(var.mfa_required)] + values = [tostring(each.value.mfa.required)] } } dynamic "condition" { - for_each = var.mfa_required ? ["go"] : [] + for_each = each.value.mfa.required ? ["go"] : [] content { test = "NumericLessThan" variable = "aws:MultiFactorAuthAge" - values = [var.mfa_ttl] + values = [each.value.mfa.ttl] } } dynamic "condition" { - for_each = var.effective_date != null ? ["go"] : [] + for_each = each.value.effective_date != null ? ["go"] : [] content { test = "DateGreaterThan" variable = "aws:CurrentTime" - values = [var.effective_date] + values = [each.value.effective_date] } } dynamic "condition" { - for_each = var.expiration_date != null ? ["go"] : [] + for_each = each.value.expiration_date != null ? ["go"] : [] content { test = "DateLessThan" variable = "aws:CurrentTime" - values = [var.expiration_date] + values = [each.value.expiration_date] } } dynamic "condition" { - for_each = length(var.source_ip_whitelist) > 0 ? ["go"] : [] + for_each = length(each.value.source_ip_whitelist) > 0 ? ["go"] : [] content { test = "IpAddress" variable = "aws:SourceIp" - values = var.source_ip_whitelist + values = each.value.source_ip_whitelist } } dynamic "condition" { - for_each = length(var.source_ip_blacklist) > 0 ? ["go"] : [] + for_each = length(each.value.source_ip_blacklist) > 0 ? ["go"] : [] content { test = "NotIpAddress" variable = "aws:SourceIp" - values = var.source_ip_blacklist + values = each.value.source_ip_blacklist } } } @@ -88,13 +99,13 @@ data "aws_iam_policy_document" "trusted_iam_entities" { for_each = var.trusted_session_tagging.enabled ? ["go"] : [] content { - sid = "TrustedTagSession" + sid = "TrustedTagSessionForIamEntities${each.key}" effect = "Allow" actions = ["sts:TagSession"] principals { type = "AWS" - identifiers = var.trusted_iam_entities + identifiers = each.value.iam_entities } dynamic "condition" { @@ -123,13 +134,13 @@ data "aws_iam_policy_document" "trusted_iam_entities" { for_each = var.trusted_source_identity.enabled ? ["go"] : [] content { - sid = "TrustedSourceIdentity" + sid = "TrustedSourceIdentityForIamEntities${each.key}" effect = "Allow" actions = ["sts:SetSourceIdentity"] principals { type = "AWS" - identifiers = var.trusted_iam_entities + identifiers = each.value.iam_entities } dynamic "condition" { diff --git a/modules/iam-role/trusted-oidc-providers.tf b/modules/iam-role/trusted-oidc-provider-policies.tf similarity index 81% rename from modules/iam-role/trusted-oidc-providers.tf rename to modules/iam-role/trusted-oidc-provider-policies.tf index 11bea70..48d9110 100644 --- a/modules/iam-role/trusted-oidc-providers.tf +++ b/modules/iam-role/trusted-oidc-provider-policies.tf @@ -8,10 +8,10 @@ locals { oidc_provider_arn_prefix = "arn:${local.partition}:iam::${local.account_id}:oidc-provider/" } -data "aws_iam_policy_document" "trusted_oidc_providers" { +data "aws_iam_policy_document" "trusted_oidc_provider_policies" { for_each = { - for idx, provider in var.trusted_oidc_providers : - idx => provider + for idx, policy in var.trusted_oidc_provider_policies : + idx => policy } statement { @@ -29,62 +29,62 @@ data "aws_iam_policy_document" "trusted_oidc_providers" { } dynamic "condition" { - for_each = each.value.conditions + for_each = var.conditions content { - variable = "${each.value.url}:${condition.value.key}" + variable = condition.value.key test = condition.value.condition values = condition.value.values } } dynamic "condition" { - for_each = var.conditions + for_each = each.value.conditions content { - variable = condition.value.key + variable = "${each.value.url}:${condition.value.key}" test = condition.value.condition values = condition.value.values } } dynamic "condition" { - for_each = var.effective_date != null ? ["go"] : [] + for_each = each.value.effective_date != null ? ["go"] : [] content { test = "DateGreaterThan" variable = "aws:CurrentTime" - values = [var.effective_date] + values = [each.value.effective_date] } } dynamic "condition" { - for_each = var.expiration_date != null ? ["go"] : [] + for_each = each.value.expiration_date != null ? ["go"] : [] content { test = "DateLessThan" variable = "aws:CurrentTime" - values = [var.expiration_date] + values = [each.value.expiration_date] } } dynamic "condition" { - for_each = length(var.source_ip_whitelist) > 0 ? ["go"] : [] + for_each = length(each.value.source_ip_whitelist) > 0 ? ["go"] : [] content { test = "IpAddress" variable = "aws:SourceIp" - values = var.source_ip_whitelist + values = each.value.source_ip_whitelist } } dynamic "condition" { - for_each = length(var.source_ip_blacklist) > 0 ? ["go"] : [] + for_each = length(each.value.source_ip_blacklist) > 0 ? ["go"] : [] content { test = "NotIpAddress" variable = "aws:SourceIp" - values = var.source_ip_blacklist + values = each.value.source_ip_blacklist } } } @@ -93,7 +93,7 @@ data "aws_iam_policy_document" "trusted_oidc_providers" { for_each = var.trusted_session_tagging.enabled ? ["go"] : [] content { - sid = "TrustedTagSession${each.key}" + sid = "TrustedTagSessionForOidcProvider${each.key}" effect = "Allow" actions = ["sts:TagSession"] @@ -132,7 +132,7 @@ data "aws_iam_policy_document" "trusted_oidc_providers" { for_each = var.trusted_source_identity.enabled ? ["go"] : [] content { - sid = "TrustedSourceIdentity${each.key}" + sid = "TrustedSourceIdentityForOidcProvider${each.key}" effect = "Allow" actions = ["sts:SetSourceIdentity"] diff --git a/modules/iam-role/trusted-saml-providers.tf b/modules/iam-role/trusted-saml-provider-policies.tf similarity index 79% rename from modules/iam-role/trusted-saml-providers.tf rename to modules/iam-role/trusted-saml-provider-policies.tf index 2008165..7a2044b 100644 --- a/modules/iam-role/trusted-saml-providers.tf +++ b/modules/iam-role/trusted-saml-provider-policies.tf @@ -2,10 +2,10 @@ locals { saml_provider_arn_prefix = "arn:${local.partition}:iam::${local.account_id}:saml-provider/" } -data "aws_iam_policy_document" "trusted_saml_providers" { +data "aws_iam_policy_document" "trusted_saml_provider_policies" { for_each = { - for idx, provider in var.trusted_saml_providers : - idx => provider + for idx, policy in var.trusted_saml_provider_policies : + idx => policy } statement { @@ -19,62 +19,62 @@ data "aws_iam_policy_document" "trusted_saml_providers" { } dynamic "condition" { - for_each = each.value.conditions + for_each = var.conditions content { - variable = "saml:${condition.value.key}" + variable = condition.value.key test = condition.value.condition values = condition.value.values } } dynamic "condition" { - for_each = var.conditions + for_each = each.value.conditions content { - variable = condition.value.key + variable = "saml:${condition.value.key}" test = condition.value.condition values = condition.value.values } } dynamic "condition" { - for_each = var.effective_date != null ? ["go"] : [] + for_each = each.value.effective_date != null ? ["go"] : [] content { test = "DateGreaterThan" variable = "aws:CurrentTime" - values = [var.effective_date] + values = [each.value.effective_date] } } dynamic "condition" { - for_each = var.expiration_date != null ? ["go"] : [] + for_each = each.value.expiration_date != null ? ["go"] : [] content { test = "DateLessThan" variable = "aws:CurrentTime" - values = [var.expiration_date] + values = [each.value.expiration_date] } } dynamic "condition" { - for_each = length(var.source_ip_whitelist) > 0 ? ["go"] : [] + for_each = length(each.value.source_ip_whitelist) > 0 ? ["go"] : [] content { test = "IpAddress" variable = "aws:SourceIp" - values = var.source_ip_whitelist + values = each.value.source_ip_whitelist } } dynamic "condition" { - for_each = length(var.source_ip_blacklist) > 0 ? ["go"] : [] + for_each = length(each.value.source_ip_blacklist) > 0 ? ["go"] : [] content { test = "NotIpAddress" variable = "aws:SourceIp" - values = var.source_ip_blacklist + values = each.value.source_ip_blacklist } } } @@ -83,7 +83,7 @@ data "aws_iam_policy_document" "trusted_saml_providers" { for_each = var.trusted_session_tagging.enabled ? ["go"] : [] content { - sid = "TrustedTagSession${each.key}" + sid = "TrustedTagSessionSamlProvider${each.key}" effect = "Allow" actions = ["sts:TagSession"] @@ -118,7 +118,7 @@ data "aws_iam_policy_document" "trusted_saml_providers" { for_each = var.trusted_source_identity.enabled ? ["go"] : [] content { - sid = "TrustedSourceIdentity${each.key}" + sid = "TrustedSourceIdentityForSamlProvider${each.key}" effect = "Allow" actions = ["sts:SetSourceIdentity"] diff --git a/modules/iam-role/trusted-services.tf b/modules/iam-role/trusted-service-policies.tf similarity index 66% rename from modules/iam-role/trusted-services.tf rename to modules/iam-role/trusted-service-policies.tf index 0b50c9e..e3bf73f 100644 --- a/modules/iam-role/trusted-services.tf +++ b/modules/iam-role/trusted-service-policies.tf @@ -1,16 +1,17 @@ -data "aws_iam_policy_document" "trusted_services" { - for_each = toset( - length(var.trusted_services) > 0 ? ["this"] : [] - ) +data "aws_iam_policy_document" "trusted_service_policies" { + for_each = { + for idx, policy in var.trusted_service_policies : + idx => policy + } statement { - sid = "TrustedServices" + sid = "TrustedServices${each.key}" effect = "Allow" actions = ["sts:AssumeRole"] principals { type = "Service" - identifiers = var.trusted_services + identifiers = each.value.services } dynamic "condition" { @@ -24,42 +25,52 @@ data "aws_iam_policy_document" "trusted_services" { } dynamic "condition" { - for_each = var.effective_date != null ? ["go"] : [] + for_each = each.value.conditions + + content { + variable = condition.value.key + test = condition.value.condition + values = condition.value.values + } + } + + dynamic "condition" { + for_each = each.value.effective_date != null ? ["go"] : [] content { test = "DateGreaterThan" variable = "aws:CurrentTime" - values = [var.effective_date] + values = [each.value.effective_date] } } dynamic "condition" { - for_each = var.expiration_date != null ? ["go"] : [] + for_each = each.value.expiration_date != null ? ["go"] : [] content { test = "DateLessThan" variable = "aws:CurrentTime" - values = [var.expiration_date] + values = [each.value.expiration_date] } } dynamic "condition" { - for_each = length(var.source_ip_whitelist) > 0 ? ["go"] : [] + for_each = length(each.value.source_ip_whitelist) > 0 ? ["go"] : [] content { test = "IpAddress" variable = "aws:SourceIp" - values = var.source_ip_whitelist + values = each.value.source_ip_whitelist } } dynamic "condition" { - for_each = length(var.source_ip_blacklist) > 0 ? ["go"] : [] + for_each = length(each.value.source_ip_blacklist) > 0 ? ["go"] : [] content { test = "NotIpAddress" variable = "aws:SourceIp" - values = var.source_ip_blacklist + values = each.value.source_ip_blacklist } } } @@ -68,13 +79,13 @@ data "aws_iam_policy_document" "trusted_services" { for_each = var.trusted_session_tagging.enabled ? ["go"] : [] content { - sid = "TrustedTagSession" + sid = "TrustedTagSessionForServices${each.key}" effect = "Allow" actions = ["sts:TagSession"] principals { type = "Service" - identifiers = var.trusted_services + identifiers = each.value.services } dynamic "condition" { @@ -103,13 +114,13 @@ data "aws_iam_policy_document" "trusted_services" { for_each = var.trusted_source_identity.enabled ? ["go"] : [] content { - sid = "TrustedSourceIdentity" + sid = "TrustedSourceIdentityForServices${each.key}" effect = "Allow" actions = ["sts:SetSourceIdentity"] principals { type = "Service" - identifiers = var.trusted_services + identifiers = each.value.services } dynamic "condition" { diff --git a/modules/iam-role/variables.tf b/modules/iam-role/variables.tf index 62b4d03..d073fea 100644 --- a/modules/iam-role/variables.tf +++ b/modules/iam-role/variables.tf @@ -1,38 +1,39 @@ variable "name" { - description = "Desired name for the IAM role." + description = "(Required) Desired name for the IAM role." type = string + nullable = false } variable "path" { - description = "Desired path for the IAM role." + description = "(Optional) Desired path for the IAM role." type = string default = "/" nullable = false } variable "description" { - description = "The description of the role." + description = "(Optional) The description of the role." type = string default = "Managed by Terraform." nullable = false } variable "max_session_duration" { - description = "Maximum CLI/API session duration in seconds between 3600 and 43200." + description = "(Optional) Maximum session duration (in seconds) that you want to set for the specified role. Valid value is from 1 hour (`3600`) to 12 hours (`43200`). Defaults to `3600`." type = number default = 3600 nullable = false } variable "force_detach_policies" { - description = "Specifies to force detaching any policies the role has before destroying it." + description = "(Optional) Specifies to force detaching any policies the role has before destroying it. Defaults to `false`." type = bool default = false nullable = false } variable "permissions_boundary" { - description = "The ARN of the policy that is used to set the permissions boundary for the role." + description = "(Optional) The ARN of the policy that is used to set the permissions boundary for the role." type = string default = null } @@ -67,29 +68,121 @@ variable "trusted_source_identity" { nullable = false } -variable "trusted_iam_entities" { - description = "A list of ARNs of AWS IAM entities who can assume the role." - type = list(string) - default = [] - nullable = false +variable "trusted_iam_entity_policies" { + description = <