Skip to content

Commit cb734da

Browse files
jamengualcloudpossebotnitrocode
authored
Attempt to fix Invalid for_each argument for var.custom_iam_policy_arns (cloudposse#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]>
1 parent 0406568 commit cb734da

File tree

7 files changed

+97
-8
lines changed

7 files changed

+97
-8
lines changed

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ Available targets:
186186
| <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 |
187187
| <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 |
188188
| <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 |
189-
| <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 |
189+
| <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 |
190190
| <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 |
191191
| <a name="input_description"></a> [description](#input\_description) | Description of what the Lambda Function does. | `string` | `null` | no |
192192
| <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 |
@@ -238,6 +238,8 @@ Available targets:
238238
| <a name="output_function_name"></a> [function\_name](#output\_function\_name) | Lambda function name |
239239
| <a name="output_invoke_arn"></a> [invoke\_arn](#output\_invoke\_arn) | Inkoke ARN of the lambda function |
240240
| <a name="output_qualified_arn"></a> [qualified\_arn](#output\_qualified\_arn) | ARN identifying your Lambda Function Version (if versioning is enabled via publish = true) |
241+
| <a name="output_role_arn"></a> [role\_arn](#output\_role\_arn) | Lambda IAM role ARN |
242+
| <a name="output_role_name"></a> [role\_name](#output\_role\_name) | Lambda IAM role name |
241243
<!-- markdownlint-restore -->
242244

243245

docs/terraform.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
| <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 |
5252
| <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 |
5353
| <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 |
54-
| <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 |
54+
| <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 |
5555
| <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 |
5656
| <a name="input_description"></a> [description](#input\_description) | Description of what the Lambda Function does. | `string` | `null` | no |
5757
| <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 |
@@ -103,4 +103,6 @@
103103
| <a name="output_function_name"></a> [function\_name](#output\_function\_name) | Lambda function name |
104104
| <a name="output_invoke_arn"></a> [invoke\_arn](#output\_invoke\_arn) | Inkoke ARN of the lambda function |
105105
| <a name="output_qualified_arn"></a> [qualified\_arn](#output\_qualified\_arn) | ARN identifying your Lambda Function Version (if versioning is enabled via publish = true) |
106+
| <a name="output_role_arn"></a> [role\_arn](#output\_role\_arn) | Lambda IAM role ARN |
107+
| <a name="output_role_name"></a> [role\_name](#output\_role\_name) | Lambda IAM role name |
106108
<!-- markdownlint-restore -->

examples/complete/main.tf

+72-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,31 @@
1+
locals {
2+
enabled = module.this.enabled
3+
4+
# The policy name has to be at least 20 characters
5+
policy_name_inside = "${module.label.id}-inside"
6+
policy_name_outside = "${module.label.id}-outside"
7+
8+
policy_arn_prefix = format(
9+
"arn:%s:iam::%s:policy",
10+
join("", data.aws_partition.current.*.partition),
11+
join("", data.aws_caller_identity.current.*.account_id),
12+
)
13+
policy_arn_inside = format("%s/%s", local.policy_arn_prefix, local.policy_name_inside)
14+
15+
policy_json = jsonencode({
16+
Version = "2012-10-17"
17+
Statement = [
18+
{
19+
Action = [
20+
"ec2:Describe*",
21+
]
22+
Effect = "Allow"
23+
Resource = "*"
24+
},
25+
]
26+
})
27+
}
28+
129
module "label" {
230
source = "cloudposse/label/null"
331
version = "0.25.0"
@@ -6,19 +34,62 @@ module "label" {
634
context = module.this.context
735
}
836

37+
data "aws_partition" "current" {
38+
count = local.enabled ? 1 : 0
39+
}
40+
41+
data "aws_caller_identity" "current" {
42+
count = local.enabled ? 1 : 0
43+
}
44+
945
data "archive_file" "lambda_zip" {
46+
count = local.enabled ? 1 : 0
1047
type = "zip"
1148
source_file = "handler.js"
1249
output_path = "lambda_function.zip"
1350
}
1451

52+
resource "aws_iam_policy" "inside" {
53+
count = local.enabled ? 1 : 0
54+
name = local.policy_name_inside
55+
path = "/"
56+
description = "My policy attached inside the lambda module"
57+
58+
policy = local.policy_json
59+
}
60+
61+
resource "aws_iam_policy" "outside" {
62+
count = local.enabled ? 1 : 0
63+
name = local.policy_name_outside
64+
path = "/"
65+
description = "My policy attached outside the lambda module"
66+
67+
policy = local.policy_json
68+
}
69+
70+
resource "aws_iam_role_policy_attachment" "outside" {
71+
count = local.enabled ? 1 : 0
72+
role = module.lambda.role_name
73+
policy_arn = aws_iam_policy.outside[0].arn
74+
}
75+
1576
module "lambda" {
1677
source = "../.."
1778

18-
filename = data.archive_file.lambda_zip.output_path
79+
filename = join("", data.archive_file.lambda_zip.*.output_path)
1980
function_name = module.label.id
2081
handler = var.handler
2182
runtime = var.runtime
2283

84+
custom_iam_policy_arns = [
85+
"arn:aws:iam::aws:policy/job-function/ViewOnlyAccess",
86+
local.policy_arn_inside,
87+
# aws_iam_policy.inside[0].id, # This will result in an error message and is why we use local.policy_name_inside
88+
]
89+
2390
context = module.this.context
91+
92+
depends_on = [
93+
aws_iam_policy.inside,
94+
]
2495
}

iam-role.tf

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
resource "aws_iam_role" "this" {
22
count = local.enabled ? 1 : 0
33
name = "${var.function_name}-${local.region_name}"
4-
assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json
4+
assume_role_policy = join("", data.aws_iam_policy_document.assume_role_policy.*.json)
55
permissions_boundary = var.permissions_boundary
66
}
77

88
data "aws_iam_policy_document" "assume_role_policy" {
9+
count = local.enabled ? 1 : 0
10+
911
statement {
1012
actions = ["sts:AssumeRole"]
1113

@@ -77,4 +79,4 @@ resource "aws_iam_role_policy_attachment" "custom" {
7779
for_each = local.enabled && length(var.custom_iam_policy_arns) > 0 ? var.custom_iam_policy_arns : toset([])
7880
role = aws_iam_role.this[0].name
7981
policy_arn = each.key
80-
}
82+
}

outputs.tf

+10
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,13 @@ output "function_name" {
1717
description = "Lambda function name"
1818
value = local.enabled ? aws_lambda_function.this[0].function_name : null
1919
}
20+
21+
output "role_name" {
22+
description = "Lambda IAM role name"
23+
value = local.enabled ? aws_iam_role.this[0].name : null
24+
}
25+
26+
output "role_arn" {
27+
description = "Lambda IAM role ARN"
28+
value = local.enabled ? aws_iam_role.this[0].arn : null
29+
}

test/src/common.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"strconv"
66
"testing"
77
"time"
8+
"strings"
89

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

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

35-
assert.Contains(t, plan, "No changes.")
37+
assert.True(t, planContainsNoChanges)
3638
}

variables.tf

+2-2
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,6 @@ variable "vpc_config" {
242242

243243
variable "custom_iam_policy_arns" {
244244
type = set(string)
245-
description = "List of custom policies to be attached to the lambda role"
245+
description = "ARNs of custom policies to be attached to the lambda role"
246246
default = []
247-
}
247+
}

0 commit comments

Comments
 (0)