feat(masking): add PII columns to generators + backfill (Faker-style, no deps)
Source generators (postgres/mysql/mongodb) now emit realistic PII (name/email/phone/ip/iban/address/national_id/dob). deploy/mask_pii_setup.py ALTERs the source tables and backfills a bounded sample so Debezium CDC and OpenMetadata PII auto-classification see real sensitive values.
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate fake employee event data for MySQL.
|
||||
Light + configurable via GEN_ROWS. Now also populates realistic PII columns
|
||||
(employee_name/email/phone, national_id, home_address, date_of_birth).
|
||||
"""
|
||||
|
||||
import mysql.connector
|
||||
import random
|
||||
from datetime import datetime, timedelta
|
||||
import uuid
|
||||
import os
|
||||
|
||||
DB_HOST = "10.0.21.51"
|
||||
DB_PORT = "3306"
|
||||
DB_NAME = "hr"
|
||||
DB_USER = "mo"
|
||||
DB_PASSWORD = "Dell2026!"
|
||||
|
||||
TARGET_ROWS = int(os.getenv("GEN_ROWS", "5000"))
|
||||
BATCH_SIZE = min(10000, max(500, TARGET_ROWS))
|
||||
|
||||
DEPARTMENTS = ["HR", "Operations", "Sales", "Marketing", "Finance", "IT", "Engineering", "Legal"]
|
||||
ROLE_NAMES = ["Analyst", "Lead", "Manager", "Consultant", "Director", "Engineer", "Specialist", "Coordinator"]
|
||||
REGIONS = ["EU", "APAC", "LATAM", "NA", "EMEA"]
|
||||
EVENT_TYPES = ["TRANSFER", "PROMOTION", "TERMINATION", "HIRED", "SALARY_CHANGE", "DEPARTMENT_CHANGE"]
|
||||
|
||||
FIRST = ["Sophie", "Liam", "Emma", "Noah", "Julia", "Lucas", "Mila", "Daan", "Anna", "Sem",
|
||||
"Eva", "Finn", "Tess", "Bram", "Lotte", "Max", "Sara", "Thijs", "Nina", "Ruben"]
|
||||
LAST = ["de Vries", "Jansen", "Bakker", "Visser", "Smit", "Meijer", "Mulder", "Bos",
|
||||
"Vos", "Peters", "Hendriks", "Dijkstra", "Kok", "Willems", "Maas", "Koning"]
|
||||
STREETS = ["Kerkstraat", "Dorpsweg", "Molenpad", "Stationsplein", "Industrieweg", "Lindelaan",
|
||||
"Beukenhof", "Havenstraat", "Parkweg", "Schoolstraat"]
|
||||
CITIES = ["Amsterdam", "Rotterdam", "Utrecht", "Eindhoven", "Den Haag", "Groningen", "Tilburg", "Almere"]
|
||||
DOMAINS = ["example.com", "mail.nl", "acme-corp.eu", "company.eu", "contact.io"]
|
||||
|
||||
|
||||
def _name():
|
||||
return f"{random.choice(FIRST)} {random.choice(LAST)}"
|
||||
|
||||
|
||||
def _pii():
|
||||
nm = _name()
|
||||
return (
|
||||
nm,
|
||||
f"{nm.lower().replace(' ', '.')}{random.randint(1, 999)}@{random.choice(DOMAINS)}",
|
||||
f"+31 6 {random.randint(10, 99)} {random.randint(100000, 999999)}",
|
||||
str(random.randint(100000000, 999999999)),
|
||||
f"{random.choice(STREETS)} {random.randint(1, 320)}, {random.randint(1000, 9999)} {random.choice(CITIES)}",
|
||||
f"{random.randint(1960, 2002)}-{random.randint(1, 12):02d}-{random.randint(1, 28):02d}",
|
||||
)
|
||||
|
||||
|
||||
def generate_fake_employee_event():
|
||||
employee_id = random.randint(1, 100000)
|
||||
department = random.choice(DEPARTMENTS)
|
||||
role_name = random.choice(ROLE_NAMES)
|
||||
region = random.choice(REGIONS)
|
||||
event_type = random.choice(EVENT_TYPES)
|
||||
days_ago = random.randint(0, 730)
|
||||
event_ts = datetime.now() - timedelta(days=days_ago, hours=random.randint(0, 23),
|
||||
minutes=random.randint(0, 59))
|
||||
salary_change = round(random.uniform(1000.0, 20000.0), 2) if random.random() > 0.3 else None
|
||||
notes = str(uuid.uuid4()) * 10
|
||||
name, email, phone, nid, address, dob = _pii()
|
||||
return (employee_id, department, role_name, region, event_type, salary_change, event_ts, notes,
|
||||
name, email, phone, nid, address, dob)
|
||||
|
||||
|
||||
INSERT_SQL = """
|
||||
INSERT INTO employee_events (employee_id, department, role_name, region,
|
||||
event_type, salary_change, event_ts, notes,
|
||||
employee_name, employee_email, employee_phone,
|
||||
national_id, home_address, date_of_birth)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
"""
|
||||
|
||||
|
||||
def main():
|
||||
print(f"Connecting to MySQL at {DB_HOST}:{DB_PORT}...")
|
||||
conn = mysql.connector.connect(host=DB_HOST, port=DB_PORT, database=DB_NAME, user=DB_USER, password=DB_PASSWORD)
|
||||
cursor = conn.cursor()
|
||||
print(f"Generating {TARGET_ROWS} employee events (with PII)... batch={BATCH_SIZE}")
|
||||
total_generated = 0
|
||||
batch = []
|
||||
for i in range(TARGET_ROWS):
|
||||
batch.append(generate_fake_employee_event())
|
||||
if len(batch) >= BATCH_SIZE:
|
||||
cursor.executemany(INSERT_SQL, batch)
|
||||
conn.commit()
|
||||
total_generated += len(batch)
|
||||
batch = []
|
||||
if batch:
|
||||
cursor.executemany(INSERT_SQL, batch)
|
||||
conn.commit()
|
||||
total_generated += len(batch)
|
||||
cursor.close()
|
||||
conn.close()
|
||||
print(f"Completed! Generated {total_generated} employee events.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user