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.
Files changed (30) hide show
  1. awslabs/__init__.py +17 -0
  2. awslabs/terraform_mcp_server/__init__.py +17 -0
  3. awslabs/terraform_mcp_server/impl/resources/__init__.py +25 -0
  4. awslabs/terraform_mcp_server/impl/resources/terraform_aws_provider_resources_listing.py +66 -0
  5. awslabs/terraform_mcp_server/impl/resources/terraform_awscc_provider_resources_listing.py +69 -0
  6. awslabs/terraform_mcp_server/impl/tools/__init__.py +33 -0
  7. awslabs/terraform_mcp_server/impl/tools/execute_terraform_command.py +223 -0
  8. awslabs/terraform_mcp_server/impl/tools/execute_terragrunt_command.py +320 -0
  9. awslabs/terraform_mcp_server/impl/tools/run_checkov_scan.py +376 -0
  10. awslabs/terraform_mcp_server/impl/tools/search_aws_provider_docs.py +691 -0
  11. awslabs/terraform_mcp_server/impl/tools/search_awscc_provider_docs.py +641 -0
  12. awslabs/terraform_mcp_server/impl/tools/search_specific_aws_ia_modules.py +458 -0
  13. awslabs/terraform_mcp_server/impl/tools/search_user_provided_module.py +349 -0
  14. awslabs/terraform_mcp_server/impl/tools/utils.py +572 -0
  15. awslabs/terraform_mcp_server/models/__init__.py +49 -0
  16. awslabs/terraform_mcp_server/models/models.py +381 -0
  17. awslabs/terraform_mcp_server/scripts/generate_aws_provider_resources.py +1240 -0
  18. awslabs/terraform_mcp_server/scripts/generate_awscc_provider_resources.py +1039 -0
  19. awslabs/terraform_mcp_server/scripts/scrape_aws_terraform_best_practices.py +143 -0
  20. awslabs/terraform_mcp_server/server.py +440 -0
  21. awslabs/terraform_mcp_server/static/AWSCC_PROVIDER_RESOURCES.md +3125 -0
  22. awslabs/terraform_mcp_server/static/AWS_PROVIDER_RESOURCES.md +3833 -0
  23. awslabs/terraform_mcp_server/static/AWS_TERRAFORM_BEST_PRACTICES.md +2523 -0
  24. awslabs/terraform_mcp_server/static/MCP_INSTRUCTIONS.md +142 -0
  25. awslabs/terraform_mcp_server/static/TERRAFORM_WORKFLOW_GUIDE.md +330 -0
  26. awslabs/terraform_mcp_server/static/__init__.py +38 -0
  27. awslabs_terraform_mcp_server-1.0.14.dist-info/METADATA +166 -0
  28. awslabs_terraform_mcp_server-1.0.14.dist-info/RECORD +30 -0
  29. awslabs_terraform_mcp_server-1.0.14.dist-info/WHEEL +4 -0
  30. 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