-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathiam.tf
224 lines (201 loc) · 7.42 KB
/
iam.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# This resource creates an S3 bucket policy for the CloudTrail bucket.
# The policy is created only if an existing CloudTrail bucket name is not provided.
resource "aws_s3_bucket_policy" "cloudtrail_bucket_policy" {
count = var.existing_cloudtrail_bucket_name == null ? 1 : 0
bucket = aws_s3_bucket.cloudtrail_bucket[0].bucket
policy = data.aws_iam_policy_document.cloudtrail_bucket_iam_document[0].json
}
# This data block defines the IAM policy document for the CloudTrail bucket.
# The policy allows the CloudTrail service to get the ACL of the bucket and put objects into the bucket.
data "aws_iam_policy_document" "cloudtrail_bucket_iam_document" {
count = var.existing_cloudtrail_bucket_name == null ? 1 : 0
# Necessary to allow any bucket permissions
statement {
actions = ["s3:GetBucketAcl"]
resources = [aws_s3_bucket.cloudtrail_bucket[0].arn]
effect = "Allow"
principals {
type = "Service"
identifiers = ["cloudtrail.amazonaws.com"]
}
}
# Allow Cloudtrail to store objects in S3 bucket
statement {
actions = ["s3:PutObject"]
resources = [
"${aws_s3_bucket.cloudtrail_bucket[0].arn}/*"
]
effect = "Allow"
principals {
type = "Service"
identifiers = ["cloudtrail.amazonaws.com"]
}
}
}
# This data block defines the IAM policy document that allows the Expel Workbench to assume a role.
# The policy includes a condition that the sts:ExternalId must match the expel_customer_organization_guid.
data "aws_iam_policy_document" "mgmt_assume_role_iam_document" {
# Allow Expel Workbench to decrypt cloudtrail bucket
statement {
actions = ["sts:AssumeRole"]
effect = "Allow"
principals {
type = "AWS"
identifiers = [var.expel_aws_user_arn]
}
condition {
test = "StringEquals"
variable = "sts:ExternalId"
values = [var.expel_customer_organization_guid]
}
}
}
# This resource creates an IAM role with the policy defined in mgmt_assume_role_iam_document.
resource "aws_iam_role" "mgmt_expel_assume_role" {
name = var.expel_assume_role_name
assume_role_policy = data.aws_iam_policy_document.mgmt_assume_role_iam_document.json
tags = local.tags
}
# This resource attaches the cloudtrail_manager_iam_policy to the mgmt_expel_assume_role.
resource "aws_iam_role_policy_attachment" "cloudtrail_manager_role_policy_attachment" {
role = aws_iam_role.mgmt_expel_assume_role.name
policy_arn = aws_iam_policy.cloudtrail_manager_iam_policy.arn
}
resource "aws_iam_policy" "cloudtrail_manager_iam_policy" {
name = "${var.prefix}-cloudtrail-manager-policy"
policy = data.aws_iam_policy_document.cloudtrail_manager_iam_document.json
tags = local.tags
}
# This data block defines the IAM policy document that allows the Expel Workbench to perform various actions.
# The actions include getting objects from the CloudTrail bucket, receiving and deleting SQS messages, decrypting the CloudTrail bucket, and decrypting notifications.
#tfsec:ignore:aws-iam-no-policy-wildcards
data "aws_iam_policy_document" "cloudtrail_manager_iam_document" {
# Allow Expel Workbench to get objects from cloudtrail bucket
dynamic "statement" {
for_each = var.is_existing_cloudtrail_cross_account ? [] : [1]
content {
actions = ["s3:GetObject"]
resources = ["${local.cloudtrail_bucket_arn}/*"]
effect = "Allow"
}
}
# Allow Expel Workbench to receive and delete SQS messages
dynamic "statement" {
for_each = var.is_existing_cloudtrail_cross_account ? [] : [1]
content {
actions = [
"sqs:DeleteMessage",
"sqs:ReceiveMessage"
]
resources = [aws_sqs_queue.cloudtrail_queue.arn]
effect = "Allow"
}
}
# Allow Expel Workbench to decrypt cloudtrail bucket
dynamic "statement" {
for_each = (var.is_existing_cloudtrail_cross_account || local.cloudtrail_bucket_encryption_key_arn == null) ? [] : [1]
content {
actions = ["kms:Decrypt"]
resources = [local.cloudtrail_bucket_encryption_key_arn]
effect = "Allow"
}
}
# Allow Expel Workbench to decrypt notifications
dynamic "statement" {
for_each = var.is_existing_cloudtrail_cross_account ? [] : [1]
content {
actions = ["kms:Decrypt"]
resources = [local.notification_encryption_key_arn]
effect = "Allow"
}
}
# Note: This is a duplicate policy statement with CloudFormation StackSet "PermeateAccountPolicy"
# Allow Expel Workbench to gather information about AWS footprint
statement {
actions = [
"cloudtrail:DescribeTrails",
"cloudtrail:GetTrailStatus",
"cloudtrail:ListTrails",
"cloudtrail:GetTrail",
"config:GetDiscoveredResourceCounts",
"config:ListDiscoveredResources",
"ec2:DescribeInstances",
"ec2:DescribeRegions",
"ec2:DescribeSecurityGroups",
"ec2:DescribeVolumes",
"ecs:DescribeClusters",
"ecs:DescribeContainerInstances",
"ecs:DescribeTaskDefinition",
"ecs:ListClusters",
"ecs:ListContainerInstances",
"ecs:ListTaskDefinitions",
"eks:DescribeCluster",
"eks:ListClusters",
"iam:Get*",
"iam:List*",
"lambda:GetFunction",
"lambda:ListFunctions",
"lightsail:GetInstances",
"lightsail:GetRegions",
"organizations:ListAccounts",
"rds:DescribeDBInstances",
"rds:ListTagsForResource",
"s3:ListAllMyBuckets",
"s3:GetBucketNotification",
"s3:GetEncryptionConfiguration"
]
resources = ["*"]
effect = "Allow"
}
}
# For existing trail with cross-account resources, deploy the expel role in log bucket account
resource "aws_iam_role_policy_attachment" "log_bucket_role_policy_attachment" {
count = var.is_existing_cloudtrail_cross_account ? 1 : 0
depends_on = [aws_cloudformation_stack_set_instance.permeate_account_policy]
provider = aws.log_bucket
role = var.expel_assume_role_name
policy_arn = aws_iam_policy.log_bucket_iam_policy[0].arn
}
# This resource creates an IAM policy for the log bucket.
# This is used when there is an existing CloudTrail with cross-account resources.
resource "aws_iam_policy" "log_bucket_iam_policy" {
count = var.is_existing_cloudtrail_cross_account ? 1 : 0
provider = aws.log_bucket
name = "${var.prefix}-log-bucket-policy"
policy = data.aws_iam_policy_document.log_bucket_iam_document.json
tags = local.tags
}
# ignoring as these policies enable necessary observability on all AWS resources
# tfsec:ignore:aws-iam-no-policy-wildcards
data "aws_iam_policy_document" "log_bucket_iam_document" {
# Allow Expel Workbench to get objects from cloudtrail bucket
statement {
actions = ["s3:GetObject"]
resources = ["${local.cloudtrail_bucket_arn}/*"]
effect = "Allow"
}
# Allow Expel Workbench to receive and delete SQS messages
statement {
actions = [
"sqs:DeleteMessage",
"sqs:ReceiveMessage"
]
resources = [aws_sqs_queue.cloudtrail_queue.arn]
effect = "Allow"
}
# Allow Expel Workbench to decrypt cloudtrail bucket
dynamic "statement" {
for_each = var.existing_cloudtrail_kms_key_arn == null ? [] : [1]
content {
actions = ["kms:Decrypt"]
resources = [var.existing_cloudtrail_kms_key_arn]
effect = "Allow"
}
}
# Allow Expel Workbench to decrypt notifications
statement {
actions = ["kms:Decrypt"]
resources = [local.notification_encryption_key_arn]
effect = "Allow"
}
}