private async Task <ResponseMessage> ReadItemHelperAsync( string id, PartitionKey partitionKey, ItemRequestOptions requestOptions, bool decryptResponse, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { ResponseMessage responseMessage = await this.container.ReadItemStreamAsync( id, partitionKey, requestOptions, cancellationToken); if (decryptResponse) { (responseMessage.Content, _) = await EncryptionProcessor.DecryptAsync( responseMessage.Content, this.Encryptor, diagnosticsContext, cancellationToken); } return(responseMessage); }
public override async Task <TransactionalBatchResponse> ExecuteAsync( CancellationToken cancellationToken = default) { CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(options: null); using (diagnosticsContext.CreateScope("TransactionalBatch.ExecuteAsync")) { TransactionalBatchResponse response = await this.transactionalBatch.ExecuteAsync(cancellationToken); if (response.IsSuccessStatusCode) { for (int index = 0; index < response.Count; index++) { TransactionalBatchOperationResult result = response[index]; if (result.ResourceStream != null) { result.ResourceStream = await EncryptionProcessor.DecryptAsync( result.ResourceStream, this.encryptor, diagnosticsContext, cancellationToken); } } } return(response); } }
private async Task <TransactionalBatchResponse> DecryptTransactionalBatchResponseAsync( TransactionalBatchResponse response, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { List <TransactionalBatchOperationResult> decryptedTransactionalBatchOperationResults = new List <TransactionalBatchOperationResult>(); if (response.IsSuccessStatusCode) { for (int index = 0; index < response.Count; index++) { TransactionalBatchOperationResult result = response[index]; if (result.ResourceStream != null) { (Stream decryptedStream, _) = await EncryptionProcessor.DecryptAsync( result.ResourceStream, this.encryptor, diagnosticsContext, cancellationToken); result = new EncryptionTransactionalBatchOperationResult(response[index], decryptedStream); } decryptedTransactionalBatchOperationResults.Add(result); } } return(new EncryptionTransactionalBatchResponse( decryptedTransactionalBatchOperationResults, response, this.cosmosSerializer)); }
public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder <T>( string processorName, ChangesHandler <T> onChangesDelegate) { CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(null); using (diagnosticsContext.CreateScope("GetChangeFeedProcessorBuilder")) { return(this.container.GetChangeFeedProcessorBuilder( processorName, async(IReadOnlyCollection <JObject> documents, CancellationToken cancellationToken) => { List <T> decryptedItems = new List <T>(documents.Count); foreach (JObject document in documents) { EncryptionSettings encryptionSettings = await this.GetOrUpdateEncryptionSettingsFromCacheAsync(obsoleteEncryptionSettings: null, cancellationToken: cancellationToken); try { JObject decryptedDocument = await EncryptionProcessor.DecryptAsync( document, encryptionSettings, diagnosticsContext, cancellationToken); decryptedItems.Add(decryptedDocument.ToObject <T>()); } // we cannot rely currently on a specific exception, this is due to the fact that the run time issue can be variable, // we can hit issue with either Json serialization say an item was not encrypted but the policy shows it as encrypted, // or we could hit a MicrosoftDataEncryptionException from MDE lib etc. catch (Exception) { // most likely the encryption policy has changed. encryptionSettings = await this.GetOrUpdateEncryptionSettingsFromCacheAsync( obsoleteEncryptionSettings: encryptionSettings, cancellationToken: cancellationToken); JObject decryptedDocument = await EncryptionProcessor.DecryptAsync( document, encryptionSettings, diagnosticsContext, cancellationToken); decryptedItems.Add(decryptedDocument.ToObject <T>()); } } // Call the original passed in delegate await onChangesDelegate(decryptedItems, cancellationToken); })); } }
private async Task <Stream> DeserializeAndDecryptResponseAsync( Stream content, EncryptionSettings encryptionSettings, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { if (!encryptionSettings.PropertiesToEncrypt.Any()) { return(content); } JObject contentJObj = EncryptionProcessor.BaseSerializer.FromStream <JObject>(content); JArray results = new JArray(); if (!(contentJObj.SelectToken(Constants.DocumentsResourcePropertyName) is JArray documents)) { throw new InvalidOperationException("Feed Response body contract was violated. Feed response did not have an array of Documents. "); } foreach (JToken value in documents) { if (value is not JObject document) { results.Add(value); continue; } JObject decryptedDocument = await EncryptionProcessor.DecryptAsync( document, encryptionSettings, diagnosticsContext, cancellationToken); results.Add(decryptedDocument); } JObject decryptedResponse = new JObject(); foreach (JProperty property in contentJObj.Properties()) { if (property.Name.Equals(Constants.DocumentsResourcePropertyName)) { decryptedResponse.Add(property.Name, (JToken)results); } else { decryptedResponse.Add(property.Name, property.Value); } } return(EncryptionProcessor.BaseSerializer.ToStream(decryptedResponse)); }
private async Task <ResponseMessage> ReplaceItemHelperAsync( Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions, bool decryptResponse, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { if (!(requestOptions is EncryptionItemRequestOptions encryptionItemRequestOptions) || encryptionItemRequestOptions.EncryptionOptions == null) { return(await this.container.ReplaceItemStreamAsync( streamPayload, id, partitionKey, requestOptions, cancellationToken)); } if (partitionKey == null) { throw new NotSupportedException($"{nameof(partitionKey)} cannot be null for operations using {nameof(EncryptionContainer)}."); } streamPayload = await EncryptionProcessor.EncryptAsync( streamPayload, this.Encryptor, encryptionItemRequestOptions.EncryptionOptions, diagnosticsContext, cancellationToken); ResponseMessage responseMessage = await this.container.ReplaceItemStreamAsync( streamPayload, id, partitionKey, requestOptions, cancellationToken); if (decryptResponse) { (responseMessage.Content, _) = await EncryptionProcessor.DecryptAsync( responseMessage.Content, this.Encryptor, diagnosticsContext, cancellationToken); } return(responseMessage); }
private async Task <Stream> DecryptResponseAsync( Stream input, Action <DecryptionResult> DecryptionResultHandler, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { if (input == null) { return(input); } try { return(await EncryptionProcessor.DecryptAsync( input, this.encryptor, diagnosticsContext, cancellationToken)); } catch (Exception exception) { input.Position = 0; if (DecryptionResultHandler == null) { throw; } using (MemoryStream memoryStream = new MemoryStream((int)input.Length)) { input.CopyTo(memoryStream); ArraySegment <byte> encryptedStream; bool wasBufferReturned = memoryStream.TryGetBuffer(out encryptedStream); Debug.Assert(wasBufferReturned); DecryptionResultHandler( DecryptionResult.CreateFailure( encryptedStream, exception)); } input.Position = 0; return(input); } }
private async Task <ResponseMessage> CreateItemHelperAsync( Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions, bool decryptResponse, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { if (!(requestOptions is EncryptionItemRequestOptions encryptionItemRequestOptions) || encryptionItemRequestOptions.EncryptionOptions == null) { return(await this.container.CreateItemStreamAsync( streamPayload, partitionKey, requestOptions, cancellationToken)); } streamPayload = await EncryptionProcessor.EncryptAsync( streamPayload, this.Encryptor, encryptionItemRequestOptions.EncryptionOptions, diagnosticsContext, cancellationToken); ResponseMessage responseMessage = await this.container.CreateItemStreamAsync( streamPayload, partitionKey, requestOptions, cancellationToken); if (decryptResponse) { (responseMessage.Content, _) = await EncryptionProcessor.DecryptAsync( responseMessage.Content, this.Encryptor, diagnosticsContext, cancellationToken); } return(responseMessage); }
internal static async Task <Stream> DeserializeAndDecryptResponseAsync( Stream content, EncryptionSettings encryptionSettings, EncryptionDiagnosticsContext operationDiagnostics, CancellationToken cancellationToken) { if (!encryptionSettings.PropertiesToEncrypt.Any()) { return(content); } operationDiagnostics?.Begin(Constants.DiagnosticsDecryptOperation); JObject contentJObj = EncryptionProcessor.BaseSerializer.FromStream <JObject>(content); if (!(contentJObj.SelectToken(Constants.DocumentsResourcePropertyName) is JArray documents)) { throw new InvalidOperationException("Feed Response body contract was violated. Feed response did not have an array of Documents. "); } int totalPropertiesDecryptedCount = 0; foreach (JToken value in documents) { if (value is not JObject document) { continue; } (_, int propertiesDecrypted) = await EncryptionProcessor.DecryptAsync( document, encryptionSettings, cancellationToken); totalPropertiesDecryptedCount += propertiesDecrypted; } operationDiagnostics?.End(totalPropertiesDecryptedCount); // the contents get decrypted in place by DecryptAsync. return(EncryptionProcessor.BaseSerializer.ToStream(contentJObj)); }
private async Task <Stream> DeserializeAndDecryptResponseAsync( Stream content, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { JObject contentJObj = EncryptionProcessor.BaseSerializer.FromStream <JObject>(content); JArray result = new JArray(); if (!(contentJObj.SelectToken(Constants.DocumentsResourcePropertyName) is JArray documents)) { throw new InvalidOperationException("Feed response Body Contract was violated. Feed response did not have an array of Documents"); } foreach (JToken value in documents) { if (!(value is JObject document)) { result.Add(value); continue; } try { JObject decryptedDocument = await EncryptionProcessor.DecryptAsync( document, this.encryptor, diagnosticsContext, cancellationToken); result.Add(decryptedDocument); } catch (Exception exception) { if (this.decryptionResultHandler == null) { throw; } result.Add(document); MemoryStream memoryStream = EncryptionProcessor.BaseSerializer.ToStream(document); Debug.Assert(memoryStream != null); bool wasBufferReturned = memoryStream.TryGetBuffer(out ArraySegment <byte> encryptedStream); Debug.Assert(wasBufferReturned); this.decryptionResultHandler( DecryptionResult.CreateFailure( encryptedStream, exception)); } } JObject decryptedResponse = new JObject(); foreach (JProperty property in contentJObj.Properties()) { if (property.Name.Equals(Constants.DocumentsResourcePropertyName)) { decryptedResponse.Add(property.Name, (JToken)result); } else { decryptedResponse.Add(property.Name, property.Value); } } return(EncryptionProcessor.BaseSerializer.ToStream(decryptedResponse)); }