Skip to content

Terraform Security: Secrets, Policies & Sentinel

DodaTech 5 min read

Terraform security encompasses secrets management, policy enforcement, IAM least-privilege, and misconfiguration scanning to ensure infrastructure is deployed securely and complies with organizational standards.

What You'll Learn

In this tutorial, you will learn how to manage Terraform secrets securely, enforce policies with Sentinel, scan for security misconfigurations, and implement least-privilege IAM for Terraform operations.

Why It Matters

Infrastructure misconfigurations cause most cloud data breaches. Hardcoded secrets, public S3 buckets, and over-permissive IAM roles are common findings in security audits. Terraform security practices prevent these vulnerabilities from reaching production.

Real-World Use

DodaTech uses HashiCorp Vault for dynamic database credentials in Terraform. Durga Antivirus Pro Sentinel policies enforce encryption, logging, and network restrictions across all Terraform deployments, maintaining compliance with SOC 2 and GDPR requirements.

Secrets Management

Environment Variables

Never hardcode secrets in Terraform files. Use environment variables:

export TF_VAR_db_password="my-secure-password"
export TF_VAR_db_username="admin"
variable "db_password" {
  description = "Database master password"
  type        = string
  sensitive   = true
}

Expected output: Terraform reads TF_VAR_db_password from the environment. The variable is marked sensitive and does not appear in logs or plan output.

HashiCorp Vault

data "vault_aws_access_credentials" "creds" {
  backend = "aws"
  role    = "terraform"
}

provider "aws" {
  region     = "us-east-1"
  access_key = data.vault_aws_access_credentials.creds.access_key
  secret_key = data.vault_aws_access_credentials.creds.secret_key
}

Expected output: Vault generates temporary AWS credentials valid for a configurable duration. Terraform uses these credentials, which are automatically revoked after the TTL expires.

Terraform Cloud Variables

Store sensitive variables in Terraform Cloud as sensitive variables. They are encrypted at rest and never displayed in the UI or API responses.

Policy as Code with Sentinel

Sentinel is a policy-as-code framework. Policies enforce rules before Terraform creates resources:

import "tfplan"

s3_buckets = filter tfplan.resource_changes as _, rc in {
  rc.mode is "managed" and rc.type is "aws_s3_bucket"
}

main = rule {
  all s3_buckets as _, bucket {
    bucket.applied.server_side_encryption_configuration is not null
  }
}

Expected output: This policy requires all S3 buckets to have encryption configured. If any bucket lacks encryption, Terraform Cloud blocks the apply.

Enforcing Tags

import "tfplan"

required_tags = ["Environment", "ManagedBy", "CostCenter"]

all_resources = filter tfplan.resource_changes as _, rc in {
  rc.mode is "managed"
}

main = rule {
  all all_resources as _, resource {
    all required_tags as _, tag {
      resource.applied.tags contains tag
    }
  }
}

Expected output: Every new or modified resource must have Environment, ManagedBy, and CostCenter tags. Violations appear as hard-mandatory failures in Terraform Cloud runs.

IAM Least Privilege

Minimum Permissions for Terraform

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["ec2:Describe*", "ec2:CreateSecurityGroup"],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket", "s3:GetObject", "s3:PutObject"],
      "Resource": ["arn:aws:s3:::dodatech-terraform-state", "arn:aws:s3:::dodatech-terraform-state/*"]
    }
  ]
}

Expected output: Terraform assumes a role with only the permissions needed for its managed resources. Unused services are denied.

Dynamic Provider Credentials

provider "aws" {
  assume_role {
    role_arn     = "arn:aws:iam::123456789012:role/TerraformRole"
    session_name = "TerraformSession"
    duration     = "1h"
  }
}

Expected output: Terraform assumes the TerraformRole for each operation. The role has scoped permissions, and the session expires after one hour.

Misconfiguration Scanning

TFSec in Pipeline

- name: TFSec Security Scan
  run: tfsec --format sarif --output tfsec.sarif .
- name: Upload TFSec Results
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: tfsec.sarif

Expected output: TFSec scans for 150+ security misconfigurations including unencrypted storage, open security groups, and missing logging.

Common Mistakes

1. Hardcoding Secrets in tfvars

Committing terraform.tfvars with passwords or API keys exposes secrets in version control. Use .gitignore for sensitive files.

2. Overly Permissive IAM Roles

Using AdministratorAccess for Terraform violates least privilege. Scope roles to only the resources Terraform manages.

3. Ignoring Sentinel Warnings

Sentinel soft-mandatory policies warn about issues. Treat all warnings as failures to prevent configuration drift.

4. Storing State Without Encryption

State files contain resource IDs and metadata. Always enable encryption on backend storage.

5. Not Rotating Provider Credentials

Long-lived access keys increase blast radius. Use Vault dynamic credentials or OIDC for short-lived authentication.

Practice Questions

1. How do you pass secrets to Terraform without storing them in files? Use environment variables with the TF_VAR_ prefix, Vault data sources, or Terraform Cloud sensitive variables.

2. What is Sentinel and how does it enforce security? Sentinel is a policy-as-code framework that runs in Terraform Cloud, enforcing rules like required encryption and tags.

3. What is the principle of least privilege in Terraform IAM? Terraform should assume a role with permissions limited to only the resources and actions it needs.

4. How does Vault integrate with Terraform for secrets? Vault data sources retrieve dynamic, temporary credentials that Terraform uses and that expire automatically.

5. Challenge: Create a Sentinel policy that requires all EC2 instances to have encryption-enabled EBS volumes and a Name tag. Test it with a non-compliant configuration.

Mini Project: Secure Terraform Pipeline

Create a Terraform configuration that uses Vault for database credentials, implements a least-privilege IAM role, adds TFSec scanning to a GitHub Actions workflow, and enforces tagging with a Sentinel-style policy check.

Terraform CI/CD
Multi-Cloud Terraform

What's Next

Secure your Terraform deployments with secrets management and policy enforcement, then extend to Multi-Cloud Architectures across AWS, Azure, and GCP.

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro