Variáveis de Ambiente no Lambda: Configuração, Acesso e Criptografia com KMS
Você tem um endpoint de banco de dados que precisa chegar até a função Lambda — hardcodar isso no código é o caminho mais rápido para um vazamento de credencial em um repositório público. Variáveis de ambiente no Lambda resolvem esse problema, e quando combinadas com KMS, você adiciona uma camada de criptografia que vai além do padrão gerenciado pela AWS.
TL;DR — Variáveis de Ambiente no Lambda
| Ponto | Detalhe |
|---|---|
| Onde configurar | Console, CLI (--environment), IaC (CloudFormation/SAM/Terraform) |
| Criptografia padrão | AWS gerencia com chave própria (aws/lambda) — transparente, sem custo adicional de KMS |
| Criptografia customizada | Você fornece uma CMK do KMS; Lambda criptografa em repouso e você descriptografa em runtime |
| Acesso no código | process.env.NOME (Node.js), os.environ['NOME'] (Python) |
| Limite de tamanho | 4 KB total para todas as variáveis — verifique a documentação oficial para limites atuais |
| Alternativa para segredos | AWS Secrets Manager ou SSM Parameter Store para rotação automática |
Como o Lambda Gerencia Variáveis de Ambiente
Antes de configurar qualquer coisa, vale entender o ciclo de vida. Variáveis de ambiente são armazenadas junto à configuração da função — não dentro do pacote de deployment. Quando o Lambda inicializa um execution environment, ele injeta essas variáveis no processo antes de executar o handler. Isso significa que uma atualização de variável não requer novo deploy do código, mas exige uma nova invocação para que o execution environment reflita o valor atualizado.
variáveis criptografadas"] --> B["Cold Start
novo execution environment"] B --> C["Init Phase
variáveis injetadas no processo"] C --> D["Handler Execution
os.environ / process.env"] D --> E{"Próxima invocação"} E -->|"Warm"| D E -->|"Novo ambiente"| B F["update-function-configuration"] --> A F -.->|"Ambientes warm existentes
NÃO são atualizados imediatamente"| D
- Configuração da função: variáveis ficam armazenadas criptografadas no plano de controle do Lambda.
- Init phase: ao criar um novo execution environment, o Lambda descriptografa e injeta as variáveis no processo.
- Handler execution: o código acessa via variáveis de ambiente do sistema operacional — sem chamada de API adicional.
- Warm invocation: execution environments reutilizados já têm as variáveis injetadas; mudanças só aparecem em novos ambientes.
Configurando Variáveis de Ambiente via AWS CLI
A forma mais direta de entender o modelo é pela CLI. Você pode definir variáveis na criação da função ou atualizá-las independentemente do código.
Criando uma função com variáveis de ambiente:
aws lambda create-function \
--function-name minha-funcao \
--runtime python3.12 \
--role arn:aws:iam::123456789012:role/minha-role-lambda \
--handler app.handler \
--zip-file fileb://function.zip \
--environment 'Variables={DB_ENDPOINT=meu-banco.cluster-abc123.us-east-1.rds.amazonaws.com,DB_PORT=5432,APP_ENV=production}'
Atualizando variáveis sem novo deploy de código:
aws lambda update-function-configuration \
--function-name minha-funcao \
--environment 'Variables={DB_ENDPOINT=meu-banco-novo.cluster-xyz.us-east-1.rds.amazonaws.com,DB_PORT=5432,APP_ENV=production}'
Atenção: update-function-configuration --environment substitui todo o bloco de variáveis, não faz merge. Se você omitir uma variável existente, ela é removida. Sempre inclua todas as variáveis no payload.
Verificando a configuração atual:
aws lambda get-function-configuration \
--function-name minha-funcao \
--query 'Environment'
Acessando Variáveis de Ambiente no Código
O acesso é direto — as variáveis estão disponíveis como variáveis de ambiente do processo. Não há SDK call, não há latência de rede.
Python:
import os
def handler(event, context):
db_endpoint = os.environ['DB_ENDPOINT']
db_port = os.environ.get('DB_PORT', '5432') # com valor padrão
app_env = os.environ['APP_ENV']
# use db_endpoint para conectar ao banco
print(f'Conectando em {db_endpoint}:{db_port}')
Node.js:
exports.handler = async (event) => {
const dbEndpoint = process.env.DB_ENDPOINT;
const dbPort = process.env.DB_PORT || '5432';
const appEnv = process.env.APP_ENV;
console.log(`Conectando em ${dbEndpoint}:${dbPort}`);
};
Uma prática que vale adotar: valide a presença das variáveis obrigatórias no início do handler — ou melhor, fora do handler para que a validação ocorra no init phase. Uma função que falha rápido com mensagem clara é muito mais fácil de debugar do que uma que quebra silenciosamente na conexão com o banco.
Criptografia com KMS — Variáveis de Ambiente no Lambda
Por padrão, o Lambda criptografa variáveis de ambiente em repouso usando uma chave gerenciada pela AWS (aws/lambda). Isso é automático e sem custo adicional de KMS. Para cenários onde você precisa de controle sobre a chave — auditoria granular via CloudTrail, rotação gerenciada por você, ou requisitos de compliance — você pode usar uma Customer Managed Key (CMK).
- Sem CMK (padrão): AWS gerencia a chave
aws/lambda. Criptografia transparente, sem custo adicional de KMS por chamada de API. - Com CMK — criptografia em repouso: Lambda usa sua CMK para criptografar os valores armazenados. Você vê as chamadas no CloudTrail.
- Com CMK — helpers de criptografia: o console oferece a opção de criptografar o valor antes de enviá-lo ao Lambda, exigindo que o código chame o KMS explicitamente para descriptografar em runtime.
Configurando uma CMK para criptografia em repouso
Primeiro, a role de execução do Lambda precisa de permissão para usar a chave:
🔽 Clique para expandir — Política IAM para a role do Lambda usar a CMK
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowLambdaToUseKMSKey",
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "arn:aws:kms:us-east-1:123456789012:key/sua-chave-id"
}
]
}
Depois, associe a CMK à função:
aws lambda update-function-configuration \
--function-name minha-funcao \
--kms-key-arn arn:aws:kms:us-east-1:123456789012:key/sua-chave-id \
--environment 'Variables={DB_ENDPOINT=meu-banco.cluster-abc123.us-east-1.rds.amazonaws.com,DB_PORT=5432,APP_ENV=production}'
Com isso, o Lambda usa sua CMK para criptografar os valores em repouso. A descriptografia acontece automaticamente durante o init phase — o código continua acessando via os.environ normalmente, sem nenhuma chamada explícita ao KMS.
Criptografia adicional com helpers do console (encrypt in transit)
O console do Lambda oferece uma opção de 'encryption helpers' que vai além da criptografia em repouso: o valor é criptografado pelo KMS antes de ser enviado para o Lambda. Nesse caso, o valor armazenado na configuração da função é o ciphertext, e o código precisa chamar o KMS explicitamente para descriptografar.
Esse modelo faz sentido quando você quer garantir que o valor nunca trafegue em plaintext — nem durante a configuração. O tradeoff é latência adicional no cold start (uma chamada KMS Decrypt por variável) e complexidade no código.
Python com descriptografia explícita via KMS:
🔽 Clique para expandir — Handler com descriptografia KMS explícita
import os
import boto3
import base64
kms_client = boto3.client('kms')
# Descriptografa uma vez no init phase, fora do handler
def decrypt_env_var(encrypted_value):
response = kms_client.decrypt(
CiphertextBlob=base64.b64decode(encrypted_value)
)
return response['Plaintext'].decode('utf-8')
# Executado no init phase — reutilizado em warm invocations
DB_ENDPOINT = decrypt_env_var(os.environ['DB_ENDPOINT'])
def handler(event, context):
# DB_ENDPOINT já está descriptografado e em memória
print(f'Conectando em {DB_ENDPOINT}')
Colocar a descriptografia fora do handler é intencional: o KMS Decrypt é chamado uma vez por execution environment, não a cada invocação. Em funções com alto throughput, isso evita tanto latência quanto custo desnecessário de KMS.
Diagnóstico: Quando a Variável Não Aparece ou o Valor Está Errado
Esse é o cenário clássico: você atualizou a variável, fez um teste, e o comportamento não mudou. A primeira suspeita costuma ser cache de código ou bug no handler — mas quase sempre é um execution environment antigo ainda ativo.
Sintoma: função retorna o valor antigo mesmo após update-function-configuration.
Diagnóstico errado: o código está cacheando o valor em uma variável global.
Causa real: execution environments warm ainda têm as variáveis antigas injetadas. O Lambda não recicla ambientes ativos imediatamente após uma atualização de configuração.
Verificação 1 — confirme que a atualização foi aplicada:
aws lambda get-function-configuration \
--function-name minha-funcao \
--query 'Environment.Variables'
Verificação 2 — confirme a versão em execução:
aws lambda get-function-configuration \
--function-name minha-funcao \
--query '{LastModified:LastModified,State:State,LastUpdateStatus:LastUpdateStatus}'
Se LastUpdateStatus for Successful e o valor no console estiver correto, o problema é execution environment antigo. A solução é aguardar o Lambda reciclar os ambientes naturalmente, ou forçar um novo deploy (mesmo sem mudança de código) para acelerar a transição.
Verificação 3 — erro de permissão KMS no CloudWatch Logs:
aws logs filter-log-events \
--log-group-name /aws/lambda/minha-funcao \
--filter-pattern 'AccessDeniedException' \
--start-time $(date -d '1 hour ago' +%s000)
Se a role do Lambda não tem permissão kms:Decrypt na CMK configurada, a função falha no init phase com AccessDeniedException. O erro aparece nos logs antes de qualquer linha do seu handler — o que confunde quem procura o problema no código da aplicação.
Variáveis de Ambiente vs. Secrets Manager vs. SSM Parameter Store
Variáveis de ambiente são convenientes, mas não são a solução certa para todos os cenários. A distinção prática:
| Critério | Env Vars + KMS | Secrets Manager | SSM Parameter Store |
|---|---|---|---|
| Rotação automática | Não | Sim (nativo) | Não (requer automação) |
| Latência de acesso | Zero (já injetado) | Chamada de API (rede) | Chamada de API (rede) |
| Atualização sem redeploy | Sim (nova invocação) | Sim (sem restart) | Sim (sem restart) |
| Custo | KMS por uso | Por segredo + por chamada de API | Gratuito (Standard); custo para Advanced |
| Ideal para | Endpoints, flags de config | Senhas, tokens com rotação | Configuração hierárquica |
Para um endpoint de banco de dados que não muda frequentemente, variáveis de ambiente com CMK são suficientes e têm latência zero. Para a senha do banco, Secrets Manager com rotação automática é o caminho correto — não coloque senhas em variáveis de ambiente se você pode evitar.
Configuração com AWS SAM (IaC)
Em produção, você raramente configura variáveis pelo console ou CLI diretamente. O SAM é a forma mais comum para funções Lambda:
🔽 Clique para expandir — template.yaml com variáveis de ambiente e CMK
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters:
DbEndpoint:
Type: String
Description: Endpoint do banco de dados RDS
KmsKeyArn:
Type: String
Description: ARN da CMK para criptografia das variáveis
Resources:
MinhaFuncao:
Type: AWS::Serverless::Function
Properties:
FunctionName: minha-funcao
Handler: app.handler
Runtime: python3.12
KmsKeyArn: !Ref KmsKeyArn
Environment:
Variables:
DB_ENDPOINT: !Ref DbEndpoint
DB_PORT: '5432'
APP_ENV: production
Policies:
- Statement:
- Effect: Allow
Action:
- kms:Decrypt
- kms:GenerateDataKey
Resource: !Ref KmsKeyArn
Passe os valores sensíveis como parâmetros no deploy — nunca os coloque diretamente no template versionado:
sam deploy \
--template-file template.yaml \
--stack-name minha-stack \
--parameter-overrides \
DbEndpoint=meu-banco.cluster-abc123.us-east-1.rds.amazonaws.com \
KmsKeyArn=arn:aws:kms:us-east-1:123456789012:key/sua-chave-id \
--capabilities CAPABILITY_IAM
Próximos Passos e Variáveis de Ambiente no Lambda em Produção
Para a maioria dos casos de uso — endpoints de banco, URLs de serviços, flags de feature — variáveis de ambiente com uma CMK cobrem o requisito com latência zero e complexidade mínima. O passo seguinte natural é avaliar se os segredos que você está colocando em variáveis deveriam estar no Secrets Manager, especialmente se houver rotação envolvida.
- AWS Docs — Lambda Environment Variables
- AWS Docs — Lambda Data Protection
- AWS Docs — Secrets Manager com Lambda
Glossário
| Termo | Definição |
|---|---|
| Execution Environment | Ambiente isolado criado pelo Lambda para executar uma função; persiste entre invocações warm para reutilização. |
| CMK (Customer Managed Key) | Chave KMS criada e gerenciada pelo cliente, com controle total sobre política, rotação e auditoria. |
| Init Phase | Fase de inicialização do execution environment onde o código fora do handler é executado; ocorre apenas em cold starts. |
| Ciphertext | Dado criptografado — o resultado de uma operação de criptografia KMS que só pode ser revertido com a chave correta. |
| Cold Start | Primeira invocação em um novo execution environment; inclui init phase e tem latência maior que invocações warm. |
Comentários
Postar um comentário