Monitoramento de Integridade de Arquivos: Uma Abordagem Escalável
As organizações enfrentam o desafio constante de rastrear mudanças em seus ambientes de nuvem. Isso inclui monitorar arquivos, softwares instalados e configurações em várias instâncias. Detectar alterações não autorizadas é crítico para a segurança, especialmente quando essas mudanças precisam ser integradas aos fluxos de trabalho existentes.
A AWS oferece uma solução altamente escalável e serverless para esse problema. O conceito apresentado utiliza o AWS Systems Manager Inventory para coletar metadados de arquivos em instâncias Amazon EC2, envia esses dados por meio do recurso de sincronização do Systems Manager para um bucket Amazon S3 com versionamento, e implementa uma função AWS Lambda que compara versões de inventário para detectar mudanças. Quando alterações são identificadas, a função cria achados no AWS Security Hub, que são posteriormente ingeridos pelo Amazon Security Lake em formato padronizado.

Vantagens desta Abordagem
Esta solução oferece uma alternativa ao padrão de integração entre AWS Config e Security Hub, que se baseia em dados limitados sem incluir, por exemplo, timestamps de modificação de arquivos. A abordagem aqui apresentada fornece flexibilidade e controle para implementar lógica personalizada de detecção adaptada às necessidades operacionais específicas de cada organização.
Além disso, o modelo é extensível. O AWS Systems Manager Inventory pode coletar não apenas metadados de arquivos, mas também dados sobre aplicativos instalados, configurações de rede ou entradas do Windows Registry, permitindo criar lógica de detecção customizada para uma ampla gama de casos de uso operacionais e de segurança.
Etapas de Implementação
Pré-requisitos
Antes de começar, você precisará de uma conta AWS com permissões para criar e gerenciar recursos como Amazon EC2, AWS Systems Manager, Amazon S3 e Lambda.
Etapa 1: Configuração da Instância EC2
O primeiro passo é iniciar uma instância EC2 e criar um arquivo de configuração que será modificado posteriormente para simular uma alteração não autorizada.
Você precisará criar um papel AWS Identity and Access Management (IAM) para permitir que a instância EC2 se comunique com o Systems Manager. No console do IAM, crie um novo papel, selecione EC2 como caso de uso e anexe a política gerenciada AmazonSSMManagedInstanceCore. Nomeie esse papel como SSMAccessRole.
Em seguida, inicie uma instância EC2, mantendo a imagem Linux padrão e uma classe de instância como t3.micro. Nos detalhes avançados, atribua o papel SSMAccessRole que foi criado anteriormente. Para criar um arquivo de configuração de aplicativo durante a inicialização, use o script fornecido na seção User Data:
#!/bin/bash
mkdir -p /etc/paymentapp
echo "db_password=initial123" > /etc/paymentapp/config.yaml
Este script cria um diretório e um arquivo de configuração que será monitorado. Você pode deixar as demais configurações com seus valores padrão e prosseguir sem um key pair, já que o acesso será feito via Session Manager.
Etapa 2: Ativar Security Hub e Security Lake
Caso esses serviços já estejam ativados em sua conta, pule para a próxima etapa. Caso contrário, comece ativando o AWS Security Hub CSPM, que coleta e agrega achados de segurança e adiciona monitoramento contínuo.
No console do Security Hub, acesse a opção CSPM e selecione ativar. Para esta demonstração, você não necessita das opções de padrões de segurança, portanto, pode desmarcá-las.
A próxima etapa é ativar o Amazon Security Lake para começar a coletar achados do Security Hub. No console do Security Lake, selecione “Começar”, escolha ingerir fontes AWS específicas e selecione Security Hub como fonte de log e eventos. Escolha a região específica onde você está trabalhando, use a opção padrão para criar um novo papel de serviço e conclua a configuração.
Etapa 3: Configurar Systems Manager Inventory e Sincronização com S3
Com Security Hub e Security Lake ativados, o próximo passo é configurar o Systems Manager Inventory para coletar metadados de arquivos e exportar esses dados para S3.
Crie um bucket S3 seguindo as orientações da documentação AWS para sincronização de dados de recursos. Após criar o bucket, ative o versionamento em suas propriedades. O versionamento garante que cada novo snapshot de inventário seja salvo como uma versão separada, permitindo rastrear mudanças ao longo do tempo.
Em produção, recomenda-se ativar logging de acesso ao S3, forçar acesso apenas por HTTPS e ativar eventos de dados do CloudTrail para auditoria completa.
No console do Systems Manager, acesse Fleet Manager e configure o inventário, selecionando apenas o tipo de dados “File”. Defina o caminho para a coleta limitada aos arquivos relevantes, neste caso:
/etc/paymentapp/
Em seguida, create a sincronização de dados de recursos no Fleet Manager, fornecendo um nome para a sincronização e o nome do bucket S3 versionado criado anteriormente.
Etapa 4: Implementar a Função Lambda
Para completar a solução, você precisa criar uma função Lambda que detecte mudanças quando novos dados de inventário chegarem ao S3. Cada vez que o Systems Manager escreve um novo objeto no S3, uma Amazon S3 Event Notification acionará a função Lambda, que comparará as versões mais recentes e anteriores do objeto.
Se forem encontrados arquivos criados, modificados ou deletados, a função cria um achado de segurança em formato ASFF (AWS Security Finding Format) no Security Hub.
Crie a função Lambda no console com o nome fim-change-detector, selecione Python como runtime e copie o código principal da função:
import boto3, os, json, re
from datetime import datetime, UTC
from urllib.parse import unquote_plus
from helpers import is_critical, load_file_metadata, is_modified, extract_instance_id
s3 = boto3.client('s3')
securityhub = boto3.client('securityhub')
CRITICAL_FILE_PATTERNS = os.environ["CRITICAL_FILE_PATTERNS"].split(",")
SEVERITY_LABEL = os.environ["SEVERITY_LABEL"]
def lambda_handler(event, context):
# Safe event handling
if "Records" not in event or not event["Records"]:
return
# Extract S3 event
record = event['Records'][0]
bucket = record['s3']['bucket']['name']
key = unquote_plus(record['s3']['object']['key'])
current_version = record['s3']['object'].get('versionId')
if not current_version:
return
# Fetching the region name
account_id = context.invoked_function_arn.split(":")[4]
region = boto3.session.Session().region_name
# Get object versions (latest first)
versions = s3.list_object_versions(Bucket=bucket, Prefix=key).get('Versions', [])
versions = sorted(versions, key=lambda v: v['LastModified'], reverse=True)
# Find previous version
idx = next((i for i,v in enumerate(versions) if v["VersionId"] == current_version), None)
if idx is None or idx + 1 >= len(versions):
return
prev_version = versions[idx+1]["VersionId"]
# Load both versions
current = load_file_metadata(bucket, key, current_version)
previous = load_file_metadata(bucket, key, prev_version)
# Compare
created = {p for p in set(current) - set(previous) if is_critical(p)}
deleted = {p for p in set(previous) - set(current) if is_critical(p)}
modified = {p for p in set(current) & set(previous) if is_critical(p) and is_modified(p, current, previous)}
# Report if changes were found
if created or deleted or modified:
instance_id = extract_instance_id(bucket, key, current_version)
now = datetime.now(UTC).isoformat(timespec='milliseconds').replace('+00:00', 'Z')
finding = {
"SchemaVersion": "2018-10-08",
"Id": f"fim-{instance_id}-{now}",
"ProductArn": f"arn:aws:securityhub:{region}:{account_id}:product/{account_id}/default",
"AwsAccountId": account_id,
"GeneratorId": "ssm-inventory-fim",
"CreatedAt": now,
"UpdatedAt": now,
"Types": ["Software and Configuration Checks/File Integrity Monitoring"],
"Severity": {"Label": SEVERITY_LABEL},
"Title": "File changes detected via SSM Inventory",
"Description": (
f"{len(created)} created, {len(modified)} modified, "
f"{len(deleted)} deleted file(s) on instance {instance_id}"
),
"Resources": [{"Type": "AwsEc2Instance", "Id": instance_id}]
}
securityhub.batch_import_findings(Findings=[finding])
# No change – delete older S3 version
else:
if prev_version != current_version:
try:
s3.delete_object(Bucket=bucket, Key=key, VersionId=prev_version)
except Exception as e:
print(f"Delete previous S3 object version failed: {e}")
Configurar Variáveis de Ambiente
A função Lambda requer duas variáveis de ambiente. No console Lambda, acesse a aba Configuração e defina:
- CRITICAL_FILE_PATTERNS:
^/etc/paymentapp/config.*$ - SEVERITY_LABEL:
MEDIUM
Definir Permissões
A função Lambda precisa de permissões específicas. Crie uma política inline no papel de execução da função com as seguintes permissões (substitua <bucket-name>, <region> e <account-id> pelos seus valores):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "securityhub:BatchImportFindings",
"Resource": "arn:aws:securityhub:::product//default"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:ListBucketVersions",
"s3:DeleteObjectVersion"
],
"Resource": [
"arn:aws:s3:::",
"arn:aws:s3:::/*"
]
}
]
}
Adicionar Funções Auxiliares via Lambda Layer
Para melhor modularidade, crie um Lambda layer contendo funções auxiliares. Abra o AWS CloudShell e execute o seguinte script:
#!/bin/bash
set -e
FUNCTION_NAME="fim-change-detector"
LAYER_NAME="fim-change-detector-layer"
mkdir -p python
cat > python/helpers.py << 'EOF'
import json, re, os
from dateutil.parser import parse as parse_dt
import boto3
s3 = boto3.client('s3')
CRITICAL_FILE_PATTERNS = os.environ.get("CRITICAL_FILE_PATTERNS", "").split(",")
def is_critical(path):
return any(re.match(p.strip(), path) for p in CRITICAL_FILE_PATTERNS if p.strip())
def load_file_metadata(bucket, key, version_id):
obj = s3.get_object(Bucket=bucket, Key=key, VersionId=version_id)
data = {}
for line in obj['Body'].read().decode().splitlines():
if line.strip():
i = json.loads(line)
n, d, m = i.get("Name","").strip(), i.get("InstalledDir","").strip(), i.get("ModificationTime","").strip()
if n and d and m:
data[f"{d.rstrip('/')}/{n}"] = m
return data
def is_modified(path, current, previous):
try:
return parse_dt(current[path]) != parse_dt(previous[path])
except:
return current[path] != previous[path]
def extract_instance_id(bucket, key, version_id):
obj = s3.get_object(Bucket=bucket, Key=key, VersionId=version_id)
for line in obj['Body'].read().decode().splitlines():
if line.strip():
r = json.loads(line)
if "resourceId" in r:
return r["resourceId"]
return None
EOF
zip -r helpers_layer.zip python >/dev/null
LAYER_VERSION_ARN=$(aws lambda publish-layer-version \
--layer-name "$LAYER_NAME" \
--description "Helper functions for File Integrity Monitoring" \
--zip-file fileb://helpers_layer.zip \
--compatible-runtimes python3.13 \
--query 'LayerVersionArn' \
--output text)
aws lambda update-function-configuration \
--function-name "$FUNCTION_NAME" \
--layers "$LAYER_VERSION_ARN" >/dev/null
echo "Layer created and attached to the Lambda function."
Etapa 5: Configurar Notificações de Eventos S3
Configure as S3 Event Notifications para acionar a função Lambda quando novos dados de inventário chegarem. No console S3, abra o bucket de inventário, acesse propriedades e crie uma notificação de evento com o seguinte configuração:
- No prefixo, defina
AWS%3AFile/para limitar os acionadores apenas aos objetos de inventário de arquivos - Selecione o tipo de evento “Put”
- Aponte para a função Lambda recém-criada
A coleta de inventário é executada a cada 30 minutos por padrão, mas pode ser ajustada conforme os requisitos de segurança da organização.
Etapa 6: Testar a Detecção de Mudanças
Com a instância EC2 em execução e o arquivo de configuração inicializado, você está pronto para simular uma alteração não autorizada.
Use o Session Manager para conectar à instância e modificar o arquivo:
echo "db_password=hacked456" | sudo tee /etc/paymentapp/config.yaml
Para acelerar o teste, force uma execução imediata do inventário através do State Manager no console do Systems Manager. Após a conclusão bem-sucedida, verifique o bucket S3 e o console do Security Hub. Você deve ver um novo achado relatando a mudança detectada no arquivo.
Análise e Visualização de Dados
Enquanto o Security Hub oferece uma visão centralizada de achados, é possível aprofundar a análise utilizando o Amazon Athena para executar consultas SQL diretamente nos dados normalizados do Security Lake armazenados em S3, que seguem o padrão Open Cybersecurity Schema Framework (OCSF).
Um exemplo de consulta:
SELECT finding_info.desc AS description, class_uid AS class_id, severity AS severity_label, type_name AS finding_type, time_dt AS event_time, region, accountid
FROM amazon_security_lake_table_us_east_1_sh_findings_2_0
Ajuste a cláusula FROM conforme a região utilizada. O Security Lake processa os achados antes deles aparecerem no Athena, portanto, espere um pequeno atraso.
Para exploração visual e insights em tempo real, integre o Security Lake com o Amazon OpenSearch Service e Amazon QuickSight, ambos com suporte amplo a IA generativa. Consulte a documentação para um guia detalhado sobre visualização de achados.
Limpeza de Recursos
Após testar a solução, remova os recursos criados para evitar custos contínuos:
- Termine a instância EC2
- Delete a sincronização de dados de recursos e a associação de inventário
- Remova a função Lambda
- Desative o Security Lake e Security Hub CSPM
- Delete os papéis IAM criados
- Delete os buckets S3 utilizados para sincronização de dados e Security Lake
Considerações para Ambientes Produtivos
Em produção, considere as seguintes práticas recomendadas para a função Lambda:
- Configure concorrência reservada para evitar escalabilidade sem limite
- Configure uma fila de letra morta para capturar invocações que falharam
- Opcionalmente, anexe a função a uma Amazon VPC para isolamento de rede
Além disso, o Security Lake suporta coleta de dados em múltiplas contas e regiões utilizando o AWS Organizations. Um Systems Manager resource data sync também pode ser configurado para enviar dados de inventário a um bucket S3 centralizado, simplificando a gestão em ambientes de múltiplas contas.
Conclusão
A solução apresentada demonstra como combinar o Systems Manager Inventory, Security Hub e Security Lake para criar um sistema robusto de monitoramento de integridade de arquivos. A abordagem oferece flexibilidade, controle e escalabilidade para organizações que buscam aprofundar a visibilidade sobre mudanças em seus ambientes AWS.
O código completo da solução está disponível no AWS Samples repository. Para uma visão mais ampla sobre implementações em múltiplas contas e regiões, consulte a documentação sobre Getting Started with Amazon Security Lake and Systems Manager Inventory.
Fonte
File integrity monitoring with AWS Systems Manager and Amazon Security Lake (https://aws.amazon.com/blogs/security/file-integrity-monitoring-with-aws-systems-manager-and-amazon-security-lake/)
Leave a Reply