Skip to content

Commit

Permalink
Attempt to fix Invalid for_each argument for `var.custom_iam_policy…
Browse files Browse the repository at this point in the history
…_arns` (#11)

* Fixing logic for lambda function policy

* Fixing logic for lambda function policy

* Fixing logic for lambda function policy

* Fixing logic for lambda function policy

* Fixing logic for lambda function policy

* Auto Format

* Fixing logic for lambda function policy

* Fixing logic for lambda function policy

* Auto Format

* Fixing logic for lambda function policy

* Auto Format

* Fixing logic for lambda function policy

* Fixing logic for lambda function policy

* Fixing logic for lambda function policy

* Auto Format

* Keep for_each and expand tests

* Auto Format

* Update iam-role.tf

* Add role_name output

* Update variables.tf

* Update iam-role.tf

* Auto Format

* Update main.tf

* Add inside/outside and enabled flag

* Update main.tf

* Add context to iam_policy and count to archive

* Auto Format

* Unique policy names

* Auto Format

* Use label, construct string arn

* Add role_arn output

* Auto Format

* Use join splat

* Remove the iam_policy module

* Add count logic to assume_role_policy

* More robust no changes check

* Update common.go

Co-authored-by: cloudpossebot <[email protected]>
Co-authored-by: nitrocode <[email protected]>
  • Loading branch information
3 people authored Apr 22, 2022
1 parent 0406568 commit cb734da
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 8 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ Available targets:
| <a name="input_cloudwatch_logs_kms_key_arn"></a> [cloudwatch\_logs\_kms\_key\_arn](#input\_cloudwatch\_logs\_kms\_key\_arn) | The ARN of the KMS Key to use when encrypting log data. | `string` | `null` | no |
| <a name="input_cloudwatch_logs_retention_in_days"></a> [cloudwatch\_logs\_retention\_in\_days](#input\_cloudwatch\_logs\_retention\_in\_days) | Specifies the number of days you want to retain log events in the specified log group. Possible values are: <br> 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653, and 0. If you select 0, the events in the <br> log group are always retained and never expire. | `number` | `null` | no |
| <a name="input_context"></a> [context](#input\_context) | Single object for setting entire context at once.<br>See description of individual variables for details.<br>Leave string and numeric variables as `null` to use default value.<br>Individual variable settings (non-null) override settings in context object,<br>except for attributes, tags, and additional\_tag\_map, which are merged. | `any` | <pre>{<br> "additional_tag_map": {},<br> "attributes": [],<br> "delimiter": null,<br> "descriptor_formats": {},<br> "enabled": true,<br> "environment": null,<br> "id_length_limit": null,<br> "label_key_case": null,<br> "label_order": [],<br> "label_value_case": null,<br> "labels_as_tags": [<br> "unset"<br> ],<br> "name": null,<br> "namespace": null,<br> "regex_replace_chars": null,<br> "stage": null,<br> "tags": {},<br> "tenant": null<br>}</pre> | no |
| <a name="input_custom_iam_policy_arns"></a> [custom\_iam\_policy\_arns](#input\_custom\_iam\_policy\_arns) | List of custom policies to be attached to the lambda role | `set(string)` | `[]` | no |
| <a name="input_custom_iam_policy_arns"></a> [custom\_iam\_policy\_arns](#input\_custom\_iam\_policy\_arns) | ARNs of custom policies to be attached to the lambda role | `set(string)` | `[]` | no |
| <a name="input_delimiter"></a> [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.<br>Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no |
| <a name="input_description"></a> [description](#input\_description) | Description of what the Lambda Function does. | `string` | `null` | no |
| <a name="input_descriptor_formats"></a> [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.<br>Map of maps. Keys are names of descriptors. Values are maps of the form<br>`{<br> format = string<br> labels = list(string)<br>}`<br>(Type is `any` so the map values can later be enhanced to provide additional options.)<br>`format` is a Terraform format string to be passed to the `format()` function.<br>`labels` is a list of labels, in order, to pass to `format()` function.<br>Label values will be normalized before being passed to `format()` so they will be<br>identical to how they appear in `id`.<br>Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no |
Expand Down Expand Up @@ -238,6 +238,8 @@ Available targets:
| <a name="output_function_name"></a> [function\_name](#output\_function\_name) | Lambda function name |
| <a name="output_invoke_arn"></a> [invoke\_arn](#output\_invoke\_arn) | Inkoke ARN of the lambda function |
| <a name="output_qualified_arn"></a> [qualified\_arn](#output\_qualified\_arn) | ARN identifying your Lambda Function Version (if versioning is enabled via publish = true) |
| <a name="output_role_arn"></a> [role\_arn](#output\_role\_arn) | Lambda IAM role ARN |
| <a name="output_role_name"></a> [role\_name](#output\_role\_name) | Lambda IAM role name |
<!-- markdownlint-restore -->


Expand Down
4 changes: 3 additions & 1 deletion docs/terraform.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
| <a name="input_cloudwatch_logs_kms_key_arn"></a> [cloudwatch\_logs\_kms\_key\_arn](#input\_cloudwatch\_logs\_kms\_key\_arn) | The ARN of the KMS Key to use when encrypting log data. | `string` | `null` | no |
| <a name="input_cloudwatch_logs_retention_in_days"></a> [cloudwatch\_logs\_retention\_in\_days](#input\_cloudwatch\_logs\_retention\_in\_days) | Specifies the number of days you want to retain log events in the specified log group. Possible values are: <br> 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653, and 0. If you select 0, the events in the <br> log group are always retained and never expire. | `number` | `null` | no |
| <a name="input_context"></a> [context](#input\_context) | Single object for setting entire context at once.<br>See description of individual variables for details.<br>Leave string and numeric variables as `null` to use default value.<br>Individual variable settings (non-null) override settings in context object,<br>except for attributes, tags, and additional\_tag\_map, which are merged. | `any` | <pre>{<br> "additional_tag_map": {},<br> "attributes": [],<br> "delimiter": null,<br> "descriptor_formats": {},<br> "enabled": true,<br> "environment": null,<br> "id_length_limit": null,<br> "label_key_case": null,<br> "label_order": [],<br> "label_value_case": null,<br> "labels_as_tags": [<br> "unset"<br> ],<br> "name": null,<br> "namespace": null,<br> "regex_replace_chars": null,<br> "stage": null,<br> "tags": {},<br> "tenant": null<br>}</pre> | no |
| <a name="input_custom_iam_policy_arns"></a> [custom\_iam\_policy\_arns](#input\_custom\_iam\_policy\_arns) | List of custom policies to be attached to the lambda role | `set(string)` | `[]` | no |
| <a name="input_custom_iam_policy_arns"></a> [custom\_iam\_policy\_arns](#input\_custom\_iam\_policy\_arns) | ARNs of custom policies to be attached to the lambda role | `set(string)` | `[]` | no |
| <a name="input_delimiter"></a> [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.<br>Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no |
| <a name="input_description"></a> [description](#input\_description) | Description of what the Lambda Function does. | `string` | `null` | no |
| <a name="input_descriptor_formats"></a> [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.<br>Map of maps. Keys are names of descriptors. Values are maps of the form<br>`{<br> format = string<br> labels = list(string)<br>}`<br>(Type is `any` so the map values can later be enhanced to provide additional options.)<br>`format` is a Terraform format string to be passed to the `format()` function.<br>`labels` is a list of labels, in order, to pass to `format()` function.<br>Label values will be normalized before being passed to `format()` so they will be<br>identical to how they appear in `id`.<br>Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no |
Expand Down Expand Up @@ -103,4 +103,6 @@
| <a name="output_function_name"></a> [function\_name](#output\_function\_name) | Lambda function name |
| <a name="output_invoke_arn"></a> [invoke\_arn](#output\_invoke\_arn) | Inkoke ARN of the lambda function |
| <a name="output_qualified_arn"></a> [qualified\_arn](#output\_qualified\_arn) | ARN identifying your Lambda Function Version (if versioning is enabled via publish = true) |
| <a name="output_role_arn"></a> [role\_arn](#output\_role\_arn) | Lambda IAM role ARN |
| <a name="output_role_name"></a> [role\_name](#output\_role\_name) | Lambda IAM role name |
<!-- markdownlint-restore -->
73 changes: 72 additions & 1 deletion examples/complete/main.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
locals {
enabled = module.this.enabled

# The policy name has to be at least 20 characters
policy_name_inside = "${module.label.id}-inside"
policy_name_outside = "${module.label.id}-outside"

policy_arn_prefix = format(
"arn:%s:iam::%s:policy",
join("", data.aws_partition.current.*.partition),
join("", data.aws_caller_identity.current.*.account_id),
)
policy_arn_inside = format("%s/%s", local.policy_arn_prefix, local.policy_name_inside)

policy_json = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"ec2:Describe*",
]
Effect = "Allow"
Resource = "*"
},
]
})
}

module "label" {
source = "cloudposse/label/null"
version = "0.25.0"
Expand All @@ -6,19 +34,62 @@ module "label" {
context = module.this.context
}

data "aws_partition" "current" {
count = local.enabled ? 1 : 0
}

data "aws_caller_identity" "current" {
count = local.enabled ? 1 : 0
}

data "archive_file" "lambda_zip" {
count = local.enabled ? 1 : 0
type = "zip"
source_file = "handler.js"
output_path = "lambda_function.zip"
}

resource "aws_iam_policy" "inside" {
count = local.enabled ? 1 : 0
name = local.policy_name_inside
path = "/"
description = "My policy attached inside the lambda module"

policy = local.policy_json
}

resource "aws_iam_policy" "outside" {
count = local.enabled ? 1 : 0
name = local.policy_name_outside
path = "/"
description = "My policy attached outside the lambda module"

policy = local.policy_json
}

resource "aws_iam_role_policy_attachment" "outside" {
count = local.enabled ? 1 : 0
role = module.lambda.role_name
policy_arn = aws_iam_policy.outside[0].arn
}

module "lambda" {
source = "../.."

filename = data.archive_file.lambda_zip.output_path
filename = join("", data.archive_file.lambda_zip.*.output_path)
function_name = module.label.id
handler = var.handler
runtime = var.runtime

custom_iam_policy_arns = [
"arn:aws:iam::aws:policy/job-function/ViewOnlyAccess",
local.policy_arn_inside,
# aws_iam_policy.inside[0].id, # This will result in an error message and is why we use local.policy_name_inside
]

context = module.this.context

depends_on = [
aws_iam_policy.inside,
]
}
6 changes: 4 additions & 2 deletions iam-role.tf
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
resource "aws_iam_role" "this" {
count = local.enabled ? 1 : 0
name = "${var.function_name}-${local.region_name}"
assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json
assume_role_policy = join("", data.aws_iam_policy_document.assume_role_policy.*.json)
permissions_boundary = var.permissions_boundary
}

data "aws_iam_policy_document" "assume_role_policy" {
count = local.enabled ? 1 : 0

statement {
actions = ["sts:AssumeRole"]

Expand Down Expand Up @@ -77,4 +79,4 @@ resource "aws_iam_role_policy_attachment" "custom" {
for_each = local.enabled && length(var.custom_iam_policy_arns) > 0 ? var.custom_iam_policy_arns : toset([])
role = aws_iam_role.this[0].name
policy_arn = each.key
}
}
10 changes: 10 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,13 @@ output "function_name" {
description = "Lambda function name"
value = local.enabled ? aws_lambda_function.this[0].function_name : null
}

output "role_name" {
description = "Lambda IAM role name"
value = local.enabled ? aws_iam_role.this[0].name : null
}

output "role_arn" {
description = "Lambda IAM role ARN"
value = local.enabled ? aws_iam_role.this[0].arn : null
}
4 changes: 3 additions & 1 deletion test/src/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"strconv"
"testing"
"time"
"strings"

"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
Expand All @@ -31,6 +32,7 @@ func testNoChanges(t *testing.T, terraformDir string) {

terraform.Init(t, terraformOptions)
plan := terraform.Plan(t, terraformOptions)
planContainsNoChanges := strings.Contains(plan, "No changes.") || strings.Contains(plan, "0 to add, 0 to change, 0 to destroy.")

assert.Contains(t, plan, "No changes.")
assert.True(t, planContainsNoChanges)
}
4 changes: 2 additions & 2 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,6 @@ variable "vpc_config" {

variable "custom_iam_policy_arns" {
type = set(string)
description = "List of custom policies to be attached to the lambda role"
description = "ARNs of custom policies to be attached to the lambda role"
default = []
}
}

0 comments on commit cb734da

Please sign in to comment.