다음을 통해 공유


PlayReady 테스트 환경용 보안 삭제 서버

개요

PlayReady 보안 삭제 서버는 PlayReady 구현에서 보안 삭제 기능의 유효성을 검사하기 위한 테스트 엔드포인트를 제공합니다. 보안 삭제는 필요한 경우 클라이언트 디바이스에서 보호된 콘텐츠 및 관련 라이선스를 안전하게 제거할 수 있도록 하며 콘텐츠 보호 및 규정 준수 요구 사항을 유지 관리합니다.

서비스 엔드포인트

보안 삭제 테스트 서버는 다음 위치에서 사용할 수 있습니다.

https://playready.directtaps.net/pr/svc/securedelete.asmx

보안 삭제 프로토콜

프로토콜 개요

보안 삭제를 사용하면 콘텐츠 공급자가 콘텐츠 및 라이선스의 보안 삭제를 원격으로 트리거할 수 있습니다.

  1. 콘텐츠 공급자가 삭제가 필요하다고 결정합니다.
  2. 서버에서 보안 삭제 명령을 생성합니다.
  3. 명령이 클라이언트 디바이스에 전달됨
  4. 클라이언트는 보안 삭제의 유효성을 검사하고 실행합니다.
  5. 클라이언트가 서버에 삭제 완료를 보고합니다.

메시지 흐름

Content Provider       Secure Delete Server        Client Device
       |                        |                        |
       |-- Delete Request ----->|                        |
       |<-- Delete Command -----|                        |
       |                        |-- Push Command ------>|
       |                        |<-- Execution Report ---|
       |<-- Completion Report --|                        |

서버 구성

보안 삭제 정책

라이선스에서 보안 삭제 요구 사항을 구성합니다.

{
  "licenseType": "persistent",
  "keyId": "key-id-guid",
  "secureDelete": {
    "enabled": true,
    "serverUrl": "https://playready.directtaps.net/pr/svc/securedelete.asmx",
    "triggerMechanism": "remote|policy|expiration",
    "deletionScope": "license|content|both",
    "customData": {
      "contentId": "content-identifier",
      "policyId": "deletion-policy-id"
    }
  }
}

삭제 정책

다양한 삭제 시나리오를 정의합니다.

{
  "deletionPolicies": [
    {
      "policyId": "immediate-delete",
      "trigger": "remote-command",
      "scope": "both",
      "verification": "required"
    },
    {
      "policyId": "expiration-delete",
      "trigger": "license-expiration",
      "scope": "license",
      "gracePeriod": "PT24H"
    },
    {
      "policyId": "compliance-delete",
      "trigger": "compliance-violation",
      "scope": "content",
      "enforcement": "immediate"
    }
  ]
}

API 엔드포인트

보안 삭제 요청

엔드포인트:POST /pr/svc/securedelete.asmx/RequestDelete

요청 형식:

POST /pr/svc/securedelete.asmx/RequestDelete HTTP/1.1
Host: playready.directtaps.net
Content-Type: application/json

{
  "contentId": "content-identifier",
  "deviceId": "target-device-id",
  "deletionScope": "license|content|both",
  "reason": "expiration|violation|request",
  "immediateExecution": true
}

응답 형식:

{
  "deleteCommandId": "command-identifier",
  "status": "queued|sent|acknowledged|completed",
  "timestamp": "2024-01-15T10:30:00Z",
  "estimatedCompletion": "2024-01-15T10:35:00Z"
}

쿼리 삭제 상태

엔드포인트:GET /pr/svc/securedelete.asmx/QueryStatus

요청 형식:

GET /pr/svc/securedelete.asmx/QueryStatus?commandId=COMMAND_ID HTTP/1.1
Host: playready.directtaps.net

응답 형식:

{
  "commandId": "command-identifier",
  "status": "pending|in-progress|completed|failed",
  "progress": {
    "itemsToDelete": 5,
    "itemsDeleted": 3,
    "percentComplete": 60
  },
  "completionTime": "2024-01-15T10:35:00Z",
  "errorDetails": null
}

보고서 삭제 완료

엔드포인트:POST /pr/svc/securedelete.asmx/ReportCompletion

요청 형식:

POST /pr/svc/securedelete.asmx/ReportCompletion HTTP/1.1
Host: playready.directtaps.net
Content-Type: application/octet-stream

[Secure Delete Completion Report - Binary Format]

테스트 시나리오

기본 보안 삭제 테스트

표준 보안 삭제 흐름 테스트:

async function testBasicSecureDelete() {
    // 1. Request secure delete for content
    const deleteRequest = {
        contentId: 'test-content-123',
        deviceId: 'test-device-456',
        deletionScope: 'both',
        reason: 'expiration',
        immediateExecution: true
    };
    
    const response = await requestSecureDelete(deleteRequest);
    
    // 2. Monitor deletion progress
    let status;
    do {
        await new Promise(resolve => setTimeout(resolve, 1000)); // Wait 1 second
        status = await queryDeleteStatus(response.deleteCommandId);
    } while (status.status === 'pending' || status.status === 'in-progress');
    
    return status.status === 'completed';
}

정책 기반 삭제 테스트

다른 삭제 정책을 테스트합니다.

async function testPolicyBasedDeletion() {
    const policies = [
        {
            name: 'Immediate Delete',
            config: { trigger: 'remote-command', scope: 'both' }
        },
        {
            name: 'Expiration Delete',
            config: { trigger: 'license-expiration', scope: 'license' }
        },
        {
            name: 'Selective Delete',
            config: { trigger: 'compliance-violation', scope: 'content' }
        }
    ];
    
    const results = [];
    for (const policy of policies) {
        try {
            const result = await testDeletionPolicy(policy.config);
            results.push({ policy: policy.name, result: 'PASS' });
        } catch (error) {
            results.push({ policy: policy.name, result: 'FAIL', error: error.message });
        }
    }
    
    return results;
}

일괄 처리 삭제 테스트

여러 콘텐츠 삭제 테스트:

async function testBatchDeletion() {
    const contentItems = [
        'content-001',
        'content-002', 
        'content-003',
        'content-004',
        'content-005'
    ];
    
    // Request batch deletion
    const batchRequest = {
        contentIds: contentItems,
        deviceId: 'test-device-789',
        deletionScope: 'both',
        reason: 'batch-cleanup'
    };
    
    const response = await requestBatchDelete(batchRequest);
    
    // Monitor batch progress
    const finalStatus = await monitorBatchProgress(response.batchCommandId);
    
    return {
        totalItems: contentItems.length,
        successfulDeletions: finalStatus.progress.itemsDeleted,
        failedDeletions: finalStatus.progress.itemsToDelete - finalStatus.progress.itemsDeleted,
        completionTime: finalStatus.completionTime
    };
}

클라이언트 통합

JavaScript 구현

class SecureDeleteClient {
    constructor(serverUrl) {
        this.serverUrl = serverUrl;
    }
    
    async requestDelete(deleteRequest) {
        const response = await fetch(`${this.serverUrl}/RequestDelete`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(deleteRequest)
        });
        
        if (!response.ok) {
            throw new Error(`Delete request failed: ${response.status}`);
        }
        
        return await response.json();
    }
    
    async queryStatus(commandId) {
        const response = await fetch(`${this.serverUrl}/QueryStatus?commandId=${commandId}`);
        
        if (!response.ok) {
            throw new Error(`Status query failed: ${response.status}`);
        }
        
        return await response.json();
    }
    
    async reportCompletion(completionData) {
        const response = await fetch(`${this.serverUrl}/ReportCompletion`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/octet-stream'
            },
            body: completionData
        });
        
        return response.ok;
    }
}

// Usage
const secureDeleteClient = new SecureDeleteClient('https://playready.directtaps.net/pr/svc/securedelete.asmx');

C# 구현

public class SecureDeleteClient
{
    private readonly HttpClient httpClient;
    private readonly string serverUrl;
    
    public SecureDeleteClient(string serverUrl)
    {
        this.serverUrl = serverUrl;
        this.httpClient = new HttpClient();
    }
    
    public async Task<DeleteResponse> RequestDeleteAsync(DeleteRequest request)
    {
        var json = JsonConvert.SerializeObject(request);
        var content = new StringContent(json, Encoding.UTF8, "application/json");
        
        var response = await httpClient.PostAsync($"{serverUrl}/RequestDelete", content);
        response.EnsureSuccessStatusCode();
        
        var responseJson = await response.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<DeleteResponse>(responseJson);
    }
    
    public async Task<DeleteStatus> QueryStatusAsync(string commandId)
    {
        var response = await httpClient.GetAsync($"{serverUrl}/QueryStatus?commandId={commandId}");
        response.EnsureSuccessStatusCode();
        
        var json = await response.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<DeleteStatus>(json);
    }
    
    public async Task<bool> ReportCompletionAsync(byte[] completionData)
    {
        var content = new ByteArrayContent(completionData);
        content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        
        var response = await httpClient.PostAsync($"{serverUrl}/ReportCompletion", content);
        return response.IsSuccessStatusCode;
    }
}

삭제 범위

License-Only 삭제

라이선스만 제거하고 콘텐츠를 유지합니다.

{
  "deletionScope": "license",
  "preserveContent": true,
  "licenseCleanup": {
    "removeFromStore": true,
    "clearCacheReferences": true,
    "revokeBindings": true
  }
}

콘텐츠 전용 삭제

라이선스를 유지하면서 콘텐츠 파일을 제거합니다.

{
  "deletionScope": "content",
  "preserveLicense": true,
  "contentCleanup": {
    "removeFiles": true,
    "clearTemporaryFiles": true,
    "cleanupMetadata": true
  }
}

전체 삭제

라이선스와 콘텐츠를 모두 제거합니다.

{
  "deletionScope": "both",
  "thoroughCleanup": true,
  "verification": {
    "confirmLicenseRemoval": true,
    "confirmContentRemoval": true,
    "verifyNoResidualData": true
  }
}

보안 고려사항

명령 인증

보안 삭제 명령을 인증해야 합니다.

{
  "commandAuthentication": {
    "signature": "cryptographic-signature",
    "certificateChain": ["cert1", "cert2"],
    "timestamp": "2024-01-15T10:30:00Z",
    "nonce": "random-value"
  }
}

확인 요구 사항

보안 삭제가 제대로 실행되었는지 확인합니다.

{
  "verificationRequirements": {
    "cryptographicProof": true,
    "overwriteVerification": true,
    "witnessReporting": true,
    "tamperDetection": true
  }
}

고급 기능

조건부 삭제

조건부 삭제 트리거 구성:

{
  "conditionalDeletion": {
    "conditions": [
      {
        "type": "time-based",
        "trigger": "2024-12-31T23:59:59Z"
      },
      {
        "type": "usage-based",
        "trigger": "max-plays-exceeded"
      },
      {
        "type": "location-based",
        "trigger": "geographic-restriction"
      }
    ],
    "logicalOperator": "OR"
  }
}

롤백 기능

삭제 롤백 지원(가능한 경우):

{
  "rollbackSupport": {
    "enabled": true,
    "retentionPeriod": "PT72H",
    "backupLocation": "secure-backup-store",
    "rollbackConditions": ["deletion-error", "false-positive"]
  }
}

모니터링 및 보고

삭제 분석

보안 삭제 작업 추적:

async function getDeletionAnalytics(period) {
    const response = await fetch(`${serverUrl}/Analytics?period=${period}`);
    return await response.json();
}

// Example response
{
  "period": "24h",
  "totalDeletions": 150,
  "successfulDeletions": 145,
  "failedDeletions": 5,
  "averageExecutionTime": "2.3s",
  "deletionReasons": {
    "expiration": 89,
    "violation": 12,
    "request": 49
  }
}

규정 준수 보고

감사에 대한 준수 보고서를 생성합니다.

async function generateComplianceReport(startDate, endDate) {
    const params = new URLSearchParams({
        startDate: startDate.toISOString(),
        endDate: endDate.toISOString(),
        format: 'detailed'
    });
    
    const response = await fetch(`${serverUrl}/ComplianceReport?${params}`);
    return await response.blob(); // Returns PDF report
}

모범 사례

구현 지침

  1. 확인: 항상 삭제 완료 확인
  2. 로깅: 자세한 삭제 로그 유지 관리
  3. 보안: 삭제 명령에 강력한 인증 사용
  4. 복구: 적절한 백업 전략 구현
  5. 테스트: 철저한 테스트 삭제 시나리오

성능 최적화

  1. 일괄 처리 작업: 그룹 관련 삭제
  2. 비동기 처리: 대규모 작업에 비동기 삭제 사용
  3. 리소스 관리: 삭제하는 동안 시스템 리소스 모니터링
  4. 일정: 사용량이 적은 기간 동안 삭제 예약

오류 처리

일반적인 오류 시나리오

  • 인증 실패: 유효하지 않거나 만료된 자격 증명
  • 콘텐츠를 찾을 수 없음: 지정된 콘텐츠가 없습니다.
  • 삭제 충돌: 현재 사용 중인 콘텐츠
  • 시스템 오류: 스토리지 또는 네트워크 문제
  • 정책 위반: 정책에서 삭제가 허용되지 않음

오류 복구

async function handleDeletionError(commandId, error) {
    switch (error.type) {
        case 'AUTHENTICATION_FAILED':
            // Refresh credentials and retry
            await refreshAuthToken();
            return await retryDeletion(commandId);
            
        case 'CONTENT_IN_USE':
            // Wait and retry
            await waitForContentRelease();
            return await retryDeletion(commandId);
            
        case 'SYSTEM_ERROR':
            // Log error and schedule retry
            await logSystemError(error);
            return await scheduleDeletionRetry(commandId);
            
        default:
            throw new Error(`Unhandled deletion error: ${error.message}`);
    }
}

지원 및 문제 해결

보안 삭제 기능 관련 문제:

  1. 라이선스에서 보안 삭제가 사용하도록 설정되어 있는지 확인
  2. 삭제 범위 및 정책 구성 확인
  3. 명령 인증 유효성 검사
  4. 삭제 진행률 및 상태 모니터링
  5. 특정 문제에 대한 오류 로그 검토

일반적인 문제 해결 단계:

  • 간소화된 삭제 시나리오를 사용하여 테스트
  • 서버에 대한 네트워크 연결 확인
  • 콘텐츠 삭제에 대한 디바이스 권한 확인
  • 암호화 서명 유효성 검사
  • 정책 충돌 검토

추가 지원은 기본 PlayReady 테스트 서버 설명서를 참조하세요.