(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Como fazer mascaramento de dados em ETL: passo a passo

João Barros 29 de August de 2026 4 min de leitura

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.