public override async Task <ItemResponse <T> > CreateItemAsync <T>(
            T item,
            PartitionKey?partitionKey           = null,
            ItemRequestOptions requestOptions   = null,
            CancellationToken cancellationToken = default)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            if (partitionKey == null)
            {
                throw new NotSupportedException($"{nameof(partitionKey)} cannot be null for operations using {nameof(EncryptionContainer)}.");
            }

            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);

            using (diagnosticsContext.CreateScope("CreateItem"))
            {
                ResponseMessage responseMessage;

                using (Stream itemStream = this.CosmosSerializer.ToStream <T>(item))
                {
                    responseMessage = await this.CreateItemHelperAsync(
                        itemStream,
                        partitionKey.Value,
                        requestOptions,
                        diagnosticsContext,
                        cancellationToken);
                }

                return(this.ResponseFactory.CreateItemResponse <T>(responseMessage));
            }
        }
        public override async Task <ResponseMessage> ReplaceItemStreamAsync(
            Stream streamPayload,
            string id,
            PartitionKey partitionKey,
            ItemRequestOptions requestOptions   = null,
            CancellationToken cancellationToken = default)
        {
            if (id == null)
            {
                throw new ArgumentNullException(nameof(id));
            }

            if (streamPayload == null)
            {
                throw new ArgumentNullException(nameof(streamPayload));
            }

            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);

            using (diagnosticsContext.CreateScope("ReplaceItemStream"))
            {
                return(await this.ReplaceItemHelperAsync(
                           streamPayload,
                           id,
                           partitionKey,
                           requestOptions,
                           diagnosticsContext,
                           cancellationToken));
            }
        }
        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);
            }
        }
Exemple #4
0
        public override async Task <ResponseMessage> ReadNextAsync(CancellationToken cancellationToken = default)
        {
            if (this.feedIterator == null)
            {
                if (this.queryDefinition != null)
                {
                    this.feedIterator = await this.InitializeInternalFeedIteratorAsync(this.queryDefinition);
                }
            }

            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(options: null);

            using (diagnosticsContext.CreateScope("FeedIterator.ReadNext"))
            {
                ResponseMessage responseMessage = await this.feedIterator.ReadNextAsync(cancellationToken);

                if (responseMessage.IsSuccessStatusCode && responseMessage.Content != null)
                {
                    Stream decryptedContent = await this.DeserializeAndDecryptResponseAsync(
                        responseMessage.Content,
                        diagnosticsContext,
                        cancellationToken);

                    return(new DecryptedResponseMessage(responseMessage, decryptedContent));
                }

                return(responseMessage);
            }
        }
        public override TransactionalBatch CreateItemStream(
            Stream streamPayload,
            TransactionalBatchItemRequestOptions requestOptions = null)
        {
            if (requestOptions is EncryptionTransactionalBatchItemRequestOptions encryptionItemRequestOptions &&
                encryptionItemRequestOptions.EncryptionOptions != null)
            {
                CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);
                using (diagnosticsContext.CreateScope("EncryptItemStream"))
                {
                    streamPayload = EncryptionProcessor.EncryptAsync(
                        streamPayload,
                        this.encryptor,
                        encryptionItemRequestOptions.EncryptionOptions,
                        diagnosticsContext,
                        cancellationToken: default).Result;
                }
            }

            this.transactionalBatch = this.transactionalBatch.CreateItemStream(
                streamPayload,
                requestOptions);

            return(this);
        }
        internal async Task <(byte[], EncryptionKeyWrapMetadata, InMemoryRawDek)> WrapAsync(
            string id,
            byte[] key,
            string encryptionAlgorithm,
            EncryptionKeyWrapMetadata metadata,
            CosmosDiagnosticsContext diagnosticsContext,
            CancellationToken cancellationToken)
        {
            EncryptionKeyWrapResult keyWrapResponse;

            using (diagnosticsContext.CreateScope("WrapDataEncryptionKey"))
            {
                keyWrapResponse = await this.DekProvider.EncryptionKeyWrapProvider.WrapKeyAsync(key, metadata, cancellationToken);
            }

            // Verify
            DataEncryptionKeyProperties tempDekProperties = new DataEncryptionKeyProperties(id, encryptionAlgorithm, keyWrapResponse.WrappedDataEncryptionKey, keyWrapResponse.EncryptionKeyWrapMetadata, DateTime.UtcNow);
            InMemoryRawDek roundTripResponse = await this.UnwrapAsync(tempDekProperties, diagnosticsContext, cancellationToken);

            if (!roundTripResponse.DataEncryptionKey.RawKey.SequenceEqual(key))
            {
                throw new InvalidOperationException("The key wrapping provider configured was unable to unwrap the wrapped key correctly.");
            }

            return(keyWrapResponse.WrappedDataEncryptionKey, keyWrapResponse.EncryptionKeyWrapMetadata, roundTripResponse);
        }
        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)
                    {
                        JObject decryptedDocument = await this.EncryptionProcessor.DecryptAsync(
                            document,
                            diagnosticsContext,
                            cancellationToken);

                        decryptedItems.Add(decryptedDocument.ToObject <T>());
                    }

                    // Call the original passed in delegate
                    await onChangesDelegate(decryptedItems, cancellationToken);
                }));
            }
        }
Exemple #8
0
        public async override Task <ResponseMessage> ReadItemStreamAsync(
            string id,
            PartitionKey partitionKey,
            ItemRequestOptions requestOptions   = null,
            CancellationToken cancellationToken = default)
        {
            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);

            using (diagnosticsContext.CreateScope("ReadItemStream"))
            {
                ResponseMessage responseMessage = await this.container.ReadItemStreamAsync(
                    id,
                    partitionKey,
                    requestOptions,
                    cancellationToken);

                Action <DecryptionResult> decryptionErroHandler = null;
                if (requestOptions is EncryptionItemRequestOptions encryptionItemRequestOptions)
                {
                    decryptionErroHandler = encryptionItemRequestOptions.DecryptionResultHandler;
                }

                responseMessage.Content = await this.DecryptResponseAsync(
                    responseMessage.Content,
                    decryptionErroHandler,
                    diagnosticsContext,
                    cancellationToken);

                return(responseMessage);
            }
        }
Exemple #9
0
        public async override Task <ResponseMessage> ReplaceItemStreamAsync(
            Stream streamPayload,
            string id,
            PartitionKey partitionKey,
            ItemRequestOptions requestOptions   = null,
            CancellationToken cancellationToken = default)
        {
            if (id == null)
            {
                throw new ArgumentNullException(nameof(id));
            }

            if (streamPayload == null)
            {
                throw new ArgumentNullException(nameof(streamPayload));
            }

            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);

            using (diagnosticsContext.CreateScope("ReplaceItemStream"))
            {
                if (requestOptions is EncryptionItemRequestOptions encryptionItemRequestOptions)
                {
                    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);

                    responseMessage.Content = await this.DecryptResponseAsync(
                        responseMessage.Content,
                        encryptionItemRequestOptions.DecryptionResultHandler,
                        diagnosticsContext,
                        cancellationToken);

                    return(responseMessage);
                }
                else
                {
                    return(await this.container.ReplaceItemStreamAsync(streamPayload,
                                                                       id,
                                                                       partitionKey,
                                                                       requestOptions,
                                                                       cancellationToken));
                }
            }
        }
Exemple #10
0
        public override TransactionalBatch CreateItemStream(
            Stream streamPayload,
            TransactionalBatchItemRequestOptions requestOptions = null)
        {
            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);

            using (diagnosticsContext.CreateScope("EncryptItemStream"))
            {
                EncryptionSettings encryptionSettings = this.encryptionContainer.GetOrUpdateEncryptionSettingsFromCacheAsync(obsoleteEncryptionSettings: null, cancellationToken: default)
        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 <DataEncryptionKeyProperties> ReadResourceAsync(
     string id,
     CosmosDiagnosticsContext diagnosticsContext,
     CancellationToken cancellationToken)
 {
     using (diagnosticsContext.CreateScope("ReadDataEncryptionKey"))
     {
         return(await this.ReadInternalAsync(
                    id : id,
                    requestOptions : null,
                    diagnosticsContext : diagnosticsContext,
                    cancellationToken : cancellationToken));
     }
 }
Exemple #13
0
        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);

                return(await this.DecryptTransactionalBatchResponseAsync(
                           response,
                           diagnosticsContext,
                           cancellationToken));
            }
        }
Exemple #14
0
        public override async Task <ResponseMessage> CreateItemStreamAsync(
            Stream streamPayload,
            PartitionKey partitionKey,
            ItemRequestOptions requestOptions   = null,
            CancellationToken cancellationToken = default)
        {
            if (streamPayload == null)
            {
                throw new ArgumentNullException(nameof(streamPayload));
            }

            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);

            using (diagnosticsContext.CreateScope("CreateItemStream"))
            {
                if (requestOptions is EncryptionItemRequestOptions encryptionItemRequestOptions)
                {
                    streamPayload = await EncryptionProcessor.EncryptAsync(
                        streamPayload,
                        this.encryptor,
                        encryptionItemRequestOptions.EncryptionOptions,
                        diagnosticsContext,
                        cancellationToken);

                    ResponseMessage responseMessage = await this.container.CreateItemStreamAsync(
                        streamPayload,
                        partitionKey,
                        requestOptions,
                        cancellationToken);

                    responseMessage.Content = await this.DecryptResponseAsync(
                        responseMessage.Content,
                        encryptionItemRequestOptions.DecryptionResultHandler,
                        diagnosticsContext,
                        cancellationToken);

                    return(responseMessage);
                }
                else
                {
                    return(await this.container.CreateItemStreamAsync(
                               streamPayload,
                               partitionKey,
                               requestOptions,
                               cancellationToken));
                }
            }
        }
        public override async Task <ResponseMessage> ReadItemStreamAsync(
            string id,
            PartitionKey partitionKey,
            ItemRequestOptions requestOptions   = null,
            CancellationToken cancellationToken = default)
        {
            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);

            using (diagnosticsContext.CreateScope("ReadItemStream"))
            {
                return(await this.ReadItemHelperAsync(
                           id,
                           partitionKey,
                           requestOptions,
                           diagnosticsContext,
                           cancellationToken));
            }
        }
        internal async Task <InMemoryRawDek> UnwrapAsync(
            DataEncryptionKeyProperties dekProperties,
            CosmosDiagnosticsContext diagnosticsContext,
            CancellationToken cancellationToken)
        {
            EncryptionKeyUnwrapResult unwrapResult;

            using (diagnosticsContext.CreateScope("UnwrapDataEncryptionKey"))
            {
                unwrapResult = await this.DekProvider.EncryptionKeyWrapProvider.UnwrapKeyAsync(
                    dekProperties.WrappedDataEncryptionKey,
                    dekProperties.EncryptionKeyWrapMetadata,
                    cancellationToken);
            }

            DataEncryptionKey dek = DataEncryptionKey.Create(unwrapResult.DataEncryptionKey, dekProperties.EncryptionAlgorithm);

            return(new InMemoryRawDek(dek, unwrapResult.ClientCacheTimeToLive));
        }
        public override async Task <ItemResponse <T> > ReadItemAsync <T>(
            string id,
            PartitionKey partitionKey,
            ItemRequestOptions requestOptions   = null,
            CancellationToken cancellationToken = default)
        {
            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);

            using (diagnosticsContext.CreateScope("ReadItem"))
            {
                ResponseMessage responseMessage;

                if (typeof(T) == typeof(DecryptableItem))
                {
                    responseMessage = await this.ReadItemHelperAsync(
                        id,
                        partitionKey,
                        requestOptions,
                        decryptResponse : false,
                        diagnosticsContext,
                        cancellationToken);

                    DecryptableItemCore decryptableItem = new DecryptableItemCore(
                        EncryptionProcessor.BaseSerializer.FromStream <JObject>(responseMessage.Content),
                        this.Encryptor,
                        this.CosmosSerializer);

                    return(new EncryptionItemResponse <T>(
                               responseMessage,
                               (T)(object)decryptableItem));
                }

                responseMessage = await this.ReadItemHelperAsync(
                    id,
                    partitionKey,
                    requestOptions,
                    decryptResponse : true,
                    diagnosticsContext,
                    cancellationToken);

                return(this.ResponseFactory.CreateItemResponse <T>(responseMessage));
            }
        }
        public override async Task <ResponseMessage> ReadNextAsync(CancellationToken cancellationToken = default)
        {
            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(options: null);

            using (diagnosticsContext.CreateScope("FeedIterator.ReadNext"))
            {
                EncryptionSettings encryptionSettings = await this.encryptionContainer.GetOrUpdateEncryptionSettingsFromCacheAsync(obsoleteEncryptionSettings : null, cancellationToken : cancellationToken);

                encryptionSettings.SetRequestHeaders(this.requestOptions);

                ResponseMessage responseMessage = await this.feedIterator.ReadNextAsync(cancellationToken);

                // check for Bad Request and Wrong RID intended and update the cached RID and Client Encryption Policy.
                if (responseMessage.StatusCode == HttpStatusCode.BadRequest &&
                    string.Equals(responseMessage.Headers.Get(Constants.SubStatusHeader), Constants.IncorrectContainerRidSubStatus))
                {
                    await this.encryptionContainer.GetOrUpdateEncryptionSettingsFromCacheAsync(
                        obsoleteEncryptionSettings : encryptionSettings,
                        cancellationToken : cancellationToken);

                    throw new CosmosException(
                              "Operation has failed due to a possible mismatch in Client Encryption Policy configured on the container. Please refer to https://aka.ms/CosmosClientEncryption for more details. " + responseMessage.ErrorMessage,
                              responseMessage.StatusCode,
                              int.Parse(Constants.IncorrectContainerRidSubStatus),
                              responseMessage.Headers.ActivityId,
                              responseMessage.Headers.RequestCharge);
                }

                if (responseMessage.IsSuccessStatusCode && responseMessage.Content != null)
                {
                    Stream decryptedContent = await this.DeserializeAndDecryptResponseAsync(
                        responseMessage.Content,
                        encryptionSettings,
                        diagnosticsContext,
                        cancellationToken);

                    return(new DecryptedResponseMessage(responseMessage, decryptedContent));
                }

                return(responseMessage);
            }
        }
        public override async Task <ItemResponse <T> > ReadItemAsync <T>(
            string id,
            PartitionKey partitionKey,
            ItemRequestOptions requestOptions   = null,
            CancellationToken cancellationToken = default)
        {
            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);

            using (diagnosticsContext.CreateScope("ReadItem"))
            {
                ResponseMessage responseMessage;

                responseMessage = await this.ReadItemHelperAsync(
                    id,
                    partitionKey,
                    requestOptions,
                    diagnosticsContext,
                    cancellationToken);

                return(this.ResponseFactory.CreateItemResponse <T>(responseMessage));
            }
        }
Exemple #20
0
        public override TransactionalBatch ReplaceItemStream(
            string id,
            Stream streamPayload,
            TransactionalBatchItemRequestOptions requestOptions = null)
        {
            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);

            using (diagnosticsContext.CreateScope("EncryptItemStream"))
            {
                streamPayload = this.encryptionProcessor.EncryptAsync(
                    streamPayload,
                    diagnosticsContext,
                    default).Result;
            }

            this.transactionalBatch = this.transactionalBatch.ReplaceItemStream(
                id,
                streamPayload,
                requestOptions);

            return(this);
        }
        public override async Task <ItemResponse <T> > CreateItemAsync <T>(
            T item,
            PartitionKey?partitionKey           = null,
            ItemRequestOptions requestOptions   = null,
            CancellationToken cancellationToken = default)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            if (!(requestOptions is EncryptionItemRequestOptions encryptionItemRequestOptions) ||
                encryptionItemRequestOptions.EncryptionOptions == null)
            {
                return(await this.container.CreateItemAsync <T>(
                           item,
                           partitionKey,
                           requestOptions,
                           cancellationToken));
            }

            if (partitionKey == null)
            {
                throw new NotSupportedException($"{nameof(partitionKey)} cannot be null for operations using {nameof(EncryptionContainer)}.");
            }

            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);

            using (diagnosticsContext.CreateScope("CreateItem"))
            {
                ResponseMessage responseMessage;

                if (item is EncryptableItem encryptableItem)
                {
                    using (Stream streamPayload = encryptableItem.ToStream(this.CosmosSerializer))
                    {
                        responseMessage = await this.CreateItemHelperAsync(
                            streamPayload,
                            partitionKey.Value,
                            requestOptions,
                            decryptResponse : false,
                            diagnosticsContext,
                            cancellationToken);
                    }

                    encryptableItem.SetDecryptableItem(
                        EncryptionProcessor.BaseSerializer.FromStream <JObject>(responseMessage.Content),
                        this.Encryptor,
                        this.CosmosSerializer);

                    return(new EncryptionItemResponse <T>(
                               responseMessage,
                               item));
                }
                else
                {
                    using (Stream itemStream = this.CosmosSerializer.ToStream <T>(item))
                    {
                        responseMessage = await this.CreateItemHelperAsync(
                            itemStream,
                            partitionKey.Value,
                            requestOptions,
                            decryptResponse : true,
                            diagnosticsContext,
                            cancellationToken);
                    }

                    return(this.ResponseFactory.CreateItemResponse <T>(responseMessage));
                }
            }
        }