Files
terraform-provider-dokploy/.agents/skills/terraform-style-guide/SECURITY.md
Max Vojtkov a6d8aa8b52 A Terraform provider for Dokploy
Plugin-framework provider covering projects, environments, applications,
Compose stacks, managed databases, domains, mounts, ports, redirects,
basic auth, registries, SSH keys, certificates and backup destinations,
over Dokploy's tRPC-over-REST API.

The shim package exposes the provider to other Go modules, which is how
pulumi-dokploy bridges it.
2026-08-09 12:17:26 +03:00

4.8 KiB

name, description
name description
terraform-style-guide-security Generate Terraform HCL code following HashiCorp's security practices

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

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.

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.

    # 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.

    # 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.

    # Good
    ephemeral "vault_kv_secret_v2" "db_secret" {
      mount = vault_mount.kvv2.path
      mount_id = vault_mount.kvv2.id
      name = vault_kv_secret_v2.db_root.name
    }
    
    resource "vault_database_secret_backend_connection" "postgres" {
      backend       = vault_mount.db.path
      name          = "postrgres-db"
      allowed_roles = ["*"]
    
      postgresql {
        connection_url = "postgresql://{{username}}:{{password}}@localhost:5432/postgres"
        password_authentication = ""
        username = "postgres"
        password_wo = tostring(ephemeral.vault_kv_secret_v2.db_secret.data.password)
        password_wo_version = 1
      }
    }
    
  3. Last resort: Regular resources Only use a regular resource that has sensitive data written to state if neither of the above options are available, resource does not offer a write-only attribute or ephemeral resource alternative, or the Terraform version is less than 1.11.0.