private async Task <ProtectedDataEncryptionKey> BuildProtectedDataEncryptionKeyAsync( ClientEncryptionKeyProperties clientEncryptionKeyProperties, EncryptionKeyWrapProvider encryptionKeyWrapProvider, string keyId, CancellationToken cancellationToken) { if (await EncryptionCosmosClient.EncryptionKeyCacheSemaphore.WaitAsync(-1, cancellationToken)) { try { KeyEncryptionKey keyEncryptionKey = KeyEncryptionKey.GetOrCreate( clientEncryptionKeyProperties.EncryptionKeyWrapMetadata.Name, clientEncryptionKeyProperties.EncryptionKeyWrapMetadata.Value, encryptionKeyWrapProvider.EncryptionKeyStoreProviderImpl); ProtectedDataEncryptionKey protectedDataEncryptionKey = ProtectedDataEncryptionKey.GetOrCreate( keyId, keyEncryptionKey, clientEncryptionKeyProperties.WrappedDataEncryptionKey); return(protectedDataEncryptionKey); } finally { EncryptionCosmosClient.EncryptionKeyCacheSemaphore.Release(1); } } throw new InvalidOperationException("Failed to build ProtectedDataEncryptionKey. "); }
/// <summary> /// Initializes a new instance of the <see cref="CosmosDataEncryptionKeyProvider"/> class. /// </summary> /// <param name="encryptionKeyWrapProvider">A provider that will be used to wrap (encrypt) and unwrap (decrypt) data encryption keys for envelope based encryption</param> /// <param name="dekPropertiesTimeToLive">Time to live for DEK properties before having to refresh.</param> public CosmosDataEncryptionKeyProvider( EncryptionKeyWrapProvider encryptionKeyWrapProvider, TimeSpan?dekPropertiesTimeToLive = null) { this.EncryptionKeyWrapProvider = encryptionKeyWrapProvider ?? throw new ArgumentNullException(nameof(encryptionKeyWrapProvider)); this.dataEncryptionKeyContainerCore = new DataEncryptionKeyContainerCore(this); this.DekCache = new DekCache(dekPropertiesTimeToLive); }
public CosmosDataEncryptionKeyProvider( EncryptionKeyWrapProvider encryptionKeyWrapProvider, TimeSpan?dekPropertiesTimeToLive = null) { this.EncryptionKeyWrapProvider = encryptionKeyWrapProvider; this.dataEncryptionKeyContainerCore = new DataEncryptionKeyContainerCore(this); this.DekCache = new DekCache(dekPropertiesTimeToLive); }
/// <summary> /// Get Cosmos Client with Encryption support for performing operations using client-side encryption. /// </summary> /// <param name="cosmosClient">Regular Cosmos Client.</param> /// <param name="encryptionKeyWrapProvider">EncryptionKeyWrapProvider, provider that allows interaction with the master keys.</param> /// <returns> CosmosClient to perform operations supporting client-side encryption / decryption.</returns> public static CosmosClient WithEncryption( this CosmosClient cosmosClient, EncryptionKeyWrapProvider encryptionKeyWrapProvider) { if (encryptionKeyWrapProvider == null) { throw new ArgumentNullException(nameof(encryptionKeyWrapProvider)); } if (cosmosClient == null) { throw new ArgumentNullException(nameof(cosmosClient)); } return(new EncryptionCosmosClient(cosmosClient, encryptionKeyWrapProvider)); }
public EncryptionKeyStoreProviderImpl(EncryptionKeyWrapProvider encryptionKeyWrapProvider) { this.encryptionKeyWrapProvider = encryptionKeyWrapProvider; }
public EncryptionCosmosClient(CosmosClient cosmosClient, EncryptionKeyWrapProvider encryptionKeyWrapProvider) { this.cosmosClient = cosmosClient ?? throw new ArgumentNullException(nameof(cosmosClient)); this.EncryptionKeyWrapProvider = encryptionKeyWrapProvider ?? throw new ArgumentNullException(nameof(encryptionKeyWrapProvider)); this.clientEncryptionKeyPropertiesCacheByKeyId = new AsyncCache <string, ClientEncryptionKeyProperties>(); }
/// <summary> /// Create a Client Encryption Key used to Encrypt data. /// </summary> /// <param name="database">Regular cosmos database.</param> /// <param name="clientEncryptionKeyId"> Client Encryption Key id.</param> /// <param name="dataEncryptionKeyAlgorithm"> Encryption Algorthm. </param> /// <param name="encryptionKeyWrapMetadata"> EncryptionKeyWrapMetadata.</param> /// <param name="cancellationToken"> cancellation token </param> /// <returns>Container to perform operations supporting client-side encryption / decryption.</returns> /// <example> /// This example shows how to create a new Client Encryption Key. /// /// <code language="c#"> /// <![CDATA[ /// ClientEncryptionKeyResponse response = await this.cosmosDatabase.CreateClientEncryptionKeyAsync( /// "testKey", /// DataEncryptionKeyAlgorithm.AEAD_AES_256_CBC_HMAC_SHA256, /// new EncryptionKeyWrapMetadata("metadataName", "MetadataValue")); /// ]]> /// </code> /// </example> public static async Task <ClientEncryptionKeyResponse> CreateClientEncryptionKeyAsync( this Database database, string clientEncryptionKeyId, string dataEncryptionKeyAlgorithm, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); if (string.IsNullOrWhiteSpace(clientEncryptionKeyId)) { throw new ArgumentNullException(nameof(clientEncryptionKeyId)); } if (!string.Equals(dataEncryptionKeyAlgorithm, DataEncryptionKeyAlgorithm.AeadAes256CbcHmacSha256)) { throw new ArgumentException($"Invalid Encryption Algorithm '{dataEncryptionKeyAlgorithm}' passed. Please refer to https://aka.ms/CosmosClientEncryption for more details. "); } if (encryptionKeyWrapMetadata == null) { throw new ArgumentNullException(nameof(encryptionKeyWrapMetadata)); } EncryptionCosmosClient encryptionCosmosClient = database is EncryptionDatabase encryptionDatabase ? encryptionDatabase.EncryptionCosmosClient : throw new ArgumentException("Creating a ClientEncryptionKey resource requires the use of an encryption - enabled client. Please refer to https://aka.ms/CosmosClientEncryption for more details. "); EncryptionKeyWrapProvider encryptionKeyWrapProvider = encryptionCosmosClient.EncryptionKeyWrapProvider; if (!string.Equals(encryptionKeyWrapMetadata.Type, encryptionKeyWrapProvider.ProviderName)) { throw new ArgumentException("The EncryptionKeyWrapMetadata Type value does not match with the ProviderName of EncryptionKeyWrapProvider configured on the Client. Please refer to https://aka.ms/CosmosClientEncryption for more details. "); } KeyEncryptionKey keyEncryptionKey = KeyEncryptionKey.GetOrCreate( encryptionKeyWrapMetadata.Name, encryptionKeyWrapMetadata.Value, encryptionKeyWrapProvider.EncryptionKeyStoreProviderImpl); ProtectedDataEncryptionKey protectedDataEncryptionKey = new ProtectedDataEncryptionKey( clientEncryptionKeyId, keyEncryptionKey); byte[] wrappedDataEncryptionKey = protectedDataEncryptionKey.EncryptedValue; // cache it. ProtectedDataEncryptionKey.GetOrCreate( clientEncryptionKeyId, keyEncryptionKey, wrappedDataEncryptionKey); ClientEncryptionKeyProperties clientEncryptionKeyProperties = new ClientEncryptionKeyProperties( clientEncryptionKeyId, dataEncryptionKeyAlgorithm, wrappedDataEncryptionKey, encryptionKeyWrapMetadata); ClientEncryptionKeyResponse clientEncryptionKeyResponse = await database.CreateClientEncryptionKeyAsync( clientEncryptionKeyProperties, cancellationToken : cancellationToken); return(clientEncryptionKeyResponse); }
/// <summary> /// Rewrap an existing Client Encryption Key. /// </summary> /// <param name="database">Regular cosmos database.</param> /// <param name="clientEncryptionKeyId"> Client Encryption Key id.</param> /// <param name="newEncryptionKeyWrapMetadata"> EncryptionKeyWrapMetadata.</param> /// <param name="cancellationToken"> cancellation token </param> /// <returns>Container to perform operations supporting client-side encryption / decryption.</returns> /// <example> /// This example shows how to rewrap a Client Encryption Key. /// /// <code language="c#"> /// <![CDATA[ /// ClientEncryptionKeyResponse response = await this.cosmosDatabase.RewrapClientEncryptionKeyAsync( /// "keyToRewrap", /// new EncryptionKeyWrapMetadata("metadataName", "UpdatedMetadataValue"))); /// ]]> /// </code> /// </example> public static async Task <ClientEncryptionKeyResponse> RewrapClientEncryptionKeyAsync( this Database database, string clientEncryptionKeyId, EncryptionKeyWrapMetadata newEncryptionKeyWrapMetadata, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); if (string.IsNullOrWhiteSpace(clientEncryptionKeyId)) { throw new ArgumentNullException(nameof(clientEncryptionKeyId)); } if (newEncryptionKeyWrapMetadata == null) { throw new ArgumentNullException(nameof(newEncryptionKeyWrapMetadata)); } ClientEncryptionKey clientEncryptionKey = database.GetClientEncryptionKey(clientEncryptionKeyId); EncryptionCosmosClient encryptionCosmosClient = database is EncryptionDatabase encryptionDatabase ? encryptionDatabase.EncryptionCosmosClient : throw new ArgumentException("Rewraping a ClientEncryptionKey requires the use of an encryption - enabled client. Please refer to https://aka.ms/CosmosClientEncryption for more details. "); EncryptionKeyWrapProvider encryptionKeyWrapProvider = encryptionCosmosClient.EncryptionKeyWrapProvider; if (!string.Equals(newEncryptionKeyWrapMetadata.Type, encryptionKeyWrapProvider.ProviderName)) { throw new ArgumentException("The EncryptionKeyWrapMetadata Type value does not match with the ProviderName of EncryptionKeyWrapProvider configured on the Client. Please refer to https://aka.ms/CosmosClientEncryption for more details. "); } ClientEncryptionKeyProperties clientEncryptionKeyProperties = await clientEncryptionKey.ReadAsync(cancellationToken : cancellationToken); RequestOptions requestOptions = new RequestOptions { IfMatchEtag = clientEncryptionKeyProperties.ETag, }; KeyEncryptionKey keyEncryptionKey = KeyEncryptionKey.GetOrCreate( clientEncryptionKeyProperties.EncryptionKeyWrapMetadata.Name, clientEncryptionKeyProperties.EncryptionKeyWrapMetadata.Value, encryptionKeyWrapProvider.EncryptionKeyStoreProviderImpl); byte[] unwrappedKey = keyEncryptionKey.DecryptEncryptionKey(clientEncryptionKeyProperties.WrappedDataEncryptionKey); keyEncryptionKey = KeyEncryptionKey.GetOrCreate( newEncryptionKeyWrapMetadata.Name, newEncryptionKeyWrapMetadata.Value, encryptionKeyWrapProvider.EncryptionKeyStoreProviderImpl); byte[] rewrappedKey = keyEncryptionKey.EncryptEncryptionKey(unwrappedKey); clientEncryptionKeyProperties = new ClientEncryptionKeyProperties( clientEncryptionKeyId, clientEncryptionKeyProperties.EncryptionAlgorithm, rewrappedKey, newEncryptionKeyWrapMetadata); ClientEncryptionKeyResponse clientEncryptionKeyResponse = await clientEncryptionKey.ReplaceAsync( clientEncryptionKeyProperties, requestOptions, cancellationToken : cancellationToken); return(clientEncryptionKeyResponse); }