はじめに
本番環境から取得したデータを使用する際のデータマスキング についてまとめる
- 特定の列や値を匿名化または置換。
- 主要なデータ項目に対し、尤もらしい形式を保持しつつ、匿名化するpython処理
Fakerを使用した簡単な例
Fakerライブラリを使用して、リアルな偽のデータを生成します
import pandas as pd
from faker import Faker
# サンプルの匿名化前のデータ
data = {
'name': ['山田太郎', '鈴木花子', '佐藤健', '田中美穂'],
'email': ['yamada@example.com', 'suzuki@example.com', 'sato@example.com', 'tanaka@example.com'],
'phone': ['090-1234-5678', '080-2345-6789', '070-3456-7890', '090-4567-8901'],
'address': ['東京都港区1-2-3', '大阪府大阪市中央区1-2-3', '愛知県名古屋市中区1-2-3', '福岡県福岡市中央区1-2-3']
}
df = pd.DataFrame(data)
# Fakerインスタンスの作成
faker = Faker('ja_JP')
# 名前の匿名化
df['name'] = [faker.name() for _ in range(len(df))]
# メールアドレスの匿名化
df['email'] = [faker.email() for _ in range(len(df))]
# 電話番号の匿名化
df['phone'] = [faker.phone_number() for _ in range(len(df))]
# 住所の匿名化
df['address'] = [faker.address() for _ in range(len(df))]
print(df)
出力結果
name email phone address
0 小林 裕美 uekimiyuki@example.org 090-4082-8195 山梨県田村市西之園町2-12-12
1 松田 花子 kubonarumi@kudo.net 090-4747-7765 神奈川県越智郡金城町前原西5-10-12
2 岩崎 美咲 ayamiyoshi@example.jp 080-7207-7844 大阪府高松市古市町2-15-5
3 今井 奈央子 maikeyasuhiro@abe.com 090-4119-8787 青森県下高井郡沼村中央4-8
Lambdaで実行する例
PythonスクリプトはAWSのLambda関数として実装し、特定のバケット内のS3から設定ファイルとデータを読み込んで、データを匿名化した後、結果を別のバケットに保存します。
import json
import boto3
import os
from faker import Faker
import pandas as pd
from io import StringIO
from botocore.exceptions import ClientError
def get_env_var(var_name):
""" 環境変数を取得し、存在しない場合はエラーを発生させる。 """
try:
return os.environ[var_name]
except KeyError:
print(f"Environment variable {var_name} not found.")
raise
def read_config_from_s3(bucket, key):
""" S3から設定ファイルを読み込む。 """
s3 = boto3.client('s3')
try:
response = s3.get_object(Bucket=bucket, Key=key)
return json.loads(response['Body'].read())
except ClientError as e:
print(f"Failed to read config from {bucket}/{key}: {e}")
raise
def load_data_from_s3(bucket, key):
""" S3からCSVファイルを読み込み、pandas DataFrameとして返す。 """
s3 = boto3.client('s3')
try:
response = s3.get_object(Bucket=bucket, Key=key)
return pd.read_csv(response['Body'])
except ClientError as e:
print(f"Failed to load data from {bucket}/{key}: {e}")
raise
def save_data_to_s3(df, bucket, key):
""" DataFrameをCSVとしてS3に保存する。 """
csv_buffer = StringIO()
df.to_csv(csv_buffer, index=False)
s3_resource = boto3.resource('s3')
try:
s3_resource.Object(bucket, key).put(Body=csv_buffer.getvalue())
except ClientError as e:
print(f"Failed to save data to {bucket}/{key}: {e}")
raise
def anonymize_data(df, columns, faker_functions):
""" DataFrame内の指定された列を匿名化する。 """
faker = Faker('ja_JP')
for column, faker_function in zip(columns, faker_functions):
function, params = faker_function['name'], faker_function.get('parameters', {})
df[column] = [getattr(faker, function)(**params) for _ in range(len(df))]
def handler(event, context):
""" Lambdaのメインハンドラ関数。 """
try:
input_bucket = get_env_var('INPUT_BUCKET')
output_bucket = get_env_var('OUTPUT_BUCKET')
config_key = get_env_var('CONFIG_KEY')
config = read_config_from_s3(input_bucket, config_key)
for table in config['tables']:
df = load_data_from_s3(input_bucket, table['input_file'])
anonymize_data(df, [col['name'] for col in table['columns']], [col['faker_function'] for col in table['columns']])
save_data_to_s3(df, output_bucket, table['output_file'])
return {'statusCode': 200, 'body': json.dumps('Data anonymization completed successfully.')}
except Exception as e:
return {'statusCode': 500, 'body': json.dumps(f"An error occurred: {str(e)}")}
nonymization_config.json
{
"tables": [
{
// ユーザーテーブル用の設定
"input_file": "user_table.csv", // 入力ファイル名
"output_file": "anonymized_user_table.csv", // 匿名化後の出力ファイル名
"columns": [
// 各列の匿名化方法の指定
{"name": "name", "faker_function": "name"}, // 名前
{"name": "last_name", "faker_function": "last_name"}, // 苗字
{"name": "first_name", "faker_function": "first_name"}, // 名前
{"name": "address", "faker_function": "address"}, // 住所
{"name": "zipcode", "faker_function": "zipcode"}, // 郵便番号
{"name": "city", "faker_function": "city"}, // 市区町村
{"name": "prefecture", "faker_function": "prefecture"}, // 都道府県
{"name": "email", "faker_function": "email"}, // メールアドレス
{"name": "phone", "faker_function": "phone_number", "parameters": {"formats": "+81-##-####-####"}}, // 電話番号
{"name": "ssn", "faker_function": "ssn"}, // 社会保険番号
{"name": "university", "faker_function": "university"}, // 大学名
{"name": "university_name", "faker_function": "university_name"}, // 大学名
{"name": "secondary_school", "faker_function": "secondary_school"}, // 中学校
{"name": "credit_card_number", "faker_function": "credit_card_number", "parameters": {"card_type": "Visa"}}, // クレジットカード番号
{"name": "credit_card_expiry", "faker_function": "credit_card_expiry", "parameters": {"format": "MM/YY"}}, // クレジットカード有効期限
{"name": "credit_card_provider", "faker_function": "credit_card_provider"} // クレジットカード提供者
]
},
{
// 販売店マスターテーブル用の設定
"input_file": "merchant_master_table.csv", // 入力ファイル名
"output_file": "anonymized_merchant_master_table.csv", // 匿名化後の出力ファイル名
"columns": [
// 各列の匿名化方法の指定
{"name": "name", "faker_function": "company"}, // 会社名
{"name": "email", "faker_function": "company_email"}, // 会社メールアドレス
{"name": "phone", "faker_function": "phone_number", "parameters": {"formats": "+81-##-####-####"}}, // 会社電話番号
{"name": "address", "faker_function": "address"}, // 会社住所
{"name": "credit_card_number", "faker_function": "credit_card_number", "parameters": {"card_type": "Visa"}}, // 会社クレジットカード番号
{"name": "url", "faker_function": "url"} // 会社ウェブサイトURL
]
},
{
// トランザクションテーブル用の設定
"input_file": "transaction_table.csv", // 入力ファイル名
"output_file": "anonymized_transaction_table.csv", // 匿名化後の出力ファイル名
"columns": [
// 各列の匿名化方法の指定
{"name": "transaction_id", "faker_function": "uuid4", "parameters": {"version": 4}}, // トランザクションID
{"name": "transaction_date", "faker_function": "date_between", "parameters": {"start_date": "-5y", "end_date": "today"}} // トランザクション日付
]
}
]
}