Sub-processor Management
ISO 27018 requires strict controls over sub-processors who handle customer PII. This lesson covers selection, due diligence, contracting, and ongoing monitoring of third-party processors.
Sub-processor Definition
What is a Sub-processor? Any third party engaged by the cloud service provider to process customer PII on behalf of the CSP.
Examples:
- Infrastructure providers (AWS, Azure, GCP)
- Payment processors (Stripe, PayPal)
- Email service providers (SendGrid, Mailgun)
- Analytics providers (with PII access)
- Support ticket systems
- Data centers
- Backup services
ISO 27018 Requirements
Core Requirements
- Customer Notification: Inform customers of all sub-processors
- Prior Authorization: Get customer approval before engaging new sub-processors
- Equivalent Protection: Ensure sub-processors provide same level of protection
- Written Agreements: Contracts with data protection obligations
- Right to Audit: Enable customer audits of sub-processors
- Liability: Remain liable for sub-processor actions
Sub-processor Selection Process
Due Diligence Framework
interface SubProcessorAssessment {
vendorName: string;
service: string;
piiCategories: string[];
riskLevel: 'low' | 'medium' | 'high' | 'critical';
dueDiligence: DueDiligenceChecks;
certifications: Certification[];
securityAssessment: SecurityAssessment;
approved: boolean;
approvedBy: string;
approvalDate: Date;
}
interface DueDiligenceChecks {
backgroundCheck: boolean;
financialStability: boolean;
reputationReview: boolean;
referenceChecks: boolean;
contractReview: boolean;
securityQuestionnaire: boolean;
onSiteVisit: boolean;
thirdPartyAudit: boolean;
}
class SubProcessorSelection {
async evaluateVendor(vendorName: string): Promise<SubProcessorAssessment> {
const assessment: SubProcessorAssessment = {
vendorName,
service: await this.getServiceDescription(vendorName),
piiCategories: await this.identifyPIIAccess(vendorName),
riskLevel: 'medium',
dueDiligence: await this.performDueDiligence(vendorName),
certifications: await this.verifyCertifications(vendorName),
securityAssessment: await this.conductSecurityAssessment(vendorName),
approved: false,
approvedBy: '',
approvalDate: new Date()
};
// Calculate risk level
assessment.riskLevel = this.calculateRiskLevel(assessment);
// Determine if approved
assessment.approved = this.meetsApprovalCriteria(assessment);
return assessment;
}
private async performDueDiligence(vendorName: string): Promise<DueDiligenceChecks> {
return {
backgroundCheck: await this.conductBackgroundCheck(vendorName),
financialStability: await this.assessFinancialStability(vendorName),
reputationReview: await this.reviewReputation(vendorName),
referenceChecks: await this.checkReferences(vendorName),
contractReview: await this.reviewContract(vendorName),
securityQuestionnaire: await this.sendSecurityQuestionnaire(vendorName),
onSiteVisit: await this.conductOnSiteVisit(vendorName),
thirdPartyAudit: await this.requestThirdPartyAudit(vendorName)
};
}
}
Required Certifications
Minimum Requirements:
- ISO 27001 (Information Security Management)
- ISO 27018 (Cloud Privacy) or ISO 27701 (Privacy Management)
- SOC 2 Type II (Security, Privacy, Availability)
Industry-Specific:
- PCI DSS (payment processing)
- HITRUST (healthcare data)
- FedRAMP (government data)
Regional:
- EU-US Data Privacy Framework
- GDPR compliance documentation
- Local data protection registrations
Sub-processor Agreements
Data Processing Agreement (DPA) Template
SUB-PROCESSOR DATA PROCESSING AGREEMENT
1. DEFINITIONS AND SCOPE
1.1 "Customer Data" means all PII processed by Sub-processor
1.2 "Services" means [specific services provided]
1.3 Scope: Sub-processor will process Customer Data solely to provide Services
2. PROCESSING INSTRUCTIONS
2.1 Sub-processor shall process Customer Data only as instructed by CSP
2.2 No processing for Sub-processor's own purposes
2.3 Immediate notification if instruction violates data protection law
3. SECURITY OBLIGATIONS
3.1 Implement ISO 27018-compliant security measures
3.2 Encryption at rest and in transit
3.3 Access controls and authentication
3.4 Security incident response
3.5 Regular security assessments
4. SUB-PROCESSOR USE
4.1 Prior written approval required for sub-sub-processors
4.2 Same obligations flow down to sub-sub-processors
4.3 Sub-processor remains fully liable
5. DATA SUBJECT RIGHTS
5.1 Assist CSP in fulfilling data subject requests
5.2 Provide tools/APIs for access, correction, deletion
5.3 Response within [X] business days
6. DATA LOCATION AND TRANSFERS
6.1 Processing locations: [list countries/regions]
6.2 No transfers outside approved locations without consent
6.3 Appropriate transfer mechanisms (SCCs, BCRs)
7. AUDIT RIGHTS
7.1 CSP may audit Sub-processor compliance annually
7.2 Sub-processor provides SOC 2 / ISO certifications
7.3 On-site audits with [X] days notice
8. DATA RETURN AND DELETION
8.1 Upon termination, return or delete all Customer Data
8.2 Deletion within [30] days
8.3 Provide certified statement of deletion
9. BREACH NOTIFICATION
9.1 Notify CSP within [24] hours of security incident
9.2 Provide incident details and remediation plan
9.3 Cooperate in breach response
10. LIABILITY AND INDEMNIFICATION
10.1 Sub-processor liable for data protection breaches
10.2 Indemnify CSP for losses from Sub-processor breach
10.3 Insurance coverage: $[X] million
11. TERM AND TERMINATION
11.1 Term: Coterminous with Master Services Agreement
11.2 Termination for material breach
11.3 Survival of confidentiality and deletion obligations
Sub-processor Registry
Public Registry Implementation
interface SubProcessorEntry {
id: string;
name: string;
service: string;
piiCategories: string[];
dataLocations: string[];
certifications: Certification[];
addedDate: Date;
status: 'active' | 'pending' | 'removed';
website: string;
privacyPolicy: string;
}
class SubProcessorRegistry {
private registry: SubProcessorEntry[] = [];
async addSubProcessor(entry: SubProcessorEntry): Promise<void> {
// 1. Customer notification (30 days before activation)
await this.notifyCustomers({
type: 'NEW_SUB_PROCESSOR',
subProcessor: entry,
effectiveDate: addDays(new Date(), 30),
objectionDeadline: addDays(new Date(), 23) // 7 days to object
});
// 2. Add to pending status
entry.status = 'pending';
this.registry.push(entry);
// 3. Schedule activation
await this.scheduler.schedule(addDays(new Date(), 30), 'activate_sub_processor', {
subProcessorId: entry.id
});
// 4. Update public registry
await this.publishRegistry();
}
async handleCustomerObjection(
customerId: string,
subProcessorId: string,
reason: string
): Promise<void> {
const sp = this.registry.find(s => s.id === subProcessorId);
if (!sp) {
throw new Error('Sub-processor not found');
}
// Log objection
await this.logObjection(customerId, subProcessorId, reason);
// Evaluate objection
const validObjection = await this.evaluateObjection(reason);
if (validObjection) {
// Don't activate for this customer
await this.exemptCustomerFromSubProcessor(customerId, subProcessorId);
} else {
// Notify customer of denial with reasoning
await this.notifyObjectionDenied(customerId, subProcessorId, reason);
}
}
getPublicRegistry(): SubProcessorEntry[] {
return this.registry
.filter(sp => sp.status === 'active')
.map(sp => ({
...sp,
// Redact sensitive internal information
id: undefined
}));
}
async generateRegistryHTML(): Promise<string> {
const activeSubProcessors = this.getPublicRegistry();
return `
<h2>Sub-processor Registry</h2>
<p>Last Updated: ${new Date().toISOString()}</p>
<p>We use the following sub-processors to help deliver our services:</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Service</th>
<th>PII Access</th>
<th>Location</th>
<th>Certifications</th>
</tr>
</thead>
<tbody>
${activeSubProcessors.map(sp => `
<tr>
<td><a href="${sp.website}">${sp.name}</a></td>
<td>${sp.service}</td>
<td>${sp.piiCategories.join(', ')}</td>
<td>${sp.dataLocations.join(', ')}</td>
<td>${sp.certifications.map(c => c.name).join(', ')}</td>
</tr>
`).join('')}
</tbody>
</table>
<p>We will notify you 30 days before engaging new sub-processors.</p>
<p>You may object to new sub-processors by contacting privacy@company.com</p>
`;
}
}
Ongoing Monitoring
Continuous Compliance Monitoring
interface SubProcessorMonitoring {
subProcessorId: string;
monitoringChecks: MonitoringCheck[];
lastAudit: Date;
nextAudit: Date;
complianceScore: number;
issues: ComplianceIssue[];
}
interface MonitoringCheck {
type: 'certification' | 'security' | 'performance' | 'breach';
status: 'pass' | 'fail' | 'warning';
lastChecked: Date;
details: string;
}
class SubProcessorMonitoringService {
async monitorSubProcessors(): Promise<void> {
const subProcessors = await this.getActiveSubProcessors();
for (const sp of subProcessors) {
const monitoring = await this.performMonitoringChecks(sp);
if (monitoring.complianceScore < 80) {
await this.alertComplianceTeam(sp, monitoring);
}
if (monitoring.issues.length > 0) {
await this.initiateRemediationProcess(sp, monitoring.issues);
}
}
}
private async performMonitoringChecks(
sp: SubProcessor
): Promise<SubProcessorMonitoring> {
const checks: MonitoringCheck[] = [];
// 1. Check certifications are current
checks.push(await this.checkCertifications(sp));
// 2. Review latest security audit
checks.push(await this.reviewSecurityAudit(sp));
// 3. Check for security incidents
checks.push(await this.checkSecurityIncidents(sp));
// 4. Verify SLA compliance
checks.push(await this.verifySLACompliance(sp));
// 5. Review access logs
checks.push(await this.reviewAccessLogs(sp));
const complianceScore = this.calculateComplianceScore(checks);
const issues = this.identifyIssues(checks);
return {
subProcessorId: sp.id,
monitoringChecks: checks,
lastAudit: sp.lastAudit,
nextAudit: addMonths(sp.lastAudit, 12),
complianceScore,
issues
};
}
private async checkCertifications(sp: SubProcessor): Promise<MonitoringCheck> {
const certifications = await this.getCertifications(sp);
const allCurrent = certifications.every(c =>
c.expiryDate > new Date()
);
return {
type: 'certification',
status: allCurrent ? 'pass' : 'fail',
lastChecked: new Date(),
details: allCurrent
? 'All certifications current'
: 'Expired certifications found'
};
}
}
// Scheduled monitoring
cron.schedule('0 0 * * *', async () => {
await subProcessorMonitoringService.monitorSubProcessors();
});
Sub-processor Audit Process
Annual Audit Requirements
interface SubProcessorAudit {
auditId: string;
subProcessorId: string;
auditDate: Date;
auditor: string;
auditType: 'on-site' | 'remote' | 'document-review';
scope: string[];
findings: AuditFinding[];
overallRating: 'satisfactory' | 'needs-improvement' | 'unsatisfactory';
remediationRequired: boolean;
nextAuditDate: Date;
}
interface AuditFinding {
category: string;
severity: 'low' | 'medium' | 'high' | 'critical';
description: string;
evidence: string;
recommendation: string;
remediationDeadline?: Date;
}
class SubProcessorAuditService {
async conductAudit(subProcessorId: string): Promise<SubProcessorAudit> {
const audit: SubProcessorAudit = {
auditId: generateId(),
subProcessorId,
auditDate: new Date(),
auditor: getCurrentUser(),
auditType: 'remote',
scope: [
'security_controls',
'data_handling',
'access_management',
'incident_response',
'compliance_certifications'
],
findings: [],
overallRating: 'satisfactory',
remediationRequired: false,
nextAuditDate: addYears(new Date(), 1)
};
// Perform audit checks
audit.findings.push(...await this.auditSecurityControls(subProcessorId));
audit.findings.push(...await this.auditDataHandling(subProcessorId));
audit.findings.push(...await this.auditAccessManagement(subProcessorId));
audit.findings.push(...await this.auditIncidentResponse(subProcessorId));
audit.findings.push(...await this.auditCompliance(subProcessorId));
// Determine overall rating
audit.overallRating = this.calculateOverallRating(audit.findings);
audit.remediationRequired = audit.findings.some(
f => f.severity === 'high' || f.severity === 'critical'
);
// Generate audit report
await this.generateAuditReport(audit);
// If remediation required, schedule follow-up
if (audit.remediationRequired) {
await this.scheduleFollowUpAudit(subProcessorId, 90); // 90 days
}
return audit;
}
}
Sub-processor Removal
Offboarding Process
class SubProcessorOffboarding {
async removeSubProcessor(subProcessorId: string, reason: string): Promise<void> {
// 1. Notify customers
await this.notifyCustomers({
type: 'SUB_PROCESSOR_REMOVAL',
subProcessorId,
effectiveDate: addDays(new Date(), 30),
reason,
replacement: await this.getReplacementSubProcessor(subProcessorId)
});
// 2. Plan data migration
const migrationPlan = await this.createMigrationPlan(subProcessorId);
// 3. Execute migration
await this.executeMigration(migrationPlan);
// 4. Request data deletion from sub-processor
await this.requestDataDeletion(subProcessorId);
// 5. Verify deletion
const deletionVerified = await this.verifyDeletion(subProcessorId);
if (!deletionVerified) {
throw new Error('Sub-processor deletion verification failed');
}
// 6. Obtain deletion certificate
await this.obtainDeletionCertificate(subProcessorId);
// 7. Terminate contract
await this.terminateContract(subProcessorId);
// 8. Update registry
await this.updateRegistry(subProcessorId, 'removed');
// 9. Archive relationship documentation
await this.archiveDocumentation(subProcessorId);
}
}
Compliance Checklist
Sub-processor Management:
- Public sub-processor registry maintained
- 30-day advance notice for new sub-processors
- Customer objection process implemented
- Due diligence performed for all sub-processors
- Written DPAs with all sub-processors
- Equivalent protection verified
- Annual audits scheduled and conducted
- Continuous monitoring in place
- Security incident notification process
- Sub-processor removal procedures documented
- Deletion verification for removed sub-processors
Next Lesson: Data transfer controls - implementing secure cross-border transfer mechanisms.