Module 3: Technical Implementation

Sub-processor Management

18 min
+75 XP

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

  1. Customer Notification: Inform customers of all sub-processors
  2. Prior Authorization: Get customer approval before engaging new sub-processors
  3. Equivalent Protection: Ensure sub-processors provide same level of protection
  4. Written Agreements: Contracts with data protection obligations
  5. Right to Audit: Enable customer audits of sub-processors
  6. 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.

Complete this lesson

Earn +75 XP and progress to the next lesson