How to Use Terraform to Enforce Secure App Settings (1-6-3)

How to Use Terraform to Enforce Secure App Settings (1-6-3)

Use terraform enforce secure application settings through reviewed plans, deployment gates, monitoring, and evidence for ECC 1-6-3.

LakeRidge Team
July 18, 2026
8 min read

Share:

Schedule Your Free Compliance Consultation

Feeling overwhelmed by compliance requirements? Not sure where to start? Get expert guidance tailored to your specific needs in just 15 minutes.

Personalized Compliance Roadmap
Expert Answers to Your Questions
No Obligation, 100% Free

CMMC Phase 2 begins November 10, 2026.

Teams can use terraform enforce secure application settings by defining approved security baselines as code, validating them before deployment, and retaining Terraform plans, pipeline logs, and configuration exports as evidence. For ECC – 2 : 2024 control 1-6-3, Terraform is particularly effective for enforcing secure configuration, hardening, diagnostic logging, and release gates, but it must be combined with secure coding, software-source governance, and security testing processes.

The practical objective is not to treat Terraform as a compliance document. It is to make approved application settings repeatable, reviewable, difficult to bypass, and traceable to the cybersecurity requirements document required by ECC practice 1-6-3.

What can be automated versus what still requires human evidence?

Terraform is strongest where a setting can be expressed as a desired technical state. For example, it can require HTTPS, disable FTP deployment, require TLS 1.2 or above, prevent public access, configure diagnostic logs, and attach managed identities. These controls support 1-6-3-5, which requires configuration review, hardening, and patching before go-live and periodically afterward.

ECC 1-6-3 area What Terraform can automate What remains a controlled process
1-6-3-1 Secure coding standards Require approved deployment settings, runtime versions, managed identity, and secure defaults. Approve coding standards, train developers, conduct code review, and demonstrate adherence in source repositories.
1-6-3-2 Trusted tools and libraries Pin Terraform provider versions and use approved module registries. Maintain the approved software and library list, license records, supplier reviews, and dependency approval process.
1-6-3-3 Compliance testing Block deployment when policy or configuration tests fail. Perform penetration testing, application security testing, access-management review, and architecture review.
1-6-3-4 Secure integration Deploy private endpoints, managed identities, and secure API-related platform settings. Perform SIT, API security testing, authentication-flow testing, and integration assessment.
1-6-3-5 Configuration and hardening Apply and continuously compare approved application settings with deployed settings. Approve the baseline, authorize exceptions, review patch impact, and accept residual risk.

A useful rule for a GRC consultant is: automate the control implementation where possible, but preserve human approval for the requirement, exception, test result, and production release decision. A Terraform plan proves intended infrastructure change; it does not prove that an API integration was penetration-tested or that a development library is properly licensed.

For example, an 85-person Riyadh-based GRC consultancy and MSP, Najd Governance Services, manages twelve Azure subscriptions for Saudi clients. Its client portal uses Azure App Service, Azure Key Vault, Log Analytics, and an API connection to a ticketing platform. The delivery workflow requires a change ticket, a reviewed Terraform plan, a successful API test record, and a production approval before release. Terraform-based application-setting enforcement handles the platform baseline, while the engagement manager retains the testing and approval records.

How can terraform enforce secure application settings before release?

Start with a version-controlled module that represents the approved application hardening baseline. The module should not contain live secrets. Instead, use managed identities and secret references, and store the Terraform state in a protected remote backend with restricted access and encryption.

The following Azure App Service example establishes practical settings for a production web application. It disables insecure deployment protocols, requires HTTPS and TLS 1.2, restricts public network exposure, sends diagnostic data to the central workspace, and prevents a production deployment without a change reference.

terraform {
  required_version = ">= 1.6.0"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.110"
    }
  }
}

provider "azurerm" {
  features {}
}

variable "environment" {
  type = string
}

variable "change_ticket" {
  type = string
}

variable "private_endpoint_enabled" {
  type = bool
}

variable "log_analytics_workspace_id" {
  type = string
}

resource "azurerm_linux_web_app" "portal" {
  name                = "ngs-client-portal-prod"
  resource_group_name = "rg-ngs-portal-prod"
  location            = "Saudi Central"
  service_plan_id     = "/subscriptions/8c3d6f1a-4e3d-4b68-a7f0-1b89c1229a09/resourceGroups/rg-ngs-portal-prod/providers/Microsoft.Web/serverfarms/asp-ngs-prod"

  https_only                    = true
  public_network_access_enabled = false

  identity {
    type = "SystemAssigned"
  }

  site_config {
    always_on              = true
    ftps_state             = "Disabled"
    minimum_tls_version    = "1.2"
    health_check_path      = "/health"
    ip_restriction_default_action     = "Deny"
    scm_ip_restriction_default_action = "Deny"

    application_stack {
      dotnet_version = "8.0"
    }
  }

  app_settings = {
    "WEBSITE_RUN_FROM_PACKAGE" = "1"
    "ASPNETCORE_ENVIRONMENT"   = "Production"
    "KeyVault__Uri"            = "https://kv-ngs-prod.vault.azure.net/"
    "Db__ConnectionString"     = "@Microsoft.KeyVault(SecretUri=https://kv-ngs-prod.vault.azure.net/secrets/PortalDbConnection)"
  }

  lifecycle {
    precondition {
      condition     = var.environment != "prod" || (var.private_endpoint_enabled && length(var.change_ticket) > 5)
      error_message = "Production requires an enabled private endpoint and an approved change ticket reference."
    }
  }

  tags = {
    Environment       = var.environment
    ECC_Control       = "1-6-3-5"
    Change_Ticket     = var.change_ticket
    Configuration_Baseline = "webapp-hardening-v3.2"
  }
}

resource "azurerm_monitor_diagnostic_setting" "portal" {
  name                       = "diag-ngs-client-portal-prod"
  target_resource_id         = azurerm_linux_web_app.portal.id
  log_analytics_workspace_id = var.log_analytics_workspace_id

  enabled_log {
    category_group = "allLogs"
  }

  metric {
    category = "AllMetrics"
    enabled  = true
  }
}

Before approving this module, document each setting in the secure configuration standard. For example, the standard should state that production web applications must use HTTPS, must not permit FTP, must use the organization’s approved runtime version, and must use centralized logging. That approved standard is the governing evidence; the Terraform code is implementation evidence.

Do not use Terraform variables to pass database passwords or API tokens unless there is no feasible alternative. Sensitive Terraform variables can still appear in state. Key Vault references, workload identities, and tightly controlled state access better support confidentiality and evidence quality.

How should the Terraform baseline be integrated into CI/CD?

The deployment pipeline should run formatting, validation, security scanning, planning, review, and controlled application in separate stages. Production applies should use a protected environment and short-lived federated credentials rather than stored cloud administrator passwords. This supports an auditable release process and reduces the opportunity for direct console changes.

name: Terraform Production Release

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

jobs:
  validate-and-plan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3

      - name: Format and validate
        run: |
          terraform fmt -check -recursive
          terraform init -backend-config=prod.backend.hcl
          terraform validate

      - name: Security scan
        run: |
          docker run --rm -v "$PWD:/src" aquasec/tfsec:v1.28.10 /src

      - name: Create reviewed plan
        run: |
          terraform plan -out=plan.tfplan \
            -var="environment=prod" \
            -var="change_ticket=CHG-2026-01482" \
            -var="private_endpoint_enabled=true"

      - name: Save plan as release evidence
        uses: actions/upload-artifact@v4
        with:
          name: production-plan
          path: plan.tfplan

  apply:
    needs: validate-and-plan
    if: github.ref == 'refs/heads/main'
    environment: production
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - name: Apply approved plan
        run: |
          terraform init -backend-config=prod.backend.hcl
          terraform apply -auto-approve plan.tfplan

In an approved implementation, pin GitHub Actions, container images, Terraform providers, and internal modules to reviewed versions or immutable digests. This is an operational application of 1-6-3-2: the pipeline itself uses development tools and libraries that must come from trusted and licensed sources. Maintain the provider lock file, approved action inventory, and exception records alongside the project evidence.

Which monitoring and alerting hooks should be added?

Terraform enforcement is not complete if configuration drift is discovered only during an annual review. Schedule a read-only Terraform plan daily or weekly against production, publish the result to the service desk, and investigate any change that was not linked to an approved change record. Azure Activity Logs and App Service diagnostics should feed the central Log Analytics workspace or SIEM.

A useful alert query identifies web application configuration writes, including settings changed directly through the portal or command line:

AzureActivity
| where ResourceProviderValue =~ "MICROSOFT.WEB"
| where OperationNameValue has_any (
  "Microsoft.Web/sites/config/write",
  "Microsoft.Web/sites/write"
)
| where ActivityStatusValue == "Succeeded"
| project TimeGenerated, Caller, OperationNameValue,
          ResourceGroup, Resource, SubscriptionId, CorrelationId
| order by TimeGenerated desc

Create a high-priority alert when this query detects an out-of-pipeline configuration change in a production subscription. Route it to the SOC or managed monitoring team and create a service-management ticket containing the affected application, caller identity, correlation ID, and required remediation deadline. Retain the alert, ticket, Terraform drift result, and remediation plan as periodic-review evidence for 1-6-3-5.

What failure modes need handling in the automation?

  • Precondition failure: If a production deployment lacks a change ticket or private endpoint confirmation, stop at planning. The requester must correct the release input; do not bypass the check with a manual portal deployment.
  • Security-scan failure: Treat a finding such as public network access or weak TLS as a failed control. Record a risk exception only when the designated representative approves compensating controls and an expiry date.
  • Terraform state lock: Investigate the active pipeline before force-unlocking state. Force-unlocking without confirming the prior job can create conflicting changes and unreliable evidence.
  • Key Vault reference failure: If the application cannot resolve a secret, verify the managed identity, Key Vault access, private DNS, and secret version. Never replace the reference with a plain-text connection string to restore service quickly.
  • Post-release health failure: Roll back to the prior approved Terraform version or deployment artifact, preserve logs and test results, and open a problem record when the hardening baseline caused an unexpected application dependency.
  • Direct configuration drift: Reconcile production back to the approved code after validating business impact. If the direct change is legitimate, update code, obtain approval, and rerun the pipeline so the baseline remains authoritative.

For Saudi client engagements, the next practical step is to map your approved secure configuration standard to a Terraform module and review its evidence flow against ECC 1-6-3 with the system owner before the next production release.

 

Quick & Simple

Discover Our Cybersecurity Compliance Solutions:

Whether you need to meet and maintain your compliance requirements, help your clients meet them, or verify supplier compliance we have the expertise and solution for you

 CMMC Level 1 Compliance App

CMMC Level 1 Compliance

Become compliant, provide compliance services, or verify partner compliance with CMMC Level 1 Basic Safeguarding of Covered Contractor Information Systems requirements.
 NIST SP 800-171 & CMMC Level 2 Compliance App

NIST SP 800-171 & CMMC Level 2 Compliance

Become compliant, provide compliance services, or verify partner compliance with NIST SP 800-171 and CMMC Level 2 requirements.
 HIPAA Compliance App

HIPAA Compliance

Become compliant, provide compliance services, or verify partner compliance with HIPAA security rule requirements.
 ISO 27001 Compliance App

ISO 27001 Compliance

Become compliant, provide compliance services, or verify partner compliance with ISO 27001 requirements.
 FAR 52.204-21 Compliance App

FAR 52.204-21 Compliance

Become compliant, provide compliance services, or verify partner compliance with FAR 52.204-21 Basic Safeguarding of Covered Contractor Information Systems requirements.
 ECC Compliance App

ECC Compliance

Become compliant, provide compliance services, or verify partner compliance with Essential Cybersecurity Controls (ECC – 2 : 2024) requirements.