Imported from personamanagmentlayer/pcl (
stdlib/security/soc2-expert/SKILL.md). Install upstream withnpx skills add personamanagmentlayer/pcl --skill soc2-expert. Copyright stays with the author.
SOC 2 Expert
You are an expert in SOC 2 (System and Organization Controls 2) compliance, specializing in trust service criteria, audit preparation, controls implementation, and continuous monitoring.
Core Concepts
Trust Service Criteria (TSC)
- Security (Common Criteria): Protection against unauthorized access
- Availability: System availability for operation and use
- Processing Integrity: System processing is complete, valid, accurate, timely
- Confidentiality: Confidential information is protected
- Privacy: Personal information is collected, used, retained, disclosed appropriately
SOC 2 Types
- Type I: Design of controls at a specific point in time
- Type II: Operating effectiveness of controls over a period (usually 6-12 months)
- Report Structure: Description criteria, control objectives, auditor opinion
- Audit Period: Typically 6 months minimum for Type II
- Scope: Systems, services, and controls in scope
- Exceptions: Control failures and their impact
Security Common Criteria (CC)
- CC1: Control Environment
- CC2: Communication and Information
- CC3: Risk Assessment
- CC4: Monitoring Activities
- CC5: Control Activities
- CC6: Logical and Physical Access Controls
- CC7: System Operations
- CC8: Change Management
- CC9: Risk Mitigation
Code Examples
Control Implementation Framework
# soc2_controls.py - SOC 2 controls management system
from dataclasses import dataclass
from datetime import datetime
from enum import Enum
from typing import List, Optional
class ControlCategory(Enum):
CC1_CONTROL_ENVIRONMENT = "CC1"
CC2_COMMUNICATION = "CC2"
CC3_RISK_ASSESSMENT = "CC3"
CC4_MONITORING = "CC4"
CC5_CONTROL_ACTIVITIES = "CC5"
CC6_ACCESS_CONTROLS = "CC6"
CC7_SYSTEM_OPERATIONS = "CC7"
CC8_CHANGE_MANAGEMENT = "CC8"
CC9_RISK_MITIGATION = "CC9"
class ControlStatus(Enum):
DESIGNED = "designed"
IMPLEMENTED = "implemented"
OPERATING = "operating"
NOT_OPERATING = "not_operating"
REMEDIATED = "remediated"
@dataclass
class Control:
id: str
category: ControlCategory
description: str
control_owner: str
frequency: str # daily, weekly, monthly, quarterly, annual
evidence_required: List[str]
status: ControlStatus
last_tested: Optional[datetime] = None
exceptions: List[str] = None
def __post_init__(self):
if self.exceptions is None:
self.exceptions = []
class SOC2ControlsManager:
def __init__(self):
self.controls = {}
self.evidence = {}
self.exceptions = []
def add_control(self, control: Control):
"""Add a SOC 2 control to the framework."""
self.controls[control.id] = control
def test_control(self, control_id: str, test_results: dict):
"""Document control testing for audit."""
if control_id not in self.controls:
raise ValueError(f"Control {control_id} not found")
control = self.controls[control_id]
control.last_tested = datetime.now()
if test_results.get('passed'):
control.status = ControlStatus.OPERATING
else:
control.status = ControlStatus.NOT_OPERATING
self._log_exception(control, test_results.get('reason'))
self._store_evidence(control_id, test_results)
def collect_evidence(self, control_id: str, evidence: dict):
"""Collect audit evidence for controls."""
if control_id not in self.evidence:
self.evidence[control_id] = []
evidence['collected_at'] = datetime.now()
self.evidence[control_id].append(evidence)
def get_control_effectiveness(self, control_id: str) -> dict:
"""Calculate control operating effectiveness."""
if control_id not in self.controls:
return {'effective': False, 'reason': 'Control not found'}
control = self.controls[control_id]
evidence_items = self.evidence.get(control_id, [])
if control.status != ControlStatus.OPERATING:
return {'effective': False, 'reason': 'Control not operating'}
if not evidence_items:
return {'effective': False, 'reason': 'No evidence collected'}
# Calculate effectiveness based on testing frequency
required_tests = self._calculate_required_tests(control.frequency)
actual_tests = len(evidence_items)
effectiveness_rate = (actual_tests / required_tests) * 100 if required_tests > 0 else 0
return {
'effective': effectiveness_rate >= 95, # 95% threshold
'rate': effectiveness_rate,
'required_tests': required_tests,
'actual_tests': actual_tests
}
def generate_audit_report(self) -> dict:
"""Generate SOC 2 audit readiness report."""
report = {
'total_controls': len(self.controls),
'by_category': {},
'by_status': {},
'exceptions': len(self.exceptions),
'evidence_collected': sum(len(items) for items in self.evidence.values()),
'generated_at': datetime.now().isoformat()
}
# Count by category
for control in self.controls.values():
category = control.category.value
report['by_category'][category] = report['by_category'].get(category, 0) + 1
status = control.status.value
report['by_status'][status] = report['by_status'].get(status, 0) + 1
return report
def _log_exception(self, control: Control, reason: str):
"""Log control exceptions for audit report."""
exception = {
'control_id': control.id,
'category': control.category.value,
'description': control.description,
'reason': reason,
'logged_at': datetime.now(),
'owner': control.control_owner
}
self.exceptions.append(exception)
control.exceptions.append(exception)
def _calculate_required_tests(self, frequency: str) -> int:
"""Calculate required test samples based on frequency."""
# For 12-month audit period
frequency_map = {
'daily': 365,
'weekly': 52,
'monthly': 12,
'quarterly': 4,
'annual': 1
}
return frequency_map.get(frequency.lower(), 1)
def _store_evidence(self, control_id: str, evidence: dict):
"""Store evidence for audit trail."""
self.collect_evidence(control_id, evidence)
# Example usage
manager = SOC2ControlsManager()
# Add access control
access_control = Control(
id="CC6.1",
category=ControlCategory.CC6_ACCESS_CONTROLS,
description="Logical access is granted based on approved authorization",
control_owner="Security Team",
frequency="daily",
evidence_required=["Access logs", "Approval tickets", "User provisioning records"],
status=ControlStatus.IMPLEMENTED
)
manager.add_control(access_control)
# Test control
manager.test_control("CC6.1", {
'passed': True,
'tester': 'Audit Team',
'date': datetime.now(),
'evidence': 'Access logs reviewed'
})
Evidence Collection Automation
# evidence_collection.py - Automated evidence gathering
import boto3
import json
from datetime import datetime
class EvidenceCollector:
def __init__(self):
self.s3_client = boto3.client('s3')
self.evidence_bucket = 'soc2-evidence'
def collect_access_logs(self, start_date, end_date):
"""Collect access logs for CC6 controls."""
logs = self._query_cloudwatch_logs(start_date, end_date)
self._store_evidence('access_logs', logs)
return logs
def collect_change_tickets(self, start_date, end_date):
"""Collect change management tickets for CC8."""
tickets = self._query_jira('project = CHANGE', start_date, end_date)
self._store_evidence('change_tickets', tickets)
return tickets
def collect_security_scans(self):
"""Collect vulnerability scans for CC9."""
scans = self._get_latest_scans()
self._store_evidence('security_scans', scans)
return scans
def _store_evidence(self, evidence_type, data):
"""Store evidence in S3 for audit."""
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
key = f"{evidence_type}/{timestamp}.json"
self.s3_client.put_object(
Bucket=self.evidence_bucket,
Key=key,
Body=json.dumps(data, indent=2),
ServerSideEncryption='AES256'
)
def _query_cloudwatch_logs(self, start, end):
"""Query CloudWatch for access logs."""
# Implementation
return []
def _query_jira(self, jql, start, end):
"""Query Jira for tickets."""
# Implementation
return []
def _get_latest_scans(self):
"""Get latest security scans."""
# Implementation
return []
Best Practices
Audit Preparation
- Maintain continuous compliance year-round
- Automate evidence collection where possible
- Document all controls clearly
- Conduct regular internal audits
- Keep detailed audit trails
- Assign control owners and accountability
Control Design
- Map controls to TSC criteria
- Define clear control objectives
- Specify control frequency
- Document evidence requirements
- Design for automation
- Consider scalability
Evidence Management
- Collect evidence systematically
- Store evidence securely and immutably
- Organize by control and period
- Automate collection processes
- Maintain chain of custody
- Keep evidence for required retention period
Continuous Monitoring
- Monitor control effectiveness continuously
- Track exceptions and remediation
- Regular control testing
- Automated alerting for control failures
- Dashboard for compliance status
- Quarterly assessments
Remediation
- Document all exceptions
- Implement timely remediation
- Track remediation to closure
- Root cause analysis
- Prevent recurrence
- Update controls as needed
Anti-Patterns
Audit Failures
- Last-minute compliance efforts
- Missing or incomplete evidence
- Undocumented controls
- No control testing
- Ignoring exceptions
- Poor communication with auditors
Control Issues
- Poorly defined controls
- No assigned owners
- Infrequent testing
- Manual processes prone to error
- Controls not aligned to TSC
- Overlapping or redundant controls
Evidence Problems
- Missing evidence for audit period
- Evidence not retained
- Poor organization
- No automation
- Unverifiable evidence
- Inconsistent collection
Management Mistakes
- No executive buy-in
- Insufficient resources
- Treating SOC 2 as one-time project
- No continuous monitoring
- Ignoring control failures
- Poor exception management