Terraform SOPS Provider: Secure Secret Management for Infrastructure as Code

Terraform configurations are infrastructure as code, and infrastructure as code requires secrets. Credentials, database passwords, API keys, and certificates must be present during plan and apply, but they must not be exposed in repositories, logs, or state files in plaintext. Mozilla SOPS provides encryption for files containing secrets, and the terraform-provider-sops ecosystem provides a bridge that lets Terraform read those encrypted values without manual decryption.

The combination addresses a persistent tension in cloud-native teams: keep secrets together with the configuration that uses them, while ensuring the secrets remain encrypted at rest and are only materialized in memory during execution. This article covers the purpose, architecture, security model, and usage patterns of the Terraform SOPS providers based on available reference material.

What SOPS Is and How It Relates to Terraform

SOPS stands for Secrets OPerationS, and is an open-source text file editor that encrypts/decrypts YAML, JSON, ENV, INI and BINARY formats and encrypts with AWS KMS, GCP KMS, Azure Key Vault, age, and PGP.

SOPS only encrypts the secrets, so the advantage is you can have key-value pairs in a yaml or json file, and while the key is readable, the value part is encrypted. This also allows to address particular keys.

The provider acts as a bridge between Terraform's infrastructure-as-code capabilities and SOPS's secret management, allowing teams to store sensitive configuration data encrypted at rest while making it accessible during Terraform execution.

The terraform-provider-sops is a Terraform provider that enables secure integration of SOPS-encrypted secrets into Terraform configurations. This document provides a comprehensive overview of the terraform-provider-sops project, explaining its purpose, architecture, and core components. It covers the provider's integration with Mozilla SOPS for secure secret management within Terraform configurations.

SOPS is Mozilla's editor for encrypted files that supports multiple encryption backends and data formats. The provider supports multiple data formats and encryption backends to accommodate different use cases.

Provider Variants and Design Philosophy

The ecosystem contains related implementations that emphasize different Terraform integration styles.

A Terraform plugin for using files encrypted with SOPS is described with a data source approach.

NOTE: To prevent plaintext secrets from being written to disk, you must set up a secure remote state backend. See the official docs on Sensitive Data in State for more information or use ephemeral block.

NOTE: All examples assume Terraform 0.13 or newer. For information about usage on older versions, see the legacy usage docs.

The provider is heavily inspired by carlpett/terraform-provider-sops but does not rely on data sources and instead uses provider functions. This distinction is important for authors choosing between a function-based workflow and a data source-based workflow.

The provider for using files encrypted with SOPS provides functions to decrypt SOPS-encrypted files and strings. This provider is heavily inspired by carlpett/terraform-provider-sops but does not rely on data sources and instead uses provider functions.

Core Components and Data Sources

The provider consists of two main data sources that handle different secret retrieval scenarios.

The provider implements a common data processing pipeline shared between both data sources.

The provider supports two primary usage patterns:

sops_file
Used when encrypted files are stored locally in the Terraform working directory:

sops_external
Used when encrypted content comes from external sources such as HTTP endpoints, other Terraform providers:

Key Differences

sopsfile auto-detects format from file extension; sopsexternal requires explicit input_type

sopsfile reads from local filesystem; sopsexternal accepts string content

data
structured map and raw
decrypted string

The provider includes comprehensive build and testing infrastructure.

Supported Data Formats and Encryption Backends

The provider supports multiple data formats and encryption backends to accommodate different use cases.

Supported Data Formats

  • json
  • JSON structured data
  • yaml
  • YAML structured data
  • ini
  • INI configuration files
  • dotenv
  • Environment variable files
  • raw
  • Raw encrypted content

Supported Encryption Backends

  • AWS KMS
  • GCP KMS
  • Azure Key Vault
  • age
  • PGP

SOPS as such supports AWS KMS, GCP KMS, Azure Key Vault, age, and PGP.

Security Architecture

Security is central to the design. Critical Security Requirement: To prevent plaintext secrets from being written to disk, you must configure a secure remote state backend when using this provider.

The provider implements several security measures to protect sensitive data.

Security Feature Implementation Purpose
In-Memory Decryption All decryption occurs in memory only Prevents plaintext secrets from being written to disk
Sensitive Attributes Terraform marks outputs as sensitive Prevents accidental exposure in logs and console output
Remote State Requirement Must use secure remote state backend Ensures encrypted storage of Terraform state containing secrets
Multi-Key Support Supports multiple encryption backends Enables key rotation and hybrid key management strategies

Security Architecture

Security Implementation Model

The provider supports multiple data formats and encryption backends to accommodate different use cases.

Usage Patterns

Local File Decryption with sops_file

The canonical workflow for a local encrypted file is:

sops demo-secret.enc.json { "password": "foo", "db": {"password": "bar"} }

Terraform configuration:

```
terraform {
requiredproviders {
sops = {
source = "carlpett/sops"
version = "~> 0.5"
}
}
}
data "sops
file" "demo-secret" {
source_file = "demo-secret.enc.json"
}
output "root-value-password" {

Access the password variable from the map

value = data.sops_file.demo-secret.data["password"]
}
output "mapped-nested-value" {

Access the password variable that is under db via the terraform map of data

value = data.sops_file.demo-secret.data["db.password"]
}
output "nested-json-value" {

Access the password variable that is under db via the terraform object

value = jsondecode(data.sops_file.demo-secret.raw).db.password
}
```

Sops also supports encrypting the entire file when in other formats.

The data source reads the encrypted file from the local working directory, decrypts it in memory, and exposes the structured map via data.sops_file.demo-secret.data and the raw decrypted content for further processing.

External Content Decryption with sops_external

When encrypted content is not available locally, sopsexternal is used. It accepts string content and requires explicit inputtype because auto-detection from file extension is not possible.

The provider acts as a bridge between Terraform's infrastructure-as-code capabilities and SOPS's secret management, allowing teams to store sensitive configuration data encrypted at rest while making it accessible during Terraform execution.

Azure Key Vault Integration

We are heavily using Terraform and and also Azure. However until now, we left out certain things cause they contain secrets which we don’t want to expose in the code. SOPS is a nice solution to solve that problem and keep things together what belongs together.

If you want more details to SOPS as such you can also have a look at A Comprehensive Guide to SOPS: Managing Your Secrets Like A Visionary, Not a Functionary.

As we will use azure-key-vault: you will need

access to the respective key-vault

sops binary

Encrypting/decrypting with Azure Key Vault requires the resource identifier for a key. This has the following form:

We setup a keyvault - Key Vault names are globally unique - you can do this using azure cli or preferable using terraform

We create a key - you can do this using azure cli or preferable using terraform

Once we have the key created and configured, then we can use it for encryption

A common operational pattern is to create per-environment secret files checked into version control.

Using both of these keys with SOPS, we can create a file that the cloud-team is able to edit, and the workspace(s) are able to use for the Terraform configuration. This file is checked into the version control system.

We typically create a file for each our our environments containing our secrets with the naming-convention secrets.{environment}.enc.yaml

  • secrets.dev.enc.yaml
  • secrets.test.enc.yaml
  • secrets.stage.enc.yaml
  • secrets.prod.enc.yaml

To create these files you need to obtain the different keys mentioned above before running the following command:

sops --azure-kv "$WORKSPACE_KV_KEY" --age "$WORKSPACE_KEY" "$FILENAME"

Here WORKSPACEKVKEY is the Azure key vault key and WORKSPACE_KEY is the public Age key for the Terraform workspace. The last argument is the FILENAME being the name of the encrypted file we want to create. A prerequisite for running this command is to have a valid Azure session in our shell, obtainable when running the following command from Azure CLI: az login

This pattern keeps the encrypted file in Git while allowing only authorized workspaces with access to the Azure Key Vault key and the Age private key to decrypt values at Terraform runtime.

Operational Considerations

State safety is non-negotiable. To prevent plaintext secrets from being written to disk, you must set up a secure remote state backend. See the official docs on Sensitive Data in State for more information or use ephemeral block.

In-memory decryption ensures that plaintext never touches disk, but Terraform state will still contain the resolved values unless the state backend is encrypted and access-controlled. Sensitive Attributes marking prevents accidental exposure in logs and console output.

Multi-key support enables key rotation and hybrid key management strategies, for example combining Azure Key Vault for key management with Age for workspace-level access control.

The provider implements a common data processing pipeline shared between both data sources, which reduces divergence in decryption behavior and simplifies security auditing.

Conclusion

The Terraform SOPS provider family solves a practical problem: how to keep secrets encrypted in code repositories while making them usable during Terraform execution. The data source-based implementation provides sopsfile for local encrypted files and sopsexternal for content from external sources, with auto-detection for the former and explicit typing for the latter. The function-based variant offers an alternative that avoids data sources entirely.

Security is enforced through in-memory decryption, Terraform sensitive attribute handling, and a strict requirement for secure remote state backends. Supported formats span json, yaml, ini, dotenv and raw, with encryption backends including AWS KMS, GCP KMS, Azure Key Vault, age and PGP. Operational patterns such as per-environment encrypted files with Azure Key Vault and Age keys demonstrate how teams can maintain secret files in version control without exposing plaintext.

The architecture is deliberately minimal: decrypt in memory at plan and apply time, expose structured data to Terraform, and rely on SOPS for the cryptographic guarantees. When combined with proper state encryption, access control, and key management, this approach lets teams treat secrets as code without sacrificing confidentiality.

Sources

  1. github.com/nobbs/terraform-provider-sops
  2. deepwiki.com/carlpett/terraform-provider-sops
  3. wyssmann.com/blog/2023/10/terraform-secrets-with-sops-and-azure-keyvault/
  4. github.com/carlpett/terraform-provider-sops
  5. digital.moller.no/sops-secrets-operations-secrets-in-code-9c0f3dbd97f9

Related Posts