Skip to content

[CRITICAL] Implement OpenTDF-based Key Management for Content Protection #26

@superninja-app

Description

@superninja-app

[CRITICAL] Implement OpenTDF-based Key Management for Content Protection

Priority

🚨 P0 (Critical - Blocker)

Description

Currently, the FairPlay integration uses a hardcoded zero-filled placeholder content key, which makes the DRM system non-functional for actual content protection. This issue proposes implementing a comprehensive OpenTDF-based key management architecture that integrates policy management via smart contracts, external key services, and OpenTDF SDK functionality.

Location: src/modules/media_api.rs:449-456

// 5. TODO: Extract content key (DEK) from policy/storage
let content_key = vec![0x00u8; 16]; // PLACEHOLDER: Replace with actual DEK retrieval

Security Impact

  • All FairPlay-protected content currently uses the same zero-filled key
  • Any attacker can decrypt all content
  • Violates DRM security requirements
  • Potential legal/compliance issues with content providers
  • CVSS Score: 9.8 (Critical)

Background & Motivation

Why OpenTDF Instead of AWS KMS?

OpenTDF Advantages:

  1. Open Standards: OpenTDF is an open-source standard for data protection, ensuring interoperability and avoiding vendor lock-in
  2. Policy-Driven Security: Attribute-Based Access Control (ABAC) policies provide fine-grained, dynamic access control
  3. Smart Contract Integration: Policies can be managed via blockchain smart contracts within the Arkavo ecosystem
  4. Decentralized Architecture: Aligns with Arkavo's decentralized approach to content protection
  5. Cost Efficiency: No per-request fees or vendor-specific pricing
  6. Flexibility: Can integrate with multiple key storage backends (HSM, KMS, distributed key management)
  7. Compliance: Built-in support for data sovereignty and regulatory compliance requirements

Arkavo Integration Benefits:

  • Seamless integration with existing Arkavo smart contract infrastructure
  • Unified policy management across TDF3 and FairPlay protocols
  • Consistent security model across all DRM implementations
  • Enhanced auditability through blockchain-based policy tracking

Architecture Overview

The proposed architecture consists of three integrated components:

┌─────────────────────────────────────────────────────────────┐
│                     Arkavo Media DRM                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌──────────────────┐      ┌──────────────────┐           │
│  │  FairPlay/TDF3   │◄────►│  OpenTDF SDK     │           │
│  │  Protocol Layer  │      │  Integration     │           │
│  └──────────────────┘      └──────────────────┘           │
│           │                         │                      │
│           │                         │                      │
│           ▼                         ▼                      │
│  ┌──────────────────────────────────────────┐             │
│  │     Policy Evaluation Engine             │             │
│  │  (Smart Contract + Local Cache)          │             │
│  └──────────────────────────────────────────┘             │
│           │                         │                      │
│           │                         │                      │
│           ▼                         ▼                      │
│  ┌──────────────────┐      ┌──────────────────┐           │
│  │  Smart Contract  │      │  OpenTDF KAS     │           │
│  │  Policy Store    │      │  (Key Access     │           │
│  │  (Blockchain)    │      │   Service)       │           │
│  └──────────────────┘      └──────────────────┘           │
│                                     │                      │
└─────────────────────────────────────┼──────────────────────┘
                                      │
                                      ▼
                              ┌──────────────────┐
                              │  Key Storage     │
                              │  Backend         │
                              │  (HSM/KMS/Redis) │
                              └──────────────────┘

Component 1: OpenTDF Policy Management via Smart Contracts

Overview

Implement policy management using Arkavo's smart contract infrastructure to provide decentralized, auditable, and flexible access control.

Technical Requirements

  1. Smart Contract Policy Schema

    pub struct ContentPolicy {
        pub asset_id: String,
        pub policy_id: String,
        pub attributes: Vec<Attribute>,
        pub dissem: Vec<String>,           // Dissemination controls
        pub expiration: Option<i64>,       // Unix timestamp
        pub max_uses: Option<u32>,
        pub geo_restrictions: Vec<String>, // ISO 3166-1 alpha-2 codes
        pub device_restrictions: Vec<DeviceType>,
        pub created_at: i64,
        pub updated_at: i64,
        pub version: u32,
    }
    
    pub struct Attribute {
        pub namespace: String,
        pub name: String,
        pub value: String,
    }
    
    pub enum DeviceType {
        Mobile,
        Desktop,
        TV,
        Web,
    }
  2. Policy Evaluation Interface

    #[async_trait]
    pub trait PolicyEvaluator: Send + Sync {
        /// Evaluate policy for content access
        async fn evaluate_policy(
            &self,
            asset_id: &str,
            user_attributes: &[Attribute],
            context: &AccessContext,
        ) -> Result<PolicyDecision, PolicyError>;
    
        /// Get policy for asset
        async fn get_policy(
            &self,
            asset_id: &str,
        ) -> Result<ContentPolicy, PolicyError>;
    
        /// Update policy (requires authorization)
        async fn update_policy(
            &self,
            policy: ContentPolicy,
            signature: &[u8],
        ) -> Result<(), PolicyError>;
    }
    
    pub struct AccessContext {
        pub user_id: String,
        pub client_ip: String,
        pub geo_region: Option<String>,
        pub device_type: DeviceType,
        pub timestamp: i64,
    }
    
    pub struct PolicyDecision {
        pub allowed: bool,
        pub reason: Option<String>,
        pub key_access_info: Option<KeyAccessInfo>,
    }
  3. Smart Contract Integration

    • Use existing Arkavo smart contract infrastructure
    • Implement policy CRUD operations via contract calls
    • Cache policies locally with TTL for performance
    • Subscribe to policy update events from blockchain

Implementation Details

pub struct SmartContractPolicyManager {
    contract_client: Arc<ContractClient>,
    policy_cache: Arc<RwLock<LruCache<String, CachedPolicy>>>,
    cache_ttl: Duration,
}

impl SmartContractPolicyManager {
    pub async fn new(
        contract_address: String,
        cache_size: usize,
        cache_ttl: Duration,
    ) -> Result<Self, PolicyError> {
        let contract_client = ContractClient::connect(contract_address).await?;
        
        Ok(Self {
            contract_client: Arc::new(contract_client),
            policy_cache: Arc::new(RwLock::new(LruCache::new(cache_size))),
            cache_ttl,
        })
    }

    async fn fetch_policy_from_contract(
        &self,
        asset_id: &str,
    ) -> Result<ContentPolicy, PolicyError> {
        // Call smart contract to retrieve policy
        let policy_data = self.contract_client
            .call_method("getPolicy", &[asset_id])
            .await?;
        
        // Deserialize policy from contract response
        let policy: ContentPolicy = serde_json::from_slice(&policy_data)?;
        
        Ok(policy)
    }
}

#[async_trait]
impl PolicyEvaluator for SmartContractPolicyManager {
    async fn evaluate_policy(
        &self,
        asset_id: &str,
        user_attributes: &[Attribute],
        context: &AccessContext,
    ) -> Result<PolicyDecision, PolicyError> {
        // Get policy (from cache or contract)
        let policy = self.get_policy(asset_id).await?;
        
        // Evaluate ABAC rules
        let allowed = self.evaluate_abac_rules(
            &policy,
            user_attributes,
            context,
        )?;
        
        if !allowed {
            return Ok(PolicyDecision {
                allowed: false,
                reason: Some("Policy evaluation failed".to_string()),
                key_access_info: None,
            });
        }
        
        // Generate key access information
        let key_access_info = KeyAccessInfo {
            kas_url: self.get_kas_url(&policy)?,
            policy_binding: self.create_policy_binding(&policy)?,
        };
        
        Ok(PolicyDecision {
            allowed: true,
            reason: None,
            key_access_info: Some(key_access_info),
        })
    }

    async fn get_policy(
        &self,
        asset_id: &str,
    ) -> Result<ContentPolicy, PolicyError> {
        // Check cache first
        {
            let cache = self.policy_cache.read().await;
            if let Some(cached) = cache.get(asset_id) {
                if !cached.is_expired() {
                    return Ok(cached.policy.clone());
                }
            }
        }
        
        // Fetch from contract
        let policy = self.fetch_policy_from_contract(asset_id).await?;
        
        // Update cache
        {
            let mut cache = self.policy_cache.write().await;
            cache.put(
                asset_id.to_string(),
                CachedPolicy {
                    policy: policy.clone(),
                    cached_at: Utc::now(),
                },
            );
        }
        
        Ok(policy)
    }

    async fn update_policy(
        &self,
        policy: ContentPolicy,
        signature: &[u8],
    ) -> Result<(), PolicyError> {
        // Verify signature
        self.verify_policy_update_signature(&policy, signature)?;
        
        // Update contract
        self.contract_client
            .call_method("updatePolicy", &[
                serde_json::to_vec(&policy)?,
                signature.to_vec(),
            ])
            .await?;
        
        // Invalidate cache
        {
            let mut cache = self.policy_cache.write().await;
            cache.pop(&policy.asset_id);
        }
        
        Ok(())
    }
}

Component 2: OpenTDF KAS (Key Access Service) Integration

Overview

Implement integration with OpenTDF Key Access Service for secure key retrieval and management.

Technical Requirements

  1. KAS Client Interface

    #[async_trait]
    pub trait KasClient: Send + Sync {
        /// Request key from KAS
        async fn request_key(
            &self,
            request: KeyRequest,
        ) -> Result<KeyResponse, KasError>;
    
        /// Rewrap key (for key rotation)
        async fn rewrap_key(
            &self,
            request: RewrapRequest,
        ) -> Result<RewrapResponse, KasError>;
    
        /// Health check
        async fn health_check(&self) -> Result<(), KasError>;
    }
    
    pub struct KeyRequest {
        pub policy_binding: Vec<u8>,
        pub client_public_key: Vec<u8>,
        pub algorithm: String,
        pub user_attributes: Vec<Attribute>,
    }
    
    pub struct KeyResponse {
        pub wrapped_key: Vec<u8>,
        pub policy: Vec<u8>,
        pub algorithm: String,
    }
  2. OpenTDF KAS Implementation

    pub struct OpenTdfKasClient {
        kas_url: String,
        http_client: reqwest::Client,
        public_key: P256PublicKey,
        private_key: SecretKey,
    }
    
    impl OpenTdfKasClient {
        pub async fn new(
            kas_url: String,
            cert_path: Option<PathBuf>,
        ) -> Result<Self, KasError> {
            // Generate or load key pair
            let private_key = SecretKey::random(&mut OsRng);
            let public_key = P256PublicKey::from(&private_key);
            
            // Configure HTTP client with TLS
            let mut http_client_builder = reqwest::Client::builder()
                .timeout(Duration::from_secs(30))
                .pool_max_idle_per_host(10);
            
            if let Some(cert) = cert_path {
                let cert_bytes = std::fs::read(cert)?;
                let cert = reqwest::Certificate::from_pem(&cert_bytes)?;
                http_client_builder = http_client_builder.add_root_certificate(cert);
            }
            
            let http_client = http_client_builder.build()?;
            
            Ok(Self {
                kas_url,
                http_client,
                public_key,
                private_key,
            })
        }
    }
    
    #[async_trait]
    impl KasClient for OpenTdfKasClient {
        async fn request_key(
            &self,
            request: KeyRequest,
        ) -> Result<KeyResponse, KasError> {
            // Construct KAS request per OpenTDF spec
            let kas_request = serde_json::json!({
                "keyAccess": {
                    "type": "wrapped",
                    "url": self.kas_url,
                    "protocol": "kas",
                    "wrappedKey": base64::encode(&request.policy_binding),
                },
                "policy": base64::encode(&request.policy_binding),
                "clientPublicKey": base64::encode(&request.client_public_key),
                "algorithm": request.algorithm,
            });
            
            // Send request to KAS
            let response = self.http_client
                .post(format!("{}/v2/rewrap", self.kas_url))
                .json(&kas_request)
                .send()
                .await?;
            
            if !response.status().is_success() {
                return Err(KasError::RequestFailed(
                    response.status(),
                    response.text().await?,
                ));
            }
            
            let kas_response: serde_json::Value = response.json().await?;
            
            // Extract wrapped key
            let wrapped_key = base64::decode(
                kas_response["entityWrappedKey"]
                    .as_str()
                    .ok_or(KasError::InvalidResponse)?,
            )?;
            
            Ok(KeyResponse {
                wrapped_key,
                policy: request.policy_binding,
                algorithm: request.algorithm,
            })
        }
    
        async fn rewrap_key(
            &self,
            request: RewrapRequest,
        ) -> Result<RewrapResponse, KasError> {
            // Implement key rewrapping for rotation
            let rewrap_request = serde_json::json!({
                "signedRequestToken": request.signed_token,
            });
            
            let response = self.http_client
                .post(format!("{}/v2/rewrap", self.kas_url))
                .json(&rewrap_request)
                .send()
                .await?;
            
            let rewrap_response: serde_json::Value = response.json().await?;
            
            Ok(RewrapResponse {
                wrapped_key: base64::decode(
                    rewrap_response["entityWrappedKey"]
                        .as_str()
                        .ok_or(KasError::InvalidResponse)?,
                )?,
            })
        }
    
        async fn health_check(&self) -> Result<(), KasError> {
            let response = self.http_client
                .get(format!("{}/healthz", self.kas_url))
                .send()
                .await?;
            
            if response.status().is_success() {
                Ok(())
            } else {
                Err(KasError::Unhealthy)
            }
        }
    }
  3. Key Storage Backend

    #[async_trait]
    pub trait KeyStorage: Send + Sync {
        /// Store encrypted key
        async fn store_key(
            &self,
            asset_id: &str,
            encrypted_key: &[u8],
            metadata: KeyMetadata,
        ) -> Result<(), StorageError>;
    
        /// Retrieve encrypted key
        async fn get_key(
            &self,
            asset_id: &str,
        ) -> Result<(Vec<u8>, KeyMetadata), StorageError>;
    
        /// Delete key
        async fn delete_key(
            &self,
            asset_id: &str,
        ) -> Result<(), StorageError>;
    }
    
    pub struct KeyMetadata {
        pub created_at: i64,
        pub algorithm: String,
        pub key_version: u32,
        pub policy_version: u32,
    }

Component 3: OpenTDF SDK Integration

Overview

Implement OpenTDF SDK functionality within Arkavo for TDF3 creation, encryption, and decryption.

Technical Requirements

  1. TDF3 Operations

    pub struct OpenTdfSdk {
        kas_client: Arc<dyn KasClient>,
        policy_evaluator: Arc<dyn PolicyEvaluator>,
    }
    
    impl OpenTdfSdk {
        pub async fn create_tdf(
            &self,
            plaintext: &[u8],
            policy: ContentPolicy,
        ) -> Result<Vec<u8>, TdfError> {
            // Generate DEK
            let dek = self.generate_dek()?;
            
            // Encrypt content with DEK
            let ciphertext = self.encrypt_content(plaintext, &dek)?;
            
            // Wrap DEK with KAS public key
            let wrapped_dek = self.wrap_dek(&dek, &policy).await?;
            
            // Create TDF3 manifest
            let manifest = self.create_manifest(
                &wrapped_dek,
                &policy,
                ciphertext.len(),
            )?;
            
            // Assemble TDF3 package
            let tdf = self.assemble_tdf(&manifest, &ciphertext)?;
            
            Ok(tdf)
        }
    
        pub async fn decrypt_tdf(
            &self,
            tdf: &[u8],
            user_attributes: &[Attribute],
        ) -> Result<Vec<u8>, TdfError> {
            // Parse TDF3 package
            let (manifest, ciphertext) = self.parse_tdf(tdf)?;
            
            // Extract policy
            let policy = self.extract_policy(&manifest)?;
            
            // Evaluate policy
            let decision = self.policy_evaluator
                .evaluate_policy(
                    &policy.asset_id,
                    user_attributes,
                    &AccessContext::current(),
                )
                .await?;
            
            if !decision.allowed {
                return Err(TdfError::PolicyDenied(
                    decision.reason.unwrap_or_default(),
                ));
            }
            
            // Unwrap DEK via KAS
            let dek = self.unwrap_dek(&manifest, user_attributes).await?;
            
            // Decrypt content
            let plaintext = self.decrypt_content(&ciphertext, &dek)?;
            
            Ok(plaintext)
        }
    
        async fn wrap_dek(
            &self,
            dek: &[u8],
            policy: &ContentPolicy,
        ) -> Result<Vec<u8>, TdfError> {
            // Create policy binding
            let policy_binding = self.create_policy_binding(policy)?;
            
            // Request key wrapping from KAS
            let request = KeyRequest {
                policy_binding,
                client_public_key: self.get_public_key()?,
                algorithm: "AES-256-GCM".to_string(),
                user_attributes: vec![],
            };
            
            let response = self.kas_client.request_key(request).await?;
            
            Ok(response.wrapped_key)
        }
    
        async fn unwrap_dek(
            &self,
            manifest: &TdfManifest,
            user_attributes: &[Attribute],
        ) -> Result<Vec<u8>, TdfError> {
            // Extract wrapped key from manifest
            let wrapped_key = &manifest.encryption_information.key_access[0].wrapped_key;
            
            // Request key unwrapping from KAS
            let request = KeyRequest {
                policy_binding: manifest.encryption_information.policy.clone(),
                client_public_key: self.get_public_key()?,
                algorithm: manifest.encryption_information.method.algorithm.clone(),
                user_attributes: user_attributes.to_vec(),
            };
            
            let response = self.kas_client.request_key(request).await?;
            
            // Unwrap DEK using ECDH
            let dek = self.perform_ecdh_unwrap(&response.wrapped_key)?;
            
            Ok(dek)
        }
    }
  2. Integration with FairPlay Handler

    pub async fn get_content_key_opentdf(
        &self,
        asset_id: &str,
        user_attributes: &[Attribute],
        context: &AccessContext,
    ) -> Result<Vec<u8>, KeyRetrievalError> {
        // Evaluate policy
        let decision = self.policy_evaluator
            .evaluate_policy(asset_id, user_attributes, context)
            .await?;
        
        if !decision.allowed {
            return Err(KeyRetrievalError::PolicyDenied(
                decision.reason.unwrap_or_default(),
            ));
        }
        
        // Get key access info from policy decision
        let key_access_info = decision.key_access_info
            .ok_or(KeyRetrievalError::NoKeyAccessInfo)?;
        
        // Request key from KAS
        let key_request = KeyRequest {
            policy_binding: key_access_info.policy_binding,
            client_public_key: self.get_public_key()?,
            algorithm: "AES-128-GCM".to_string(),
            user_attributes: user_attributes.to_vec(),
        };
        
        let key_response = self.kas_client
            .request_key(key_request)
            .await?;
        
        // Unwrap key
        let dek = self.unwrap_key(&key_response.wrapped_key)?;
        
        // Validate key
        if dek.len() != 16 {
            return Err(KeyRetrievalError::InvalidKeySize);
        }
        if dek.iter().all(|&b| b == 0) {
            return Err(KeyRetrievalError::InvalidKey);
        }
        
        Ok(dek)
    }

Dependencies & Prerequisites

External Dependencies

  1. OpenTDF Rust SDK (if available) or implement OpenTDF protocol
  2. Smart Contract Client Library (existing Arkavo infrastructure)
  3. Cryptographic Libraries:
    • p256 for ECDH operations
    • aes-gcm for content encryption
    • hkdf for key derivation
    • sha2 for hashing

Infrastructure Requirements

  1. OpenTDF KAS Deployment:

    • Deploy OpenTDF KAS service (Docker/Kubernetes)
    • Configure TLS certificates
    • Set up key storage backend (HSM, KMS, or Redis)
  2. Smart Contract Deployment:

    • Deploy policy management contracts
    • Configure contract access permissions
    • Set up event listeners for policy updates
  3. Configuration:

    [opentdf]
    kas_url = "https://kas.arkavo.com"
    kas_public_key_path = "./config/kas_public_key.pem"
    kas_cert_path = "./config/kas_cert.pem"
    
    [policy]
    contract_address = "0x..."
    cache_size = 1000
    cache_ttl_seconds = 300
    
    [key_storage]
    backend = "redis"  # or "hsm", "kms"
    redis_url = "redis://localhost:6379"

Implementation Plan

Phase 1: Core Infrastructure (Week 1-2)

  1. Implement PolicyEvaluator trait and SmartContractPolicyManager
  2. Implement KasClient trait and OpenTdfKasClient
  3. Set up policy caching mechanism
  4. Add configuration management

Phase 2: OpenTDF SDK Integration (Week 2-3)

  1. Implement TDF3 creation and decryption
  2. Implement key wrapping/unwrapping
  3. Integrate with existing crypto module
  4. Add ECDH operations

Phase 3: FairPlay Integration (Week 3-4)

  1. Replace placeholder key retrieval in media_api.rs
  2. Integrate policy evaluation with key requests
  3. Add user attribute extraction from session
  4. Implement key validation

Phase 4: Testing & Validation (Week 4-5)

  1. Unit tests for all components
  2. Integration tests with mock KAS
  3. End-to-end tests with real KAS
  4. Performance testing (< 10ms overhead target)
  5. Security testing

Phase 5: Documentation & Deployment (Week 5-6)

  1. Architecture documentation
  2. API documentation
  3. Deployment guides
  4. Operational runbooks
  5. Security audit

Acceptance Criteria

Functional Requirements

  • Policy evaluation via smart contracts working
  • KAS integration functional for key requests
  • OpenTDF SDK operations (create/decrypt TDF) working
  • FairPlay integration using OpenTDF keys
  • Per-content unique keys supported
  • Key rotation mechanism implemented
  • Runtime validation prevents zero-filled keys

Non-Functional Requirements

  • Key retrieval latency < 10ms (cached policies)
  • Key retrieval latency < 50ms (uncached policies)
  • Policy cache hit rate > 90%
  • Support for 1000+ concurrent key requests
  • Zero downtime during key rotation

Testing Requirements

  • Unit test coverage > 80%
  • Integration tests with mock KAS passing
  • End-to-end tests with real KAS passing
  • Performance tests meeting latency targets
  • Security tests passing (no zero-filled keys, proper validation)

Documentation Requirements

  • Architecture Decision Record (ADR) created
  • API documentation complete
  • Deployment guide written
  • Operational runbook created
  • Security audit report completed

Security Requirements

  • All keys encrypted at rest
  • TLS for all KAS communication
  • Policy signatures verified
  • Audit logging for all key access
  • No sensitive data in logs

Testing Strategy

Unit Tests

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_policy_evaluation_allowed() {
        let policy_manager = create_mock_policy_manager();
        let user_attrs = vec![
            Attribute {
                namespace: "https://arkavo.com".to_string(),
                name: "role".to_string(),
                value: "premium".to_string(),
            },
        ];
        
        let decision = policy_manager
            .evaluate_policy("asset-123", &user_attrs, &mock_context())
            .await
            .unwrap();
        
        assert!(decision.allowed);
    }

    #[tokio::test]
    async fn test_kas_key_request() {
        let kas_client = create_mock_kas_client();
        let request = KeyRequest {
            policy_binding: vec![1, 2, 3],
            client_public_key: vec![4, 5, 6],
            algorithm: "AES-256-GCM".to_string(),
            user_attributes: vec![],
        };
        
        let response = kas_client.request_key(request).await.unwrap();
        
        assert!(!response.wrapped_key.is_empty());
    }

    #[tokio::test]
    async fn test_zero_filled_key_rejected() {
        let sdk = create_test_sdk();
        let zero_key = vec![0u8; 16];
        
        let result = sdk.validate_key(&zero_key);
        
        assert!(result.is_err());
        assert!(matches!(result.unwrap_err(), KeyRetrievalError::InvalidKey));
    }
}

Integration Tests

#[tokio::test]
#[ignore] // Requires KAS service
async fn test_end_to_end_key_retrieval() {
    let config = load_test_config();
    let sdk = OpenTdfSdk::new(config).await.unwrap();
    
    // Create test policy
    let policy = create_test_policy();
    
    // Request key
    let key = sdk.get_content_key_opentdf(
        "test-asset",
        &test_user_attributes(),
        &test_context(),
    ).await.unwrap();
    
    // Validate key
    assert_eq!(key.len(), 16);
    assert!(!key.iter().all(|&b| b == 0));
}

Performance Considerations

Optimization Strategies

  1. Policy Caching:

    • LRU cache with configurable TTL
    • Cache invalidation on policy updates
    • Target: 90%+ cache hit rate
  2. Connection Pooling:

    • Reuse HTTP connections to KAS
    • Connection pool size: 10-20 per instance
  3. Async Operations:

    • All I/O operations async
    • Parallel policy evaluation when possible
  4. Key Prefetching:

    • Prefetch keys for popular content
    • Background refresh before expiration

Performance Targets

  • Policy evaluation (cached): < 1ms
  • Policy evaluation (uncached): < 50ms
  • KAS key request: < 30ms
  • Total key retrieval: < 50ms (P95)

Security Considerations

Threat Model

  1. Key Exposure: Keys must never be logged or exposed in plaintext
  2. Policy Bypass: Policy evaluation must be tamper-proof
  3. Replay Attacks: Prevent reuse of old policy decisions
  4. Man-in-the-Middle: All KAS communication over TLS

Security Controls

  1. Encryption at Rest: All keys encrypted in storage
  2. Encryption in Transit: TLS 1.3 for all network communication
  3. Access Control: Policy-based access to keys
  4. Audit Logging: All key access logged with user context
  5. Key Rotation: Automated key rotation every 90 days
  6. Zero-Knowledge: KAS cannot decrypt content

Monitoring & Observability

Metrics to Track

pub struct KeyManagementMetrics {
    pub key_requests_total: Counter,
    pub key_request_duration: Histogram,
    pub policy_cache_hits: Counter,
    pub policy_cache_misses: Counter,
    pub kas_errors: Counter,
    pub policy_evaluation_duration: Histogram,
}

Alerts

  1. High Error Rate: > 1% key request failures
  2. High Latency: P95 > 100ms
  3. Low Cache Hit Rate: < 80%
  4. KAS Unavailable: Health check failures

Logging

// Structured logging for key access
log::info!(
    target: "key_access",
    user_id = %user_id,
    asset_id = %asset_id,
    policy_version = policy.version,
    decision = %decision.allowed,
    latency_ms = latency,
    "Key access request"
);

Migration Strategy

Phase 1: Parallel Operation

  1. Deploy OpenTDF infrastructure alongside existing system
  2. Route 10% of traffic to new system
  3. Monitor metrics and errors
  4. Gradually increase traffic

Phase 2: Full Migration

  1. Route 100% of new sessions to OpenTDF
  2. Maintain backward compatibility for existing sessions
  3. Migrate existing keys to new system

Phase 3: Cleanup

  1. Remove placeholder key code
  2. Remove old key management code
  3. Update documentation

Rollback Plan

Rollback Triggers

  1. Error rate > 5%
  2. Latency P95 > 200ms
  3. KAS unavailability > 5 minutes
  4. Critical security issue discovered

Rollback Procedure

  1. Route traffic back to placeholder (temporary)
  2. Investigate root cause
  3. Fix issues in staging
  4. Redeploy with fixes

Related Issues & PRs


References

  1. OpenTDF Specification
  2. OpenTDF Protocol
  3. TDF3 Format Specification
  4. Arkavo Smart Contracts Documentation
  5. ABAC Policy Model

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions