Como fazer mascaramento de dados em ETL: passo a passo
Este tutorial mostra como aplicar mascaramento de dados em ETL para proteger PII (Personally Identifiable Information) durante o processamento. Irás aprender um método simples e seguro para substituir ou ofuscar campos sensíveis antes de carregar para sistemas de consumo.
Pré-requisitos
- Conhecimentos básicos de Python e manipulação de ficheiros CSV.
- Python 3.8+ instalado com pandas e faker (pip install pandas faker).
- Um ficheiro CSV de exemplo com colunas PII (ex.: name, email, ssn).
Passo 1: Por que mascarar dados e estratégias comuns
O mascaramento de dados protege PII para desenvolvimento, testes e análise, reduzindo a exposição. Estratégias comuns: substituição determinística (mapeamento consistente), substituição aleatória (não reversível), tokenização e encriptação. Vamos aplicar duas técnicas: substituição determinística para contactos e substituição aleatória para SSN.
Passo 2: Preparar o ambiente e carregar dados
Carrega o CSV para um DataFrame com pandas. Mantém uma cópia original e trabalha sobre outra para garantir auditoria.
import pandas as pd
from faker import Faker
fake = Faker()
# Exemplo: ficheiro input.csv com colunas: id,name,email,ssn,phone
df = pd.read_csv('input.csv')
df_orig = df.copy()
Passo 3: Implementar substituição determinística
A substituição determinística garante que o mesmo valor de entrada gera sempre o mesmo valor mascarado — útil para preservação de relações entre tabelas. Usa um hash simples e um mapeamento persistente (aqui um ficheiro JSON como exemplo).
import hashlib, json
from pathlib import Path
map_file = Path('mask_map.json')
if map_file.exists():
mask_map = json.loads(map_file.read_text())
else:
mask_map = {}
def deterministic_mask(value, prefix='U'):
if pd.isna(value):
return value
key = str(value)
if key in mask_map:
return mask_map[key]
h = hashlib.sha256(key.encode('utf-8')).hexdigest()[:10]
masked = f"{prefix}_{h}"
mask_map[key] = masked
return masked
# Exemplo para email e phone
df['email_masked'] = df['email'].apply(lambda v: deterministic_mask(v, prefix='EM'))
df['phone_masked'] = df['phone'].apply(lambda v: deterministic_mask(v, prefix='PH'))
# Persistir o mapa para reutilização
map_file.write_text(json.dumps(mask_map))
Passo 4: Implementar substituição aleatória (irreversível)
Para campos que não precisam de ser correlacionados (ex.: SSN em dados de teste), gera valores aleatórios não reversíveis. O módulo Faker é útil para criar valores plausíveis.
def random_ssn(_):
# Gera um número de identificação plausível (exemplo US SSN-format)
return fake.ssn()
# Aplica substituição aleatória; não é determinística
df['ssn_masked'] = df['ssn'].apply(random_ssn)
Passo 5: Manter registos de auditoria e regras de anonimização
Guarda metadados sobre o que foi mascarado: colunas, método (determinístico/aleatório), data e utilizador. Isso ajuda à governação e reprodutibilidade sem expor PII.
from datetime import datetime
metadata = {
'masked_columns': ['email','phone','ssn'],
'methods': {'email':'deterministic','phone':'deterministic','ssn':'random'},
'timestamp': datetime.utcnow().isoformat() + 'Z'
}
pd.Series(metadata).to_json('mask_metadata.json')
Passo 6: Validar e exportar os dados mascarados
Verifica que não existem valores originais nas colunas mascaradas e exporta para o destino (CSV, data lake ou base de dados). Mantém bases de dados separadas para os originais e as máscaras quando necessário.
# Verificações simples
assert df['email_masked'].isna().sum() == df['email'].isna().sum()
assert not df['ssn_masked'].isin(df['ssn']).any()
# Escolhe colunas para exportar (substitui originais)
df_out = df.copy()
df_out['email'] = df_out['email_masked']
df_out['phone'] = df_out['phone_masked']
df_out['ssn'] = df_out['ssn_masked']
# Exporta
df_out.drop(columns=['email_masked','phone_masked','ssn_masked']).to_csv('output_masked.csv', index=False)
Verificar o resultado
Abre output_masked.csv e confirma que as colunas sensíveis estão substituídas e que não há valores originais. Verifica também mask_map.json para garantir consistência determinística e mask_metadata.json para auditoria. Testa a reexecução com alguns registos adicionados para garantir o mapeamento persistente.
Conclusão
Aplicar mascaramento de dados em ETL protege PII e permite partilhar dados para testes e análise sem exposição. Próximos passos: integrar este código num pipeline (ex.: Airflow ou Azure Data Factory), adicionar encriptação para map_file e controlar acessos. Dica: escolhe determinístico para chaves que necessitam de ligação entre sistemas e aleatório quando não é necessária correlação.