コード例 #1
0
        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);
            }
        }
コード例 #3
0
        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));
        }
コード例 #4
0
        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);
                }));
            }
        }
コード例 #5
0
        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));
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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);
            }
        }
コード例 #8
0
        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);
        }
コード例 #9
0
        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));
        }
コード例 #10
0
        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));
        }