awslabs.terraform-mcp-server 1.0.14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- awslabs/__init__.py +17 -0
- awslabs/terraform_mcp_server/__init__.py +17 -0
- awslabs/terraform_mcp_server/impl/resources/__init__.py +25 -0
- awslabs/terraform_mcp_server/impl/resources/terraform_aws_provider_resources_listing.py +66 -0
- awslabs/terraform_mcp_server/impl/resources/terraform_awscc_provider_resources_listing.py +69 -0
- awslabs/terraform_mcp_server/impl/tools/__init__.py +33 -0
- awslabs/terraform_mcp_server/impl/tools/execute_terraform_command.py +223 -0
- awslabs/terraform_mcp_server/impl/tools/execute_terragrunt_command.py +320 -0
- awslabs/terraform_mcp_server/impl/tools/run_checkov_scan.py +376 -0
- awslabs/terraform_mcp_server/impl/tools/search_aws_provider_docs.py +691 -0
- awslabs/terraform_mcp_server/impl/tools/search_awscc_provider_docs.py +641 -0
- awslabs/terraform_mcp_server/impl/tools/search_specific_aws_ia_modules.py +458 -0
- awslabs/terraform_mcp_server/impl/tools/search_user_provided_module.py +349 -0
- awslabs/terraform_mcp_server/impl/tools/utils.py +572 -0
- awslabs/terraform_mcp_server/models/__init__.py +49 -0
- awslabs/terraform_mcp_server/models/models.py +381 -0
- awslabs/terraform_mcp_server/scripts/generate_aws_provider_resources.py +1240 -0
- awslabs/terraform_mcp_server/scripts/generate_awscc_provider_resources.py +1039 -0
- awslabs/terraform_mcp_server/scripts/scrape_aws_terraform_best_practices.py +143 -0
- awslabs/terraform_mcp_server/server.py +440 -0
- awslabs/terraform_mcp_server/static/AWSCC_PROVIDER_RESOURCES.md +3125 -0
- awslabs/terraform_mcp_server/static/AWS_PROVIDER_RESOURCES.md +3833 -0
- awslabs/terraform_mcp_server/static/AWS_TERRAFORM_BEST_PRACTICES.md +2523 -0
- awslabs/terraform_mcp_server/static/MCP_INSTRUCTIONS.md +142 -0
- awslabs/terraform_mcp_server/static/TERRAFORM_WORKFLOW_GUIDE.md +330 -0
- awslabs/terraform_mcp_server/static/__init__.py +38 -0
- awslabs_terraform_mcp_server-1.0.14.dist-info/METADATA +166 -0
- awslabs_terraform_mcp_server-1.0.14.dist-info/RECORD +30 -0
- awslabs_terraform_mcp_server-1.0.14.dist-info/WHEEL +4 -0
- awslabs_terraform_mcp_server-1.0.14.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,2523 @@
|
|
|
1
|
+
# AWS Terraform Provider Best Practices
|
|
2
|
+
|
|
3
|
+
_This document was automatically extracted from the AWS Prescriptive Guidance PDF._
|
|
4
|
+
|
|
5
|
+
_Source: [https://docs.aws.amazon.com/pdfs/prescriptive-guidance/latest/terraform-aws-provider-best-practices/terraform-aws-provider-best-practices.pdf](https://docs.aws.amazon.com/pdfs/prescriptive-guidance/latest/terraform-aws-provider-best-practices/terraform-aws-provider-best-practices.pdf)_
|
|
6
|
+
|
|
7
|
+
## Best practices for using the Terraform AWS Provider
|
|
8
|
+
|
|
9
|
+
## AWS Prescriptive Guidance
|
|
10
|
+
|
|
11
|
+
Copyright © 2025 Amazon Web Services, Inc. and/or its affiliates. All rights reserved.
|
|
12
|
+
|
|
13
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
14
|
+
|
|
15
|
+
AWS Prescriptive Guidance: Best practices for using the Terraform
|
|
16
|
+
|
|
17
|
+
## AWS Provider
|
|
18
|
+
|
|
19
|
+
Copyright © 2025 Amazon Web Services, Inc. and/or its affiliates. All rights reserved.
|
|
20
|
+
|
|
21
|
+
Amazon's trademarks and trade dress may not be used in connection with any product or service
|
|
22
|
+
|
|
23
|
+
that is not Amazon's, in any manner that is likely to cause confusion among customers, or in any
|
|
24
|
+
|
|
25
|
+
manner that disparages or discredits Amazon. All other trademarks not owned by Amazon are
|
|
26
|
+
|
|
27
|
+
the property of their respective owners, who may or may not be affiliated with, connected to, or
|
|
28
|
+
|
|
29
|
+
sponsored by Amazon.
|
|
30
|
+
|
|
31
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
32
|
+
|
|
33
|
+
## Table of Contents
|
|
34
|
+
|
|
35
|
+
Introduction.....................................................................................................................................1
|
|
36
|
+
|
|
37
|
+
Objectives.......................................................................................................................................................1
|
|
38
|
+
|
|
39
|
+
Target audience.............................................................................................................................................2
|
|
40
|
+
|
|
41
|
+
Overview..........................................................................................................................................3
|
|
42
|
+
|
|
43
|
+
Security best practices....................................................................................................................5
|
|
44
|
+
|
|
45
|
+
Follow the principle of least privilege.....................................................................................................5
|
|
46
|
+
|
|
47
|
+
Use IAM roles................................................................................................................................................6
|
|
48
|
+
|
|
49
|
+
Grant least privilege access by using IAM policies...........................................................................6
|
|
50
|
+
|
|
51
|
+
Assume IAM roles for local authentication........................................................................................6
|
|
52
|
+
|
|
53
|
+
Use IAM roles for Amazon EC2 authentication.................................................................................8
|
|
54
|
+
|
|
55
|
+
Use dynamic credentials for HCP Terraform workspaces...............................................................9
|
|
56
|
+
|
|
57
|
+
Use IAM roles in AWS CodeBuild.........................................................................................................9
|
|
58
|
+
|
|
59
|
+
Run GitHub Actions remotely on HCP Terraform.............................................................................9
|
|
60
|
+
|
|
61
|
+
Use GitHub Actions with OIDC and configure the AWS Credentials action.................................9
|
|
62
|
+
|
|
63
|
+
Use GitLab with OIDC and the AWS CLI............................................................................................9
|
|
64
|
+
|
|
65
|
+
Use unique IAM users with legacy automation tools.........................................................................10
|
|
66
|
+
|
|
67
|
+
Use the Jenkins AWS Credentials plugin.........................................................................................10
|
|
68
|
+
|
|
69
|
+
Continuously monitor, validate, and optimize least privilege...........................................................10
|
|
70
|
+
|
|
71
|
+
Continuously monitor access key usage..........................................................................................10
|
|
72
|
+
|
|
73
|
+
Continually validate IAM policies .........................................................................................................6
|
|
74
|
+
|
|
75
|
+
Secure remote state storage...................................................................................................................11
|
|
76
|
+
|
|
77
|
+
Enable encryption and access controls............................................................................................12
|
|
78
|
+
|
|
79
|
+
Limit direct access to collaborative workflows...............................................................................12
|
|
80
|
+
|
|
81
|
+
Use AWS Secrets Manager.......................................................................................................................12
|
|
82
|
+
|
|
83
|
+
Continuously scan infrastructure and source code.............................................................................12
|
|
84
|
+
|
|
85
|
+
Use AWS services for dynamic scanning..........................................................................................13
|
|
86
|
+
|
|
87
|
+
Perform static analysis........................................................................................................................13
|
|
88
|
+
|
|
89
|
+
Ensure prompt remediation................................................................................................................13
|
|
90
|
+
|
|
91
|
+
Enforce policy checks................................................................................................................................13
|
|
92
|
+
|
|
93
|
+
Backend best practices..................................................................................................................15
|
|
94
|
+
|
|
95
|
+
Use Amazon S3 for remote storage.......................................................................................................16
|
|
96
|
+
|
|
97
|
+
Enable remote state locking..............................................................................................................16
|
|
98
|
+
|
|
99
|
+
Enable versioning and automatic backups......................................................................................16
|
|
100
|
+
|
|
101
|
+
Restore previous versions if needed.................................................................................................17
|
|
102
|
+
|
|
103
|
+
iii
|
|
104
|
+
|
|
105
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
106
|
+
|
|
107
|
+
Use HCP Terraform...............................................................................................................................17
|
|
108
|
+
|
|
109
|
+
Facilitate team collaboration...................................................................................................................17
|
|
110
|
+
|
|
111
|
+
Improve accountability by using AWS CloudTrail..........................................................................17
|
|
112
|
+
|
|
113
|
+
Separate the backends for each environment.....................................................................................18
|
|
114
|
+
|
|
115
|
+
Reduce the scope of impact...............................................................................................................18
|
|
116
|
+
|
|
117
|
+
Restrict production access..................................................................................................................18
|
|
118
|
+
|
|
119
|
+
Simplify access controls......................................................................................................................18
|
|
120
|
+
|
|
121
|
+
Avoid shared workspaces....................................................................................................................19
|
|
122
|
+
|
|
123
|
+
Actively monitor remote state activity..................................................................................................19
|
|
124
|
+
|
|
125
|
+
Get alerts on suspicious unlocks.......................................................................................................19
|
|
126
|
+
|
|
127
|
+
Monitor access attempts.....................................................................................................................19
|
|
128
|
+
|
|
129
|
+
Best practices for code base structure and organization............................................................20
|
|
130
|
+
|
|
131
|
+
Implement a standard repository structure.........................................................................................21
|
|
132
|
+
|
|
133
|
+
Root module structure.........................................................................................................................24
|
|
134
|
+
|
|
135
|
+
Reusable module structure.................................................................................................................24
|
|
136
|
+
|
|
137
|
+
Structure for modularity..........................................................................................................................25
|
|
138
|
+
|
|
139
|
+
Don't wrap single resources...............................................................................................................26
|
|
140
|
+
|
|
141
|
+
Encapsulate logical relationships......................................................................................................26
|
|
142
|
+
|
|
143
|
+
Keep inheritance flat............................................................................................................................26
|
|
144
|
+
|
|
145
|
+
Reference resources in outputs..........................................................................................................26
|
|
146
|
+
|
|
147
|
+
Don't configure providers....................................................................................................................26
|
|
148
|
+
|
|
149
|
+
Declare required providers..................................................................................................................27
|
|
150
|
+
|
|
151
|
+
Follow naming conventions.....................................................................................................................28
|
|
152
|
+
|
|
153
|
+
Follow guidelines for resource naming............................................................................................28
|
|
154
|
+
|
|
155
|
+
Follow guidelines for variable naming.............................................................................................28
|
|
156
|
+
|
|
157
|
+
Use attachment resources........................................................................................................................29
|
|
158
|
+
|
|
159
|
+
Use default tags .........................................................................................................................................30
|
|
160
|
+
|
|
161
|
+
Meet Terraform registry requirements..................................................................................................30
|
|
162
|
+
|
|
163
|
+
Use recommended module sources.......................................................................................................31
|
|
164
|
+
|
|
165
|
+
Registry...................................................................................................................................................31
|
|
166
|
+
|
|
167
|
+
VCS providers.........................................................................................................................................32
|
|
168
|
+
|
|
169
|
+
Follow coding standards...........................................................................................................................33
|
|
170
|
+
|
|
171
|
+
Follow style guidelines........................................................................................................................34
|
|
172
|
+
|
|
173
|
+
Configure pre-commit hooks.............................................................................................................34
|
|
174
|
+
|
|
175
|
+
Best practices for AWS Provider version management...............................................................35
|
|
176
|
+
|
|
177
|
+
Add automated version checks...............................................................................................................35
|
|
178
|
+
|
|
179
|
+
iv
|
|
180
|
+
|
|
181
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
182
|
+
|
|
183
|
+
Monitor new releases................................................................................................................................35
|
|
184
|
+
|
|
185
|
+
Contribute to providers............................................................................................................................36
|
|
186
|
+
|
|
187
|
+
Best practices for community modules........................................................................................37
|
|
188
|
+
|
|
189
|
+
Discover community modules.................................................................................................................37
|
|
190
|
+
|
|
191
|
+
Use variables for customization ........................................................................................................37
|
|
192
|
+
|
|
193
|
+
Understand dependencies ........................................................................................................................37
|
|
194
|
+
|
|
195
|
+
Use trusted sources...................................................................................................................................38
|
|
196
|
+
|
|
197
|
+
Subscribe to notifications ...................................................................................................................38
|
|
198
|
+
|
|
199
|
+
Contribute to community modules........................................................................................................38
|
|
200
|
+
|
|
201
|
+
FAQ.................................................................................................................................................40
|
|
202
|
+
|
|
203
|
+
Next steps......................................................................................................................................41
|
|
204
|
+
|
|
205
|
+
Resources........................................................................................................................................42
|
|
206
|
+
|
|
207
|
+
References....................................................................................................................................................42
|
|
208
|
+
|
|
209
|
+
Tools..............................................................................................................................................................42
|
|
210
|
+
|
|
211
|
+
Document history..........................................................................................................................43
|
|
212
|
+
|
|
213
|
+
Glossary..........................................................................................................................................44
|
|
214
|
+
|
|
215
|
+
#.....................................................................................................................................................................44
|
|
216
|
+
|
|
217
|
+
A.....................................................................................................................................................................45
|
|
218
|
+
|
|
219
|
+
B.....................................................................................................................................................................48
|
|
220
|
+
|
|
221
|
+
C.....................................................................................................................................................................50
|
|
222
|
+
|
|
223
|
+
D.....................................................................................................................................................................53
|
|
224
|
+
|
|
225
|
+
E.....................................................................................................................................................................57
|
|
226
|
+
|
|
227
|
+
F.....................................................................................................................................................................59
|
|
228
|
+
|
|
229
|
+
G.....................................................................................................................................................................61
|
|
230
|
+
|
|
231
|
+
H.....................................................................................................................................................................62
|
|
232
|
+
|
|
233
|
+
I......................................................................................................................................................................63
|
|
234
|
+
|
|
235
|
+
L.....................................................................................................................................................................65
|
|
236
|
+
|
|
237
|
+
M....................................................................................................................................................................67
|
|
238
|
+
|
|
239
|
+
O....................................................................................................................................................................71
|
|
240
|
+
|
|
241
|
+
P.....................................................................................................................................................................73
|
|
242
|
+
|
|
243
|
+
Q....................................................................................................................................................................76
|
|
244
|
+
|
|
245
|
+
R.....................................................................................................................................................................76
|
|
246
|
+
|
|
247
|
+
S.....................................................................................................................................................................79
|
|
248
|
+
|
|
249
|
+
T.....................................................................................................................................................................83
|
|
250
|
+
|
|
251
|
+
U.....................................................................................................................................................................84
|
|
252
|
+
|
|
253
|
+
V.....................................................................................................................................................................85
|
|
254
|
+
|
|
255
|
+
v
|
|
256
|
+
|
|
257
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
258
|
+
|
|
259
|
+
W....................................................................................................................................................................85
|
|
260
|
+
|
|
261
|
+
Z.....................................................................................................................................................................86
|
|
262
|
+
|
|
263
|
+
vi
|
|
264
|
+
|
|
265
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
266
|
+
|
|
267
|
+
## Best practices for using the Terraform AWS Provider
|
|
268
|
+
|
|
269
|
+
Michael Begin, Senior DevOps Consultant, Amazon Web Services (AWS)
|
|
270
|
+
|
|
271
|
+
May 2024 (document history)
|
|
272
|
+
|
|
273
|
+
Managing infrastructure as code (IaC) with Terraform on AWS offers important benefits such as
|
|
274
|
+
|
|
275
|
+
improved consistency, security, and agility. However, as your Terraform configuration grows in size
|
|
276
|
+
|
|
277
|
+
and complexity, it becomes critical to follow best practices to avoid pitfalls.
|
|
278
|
+
|
|
279
|
+
This guide provides recommended best practices for using the Terraform AWS Provider from
|
|
280
|
+
|
|
281
|
+
HashiCorp. It walks you through proper versioning, security controls, remote backends, codebase
|
|
282
|
+
|
|
283
|
+
structure, and community providers to optimize Terraform on AWS. Each section dives into more
|
|
284
|
+
|
|
285
|
+
details on the specifics of applying these best practices:
|
|
286
|
+
|
|
287
|
+
*Security
|
|
288
|
+
|
|
289
|
+
*Backends
|
|
290
|
+
|
|
291
|
+
*Code base structure and organization
|
|
292
|
+
|
|
293
|
+
*AWS Provider version management
|
|
294
|
+
|
|
295
|
+
*Community modules
|
|
296
|
+
|
|
297
|
+
## Objectives
|
|
298
|
+
|
|
299
|
+
This guide helps you gain operational knowledge on the Terraform AWS Provider and addresses
|
|
300
|
+
|
|
301
|
+
the following business goals that you can achieve by following IaC best practices around security,
|
|
302
|
+
|
|
303
|
+
reliability, compliance, and developer productivity.
|
|
304
|
+
|
|
305
|
+
*Improve infrastructure code quality and consistency across Terraform projects.
|
|
306
|
+
|
|
307
|
+
*Accelerate developer onboarding and ability to contribute to infrastructure code.
|
|
308
|
+
|
|
309
|
+
*Increase business agility through faster infrastructure changes.
|
|
310
|
+
|
|
311
|
+
*Reduce errors and downtime related to infrastructure changes.
|
|
312
|
+
|
|
313
|
+
*Optimize infrastructure costs by following IaC best practices.
|
|
314
|
+
|
|
315
|
+
*Strengthen your overall security posture through best practice implementation.
|
|
316
|
+
|
|
317
|
+
Objectives 1
|
|
318
|
+
|
|
319
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
320
|
+
|
|
321
|
+
## Target audience
|
|
322
|
+
|
|
323
|
+
The target audience for this guide includes technical leads and managers who oversee teams
|
|
324
|
+
|
|
325
|
+
that use Terraform for IaC on AWS. Other potential readers include infrastructure engineers,
|
|
326
|
+
|
|
327
|
+
DevOps engineers, solutions architects, and developers who actively use Terraform to manage AWS
|
|
328
|
+
|
|
329
|
+
infrastructure.
|
|
330
|
+
|
|
331
|
+
Following these best practices will save time and help unlock the benefits of IaC for these roles.
|
|
332
|
+
|
|
333
|
+
Target audience 2
|
|
334
|
+
|
|
335
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
336
|
+
|
|
337
|
+
## Overview
|
|
338
|
+
|
|
339
|
+
Terraform providers are plugins that allow Terraform to interact with different APIs. The Terraform
|
|
340
|
+
|
|
341
|
+
AWS Provider is the official plugin for managing AWS infrastructure as code (IaC) with Terraform. It
|
|
342
|
+
|
|
343
|
+
translates Terraform syntax into AWS API calls to create, read, update, and delete AWS resources.
|
|
344
|
+
|
|
345
|
+
The AWS Provider handles authentication, translating Terraform syntax to AWS API calls, and
|
|
346
|
+
|
|
347
|
+
provisioning resources in AWS. You use a Terraform provider code block to configure the provider
|
|
348
|
+
|
|
349
|
+
plugin that Terraform uses to interact with the AWS API. You can configure multiple AWS Provider
|
|
350
|
+
|
|
351
|
+
blocks to manage resources across different AWS accounts and Regions.
|
|
352
|
+
|
|
353
|
+
Here's an example Terraform configuration that uses multiple AWS Provider blocks with aliases
|
|
354
|
+
|
|
355
|
+
to manage an Amazon Relational Database Service (Amazon RDS) database that has a replica in a
|
|
356
|
+
|
|
357
|
+
different Region and account. The primary and secondary providers assume different AWS Identity
|
|
358
|
+
|
|
359
|
+
and Access Management (IAM) roles:
|
|
360
|
+
|
|
361
|
+
# Configure the primary AWS Provider
|
|
362
|
+
|
|
363
|
+
provider "aws" {
|
|
364
|
+
|
|
365
|
+
region = "us-west-1"
|
|
366
|
+
|
|
367
|
+
alias = "primary"
|
|
368
|
+
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
# Configure a secondary AWS Provider for the replica Region and account
|
|
372
|
+
|
|
373
|
+
provider "aws" {
|
|
374
|
+
|
|
375
|
+
region = "us-east-1"
|
|
376
|
+
|
|
377
|
+
alias = "replica"
|
|
378
|
+
|
|
379
|
+
assume_role {
|
|
380
|
+
|
|
381
|
+
role_arn = "arn:aws:iam::<replica-account-id>:role/<role-name>"
|
|
382
|
+
|
|
383
|
+
session_name = "terraform-session"
|
|
384
|
+
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
# Primary Amazon RDS database
|
|
390
|
+
|
|
391
|
+
resource "aws_db_instance" "primary" {
|
|
392
|
+
|
|
393
|
+
provider = aws.primary
|
|
394
|
+
|
|
395
|
+
# ... RDS instance configuration
|
|
396
|
+
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
# Read replica in a different Region and account
|
|
400
|
+
|
|
401
|
+
resource "aws_db_instance" "read_replica" {
|
|
402
|
+
|
|
403
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
404
|
+
|
|
405
|
+
provider = aws.replica
|
|
406
|
+
|
|
407
|
+
# ... RDS read replica configuration
|
|
408
|
+
|
|
409
|
+
replicate_source_db = aws_db_instance.primary.id
|
|
410
|
+
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
In this example:
|
|
414
|
+
|
|
415
|
+
*The first provider block configures the primary AWS Provider in the us-west-1 Region with
|
|
416
|
+
|
|
417
|
+
the alias primary .
|
|
418
|
+
|
|
419
|
+
*The second provider block configures a secondary AWS Provider in the us-east-1 Region
|
|
420
|
+
|
|
421
|
+
with the alias replica. This provider is used to create a read replica of the primary database in
|
|
422
|
+
|
|
423
|
+
a different Region and account. The assume_role block is used to assume an IAM role in the
|
|
424
|
+
|
|
425
|
+
replica account. The role_arn specifies the Amazon Resource Name (ARN) of the IAM role to
|
|
426
|
+
|
|
427
|
+
assume, and session_name is a unique identifier for the Terraform session.
|
|
428
|
+
|
|
429
|
+
*The aws_db_instance.primary resource creates the primary Amazon RDS database by using
|
|
430
|
+
|
|
431
|
+
the primary provider in the us-west-1 Region.
|
|
432
|
+
|
|
433
|
+
*The aws_db_instance.read_replica resource creates a read replica of the primary database
|
|
434
|
+
|
|
435
|
+
in the us-east-1 Region by using the replica provider. The replicate_source_db
|
|
436
|
+
|
|
437
|
+
attribute references the ID of the primary database.
|
|
438
|
+
|
|
439
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
440
|
+
|
|
441
|
+
## Security best practices
|
|
442
|
+
|
|
443
|
+
Properly managing authentication, access controls, and security is critical for secure usage of the
|
|
444
|
+
|
|
445
|
+
Terraform AWS Provider. This section outlines best practices around:
|
|
446
|
+
|
|
447
|
+
*IAM roles and permissions for least-privilege access
|
|
448
|
+
|
|
449
|
+
*Securing credentials to help prevent unauthorized access to AWS accounts and resources
|
|
450
|
+
|
|
451
|
+
*Remote state encryption to help protect sensitive data
|
|
452
|
+
|
|
453
|
+
*Infrastructure and source code scanning to identify misconfigurations
|
|
454
|
+
|
|
455
|
+
*Access controls for remote state storage
|
|
456
|
+
|
|
457
|
+
*Sentinel policy enforcement to implement governance guardrails
|
|
458
|
+
|
|
459
|
+
Following these best practices helps strengthen your security posture when you use Terraform to
|
|
460
|
+
|
|
461
|
+
manage AWS infrastructure.
|
|
462
|
+
|
|
463
|
+
## Follow the principle of least privilege
|
|
464
|
+
|
|
465
|
+
Least privilege is a fundamental security principle that refers to granting only the minimum
|
|
466
|
+
|
|
467
|
+
permissions required for a user, process, or system to perform its intended functions. It's a core
|
|
468
|
+
|
|
469
|
+
concept in access control and a preventative measure against unauthorized access and potential
|
|
470
|
+
|
|
471
|
+
data breaches.
|
|
472
|
+
|
|
473
|
+
The principle of least privilege is emphasized multiple times in this section because it directly
|
|
474
|
+
|
|
475
|
+
relates to how Terraform authenticates and runs actions against cloud providers such as AWS.
|
|
476
|
+
|
|
477
|
+
When you use Terraform to provision and manage AWS resources, it acts on behalf of an entity
|
|
478
|
+
|
|
479
|
+
(user or role) that requires appropriate permissions to make API calls. Not following least privilege
|
|
480
|
+
|
|
481
|
+
opens up major security risks:
|
|
482
|
+
|
|
483
|
+
*If Terraform has excessive permissions beyond what's needed, an unintended misconfiguration
|
|
484
|
+
|
|
485
|
+
could make undesired changes or deletions.
|
|
486
|
+
|
|
487
|
+
*Overly permissive access grants increase the scope of impact if Terraform state files or
|
|
488
|
+
|
|
489
|
+
credentials are compromised.
|
|
490
|
+
|
|
491
|
+
*Not following least privilege goes against security best practices and regulatory compliance
|
|
492
|
+
|
|
493
|
+
requirements for granting minimal required access.
|
|
494
|
+
|
|
495
|
+
Follow the principle of least privilege 5
|
|
496
|
+
|
|
497
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
498
|
+
|
|
499
|
+
## Use IAM roles
|
|
500
|
+
|
|
501
|
+
Use IAM roles instead of IAM users wherever possible to enhance security with the Terraform
|
|
502
|
+
|
|
503
|
+
AWS Provider. IAM roles provide temporary security credentials that automatically rotate, which
|
|
504
|
+
|
|
505
|
+
eliminates the need to manage long-term access keys. Roles also offer precise access controls
|
|
506
|
+
|
|
507
|
+
through IAM policies.
|
|
508
|
+
|
|
509
|
+
## Grant least privilege access by using IAM policies
|
|
510
|
+
|
|
511
|
+
Carefully construct IAM policies to ensure that roles and users have only the minimum set of
|
|
512
|
+
|
|
513
|
+
permissions that are required for their workload. Start with an empty policy and iteratively add
|
|
514
|
+
|
|
515
|
+
allowed services and actions. To accomplish this:
|
|
516
|
+
|
|
517
|
+
*Enable IAM Access Analyzer to evaluate policies and highlight unused permissions that can be
|
|
518
|
+
|
|
519
|
+
removed.
|
|
520
|
+
|
|
521
|
+
*Manually review policies to remove any capabilities that aren't essential for the role's intended
|
|
522
|
+
|
|
523
|
+
responsibility.
|
|
524
|
+
|
|
525
|
+
*Use IAM policy variables and tags to simplify permission management.
|
|
526
|
+
|
|
527
|
+
Well-constructed policies grant just enough access to accomplish the workload's responsibilities
|
|
528
|
+
|
|
529
|
+
and nothing more. Define actions at the operation level, and allow calls only to required APIs on
|
|
530
|
+
|
|
531
|
+
specific resources.
|
|
532
|
+
|
|
533
|
+
Following this best practice reduces the scope of impact and follows the fundamental security
|
|
534
|
+
|
|
535
|
+
principles of separation of duties and least privilege access. Start strict and open access gradually
|
|
536
|
+
|
|
537
|
+
as needed, instead of starting open and trying to restrict access later.
|
|
538
|
+
|
|
539
|
+
## Assume IAM roles for local authentication
|
|
540
|
+
|
|
541
|
+
When you run Terraform locally, avoid configuring static access keys. Instead, use IAM roles to grant
|
|
542
|
+
|
|
543
|
+
privileged access temporarily without exposing long-term credentials.
|
|
544
|
+
|
|
545
|
+
First, create an IAM role with the necessary minimum permissions and add a trust relationship
|
|
546
|
+
|
|
547
|
+
that allows the IAM role to be assumed by your user account or federated identity. This authorizes
|
|
548
|
+
|
|
549
|
+
temporary usage of the role.
|
|
550
|
+
|
|
551
|
+
Trust relationship policy example:
|
|
552
|
+
|
|
553
|
+
Use IAM roles 6
|
|
554
|
+
|
|
555
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
556
|
+
|
|
557
|
+
{
|
|
558
|
+
|
|
559
|
+
"Version": "2012-10-17",
|
|
560
|
+
|
|
561
|
+
"Statement": [
|
|
562
|
+
|
|
563
|
+
{
|
|
564
|
+
|
|
565
|
+
"Effect": "Allow",
|
|
566
|
+
|
|
567
|
+
"Principal": {
|
|
568
|
+
|
|
569
|
+
"AWS": "arn:aws:iam::111122223333:role/terraform-execution"
|
|
570
|
+
|
|
571
|
+
},
|
|
572
|
+
|
|
573
|
+
"Action": "sts:AssumeRole"
|
|
574
|
+
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
]
|
|
578
|
+
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
Then, run the AWS CLI command aws sts assume-role to retrieve short-lived credentials for the
|
|
582
|
+
|
|
583
|
+
role. These credentials are typically valid for one hour.
|
|
584
|
+
|
|
585
|
+
AWS CLI command example:
|
|
586
|
+
|
|
587
|
+
aws sts assume-role --role-arn arn:aws:iam::111122223333:role/terraform-execution --
|
|
588
|
+
|
|
589
|
+
role-session-name terraform-session-example
|
|
590
|
+
|
|
591
|
+
The output of the command contains an access key, secret key, and session token that you can use
|
|
592
|
+
|
|
593
|
+
to authenticate to AWS:
|
|
594
|
+
|
|
595
|
+
{
|
|
596
|
+
|
|
597
|
+
"AssumedRoleUser": {
|
|
598
|
+
|
|
599
|
+
"AssumedRoleId": "AROA3XFRBF535PLBIFPI4:terraform-session-example",
|
|
600
|
+
|
|
601
|
+
"Arn": "arn:aws:sts::111122223333:assumed-role/terraform-execution/terraform-
|
|
602
|
+
|
|
603
|
+
session-example"
|
|
604
|
+
|
|
605
|
+
},
|
|
606
|
+
|
|
607
|
+
"Credentials": {
|
|
608
|
+
|
|
609
|
+
"SecretAccessKey": " wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
|
|
610
|
+
|
|
611
|
+
"SessionToken": " AQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5TthT
|
|
612
|
+
|
|
613
|
+
+FvwqnKwRcOIfrRh3c/LTo6UDdyJwOOvEVPvLXCrrrUtdnniCEXAMPLE/
|
|
614
|
+
|
|
615
|
+
IvU1dYUg2RVAJBanLiHb4IgRmpRV3zrkuWJOgQs8IZZaIv2BXIa2R4OlgkBN9bkUDNCJiBeb/
|
|
616
|
+
|
|
617
|
+
AXlzBBko7b15fjrBs2+cTQtpZ3CYWFXG8C5zqx37wnOE49mRl/+OtkIKGO7fAE",
|
|
618
|
+
|
|
619
|
+
"Expiration": "2024-03-15T00:05:07Z",
|
|
620
|
+
|
|
621
|
+
"AccessKeyId": ...
|
|
622
|
+
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
The AWS Provider can also automatically handle assuming the role.
|
|
628
|
+
|
|
629
|
+
Assume IAM roles for local authentication 7
|
|
630
|
+
|
|
631
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
632
|
+
|
|
633
|
+
Provider configuration example for assuming an IAM role:
|
|
634
|
+
|
|
635
|
+
provider "aws" {
|
|
636
|
+
|
|
637
|
+
assume_role {
|
|
638
|
+
|
|
639
|
+
role_arn = "arn:aws:iam::111122223333:role/terraform-execution"
|
|
640
|
+
|
|
641
|
+
session_name = "terraform-session-example"
|
|
642
|
+
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
This grants elevated privilege strictly for the Terraform session's duration. The temporary keys
|
|
648
|
+
|
|
649
|
+
cannot be leaked because they expire automatically after the maximum duration of the session.
|
|
650
|
+
|
|
651
|
+
The key benefits of this best practice include improved security compared with long-lived access
|
|
652
|
+
|
|
653
|
+
keys, fine-grained access controls on the role for least privileges, and the ability to easily revoke
|
|
654
|
+
|
|
655
|
+
access by modifying the role's permissions. By using IAM roles, you also avoid having to directly
|
|
656
|
+
|
|
657
|
+
store secrets locally in scripts or on disk, which helps you share Terraform configuration securely
|
|
658
|
+
|
|
659
|
+
across a team.
|
|
660
|
+
|
|
661
|
+
Use IAM roles for Amazon EC2 authentication
|
|
662
|
+
|
|
663
|
+
When you run Terraform from Amazon Elastic Compute Cloud (Amazon EC2) instances, avoid
|
|
664
|
+
|
|
665
|
+
storing long-term credentials locally. Instead, use IAM roles and instance profiles to grant least-
|
|
666
|
+
|
|
667
|
+
privilege permissions automatically.
|
|
668
|
+
|
|
669
|
+
First, create an IAM role with the minimum permissions and assign the role to the instance profile.
|
|
670
|
+
|
|
671
|
+
The instance profile allows EC2 instances to inherit the permissions defined in the role. Then,
|
|
672
|
+
|
|
673
|
+
launch instances by specifying that instance profile. The instance will authenticate through the
|
|
674
|
+
|
|
675
|
+
attached role.
|
|
676
|
+
|
|
677
|
+
Before you run any Terraform operations, verify that the role is present in the instance metadata to
|
|
678
|
+
|
|
679
|
+
confirm that the credentials were successfully inherited.
|
|
680
|
+
|
|
681
|
+
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-
|
|
682
|
+
|
|
683
|
+
metadata-token-ttl-seconds: 21600")
|
|
684
|
+
|
|
685
|
+
curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/
|
|
686
|
+
|
|
687
|
+
iam/security-credentials/
|
|
688
|
+
|
|
689
|
+
This approach avoids hardcoding permanent AWS keys into scripts or Terraform configuration
|
|
690
|
+
|
|
691
|
+
within the instance. The temporary credentials are made available to Terraform transparently
|
|
692
|
+
|
|
693
|
+
through the instance role and profile.
|
|
694
|
+
|
|
695
|
+
Use IAM roles for Amazon EC2 authentication 8
|
|
696
|
+
|
|
697
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
698
|
+
|
|
699
|
+
The key benefits of this best practice include improved security over long-term credentials,
|
|
700
|
+
|
|
701
|
+
reduced credential management overhead, and consistency between development, test, and
|
|
702
|
+
|
|
703
|
+
production environments. IAM role authentication simplifies Terraform runs from EC2 instances
|
|
704
|
+
|
|
705
|
+
while enforcing least-privilege access.
|
|
706
|
+
|
|
707
|
+
## Use dynamic credentials for HCP Terraform workspaces
|
|
708
|
+
|
|
709
|
+
HCP Terraform is a managed service provided by HashiCorp that helps teams use Terraform to
|
|
710
|
+
|
|
711
|
+
provision and manage infrastructure across multiple projects and environments. When you run
|
|
712
|
+
|
|
713
|
+
Terraform in HCP Terraform, use dynamic credentials to simplify and secure AWS authentication.
|
|
714
|
+
|
|
715
|
+
Terraform automatically exchanges temporary credentials on each run without needing IAM role
|
|
716
|
+
|
|
717
|
+
assumption.
|
|
718
|
+
|
|
719
|
+
Benefits include easier secret rotation, centralized credential management across workspaces,
|
|
720
|
+
|
|
721
|
+
least-privilege permissions, and eliminating hardcoded keys. Relying on hashed ephemeral keys
|
|
722
|
+
|
|
723
|
+
enhances security compared with long-lived access keys.
|
|
724
|
+
|
|
725
|
+
## Use IAM roles in AWS CodeBuild
|
|
726
|
+
|
|
727
|
+
In AWS CodeBuild, run your builds by using an IAM role that's assigned to the CodeBuild project.
|
|
728
|
+
|
|
729
|
+
This allows each build to automatically inherit temporary credentials from the role instead of using
|
|
730
|
+
|
|
731
|
+
long-term keys.
|
|
732
|
+
|
|
733
|
+
## Run GitHub Actions remotely on HCP Terraform
|
|
734
|
+
|
|
735
|
+
Configure GitHub Actions workflows to run Terraform remotely on HCP Terraform workspaces. Rely
|
|
736
|
+
|
|
737
|
+
on dynamic credentials and remote state locking instead of GitHub secrets management.
|
|
738
|
+
|
|
739
|
+
Use GitHub Actions with OIDC and configure the AWS Credentials
|
|
740
|
+
|
|
741
|
+
action
|
|
742
|
+
|
|
743
|
+
Use the OpenID Connect (OIDC) standard to federate GitHub Actions identity through IAM. Use the
|
|
744
|
+
|
|
745
|
+
Configure AWS Credentials action to exchange the GitHub token for temporary AWS credentials
|
|
746
|
+
|
|
747
|
+
without needing long-term access keys.
|
|
748
|
+
|
|
749
|
+
## Use GitLab with OIDC and the AWS CLI
|
|
750
|
+
|
|
751
|
+
Use the OIDC standard to federate GitLab identities through IAM for temporary access. By
|
|
752
|
+
|
|
753
|
+
relying on OIDC, you avoid having to directly manage long-term AWS access keys within GitLab.
|
|
754
|
+
|
|
755
|
+
Use dynamic credentials for HCP Terraform workspaces 9
|
|
756
|
+
|
|
757
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
758
|
+
|
|
759
|
+
Credentials are exchanged just-in-time, which improves security. Users also gain least privilege
|
|
760
|
+
|
|
761
|
+
access according to the permissions in the IAM role.
|
|
762
|
+
|
|
763
|
+
## Use unique IAM users with legacy automation tools
|
|
764
|
+
|
|
765
|
+
If you have automation tools and scripts that lack native support for using IAM roles, you can
|
|
766
|
+
|
|
767
|
+
create individual IAM users to grant programmatic access. The principle of least privilege still
|
|
768
|
+
|
|
769
|
+
applies. Minimize policy permissions and rely on separate roles for each pipeline or script. As you
|
|
770
|
+
|
|
771
|
+
migrate to more modern tools or scripts, begin supporting roles natively and gradually transition
|
|
772
|
+
|
|
773
|
+
to them.
|
|
774
|
+
|
|
775
|
+
## Warning
|
|
776
|
+
|
|
777
|
+
IAM users have long-term credentials, which present a security risk. To help mitigate this
|
|
778
|
+
|
|
779
|
+
risk, we recommend that you provide these users with only the permissions they require to
|
|
780
|
+
|
|
781
|
+
perform the task and that you remove these users when they are no longer needed.
|
|
782
|
+
|
|
783
|
+
## Use the Jenkins AWS Credentials plugin
|
|
784
|
+
|
|
785
|
+
Use the AWS Credentials plugin in Jenkins to centrally configure and inject AWS credentials into
|
|
786
|
+
|
|
787
|
+
builds dynamically. This avoids checking secrets into source control.
|
|
788
|
+
|
|
789
|
+
Continuously monitor, validate, and optimize least privilege
|
|
790
|
+
|
|
791
|
+
Over time, additional permissions might get granted that can exceed the minimum policies
|
|
792
|
+
|
|
793
|
+
required. Continuously analyze access to identify and remove any unnecessary entitlements.
|
|
794
|
+
|
|
795
|
+
## Continuously monitor access key usage
|
|
796
|
+
|
|
797
|
+
If you cannot avoid using access keys, use IAM credential reports to find unused access keys that
|
|
798
|
+
|
|
799
|
+
are older than 90 days, and revoke inactive keys across both user accounts and machine roles. Alert
|
|
800
|
+
|
|
801
|
+
administrators to manually confirm the removal of keys for active employees and systems.
|
|
802
|
+
|
|
803
|
+
Monitoring key usage helps you optimize permissions because you can identify and remove unused
|
|
804
|
+
|
|
805
|
+
entitlements. When you follow this best practice with access key rotation, it limits credential
|
|
806
|
+
|
|
807
|
+
lifespan and enforces least privilege access.
|
|
808
|
+
|
|
809
|
+
Use unique IAM users with legacy automation tools 10
|
|
810
|
+
|
|
811
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
812
|
+
|
|
813
|
+
AWS provides several services and features that you can use to set up alerts and notifications for
|
|
814
|
+
|
|
815
|
+
administrators. Here are some options:
|
|
816
|
+
|
|
817
|
+
*AWS Config: You can use AWS Config rules to evaluate the configuration settings of your AWS
|
|
818
|
+
|
|
819
|
+
resources, including IAM access keys. You can create custom rules to check for specific conditions,
|
|
820
|
+
|
|
821
|
+
such as unused access keys that are older than a specific number of days. When a rule is violated,
|
|
822
|
+
|
|
823
|
+
AWS Config can start an evaluation for remediation or send notifications to an Amazon Simple
|
|
824
|
+
|
|
825
|
+
Notification Service (Amazon SNS) topic.
|
|
826
|
+
|
|
827
|
+
*AWS Security Hub: Security Hub provides a comprehensive view of your AWS account's security
|
|
828
|
+
|
|
829
|
+
posture and can help detect and notify you about potential security issues, including unused or
|
|
830
|
+
|
|
831
|
+
inactive IAM access keys. Security Hub can integrate with Amazon EventBridge and Amazon SNS
|
|
832
|
+
|
|
833
|
+
or Amazon Q Developer in chat applications to send notifications to administrators.
|
|
834
|
+
|
|
835
|
+
*AWS Lambda: Lambda functions can be called by various events, including Amazon CloudWatch
|
|
836
|
+
|
|
837
|
+
Events or AWS Config rules. You can write custom Lambda functions to evaluate IAM access key
|
|
838
|
+
|
|
839
|
+
usage, perform additional checks, and send notifications by using services such as Amazon SNS
|
|
840
|
+
|
|
841
|
+
or Amazon Q Developer in chat applications.
|
|
842
|
+
|
|
843
|
+
## Continually validate IAM policies
|
|
844
|
+
|
|
845
|
+
Use IAM Access Analyzer to evaluate policies that are attached to roles and identify any unused
|
|
846
|
+
|
|
847
|
+
services or excess actions that were granted. Implement periodic access reviews to manually verify
|
|
848
|
+
|
|
849
|
+
that policies match current requirements.
|
|
850
|
+
|
|
851
|
+
Compare the existing policy with the policy generated by IAM Access Analyzer and remove any
|
|
852
|
+
|
|
853
|
+
unnecessary permissions. You should also provide reports to users and automatically revoke
|
|
854
|
+
|
|
855
|
+
unused permissions after a grace period. This helps ensure that minimal policies remain in effect.
|
|
856
|
+
|
|
857
|
+
Proactively and frequently revoking obsolete access minimizes the credentials that might be at risk
|
|
858
|
+
|
|
859
|
+
during a breach. Automation provides sustainable, long-term credential hygiene and permissions
|
|
860
|
+
|
|
861
|
+
optimization. Following this best practice limits the scope of impact by proactively enforcing least
|
|
862
|
+
|
|
863
|
+
privilege across AWS identities and resources.
|
|
864
|
+
|
|
865
|
+
## Secure remote state storage
|
|
866
|
+
|
|
867
|
+
Remote state storage refers to storing the Terraform state file remotely instead of locally on the
|
|
868
|
+
|
|
869
|
+
machine where Terraform is running. The state file is crucial because it keeps track of the resources
|
|
870
|
+
|
|
871
|
+
that are provisioned by Terraform and their metadata.
|
|
872
|
+
|
|
873
|
+
Continually validate IAM policies 11
|
|
874
|
+
|
|
875
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
876
|
+
|
|
877
|
+
Failure to secure remote state can lead to serious issues such as loss of state data, inability to
|
|
878
|
+
|
|
879
|
+
manage infrastructure, inadvertent resource deletion, and exposure of sensitive information that
|
|
880
|
+
|
|
881
|
+
might be present in the state file. For this reason, securing remote state storage is crucial for
|
|
882
|
+
|
|
883
|
+
production-grade Terraform usage.
|
|
884
|
+
|
|
885
|
+
## Enable encryption and access controls
|
|
886
|
+
|
|
887
|
+
Use Amazon Simple Storage Service (Amazon S3) server-side encryption (SSE) to encrypt remote
|
|
888
|
+
|
|
889
|
+
state at rest.
|
|
890
|
+
|
|
891
|
+
Limit direct access to collaborative workflows
|
|
892
|
+
|
|
893
|
+
*Structure collaboration workflows in HCP Terraform or in a CI/CD pipeline within your Git
|
|
894
|
+
|
|
895
|
+
repository to limit direct state access.
|
|
896
|
+
|
|
897
|
+
*Rely on pull requests, run approvals, policy checks, and notifications to coordinate changes.
|
|
898
|
+
|
|
899
|
+
Following these guidelines helps secure sensitive resource attributes and avoids conflicts with team
|
|
900
|
+
|
|
901
|
+
members' changes. Encryption and strict access protections help reduce the attack surface, and
|
|
902
|
+
|
|
903
|
+
collaboration workflows enable productivity.
|
|
904
|
+
|
|
905
|
+
## Use AWS Secrets Manager
|
|
906
|
+
|
|
907
|
+
There are many resources and data sources in Terraform that store secret values in plaintext in the
|
|
908
|
+
|
|
909
|
+
state file. Avoid storing secrets in state―use AWS Secrets Manager instead.
|
|
910
|
+
|
|
911
|
+
Instead of attempting to manually encrypt sensitive values, rely on Terraform's built-in support for
|
|
912
|
+
|
|
913
|
+
sensitive state management. When exporting sensitive values to output, make sure that the values
|
|
914
|
+
|
|
915
|
+
are marked as sensitive.
|
|
916
|
+
|
|
917
|
+
## Continuously scan infrastructure and source code
|
|
918
|
+
|
|
919
|
+
Proactively scan both infrastructure and source code continuously for risks such as exposed
|
|
920
|
+
|
|
921
|
+
credentials or misconfigurations to harden your security posture. Address findings promptly by
|
|
922
|
+
|
|
923
|
+
reconfiguring or patching resources.
|
|
924
|
+
|
|
925
|
+
Enable encryption and access controls 12
|
|
926
|
+
|
|
927
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
928
|
+
|
|
929
|
+
## Use AWS services for dynamic scanning
|
|
930
|
+
|
|
931
|
+
Use AWS native tools such as Amazon Inspector, AWS Security Hub, Amazon Detective, and
|
|
932
|
+
|
|
933
|
+
Amazon GuardDuty to monitor provisioned infrastructure across accounts and Regions. Schedule
|
|
934
|
+
|
|
935
|
+
recurring scans in Security Hub to track deployment and configuration drift. Scan EC2 instances,
|
|
936
|
+
|
|
937
|
+
Lambda functions, containers, S3 buckets, and other resources.
|
|
938
|
+
|
|
939
|
+
## Perform static analysis
|
|
940
|
+
|
|
941
|
+
Embed static analyzers such as Checkov directly into CI/CD pipelines to scan Terraform
|
|
942
|
+
|
|
943
|
+
configuration code (HCL) and identify risks preemptively before deployment. This moves security
|
|
944
|
+
|
|
945
|
+
checks to an earlier point in the development process (referred to as shifting left) and prevents
|
|
946
|
+
|
|
947
|
+
misconfigured infrastructure.
|
|
948
|
+
|
|
949
|
+
## Ensure prompt remediation
|
|
950
|
+
|
|
951
|
+
For all scan findings, ensure prompt remediation by either updating Terraform configuration,
|
|
952
|
+
|
|
953
|
+
applying patches, or reconfiguring resources manually as appropriate. Lower risk levels by
|
|
954
|
+
|
|
955
|
+
addressing the root causes.
|
|
956
|
+
|
|
957
|
+
Using both infrastructure scanning and code scanning provides layered insight across Terraform
|
|
958
|
+
|
|
959
|
+
configurations, the provisioned resources, and application code. This maximizes the coverage of risk
|
|
960
|
+
|
|
961
|
+
and compliance through preventative, detective, and reactive controls while embedding security
|
|
962
|
+
|
|
963
|
+
earlier into the software development lifecycle (SDLC).
|
|
964
|
+
|
|
965
|
+
## Enforce policy checks
|
|
966
|
+
|
|
967
|
+
Use code frameworks such as HashiCorp Sentinel policies to provide governance guardrails and
|
|
968
|
+
|
|
969
|
+
standardized templates for infrastructure provisioning with Terraform.
|
|
970
|
+
|
|
971
|
+
Sentinel policies can define requirements or restrictions on Terraform configuration to align with
|
|
972
|
+
|
|
973
|
+
organizational standards and best practices. For example, you can use Sentinel policies to:
|
|
974
|
+
|
|
975
|
+
*Require tags on all resources.
|
|
976
|
+
|
|
977
|
+
*Restrict instance types to an approved list.
|
|
978
|
+
|
|
979
|
+
*Enforce mandatory variables.
|
|
980
|
+
|
|
981
|
+
*Prevent the destruction of production resources.
|
|
982
|
+
|
|
983
|
+
Use AWS services for dynamic scanning 13
|
|
984
|
+
|
|
985
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
986
|
+
|
|
987
|
+
Embedding policy checks into Terraform configuration lifecycles enables proactive enforcement of
|
|
988
|
+
|
|
989
|
+
standards and architecture guidelines. Sentinel provides shared policy logic that helps accelerate
|
|
990
|
+
|
|
991
|
+
development while preventing unapproved practices.
|
|
992
|
+
|
|
993
|
+
Enforce policy checks 14
|
|
994
|
+
|
|
995
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
996
|
+
|
|
997
|
+
## Backend best practices
|
|
998
|
+
|
|
999
|
+
Using a proper remote backend to store your state file is critical for enabling collaboration,
|
|
1000
|
+
|
|
1001
|
+
ensuring state file integrity through locking, providing reliable backup and recovery, integrating
|
|
1002
|
+
|
|
1003
|
+
with CI/CD workflows, and taking advantage of advanced security, governance, and management
|
|
1004
|
+
|
|
1005
|
+
features offered by managed services such as HCP Terraform.
|
|
1006
|
+
|
|
1007
|
+
Terraform supports various backend types such as Kubernetes, HashiCorp Consul, and HTTP.
|
|
1008
|
+
|
|
1009
|
+
However, this guide focuses on Amazon S3, which is an optimal backend solution for most AWS
|
|
1010
|
+
|
|
1011
|
+
users.
|
|
1012
|
+
|
|
1013
|
+
As a fully managed object storage service that offers high durability and availability, Amazon S3
|
|
1014
|
+
|
|
1015
|
+
provides a secure, scalable and low-cost backend for managing Terraform state on AWS. The global
|
|
1016
|
+
|
|
1017
|
+
footprint and resilience of Amazon S3 exceeds what most teams can achieve by self-managing
|
|
1018
|
+
|
|
1019
|
+
state storage. Additionally, being natively integrated with AWS access controls, encryption options,
|
|
1020
|
+
|
|
1021
|
+
versioning capabilities, and other services makes Amazon S3 a convenient backend choice.
|
|
1022
|
+
|
|
1023
|
+
This guide doesn't provide backend guidance for other solutions such as Kubernetes or Consul
|
|
1024
|
+
|
|
1025
|
+
because the primary target audience is AWS customers. For teams that are fully in the AWS
|
|
1026
|
+
|
|
1027
|
+
Cloud, Amazon S3 is typically the ideal choice over Kubernetes or HashiCorp Consul clusters. The
|
|
1028
|
+
|
|
1029
|
+
simplicity, resilience, and tight AWS integration of Amazon S3 state storage provides an optimal
|
|
1030
|
+
|
|
1031
|
+
foundation for most users who follow AWS best practices. Teams can take advantage of the
|
|
1032
|
+
|
|
1033
|
+
durability, backup protections, and availability of AWS services to keep remote Terraform state
|
|
1034
|
+
|
|
1035
|
+
highly resilient.
|
|
1036
|
+
|
|
1037
|
+
Following the backend recommendations in this section will lead to more collaborative Terraform
|
|
1038
|
+
|
|
1039
|
+
code bases while limiting the impact of errors or unauthorized modifications. By implementing a
|
|
1040
|
+
|
|
1041
|
+
well-architected remote backend, teams can optimize Terraform workflows.
|
|
1042
|
+
|
|
1043
|
+
Best practices:
|
|
1044
|
+
|
|
1045
|
+
*Use Amazon S3 for remote storage
|
|
1046
|
+
|
|
1047
|
+
*Facilitate team collaboration
|
|
1048
|
+
|
|
1049
|
+
*Separate the backends for each environment
|
|
1050
|
+
|
|
1051
|
+
*Actively monitor remote state activity
|
|
1052
|
+
|
|
1053
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1054
|
+
|
|
1055
|
+
Use Amazon S3 for remote storage
|
|
1056
|
+
|
|
1057
|
+
Storing Terraform state remotely in Amazon S3 and implementing state locking and consistency
|
|
1058
|
+
|
|
1059
|
+
checking by using Amazon DynamoDB provide major benefits over local file storage. Remote state
|
|
1060
|
+
|
|
1061
|
+
enables team collaboration, change tracking, backup protections, and remote locking for increased
|
|
1062
|
+
|
|
1063
|
+
safety.
|
|
1064
|
+
|
|
1065
|
+
Using Amazon S3 with the S3 Standard storage class (default) instead of ephemeral local storage
|
|
1066
|
+
|
|
1067
|
+
or self-managed solutions provides 99.999999999% durability and 99.99% availability protections
|
|
1068
|
+
|
|
1069
|
+
to prevent accidental state data loss. AWS managed services such as Amazon S3 and DynamoDB
|
|
1070
|
+
|
|
1071
|
+
provide service-level agreements (SLAs) that exceed what most organizations can achieve when
|
|
1072
|
+
|
|
1073
|
+
they self-manage storage. Rely on these protections to keep remote backends accessible.
|
|
1074
|
+
|
|
1075
|
+
## Enable remote state locking
|
|
1076
|
+
|
|
1077
|
+
DynamoDB locking restricts state access to prevent concurrent write operations. This prevents
|
|
1078
|
+
|
|
1079
|
+
simultaneous modifications from multiple users and reduces errors.
|
|
1080
|
+
|
|
1081
|
+
Example backend configuration with state locking:
|
|
1082
|
+
|
|
1083
|
+
terraform {
|
|
1084
|
+
|
|
1085
|
+
backend "s3" {
|
|
1086
|
+
|
|
1087
|
+
bucket = "myorg-terraform-states"
|
|
1088
|
+
|
|
1089
|
+
key = "myapp/production/tfstate"
|
|
1090
|
+
|
|
1091
|
+
region = "us-east-1"
|
|
1092
|
+
|
|
1093
|
+
dynamodb_table = "TerraformStateLocking"
|
|
1094
|
+
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
## Enable versioning and automatic backups
|
|
1100
|
+
|
|
1101
|
+
For additional safeguarding, enable automatic versioning and backups by using AWS Backup on
|
|
1102
|
+
|
|
1103
|
+
Amazon S3 backends. Versioning preserves all previous versions of the state whenever changes are
|
|
1104
|
+
|
|
1105
|
+
made. It also lets you restore previous working state snapshots if needed to roll back unwanted
|
|
1106
|
+
|
|
1107
|
+
changes or recover from accidents.
|
|
1108
|
+
|
|
1109
|
+
Use Amazon S3 for remote storage 16
|
|
1110
|
+
|
|
1111
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1112
|
+
|
|
1113
|
+
## Restore previous versions if needed
|
|
1114
|
+
|
|
1115
|
+
Versioned Amazon S3 state buckets make it easy to revert changes by restoring a previous known
|
|
1116
|
+
|
|
1117
|
+
good state snapshot. This helps protect against accidental changes and provides additional backup
|
|
1118
|
+
|
|
1119
|
+
capabilities.
|
|
1120
|
+
|
|
1121
|
+
## Use HCP Terraform
|
|
1122
|
+
|
|
1123
|
+
HCP Terraform provides a fully managed backend alternative to configuring your own state
|
|
1124
|
+
|
|
1125
|
+
storage. HCP Terraform automatically handles the secure storage of state and encryption while
|
|
1126
|
+
|
|
1127
|
+
unlocking additional features.
|
|
1128
|
+
|
|
1129
|
+
When you use HCP Terraform, state is stored remotely by default, which enables state sharing
|
|
1130
|
+
|
|
1131
|
+
and locking across your organization. Detailed policy controls help you restrict state access and
|
|
1132
|
+
|
|
1133
|
+
changes.
|
|
1134
|
+
|
|
1135
|
+
Additional capabilities include version control integrations, policy guardrails, workflow automation,
|
|
1136
|
+
|
|
1137
|
+
variables management, and single sign-on integrations with SAML. You can also use Sentinel policy
|
|
1138
|
+
|
|
1139
|
+
as code to implement governance controls.
|
|
1140
|
+
|
|
1141
|
+
Although HCP Terraform requires using a software as a service (SaaS) platform, for many teams
|
|
1142
|
+
|
|
1143
|
+
the benefits around security, access controls, automated policy checks, and collaboration features
|
|
1144
|
+
|
|
1145
|
+
make it an optimal choice over self-managing state storage with Amazon S3 or DynamoDB.
|
|
1146
|
+
|
|
1147
|
+
Easy integration with services such as GitHub and GitLab with minor configuration also appeals to
|
|
1148
|
+
|
|
1149
|
+
users who fully embrace cloud and SaaS tools for better team workflows.
|
|
1150
|
+
|
|
1151
|
+
## Facilitate team collaboration
|
|
1152
|
+
|
|
1153
|
+
Use remote backends to share state data across all the members of your Terraform team. This
|
|
1154
|
+
|
|
1155
|
+
facilitates collaboration because it gives the entire team visibility into infrastructure changes.
|
|
1156
|
+
|
|
1157
|
+
Shared backend protocols combined with state history transparency simplify internal change
|
|
1158
|
+
|
|
1159
|
+
management. All infrastructure changes go through the established pipeline, which increases
|
|
1160
|
+
|
|
1161
|
+
business agility across the enterprise.
|
|
1162
|
+
|
|
1163
|
+
## Improve accountability by using AWS CloudTrail
|
|
1164
|
+
|
|
1165
|
+
Integrate AWS CloudTrail with the Amazon S3 bucket to capture API calls made to the state bucket.
|
|
1166
|
+
|
|
1167
|
+
Filter CloudTrail events to track PutObject , DeleteObject, and other relevant calls.
|
|
1168
|
+
|
|
1169
|
+
Restore previous versions if needed 17
|
|
1170
|
+
|
|
1171
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1172
|
+
|
|
1173
|
+
CloudTrail logs show the AWS identity of the principal that made each API call for state change.
|
|
1174
|
+
|
|
1175
|
+
The user's identity can be matched to a machine account or to members of the team who interact
|
|
1176
|
+
|
|
1177
|
+
with the backend storage.
|
|
1178
|
+
|
|
1179
|
+
Combine CloudTrail logs with Amazon S3 state versioning to tie infrastructure changes to the
|
|
1180
|
+
|
|
1181
|
+
principal who applied them. By analyzing multiple revisions, you can attribute any updates to the
|
|
1182
|
+
|
|
1183
|
+
machine account or responsible team member.
|
|
1184
|
+
|
|
1185
|
+
If an unintended or disruptive change occurs, state versioning provides rollback capabilities.
|
|
1186
|
+
|
|
1187
|
+
CloudTrail traces the change to the user so you can discuss preventative improvements.
|
|
1188
|
+
|
|
1189
|
+
We also recommend that you enforce IAM permissions to limit state bucket access. Overall, S3
|
|
1190
|
+
|
|
1191
|
+
Versioning and CloudTrail monitoring supports auditing across infrastructure changes. Teams gain
|
|
1192
|
+
|
|
1193
|
+
improved accountability, transparency, and audit capabilities into the Terraform state history.
|
|
1194
|
+
|
|
1195
|
+
## Separate the backends for each environment
|
|
1196
|
+
|
|
1197
|
+
Use distinct Terraform backends for each application environment. Separate backends isolate state
|
|
1198
|
+
|
|
1199
|
+
between development, test, and production.
|
|
1200
|
+
|
|
1201
|
+
## Reduce the scope of impact
|
|
1202
|
+
|
|
1203
|
+
Isolating state helps ensure that changes in lower environments don't impact production
|
|
1204
|
+
|
|
1205
|
+
infrastructure. Accidents or experiments in development and test environments have limited
|
|
1206
|
+
|
|
1207
|
+
impact.
|
|
1208
|
+
|
|
1209
|
+
## Restrict production access
|
|
1210
|
+
|
|
1211
|
+
Lock down permissions for the production state backend to read-only access for most users. Limit
|
|
1212
|
+
|
|
1213
|
+
who can modify the production infrastructure to the CI/CD pipeline and break glass roles.
|
|
1214
|
+
|
|
1215
|
+
## Simplify access controls
|
|
1216
|
+
|
|
1217
|
+
Managing permissions at the backend level simplifies access control between environments.
|
|
1218
|
+
|
|
1219
|
+
Using distinct S3 buckets for each application and environment means that broad read or write
|
|
1220
|
+
|
|
1221
|
+
permissions can be granted on entire backend buckets.
|
|
1222
|
+
|
|
1223
|
+
Separate the backends for each environment 18
|
|
1224
|
+
|
|
1225
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1226
|
+
|
|
1227
|
+
## Avoid shared workspaces
|
|
1228
|
+
|
|
1229
|
+
Although you can use Terraform workspaces to separate state between environments, distinct
|
|
1230
|
+
|
|
1231
|
+
backends provide stronger isolation. If you have shared workspaces, accidents can still impact
|
|
1232
|
+
|
|
1233
|
+
multiple environments.
|
|
1234
|
+
|
|
1235
|
+
Keeping environment backends fully isolated minimizes the impact of any single failure or
|
|
1236
|
+
|
|
1237
|
+
breach. Separate backends also align access controls to the environment's sensitivity level. For
|
|
1238
|
+
|
|
1239
|
+
example, you can provide write protection for the production environment and broader access for
|
|
1240
|
+
|
|
1241
|
+
development and test environments.
|
|
1242
|
+
|
|
1243
|
+
## Actively monitor remote state activity
|
|
1244
|
+
|
|
1245
|
+
Continuously monitoring remote state activity is critical for detecting potential issues early. Look
|
|
1246
|
+
|
|
1247
|
+
for anomalous unlocks, changes, or access attempts.
|
|
1248
|
+
|
|
1249
|
+
## Get alerts on suspicious unlocks
|
|
1250
|
+
|
|
1251
|
+
Most state changes should run through CI/CD pipelines. Generate alerts if state unlocks occur
|
|
1252
|
+
|
|
1253
|
+
directly through developer workstations, which could signal unauthorized or untested changes.
|
|
1254
|
+
|
|
1255
|
+
## Monitor access attempts
|
|
1256
|
+
|
|
1257
|
+
Authentication failures on state buckets might indicate reconnaissance activity. Notice if multiple
|
|
1258
|
+
|
|
1259
|
+
accounts are trying to access state, or unusual IP addresses appear, which signals compromised
|
|
1260
|
+
|
|
1261
|
+
credentials.
|
|
1262
|
+
|
|
1263
|
+
Avoid shared workspaces 19
|
|
1264
|
+
|
|
1265
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1266
|
+
|
|
1267
|
+
## Best practices for code base structure and organization
|
|
1268
|
+
|
|
1269
|
+
Proper code base structure and organization is critical as Terraform usage grows across large teams
|
|
1270
|
+
|
|
1271
|
+
and enterprises. A well-architected code base enables collaboration at scale while enhancing
|
|
1272
|
+
|
|
1273
|
+
maintainability.
|
|
1274
|
+
|
|
1275
|
+
This section provides recommendations on Terraform modularity, naming conventions,
|
|
1276
|
+
|
|
1277
|
+
documentation, and coding standards that support quality and consistency.
|
|
1278
|
+
|
|
1279
|
+
Guidance includes breaking configuration into reusable modules by environment and components,
|
|
1280
|
+
|
|
1281
|
+
establishing naming conventions by using prefixes and suffixes, documenting modules and clearly
|
|
1282
|
+
|
|
1283
|
+
explaining inputs and outputs, and applying consistent formatting rules by using automated style
|
|
1284
|
+
|
|
1285
|
+
checks.
|
|
1286
|
+
|
|
1287
|
+
Additional best practices cover logically organizing modules and resources in a structured
|
|
1288
|
+
|
|
1289
|
+
hierarchy, cataloging public and private modules in documentation, and abstracting unnecessary
|
|
1290
|
+
|
|
1291
|
+
implementation details in modules to simplify usage.
|
|
1292
|
+
|
|
1293
|
+
By implementing code base structure guidelines around modularity, documentation, standards, and
|
|
1294
|
+
|
|
1295
|
+
logical organization, you can support broad collaboration across teams while keeping Terraform
|
|
1296
|
+
|
|
1297
|
+
maintainable as usage spreads across an organization. By enforcing conventions and standards, you
|
|
1298
|
+
|
|
1299
|
+
can avoid the complexity of a fragmented code base.
|
|
1300
|
+
|
|
1301
|
+
Best practices:
|
|
1302
|
+
|
|
1303
|
+
*Implement a standard repository structure
|
|
1304
|
+
|
|
1305
|
+
*Structure for modularity
|
|
1306
|
+
|
|
1307
|
+
*Follow naming conventions
|
|
1308
|
+
|
|
1309
|
+
*Use attachment resources
|
|
1310
|
+
|
|
1311
|
+
*Use default tags
|
|
1312
|
+
|
|
1313
|
+
*Meet Terraform registry requirements
|
|
1314
|
+
|
|
1315
|
+
*Use recommended module sources
|
|
1316
|
+
|
|
1317
|
+
*Follow coding standards
|
|
1318
|
+
|
|
1319
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1320
|
+
|
|
1321
|
+
## Implement a standard repository structure
|
|
1322
|
+
|
|
1323
|
+
We recommend that you implement the following repository layout. Standardizing on these
|
|
1324
|
+
|
|
1325
|
+
consistency practices across modules improves discoverability, transparency, organization, and
|
|
1326
|
+
|
|
1327
|
+
reliability while enabling reuse across many Terraform configurations.
|
|
1328
|
+
|
|
1329
|
+
*Root module or directory: This should be the primary entry point for both Terraform root and
|
|
1330
|
+
|
|
1331
|
+
re-usable modules and is expected to be unique. If you have a more complex architecture, you
|
|
1332
|
+
|
|
1333
|
+
can use nested modules to create lightweight abstractions. This helps you describe infrastructure
|
|
1334
|
+
|
|
1335
|
+
in terms of its architecture instead of directly, in terms of physical objects.
|
|
1336
|
+
|
|
1337
|
+
*README : The root module and any nested modules should have README files. This file must
|
|
1338
|
+
|
|
1339
|
+
be named README.md . It should contain a description of the module and what it should be
|
|
1340
|
+
|
|
1341
|
+
used for. If you want to include an example of using this module with other resources, put it in
|
|
1342
|
+
|
|
1343
|
+
an examples directory. Consider including a diagram that depicts the infrastructure resources
|
|
1344
|
+
|
|
1345
|
+
the module might create and their relationships. Use terraform-docs to automatically generate
|
|
1346
|
+
|
|
1347
|
+
inputs or outputs of the module.
|
|
1348
|
+
|
|
1349
|
+
*main.tf: This is the primary entry point. For a simple module, all resources might be created in
|
|
1350
|
+
|
|
1351
|
+
this file. For a complex module, resource creation might be spread across multiple files, but any
|
|
1352
|
+
|
|
1353
|
+
nested module calls should be in the main.tf file.
|
|
1354
|
+
|
|
1355
|
+
*variables.tf and outputs.tf: These files contain the declarations for variables and outputs. All
|
|
1356
|
+
|
|
1357
|
+
variables and outputs should have one-sentence or two-sentence descriptions that explain
|
|
1358
|
+
|
|
1359
|
+
their purpose. These descriptions are used for documentation. For more information, see the
|
|
1360
|
+
|
|
1361
|
+
HashiCorp documentation for variable configuration and output configuration.
|
|
1362
|
+
|
|
1363
|
+
*All variables must have a defined type.
|
|
1364
|
+
|
|
1365
|
+
*The variable declaration can also include a default argument. If the declaration includes a
|
|
1366
|
+
|
|
1367
|
+
default argument, the variable is considered to be optional, and the default value is used if you
|
|
1368
|
+
|
|
1369
|
+
don't set a value when you call the module or run Terraform. The default argument requires
|
|
1370
|
+
|
|
1371
|
+
a literal value and cannot reference other objects in the configuration. To make a variable
|
|
1372
|
+
|
|
1373
|
+
required, omit a default in the variable declaration and consider whether setting nullable =
|
|
1374
|
+
|
|
1375
|
+
false makes sense.
|
|
1376
|
+
|
|
1377
|
+
*For variables that have environment-independent values (such as disk_size ), provide default
|
|
1378
|
+
|
|
1379
|
+
values.
|
|
1380
|
+
|
|
1381
|
+
*For variables that have environment-specific values (such as project_id ), don't provide
|
|
1382
|
+
|
|
1383
|
+
default values. In this case, the calling module must provide meaningful values.
|
|
1384
|
+
|
|
1385
|
+
Implement a standard repository structure 21
|
|
1386
|
+
|
|
1387
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1388
|
+
|
|
1389
|
+
*Use empty defaults for variables such as empty strings or lists only when leaving the variable
|
|
1390
|
+
|
|
1391
|
+
empty is a valid preference that the underlying APIs don't reject.
|
|
1392
|
+
|
|
1393
|
+
*Be judicious in your use of variables. Parameterize values only if they must vary for each
|
|
1394
|
+
|
|
1395
|
+
instance or environment. When you decide whether to expose a variable, ensure that you have
|
|
1396
|
+
|
|
1397
|
+
a concrete use case for changing that variable. If there's only a small chance that a variable
|
|
1398
|
+
|
|
1399
|
+
might be needed, don't expose it.
|
|
1400
|
+
|
|
1401
|
+
*Adding a variable with a default value is backward compatible.
|
|
1402
|
+
|
|
1403
|
+
*Removing a variable is backward incompatible.
|
|
1404
|
+
|
|
1405
|
+
*In cases where a literal is reused in multiple places, you should use a local value without
|
|
1406
|
+
|
|
1407
|
+
exposing it as a variable.
|
|
1408
|
+
|
|
1409
|
+
*Don't pass outputs directly through input variables, because doing so prevents them from
|
|
1410
|
+
|
|
1411
|
+
being properly added to the dependency graph. To ensure that implicit dependencies are
|
|
1412
|
+
|
|
1413
|
+
created, make sure that outputs reference attributes from resources. Instead of referencing an
|
|
1414
|
+
|
|
1415
|
+
input variable for an instance directly, pass the attribute.
|
|
1416
|
+
|
|
1417
|
+
*locals.tf: This file contains local values that assign a name to an expression, so a name can be
|
|
1418
|
+
|
|
1419
|
+
used multiple times within a module instead of repeating the expression. Local values are like
|
|
1420
|
+
|
|
1421
|
+
a function's temporary local variables. The expressions in local values aren't limited to literal
|
|
1422
|
+
|
|
1423
|
+
constants; they can also reference other values in the module, including variables, resource
|
|
1424
|
+
|
|
1425
|
+
attributes, or other local values, in order to combine them.
|
|
1426
|
+
|
|
1427
|
+
*providers.tf: This file contains the terraform block and provider blocks. provider blocks must
|
|
1428
|
+
|
|
1429
|
+
be declared only in root modules by consumers of modules.
|
|
1430
|
+
|
|
1431
|
+
If you're using HCP Terraform, also add an empty cloud block . The cloud block should be
|
|
1432
|
+
|
|
1433
|
+
configured entirely through environment variables and environment variable credentials as part
|
|
1434
|
+
|
|
1435
|
+
of a CI/CD pipeline.
|
|
1436
|
+
|
|
1437
|
+
*versions.tf: This file contains the required_providers block. All Terraform modules must declare
|
|
1438
|
+
|
|
1439
|
+
which providers it requires so that Terraform can install and use these providers.
|
|
1440
|
+
|
|
1441
|
+
*data.tf: For simple configuration, put data sources next to the resources that reference them.
|
|
1442
|
+
|
|
1443
|
+
For example, if you are fetching an image to be used in launching an instance, place it alongside
|
|
1444
|
+
|
|
1445
|
+
the instance instead of collecting data resources in their own file. If the number of data sources
|
|
1446
|
+
|
|
1447
|
+
becomes too large, consider moving them to a dedicated data.tf file.
|
|
1448
|
+
|
|
1449
|
+
*.tfvars files: For root modules, you can provide non-sensitive variables by using a .tfvars file.
|
|
1450
|
+
|
|
1451
|
+
For consistency, name the variable files terraform.tfvars . Place common values at the root
|
|
1452
|
+
|
|
1453
|
+
of the repository, and environment-specific values within the envs/ folder.
|
|
1454
|
+
|
|
1455
|
+
Implement a standard repository structure 22
|
|
1456
|
+
|
|
1457
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1458
|
+
|
|
1459
|
+
*Nested modules: Nested modules should exist under the modules/ subdirectory. Any nested
|
|
1460
|
+
|
|
1461
|
+
module that has a README.md is considered usable by an external user. If a README.md doesn't
|
|
1462
|
+
|
|
1463
|
+
exist, the module is considered for internal use only. Nested modules should be used to split
|
|
1464
|
+
|
|
1465
|
+
complex behavior into multiple small modules that users can carefully pick and choose.
|
|
1466
|
+
|
|
1467
|
+
If the root module includes calls to nested modules, these calls should use relative paths such
|
|
1468
|
+
|
|
1469
|
+
as ./modules/sample-module so that Terraform will consider them to be part of the same
|
|
1470
|
+
|
|
1471
|
+
repository or package instead of downloading them again separately.
|
|
1472
|
+
|
|
1473
|
+
If a repository or package contains multiple nested modules, they should ideally be composable
|
|
1474
|
+
|
|
1475
|
+
by the caller instead of directly calling each other and creating a deeply nested tree of modules.
|
|
1476
|
+
|
|
1477
|
+
*Examples: Examples of using a reusable module should exist under the examples/ subdirectory
|
|
1478
|
+
|
|
1479
|
+
at the root of the repository. For each example, you can add a README to explain the goal and
|
|
1480
|
+
|
|
1481
|
+
usage of the example. Examples for submodules should also be placed in the root examples/
|
|
1482
|
+
|
|
1483
|
+
directory.
|
|
1484
|
+
|
|
1485
|
+
Because examples are often copied into other repositories for customization, module blocks
|
|
1486
|
+
|
|
1487
|
+
should have their source set to the address an external caller would use, not to a relative path.
|
|
1488
|
+
|
|
1489
|
+
*Service named files: Users often want to separate Terraform resources by service in multiple
|
|
1490
|
+
|
|
1491
|
+
files. This practice should be discouraged as much as possible, and resources should be defined
|
|
1492
|
+
|
|
1493
|
+
in main.tf instead. However, if a collection of resources (for example, IAM roles and policies)
|
|
1494
|
+
|
|
1495
|
+
exceeds 150 lines, it's reasonable to break it into its own files, such as iam.tf. Otherwise, all
|
|
1496
|
+
|
|
1497
|
+
resource code should be defined in the main.tf .
|
|
1498
|
+
|
|
1499
|
+
*Custom scripts : Use scripts only when necessary. Terraform doesn't account for, or manage,
|
|
1500
|
+
|
|
1501
|
+
the state of resources that are created through scripts. Use custom scripts only when Terraform
|
|
1502
|
+
|
|
1503
|
+
resources don't support the desired behavior. Place custom scripts called by Terraform in a
|
|
1504
|
+
|
|
1505
|
+
scripts/ directory.
|
|
1506
|
+
|
|
1507
|
+
*Helper scripts : Organize helper scripts that aren't called by Terraform in a helpers/ directory.
|
|
1508
|
+
|
|
1509
|
+
Document helper scripts in the README.md file with explanations and example invocations. If
|
|
1510
|
+
|
|
1511
|
+
helper scripts accept arguments, provide argument checking and --help output.
|
|
1512
|
+
|
|
1513
|
+
*Static files: Static files that Terraform references but doesn't run (such as startup scripts loaded
|
|
1514
|
+
|
|
1515
|
+
onto EC2 instances) must be organized into a files/ directory. Place lengthy documents in
|
|
1516
|
+
|
|
1517
|
+
external files, separate from their HCL. Reference them with the file() function.
|
|
1518
|
+
|
|
1519
|
+
*Templates: For files that the Terraform templatefile function reads in, use the file extension
|
|
1520
|
+
|
|
1521
|
+
.tftpl. Templates must be placed in a templates/ directory.
|
|
1522
|
+
|
|
1523
|
+
Implement a standard repository structure 23
|
|
1524
|
+
|
|
1525
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1526
|
+
|
|
1527
|
+
## Root module structure
|
|
1528
|
+
|
|
1529
|
+
Terraform always runs in the context of a single root module. A complete Terraform configuration
|
|
1530
|
+
|
|
1531
|
+
consists of a root module and the tree of child modules (which includes the modules that are called
|
|
1532
|
+
|
|
1533
|
+
by the root module, any modules called by those modules, and so on).
|
|
1534
|
+
|
|
1535
|
+
Terraform root module layout basic example:
|
|
1536
|
+
|
|
1537
|
+
.
|
|
1538
|
+
|
|
1539
|
+
### data.tf
|
|
1540
|
+
|
|
1541
|
+
### envs
|
|
1542
|
+
|
|
1543
|
+
# ### dev
|
|
1544
|
+
|
|
1545
|
+
# # ### terraform.tfvars
|
|
1546
|
+
|
|
1547
|
+
# ### prod
|
|
1548
|
+
|
|
1549
|
+
# # ### terraform.tfvars
|
|
1550
|
+
|
|
1551
|
+
# ### test
|
|
1552
|
+
|
|
1553
|
+
# ### terraform.tfvars
|
|
1554
|
+
|
|
1555
|
+
### locals.tf
|
|
1556
|
+
|
|
1557
|
+
### main.tf
|
|
1558
|
+
|
|
1559
|
+
### outputs.tf
|
|
1560
|
+
|
|
1561
|
+
### providers.tf
|
|
1562
|
+
|
|
1563
|
+
### README.md
|
|
1564
|
+
|
|
1565
|
+
### terraform.tfvars
|
|
1566
|
+
|
|
1567
|
+
### variables.tf
|
|
1568
|
+
|
|
1569
|
+
### versions.tf
|
|
1570
|
+
|
|
1571
|
+
## Reusable module structure
|
|
1572
|
+
|
|
1573
|
+
Reusable modules follow the same concepts as root modules. To define a module, create a new
|
|
1574
|
+
|
|
1575
|
+
directory for it and place the .tf files inside, just as you would define a root module. Terraform
|
|
1576
|
+
|
|
1577
|
+
can load modules either from local relative paths or from remote repositories. If you expect a
|
|
1578
|
+
|
|
1579
|
+
module to be reused by many configurations, place it in its own version control repository. It's
|
|
1580
|
+
|
|
1581
|
+
important to keep the module tree relatively flat to make it easier to reuse the modules in different
|
|
1582
|
+
|
|
1583
|
+
combinations.
|
|
1584
|
+
|
|
1585
|
+
Terraform reusable module layout basic example:
|
|
1586
|
+
|
|
1587
|
+
.
|
|
1588
|
+
|
|
1589
|
+
### data.tf
|
|
1590
|
+
|
|
1591
|
+
### examples
|
|
1592
|
+
|
|
1593
|
+
Root module structure 24
|
|
1594
|
+
|
|
1595
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1596
|
+
|
|
1597
|
+
# ### multi-az-new-vpc
|
|
1598
|
+
|
|
1599
|
+
# # ### data.tf
|
|
1600
|
+
|
|
1601
|
+
# # ### locals.tf
|
|
1602
|
+
|
|
1603
|
+
# # ### main.tf
|
|
1604
|
+
|
|
1605
|
+
# # ### outputs.tf
|
|
1606
|
+
|
|
1607
|
+
# # ### providers.tf
|
|
1608
|
+
|
|
1609
|
+
# # ### README.md
|
|
1610
|
+
|
|
1611
|
+
# # ### terraform.tfvars
|
|
1612
|
+
|
|
1613
|
+
# # ### variables.tf
|
|
1614
|
+
|
|
1615
|
+
# # ### versions.tf
|
|
1616
|
+
|
|
1617
|
+
# # ### vpc.tf
|
|
1618
|
+
|
|
1619
|
+
# ### single-az-existing-vpc
|
|
1620
|
+
|
|
1621
|
+
# # ### data.tf
|
|
1622
|
+
|
|
1623
|
+
# # ### locals.tf
|
|
1624
|
+
|
|
1625
|
+
# # ### main.tf
|
|
1626
|
+
|
|
1627
|
+
# # ### outputs.tf
|
|
1628
|
+
|
|
1629
|
+
# # ### providers.tf
|
|
1630
|
+
|
|
1631
|
+
# # ### README.md
|
|
1632
|
+
|
|
1633
|
+
# # ### terraform.tfvars
|
|
1634
|
+
|
|
1635
|
+
# # ### variables.tf
|
|
1636
|
+
|
|
1637
|
+
# # ### versions.tf
|
|
1638
|
+
|
|
1639
|
+
### iam.tf
|
|
1640
|
+
|
|
1641
|
+
### locals.tf
|
|
1642
|
+
|
|
1643
|
+
### main.tf
|
|
1644
|
+
|
|
1645
|
+
### outputs.tf
|
|
1646
|
+
|
|
1647
|
+
### README.md
|
|
1648
|
+
|
|
1649
|
+
### variables.tf
|
|
1650
|
+
|
|
1651
|
+
### versions.tf
|
|
1652
|
+
|
|
1653
|
+
## Structure for modularity
|
|
1654
|
+
|
|
1655
|
+
In principle, you can combine any resources and other constructs into a module, but overusing
|
|
1656
|
+
|
|
1657
|
+
nested and reusable modules can make your overall Terraform configuration harder to understand
|
|
1658
|
+
|
|
1659
|
+
and maintain, so use these modules in moderation.
|
|
1660
|
+
|
|
1661
|
+
When it makes sense, break your configuration into reusable modules that raise the level of
|
|
1662
|
+
|
|
1663
|
+
abstraction by describing a new concept in your architecture that is constructed from resource
|
|
1664
|
+
|
|
1665
|
+
types.
|
|
1666
|
+
|
|
1667
|
+
When you modularize your infrastructure into reusable definitions, aim for logical sets of resources
|
|
1668
|
+
|
|
1669
|
+
instead of individual components or overly complex collections.
|
|
1670
|
+
|
|
1671
|
+
Structure for modularity 25
|
|
1672
|
+
|
|
1673
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1674
|
+
|
|
1675
|
+
Don't wrap single resources
|
|
1676
|
+
|
|
1677
|
+
You shouldn't create modules that are thin wrappers around other single resource types. If you
|
|
1678
|
+
|
|
1679
|
+
have trouble finding a name for your module that's different from the name of the main resource
|
|
1680
|
+
|
|
1681
|
+
type inside it, your module probably isn't creating a new abstraction―it's adding unnecessary
|
|
1682
|
+
|
|
1683
|
+
complexity. Instead, use the resource type directly in the calling module.
|
|
1684
|
+
|
|
1685
|
+
## Encapsulate logical relationships
|
|
1686
|
+
|
|
1687
|
+
Group sets of related resources such as networking foundations, data tiers, security controls, and
|
|
1688
|
+
|
|
1689
|
+
applications. A reusable module should encapsulate infrastructure pieces that work together to
|
|
1690
|
+
|
|
1691
|
+
enable a capability.
|
|
1692
|
+
|
|
1693
|
+
Keep inheritance flat
|
|
1694
|
+
|
|
1695
|
+
When you nest modules in subdirectories, avoid going more than one or two levels deep. Deeply
|
|
1696
|
+
|
|
1697
|
+
nested inheritance structures complicate configurations and troubleshooting. Modules should build
|
|
1698
|
+
|
|
1699
|
+
on other modules―not build tunnels through them.
|
|
1700
|
+
|
|
1701
|
+
By focusing modules on logical resource groupings that represent architecture patterns, teams can
|
|
1702
|
+
|
|
1703
|
+
quickly configure reliable infrastructure foundations. Balance abstraction without over-engineering
|
|
1704
|
+
|
|
1705
|
+
or over-simplification.
|
|
1706
|
+
|
|
1707
|
+
## Reference resources in outputs
|
|
1708
|
+
|
|
1709
|
+
For every resource that's defined in a reusable module, include at least one output that references
|
|
1710
|
+
|
|
1711
|
+
the resource. Variables and outputs let you infer dependencies between modules and resources.
|
|
1712
|
+
|
|
1713
|
+
Without any outputs, users cannot properly order your module in relation to their Terraform
|
|
1714
|
+
|
|
1715
|
+
configurations.
|
|
1716
|
+
|
|
1717
|
+
Well-structured modules that provide environment consistency, purpose-driven groupings, and
|
|
1718
|
+
|
|
1719
|
+
exported resource references enable organization-wide Terraform collaboration at scale. Teams can
|
|
1720
|
+
|
|
1721
|
+
assemble infrastructure from reusable building blocks.
|
|
1722
|
+
|
|
1723
|
+
Don't configure providers
|
|
1724
|
+
|
|
1725
|
+
Although shared modules inherit providers from calling modules, modules should not configure
|
|
1726
|
+
|
|
1727
|
+
provider settings themselves. Avoid specifying provider configuration blocks in modules. This
|
|
1728
|
+
|
|
1729
|
+
configuration should only be declared once globally.
|
|
1730
|
+
|
|
1731
|
+
Don't wrap single resources 26
|
|
1732
|
+
|
|
1733
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1734
|
+
|
|
1735
|
+
## Declare required providers
|
|
1736
|
+
|
|
1737
|
+
Although provider configurations are shared between modules, shared modules must also declare
|
|
1738
|
+
|
|
1739
|
+
their own provider requirements. This practice enables Terraform to ensure that there is a single
|
|
1740
|
+
|
|
1741
|
+
version of the provider that's compatible with all modules in the configuration, and to specify the
|
|
1742
|
+
|
|
1743
|
+
source address that serves as the global (module-agnostic) identifier for the provider. However,
|
|
1744
|
+
|
|
1745
|
+
module-specific provider requirements don't specify any of the configuration settings that
|
|
1746
|
+
|
|
1747
|
+
determine what remote endpoints the provider will access, such as an AWS Region.
|
|
1748
|
+
|
|
1749
|
+
By declaring version requirements and avoiding hardcoded provider configuration, modules provide
|
|
1750
|
+
|
|
1751
|
+
portability and reusability across Terraform configurations using shared providers.
|
|
1752
|
+
|
|
1753
|
+
For shared modules, define the minimum required provider versions in a required_providers block
|
|
1754
|
+
|
|
1755
|
+
in versions.tf .
|
|
1756
|
+
|
|
1757
|
+
To declare that a module requires a particular version of the AWS provider, use a
|
|
1758
|
+
|
|
1759
|
+
required_providers block inside a terraform block:
|
|
1760
|
+
|
|
1761
|
+
terraform {
|
|
1762
|
+
|
|
1763
|
+
required_version = ">= 1.0.0"
|
|
1764
|
+
|
|
1765
|
+
required_providers {
|
|
1766
|
+
|
|
1767
|
+
aws = {
|
|
1768
|
+
|
|
1769
|
+
source = "hashicorp/aws"
|
|
1770
|
+
|
|
1771
|
+
version = ">= 4.0.0"
|
|
1772
|
+
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
}
|
|
1776
|
+
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1779
|
+
If a shared module supports only a specific version of the AWS provider, use the pessimistic
|
|
1780
|
+
|
|
1781
|
+
constraint operator (~> ), which allows only the rightmost version component to increment:
|
|
1782
|
+
|
|
1783
|
+
terraform {
|
|
1784
|
+
|
|
1785
|
+
required_version = ">= 1.0.0"
|
|
1786
|
+
|
|
1787
|
+
required_providers {
|
|
1788
|
+
|
|
1789
|
+
aws = {
|
|
1790
|
+
|
|
1791
|
+
source = "hashicorp/aws"
|
|
1792
|
+
|
|
1793
|
+
version = "~> 4.0"
|
|
1794
|
+
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
Declare required providers 27
|
|
1798
|
+
|
|
1799
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1800
|
+
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1805
|
+
In this example, ~> 4.0 allows the installation of 4.57.1 and 4.67.0 but not 5.0.0. For more
|
|
1806
|
+
|
|
1807
|
+
information, see Version Constraint Syntax in the HashiCorp documentation.
|
|
1808
|
+
|
|
1809
|
+
## Follow naming conventions
|
|
1810
|
+
|
|
1811
|
+
Clear, descriptive names simplify your understanding of relationships between resources in the
|
|
1812
|
+
|
|
1813
|
+
module and the purpose of configuration values. Consistency with style guidelines enhances
|
|
1814
|
+
|
|
1815
|
+
readability for both module users and maintainers.
|
|
1816
|
+
|
|
1817
|
+
## Follow guidelines for resource naming
|
|
1818
|
+
|
|
1819
|
+
*Use snake_case (where lowercase terms are separated by underscores) for all resource names to
|
|
1820
|
+
|
|
1821
|
+
match Terraform style standards. This practice ensures consistency with the naming convention
|
|
1822
|
+
|
|
1823
|
+
for resource types, data source types, and other predefined values. This convention doesn't apply
|
|
1824
|
+
|
|
1825
|
+
to name arguments.
|
|
1826
|
+
|
|
1827
|
+
*To simplify references to a resource that is the only one of its type (for example, a single load
|
|
1828
|
+
|
|
1829
|
+
balancer for an entire module), name the resource main or this for clarity.
|
|
1830
|
+
|
|
1831
|
+
*Use meaningful names that describe the purpose and context of the resource, and that help
|
|
1832
|
+
|
|
1833
|
+
differentiate between similar resources (for example, primary for the main database and
|
|
1834
|
+
|
|
1835
|
+
read_replica for a read replica of the database).
|
|
1836
|
+
|
|
1837
|
+
*Use singular, not plural names.
|
|
1838
|
+
|
|
1839
|
+
*Don't repeat the resource type in the resource name.
|
|
1840
|
+
|
|
1841
|
+
## Follow guidelines for variable naming
|
|
1842
|
+
|
|
1843
|
+
*Add units to the names of inputs, local variables, and outputs that represent numeric values such
|
|
1844
|
+
|
|
1845
|
+
as disk size or RAM size (for example, ram_size_gb for RAM size in gigabytes). This practice
|
|
1846
|
+
|
|
1847
|
+
makes the expected input unit clear for configuration maintainers.
|
|
1848
|
+
|
|
1849
|
+
*Use binary units such as MiB and GiB for storage sizes, and decimal units such as MB or GB for
|
|
1850
|
+
|
|
1851
|
+
other metrics.
|
|
1852
|
+
|
|
1853
|
+
*Give Boolean variables positive names such as enable_external_access .
|
|
1854
|
+
|
|
1855
|
+
Follow naming conventions 28
|
|
1856
|
+
|
|
1857
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1858
|
+
|
|
1859
|
+
## Use attachment resources
|
|
1860
|
+
|
|
1861
|
+
Some resources have pseudo-resources embedded as attributes in them. Where possible, you
|
|
1862
|
+
|
|
1863
|
+
should avoid using these embedded resource attributes and use the unique resource to attach that
|
|
1864
|
+
|
|
1865
|
+
pseudo-resource instead. These resource relationships can cause cause-and-effect issues that are
|
|
1866
|
+
|
|
1867
|
+
unique for each resource.
|
|
1868
|
+
|
|
1869
|
+
Using an embedded attribute (avoid this pattern):
|
|
1870
|
+
|
|
1871
|
+
resource "aws_security_group" "allow_tls" {
|
|
1872
|
+
|
|
1873
|
+
...
|
|
1874
|
+
|
|
1875
|
+
ingress {
|
|
1876
|
+
|
|
1877
|
+
description = "TLS from VPC"
|
|
1878
|
+
|
|
1879
|
+
from_port = 443
|
|
1880
|
+
|
|
1881
|
+
to_port = 443
|
|
1882
|
+
|
|
1883
|
+
protocol = "tcp"
|
|
1884
|
+
|
|
1885
|
+
cidr_blocks = [aws_vpc.main.cidr_block]
|
|
1886
|
+
|
|
1887
|
+
ipv6_cidr_blocks = [aws_vpc.main.ipv6_cidr_block]
|
|
1888
|
+
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
egress {
|
|
1892
|
+
|
|
1893
|
+
from_port = 0
|
|
1894
|
+
|
|
1895
|
+
to_port = 0
|
|
1896
|
+
|
|
1897
|
+
protocol = "-1"
|
|
1898
|
+
|
|
1899
|
+
cidr_blocks = ["0.0.0.0/0"]
|
|
1900
|
+
|
|
1901
|
+
ipv6_cidr_blocks = ["::/0"]
|
|
1902
|
+
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
Using attachment resources (preferred):
|
|
1908
|
+
|
|
1909
|
+
resource "aws_security_group" "allow_tls" {
|
|
1910
|
+
|
|
1911
|
+
...
|
|
1912
|
+
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
resource "aws_security_group_rule" "example" {
|
|
1916
|
+
|
|
1917
|
+
type = "ingress"
|
|
1918
|
+
|
|
1919
|
+
description = "TLS from VPC"
|
|
1920
|
+
|
|
1921
|
+
from_port = 443
|
|
1922
|
+
|
|
1923
|
+
to_port = 443
|
|
1924
|
+
|
|
1925
|
+
protocol = "tcp"
|
|
1926
|
+
|
|
1927
|
+
cidr_blocks = [aws_vpc.main.cidr_block]
|
|
1928
|
+
|
|
1929
|
+
Use attachment resources 29
|
|
1930
|
+
|
|
1931
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1932
|
+
|
|
1933
|
+
ipv6_cidr_blocks = [aws_vpc.main.ipv6_cidr_block]
|
|
1934
|
+
|
|
1935
|
+
security_group_id = aws_security_group.allow_tls.id
|
|
1936
|
+
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
## Use default tags
|
|
1940
|
+
|
|
1941
|
+
Assign tags to all resources that can accept tags. The Terraform AWS Provider has an
|
|
1942
|
+
|
|
1943
|
+
aws_default_tags data source that you should use inside the root module.
|
|
1944
|
+
|
|
1945
|
+
Consider adding necessary tags to all resources that are created by a Terraform module. Here's a
|
|
1946
|
+
|
|
1947
|
+
list of possible tags to attach:
|
|
1948
|
+
|
|
1949
|
+
*Name : Human-readable resource name
|
|
1950
|
+
|
|
1951
|
+
*AppId : The ID for the application that uses the resource
|
|
1952
|
+
|
|
1953
|
+
*AppRole: The resource's technical function; for example, "webserver" or "database"
|
|
1954
|
+
|
|
1955
|
+
*AppPurpose : The resource's business purpose; for example, "frontend ui" or "payment processor"
|
|
1956
|
+
|
|
1957
|
+
*Environment: The software environment, such as dev, test, or prod
|
|
1958
|
+
|
|
1959
|
+
*Project: The projects that use the resource
|
|
1960
|
+
|
|
1961
|
+
*CostCenter : Who to bill for resource usage
|
|
1962
|
+
|
|
1963
|
+
## Meet Terraform registry requirements
|
|
1964
|
+
|
|
1965
|
+
A module repository must meet all of the following requirements so it can be published to a
|
|
1966
|
+
|
|
1967
|
+
Terraform registry.
|
|
1968
|
+
|
|
1969
|
+
You should always follow these requirements even if you aren't planning to publish the module
|
|
1970
|
+
|
|
1971
|
+
to a registry in the short term. By doing so, you can publish the module to a registry later without
|
|
1972
|
+
|
|
1973
|
+
having to change the configuration and structure of the repository.
|
|
1974
|
+
|
|
1975
|
+
*Repository name: For a module repository, use the three-part name terraform-aws-<NAME> ,
|
|
1976
|
+
|
|
1977
|
+
where <NAME> reflects the type of infrastructure the module manages. The <NAME> segment can
|
|
1978
|
+
|
|
1979
|
+
contain additional hyphens (for example, terraform-aws-iam-terraform-roles ).
|
|
1980
|
+
|
|
1981
|
+
*Standard module structure: The module must adhere to the standard repository structure. This
|
|
1982
|
+
|
|
1983
|
+
allows the registry to inspect your module and generate documentation, track resource usage,
|
|
1984
|
+
|
|
1985
|
+
and more.
|
|
1986
|
+
|
|
1987
|
+
Use default tags 30
|
|
1988
|
+
|
|
1989
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
1990
|
+
|
|
1991
|
+
*After you create the Git repository, copy the module files to the root of the repository. We
|
|
1992
|
+
|
|
1993
|
+
recommend that you place each module that is intended to be reusable in the root of its own
|
|
1994
|
+
|
|
1995
|
+
repository, but you can also reference modules from subdirectories.
|
|
1996
|
+
|
|
1997
|
+
*If you're using HCP Terraform, publish the modules that are intended to be shared to your
|
|
1998
|
+
|
|
1999
|
+
organization registry. The registry handles downloads and controls access with HCP Terraform
|
|
2000
|
+
|
|
2001
|
+
API tokens, so consumers do not need access to the module's source repository even when
|
|
2002
|
+
|
|
2003
|
+
they run Terraform from the command line.
|
|
2004
|
+
|
|
2005
|
+
*Location and permissions: The repository must be in one of your configured version control
|
|
2006
|
+
|
|
2007
|
+
system (VCS) providers, and the HCP Terraform VCS user account must have administrator access
|
|
2008
|
+
|
|
2009
|
+
to the repository. The registry needs administrator access to create the webhooks to import new
|
|
2010
|
+
|
|
2011
|
+
module versions.
|
|
2012
|
+
|
|
2013
|
+
*x.y.z tags for releases: At least one release tag must be present for you to publish a module. The
|
|
2014
|
+
|
|
2015
|
+
registry uses release tags to identify module versions. Release tag names must use semantic
|
|
2016
|
+
|
|
2017
|
+
versioning, which you can optionally prefix with a v (for example, v1.1.0 and 1.1.0 ). The
|
|
2018
|
+
|
|
2019
|
+
registry ignores tags that do not look like version numbers. For more information about
|
|
2020
|
+
|
|
2021
|
+
publishing modules, see the Terraform documentation.
|
|
2022
|
+
|
|
2023
|
+
For more information, see Preparing a Module Repository in the Terraform documentation.
|
|
2024
|
+
|
|
2025
|
+
## Use recommended module sources
|
|
2026
|
+
|
|
2027
|
+
Terraform uses the source argument in a module block to find and download the source code for
|
|
2028
|
+
|
|
2029
|
+
a child module.
|
|
2030
|
+
|
|
2031
|
+
We recommend that you use local paths for closely related modules that have the primary purpose
|
|
2032
|
+
|
|
2033
|
+
of factoring out repeated code elements, and using a native Terraform module registry or a VCS
|
|
2034
|
+
|
|
2035
|
+
provider for modules that are intended to be shared by multiple configurations.
|
|
2036
|
+
|
|
2037
|
+
The following examples illustrate the most common and recommended source types for sharing
|
|
2038
|
+
|
|
2039
|
+
modules. Registry modules support versioning. You should always provide a specific version, as
|
|
2040
|
+
|
|
2041
|
+
shown in the following examples.
|
|
2042
|
+
|
|
2043
|
+
## Registry
|
|
2044
|
+
|
|
2045
|
+
Terraform registry:
|
|
2046
|
+
|
|
2047
|
+
module "lambda" {
|
|
2048
|
+
|
|
2049
|
+
Use recommended module sources 31
|
|
2050
|
+
|
|
2051
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
2052
|
+
|
|
2053
|
+
source = "github.com/terraform-aws-modules/terraform-aws-lambda.git?
|
|
2054
|
+
|
|
2055
|
+
ref=e78cdf1f82944897ca6e30d6489f43cf24539374" #--> v4.18.0
|
|
2056
|
+
|
|
2057
|
+
...
|
|
2058
|
+
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
By pinning commit hashes, you can avoid drift from public registries that are vulnerable to supply
|
|
2062
|
+
|
|
2063
|
+
chain attacks.
|
|
2064
|
+
|
|
2065
|
+
HCP Terraform:
|
|
2066
|
+
|
|
2067
|
+
module "eks_karpenter" {
|
|
2068
|
+
|
|
2069
|
+
source = "app.terraform.io/my-org/eks/aws"
|
|
2070
|
+
|
|
2071
|
+
version = "1.1.0"
|
|
2072
|
+
|
|
2073
|
+
...
|
|
2074
|
+
|
|
2075
|
+
enable_karpenter = true
|
|
2076
|
+
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
Terraform Enterprise:
|
|
2080
|
+
|
|
2081
|
+
module "eks_karpenter" {
|
|
2082
|
+
|
|
2083
|
+
source = "terraform.mydomain.com/my-org/eks/aws"
|
|
2084
|
+
|
|
2085
|
+
version = "1.1.0"
|
|
2086
|
+
|
|
2087
|
+
...
|
|
2088
|
+
|
|
2089
|
+
enable_karpenter = true
|
|
2090
|
+
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
## VCS providers
|
|
2094
|
+
|
|
2095
|
+
VCS providers support the ref argument for selecting a specific revision, as shown in the following
|
|
2096
|
+
|
|
2097
|
+
examples.
|
|
2098
|
+
|
|
2099
|
+
GitHub (HTTPS):
|
|
2100
|
+
|
|
2101
|
+
module "eks_karpenter" {
|
|
2102
|
+
|
|
2103
|
+
VCS providers 32
|
|
2104
|
+
|
|
2105
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
2106
|
+
|
|
2107
|
+
source = "github.com/my-org/terraform-aws-eks.git?ref=v1.1.0"
|
|
2108
|
+
|
|
2109
|
+
...
|
|
2110
|
+
|
|
2111
|
+
enable_karpenter = true
|
|
2112
|
+
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
Generic Git repository (HTTPS):
|
|
2116
|
+
|
|
2117
|
+
module "eks_karpenter" {
|
|
2118
|
+
|
|
2119
|
+
source = "git::https://example.com/terraform-aws-eks.git?ref=v1.1.0"
|
|
2120
|
+
|
|
2121
|
+
...
|
|
2122
|
+
|
|
2123
|
+
enable_karpenter = true
|
|
2124
|
+
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
Generic Git repository (SSH):
|
|
2128
|
+
|
|
2129
|
+
## Warning
|
|
2130
|
+
|
|
2131
|
+
You need to configure credentials to access private repositories.
|
|
2132
|
+
|
|
2133
|
+
module "eks_karpenter" {
|
|
2134
|
+
|
|
2135
|
+
source = "git::ssh://username@example.com/terraform-aws-eks.git?ref=v1.1.0"
|
|
2136
|
+
|
|
2137
|
+
...
|
|
2138
|
+
|
|
2139
|
+
enable_karpenter = true
|
|
2140
|
+
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
## Follow coding standards
|
|
2144
|
+
|
|
2145
|
+
Apply consistent Terraform formatting rules and styles across all configuration files. Enforce
|
|
2146
|
+
|
|
2147
|
+
standards by using automated style checks in CI/CD pipelines. When you embed coding best
|
|
2148
|
+
|
|
2149
|
+
practices into team workflows, configurations remain readable, maintainable, and collaborative as
|
|
2150
|
+
|
|
2151
|
+
usage spreads widely across an organization.
|
|
2152
|
+
|
|
2153
|
+
Follow coding standards 33
|
|
2154
|
+
|
|
2155
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
2156
|
+
|
|
2157
|
+
## Follow style guidelines
|
|
2158
|
+
|
|
2159
|
+
*Format all Terraform files (.tf files) with the terraform fmt command to match HashiCorp style
|
|
2160
|
+
|
|
2161
|
+
standards.
|
|
2162
|
+
|
|
2163
|
+
*Use the terraform validate command to verify the syntax and structure of your configuration.
|
|
2164
|
+
|
|
2165
|
+
*Statically analyze code quality by using TFLint . This linter checks for Terraform best practices
|
|
2166
|
+
|
|
2167
|
+
beyond just formatting and fails builds when it encounters errors.
|
|
2168
|
+
|
|
2169
|
+
Configure pre-commit hooks
|
|
2170
|
+
|
|
2171
|
+
Configure client-side pre-commit hooks that run terraform fmt , tflint , checkov , and other
|
|
2172
|
+
|
|
2173
|
+
code scans and style checks before you allow commits. This practice helps you validate standards
|
|
2174
|
+
|
|
2175
|
+
conformance earlier in developer workflows.
|
|
2176
|
+
|
|
2177
|
+
Use pre-commit frameworks such as pre-commit to add Terraform linting, formatting, and code
|
|
2178
|
+
|
|
2179
|
+
scanning as hooks on your local machine. Hooks run on each Git commit and fail the commit if
|
|
2180
|
+
|
|
2181
|
+
checks don't pass.
|
|
2182
|
+
|
|
2183
|
+
Moving style and quality checks to local pre-commit hooks provides rapid feedback to developers
|
|
2184
|
+
|
|
2185
|
+
before changes are introduced. Standards become part of the coding workflow.
|
|
2186
|
+
|
|
2187
|
+
Follow style guidelines 34
|
|
2188
|
+
|
|
2189
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
2190
|
+
|
|
2191
|
+
## Best practices for AWS Provider version management
|
|
2192
|
+
|
|
2193
|
+
Carefully managing versions of the AWS Provider and associated Terraform modules is critical for
|
|
2194
|
+
|
|
2195
|
+
stability. This section outlines best practices around version constraints and upgrades.
|
|
2196
|
+
|
|
2197
|
+
Best practices:
|
|
2198
|
+
|
|
2199
|
+
*Add automated version checks
|
|
2200
|
+
|
|
2201
|
+
*Monitor new releases
|
|
2202
|
+
|
|
2203
|
+
*Contribute to providers
|
|
2204
|
+
|
|
2205
|
+
## Add automated version checks
|
|
2206
|
+
|
|
2207
|
+
Add version checks for Terraform providers in your CI/CD pipelines to validate version pinning, and
|
|
2208
|
+
|
|
2209
|
+
fail builds if the version is undefined.
|
|
2210
|
+
|
|
2211
|
+
*Add TFLint checks in CI/CD pipelines to scan for provider versions that don't have pinned major/
|
|
2212
|
+
|
|
2213
|
+
minor version constraints defined. Use the TFLint ruleset plugin for Terraform AWS Provider,
|
|
2214
|
+
|
|
2215
|
+
which provides rules for detecting possible errors and checks for best practices about AWS
|
|
2216
|
+
|
|
2217
|
+
resources.
|
|
2218
|
+
|
|
2219
|
+
*Fail CI runs that detect unpinned provider versions to prevent implicit upgrades from reaching
|
|
2220
|
+
|
|
2221
|
+
production.
|
|
2222
|
+
|
|
2223
|
+
## Monitor new releases
|
|
2224
|
+
|
|
2225
|
+
*Monitor provider release notes and changelog feeds. Get notifications on new major/minor
|
|
2226
|
+
|
|
2227
|
+
releases.
|
|
2228
|
+
|
|
2229
|
+
*Assess release notes for potentially breaking changes and evaluate their impact on your existing
|
|
2230
|
+
|
|
2231
|
+
infrastructure.
|
|
2232
|
+
|
|
2233
|
+
*Upgrade minor versions in non-production environments first to validate them before updating
|
|
2234
|
+
|
|
2235
|
+
the production environment.
|
|
2236
|
+
|
|
2237
|
+
By automating version checks in pipelines and monitoring new releases, you can catch unsupported
|
|
2238
|
+
|
|
2239
|
+
upgrades early and give your teams time to evaluate the impact of new major/minor releases
|
|
2240
|
+
|
|
2241
|
+
before you update production environments.
|
|
2242
|
+
|
|
2243
|
+
Add automated version checks 35
|
|
2244
|
+
|
|
2245
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
2246
|
+
|
|
2247
|
+
## Contribute to providers
|
|
2248
|
+
|
|
2249
|
+
Actively contribute to HashiCorp AWS Provider by reporting defects or requesting features in
|
|
2250
|
+
|
|
2251
|
+
GitHub issues:
|
|
2252
|
+
|
|
2253
|
+
*Open well-documented issues on the AWS Provider repository to detail any bugs you
|
|
2254
|
+
|
|
2255
|
+
encountered or functionality that is missing. Provide reproducible steps.
|
|
2256
|
+
|
|
2257
|
+
*Request and vote on enhancements to expand the capabilities of the AWS Provider for managing
|
|
2258
|
+
|
|
2259
|
+
new services.
|
|
2260
|
+
|
|
2261
|
+
*Reference issued pull requests when you contribute proposed fixes for provider defects or
|
|
2262
|
+
|
|
2263
|
+
enhancements. Link to related issues.
|
|
2264
|
+
|
|
2265
|
+
*Follow the contribution guidelines in the repository for coding conventions, testing standards,
|
|
2266
|
+
|
|
2267
|
+
and documentation.
|
|
2268
|
+
|
|
2269
|
+
By giving back to the providers you use, you can provide direct input into their roadmap and help
|
|
2270
|
+
|
|
2271
|
+
improve their quality and capabilities for all users.
|
|
2272
|
+
|
|
2273
|
+
Contribute to providers 36
|
|
2274
|
+
|
|
2275
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
2276
|
+
|
|
2277
|
+
## Best practices for community modules
|
|
2278
|
+
|
|
2279
|
+
Using modules effectively is key to managing complex Terraform configurations and promoting
|
|
2280
|
+
|
|
2281
|
+
reuse. This section provides best practices around community modules, dependencies, sources,
|
|
2282
|
+
|
|
2283
|
+
abstraction, and contributions.
|
|
2284
|
+
|
|
2285
|
+
Best practices:
|
|
2286
|
+
|
|
2287
|
+
*Discover community modules
|
|
2288
|
+
|
|
2289
|
+
*Understand dependencies
|
|
2290
|
+
|
|
2291
|
+
*Use trusted sources
|
|
2292
|
+
|
|
2293
|
+
*Contribute to community modules
|
|
2294
|
+
|
|
2295
|
+
## Discover community modules
|
|
2296
|
+
|
|
2297
|
+
Search the Terraform Registry, GitHub , and other sources for existing AWS modules that might
|
|
2298
|
+
|
|
2299
|
+
solve your use case before you build a new module. Look for popular options that have recent
|
|
2300
|
+
|
|
2301
|
+
updates and are actively maintained.
|
|
2302
|
+
|
|
2303
|
+
## Use variables for customization
|
|
2304
|
+
|
|
2305
|
+
When you use community modules, pass inputs through variables instead of forking or directly
|
|
2306
|
+
|
|
2307
|
+
modifying the source code. Override defaults where required instead of changing the internals of
|
|
2308
|
+
|
|
2309
|
+
the module.
|
|
2310
|
+
|
|
2311
|
+
Forking should be limited to contributing fixes or features to the original module to benefit the
|
|
2312
|
+
|
|
2313
|
+
broader community.
|
|
2314
|
+
|
|
2315
|
+
## Understand dependencies
|
|
2316
|
+
|
|
2317
|
+
Before you use the module, review its source code and documentation to identify dependencies:
|
|
2318
|
+
|
|
2319
|
+
*Required providers: Note the versions of AWS, Kubernetes, or other providers the module
|
|
2320
|
+
|
|
2321
|
+
requires.
|
|
2322
|
+
|
|
2323
|
+
*Nested modules: Check for other modules used internally that introduce cascading
|
|
2324
|
+
|
|
2325
|
+
dependencies.
|
|
2326
|
+
|
|
2327
|
+
Discover community modules 37
|
|
2328
|
+
|
|
2329
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
2330
|
+
|
|
2331
|
+
*External data sources: Note the APIs, custom plugins, or infrastructure dependencies that the
|
|
2332
|
+
|
|
2333
|
+
module relies on.
|
|
2334
|
+
|
|
2335
|
+
By mapping out the full tree of direct and indirect dependencies, you can avoid surprises when you
|
|
2336
|
+
|
|
2337
|
+
use the module.
|
|
2338
|
+
|
|
2339
|
+
## Use trusted sources
|
|
2340
|
+
|
|
2341
|
+
Sourcing Terraform modules from unverified or unknown publishers introduces significant risk. Use
|
|
2342
|
+
|
|
2343
|
+
modules only from trusted sources.
|
|
2344
|
+
|
|
2345
|
+
*Favor certified modules from the Terraform Registry that are published by verified creators such
|
|
2346
|
+
|
|
2347
|
+
as AWS or HashiCorp partners.
|
|
2348
|
+
|
|
2349
|
+
*For custom modules, review publisher history, support levels, and usage reputation, even if the
|
|
2350
|
+
|
|
2351
|
+
module is from your own organization.
|
|
2352
|
+
|
|
2353
|
+
By not allowing modules from unknown or unvetted sources, you can reduce the risk of injecting
|
|
2354
|
+
|
|
2355
|
+
vulnerabilities or maintenance issues into your code.
|
|
2356
|
+
|
|
2357
|
+
Subscribe to notifications
|
|
2358
|
+
|
|
2359
|
+
Subscribe to notifications for new module releases from trusted publishers:
|
|
2360
|
+
|
|
2361
|
+
*Watch GitHub module repositories to get alerts on new versions of the module.
|
|
2362
|
+
|
|
2363
|
+
*Monitor publisher blogs and changelogs for updates.
|
|
2364
|
+
|
|
2365
|
+
*Get proactive notifications for new versions from verified, highly rated sources instead of
|
|
2366
|
+
|
|
2367
|
+
implicitly pulling in updates.
|
|
2368
|
+
|
|
2369
|
+
Consuming modules only from trusted sources and monitoring changes provide stability and
|
|
2370
|
+
|
|
2371
|
+
security. Vetted modules enhance productivity while minimizing supply chain risk.
|
|
2372
|
+
|
|
2373
|
+
## Contribute to community modules
|
|
2374
|
+
|
|
2375
|
+
Submit fixes and enhancements for community modules that are hosted in GitHub:
|
|
2376
|
+
|
|
2377
|
+
*Open pull requests on modules to address defects or limitations that you encounter in your
|
|
2378
|
+
|
|
2379
|
+
usage.
|
|
2380
|
+
|
|
2381
|
+
Use trusted sources 38
|
|
2382
|
+
|
|
2383
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
2384
|
+
|
|
2385
|
+
*Request new best practice configurations to be added to existing OSS modules by creating
|
|
2386
|
+
|
|
2387
|
+
issues.
|
|
2388
|
+
|
|
2389
|
+
Contributing to community modules enhances reusable, codified patterns for all Terraform
|
|
2390
|
+
|
|
2391
|
+
practitioners.
|
|
2392
|
+
|
|
2393
|
+
Contribute to community modules 39
|
|
2394
|
+
|
|
2395
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
2396
|
+
|
|
2397
|
+
## FAQ
|
|
2398
|
+
|
|
2399
|
+
Q. Why focus on the AWS Provider?
|
|
2400
|
+
|
|
2401
|
+
A. The AWS Provider is one of the most widely used and complex providers for provisioning
|
|
2402
|
+
|
|
2403
|
+
infrastructure in Terraform. Following these best practices help users optimize their usage of the
|
|
2404
|
+
|
|
2405
|
+
provider for the AWS environment.
|
|
2406
|
+
|
|
2407
|
+
Q. I'm new to Terraform. Can I use this guide?
|
|
2408
|
+
|
|
2409
|
+
A. The guide is for people who are new to Terraform as well as more advanced practitioners who
|
|
2410
|
+
|
|
2411
|
+
want to level up their skills. The practices improve workflows for users at any stage of learning.
|
|
2412
|
+
|
|
2413
|
+
Q. What are some key best practices covered?
|
|
2414
|
+
|
|
2415
|
+
A. Key best practices include using IAM roles over access keys, pinning versions, incorporating
|
|
2416
|
+
|
|
2417
|
+
automated testing , remote state locking, credential rotation, contributing back to providers, and
|
|
2418
|
+
|
|
2419
|
+
logically organizing code bases.
|
|
2420
|
+
|
|
2421
|
+
Q. Where can I learn more about Terraform?
|
|
2422
|
+
|
|
2423
|
+
A. The Resources section includes links to the official HashiCorp Terraform documentation and
|
|
2424
|
+
|
|
2425
|
+
community forums. Use the links to learn more about advanced Terraform workflows.
|
|
2426
|
+
|
|
2427
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
2428
|
+
|
|
2429
|
+
## Next steps
|
|
2430
|
+
|
|
2431
|
+
Here are some potential next steps after reading this guide:
|
|
2432
|
+
|
|
2433
|
+
*If you have an existing Terraform code base, review your configuration and identify areas that
|
|
2434
|
+
|
|
2435
|
+
could be improved based on the recommendations that are provided in this guide. For example,
|
|
2436
|
+
|
|
2437
|
+
review best practices for implementing remote backends, separating code into modules, using
|
|
2438
|
+
|
|
2439
|
+
version pinning, and so on, and validate these in your configuration.
|
|
2440
|
+
|
|
2441
|
+
*If you don't have an existing Terraform code base, use these best practices when you structure
|
|
2442
|
+
|
|
2443
|
+
your new configuration. Follow the advice around state management, authentication, code
|
|
2444
|
+
|
|
2445
|
+
structure, and so on from the beginning.
|
|
2446
|
+
|
|
2447
|
+
*Try using some of the HashiCorp community modules referenced in this guide to see if they
|
|
2448
|
+
|
|
2449
|
+
simplify your architecture patterns. The modules allow higher levels of abstraction, so you don't
|
|
2450
|
+
|
|
2451
|
+
have to rewrite common resources.
|
|
2452
|
+
|
|
2453
|
+
*Enable linting, security scans, policy checks, and automated testing tools to reinforce some of
|
|
2454
|
+
|
|
2455
|
+
the best practices around security, compliance, and code quality. Tools such as TFLint, tfsec, and
|
|
2456
|
+
|
|
2457
|
+
Checkov can help.
|
|
2458
|
+
|
|
2459
|
+
*Review the latest AWS Provider documentation to see if there are any new resources or
|
|
2460
|
+
|
|
2461
|
+
functionality that could help optimize your Terraform usage. Stay up to date on new versions of
|
|
2462
|
+
|
|
2463
|
+
the AWS Provider.
|
|
2464
|
+
|
|
2465
|
+
*For additional guidance, see the Terraform documentation, best practices guide, and style guide
|
|
2466
|
+
|
|
2467
|
+
on the HashiCorp website.
|
|
2468
|
+
|
|
2469
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|
|
2470
|
+
|
|
2471
|
+
## Resources
|
|
2472
|
+
|
|
2473
|
+
## References
|
|
2474
|
+
|
|
2475
|
+
The following links provide additional reading material for the Terraform AWS Provider and using
|
|
2476
|
+
|
|
2477
|
+
Terraform for IaC on AWS.
|
|
2478
|
+
|
|
2479
|
+
*Terraform AWS Provider (HashiCorp documentation)
|
|
2480
|
+
|
|
2481
|
+
*Terraform modules for AWS services (Terraform Registry)
|
|
2482
|
+
|
|
2483
|
+
*The AWS and HashiCorp Partnership (HashiCorp blog post)
|
|
2484
|
+
|
|
2485
|
+
*Dynamic Credentials with the AWS Provider (HCP Terraform documentation)
|
|
2486
|
+
|
|
2487
|
+
*DynamoDB State Locking (Terraform documentation)
|
|
2488
|
+
|
|
2489
|
+
*Enforce Policy with Sentinel (Terraform documentation)
|
|
2490
|
+
|
|
2491
|
+
## Tools
|
|
2492
|
+
|
|
2493
|
+
The following tools help improve code quality and automation of Terraform configurations on
|
|
2494
|
+
|
|
2495
|
+
AWS, as recommended in this best practices guide.
|
|
2496
|
+
|
|
2497
|
+
Code quality:
|
|
2498
|
+
|
|
2499
|
+
*Checkov: Scans Terraform code to identify misconfigurations before deployment.
|
|
2500
|
+
|
|
2501
|
+
*TFLint : Identifies possible errors, deprecated syntax, and unused declarations. This linter can also
|
|
2502
|
+
|
|
2503
|
+
enforce AWS best practices and naming conventions.
|
|
2504
|
+
|
|
2505
|
+
*terraform-docs : Generates documentation from Terraform modules in various output formats.
|
|
2506
|
+
|
|
2507
|
+
Automation tools:
|
|
2508
|
+
|
|
2509
|
+
*HCP Terraform: Helps teams version, collaborate, and build Terraform workflows with policy
|
|
2510
|
+
|
|
2511
|
+
checks and approval gates.
|
|
2512
|
+
|
|
2513
|
+
*Atlantis : An open source Terraform pull request automation tool for validating code changes.
|
|
2514
|
+
|
|
2515
|
+
*CDK for Terraform: A framework that lets you use familiar languages such as TypeScript, Python,
|
|
2516
|
+
|
|
2517
|
+
Java, C#, and Go instead of HashiCorp Configuration Language (HCL) to define, provision, and
|
|
2518
|
+
|
|
2519
|
+
test your Terraform infrastructure as code.
|
|
2520
|
+
|
|
2521
|
+
References 42
|
|
2522
|
+
|
|
2523
|
+
## AWS Prescriptive Guidance Best practices for using the Terraform AWS Provider
|