SOC 2 Technical Controls


SOC 2 Overview

SOC 2 audits trust service criteria: Security, Availability, Processing Integrity, Confidentiality, and Privacy. Technical controls are essential for meeting these criteria.

Logging and Monitoring

Comprehensive logging is the foundation of SOC 2:




import structlog


from datetime import datetime




class SOC2Logger:


def __init__(self):


self.logger = structlog.get_logger()


self.required_fields = [


"timestamp", "user_id", "action", "resource",


"source_ip", "outcome", "correlation_id"


]




def log_access(self, user_id, action, resource, outcome, metadata=None):


log_entry = {


"timestamp": datetime.utcnow().isoformat(),


"user_id": user_id,


"action": action,


"resource": resource,


"source_ip": metadata.get("ip", "unknown"),


"outcome": outcome,


"correlation_id": metadata.get("correlation_id", str(uuid.uuid4())),


"user_agent": metadata.get("user_agent"),


"geo_location": metadata.get("geo"),


"auth_method": metadata.get("auth_method")


}




self.logger.info("access_log", **log_entry)


self.store_immutable(log_entry)


return log_entry




def store_immutable(self, log_entry):


"""Store logs in immutable storage for audit"""


# Write to append-only log


with open("/var/log/soc2/access.log", "a") as f:


f.write(json.dumps(log_entry) + "\n")




# Also send to SIEM


self.send_to_siem(log_entry)





Access Review Automation

Automate periodic access reviews:




class AccessReviewAutomation:


def __init__(self, identity_provider):


self.idp = identity_provider


self.reviewers = {


"engineering": "eng-manager@example.com",


"sales": "sales-director@example.com",


"finance": "cfo@example.com"


}




def generate_review(self, department):


users = self.idp.get_users_by_department(department)




review = {


"department": department,


"review_date": datetime.utcnow().isoformat(),


"reviewer": self.reviewers[department],


"users": []


}




for user in users:


review["users"].append({


"name": user["name"],


"email": user["email"],


"roles": user["roles"],


"last_login": user["last_login"],


"access_keys_count": user.get("access_keys", 0),


"days_since_last_access": (


datetime.utcnow() - user["last_login"]


).days if user["last_login"] else None


})




return review




def auto_disable_inactive(self, days_threshold=90):


cutoff = datetime.utcnow() - timedelta(days=days_threshold)


disabled = []




for user in self.idp.get_all_users():


if user.get("last_login", datetime.min) < cutoff:


self.idp.disable_user(user["email"])


disabled.append(user["email"])




return disabled





Change Management

Track and approve all infrastructure changes:




# change-management-pipeline.yaml


change_management:


required_for:


- infrastructure_changes


- code_deployments


- configuration_changes


- access_policy_changes




workflow:


- request:


fields:


- change_description


- risk_assessment


- rollback_plan


- testing_completed




- review:


required_approvals:


- technical_reviewer


- security_reviewer


auto_approve:


- risk: low


- owner: same_team




- implementation:


window: business_hours


blackout_periods:


- end_of_month


- holiday_season


require_change_window: high_risk




- verification:


- monitoring_metrics_normal


- smoke_tests_passed


- no_security_events








# Change management API


class ChangeManager:


def __init__(self):


self.changes = []




def create_change(self, request):


change = {


"id": str(uuid.uuid4()),


"description": request["description"],


"risk": request.get("risk", "medium"),


"requester": request["requester"],


"status": "pending_review",


"created_at": datetime.utcnow().isoformat(),


"approvals": [],


"rollback_plan": request["rollback_plan"]


}




self.changes.append(change)


self.notify_reviewers(change)




return change




def approve_change(self, change_id, reviewer, decision, comments):


change = self.find_change(change_id)




change["approvals"].append({


"reviewer": reviewer,


"decision": decision,


"comments": comments,


"timestamp": datetime.utcnow().isoformat()


})




if decision == "approved":


change["status"] = "approved"


self.schedule_implementation(change)


else:


change["status"] = "rejected"




def post_implementation_review(self, change_id):


change = self.find_change(change_id)


change["status"] = "completed"


change["completed_at"] = datetime.utcnow().isoformat()





Conclusion

SOC 2 technical controls require systematic implementation across logging, access review, and change management. Implement immutable audit logging, automate access recertification, and enforce change management workflows. Continuous monitoring provides evidence for auditors and early detection of control failures. Automate evidence collection to reduce audit burden.