File size: 1,891 Bytes
f4bf832
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
"""PII masking tool — regex fallback, Cloud DLP when credentials available."""
from __future__ import annotations
import os
import re

# Regex patterns for Korean PII
_PATTERNS = [
    (re.compile(r"\d{6}-[1-4]\d{6}"), "[주민등록번호]"),
    (re.compile(r"01[016789]-?\d{3,4}-?\d{4}"), "[전화번호]"),
    (re.compile(r"[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}"), "[이메일]"),
    (re.compile(r"\b\d{4}-\d{4}-\d{4}-\d{4}\b"), "[카드번호]"),
]


def mask_pii(text: str) -> str:
    """Mask personally identifiable information from text using regex patterns."""
    for pattern, replacement in _PATTERNS:
        text = pattern.sub(replacement, text)
    return text


async def mask_pii_safe(text: str) -> str:
    """Mask PII, preferring Cloud DLP when credentials are available."""
    project_id = os.getenv("GOOGLE_CLOUD_PROJECT_ID")
    if not project_id:
        return mask_pii(text)

    try:
        import google.cloud.dlp_v2 as dlp
        import asyncio

        client = dlp.DlpServiceClient()
        deidentify_config = {
            "info_type_transformations": {
                "transformations": [
                    {"primitive_transformation": {"replace_with_info_type_config": {}}}
                ]
            }
        }
        inspect_config = {
            "info_types": [
                {"name": "KOREA_RRN"},
                {"name": "PHONE_NUMBER"},
                {"name": "EMAIL_ADDRESS"},
            ]
        }
        response = await asyncio.to_thread(
            client.deidentify_content,
            request={
                "parent": f"projects/{project_id}",
                "deidentify_config": deidentify_config,
                "inspect_config": inspect_config,
                "item": {"value": text},
            },
        )
        return response.item.value
    except Exception:
        return mask_pii(text)