Cómo hacer enmascaramiento de datos en ETL: paso a paso
Este tutorial muestra cómo aplicar enmascaramiento de datos en ETL para proteger PII (Personally Identifiable Information) durante el procesamiento. Aprenderás un método sencillo y seguro para sustituir u ofuscar campos sensibles antes de cargar a sistemas de consumo.
Requisitos previos
- Conocimientos básicos de Python y manipulación de archivos CSV.
- Python 3.8+ instalado con pandas y faker (pip install pandas faker).
- Un archivo CSV de ejemplo con columnas PII (p. ej.: name, email, ssn).
Paso 1: Por qué enmascarar datos y estrategias comunes
El enmascaramiento de datos protege PII para desarrollo, pruebas y análisis, reduciendo la exposición. Estrategias comunes: sustitución determinística (mapeo consistente), sustitución aleatoria (no reversible), tokenización y cifrado. Vamos a aplicar dos técnicas: sustitución determinística para contactos y sustitución aleatoria para SSN.
Paso 2: Preparar el entorno y cargar datos
Carga el CSV en un DataFrame con pandas. Mantén una copia original y trabaja sobre otra para garantizar auditoría.
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()
Paso 3: Implementar sustitución determinística
La sustitución determinística garantiza que el mismo valor de entrada genera siempre el mismo valor enmascarado — útil para preservar relaciones entre tablas. Usa un hash simple y un mapeo persistente (aquí un archivo JSON como ejemplo).
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))
Paso 4: Implementar sustitución aleatoria (irreversible)
Para campos que no necesitan correlación (p. ej.: SSN en datos de prueba), genera valores aleatorios no reversibles. El módulo Faker es útil para crear valores plausibles.
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)
Paso 5: Mantener registros de auditoría y reglas de anonimización
Guarda metadatos sobre lo que se ha enmascarado: columnas, método (determinístico/aleatorio), fecha y usuario. Esto ayuda a la gobernanza y reproducibilidad sin exponer 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')
Paso 6: Validar y exportar los datos enmascarados
Verifica que no existen valores originales en las columnas enmascaradas y exporta al destino (CSV, data lake o base de datos). Mantén bases de datos separadas para los originales y las máscaras cuando sea necesario.
# 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 el resultado
Abre output_masked.csv y confirma que las columnas sensibles están sustituidas y que no hay valores originales. Verifica también mask_map.json para asegurar consistencia determinística y mask_metadata.json para auditoría. Prueba la reejecución con algunos registros añadidos para garantizar el mapeo persistente.
Conclusión
Aplicar enmascaramiento de datos en ETL protege PII y permite compartir datos para pruebas y análisis sin exposición. Próximos pasos: integrar este código en un pipeline (p. ej.: Airflow o Azure Data Factory), añadir cifrado para map_file y controlar accesos. Consejo: elige determinístico para claves que necesiten vinculación entre sistemas y aleatorio cuando no sea necesaria correlación.