Skip to content

Commit 39c90e6

Browse files
ROSAENG-57757 | feat: add trust_policy_external_id to account-iam-resources
Inject optional sts:ExternalId into installer and support account role trust policies, expose module input/output, and regenerate module documentation. Part of ROSA-786. Signed-off-by: michaelryanmcneill <michael@michaelryanmcneill.com>
1 parent 7ddac04 commit 39c90e6

5 files changed

Lines changed: 306 additions & 21 deletions

File tree

modules/account-iam-resources/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ module "account_iam_resources" {
5656
| [null_resource.validate_openshift_version](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
5757
| [random_string.default_random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource |
5858
| [time_sleep.account_iam_resources_wait](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource |
59-
| [aws_iam_policy_document.custom_trust_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
6059
| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source |
6160
| [rhcs_info.current](https://registry.terraform.io/providers/terraform-redhat/rhcs/latest/docs/data-sources/info) | data source |
6261
| [rhcs_policies.all_policies](https://registry.terraform.io/providers/terraform-redhat/rhcs/latest/docs/data-sources/policies) | data source |
@@ -71,13 +70,16 @@ module "account_iam_resources" {
7170
| <a name="input_path"></a> [path](#input\_path) | The ARN path for the account/operator roles as well as their policies. | `string` | `"/"` | no |
7271
| <a name="input_permissions_boundary"></a> [permissions\_boundary](#input\_permissions\_boundary) | The ARN of the policy that is used to set the permissions boundary for the IAM roles in STS clusters. | `string` | `""` | no |
7372
| <a name="input_tags"></a> [tags](#input\_tags) | List of AWS resource tags to apply. | `map(string)` | `null` | no |
73+
| <a name="input_trust_policy_external_id"></a> [trust\_policy\_external\_id](#input\_trust\_policy\_external\_id) | External ID for trust policy condition in installer and support account roles. | `string` | `null` | no |
7474

7575
## Outputs
7676

7777
| Name | Description |
7878
| ---- | ----------- |
7979
| <a name="output_account_role_prefix"></a> [account\_role\_prefix](#output\_account\_role\_prefix) | The prefix used for all generated AWS resources. |
8080
| <a name="output_account_roles_arn"></a> [account\_roles\_arn](#output\_account\_roles\_arn) | A map of Amazon Resource Names (ARNs) associated with the AWS IAM roles created. The key in the map represents the name of an AWS IAM role, while the corresponding value represents the associated Amazon Resource Name (ARN) of that role. |
81+
| <a name="output_custom_trust_policy_json"></a> [custom\_trust\_policy\_json](#output\_custom\_trust\_policy\_json) | Rendered IAM trust policy JSON for each account role (Installer, Support, Worker, ControlPlane order). |
8182
| <a name="output_openshift_version"></a> [openshift\_version](#output\_openshift\_version) | The Openshift cluster version of the cluster those account roles are used for. |
8283
| <a name="output_path"></a> [path](#output\_path) | The arn path for the account/operator roles as well as their policies. |
84+
| <a name="output_trust_policy_external_id"></a> [trust\_policy\_external\_id](#output\_trust\_policy\_external\_id) | External ID for trust policy condition in account roles |
8385
<!-- END_AUTOMATED_TF_DOCS_BLOCK -->

modules/account-iam-resources/main.tf

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@
44
locals {
55
path = coalesce(var.path, "/")
66
short_openshift_version = format("%s.%s", split(".", var.openshift_version)[0], split(".", var.openshift_version)[1])
7+
trust_policy_external_id = (
8+
var.trust_policy_external_id != null && var.trust_policy_external_id != ""
9+
) ? var.trust_policy_external_id : null
710
account_roles_properties = [
811
{
912
role_name = "Installer"
1013
role_type = "installer"
1114
policy_details = data.rhcs_policies.all_policies.account_role_policies["sts_installer_permission_policy"]
1215
principal_type = "AWS"
1316
principal_identifier = "arn:${data.aws_partition.current.partition}:iam::${data.rhcs_info.current.ocm_aws_account_id}:role/RH-Managed-OpenShift-Installer"
17+
external_id = local.trust_policy_external_id
1418
},
1519
{
1620
role_name = "Support"
@@ -19,24 +23,30 @@ locals {
1923
principal_type = "AWS"
2024
// This is a SRE RH Support role which is used to assume this support role
2125
principal_identifier = data.rhcs_policies.all_policies.account_role_policies["sts_support_rh_sre_role"]
26+
external_id = local.trust_policy_external_id
2227
},
2328
{
2429
role_name = "Worker"
2530
role_type = "instance_worker"
2631
policy_details = data.rhcs_policies.all_policies.account_role_policies["sts_instance_worker_permission_policy"]
2732
principal_type = "Service"
2833
principal_identifier = "ec2.amazonaws.com"
34+
external_id = null
2935
},
3036
{
3137
role_name = "ControlPlane"
3238
role_type = "instance_controlplane"
3339
policy_details = data.rhcs_policies.all_policies.account_role_policies["sts_instance_controlplane_permission_policy"]
3440
principal_type = "Service"
3541
principal_identifier = "ec2.amazonaws.com"
42+
external_id = null
3643
}
3744
]
3845
account_roles_count = null_resource.validate_openshift_version != null ? length(local.account_roles_properties) : 0
39-
patch_version_list = [for s in data.rhcs_versions.all_versions.items : s.name]
46+
patch_version_list = distinct(concat(
47+
[for s in data.rhcs_versions.all_versions.items : s.name],
48+
try([data.rhcs_versions.all_versions.item.name], []),
49+
))
4050
minor_version_list = length(local.patch_version_list) > 0 ? (
4151
distinct([for s in local.patch_version_list : format("%s.%s", split(".", s)[0], split(".", s)[1])])
4252
) : (
@@ -47,19 +57,31 @@ locals {
4757
) : (
4858
"account-role-${random_string.default_random[0].result}"
4959
)
50-
}
51-
52-
data "aws_iam_policy_document" "custom_trust_policy" {
53-
count = local.account_roles_count
54-
55-
statement {
56-
effect = "Allow"
57-
actions = ["sts:AssumeRole"]
58-
principals {
59-
type = local.account_roles_properties[count.index].principal_type
60-
identifiers = [local.account_roles_properties[count.index].principal_identifier]
61-
}
62-
}
60+
custom_trust_policy_json = [
61+
for idx in range(local.account_roles_count) : jsonencode({
62+
Version = "2012-10-17"
63+
Statement = [
64+
merge(
65+
{
66+
Effect = "Allow"
67+
Action = "sts:AssumeRole"
68+
Principal = local.account_roles_properties[idx].principal_type == "AWS" ? {
69+
AWS = local.account_roles_properties[idx].principal_identifier
70+
} : {
71+
Service = local.account_roles_properties[idx].principal_identifier
72+
}
73+
},
74+
local.account_roles_properties[idx].external_id != null ? {
75+
Condition = {
76+
StringEquals = {
77+
"sts:ExternalId" = local.account_roles_properties[idx].external_id
78+
}
79+
}
80+
} : {}
81+
)
82+
]
83+
})
84+
]
6385
}
6486

6587
module "account_iam_role" {
@@ -77,7 +99,7 @@ module "account_iam_role" {
7799
role_permissions_boundary_arn = var.permissions_boundary
78100

79101
create_custom_role_trust_policy = true
80-
custom_role_trust_policy = data.aws_iam_policy_document.custom_trust_policy[count.index].json
102+
custom_role_trust_policy = local.custom_trust_policy_json[count.index]
81103

82104
tags = merge(var.tags, {
83105
red-hat-managed = true
@@ -140,11 +162,12 @@ resource "time_sleep" "account_iam_resources_wait" {
140162
destroy_duration = "10s"
141163
create_duration = "10s"
142164
triggers = {
143-
account_iam_role_name = jsonencode([for value in aws_iam_role_policy_attachment.role_policy_attachment : value.role])
144-
account_roles_arn = jsonencode({ for idx, value in module.account_iam_role : local.account_roles_properties[idx].role_name => value.iam_role_arn })
145-
account_role_prefix = local.account_role_prefix_valid
146-
openshift_version = var.openshift_version
147-
path = var.path
165+
account_iam_role_name = jsonencode([for value in aws_iam_role_policy_attachment.role_policy_attachment : value.role])
166+
account_roles_arn = jsonencode({ for idx, value in module.account_iam_role : local.account_roles_properties[idx].role_name => value.iam_role_arn })
167+
account_role_prefix = local.account_role_prefix_valid
168+
openshift_version = var.openshift_version
169+
path = var.path
170+
trust_policy_external_id = local.trust_policy_external_id
148171
}
149172
}
150173

modules/account-iam-resources/outputs.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,13 @@ output "path" {
2020
value = time_sleep.account_iam_resources_wait.triggers["path"]
2121
description = "The arn path for the account/operator roles as well as their policies."
2222
}
23+
24+
output "trust_policy_external_id" {
25+
value = time_sleep.account_iam_resources_wait.triggers["trust_policy_external_id"]
26+
description = "External ID for trust policy condition in account roles"
27+
}
28+
29+
output "custom_trust_policy_json" {
30+
value = local.custom_trust_policy_json
31+
description = "Rendered IAM trust policy JSON for each account role (Installer, Support, Worker, ControlPlane order)."
32+
}

0 commit comments

Comments
 (0)