Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1c2dfd7

Browse files
igor-raitsbryantbiggs
andauthored
feat: Implement user inline policy for iam-user (#607)
Co-authored-by: Bryant Biggs <bryantbiggs@gmail.com>
1 parent 03d1b49 commit 1c2dfd7

File tree

9 files changed

+171
-25
lines changed

9 files changed

+171
-25
lines changed

‎examples/iam-user/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# AWS IAM User Example
22

3-
Configuration in this directory creates an IAM user with a random password, a pair of IAM access/secret keys and uploads IAM SSH public key.
3+
Configuration in this directory creates an IAM user with a random password, a pair of IAM access/secret keys, uploads IAM SSH public key, and demonstrates inline policy creation.
44
User password and secret key is encrypted using public key of keybase.io user named `test`.
55

66
# Usage

‎examples/iam-user/main.tf

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,30 @@ module "iam_user2" {
4545
create_login_profile = false
4646
create_access_key = true
4747

48+
create_inline_policy = true
49+
inline_policy_permissions = {
50+
s3_read_access = {
51+
effect = "Allow"
52+
actions = [
53+
"s3:GetObject",
54+
"s3:ListBucket"
55+
]
56+
resources = [
57+
"arn:aws:s3:::example-bucket",
58+
"arn:aws:s3:::example-bucket/*"
59+
]
60+
}
61+
cloudwatch_logs = {
62+
effect = "Allow"
63+
actions = [
64+
"logs:CreateLogGroup",
65+
"logs:CreateLogStream",
66+
"logs:PutLogEvents"
67+
]
68+
resources = ["*"]
69+
}
70+
}
71+
4872
tags = local.tags
4973
}
5074

‎modules/iam-role-for-service-accounts/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
> Upgrade to use EKS Pod Identity instead of IRSA
55
> A similar module for EKS Pod Identity is available [here](https://github.com/terraform-aws-modules/terraform-aws-eks-pod-identity).
66
7-
> [!INFO]
7+
> [!IMPORTANT]
88
> The [karpenter](https://github.com/terraform-aws-modules/terraform-aws-eks/tree/master/modules/karpenter) sub-module contains the necessary AWS resources for running Karpenter, including the Karpenter controller IAM role & policy
99
1010
Creates an IAM role which can be assumed by AWS EKS `ServiceAccount`s with optional policies for commonly used controllers/custom resources within EKS. The optional policies supported include:

‎modules/iam-role-for-service-accounts/main.tf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,11 @@ resource "aws_iam_role_policy_attachment" "this" {
207207
################################################################################
208208

209209
locals {
210-
create_iam_role_inline_policy = var.create && var.create_inline_policy
210+
create_inline_policy = var.create && var.create_inline_policy
211211
}
212212

213213
data "aws_iam_policy_document" "inline" {
214-
count = local.create_iam_role_inline_policy ? 1 : 0
214+
count = local.create_inline_policy ? 1 : 0
215215

216216
source_policy_documents = var.source_inline_policy_documents
217217
override_policy_documents = var.override_inline_policy_documents
@@ -259,7 +259,7 @@ data "aws_iam_policy_document" "inline" {
259259
}
260260

261261
resource "aws_iam_role_policy" "inline" {
262-
count = local.create_iam_role_inline_policy ? 1 : 0
262+
count = local.create_inline_policy ? 1 : 0
263263

264264
role = aws_iam_role.this[0].name
265265
name = var.use_name_prefix ? null : var.name

‎modules/iam-role/main.tf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,11 +306,11 @@ resource "aws_iam_role_policy_attachment" "this" {
306306
################################################################################
307307

308308
locals {
309-
create_iam_role_inline_policy = var.create && var.create_inline_policy
309+
create_inline_policy = var.create && var.create_inline_policy
310310
}
311311

312312
data "aws_iam_policy_document" "inline" {
313-
count = local.create_iam_role_inline_policy ? 1 : 0
313+
count = local.create_inline_policy ? 1 : 0
314314

315315
source_policy_documents = var.source_inline_policy_documents
316316
override_policy_documents = var.override_inline_policy_documents
@@ -358,7 +358,7 @@ data "aws_iam_policy_document" "inline" {
358358
}
359359

360360
resource "aws_iam_role_policy" "inline" {
361-
count = local.create_iam_role_inline_policy ? 1 : 0
361+
count = local.create_inline_policy ? 1 : 0
362362

363363
role = aws_iam_role.this[0].name
364364
name = var.use_name_prefix ? null : var.name

‎modules/iam-user/README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# AWS IAM User Terraform Module
22

3-
Creates an IAM user with ability to create a login profile, access key, and SSH key.
3+
Creates an IAM user with ability to create a login profile, access key, SSH key, and inline policies.
44

55
## Usage
66

@@ -52,8 +52,10 @@ No modules.
5252
| [aws_iam_access_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_access_key) | resource |
5353
| [aws_iam_user.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user) | resource |
5454
| [aws_iam_user_login_profile.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_login_profile) | resource |
55+
| [aws_iam_user_policy.inline](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy) | resource |
5556
| [aws_iam_user_policy_attachment.additional](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy_attachment) | resource |
5657
| [aws_iam_user_ssh_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_ssh_key) | resource |
58+
| [aws_iam_policy_document.inline](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
5759

5860
## Inputs
5961

@@ -62,16 +64,20 @@ No modules.
6264
| <a name="input_access_key_status"></a> [access\_key\_status](#input\_access\_key\_status) | Access key status to apply | `string` | `null` | no |
6365
| <a name="input_create"></a> [create](#input\_create) | Controls if resources should be created (affects all resources) | `bool` | `true` | no |
6466
| <a name="input_create_access_key"></a> [create\_access\_key](#input\_create\_access\_key) | Whether to create IAM access key | `bool` | `true` | no |
67+
| <a name="input_create_inline_policy"></a> [create\_inline\_policy](#input\_create\_inline\_policy) | Determines whether to create an inline policy | `bool` | `false` | no |
6568
| <a name="input_create_login_profile"></a> [create\_login\_profile](#input\_create\_login\_profile) | Whether to create IAM user login profile | `bool` | `true` | no |
6669
| <a name="input_create_ssh_key"></a> [create\_ssh\_key](#input\_create\_ssh\_key) | Whether to upload a public ssh key to the IAM user | `bool` | `false` | no |
6770
| <a name="input_force_destroy"></a> [force\_destroy](#input\_force\_destroy) | When destroying this user, destroy even if it has non-Terraform-managed IAM access keys, login profile or MFA devices. Without force\_destroy a user with non-Terraform-managed access keys and login profile will fail to be destroyed | `bool` | `false` | no |
71+
| <a name="input_inline_policy_permissions"></a> [inline\_policy\_permissions](#input\_inline\_policy\_permissions) | A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for inline policy permissions | <pre>map(object({<br/> sid = optional(string)<br/> actions = optional(list(string))<br/> not_actions = optional(list(string))<br/> effect = optional(string, "Allow")<br/> resources = optional(list(string))<br/> not_resources = optional(list(string))<br/> principals = optional(list(object({<br/> type = string<br/> identifiers = list(string)<br/> })))<br/> not_principals = optional(list(object({<br/> type = string<br/> identifiers = list(string)<br/> })))<br/> condition = optional(list(object({<br/> test = string<br/> variable = string<br/> values = list(string)<br/> })))<br/> }))</pre> | `null` | no |
6872
| <a name="input_name"></a> [name](#input\_name) | Desired name for the IAM user | `string` | `""` | no |
73+
| <a name="input_override_inline_policy_documents"></a> [override\_inline\_policy\_documents](#input\_override\_inline\_policy\_documents) | List of IAM policy documents that are merged together into the exported document. In merging, statements with non-blank `sid`s will override statements with the same `sid` | `list(string)` | `[]` | no |
6974
| <a name="input_password_length"></a> [password\_length](#input\_password\_length) | The length of the generated password | `number` | `null` | no |
7075
| <a name="input_password_reset_required"></a> [password\_reset\_required](#input\_password\_reset\_required) | Whether the user should be forced to reset the generated password on first login | `bool` | `true` | no |
7176
| <a name="input_path"></a> [path](#input\_path) | Desired path for the IAM user | `string` | `null` | no |
7277
| <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 user | `string` | `null` | no |
7378
| <a name="input_pgp_key"></a> [pgp\_key](#input\_pgp\_key) | Either a base-64 encoded PGP public key, or a keybase username in the form `keybase:username`. Used to encrypt password and access key | `string` | `null` | no |
7479
| <a name="input_policies"></a> [policies](#input\_policies) | Policies to attach to the IAM user in `{'static_name' = 'policy_arn'}` format | `map(string)` | `{}` | no |
80+
| <a name="input_source_inline_policy_documents"></a> [source\_inline\_policy\_documents](#input\_source\_inline\_policy\_documents) | List of IAM policy documents that are merged together into the exported document. Statements must have unique `sid`s | `list(string)` | `[]` | no |
7581
| <a name="input_ssh_key_encoding"></a> [ssh\_key\_encoding](#input\_ssh\_key\_encoding) | Specifies the public key encoding format to use in the response. To retrieve the public key in ssh-rsa format, use SSH. To retrieve the public key in PEM format, use PEM | `string` | `"SSH"` | no |
7682
| <a name="input_ssh_public_key"></a> [ssh\_public\_key](#input\_ssh\_public\_key) | The SSH public key. The public key must be encoded in ssh-rsa format or PEM format | `string` | `""` | no |
7783
| <a name="input_tags"></a> [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no |

‎modules/iam-user/main.tf

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,70 @@ resource "aws_iam_user_policy_attachment" "additional" {
2020
policy_arn = each.value
2121
}
2222

23+
################################################################################
24+
# IAM User Inline policy
25+
################################################################################
26+
27+
locals {
28+
create_inline_policy = var.create && var.create_inline_policy
29+
}
30+
31+
data "aws_iam_policy_document" "inline" {
32+
count = local.create_inline_policy ? 1 : 0
33+
34+
source_policy_documents = var.source_inline_policy_documents
35+
override_policy_documents = var.override_inline_policy_documents
36+
37+
dynamic "statement" {
38+
for_each = var.inline_policy_permissions != null ? var.inline_policy_permissions : {}
39+
40+
content {
41+
sid = try(coalesce(statement.value.sid, statement.key))
42+
actions = statement.value.actions
43+
not_actions = statement.value.not_actions
44+
effect = statement.value.effect
45+
resources = statement.value.resources
46+
not_resources = statement.value.not_resources
47+
48+
dynamic "principals" {
49+
for_each = statement.value.principals != null ? statement.value.principals : []
50+
51+
content {
52+
type = principals.value.type
53+
identifiers = principals.value.identifiers
54+
}
55+
}
56+
57+
dynamic "not_principals" {
58+
for_each = statement.value.not_principals != null ? statement.value.not_principals : []
59+
60+
content {
61+
type = not_principals.value.type
62+
identifiers = not_principals.value.identifiers
63+
}
64+
}
65+
66+
dynamic "condition" {
67+
for_each = statement.value.condition != null ? statement.value.condition : []
68+
69+
content {
70+
test = condition.value.test
71+
values = condition.value.values
72+
variable = condition.value.variable
73+
}
74+
}
75+
}
76+
}
77+
}
78+
79+
resource "aws_iam_user_policy" "inline" {
80+
count = local.create_inline_policy ? 1 : 0
81+
82+
user = aws_iam_user.this[0].name
83+
name = var.name
84+
policy = data.aws_iam_policy_document.inline[0].json
85+
}
86+
2387
################################################################################
2488
# User Login Profile
2589
################################################################################

‎modules/iam-user/variables.tf

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,51 @@ variable "ssh_public_key" {
109109
type = string
110110
default = ""
111111
}
112+
113+
################################################################################
114+
# Inline policy
115+
################################################################################
116+
117+
variable "create_inline_policy" {
118+
description = "Determines whether to create an inline policy"
119+
type = bool
120+
default = false
121+
}
122+
123+
variable "source_inline_policy_documents" {
124+
description = "List of IAM policy documents that are merged together into the exported document. Statements must have unique `sid`s"
125+
type = list(string)
126+
default = []
127+
}
128+
129+
variable "override_inline_policy_documents" {
130+
description = "List of IAM policy documents that are merged together into the exported document. In merging, statements with non-blank `sid`s will override statements with the same `sid`"
131+
type = list(string)
132+
default = []
133+
}
134+
135+
variable "inline_policy_permissions" {
136+
description = "A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for inline policy permissions"
137+
type = map(object({
138+
sid = optional(string)
139+
actions = optional(list(string))
140+
not_actions = optional(list(string))
141+
effect = optional(string, "Allow")
142+
resources = optional(list(string))
143+
not_resources = optional(list(string))
144+
principals = optional(list(object({
145+
type = string
146+
identifiers = list(string)
147+
})))
148+
not_principals = optional(list(object({
149+
type = string
150+
identifiers = list(string)
151+
})))
152+
condition = optional(list(object({
153+
test = string
154+
variable = string
155+
values = list(string)
156+
})))
157+
}))
158+
default = null
159+
}

‎wrappers/iam-user/main.tf

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,24 @@ module "wrapper" {
33

44
for_each = var.items
55

6-
access_key_status = try(each.value.access_key_status, var.defaults.access_key_status, null)
7-
create = try(each.value.create, var.defaults.create, true)
8-
create_access_key = try(each.value.create_access_key, var.defaults.create_access_key, true)
9-
create_login_profile = try(each.value.create_login_profile, var.defaults.create_login_profile, true)
10-
create_ssh_key = try(each.value.create_ssh_key, var.defaults.create_ssh_key, false)
11-
force_destroy = try(each.value.force_destroy, var.defaults.force_destroy, false)
12-
name = try(each.value.name, var.defaults.name, "")
13-
password_length = try(each.value.password_length, var.defaults.password_length, null)
14-
password_reset_required = try(each.value.password_reset_required, var.defaults.password_reset_required, true)
15-
path = try(each.value.path, var.defaults.path, null)
16-
permissions_boundary = try(each.value.permissions_boundary, var.defaults.permissions_boundary, null)
17-
pgp_key = try(each.value.pgp_key, var.defaults.pgp_key, null)
18-
policies = try(each.value.policies, var.defaults.policies, {})
19-
ssh_key_encoding = try(each.value.ssh_key_encoding, var.defaults.ssh_key_encoding, "SSH")
20-
ssh_public_key = try(each.value.ssh_public_key, var.defaults.ssh_public_key, "")
21-
tags = try(each.value.tags, var.defaults.tags, {})
6+
access_key_status = try(each.value.access_key_status, var.defaults.access_key_status, null)
7+
create = try(each.value.create, var.defaults.create, true)
8+
create_access_key = try(each.value.create_access_key, var.defaults.create_access_key, true)
9+
create_inline_policy = try(each.value.create_inline_policy, var.defaults.create_inline_policy, false)
10+
create_login_profile = try(each.value.create_login_profile, var.defaults.create_login_profile, true)
11+
create_ssh_key = try(each.value.create_ssh_key, var.defaults.create_ssh_key, false)
12+
force_destroy = try(each.value.force_destroy, var.defaults.force_destroy, false)
13+
inline_policy_permissions = try(each.value.inline_policy_permissions, var.defaults.inline_policy_permissions, null)
14+
name = try(each.value.name, var.defaults.name, "")
15+
override_inline_policy_documents = try(each.value.override_inline_policy_documents, var.defaults.override_inline_policy_documents, [])
16+
password_length = try(each.value.password_length, var.defaults.password_length, null)
17+
password_reset_required = try(each.value.password_reset_required, var.defaults.password_reset_required, true)
18+
path = try(each.value.path, var.defaults.path, null)
19+
permissions_boundary = try(each.value.permissions_boundary, var.defaults.permissions_boundary, null)
20+
pgp_key = try(each.value.pgp_key, var.defaults.pgp_key, null)
21+
policies = try(each.value.policies, var.defaults.policies, {})
22+
source_inline_policy_documents = try(each.value.source_inline_policy_documents, var.defaults.source_inline_policy_documents, [])
23+
ssh_key_encoding = try(each.value.ssh_key_encoding, var.defaults.ssh_key_encoding, "SSH")
24+
ssh_public_key = try(each.value.ssh_public_key, var.defaults.ssh_public_key, "")
25+
tags = try(each.value.tags, var.defaults.tags, {})
2226
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /