Sign in
Menu
Sign up
Docs

Get started

For an engineer trying compliance.tf for the first time. In about 15 minutes you authenticate to the registry, add one S3 bucket module with the SOC 2 controls built in, and run terraform plan against it. If the configuration breaks a control, you will see the error that names it and know how to fix it.

Before you start

  • Terraform or OpenTofu at a version the module accepts. The s3-bucket 5.0.0 module used here declares Terraform 1.10 or later. Compatibility with terraform-aws-modules explains how to find the minimum for any module.
  • AWS credentials and a provider "aws" block. Your AWS credentials and provider stay as they are. terraform plan needs read access; terraform apply needs the same permissions as any Terraform project.
  • A compliance.tf account. Start a free trial or sign in. The examples use SOC 2, which the trial includes. The Free plan covers only CIS AWS v6.0 (cis.compliance.tf); its controls, and so the settings Step 3 needs, differ, and the plan errors name them. See Plans and entitlements.

Step 1: Log in to the registry

Each framework has its own registry host, such as soc2.compliance.tf or hipaa.compliance.tf; Registry endpoints lists them. The examples use soc2; substitute yours.

terraform login soc2.compliance.tf

With OpenTofu, run tofu login soc2.compliance.tf. A browser window opens; sign in with your compliance.tf account. The CLI stores a token that expires after one day, which is what you want on your own machine.

For a pipeline, use a long-lived registry token instead; Registry tokens shows how to create one, and CI/CD integration shows where to put it. See also the Terraform login and OpenTofu login docs.

Step 2: Configure the CLI by hand (only without login)

Skip this step if terraform login worked. Otherwise, put a registry token in the file that matches your source format:

credentials "soc2.compliance.tf" {
  token = "ctf_YOUR_TOKEN_HERE"
}

The hostname must match the host in your module source. In CI, the TF_TOKEN_soc2_compliance_tf environment variable does the same.

machine soc2.compliance.tf
    login anything
    password ctf_YOUR_TOKEN_HERE

The login value is not checked; the token goes in password.

Which format to use, and why the HTTPS form reads .netrc, is on Registry endpoints.

Step 3: Add a module

Under SOC 2, an S3 bucket needs settings the module cannot choose for you: a bucket for its access logs, a KMS key for default encryption, a replication rule to a bucket in another region, and, because versioning is on, an enabled lifecycle rule. The block below sets them, so the plan can pass:

module "s3_bucket" {
  source  = "soc2.compliance.tf/terraform-aws-modules/s3-bucket/aws"
  version = "5.0.0"

  bucket = "my-first-compliancetf-bucket"

  logging = {
    target_bucket = "my-access-log-bucket"
    target_prefix = "s3-access-logs/"
  }

  server_side_encryption_configuration = {
    rule = {
      apply_server_side_encryption_by_default = {
        sse_algorithm     = "aws:kms"
        kms_master_key_id = "arn:aws:kms:eu-west-1:111122223333:key/EXAMPLE-KEY-ID"
      }
    }
  }

  versioning = {
    enabled = true
  }

  lifecycle_rule = [{
    id                                     = "abort-incomplete-multipart-upload"
    status                                 = "Enabled"
    abort_incomplete_multipart_upload_days = 7
  }]

  replication_configuration = {
    role = "arn:aws:iam::111122223333:role/s3-replication"

    rules = [{
      id       = "replicate-all"
      status   = "Enabled"
      priority = 1

      delete_marker_replication = true

      # The bucket is KMS-encrypted, so the rule has to opt in to replicating those objects
      source_selection_criteria = {
        sse_kms_encrypted_objects = {
          enabled = true
        }
      }

      destination = {
        bucket             = "arn:aws:s3:::my-first-compliancetf-bucket-replica"
        storage_class      = "STANDARD"
        replica_kms_key_id = "arn:aws:kms:us-west-2:111122223333:key/EXAMPLE-REPLICA-KEY-ID"
      }
    }]
  }
}

Bucket names are global, so choose your own. For a plan, the placeholder ARNs are enough: Terraform does not look them up. Before you apply, replace them with a log bucket, a KMS key, a replication role allowed to decrypt with the source key and encrypt with the replica key, and a versioned destination bucket that exist in your account. Compliance starter kits has the Terraform for the replication role and destination bucket.

The other SOC 2 controls on this module, such as object lock, event notifications and public access blocking, have defaults in the module that satisfy them. One of them turns Object Lock on for the new bucket, and AWS never turns it off; without a retention rule, objects in it can still be deleted. The module page on soc2.compliance.tf lists its versions, inputs and outputs.

Step 4: Run init and plan

terraform init    # downloads the module from soc2.compliance.tf
terraform plan    # the module's controls run here

Run terraform init again whenever you change a module source. Add -upgrade only to fetch the same source and version again, for example after your organization changes its rules; the Migration kit covers moving existing modules.

Check the result

Success case

The plan lists the resources to create, starting with the bucket, and ends with Terraform's usual summary:

  # module.s3_bucket.aws_s3_bucket.this[0] will be created
  + resource "aws_s3_bucket" "this" {
      + bucket = "my-first-compliancetf-bucket"
      ...
    }

Plan: N to add, 0 to change, 0 to destroy.

N is the bucket plus the logging, encryption, versioning, lifecycle, replication and other configuration resources the module manages for it. No validation error means the configuration satisfies every control the module enforces for SOC 2.

Failure case

If the configuration breaks a control, the plan stops with an error before anything reaches AWS. Remove the logging block from Step 3 and plan again. Abridged, the error reads:

│ Error: Invalid value for variable
│
│ ...
│
│ Control 's3_bucket_logging_enabled': S3 bucket access logging is required: configure logging with a valid target bucket
│ Read more: https://compliance.tf/docs/controls/aws/s3_bucket_logging_enabled/

Terraform also prints where the variable and its validation rule are declared; those lines are left out above. The Control line names the control and what it needs. The Read more link opens the control's page, which lists the frameworks that map it and their clause IDs. Add what the error names and plan again. The S3 bucket playbook has the fix for each S3 control error; if a control does not fit this bucket, turn it off and record why.

Undo it

If you only planned, delete the module block; nothing was created. If you applied, run terraform destroy for this root. To keep the bucket but stop using compliance.tf, change the source to terraform-aws-modules/s3-bucket/aws and run terraform init: the plan shows no resource changes.

Troubleshooting

ErrorCauseFix
401 or 403 during terraform initNo token for this exact host, an expired login, or a framework your plan does not includeRun terraform login soc2.compliance.tf again, check the host in .terraformrc or .netrc matches source, and check Plans and entitlements
Unsupported Terraform Core versionYour Terraform is older than the module's required_versionUpgrade Terraform, or pin an older module version that your Terraform accepts
Control 's3_bucket_default_encryption_enabled_kms': S3 bucket encryption must use aws:kms or aws:kms:dsseDefault encryption is AES-256Set sse_algorithm = "aws:kms" with a kms_master_key_id, as in Step 3
Control 's3_bucket_cross_region_replication_enabled': S3 bucket replication rule must have status EnabledNo replication rule, or one with status = "Disabled"Add the replication_configuration block from Step 3

Next steps

On this page

Ask AI about this

Help improve this page