AWS Lake Formation은 데이터 레이크의 보안과 거버넌스를 중앙에서 관리하는 서비스입니다. 세분화된 접근 제어와 데이터 공유 기능을 제공합니다.
┌─────────────────────────────────────────────────────────────────────┐
│ AWS Lake Formation │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐│
│ │ Central Permissions ││
│ │ ┌─────────────────────────────────────────────────────────────┐││
│ │ │ Database: analytics_db │││
│ │ │ ├── Table: customers │││
│ │ │ │ ├── Column: name → Data Analyst: SELECT │││
│ │ │ │ ├── Column: email → Data Analyst: DENIED │││
│ │ │ │ └── Column: region → Data Analyst: SELECT │││
│ │ │ └── Table: orders │││
│ │ │ └── Row Filter: region = 'APAC' │││
│ │ └─────────────────────────────────────────────────────────────┘││
│ └─────────────────────────────────────────────────────────────────┘│
│ │ │
│ ┌───────────────┼───────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Athena │ │ Redshift │ │ EMR │ │
│ │ │ │ Spectrum │ │ │ │
│ │ 권한 자동 적용 │ │ 권한 자동 적용 │ │ 권한 자동 적용 │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘민감한 컬럼(PII)에 대한 접근을 사용자/역할별로 제어
필터 조건으로 사용자가 볼 수 있는 행을 제한
// Terraform - Lake Formation 권한
# 데이터베이스 권한
resource "aws_lakeformation_permissions" "database" {
principal = aws_iam_role.data_analyst.arn
permissions = ["DESCRIBE"]
database {
name = aws_glue_catalog_database.analytics.name
}
}
# 테이블 권한 (컬럼 수준)
resource "aws_lakeformation_permissions" "table_columns" {
principal = aws_iam_role.data_analyst.arn
permissions = ["SELECT"]
table_with_columns {
database_name = aws_glue_catalog_database.analytics.name
name = "customers"
column_names = ["customer_id", "name", "region"] # email 제외
}
}
# 행 수준 필터
resource "aws_lakeformation_data_cells_filter" "region_filter" {
table_data {
database_name = aws_glue_catalog_database.analytics.name
table_name = "orders"
name = "apac-only"
row_filter {
filter_expression = "region = 'APAC'"
}
}
}Lake Formation을 사용하면 다른 AWS 계정이나 조직과 데이터를 안전하게 공유할 수 있습니다.
┌─────────────────────────────────────────────────────────────────────┐
│ Cross-Account Data Sharing │
│ │
│ Producer Account (123456789012) │
│ ┌─────────────────────────────────────────────────────────────────┐│
│ │ Lake Formation ││
│ │ └── Grant: SELECT on analytics_db.customers ││
│ │ └── To: Account 987654321098 ││
│ └─────────────────────────────────────────────────────────────────┘│
│ │ │
│ ▼ RAM (Resource Access Manager) │
│ │
│ Consumer Account (987654321098) │
│ ┌─────────────────────────────────────────────────────────────────┐│
│ │ Resource Link → analytics_db.customers ││
│ │ └── Athena에서 쿼리 가능 ││
│ └─────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────┘┌─────────────────────────────────────────────────────────────────────┐
│ 데이터 암호화 계층 │
│ │
│ 전송 중 암호화 (In-Transit) │
│ ┌─────────────────────────────────────────────────────────────────┐│
│ │ Client ──── TLS 1.2+ ────▶ AWS Service ││
│ │ • HTTPS 엔드포인트 ││
│ │ • VPC 엔드포인트 (PrivateLink) ││
│ └─────────────────────────────────────────────────────────────────┘│
│ │
│ 저장 시 암호화 (At-Rest) │
│ ┌─────────────────────────────────────────────────────────────────┐│
│ │ S3 ││
│ │ ├── SSE-S3: AWS 관리 키 (기본) ││
│ │ ├── SSE-KMS: 고객 관리 CMK (권장) ││
│ │ └── SSE-C: 고객 제공 키 ││
│ │ ││
│ │ Redshift: AES-256 (KMS 통합) ││
│ │ Glue: KMS 암호화 ││
│ │ OpenSearch: KMS 암호화 ││
│ └─────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────┘// S3 버킷 암호화 설정
resource "aws_s3_bucket_server_side_encryption_configuration" "data_lake" {
bucket = aws_s3_bucket.data_lake.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.data_lake.arn
}
bucket_key_enabled = true # 비용 절감
}
}
resource "aws_kms_key" "data_lake" {
description = "Data Lake encryption key"
deletion_window_in_days = 30
enable_key_rotation = true
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "Enable IAM policies"
Effect = "Allow"
Principal = { AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" }
Action = "kms:*"
Resource = "*"
}
]
})
}// 데이터 분석가 IAM 정책
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AthenaAccess",
"Effect": "Allow",
"Action": [
"athena:StartQueryExecution",
"athena:GetQueryExecution",
"athena:GetQueryResults"
],
"Resource": "arn:aws:athena:*:*:workgroup/analysts"
},
{
"Sid": "S3ReadOnly",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::data-lake-curated",
"arn:aws:s3:::data-lake-curated/*"
],
"Condition": {
"StringEquals": {
"s3:prefix": ["analytics/", "reports/"]
}
}
},
{
"Sid": "GlueCatalogRead",
"Effect": "Allow",
"Action": [
"glue:GetDatabase",
"glue:GetTable",
"glue:GetPartitions"
],
"Resource": [
"arn:aws:glue:*:*:catalog",
"arn:aws:glue:*:*:database/analytics_db",
"arn:aws:glue:*:*:table/analytics_db/*"
]
}
]
}┌─────────────────────────────────────────────────────────────────────┐
│ Glue Data Quality │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐│
│ │ Data Quality Ruleset ││
│ │ ├── Completeness: IsComplete "customer_id" ││
│ │ ├── Uniqueness: IsUnique "order_id" ││
│ │ ├── Freshness: IsFresh "created_at" > 24 hours ││
│ │ ├── Validity: ColumnValues "status" in ["A","B","C"] ││
│ │ └── Custom: RowCount > 1000 ││
│ └─────────────────────────────────────────────────────────────────┘│
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐│
│ │ Quality Score: 94.5% ││
│ │ ├── Passed: 47/50 rules ││
│ │ ├── Failed: 3 rules (email format, null values) ││
│ │ └── Action: Alert → SNS → Slack ││
│ └─────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────┘// DQDL (Data Quality Definition Language)
Rules = [
# 완전성 검사
IsComplete "customer_id",
IsComplete "order_date",
# 고유성 검사
IsUnique "order_id",
# 유효성 검사
ColumnValues "status" in ["pending", "completed", "cancelled"],
ColumnValues "amount" > 0,
ColumnValues "email" matches "^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$",
# 참조 무결성
ColumnValues "customer_id" in (select customer_id from customers),
# 통계적 검사
ColumnLength "phone" = 10,
StandardDeviation "amount" < 1000,
# 데이터 신선도
Freshness "created_at" <= 24 hours,
# 행 수 검사
RowCount between 1000 and 1000000
]┌─────────────────────────────────────────────────────────────────────┐
│ Data Catalog Metadata │
│ │
│ Table: orders │
│ ┌─────────────────────────────────────────────────────────────────┐│
│ │ Technical Metadata ││
│ │ ├── Location: s3://data-lake/curated/orders/ ││
│ │ ├── Format: Parquet ││
│ │ ├── Partitions: year, month, day ││
│ │ └── Row Count: 15,234,567 ││
│ ├─────────────────────────────────────────────────────────────────┤│
│ │ Business Metadata ││
│ │ ├── Owner: data-platform-team ││
│ │ ├── Description: Customer order transactions ││
│ │ ├── Classification: Confidential ││
│ │ └── Tags: [sales, transactions, pii] ││
│ ├─────────────────────────────────────────────────────────────────┤│
│ │ Data Lineage ││
│ │ └── raw.orders → curated.orders → analytics.order_summary ││
│ └─────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────┘// Glue Catalog 테이블 정의
resource "aws_glue_catalog_table" "orders" {
database_name = aws_glue_catalog_database.analytics.name
name = "orders"
table_type = "EXTERNAL_TABLE"
parameters = {
"classification" = "parquet"
"data_owner" = "data-platform-team"
"data_classification" = "confidential"
"has_pii" = "true"
}
storage_descriptor {
location = "s3://${aws_s3_bucket.data_lake.id}/curated/orders/"
input_format = "org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat"
output_format = "org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat"
columns {
name = "order_id"
type = "string"
comment = "Unique order identifier"
}
columns {
name = "customer_id"
type = "string"
comment = "Customer reference (PII)"
}
columns {
name = "amount"
type = "decimal(10,2)"
comment = "Order total amount"
}
}
partition_keys {
name = "year"
type = "string"
}
partition_keys {
name = "month"
type = "string"
}
}데이터 리니지는 데이터의 출처와 변환 과정을 추적합니다. 문제 발생 시 영향 범위 파악과 규정 준수에 필수적입니다.
┌─────────────────────────────────────────────────────────────────────┐
│ Data Lineage Flow │
│ │
│ Source Systems │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ MySQL │ │ API │ │ S3 │ │
│ │ orders │ │ events │ │ logs │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐│
│ │ Raw Layer (Bronze) ││
│ │ raw.orders | raw.events | raw.logs ││
│ └─────────────────────────────────────────────────────────────────┘│
│ │ Glue ETL │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐│
│ │ Curated Layer (Silver) ││
│ │ curated.orders_cleaned | curated.events_enriched ││
│ └─────────────────────────────────────────────────────────────────┘│
│ │ Glue ETL │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐│
│ │ Analytics Layer (Gold) ││
│ │ analytics.daily_sales | analytics.customer_360 ││
│ └─────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────┘Lake Formation vs IAM
Lake Formation = 데이터 레이크 전용, 컬럼/행 수준 제어
SSE-S3 vs SSE-KMS
SSE-KMS = 감사 로그, 키 로테이션, 세분화된 제어
데이터 품질 자동화
Glue Data Quality + EventBridge + SNS 알림
Cross-Account 공유
Lake Formation + RAM = 안전한 데이터 공유
┌─────────────────────────────────────────────────────────────────────────────┐
│ Amazon Macie │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ S3 Buckets ││
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││
│ │ │ data-lake │ │ analytics │ │ raw-data │ ││
│ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ ││
│ │ └────────────────┼────────────────┘ ││
│ │ │ ││
│ │ ▼ ││
│ │ ┌─────────────────────────────────────────────────────────────────┐ ││
│ │ │ Macie Discovery Job │ ││
│ │ │ │ ││
│ │ │ ML-based Classification: │ ││
│ │ │ ├── PII (Personally Identifiable Information) │ ││
│ │ │ │ ├── Names, Addresses, Phone Numbers │ ││
│ │ │ │ ├── Email Addresses │ ││
│ │ │ │ ├── Social Security Numbers │ ││
│ │ │ │ └── Credit Card Numbers │ ││
│ │ │ ├── Financial Data │ ││
│ │ │ │ ├── Bank Account Numbers │ ││
│ │ │ │ └── Financial Statements │ ││
│ │ │ └── Healthcare Data (PHI) │ ││
│ │ │ ├── Medical Record Numbers │ ││
│ │ │ └── Health Insurance IDs │ ││
│ │ └─────────────────────────────────────────────────────────────────┘ ││
│ │ │ ││
│ │ ▼ ││
│ │ ┌─────────────────────────────────────────────────────────────────┐ ││
│ │ │ Findings │ ││
│ │ │ • Severity: Critical / High / Medium / Low │ ││
│ │ │ • Location: s3://bucket/path/file.csv:line:column │ ││
│ │ │ • Data Type: CREDIT_CARD_NUMBER │ ││
│ │ │ • Count: 1,234 occurrences │ ││
│ │ └─────────────────────────────────────────────────────────────────┘ ││
│ └─────────────────────────────────────────────────────────────────────────┘│
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ EventBridge → Lambda → SNS/Slack (알림) ││
│ │ EventBridge → Step Functions (자동 조치) ││
│ └─────────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────────┘// Terraform - Macie 설정
# Macie 활성화
resource "aws_macie2_account" "main" {
finding_publishing_frequency = "FIFTEEN_MINUTES"
status = "ENABLED"
}
# 분류 작업 생성
resource "aws_macie2_classification_job" "sensitive_data" {
name = "sensitive-data-discovery"
job_type = "SCHEDULED"
job_status = "RUNNING"
s3_job_definition {
bucket_definitions {
account_id = data.aws_caller_identity.current.account_id
buckets = ["data-lake-raw", "data-lake-curated"]
}
scoping {
includes {
and {
simple_scope_term {
comparator = "STARTS_WITH"
key = "OBJECT_KEY"
values = ["customers/", "orders/"]
}
}
}
}
}
schedule_frequency {
weekly_schedule {
day_of_week = "MONDAY"
}
}
sampling_percentage = 100
custom_data_identifier_ids = [
aws_macie2_custom_data_identifier.employee_id.id
]
}
# 커스텀 데이터 식별자
resource "aws_macie2_custom_data_identifier" "employee_id" {
name = "employee-id"
description = "Employee ID pattern"
regex = "EMP-[0-9]{6}"
keywords = ["employee", "emp", "직원"]
}┌─────────────────────────────────────────────────────────────────────────────┐
│ Data Classification Framework │
│ │
│ Classification Levels: │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ Level 4: Restricted (제한) ││
│ │ ├── PII, PHI, Financial Data ││
│ │ ├── Encryption: Required (KMS CMK) ││
│ │ ├── Access: Need-to-know basis ││
│ │ └── Retention: Compliance-driven ││
│ ├─────────────────────────────────────────────────────────────────────────┤│
│ │ Level 3: Confidential (기밀) ││
│ │ ├── Business sensitive data ││
│ │ ├── Encryption: Required ││
│ │ ├── Access: Role-based ││
│ │ └── Retention: 7 years ││
│ ├─────────────────────────────────────────────────────────────────────────┤│
│ │ Level 2: Internal (내부) ││
│ │ ├── Internal business data ││
│ │ ├── Encryption: Recommended ││
│ │ ├── Access: All employees ││
│ │ └── Retention: 3 years ││
│ ├─────────────────────────────────────────────────────────────────────────┤│
│ │ Level 1: Public (공개) ││
│ │ ├── Public information ││
│ │ ├── Encryption: Optional ││
│ │ ├── Access: Anyone ││
│ │ └── Retention: As needed ││
│ └─────────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────────┘// S3 객체 태깅 자동화
import boto3
import json
def lambda_handler(event, context):
"""Macie 발견 시 자동 태깅"""
s3 = boto3.client('s3')
# Macie 발견 정보
finding = event['detail']
bucket = finding['resourcesAffected']['s3Bucket']['name']
key = finding['resourcesAffected']['s3Object']['key']
severity = finding['severity']['description']
data_types = [t['name'] for t in finding['classificationDetails']['result']['sensitiveData']]
# 분류 레벨 결정
if 'CREDIT_CARD_NUMBER' in data_types or 'AWS_CREDENTIALS' in data_types:
classification = 'restricted'
elif any(t in data_types for t in ['NAME', 'EMAIL_ADDRESS', 'PHONE_NUMBER']):
classification = 'confidential'
else:
classification = 'internal'
# 태그 적용
s3.put_object_tagging(
Bucket=bucket,
Key=key,
Tagging={
'TagSet': [
{'Key': 'data-classification', 'Value': classification},
{'Key': 'contains-pii', 'Value': 'true'},
{'Key': 'macie-severity', 'Value': severity},
{'Key': 'data-types', 'Value': ','.join(data_types[:5])}
]
}
)
return {'statusCode': 200}| 규정 | 대상 데이터 | AWS 서비스 |
|---|---|---|
| GDPR | EU 시민 개인정보 | Macie, Lake Formation, KMS |
| HIPAA | 의료 정보 (PHI) | KMS, CloudTrail, Config |
| PCI DSS | 카드 결제 정보 | KMS, VPC, WAF |
| SOC 2 | 서비스 조직 통제 | CloudTrail, Config, GuardDuty |
| 개인정보보호법 | 한국 개인정보 | Macie, Lake Formation, KMS |
Lake Formation vs IAM
Lake Formation = 데이터 레이크 전용, 컬럼/행 수준 제어
SSE-S3 vs SSE-KMS
SSE-KMS = 감사 로그, 키 로테이션, 세분화된 제어
Glue Data Quality
DQDL로 규칙 정의, ETL 파이프라인 통합
Amazon Macie
ML 기반 PII 검색, S3 버킷 스캔
Cross-Account 공유
Lake Formation + RAM = 안전한 데이터 공유
GDPR 삭제 요청
Iceberg DELETE 또는 S3 객체 삭제
┌─────────────────────────────────────────────────────────────────────────────┐
│ Data Governance Architecture │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ Central Governance Layer ││
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││
│ │ │ Lake │ │ Glue │ │ Amazon │ │ CloudTrail │ ││
│ │ │ Formation │ │ Catalog │ │ Macie │ │ + Config │ ││
│ │ │ (Access) │ │ (Metadata) │ │ (Privacy) │ │ (Audit) │ ││
│ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ ││
│ └─────────────────────────────────────────────────────────────────────────┘│
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ Data Quality Layer ││
│ │ ┌─────────────────────────────────────────────────────────────────┐ ││
│ │ │ Glue Data Quality │ ││
│ │ │ ├── Completeness Rules │ ││
│ │ │ ├── Uniqueness Rules │ ││
│ │ │ ├── Validity Rules │ ││
│ │ │ └── Freshness Rules │ ││
│ │ └─────────────────────────────────────────────────────────────────┘ ││
│ └─────────────────────────────────────────────────────────────────────────┘│
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ Security Layer ││
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││
│ │ │ KMS │ │ VPC │ │ IAM │ │ GuardDuty │ ││
│ │ │ (Encryption)│ │ (Network) │ │ (Identity) │ │ (Threat) │ ││
│ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ ││
│ └─────────────────────────────────────────────────────────────────────────┘│
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ Data Lake ││
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││
│ │ │ Raw │ │ Curated │ │ Analytics │ ││
│ │ │ (Bronze) │ │ (Silver) │ │ (Gold) │ ││
│ │ └─────────────┘ └─────────────┘ └─────────────┘ ││
│ └─────────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────────┘| 거버넌스 영역 | AWS 서비스 | 주요 기능 |
|---|---|---|
| 접근 제어 | Lake Formation | 컬럼/행 수준 보안, Cross-account |
| 메타데이터 | Glue Data Catalog | 스키마, 파티션, 태그 |
| 데이터 품질 | Glue Data Quality | DQDL 규칙, 품질 점수 |
| 프라이버시 | Amazon Macie | PII 검색, 분류 |
| 암호화 | KMS | 키 관리, 로테이션 |
| 감사 | CloudTrail, Config | API 로깅, 규정 준수 |
AWS DataZone은 데이터 카탈로그, 검색, 공유를 위한 데이터 관리 서비스입니다. 조직 전체에서 데이터를 검색하고 안전하게 공유할 수 있습니다.
┌─────────────────────────────────────────────────────────────────────────────┐
│ AWS DataZone Architecture │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ DataZone Domain ││
│ │ ││
│ │ ┌─────────────────────────────────────────────────────────────────┐ ││
│ │ │ Business Data Catalog │ ││
│ │ │ • 데이터 자산 검색 │ ││
│ │ │ • 비즈니스 용어집 (Glossary) │ ││
│ │ │ • 데이터 품질 점수 │ ││
│ │ │ • 소유자 및 관리자 정보 │ ││
│ │ └─────────────────────────────────────────────────────────────────┘ ││
│ │ ││
│ │ ┌─────────────────────────────────────────────────────────────────┐ ││
│ │ │ Projects │ ││
│ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ ││
│ │ │ │ Sales │ │ Marketing │ │ Finance │ │ ││
│ │ │ │ Project │ │ Project │ │ Project │ │ ││
│ │ │ │ │ │ │ │ │ │ ││
│ │ │ │ Members: │ │ Members: │ │ Members: │ │ ││
│ │ │ │ - Analysts │ │ - Analysts │ │ - Analysts │ │ ││
│ │ │ │ - Engineers│ │ - Engineers│ │ - Engineers│ │ ││
│ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ ││
│ │ └─────────────────────────────────────────────────────────────────┘ ││
│ │ ││
│ │ ┌─────────────────────────────────────────────────────────────────┐ ││
│ │ │ Data Sources (Environments) │ ││
│ │ │ ├── Redshift Cluster │ ││
│ │ │ ├── Glue Data Catalog │ ││
│ │ │ ├── S3 Data Lake │ ││
│ │ │ └── RDS Databases │ ││
│ │ └─────────────────────────────────────────────────────────────────┘ ││
│ └─────────────────────────────────────────────────────────────────────────┘│
│ │
│ Workflow: │
│ 1. 데이터 소유자가 자산 게시 │
│ 2. 데이터 소비자가 카탈로그에서 검색 │
│ 3. 구독 요청 → 승인 워크플로우 │
│ 4. 승인 후 자동으로 접근 권한 부여 │
└─────────────────────────────────────────────────────────────────────────────┘┌─────────────────────────────────────────────────────────────────────────────┐
│ Data Asset Publishing │
│ │
│ Step 1: 데이터 소스 연결 │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ Environment: Production Data Lake ││
│ │ ├── Type: AWS Glue ││
│ │ ├── Account: 123456789012 ││
│ │ ├── Region: ap-northeast-2 ││
│ │ └── IAM Role: DataZoneGlueRole ││
│ └─────────────────────────────────────────────────────────────────────────┘│
│ │
│ Step 2: 자산 메타데이터 정의 │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ Asset: Customer Orders ││
│ │ ├── Name: customer_orders ││
│ │ ├── Description: Daily customer order transactions ││
│ │ ├── Owner: data-platform-team ││
│ │ ├── Business Glossary Terms: ││
│ │ │ - Order ││
│ │ │ - Customer ││
│ │ │ - Revenue ││
│ │ ├── Data Classification: Confidential ││
│ │ ├── PII: Yes (customer_email, customer_phone) ││
│ │ └── Refresh Frequency: Daily ││
│ └─────────────────────────────────────────────────────────────────────────┘│
│ │
│ Step 3: 게시 및 승인 │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ Publishing Status: Published ││
│ │ ├── Visibility: Domain-wide ││
│ │ ├── Subscription Required: Yes ││
│ │ ├── Auto-approve: No (Manual approval required) ││
│ │ └── Approvers: data-governance-team ││
│ └─────────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────────┘┌─────────────────────────────────────────────────────────────────────────────┐
│ Subscription Workflow │
│ │
│ Consumer DataZone Producer │
│ │ │ │ │
│ │ 1. Search & Discover │ │ │
│ │ ─────────────────────────▶│ │ │
│ │ │ │ │
│ │ 2. Request Subscription │ │ │
│ │ ─────────────────────────▶│ │ │
│ │ │ │ │
│ │ │ 3. Approval Request │ │
│ │ │ ─────────────────────────▶│ │
│ │ │ │ │
│ │ │ 4. Approve/Reject │ │
│ │ │ ◀─────────────────────────│ │
│ │ │ │ │
│ │ 5. Access Granted │ │ │
│ │ ◀─────────────────────────│ │ │
│ │ │ │ │
│ │ 6. Query Data │ │ │
│ │ ─────────────────────────▶│ ─────────────────────────▶│ │
│ │ │ │ │
│ │
│ 자동 권한 부여: │
│ • Lake Formation 권한 자동 설정 │
│ • Redshift 데이터 공유 자동 생성 │
│ • IAM 정책 자동 업데이트 │
└─────────────────────────────────────────────────────────────────────────────┘Lake Formation vs IAM
Lake Formation = 데이터 레이크 전용, 컬럼/행 수준 제어
SSE-S3 vs SSE-KMS
SSE-KMS = 감사 로그, 키 로테이션, 세분화된 제어
Glue Data Quality
DQDL로 규칙 정의, ETL 파이프라인 통합
Amazon Macie
ML 기반 PII 검색, S3 버킷 스캔
Cross-Account 공유
Lake Formation + RAM = 안전한 데이터 공유
DataZone
데이터 카탈로그, 구독 기반 공유, 셀프 서비스
| 거버넌스 영역 | AWS 서비스 | 주요 기능 |
|---|---|---|
| 접근 제어 | Lake Formation | 컬럼/행 수준 보안, Cross-account |
| 메타데이터 | Glue Data Catalog | 스키마, 파티션, 태그 |
| 데이터 품질 | Glue Data Quality | DQDL 규칙, 품질 점수 |
| 프라이버시 | Amazon Macie | PII 검색, 분류 |
| 암호화 | KMS | 키 관리, 로테이션 |
| 감사 | CloudTrail, Config | API 로깅, 규정 준수 |
| 데이터 카탈로그 | DataZone | 검색, 구독, 공유 |
데이터 플랫폼의 보안은 암호화, 접근 제어, 감사 로깅의 세 축으로 구성됩니다. 각 영역의 심화 내용을 살펴봅니다.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Data Encryption Strategy │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ At Rest (저장 시 암호화) │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ SSE-S3 │ │ SSE-KMS │ │ SSE-C │ │ │
│ │ │ (AWS 관리) │ │ (고객 관리) │ │ (고객 제공) │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ │ │
│ │ S3, EBS, RDS, Redshift, DynamoDB, Glue Data Catalog │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ In Transit (전송 시 암호화) │ │
│ │ │ │
│ │ • TLS 1.2+ 필수 │ │
│ │ • VPC Endpoints (PrivateLink) │ │
│ │ • Certificate Manager (ACM) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ In Use (사용 중 암호화) │ │
│ │ │ │
│ │ • Nitro Enclaves (격리된 컴퓨팅) │ │
│ │ • Clean Rooms (데이터 공유 시) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘// KMS 키 정책 예시
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow Glue Service",
"Effect": "Allow",
"Principal": {
"Service": "glue.amazonaws.com"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:CallerAccount": "111122223333"
}
}
},
{
"Sid": "Allow Data Engineers",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:role/DataEngineerRole"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey"
],
"Resource": "*"
}
]
}// Terraform VPC Endpoint 구성
# S3 Gateway Endpoint
resource "aws_vpc_endpoint" "s3" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.${var.region}.s3"
vpc_endpoint_type = "Gateway"
route_table_ids = [aws_route_table.private.id]
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AllowS3Access"
Effect = "Allow"
Principal = "*"
Action = ["s3:GetObject", "s3:PutObject", "s3:ListBucket"]
Resource = [
"arn:aws:s3:::my-data-lake-bucket",
"arn:aws:s3:::my-data-lake-bucket/*"
]
}
]
})
tags = {
Name = "s3-endpoint"
}
}
# Glue Interface Endpoint
resource "aws_vpc_endpoint" "glue" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.${var.region}.glue"
vpc_endpoint_type = "Interface"
subnet_ids = aws_subnet.private[*].id
security_group_ids = [aws_security_group.vpc_endpoints.id]
private_dns_enabled = true
tags = {
Name = "glue-endpoint"
}
}
# Kinesis Interface Endpoint
resource "aws_vpc_endpoint" "kinesis" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.${var.region}.kinesis-streams"
vpc_endpoint_type = "Interface"
subnet_ids = aws_subnet.private[*].id
security_group_ids = [aws_security_group.vpc_endpoints.id]
private_dns_enabled = true
}
# Security Group for VPC Endpoints
resource "aws_security_group" "vpc_endpoints" {
name = "vpc-endpoints-sg"
description = "Security group for VPC endpoints"
vpc_id = aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = [aws_vpc.main.cidr_block]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}// CloudTrail 데이터 이벤트 로깅
resource "aws_cloudtrail" "data_events" {
name = "data-platform-trail"
s3_bucket_name = aws_s3_bucket.cloudtrail.id
include_global_service_events = true
is_multi_region_trail = true
enable_log_file_validation = true
kms_key_id = aws_kms_key.cloudtrail.arn
# S3 데이터 이벤트 로깅
event_selector {
read_write_type = "All"
include_management_events = true
data_resource {
type = "AWS::S3::Object"
values = ["arn:aws:s3:::my-data-lake-bucket/"]
}
}
# Lambda 데이터 이벤트 로깅
event_selector {
read_write_type = "All"
include_management_events = true
data_resource {
type = "AWS::Lambda::Function"
values = ["arn:aws:lambda"]
}
}
# Glue 테이블 이벤트 로깅
advanced_event_selector {
name = "Glue Data Catalog Events"
field_selector {
field = "eventCategory"
equals = ["Data"]
}
field_selector {
field = "resources.type"
equals = ["AWS::Glue::Table"]
}
}
}
# CloudWatch Logs로 전송
resource "aws_cloudwatch_log_group" "cloudtrail" {
name = "/aws/cloudtrail/data-platform"
retention_in_days = 365
kms_key_id = aws_kms_key.cloudwatch.arn
}
# 의심스러운 활동 알림
resource "aws_cloudwatch_metric_alarm" "unauthorized_api_calls" {
alarm_name = "unauthorized-api-calls"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name = "UnauthorizedAttemptCount"
namespace = "CloudTrailMetrics"
period = 300
statistic = "Sum"
threshold = 5
alarm_description = "Unauthorized API calls detected"
alarm_actions = [aws_sns_topic.security_alerts.arn]
}// Macie 자동 분류 설정
# Macie 활성화
resource "aws_macie2_account" "main" {}
# 분류 작업 생성
resource "aws_macie2_classification_job" "sensitive_data" {
name = "sensitive-data-discovery"
description = "Discover sensitive data in data lake"
job_type = "SCHEDULED"
s3_job_definition {
bucket_definitions {
account_id = data.aws_caller_identity.current.account_id
buckets = ["my-data-lake-bucket"]
}
scoping {
includes {
and {
simple_scope_term {
comparator = "STARTS_WITH"
key = "OBJECT_KEY"
values = ["raw/", "processed/"]
}
}
}
}
}
schedule_frequency {
weekly_schedule = "MONDAY"
}
sampling_percentage = 100
custom_data_identifier_ids = [
aws_macie2_custom_data_identifier.korean_rrn.id
]
}
# 한국 주민등록번호 커스텀 식별자
resource "aws_macie2_custom_data_identifier" "korean_rrn" {
name = "korean-resident-registration-number"
description = "Korean Resident Registration Number"
regex = "\\d{6}-[1-4]\\d{6}"
keywords = ["주민등록번호", "주민번호", "RRN"]
maximum_match_distance = 50
}| 분류 레벨 | 데이터 유형 | 보호 조치 |
|---|---|---|
| Restricted | PII, 금융정보, 의료정보 | 암호화 + 마스킹 + 감사 |
| Confidential | 내부 비즈니스 데이터 | 암호화 + 접근 제어 |
| Internal | 일반 운영 데이터 | 기본 암호화 |
| Public | 공개 가능 데이터 | 무결성 검증 |
데이터 플랫폼은 다양한 규정 준수 요구사항을 충족해야 합니다. 주요 규정과 AWS 서비스 매핑을 살펴봅니다.
| 규정 | 적용 대상 | 핵심 요구사항 | AWS 서비스 |
|---|---|---|---|
| GDPR | EU 개인정보 | 동의, 삭제권, 이동권 | Macie, Lake Formation |
| HIPAA | 의료 정보 | PHI 보호, 감사 | HealthLake, KMS |
| PCI-DSS | 카드 결제 | 암호화, 접근 제어 | KMS, CloudTrail |
| SOX | 재무 데이터 | 감사 추적, 무결성 | CloudTrail, Config |
| CCPA | 캘리포니아 개인정보 | 공개, 삭제, 옵트아웃 | Macie, Glue |
┌─────────────────────────────────────────────────────────────────────────────┐
│ AWS Compliance Framework │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ AWS Artifact │ │
│ │ • SOC 1/2/3 보고서 │ │
│ │ • PCI-DSS 인증 │ │
│ │ • ISO 27001/27017/27018 │ │
│ │ • HIPAA BAA (Business Associate Agreement) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ AWS Config Rules │ │
│ │ • 규정 준수 자동 평가 │ │
│ │ • 사전 정의된 규칙 팩 │ │
│ │ • 커스텀 규칙 생성 │ │
│ │ • 자동 수정 (Remediation) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ AWS Audit Manager │ │
│ │ • 감사 증거 자동 수집 │ │
│ │ • 프레임워크 기반 평가 │ │
│ │ • 보고서 생성 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘데이터 관리가 개인/팀 수준, 표준화 없음, 반응적 대응
기본 정책 수립, 데이터 카탈로그 도입, 역할 정의
표준화된 프로세스, 메타데이터 관리, 품질 측정
KPI 기반 관리, 자동화된 품질 검사, 리니지 추적
지속적 개선, AI 기반 거버넌스, 셀프서비스 데이터