Skip to content

Commit c334a54

Browse files
authored
feat: Add iam-assumable-role-with-saml module (#127)
1 parent 60d30cc commit c334a54

File tree

12 files changed

+360
-0
lines changed

12 files changed

+360
-0
lines changed

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,29 @@ module "iam_assumable_role_with_oidc" {
8585
}
8686
```
8787

88+
`iam-assumable-role-with-saml`:
89+
```hcl
90+
module "iam_assumable_role_with_saml" {
91+
source = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-saml"
92+
version = "~> 3.0"
93+
94+
create_role = true
95+
96+
role_name = "role-with-saml"
97+
98+
tags = {
99+
Role = "role-with-saml"
100+
}
101+
102+
provider_id = "arn:aws:iam::235367859851:saml-provider/idp_saml"
103+
104+
role_policy_arns = [
105+
"arn:aws:iam::aws:policy/ReadOnlyAccess"
106+
]
107+
number_of_role_policy_arns = 1
108+
}
109+
```
110+
88111
`iam-assumable-roles`:
89112
```hcl
90113
module "iam_assumable_roles" {
@@ -255,6 +278,7 @@ Use [iam-policy module](https://github.com/terraform-aws-modules/terraform-aws-i
255278
* [iam-account](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-account) - Set AWS account alias and password policy
256279
* [iam-assumable-role](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-assumable-role) - Create individual IAM role which can be assumed from specified ARNs (AWS accounts, IAM users, etc)
257280
* [iam-assumable-role-with-oidc](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-assumable-role-with-oidc) - Create individual IAM role which can be assumed from specified subjects federated with a OIDC Identity Provider
281+
* [iam-assumable-role-with-saml](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-assumable-role-with-saml) - Create individual IAM role which can be assumed by users with a SAML Identity Provider
258282
* [iam-assumable-roles](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-assumable-roles) - Create several IAM roles which can be assumed from specified ARNs (AWS accounts, IAM users, etc)
259283
* [iam-assumable-roles-with-saml](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-assumable-roles-with-saml) - Create several IAM roles which can be assumed by users with a SAML Identity Provider
260284
* [iam-group-with-assumable-roles-policy](https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/examples/iam-group-with-assumable-roles-policy) - IAM group with users who are allowed to assume IAM roles in the same or in separate AWS account
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Individual IAM assumable role with SAML Identity Provider example
2+
3+
Configuration in this directory creates a single IAM role which can be assumed by users with a SAML Identity Provider.
4+
5+
# Usage
6+
7+
To run this example you need to execute:
8+
9+
```bash
10+
$ terraform init
11+
$ terraform plan
12+
$ terraform apply
13+
```
14+
15+
Run `terraform destroy` when you don't need these resources.
16+
17+
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
18+
## Requirements
19+
20+
| Name | Version |
21+
|------|---------|
22+
| terraform | >= 0.12.6 |
23+
| aws | >= 2.23 |
24+
25+
## Providers
26+
27+
| Name | Version |
28+
|------|---------|
29+
| aws | >= 2.23 |
30+
31+
## Modules
32+
33+
| Name | Source | Version |
34+
|------|--------|---------|
35+
| iam_assumable_role_admin | ../../modules/iam-assumable-role-with-saml | |
36+
37+
## Resources
38+
39+
| Name |
40+
|------|
41+
| [aws_iam_saml_provider](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_saml_provider) |
42+
43+
## Inputs
44+
45+
No input.
46+
47+
## Outputs
48+
49+
| Name | Description |
50+
|------|-------------|
51+
| this\_iam\_role\_arn | ARN of IAM role |
52+
| this\_iam\_role\_name | Name of IAM role |
53+
| this\_iam\_role\_path | Path of IAM role |
54+
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
provider "aws" {
2+
region = "eu-west-1"
3+
}
4+
5+
resource "aws_iam_saml_provider" "idp_saml" {
6+
name = "idp_saml"
7+
saml_metadata_document = file("saml-metadata.xml")
8+
}
9+
10+
resource "aws_iam_saml_provider" "second_idp_saml" {
11+
name = "second_idp_saml"
12+
saml_metadata_document = file("saml-metadata.xml")
13+
}
14+
15+
###############################
16+
# IAM assumable role for admin
17+
###############################
18+
module "iam_assumable_role_admin" {
19+
source = "../../modules/iam-assumable-role-with-saml"
20+
21+
create_role = true
22+
23+
role_name = "role-with-saml"
24+
25+
tags = {
26+
Role = "role-with-saml"
27+
}
28+
29+
provider_id = aws_iam_saml_provider.idp_saml.id
30+
provider_ids = [aws_iam_saml_provider.second_idp_saml.id]
31+
32+
role_policy_arns = [
33+
"arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy",
34+
]
35+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
output "this_iam_role_arn" {
2+
description = "ARN of IAM role"
3+
value = module.iam_assumable_role_admin.this_iam_role_arn
4+
}
5+
6+
output "this_iam_role_name" {
7+
description = "Name of IAM role"
8+
value = module.iam_assumable_role_admin.this_iam_role_name
9+
}
10+
11+
output "this_iam_role_path" {
12+
description = "Path of IAM role"
13+
value = module.iam_assumable_role_admin.this_iam_role_path
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="https://terraform-dev-ed.my.salesforce.com" validUntil="2025-09-02T18:27:19.710Z">
2+
<md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
3+
<md:KeyDescriptor use="signing">
4+
<ds:KeyInfo>
5+
<ds:X509Data>
6+
<ds:X509Certificate>MIIErDCCA5SgAwIBAgIOAU+PT8RBAAAAAHxJXEcwDQYJKoZIhvcNAQELBQAwgZAxKDAmBgNVBAMMH1NlbGZTaWduZWRDZXJ0XzAyU2VwMjAxNV8xODI2NTMxGDAWBgNVBAsMDzAwRDI0MDAwMDAwcEFvQTEXMBUGA1UECgwOU2FsZXNmb3JjZS5jb20xFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xCzAJBgNVBAgMAkNBMQwwCgYDVQQGEwNVU0EwHhcNMTUwOTAyMTgyNjUzWhcNMTcwOTAyMTIwMDAwWjCBkDEoMCYGA1UEAwwfU2VsZlNpZ25lZENlcnRfMDJTZXAyMDE1XzE4MjY1MzEYMBYGA1UECwwPMDBEMjQwMDAwMDBwQW9BMRcwFQYDVQQKDA5TYWxlc2ZvcmNlLmNvbTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzELMAkGA1UECAwCQ0ExDDAKBgNVBAYTA1VTQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJp/wTRr9n1IWJpkRTjNpep47OKJrD2E6rGbJ18TG2RxtIz+zCn2JwH2aP3TULh0r0hhcg/pecv51RRcG7O19DBBaTQ5+KuoICQyKZy07/yDXSiZontTwkEYs06ssTwTHUcRXbcwTKv16L7omt0MjIhTTGfvtLOYiPwyvKvzAHg4eNuAcli0duVM78UIBORtdmy9C9ZcMh8yRJo5aPBq85wsE3JXU58ytyZzCHTBLH+2xFQrjYnUSEW+FOEEpI7o33MVdFBvWWg1R17HkWzcve4C30lqOHqvxBzyESZ/N1mMlmSt8gPFyB+mUXY99StJDJpnytbY8DwSzMQUo/sOVB0CAwEAAaOCAQAwgf0wHQYDVR0OBBYEFByu1EQqRQS0bYQBKS9K5qwKi+6IMA8GA1UdEwEB/wQFMAMBAf8wgcoGA1UdIwSBwjCBv4AUHK7URCpFBLRthAEpL0rmrAqL7oihgZakgZMwgZAxKDAmBgNVBAMMH1NlbGZTaWduZWRDZXJ0XzAyU2VwMjAxNV8xODI2NTMxGDAWBgNVBAsMDzAwRDI0MDAwMDAwcEFvQTEXMBUGA1UECgwOU2FsZXNmb3JjZS5jb20xFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xCzAJBgNVBAgMAkNBMQwwCgYDVQQGEwNVU0GCDgFPj0/EQQAAAAB8SVxHMA0GCSqGSIb3DQEBCwUAA4IBAQA9O5o1tC71qJnkq+ABPo4A1aFKZVT/07GcBX4/wetcbYySL4Q2nR9pMgfPYYS1j+P2E3viPsQwPIWDUBwFkNsjjX5DSGEkLAioVGKRwJshRSCSynMcsVZbQkfBUiZXqhM0wzvoa/ALvGD+aSSb1m+x7lEpDYNwQKWaUW2VYcHWv9wjujMyy7dlj8E/jqM71mw7ThNl6k4+3RQ802dMa14txm8pkF0vZgfpV3tkqhBqtjBAicVCaveqr3r3iGqjvyilBgdY+0NR8szqzm7CD/Bkb22+/IgM/mXQuL9KHD/WADlSGmYKmG3SSahmcZxznYCnzcRNN9LVuXlz5cbljmBj</ds:X509Certificate>
7+
</ds:X509Data>
8+
</ds:KeyInfo>
9+
</md:KeyDescriptor>
10+
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
11+
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://terraform-dev-ed.my.salesforce.com/idp/endpoint/HttpPost"/>
12+
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://terraform-dev-ed.my.salesforce.com/idp/endpoint/HttpRedirect"/>
13+
</md:IDPSSODescriptor>
14+
</md:EntityDescriptor>

examples/iam-assumable-role-with-saml/variables.tf

Whitespace-only changes.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
terraform {
2+
required_version = ">= 0.12.6"
3+
4+
required_providers {
5+
aws = ">= 2.23"
6+
}
7+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# iam-assumable-role-with-saml
2+
3+
Creates single IAM role which can be assumed by trusted resources using SAML Federated Users.
4+
5+
[Creating IAM SAML Identity Providers](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml.html)
6+
[Enabling SAML 2.0 Federated Users to Access the AWS Management Console](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-saml.html)
7+
8+
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
9+
## Requirements
10+
11+
| Name | Version |
12+
|------|---------|
13+
| terraform | >= 0.12.6 |
14+
| aws | >= 2.23 |
15+
16+
## Providers
17+
18+
| Name | Version |
19+
|------|---------|
20+
| aws | >= 2.23 |
21+
22+
## Modules
23+
24+
No Modules.
25+
26+
## Resources
27+
28+
| Name |
29+
|------|
30+
| [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) |
31+
| [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) |
32+
| [aws_iam_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) |
33+
34+
## Inputs
35+
36+
| Name | Description | Type | Default | Required |
37+
|------|-------------|------|---------|:--------:|
38+
| aws\_saml\_endpoint | AWS SAML Endpoint | `string` | `"https://signin.aws.amazon.com/saml"` | no |
39+
| create\_role | Whether to create a role | `bool` | `false` | no |
40+
| force\_detach\_policies | Whether policies should be detached from this role when destroying | `bool` | `false` | no |
41+
| max\_session\_duration | Maximum CLI/API session duration in seconds between 3600 and 43200 | `number` | `3600` | no |
42+
| number\_of\_role\_policy\_arns | Number of IAM policies to attach to IAM role | `number` | `null` | no |
43+
| provider\_id | ID of the SAML Provider. Use provider\_ids to specify several IDs. | `string` | `""` | no |
44+
| provider\_ids | List of SAML Provider IDs | `list(string)` | `[]` | no |
45+
| role\_description | IAM Role description | `string` | `""` | no |
46+
| role\_name | IAM role name | `string` | `null` | no |
47+
| role\_name\_prefix | IAM role name prefix | `string` | `null` | no |
48+
| role\_path | Path of IAM role | `string` | `"/"` | no |
49+
| role\_permissions\_boundary\_arn | Permissions boundary ARN to use for IAM role | `string` | `""` | no |
50+
| role\_policy\_arns | List of ARNs of IAM policies to attach to IAM role | `list(string)` | `[]` | no |
51+
| tags | A map of tags to add to IAM role resources | `map(string)` | `{}` | no |
52+
53+
## Outputs
54+
55+
| Name | Description |
56+
|------|-------------|
57+
| this\_iam\_role\_arn | ARN of IAM role |
58+
| this\_iam\_role\_name | Name of IAM role |
59+
| this\_iam\_role\_path | Path of IAM role |
60+
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
locals {
2+
identifiers = compact(distinct(concat(var.provider_ids, [var.provider_id])))
3+
number_of_role_policy_arns = coalesce(var.number_of_role_policy_arns, length(var.role_policy_arns))
4+
}
5+
6+
data "aws_iam_policy_document" "assume_role_with_saml" {
7+
statement {
8+
effect = "Allow"
9+
10+
actions = ["sts:AssumeRoleWithSAML"]
11+
12+
principals {
13+
type = "Federated"
14+
15+
identifiers = local.identifiers
16+
}
17+
18+
condition {
19+
test = "StringEquals"
20+
variable = "SAML:aud"
21+
values = [var.aws_saml_endpoint]
22+
}
23+
}
24+
}
25+
26+
resource "aws_iam_role" "this" {
27+
count = var.create_role ? 1 : 0
28+
29+
name = var.role_name
30+
name_prefix = var.role_name_prefix
31+
description = var.role_description
32+
path = var.role_path
33+
max_session_duration = var.max_session_duration
34+
35+
force_detach_policies = var.force_detach_policies
36+
permissions_boundary = var.role_permissions_boundary_arn
37+
38+
assume_role_policy = data.aws_iam_policy_document.assume_role_with_saml.json
39+
40+
tags = var.tags
41+
}
42+
43+
resource "aws_iam_role_policy_attachment" "custom" {
44+
count = var.create_role ? local.number_of_role_policy_arns : 0
45+
46+
role = join("", aws_iam_role.this.*.name)
47+
policy_arn = var.role_policy_arns[count.index]
48+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
output "this_iam_role_arn" {
2+
description = "ARN of IAM role"
3+
value = element(concat(aws_iam_role.this.*.arn, [""]), 0)
4+
}
5+
6+
output "this_iam_role_name" {
7+
description = "Name of IAM role"
8+
value = element(concat(aws_iam_role.this.*.name, [""]), 0)
9+
}
10+
11+
output "this_iam_role_path" {
12+
description = "Path of IAM role"
13+
value = element(concat(aws_iam_role.this.*.path, [""]), 0)
14+
}

0 commit comments

Comments
 (0)