internal async Task <InMemoryRawDek> UnwrapAsync( DataEncryptionKeyProperties dekProperties, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { EncryptionKeyUnwrapResult unwrapResult; if (this.DekProvider.EncryptionKeyWrapProvider == null) { throw new InvalidOperationException($"For use of '{CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized}' algorithm, " + "Encryptor or CosmosDataEncryptionKeyProvider needs to be initialized with EncryptionKeyWrapProvider."); } 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)); }
internal async Task <DataEncryptionKey> FetchUnWrappedLegacySupportedMdeDekAsync( DataEncryptionKeyProperties dekProperties, string encryptionAlgorithm, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { EncryptionKeyUnwrapResult unwrapResult; if (this.DekProvider.EncryptionKeyStoreProvider == null) { throw new InvalidOperationException($"For use of '{CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized}' algorithm based DEK, " + "Encryptor or CosmosDataEncryptionKeyProvider needs to be initialized with EncryptionKeyStoreProvider."); } try { using (diagnosticsContext.CreateScope("UnwrapDataEncryptionKey")) { unwrapResult = await this.UnWrapDekMdeEncAlgoAsync( dekProperties, diagnosticsContext, cancellationToken); } return(DataEncryptionKey.Create( unwrapResult.DataEncryptionKey, encryptionAlgorithm)); } catch (Exception exception) { throw EncryptionExceptionFactory.EncryptionKeyNotFoundException( $"Failed to unwrap Data Encryption Key with id: '{dekProperties.Id}'.", exception); } }
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); }
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, decryptResponse : true, diagnosticsContext, cancellationToken)); } }
internal static async Task <Stream> DeserializeAndDecryptResponseAsync( Stream content, Encryptor encryptor, CancellationToken cancellationToken) { 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"); } foreach (JToken value in documents) { if (!(value is JObject document)) { continue; } CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(null); using (diagnosticsContext.CreateScope("EncryptionProcessor.DeserializeAndDecryptResponseAsync")) { await EncryptionProcessor.DecryptAsync( document, encryptor, diagnosticsContext, cancellationToken); } } // the contents of contentJObj get decrypted in place for MDE algorithm model, and for legacy model _ei property is removed // and corresponding decrypted properties are added back in the documents. return(EncryptionProcessor.BaseSerializer.ToStream(contentJObj)); }
internal async Task <(byte[], EncryptionKeyWrapMetadata, InMemoryRawDek)> WrapAsync( string id, byte[] key, string encryptionAlgorithm, EncryptionKeyWrapMetadata metadata, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { EncryptionKeyWrapResult keyWrapResponse = null; using (diagnosticsContext.CreateScope("WrapDataEncryptionKey")) { keyWrapResponse = string.Equals(encryptionAlgorithm, CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized) && this.DekProvider.EncryptionKeyWrapProvider != null ? await this.DekProvider.EncryptionKeyWrapProvider.WrapKeyAsync(key, metadata, cancellationToken) : string.Equals(encryptionAlgorithm, CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized) && this.DekProvider.MdeKeyWrapProvider != null ? await this.DekProvider.MdeKeyWrapProvider.WrapKeyAsync(key, metadata, cancellationToken) : throw new ArgumentException(string.Format( "Unsupported encryption algorithm {0}." + " Please initialize the Encryptor or CosmosDataEncryptionKeyProvider with an implementation of the EncryptionKeyStoreProvider / EncryptionKeyWrapProvider.", encryptionAlgorithm)); } // Verify DataEncryptionKeyProperties tempDekProperties = new DataEncryptionKeyProperties( id, encryptionAlgorithm, keyWrapResponse.WrappedDataEncryptionKey, keyWrapResponse.EncryptionKeyWrapMetadata, DateTime.UtcNow); byte[] rawKey = null; InMemoryRawDek roundTripResponse = null; if (string.Equals(encryptionAlgorithm, CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized)) { roundTripResponse = await this.UnwrapAsync(tempDekProperties, diagnosticsContext, cancellationToken); rawKey = roundTripResponse.DataEncryptionKey.RawKey; } else if (string.Equals(encryptionAlgorithm, CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized)) { EncryptionKeyUnwrapResult unwrapResult = await this.UnWrapDekMdeEncAlgoAsync( tempDekProperties, diagnosticsContext, cancellationToken); rawKey = unwrapResult.DataEncryptionKey; } if (!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); }
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)); } }
internal static async Task <Stream> DeserializeAndDecryptResponseAsync( Stream content, Encryptor encryptor, 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; } CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(null); using (diagnosticsContext.CreateScope("EncryptionProcessor.DeserializeAndDecryptResponseAsync")) { (JObject decryptedDocument, DecryptionContext _) = await EncryptionProcessor.DecryptAsync( document, encryptor, diagnosticsContext, cancellationToken); result.Add(decryptedDocument); } } 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)); }
private async Task <ItemResponse <DataEncryptionKeyProperties> > ReadInternalAsync( string id, ItemRequestOptions requestOptions, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { using (diagnosticsContext.CreateScope("ReadInternalAsync")) { return(await this.DekProvider.Container.ReadItemAsync <DataEncryptionKeyProperties>( id, new PartitionKey(id), requestOptions, 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); return(await this.DecryptTransactionalBatchResponseAsync( response, diagnosticsContext, cancellationToken)); } }
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> decryptItems = new List <T>(documents.Count); if (typeof(T) == typeof(DecryptableItem)) { foreach (JToken value in documents) { DecryptableItemCore item = new DecryptableItemCore( value, this.Encryptor, this.CosmosSerializer); decryptItems.Add((T)(object)item); } } else { foreach (JObject document in documents) { (JObject decryptedDocument, DecryptionContext _) = await EncryptionProcessor.DecryptAsync( document, this.Encryptor, diagnosticsContext, cancellationToken); decryptItems.Add(decryptedDocument.ToObject <T>()); } } // Call the original passed in delegate await onChangesDelegate(decryptItems, 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, decryptResponse : true, diagnosticsContext, cancellationToken)); } }
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")) { ResponseMessage responseMessage = await this.feedIterator.ReadNextAsync(cancellationToken); if (responseMessage.IsSuccessStatusCode && responseMessage.Content != null) { Stream decryptedContent = await EncryptionProcessor.DeserializeAndDecryptResponseAsync( responseMessage.Content, this.encryptor, cancellationToken); return(new DecryptedResponseMessage(responseMessage, decryptedContent)); } return(responseMessage); } }
private async Task <EncryptionKeyUnwrapResult> UnWrapDekMdeEncAlgoAsync( DataEncryptionKeyProperties dekProperties, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { EncryptionKeyUnwrapResult unwrapResult; if (this.DekProvider.MdeKeyWrapProvider == null) { throw new InvalidOperationException($"For use of '{CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized}' algorithm, " + "Encryptor or CosmosDataEncryptionKeyProvider needs to be initialized with EncryptionKeyStoreProvider."); } using (diagnosticsContext.CreateScope("UnwrapDataEncryptionKey")) { unwrapResult = await this.DekProvider.MdeKeyWrapProvider.UnwrapKeyAsync( dekProperties.WrappedDataEncryptionKey, dekProperties.EncryptionKeyWrapMetadata, cancellationToken); } return(unwrapResult); }
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)); } } }