IaC Security Best Practices: Secrets Hardening, Least-Privilege IAM & State Protection

Infrastructure as Code is code—which means it can introduce severe security vulnerabilities directly into production clouds. Learn how to secure secrets, enforce strict IAM boundaries, and automate security linting.

1. The Infrastructure Attack Surface

According to cloud security research, over 80% of data breaches in cloud environments originate from architectural misconfigurations rather than zero-day software exploits. When infrastructure is codified into Git repositories, misconfigurations become codified at scale.

Common high-risk vulnerabilities include:

  • Over-Permissive Ingress Rules: Exposing administrative SSH (port 22) or database ports (port 5432/3306) to the public internet (0.0.0.0/0).
  • Plaintext Secrets: Hardcoding API tokens, database passwords, or TLS keys directly into configuration files.
  • Excessive IAM Permissions: Assigning wildcard policies (Action: "*", Resource: "*") to application execution roles.
  • Unencrypted Storage Buckets: Provisioning S3, Blob, or GCS buckets without server-side encryption or with public read ACLs.

2. Automated Static Security Scanning (`telliac lint`)

Before running plan or apply commands, automate static security linting. TellIaC includes a dedicated security scanner that analyzes your AST for policy violations:

# Run security linting across all .hiac files
telliac lint

# Output:
# [PASS] No plaintext credentials detected in variable declarations
# [WARN] aws_security_group "web_sg": Ingress port 22 open to 0.0.0.0/0
# [FAIL] aws_s3_bucket "data_lake": Encryption at rest is disabled!
# Result: 1 Failures, 1 Warning found. Exit code 1.
🛑
Gatekeeper Rule: Fail the CI/CD Pipeline Always execute security linters on every pull request. If high-severity vulnerabilities are detected, fail the build automatically to block merges into release branches.
Advertisement
TellIaC is supported by compliant advertising to keep open documentation and tools freely accessible.

3. Secrets Architecture: Dynamic Injection vs. Hardcoding

Never declare passwords or secrets in your .hiac or .tf files. Instead, use a centralized secrets engine such as AWS Secrets Manager, Azure Key Vault, or HashiCorp Vault:

# ❌ INSECURE ANTI-PATTERN: Hardcoded secret
db_password = "SuperSecretPassword123!"

# ✔ SECURE PATTERN: Dynamic secret reference injected at runtime via KMS
Create 1 "aws_secretsmanager_secret_version" resource named "db_credentials" with secret_id "prod_db_secret" in environment "production".

4. Securing Remote State Storage

As discussed in our state management guide, state files frequently contain decrypted attributes. You must implement Defense in Depth for your state storage buckets:

  1. KMS Customer Managed Keys: Encrypt state files using hardware-backed KMS keys with strict key usage policies.
  2. Bucket Policies Blocking Non-TLS Traffic: Enforce aws:SecureTransport: true to ensure state files can only be accessed over HTTPS.
  3. MFA Delete Protection: Require Multi-Factor Authentication to delete state file versions, protecting against malicious insider tampering or ransomware.

Next in the Series: Automate testing, security, and deployments with GitHub Actions:
Automating IaC in CI/CD: Building a Production-Grade GitHub Actions Pipeline →