Segurança no Terraform: Boas Práticas para uma Infraestrutura Segura
Boas práticas de segurança no Terraform para state, segredos, IAM, módulos e CI para que sua infraestrutura como código chegue à produção com segurança.
Segurança no Terraform é a disciplina de garantir que a infraestrutura que você define como código esteja segura quando chegar a uma conta de nuvem, e não apenas conveniente de escrever. O Terraform é uma forma excelente de descrever infraestrutura de maneira declarativa e reproduzível, mas ele vai construir exatamente o que você mandar, incluindo um security group totalmente aberto ou um banco de dados público, se for isso que a configuração disser. A boa notícia é que, como tudo é código, todo risco pode ser revisado, testado e detectado antes de qualquer coisa ser provisionada. Este mergulho profundo percorre as práticas específicas do Terraform que mais importam, do state file ao CI, e se encaixa no nosso guia mais amplo de segurança em infraestrutura como código.
Ajuda manter uma ideia em mente o tempo todo: no Terraform, um problema de segurança e uma alteração de código são a mesma coisa. Uma configuração incorreta é uma linha em um pull request, uma role com privilégios em excesso é um bloco de recurso, um segredo vazado é um arquivo commitado. Isso é uma dádiva, porque significa que você pode aplicar as mesmas ferramentas em que já confia para o código de aplicação, controle de versão, revisão, testes automatizados e gates de CI, à própria infraestrutura. As práticas abaixo são simplesmente os pontos de maior alavancagem para apontar essas ferramentas. Nenhuma delas exige desacelerar seu time; a maioria é uma configuração única que passa a proteger automaticamente toda alteração futura.
O state file é seu maior risco
Toda conversa sobre segurança no Terraform deveria começar pelo state. O Terraform registra os recursos do mundo real que gerencia em um state file, e esse arquivo não é apenas metadado: ele pode conter segredos em texto puro. Senhas de banco de dados, access keys geradas, chaves privadas e qualquer atributo sensível que o Terraform leia de volta de um provider podem parar no state exatamente como estão. Qualquer pessoa capaz de ler o state pode ler esses segredos.
A primeira regra decorre diretamente disso: nunca coloque o state no controle de versão. Um arquivo terraform.tfstate no Git é um vazamento de credenciais esperando para ser clonado, e ele permanece no histórico mesmo depois de você apagá-lo. Adicione-o ao .gitignore já no primeiro dia.
Em vez disso, use um backend remoto com criptografia em repouso, locking de state e controle de acesso rigoroso. O locking impede que duas execuções corrompam o state simultaneamente, a criptografia protege os segredos dentro dele e o controle de acesso mantém o state legível apenas para os pipelines e as pessoas que realmente precisam.
terraform {
backend "s3" {
bucket = "acme-tfstate-prod"
key = "network/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "tf-locks"
}
}
Proteja também o próprio backend: bloqueie o acesso público ao bucket de armazenamento, restrinja quem pode lê-lo com uma policy de escopo reduzido e ative o versionamento para que você possa se recuperar de um apply ruim. Trate o repositório de state como o datastore de joias da coroa que ele é.
Dois hábitos relacionados fazem grande diferença. Primeiro, audite quem e o que pode ler o state e revisite essa lista periodicamente; o acesso tende a se acumular à medida que os times crescem, e uma permissão ampla de leitura em um bucket de state silenciosamente se torna uma permissão ampla de leitura sobre todos os segredos ali dentro. Segundo, se você realmente não quer um valor no state de forma alguma, evite deixar o Terraform gerenciar o recurso que o produz, ou gere o segredo fora do Terraform e apenas o referencie, para que o material sensível nunca passe pelo state file em primeiro lugar. A criptografia do state protege o arquivo em repouso, mas reduzir o que chega ao state é o controle mais forte.
Mantenha os segredos fora do código e das variáveis
O segundo problema recorrente de segurança no Terraform são os segredos hardcoded. É tentador jogar um token de API diretamente em um arquivo .tf ou em um terraform.tfvars, mas esses arquivos costumam ser commitados, e qualquer coisa commitada é efetivamente pública dentro da sua organização.
Não faça hardcode de segredos e não commite arquivos .tfvars que os contenham. Em vez disso, busque os segredos em tempo de execução a partir de um secrets manager dedicado ou de um provider de vault, para que o valor viva em um sistema feito para esse fim, e não no seu repositório.
data "vault_kv_secret_v2" "db" {
mount = "secret"
name = "prod/database"
}
resource "aws_db_instance" "main" {
username = "app"
password = data.vault_kv_secret_v2.db.data["password"]
}
Quando você de fato aceitar uma entrada sensível, marque-a como tal. Definir sensitive = true em uma variável ou output impede que seu valor seja impresso na saída do plan e do apply, o que é uma forma comum de os segredos acabarem colados em logs de CI e canais de chat.
variable "db_password" {
type = string
sensitive = true
}
Marcar valores como sensíveis reduz a exposição, mas não criptografa o state, então essa prática funciona em conjunto com um backend protegido, e não em substituição a ele.
Dê aos providers o mínimo privilégio
O Terraform atua na sua nuvem por meio de credenciais de provider, e essas credenciais costumam ser muito mais poderosas do que qualquer configuração isolada precisa. Um pipeline que só gerencia rede não precisa de permissão para excluir bancos de dados ou rotacionar usuários IAM.
Restrinja a identidade de cada provider aos recursos que ele de fato gerencia. Prefira credenciais de curta duração e federadas, como OpenID Connect a partir do seu sistema de CI, em vez de chaves estáticas de longa duração, e separe as roles por ambiente para que um pipeline de desenvolvimento comprometido não consiga tocar a produção. O mínimo privilégio aqui limita o raio de impacto caso uma execução, um runner ou um conjunto de credenciais seja comprometido.
Acertar o escopo exatamente na primeira tentativa é difícil, então trate isso como algo iterativo. Comece deliberadamente restrito, execute um plan e amplie as permissões apenas para as ações específicas de que o Terraform realmente precisa, em vez de conceder uma role administrativa ampla e prometer apertá-la depois, uma promessa que raramente é cumprida. Também vale ser explícito sobre onde as credenciais residem: uma chave de longa duração embutida no notebook de um desenvolvedor ou em uma variável de CI é, ela própria, um segredo a ser protegido, o que é mais um motivo para credenciais federadas e com expiração serem o padrão mais seguro.
Cuidado com a cadeia de suprimentos de módulos
Módulos são uma das melhores funcionalidades do Terraform e um de seus riscos mais silenciosos. Quando você puxa um módulo de um registry público, está executando código de outra pessoa com suas credenciais, e uma referência não fixada significa que o código pode mudar sob seus pés sem aviso.
Fixe tanto as versões de módulos quanto as de providers em releases específicas e comprovadamente boas, em vez de faixas flutuantes, para que uma mudança upstream nunca entre no seu plan sem revisão. Avalie as fontes do registry antes de adotá-las e, para qualquer coisa sensível ou amplamente reutilizada, hospede módulos verificados em um registry privado sob seu controle.
module "vpc" {
source = "app.private-registry.acme.com/networking/vpc/aws"
version = "3.4.1"
}
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.40"
}
}
}
O arquivo de lock de dependências, .terraform.lock.hcl, complementa isso registrando versões exatas de providers e checksums. Faça o commit dele para que toda execução e todo colega de time resolvam os mesmos binários de provider, verificados.
Detecte padrões inseguros de recursos com análise estática
A maioria dos incidentes reais de segurança no Terraform não é exótica. São configurações incorretas comuns: um bucket de armazenamento deixado público, um security group aberto para 0.0.0.0/0, um volume ou banco de dados criado sem criptografia, um banco de dados exposto à internet. Os provedores de nuvem muitas vezes facilitam a opção insegura, e uma pequena omissão no HCL vira uma exposição real.
# Arriscado: aberto para toda a internet
resource "aws_security_group_rule" "ssh" {
type = "ingress"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
É exatamente isso que a análise estática, às vezes chamada de IaC scanning, foi feita para encontrar. Um scanner analisa seu Terraform antes de ele ser aplicado e sinaliza o bucket público, a porta aberta para o mundo, o disco sem criptografia e a configuração de logging ausente, mapeando cada um ao recurso e à linha que o causou. Como ele lê o plan em vez da nuvem em execução, detecta problemas enquanto ainda são uma correção de uma linha em um pull request, e não um incidente em produção. Muitas dessas configurações incorretas se relacionam aos riscos de controle de acesso e de configuração incorreta destacados no OWASP Top 10 (2025), o que os torna uma linguagem comum e fácil entre os times de segurança e de plataforma.
Aplique policy as code
A varredura estática diz o que está mal configurado em relação a um baseline geral. Policy as code permite codificar as regras da sua própria organização e aplicá-las automaticamente. Usando um motor no estilo OPA ou Sentinel, você escreve guardrails como código testável: todo bucket deve ser criptografado, nenhum security group pode permitir acesso de entrada irrestrito, recursos de produção precisam ter uma tag de centro de custo, apenas regiões aprovadas são permitidas.
O ponto-chave é avaliar essas policies no momento do plan, antes do apply, para que uma violação bloqueie a mudança em vez de documentá-la depois do fato. Policy as code transforma conhecimento tribal e páginas de wiki em gates automatizados que se aplicam de forma consistente a toda mudança, de todo engenheiro, em toda execução.
Detecte drift
Mesmo um Terraform perfeitamente protegido pode ser minado depois do fato quando alguém faz uma alteração diretamente no console da nuvem. Essa divergência entre seu código e a realidade é chamada de drift, e é tanto uma preocupação de segurança quanto operacional: uma porta aberta manualmente ou uma configuração de criptografia desativada não vão aparecer na sua configuração revisada.
Execute terraform plan regularmente contra a produção, idealmente de forma agendada, e trate diffs inesperados como sinais para investigar. Detectar drift cedo mantém seu código como a verdadeira fonte de registro e impede que mudanças fora de banda enfraqueçam silenciosamente sua postura. Combine a detecção de drift com uma regra cultural de que o console é para leitura, não para alteração: quando toda mudança em produção passa por um pull request revisado, o drift se torna a exceção que se destaca, em vez da norma que você aprendeu a ignorar.
Faça a varredura do Terraform no CI
Todas essas práticas se juntam no seu pipeline. Um estágio de CI sólido para Terraform executa terraform fmt -check e terraform validate para pegar problemas de formatação e sintaxe, gera um terraform plan e então roda uma varredura de segurança de IaC e suas verificações de policy contra esse plan.
O detalhe crucial é o comportamento em caso de falha: configure o pipeline para falhar em achados críticos, para que infraestrutura insegura não consiga fazer merge. Avisos podem informar, mas críticos devem bloquear. Rodar a varredura em todo pull request também dá aos revisores um feedback de segurança inline, ao lado da mudança, que é onde é mais barato agir sobre ele.
A ordem também importa aqui. Execute primeiro as verificações rápidas e baratas, para que um erro de formatação ou validação falhe em segundos, e reserve a varredura de segurança e a avaliação de policy para o plan, que é a representação mais fiel do que realmente vai mudar. Fazer a varredura do plan em vez de apenas da configuração bruta captura problemas que surgem de como módulos e variáveis se resolvem em conjunto, e não apenas do que um único arquivo diz isoladamente. Por fim, mantenha o conjunto de regras no controle de versão junto com a infraestrutura, para que apertar uma policy seja, ele próprio, uma mudança revisada com histórico claro, e para que toda branch seja medida pela mesma régua.
# Estágio de CI ilustrativo
steps:
- run: terraform fmt -check
- run: terraform validate
- run: terraform plan -out=plan.tfplan
- run: iac-scan plan.tfplan --fail-on=critical
Como a Rainforest ajuda
A Rainforest oferece uma varredura genérica de segurança de IaC que se encaixa naturalmente nesse fluxo de trabalho. Ela analisa seu Terraform em busca de padrões inseguros e configurações incorretas, conecta os achados ao recurso e à linha exatos e roda dentro do CI, para que os problemas sejam pegos nos pull requests antes de qualquer coisa ser provisionada. Como trata a infraestrutura como código como parte do mesmo panorama de segurança de aplicação, você obtém uma visão única e consistente entre seu código e suas definições de nuvem, em vez de um silo separado. Você pode ler mais sobre nossa abordagem de teste de segurança de IaC e como ela se encaixa na plataforma mais ampla de teste de segurança de aplicações.
O Terraform lhe dá uma enorme alavancagem sobre sua infraestrutura, e segurança tem a ver com garantir que essa alavancagem aponte na direção certa. Proteja seu state, mantenha os segredos em um vault, restrinja o escopo dos seus providers, fixe seus módulos e deixe que a varredura automatizada e as verificações de policy peguem o resto no CI. Se você quer ver como a varredura automatizada de Terraform funciona contra suas próprias configurações, agende uma demonstração. Para plataformas vizinhas, nossos guias sobre segurança em CloudFormation e segurança em Kubernetes aplicam os mesmos princípios a seus respectivos ecossistemas.
Perguntas frequentes
O Terraform é seguro por padrão?
Não. O Terraform provisiona fielmente o que sua configuração descrever, e os provedores de nuvem muitas vezes têm como padrão a opção mais permissiva. Se o seu código especifica um bucket público, um volume sem criptografia ou um security group aberto para a internet, o Terraform vai construir exatamente isso. A segurança vem de como você escreve e revisa a configuração, protege o state e faz a varredura das mudanças, não do Terraform em si.
Como eu protejo o state do Terraform?
Use um backend remoto com criptografia em repouso, locking de state e controle de acesso rigoroso, e nunca coloque o state no controle de versão. O state pode conter segredos em texto puro, então restrinja quem e o que pode lê-lo, ative o versionamento no store de apoio e bloqueie o acesso público ao bucket ou container que o contém. Trate o repositório de state como um datastore sensível.
Como eu mantenho os segredos fora do Terraform?
Não faça hardcode de segredos em arquivos .tf ou .tfvars e não commite arquivos que os contenham. Busque os segredos em tempo de execução a partir de um secrets manager ou provider de vault e marque variáveis e outputs sensíveis com sensitive = true para que não sejam impressos nos logs de plan ou apply. Lembre-se de que marcar valores como sensíveis não criptografa o state, então combine isso com um backend protegido.
Como eu faço a varredura do Terraform em busca de configurações incorretas?
Execute a análise estática, também chamada de IaC scanning, contra seu Terraform antes de aplicá-lo. Um scanner lê sua configuração ou plan e sinaliza padrões inseguros, como armazenamento público, portas abertas e recursos sem criptografia, ligando cada achado ao recurso e à linha. Conecte a varredura ao CI para que ela rode em todo pull request e falhe o build em achados críticos.
O que é policy as code para o Terraform?
Policy as code significa escrever as regras de segurança e conformidade da sua organização como verificações executáveis, usando um motor no estilo OPA ou Sentinel, e aplicá-las automaticamente. Avaliados no momento do plan, esses guardrails bloqueiam mudanças que violem regras como exigir criptografia, proibir acesso de entrada irrestrito ou limitar as regiões permitidas, transformando padrões escritos em gates automatizados e consistentes.

Escrito por
Bruno Baldo
CMO
Um pouco de marketing e um pouco de curiosidade e temos a receita pra criar um apaixonado por cyber!

Segurança de Infrastructure as Code (IaC): o guia completo
Segurança de IaC explicada: o modelo de ameaças, o scanning ao longo do SDLC, policy as code, secrets e state e um fluxo prático de remediação.

Segurança no AWS CloudFormation: Boas Práticas
Um guia prático de segurança no CloudFormation: tratamento de segredos, menor privilégio de IAM, defaults inseguros, drift, stack policies e scanning na CI.

Segurança no Kubernetes: o guia completo
Guia completo de segurança no Kubernetes: o modelo dos 4C's, superfície de ataque, RBAC, pods, network policies, secrets, cadeia de suprimentos e shift-left.
