
Terraform Style Guide
Generate Terraform HCL that follows HashiCorp security hardening—encryption, private networking, least-privilege SGs, logging, and no hardcoded secrets.
Install
npx skills add https://github.com/hashicorp/agent-skills --skill terraform-style-guideWhat is this skill?
- Default encryption at rest and private networking guidance
- Least-privilege security groups and enabled logging/monitoring
- No hardcoded credentials; sensitive outputs marked sensitive = true
- Ephemeral resources and write-only attributes for sensitive data
- Worked secure S3 example: versioning, KMS SSE, and public access block
Adoption & trust: 5.5k installs on skills.sh; 654 GitHub stars; 3/3 security scanners passed (skills.sh audits); trending (+100% hot-view momentum).
Recommended Skills
Journey fit
Security-first Terraform generation is canonically shelved at ship/security because it gates what reaches production, even though authoring often happens during build. The skill encodes appsec and infra hardening rules (KMS, public access block, sensitive outputs)—security subphase rather than generic backend CRUD.
Common Questions / FAQ
Is Terraform Style Guide safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Terraform Style Guide
# Terraform Style Guide - Security When generating code, apply security hardening: - Enable encryption at rest by default - Configure private networking where applicable - Apply principle of least privilege for security groups - Enable logging and monitoring - Never hardcode credentials or secrets - Mark sensitive outputs with `sensitive = true` - Use `ephemeral` resources and write-only attributes for sensitive data when possible ## Example: Secure S3 Bucket ```hcl resource "aws_s3_bucket" "data" { bucket = "${var.project}-${var.environment}-data" tags = local.common_tags } resource "aws_s3_bucket_versioning" "data" { bucket = aws_s3_bucket.data.id versioning_configuration { status = "Enabled" } } resource "aws_s3_bucket_server_side_encryption_configuration" "data" { bucket = aws_s3_bucket.data.id rule { apply_server_side_encryption_by_default { sse_algorithm = "aws:kms" kms_master_key_id = aws_kms_key.s3.arn } } } resource "aws_s3_bucket_public_access_block" "data" { bucket = aws_s3_bucket.data.id block_public_acls = true block_public_policy = true ignore_public_acls = true restrict_public_buckets = true } ``` ## Ephemeral resources Ephemeral resources prevent sensitive data being stored in state. For more information on ephemeral resources, see the [Terraform documentation](https://developer.hashicorp.com/terraform/language/block/ephemeral). Before you generate code for an ephemeral resource, check that the Terraform version is greater than or equal to 1.11.0. Then, follow this priority order for managing sensitive attributes: 1. **First priority: Native secrets manager integration** If a resource has the ability to automatically manage a sensitive attribute by storing it in a secrets manager (e.g., AWS Secrets Manager, Azure Key Vault), use that configuration. This is the preferred approach. ```hcl # Bad resource "aws_rds_cluster" "example" { cluster_identifier = "example" database_name = "test" master_username = "test" master_password = var.db_master_password } # Good, managed by AWS Secrets Manager by default resource "aws_rds_cluster" "test" { cluster_identifier = "example" database_name = "test" manage_master_user_password = true master_username = "test" } ``` 2. **Second priority: Write-only attributes with ephemeral resources** If a resource has a write-only attribute but no native secrets manager integration, use an `ephemeral` resource for the sensitive data and pass that to the write-only attribute. Default the write-only version to 1. ```hcl # Bad resource "random_password" "password" { length = 16 special = true override_special = "!#$%&*()-_=+[]{}<>:?" } resource "vault_kv_secret_v2" "example" { mount = vault_mount.kvv2.path name = "secret" data_json = jsonencode( { password = "${random_password.password.result}", } ) } # Good ephemeral "random_password" "password" { length = 16 special = true override_special = "!#$%&*()-_=+[]{}<>:?" } resource "vault_kv_secret_v2" "example" { mount = vault_mount.kvv2.path name = "secret" data_json_wo = jsonencode( { password = "${ephemeral.random_password.password.result}", } ) data_json_wo_version = 1 } ``` If you need to retrieve a secret from a secrets manager to pass to a resource, use the `ephemeral` version of the resource to retrieve the secret and pass it to another resource. ```hcl # Good ephemeral "vault_kv_secret_v2" "db_secret" { mount =