1
+ provider "aws" {
2
+ region = " us-east-1"
3
+ }
4
+
5
+ # create SNS
6
+ resource "aws_sns_topic" "p0tion_sns_topic" {
7
+ name = " p0tion_sns_topic"
8
+ }
9
+
10
+ # create Lambda execution role
11
+ data "aws_iam_policy_document" "p0tion_assume_role_policy_lambda" {
12
+ statement {
13
+ actions = [" sts:AssumeRole" ]
14
+
15
+ principals {
16
+ type = " Service"
17
+ identifiers = [" lambda.amazonaws.com" ]
18
+ }
19
+ }
20
+ }
21
+
22
+ resource "aws_iam_role" "p0tion_lambda_role" {
23
+ name = " p0tion_lambda_role"
24
+ assume_role_policy = data. aws_iam_policy_document . p0tion_assume_role_policy_lambda . json
25
+ }
26
+
27
+ # Execution role with EC2 and logs permissions
28
+ resource "aws_iam_role_policy" "p0tion_lambda_exec_role_policy" {
29
+ name = " p0tion_lambda_exec_role_policy"
30
+ role = aws_iam_role. p0tion_lambda_role . id
31
+
32
+ policy = << EOF
33
+ {
34
+ "Version": "2012-10-17",
35
+ "Statement": [
36
+ {
37
+ "Sid": "p0tionLambdaExec",
38
+ "Effect": "Allow",
39
+ "Action": [
40
+ "ec2:DescribeInstances",
41
+ "ec2:StopInstances",
42
+ "ec2:CreateTags",
43
+ "logs:CreateLogGroup",
44
+ "logs:CreateLogStream",
45
+ "logs:PutLogEvents"
46
+ ],
47
+ "Resource": "*"
48
+ }
49
+ ]
50
+ }
51
+ EOF
52
+ }
53
+
54
+ # Deploy the Lambda with the code to stop the EC2 instance
55
+ resource "aws_lambda_function" "p0tion_lambda_stop_vm" {
56
+ filename = " ./lambda.zip"
57
+ function_name = " p0tion_lambda_stop_vm"
58
+ role = aws_iam_role. p0tion_lambda_role . arn
59
+ handler = " lambda_function.lambda_handler"
60
+
61
+ runtime = " nodejs18.x"
62
+ source_code_hash = filebase64sha256 (" ./lambda.zip" )
63
+ timeout = 300
64
+
65
+ environment {
66
+ variables = {
67
+ SNS_TOPIC_ARN = aws_sns_topic.p0tion_sns_topic.arn
68
+ }
69
+ }
70
+ }
71
+
72
+ # Allow the lambda to be triggered by SNS
73
+ resource "aws_lambda_permission" "sns" {
74
+ statement_id = " AllowExecutionFromSNS"
75
+ action = " lambda:InvokeFunction"
76
+ function_name = aws_lambda_function. p0tion_lambda_stop_vm . function_name
77
+ principal = " sns.amazonaws.com"
78
+ source_arn = aws_sns_topic. p0tion_sns_topic . arn
79
+ }
80
+
81
+ resource "aws_sns_topic_subscription" "lambda" {
82
+ topic_arn = aws_sns_topic. p0tion_sns_topic . arn
83
+ protocol = " lambda"
84
+ endpoint = aws_lambda_function. p0tion_lambda_stop_vm . arn
85
+ }
86
+
87
+ # Create instance role for EC2
88
+ data "aws_iam_policy_document" "p0tion_assume_role_policy_ec2" {
89
+ statement {
90
+ actions = [" sts:AssumeRole" ]
91
+
92
+ principals {
93
+ type = " Service"
94
+ identifiers = [" ec2.amazonaws.com" ]
95
+ }
96
+ }
97
+ }
98
+
99
+ # Associate the role with the instance profile
100
+ resource "aws_iam_role" "p0tion_ec2_role" {
101
+ name = " p0tion_ec2_role"
102
+ assume_role_policy = data. aws_iam_policy_document . p0tion_assume_role_policy_ec2 . json
103
+ }
104
+
105
+ # EC2 SNS policy
106
+ resource "aws_iam_role_policy" "p0tion_ec2_sns" {
107
+ name = " p0tion_ec2_sns"
108
+ role = aws_iam_role. p0tion_ec2_role . id
109
+
110
+ policy = << EOF
111
+ {
112
+ "Version": "2012-10-17",
113
+ "Statement": [
114
+ {
115
+ "Sid": "p0tionEC2SNS",
116
+ "Effect": "Allow",
117
+ "Action": "sns:Publish",
118
+ "Resource": "${ aws_sns_topic . p0tion_sns_topic . arn } "
119
+ }
120
+ ]
121
+ }
122
+ EOF
123
+ }
124
+
125
+ # EC2 S3 and SSM policy
126
+ resource "aws_iam_role_policy" "p0tion_ec2_s3_ssm" {
127
+ name = " p0tion_ec2_s3_ssm"
128
+ role = aws_iam_role. p0tion_ec2_role . id
129
+
130
+ policy = << EOF
131
+ {
132
+ "Version": "2012-10-17",
133
+ "Statement": [
134
+ {
135
+ "Sid": "p0tionEc2S3SSM",
136
+ "Effect": "Allow",
137
+ "Action": [
138
+ "s3:ListBucket",
139
+ "s3:PutObject",
140
+ "s3:GetObject",
141
+ "s3:PutObjectAcl",
142
+ "ssm:UpdateInstanceInformation",
143
+ "ssmmessages:CreateControlChannel",
144
+ "ssmmessages:CreateDataChannel",
145
+ "ssmmessages:OpenControlChannel",
146
+ "ssmmessages:OpenDataChannel"
147
+ ],
148
+ "Resource": "${ aws_sns_topic . p0tion_sns_topic . arn } "
149
+ }
150
+ ]
151
+ }
152
+ EOF
153
+ }
154
+
155
+ # IAM user for all operations
156
+ resource "aws_iam_user" "p0tion_iam_user" {
157
+ name = " p0tion_iam_user"
158
+ }
159
+
160
+ resource "aws_iam_access_key" "p0tion_access_key" {
161
+ user = aws_iam_user. p0tion_iam_user . name
162
+ }
163
+
164
+ resource "aws_iam_user_policy" "p0tion_s3_ssm" {
165
+ name = " p0tion_s3_ssm"
166
+ user = aws_iam_user. p0tion_iam_user . name
167
+
168
+ policy = << EOF
169
+ {
170
+ "Version": "2012-10-17",
171
+ "Statement": [
172
+ {
173
+ "Sid": "S3andEC2andSSM",
174
+ "Effect": "Allow",
175
+ "Action": [
176
+ "s3:CreateBucket",
177
+ "s3:ListBucket",
178
+ "s3:ListMultipartUploadParts",
179
+ "s3:GetObject",
180
+ "s3:AbortMultipartUpload",
181
+ "s3:GetObjectVersion",
182
+ "s3:HeadBucket",
183
+ "ec2:RunInstances",
184
+ "ec2:DescribeInstanceStatus",
185
+ "ec2:CreateTags",
186
+ "iam:PassRole"
187
+ ],
188
+ "Resource": "*"
189
+ }
190
+ ]
191
+ }
192
+ EOF
193
+ }
194
+
195
+ resource "aws_iam_user_policy" "p0tion_ec2_privileged" {
196
+ name = " p0tion_ec2_privileged"
197
+ user = aws_iam_user. p0tion_iam_user . name
198
+
199
+ policy = << EOF
200
+ {
201
+ "Version": "2012-10-17",
202
+ "Statement": [
203
+ {
204
+ "Sid": "EC2Privileged",
205
+ "Effect": "Allow",
206
+ "Action": [
207
+ "ec2:StopInstances",
208
+ "ec2:TerminateInstances",
209
+ "ec2:StartInstances",
210
+ "ssm:SendCommand",
211
+ "ssm:GetCommandInvocation"
212
+ ],
213
+ "Resource": "*"
214
+ }
215
+ ]
216
+ }
217
+ EOF
218
+ }
219
+
220
+ resource "aws_iam_user_policy" "p0tion_s3_privileged" {
221
+ name = " p0tion_s3_privileged"
222
+ user = aws_iam_user. p0tion_iam_user . name
223
+
224
+ policy = << EOF
225
+ {
226
+ "Version": "2012-10-17",
227
+ "Statement": [
228
+ {
229
+ "Sid": "S3Privileged",
230
+ "Effect": "Allow",
231
+ "Action": [
232
+ "s3:DeleteObject",
233
+ "s3:DeleteBucket",
234
+ "s3:PutBucketPublicAccessBlock",
235
+ "s3:PutBucketCORS",
236
+ "s3:PutBucketObjectLockConfiguration",
237
+ "s3:PutBucketAcl",
238
+ "s3:PutBucketVersioning",
239
+ "s3:PutObject",
240
+ "s3:PutObjectAcl",
241
+ "s3:PutBucketOwnershipControls"
242
+ ],
243
+ "Resource": "*"
244
+ }
245
+ ]
246
+ }
247
+ EOF
248
+ }
249
+
250
+ # The user access keys
251
+ output "access_key" {
252
+ value = aws_iam_access_key. p0tion_access_key . id
253
+ description = " The access key ID"
254
+ }
255
+
256
+ output "secret_key" {
257
+ value = aws_iam_access_key. p0tion_access_key . secret
258
+ description = " The secret access key. This key will be encrypted and stored in the state file, use terraform output secret_key"
259
+ sensitive = true
260
+ }
0 commit comments