🔒 보안

SOC 2

Service Organization Control 2 (서비스 조직 통제 보고서)

SOC 2는 AICPA(미국공인회계사협회)가 개발한 감사 프레임워크로, 서비스 조직의 보안 통제를 독립적으로 검증합니다. Trust Services Criteria의 5가지 원칙(보안, 가용성, 처리 무결성, 기밀성, 개인정보 보호)을 기반으로 하며, 특히 SaaS/클라우드 기업에서 고객 신뢰를 증명하는 핵심 인증입니다.

📖 상세 설명

SOC 2(Service Organization Control 2)는 AICPA(American Institute of Certified Public Accountants)가 개발한 감사 프레임워크입니다. 원래 SOC 1(재무 보고 관련 통제)에서 파생되었으며, 2010년대 클라우드 서비스의 확산과 함께 IT 서비스 제공업체의 보안을 검증하는 사실상의 표준이 되었습니다. B2B SaaS 기업이 엔터프라이즈 고객을 확보하려면 SOC 2 보고서가 거의 필수입니다.

SOC 2는 Trust Services Criteria(TSC)의 5가지 원칙을 기반으로 합니다. Security(보안)는 필수이며, 시스템이 무단 접근으로부터 보호되는지 평가합니다. Availability(가용성)는 서비스가 약정된 수준으로 운영되는지 확인합니다. Processing Integrity(처리 무결성)는 데이터 처리가 완전하고 정확하며 적시에 이루어지는지 검증합니다. Confidentiality(기밀성)는 민감한 정보가 적절히 보호되는지 평가합니다. Privacy(개인정보 보호)는 개인정보가 수집, 사용, 보관, 폐기되는 방식을 검토합니다.

SOC 2 보고서는 Type I과 Type II로 구분됩니다. Type I은 특정 시점에 통제가 적절히 설계되어 있는지 평가합니다(설계 적합성). Type II는 일정 기간(보통 6-12개월) 동안 통제가 효과적으로 운영되었는지 평가합니다(운영 효과성). Type II가 훨씬 신뢰도가 높으며, 대부분의 엔터프라이즈 고객은 Type II를 요구합니다. 첫 감사는 Type I으로 시작하고, 이후 Type II로 전환하는 것이 일반적입니다.

SOC 2 감사는 공인 CPA 회계법인이 수행합니다. 감사 과정에서 정책/절차 문서, 시스템 구성, 접근 로그, 변경 관리 기록, 인시던트 대응 기록 등의 증거를 검토합니다. 감사 의견은 적정(Unqualified), 한정(Qualified), 부적정(Adverse), 의견 거절로 나뉩니다. 적정 의견을 받으면 고객에게 보고서를 공유할 수 있습니다. 보고서는 보통 NDA 하에 공유되며, 1년마다 갱신해야 합니다.

💻 코드 예제

# SOC 2 컴플라이언스 자동화: 증거 수집 및 모니터링 - Python
import json
import boto3
from datetime import datetime, timedelta
from typing import Dict, List, Any
from dataclasses import dataclass, field
from enum import Enum

class TrustServicesCriteria(Enum):
    """Trust Services Criteria 5가지 원칙"""
    SECURITY = "CC"           # Common Criteria (필수)
    AVAILABILITY = "A"        # 가용성
    PROCESSING_INTEGRITY = "PI"  # 처리 무결성
    CONFIDENTIALITY = "C"     # 기밀성
    PRIVACY = "P"             # 개인정보 보호

@dataclass
class Control:
    """SOC 2 통제 항목"""
    id: str
    name: str
    criteria: TrustServicesCriteria
    description: str
    evidence_types: List[str]
    automated: bool = False

@dataclass
class Evidence:
    """감사 증거"""
    control_id: str
    collected_at: str
    source: str
    data: Any
    period_start: str
    period_end: str

class SOC2EvidenceCollector:
    """SOC 2 감사 증거 자동 수집기"""

    def __init__(self, aws_session=None):
        self.session = aws_session or boto3.Session()
        self.evidences: List[Evidence] = []

    def collect_access_logs(self, start_date: datetime, end_date: datetime) -> Evidence:
        """CC6.1 - 논리적 접근 통제 증거 수집

        CloudTrail 로그에서 접근 기록 추출
        """
        cloudtrail = self.session.client('cloudtrail')

        events = []
        paginator = cloudtrail.get_paginator('lookup_events')

        for page in paginator.paginate(
            StartTime=start_date,
            EndTime=end_date,
            LookupAttributes=[
                {'AttributeKey': 'EventSource', 'AttributeValue': 'signin.amazonaws.com'}
            ]
        ):
            events.extend(page['Events'])

        evidence = Evidence(
            control_id="CC6.1",
            collected_at=datetime.utcnow().isoformat(),
            source="AWS CloudTrail",
            data={
                "total_login_events": len(events),
                "failed_logins": sum(1 for e in events
                    if json.loads(e['CloudTrailEvent']).get('responseElements', {}).get('ConsoleLogin') == 'Failure'),
                "unique_users": len(set(e['Username'] for e in events if 'Username' in e)),
                "sample_events": events[:10]  # 샘플
            },
            period_start=start_date.isoformat(),
            period_end=end_date.isoformat()
        )

        self.evidences.append(evidence)
        return evidence

    def collect_change_management(self, start_date: datetime, end_date: datetime) -> Evidence:
        """CC8.1 - 변경 관리 통제 증거 수집

        GitHub/GitLab에서 PR 및 배포 기록 추출
        """
        # 실제로는 GitHub API 사용
        # 여기서는 샘플 데이터
        evidence = Evidence(
            control_id="CC8.1",
            collected_at=datetime.utcnow().isoformat(),
            source="GitHub",
            data={
                "total_pull_requests": 150,
                "approved_before_merge": 148,
                "approval_rate": "98.7%",
                "average_reviewers": 2.3,
                "deployments": 45,
                "rollbacks": 2,
                "sample_prs": [
                    {"id": "PR-1234", "title": "Add MFA requirement", "reviewers": 2, "approved": True},
                    {"id": "PR-1235", "title": "Update encryption", "reviewers": 3, "approved": True}
                ]
            },
            period_start=start_date.isoformat(),
            period_end=end_date.isoformat()
        )

        self.evidences.append(evidence)
        return evidence

    def collect_encryption_status(self) -> Evidence:
        """CC6.7 - 데이터 암호화 통제 증거 수집

        S3 버킷, RDS, EBS 볼륨의 암호화 상태 확인
        """
        s3 = self.session.client('s3')
        rds = self.session.client('rds')
        ec2 = self.session.client('ec2')

        # S3 암호화 상태
        buckets = s3.list_buckets()['Buckets']
        encrypted_buckets = 0
        for bucket in buckets:
            try:
                encryption = s3.get_bucket_encryption(Bucket=bucket['Name'])
                encrypted_buckets += 1
            except s3.exceptions.ClientError:
                pass

        # RDS 암호화 상태
        instances = rds.describe_db_instances()['DBInstances']
        encrypted_rds = sum(1 for i in instances if i.get('StorageEncrypted', False))

        # EBS 볼륨 암호화 상태
        volumes = ec2.describe_volumes()['Volumes']
        encrypted_ebs = sum(1 for v in volumes if v.get('Encrypted', False))

        evidence = Evidence(
            control_id="CC6.7",
            collected_at=datetime.utcnow().isoformat(),
            source="AWS (S3, RDS, EBS)",
            data={
                "s3_buckets": {
                    "total": len(buckets),
                    "encrypted": encrypted_buckets,
                    "compliance": f"{encrypted_buckets/len(buckets)*100:.1f}%" if buckets else "N/A"
                },
                "rds_instances": {
                    "total": len(instances),
                    "encrypted": encrypted_rds,
                    "compliance": f"{encrypted_rds/len(instances)*100:.1f}%" if instances else "N/A"
                },
                "ebs_volumes": {
                    "total": len(volumes),
                    "encrypted": encrypted_ebs,
                    "compliance": f"{encrypted_ebs/len(volumes)*100:.1f}%" if volumes else "N/A"
                }
            },
            period_start=datetime.utcnow().isoformat(),
            period_end=datetime.utcnow().isoformat()
        )

        self.evidences.append(evidence)
        return evidence

    def collect_incident_response(self, start_date: datetime, end_date: datetime) -> Evidence:
        """CC7.4 - 인시던트 대응 통제 증거 수집

        PagerDuty/Opsgenie에서 인시던트 기록 추출
        """
        # 실제로는 PagerDuty API 사용
        evidence = Evidence(
            control_id="CC7.4",
            collected_at=datetime.utcnow().isoformat(),
            source="PagerDuty",
            data={
                "total_incidents": 25,
                "security_incidents": 3,
                "mean_time_to_acknowledge": "5 minutes",
                "mean_time_to_resolve": "2.5 hours",
                "postmortems_completed": 3,
                "sample_incidents": [
                    {
                        "id": "INC-001",
                        "severity": "P2",
                        "type": "Security",
                        "acknowledged_in": "3 min",
                        "resolved_in": "45 min",
                        "postmortem": True
                    }
                ]
            },
            period_start=start_date.isoformat(),
            period_end=end_date.isoformat()
        )

        self.evidences.append(evidence)
        return evidence

    def generate_evidence_package(self) -> Dict:
        """감사용 증거 패키지 생성"""
        return {
            "generated_at": datetime.utcnow().isoformat(),
            "report_type": "SOC 2 Type II",
            "period": {
                "start": min(e.period_start for e in self.evidences),
                "end": max(e.period_end for e in self.evidences)
            },
            "controls_covered": list(set(e.control_id for e in self.evidences)),
            "evidence_count": len(self.evidences),
            "evidences": [
                {
                    "control_id": e.control_id,
                    "source": e.source,
                    "collected_at": e.collected_at,
                    "data": e.data
                }
                for e in self.evidences
            ]
        }


# 사용 예시
if __name__ == "__main__":
    collector = SOC2EvidenceCollector()

    # 감사 기간 설정 (지난 12개월)
    end_date = datetime.utcnow()
    start_date = end_date - timedelta(days=365)

    # 증거 수집
    collector.collect_access_logs(start_date, end_date)
    collector.collect_change_management(start_date, end_date)
    collector.collect_encryption_status()
    collector.collect_incident_response(start_date, end_date)

    # 증거 패키지 생성
    package = collector.generate_evidence_package()
    print(json.dumps(package, indent=2, default=str))
# SOC 2 Trust Services Criteria 통제 매핑 - YAML
# Common Criteria (Security) 중심으로 구성

soc2_controls:
  report_type: "SOC 2 Type II"
  audit_period:
    start: "2024-01-01"
    end: "2024-12-31"
  auditor: "Big 4 CPA Firm"

  trust_services_criteria:
    # CC (Common Criteria) - Security 필수
    security:
      category: "CC"
      required: true
      controls:
        # CC1 - Control Environment
        - id: "CC1.1"
          name: "COSO 원칙 1: 무결성과 윤리적 가치"
          description: "조직은 무결성과 윤리적 가치에 대한 commitment를 보여줌"
          implementation:
            - "Code of Conduct 정책 수립"
            - "연간 직원 윤리 교육"
            - "내부고발자 프로그램"
          evidence:
            - "Code of Conduct 문서"
            - "교육 이수 기록"
            - "윤리 위반 보고 및 처리 기록"
          status: "implemented"
          owner: "HR"

        # CC2 - Communication and Information
        - id: "CC2.1"
          name: "내부 커뮤니케이션"
          description: "정보보안 책임과 역할에 대한 내부 커뮤니케이션"
          implementation:
            - "보안 정책 포털"
            - "월간 보안 뉴스레터"
            - "Slack 보안 채널"
          evidence:
            - "정책 배포 로그"
            - "뉴스레터 아카이브"
          status: "implemented"
          owner: "Security Team"

        # CC5 - Control Activities
        - id: "CC5.2"
          name: "논리적 접근 통제"
          description: "시스템에 대한 논리적 접근 통제"
          implementation:
            - "SSO + MFA 필수"
            - "RBAC 기반 권한 관리"
            - "분기별 접근 권한 검토"
          evidence:
            - "Okta 접근 로그"
            - "권한 검토 기록"
            - "MFA 적용률 리포트"
          status: "implemented"
          owner: "IT Security"

        # CC6 - Logical and Physical Access Controls
        - id: "CC6.1"
          name: "인증 메커니즘"
          description: "사용자 인증 및 접근 통제"
          implementation:
            - "Okta SSO"
            - "Google Authenticator MFA"
            - "비밀번호 정책 (12자+, 90일 교체)"
          evidence:
            - "SSO 설정 스크린샷"
            - "MFA 적용률 리포트"
            - "비밀번호 정책 문서"
          status: "implemented"
          owner: "IT"

        - id: "CC6.7"
          name: "데이터 암호화"
          description: "저장 및 전송 중인 데이터 암호화"
          implementation:
            - "AWS KMS로 저장 데이터 암호화"
            - "TLS 1.3 필수"
            - "데이터베이스 암호화"
          evidence:
            - "KMS 키 정책"
            - "SSL Labs 스캔 결과"
            - "RDS 암호화 설정 스크린샷"
          status: "implemented"
          owner: "Platform Team"

        # CC7 - System Operations
        - id: "CC7.2"
          name: "시스템 모니터링"
          description: "시스템 성능 및 보안 이벤트 모니터링"
          implementation:
            - "Datadog APM/인프라 모니터링"
            - "AWS CloudWatch 알람"
            - "SIEM (Splunk)"
          evidence:
            - "모니터링 대시보드 스크린샷"
            - "알림 설정 문서"
            - "월간 모니터링 리포트"
          status: "implemented"
          owner: "SRE"

        - id: "CC7.4"
          name: "인시던트 대응"
          description: "보안 인시던트 탐지 및 대응"
          implementation:
            - "인시던트 대응 계획"
            - "PagerDuty 온콜 로테이션"
            - "사후 분석(Postmortem) 프로세스"
          evidence:
            - "IRP 문서"
            - "인시던트 로그"
            - "Postmortem 기록"
          status: "implemented"
          owner: "Security Team"

        # CC8 - Change Management
        - id: "CC8.1"
          name: "변경 관리"
          description: "시스템 변경에 대한 통제"
          implementation:
            - "GitHub PR 필수"
            - "코드 리뷰 (2명 이상)"
            - "CI/CD 자동화 테스트"
          evidence:
            - "GitHub 브랜치 보호 설정"
            - "PR 승인 기록"
            - "배포 로그"
          status: "implemented"
          owner: "Engineering"

        # CC9 - Risk Mitigation
        - id: "CC9.2"
          name: "공급업체 관리"
          description: "서브서비스 조직에 대한 리스크 관리"
          implementation:
            - "공급업체 보안 평가"
            - "연간 공급업체 검토"
            - "계약서 보안 조항"
          evidence:
            - "공급업체 평가 체크리스트"
            - "AWS, GCP SOC 2 보고서"
            - "계약서 보안 조항"
          status: "implemented"
          owner: "Legal/Security"

    # A - Availability
    availability:
      category: "A"
      required: false
      controls:
        - id: "A1.1"
          name: "시스템 가용성"
          description: "서비스 가용성 목표 및 모니터링"
          implementation:
            - "99.9% SLA 약정"
            - "멀티 AZ 배포"
            - "자동 스케일링"
          evidence:
            - "SLA 문서"
            - "가용성 대시보드"
            - "인프라 아키텍처 다이어그램"
          status: "implemented"
          owner: "SRE"

        - id: "A1.2"
          name: "재해 복구"
          description: "비즈니스 연속성 및 재해 복구 계획"
          implementation:
            - "DR 계획 수립"
            - "연 2회 DR 테스트"
            - "데이터 백업 (일일)"
          evidence:
            - "DR 계획 문서"
            - "DR 테스트 결과"
            - "백업 로그"
          status: "implemented"
          owner: "Infrastructure"

    # C - Confidentiality
    confidentiality:
      category: "C"
      required: false
      controls:
        - id: "C1.1"
          name: "기밀 정보 식별"
          description: "기밀 정보의 식별 및 분류"
          implementation:
            - "데이터 분류 정책"
            - "민감 데이터 태깅"
          evidence:
            - "데이터 분류 정책"
            - "데이터 인벤토리"
          status: "implemented"
          owner: "Data Team"

  # 예외 및 관찰 사항
  exceptions:
    - control_id: "CC5.2"
      description: "일부 레거시 시스템 MFA 미적용"
      compensating_control: "IP 화이트리스트 및 추가 모니터링"
      remediation_date: "2025-Q1"

  # 감사 준비 상태
  readiness:
    controls_implemented: 23
    controls_total: 25
    evidence_collected: true
    management_assertion_ready: true
# SOC 2 컴플라이언스를 위한 AWS 인프라 - Terraform
# Trust Services Criteria 통제 구현

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# ============================================
# CC6.1 - 논리적 접근 통제
# ============================================

# IAM 비밀번호 정책 (SOC 2 요구사항)
resource "aws_iam_account_password_policy" "soc2_password_policy" {
  minimum_password_length        = 14
  require_lowercase_characters   = true
  require_uppercase_characters   = true
  require_numbers               = true
  require_symbols               = true
  allow_users_to_change_password = true
  max_password_age              = 90   # 90일 만료
  password_reuse_prevention     = 24   # 24개 이전 비밀번호 재사용 금지
  hard_expiry                   = false
}

# MFA 미사용 사용자 탐지 Config Rule
resource "aws_config_config_rule" "mfa_enabled" {
  name = "soc2-mfa-enabled-for-iam-users"

  source {
    owner             = "AWS"
    source_identifier = "MFA_ENABLED_FOR_IAM_CONSOLE_ACCESS"
  }

  tags = {
    SOC2Control = "CC6.1"
    Compliance  = "SOC2"
  }
}

# ============================================
# CC6.7 - 데이터 암호화
# ============================================

# 암호화 키 (SOC 2 C1.1 기밀성)
resource "aws_kms_key" "soc2_data_key" {
  description             = "SOC 2 compliant data encryption key"
  deletion_window_in_days = 30
  enable_key_rotation     = true

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid       = "Enable IAM User Permissions"
        Effect    = "Allow"
        Principal = { AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" }
        Action    = "kms:*"
        Resource  = "*"
      },
      {
        Sid       = "Allow CloudWatch Logs"
        Effect    = "Allow"
        Principal = { Service = "logs.${data.aws_region.current.name}.amazonaws.com" }
        Action    = ["kms:Encrypt*", "kms:Decrypt*", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:Describe*"]
        Resource  = "*"
      }
    ]
  })

  tags = {
    SOC2Control = "CC6.7"
    Compliance  = "SOC2"
  }
}

# S3 버킷 기본 암호화 설정
resource "aws_s3_bucket" "soc2_data_bucket" {
  bucket = "soc2-compliant-data-${random_id.bucket_suffix.hex}"

  tags = {
    SOC2Control = "CC6.7"
    Compliance  = "SOC2"
    DataClass   = "Confidential"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "soc2_encryption" {
  bucket = aws_s3_bucket.soc2_data_bucket.id

  rule {
    apply_server_side_encryption_by_default {
      kms_master_key_id = aws_kms_key.soc2_data_key.arn
      sse_algorithm     = "aws:kms"
    }
    bucket_key_enabled = true
  }
}

# S3 버킷 퍼블릭 액세스 차단
resource "aws_s3_bucket_public_access_block" "soc2_public_access" {
  bucket = aws_s3_bucket.soc2_data_bucket.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# ============================================
# CC7.2 - 시스템 모니터링
# ============================================

# CloudTrail (CC7.2, CC7.4)
resource "aws_cloudtrail" "soc2_audit_trail" {
  name                          = "soc2-audit-trail"
  s3_bucket_name               = aws_s3_bucket.audit_logs.id
  include_global_service_events = true
  is_multi_region_trail        = true
  enable_log_file_validation   = true
  kms_key_id                   = aws_kms_key.soc2_data_key.arn

  # 모든 이벤트 로깅
  event_selector {
    read_write_type           = "All"
    include_management_events = true

    data_resource {
      type   = "AWS::S3::Object"
      values = ["arn:aws:s3"]
    }
  }

  tags = {
    SOC2Control = "CC7.2"
    Compliance  = "SOC2"
  }
}

# CloudWatch 로그 그룹 (1년 보관)
resource "aws_cloudwatch_log_group" "soc2_audit_logs" {
  name              = "/soc2/audit-logs"
  retention_in_days = 365  # SOC 2 요구사항
  kms_key_id        = aws_kms_key.soc2_data_key.arn

  tags = {
    SOC2Control = "CC7.2"
    Compliance  = "SOC2"
  }
}

# ============================================
# CC7.4 - 보안 이벤트 탐지
# ============================================

# GuardDuty 활성화
resource "aws_guardduty_detector" "soc2_guardduty" {
  enable = true

  datasources {
    s3_logs {
      enable = true
    }
    kubernetes {
      audit_logs {
        enable = true
      }
    }
  }

  tags = {
    SOC2Control = "CC7.4"
    Compliance  = "SOC2"
  }
}

# 보안 이벤트 알림
resource "aws_cloudwatch_metric_alarm" "security_event_alarm" {
  alarm_name          = "soc2-security-event-detected"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 1
  metric_name         = "SecurityEventCount"
  namespace           = "SOC2/Security"
  period              = 300
  statistic           = "Sum"
  threshold           = 0
  alarm_description   = "Security event detected - SOC 2 CC7.4"

  alarm_actions = [aws_sns_topic.security_alerts.arn]

  tags = {
    SOC2Control = "CC7.4"
    Compliance  = "SOC2"
  }
}

# ============================================
# A1.1 - 가용성 (선택적)
# ============================================

# 멀티 AZ RDS 인스턴스
resource "aws_db_instance" "soc2_database" {
  identifier     = "soc2-compliant-db"
  engine         = "postgres"
  engine_version = "15.4"
  instance_class = "db.r6g.large"

  allocated_storage     = 100
  max_allocated_storage = 1000
  storage_type          = "gp3"
  storage_encrypted     = true
  kms_key_id           = aws_kms_key.soc2_data_key.arn

  # 고가용성
  multi_az               = true
  db_subnet_group_name   = aws_db_subnet_group.soc2_subnet.name
  vpc_security_group_ids = [aws_security_group.soc2_db_sg.id]

  # 백업 (A1.2)
  backup_retention_period = 35
  backup_window          = "03:00-04:00"
  maintenance_window     = "Mon:04:00-Mon:05:00"

  # 삭제 보호
  deletion_protection = true
  skip_final_snapshot = false

  # 성능 인사이트 (모니터링)
  performance_insights_enabled    = true
  performance_insights_kms_key_id = aws_kms_key.soc2_data_key.arn

  tags = {
    SOC2Control = "A1.1,A1.2,CC6.7"
    Compliance  = "SOC2"
  }
}

# ============================================
# CC9.2 - AWS Config (규정 준수 모니터링)
# ============================================

resource "aws_config_configuration_recorder" "soc2_recorder" {
  name     = "soc2-config-recorder"
  role_arn = aws_iam_role.config_role.arn

  recording_group {
    all_supported = true
  }
}

# 암호화되지 않은 S3 버킷 탐지
resource "aws_config_config_rule" "s3_bucket_encrypted" {
  name = "soc2-s3-bucket-server-side-encryption-enabled"

  source {
    owner             = "AWS"
    source_identifier = "S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED"
  }

  tags = {
    SOC2Control = "CC6.7"
    Compliance  = "SOC2"
  }
}

# 암호화되지 않은 EBS 볼륨 탐지
resource "aws_config_config_rule" "ebs_encrypted" {
  name = "soc2-encrypted-volumes"

  source {
    owner             = "AWS"
    source_identifier = "ENCRYPTED_VOLUMES"
  }

  tags = {
    SOC2Control = "CC6.7"
    Compliance  = "SOC2"
  }
}

# ============================================
# 출력
# ============================================
output "soc2_compliance_resources" {
  value = {
    kms_key_arn     = aws_kms_key.soc2_data_key.arn
    cloudtrail_arn  = aws_cloudtrail.soc2_audit_trail.arn
    guardduty_id    = aws_guardduty_detector.soc2_guardduty.id
    config_recorder = aws_config_configuration_recorder.soc2_recorder.id
  }
  description = "SOC 2 compliant infrastructure resources"
}

🗣️ 실무에서 이렇게 말하세요

💬 엔터프라이즈 영업 미팅에서
"저희는 SOC 2 Type II 보고서를 보유하고 있습니다. 지난 12개월간 Security, Availability, Confidentiality 세 가지 Trust Services Criteria에 대해 감사를 받았고, 적정 의견을 받았습니다. NDA 체결 후 전체 보고서를 공유드릴 수 있습니다. 또한 AWS와 GCP의 SOC 2 보고서도 서브서비스 증빙으로 확보하고 있습니다."
💬 SOC 2 감사 준비 회의에서
"올해 Type II 감사 기간은 1월부터 12월까지입니다. 주요 통제별로 증거를 수집해야 합니다. CC6.1 접근 통제는 Okta 로그와 분기별 권한 검토 기록, CC7.2 모니터링은 Datadog 대시보드와 알림 설정, CC8.1 변경 관리는 GitHub PR 기록이 필요합니다. 증거 수집을 자동화해서 감사 직전에 허둥대지 않도록 합시다."
💬 감사인과의 킥오프 미팅에서
"감사 범위는 Security(CC 전체), Availability(A1), Confidentiality(C1)입니다. 서브서비스 조직으로 AWS, GCP, Okta가 있으며, 포괄적 접근법(Inclusive Method)을 적용합니다. 시스템 경계는 프로덕션 환경으로 한정하고, 개발/스테이징 환경은 제외합니다. 증거 요청 목록과 일정을 공유해주시면 담당자를 배정하겠습니다."

⚠️ 주의사항 & 베스트 프랙티스

Type I만 보유 (Type II 없음)

Type I은 특정 시점의 설계 적합성만 검증합니다. 대부분의 엔터프라이즈 고객은 운영 효과성을 검증하는 Type II를 요구합니다. Type I만으로는 영업에서 거절당할 수 있습니다. 첫해 Type I 취득 후 바로 Type II 준비를 시작하세요.

감사 직전에 증거 수집

SOC 2 Type II는 감사 기간 전체(6-12개월)의 증거가 필요합니다. 감사 직전에 수집하면 기간 중 공백이 발생해 예외사항으로 기록됩니다. 자동화된 증거 수집 시스템을 구축하고. Vanta, Drata, Secureframe 같은 컴플라이언스 자동화 도구를 활용하세요.

서브서비스 조직 관리 소홀

AWS, GCP 등 서브서비스 조직의 SOC 2 보고서를 확보하지 않으면 감사 범위가 누락됩니다. Carve-out(제외)과 Inclusive(포함) 방법 중 적절한 방식을 선택하고, 서브서비스 조직의 보고서를 매년 갱신하세요.

SOC 2 베스트 프랙티스

조기 준비(최소 6개월 전), 자동화된 증거 수집(Vanta, Drata 등), 명확한 시스템 경계 정의, 정책과 실제 운영의 일치, 예외사항 최소화, 내부 Readiness Assessment 수행, 서브서비스 보고서 확보를 실행하세요. ISO 27001과 통제를 매핑하면 중복 작업을 줄일 수 있습니다.

🔗 관련 용어

📚 더 배우기