diff --git a/Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/DataEncryptionKeyAlgorithm.cs b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionAlgorithm.cs
similarity index 92%
rename from Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/DataEncryptionKeyAlgorithm.cs
rename to Microsoft.Azure.Cosmos.Encryption/src/EncryptionAlgorithm.cs
index e5216c1eb9..67b91829dd 100644
--- a/Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/DataEncryptionKeyAlgorithm.cs
+++ b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionAlgorithm.cs
@@ -7,7 +7,7 @@ namespace Microsoft.Azure.Cosmos.Encryption
///
/// Represents the encryption algorithms supported for data encryption.
///
- public static class DataEncryptionKeyAlgorithm
+ public static class EncryptionAlgorithm
{
///
/// Represents the authenticated encryption algorithm with associated data as described in
diff --git a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionCosmosClient.cs b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionCosmosClient.cs
index 89dfc4b7bd..9864fbd65f 100644
--- a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionCosmosClient.cs
+++ b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionCosmosClient.cs
@@ -8,6 +8,8 @@ namespace Microsoft.Azure.Cosmos.Encryption
using System.Net;
using System.Threading;
using System.Threading.Tasks;
+ using global::Azure.Core.Cryptography;
+ using Microsoft.Data.Encryption.Cryptography;
///
/// CosmosClient with Encryption support.
@@ -20,14 +22,43 @@ internal sealed class EncryptionCosmosClient : CosmosClient
private readonly AsyncCache clientEncryptionKeyPropertiesCacheByKeyId;
- public EncryptionCosmosClient(CosmosClient cosmosClient, EncryptionKeyWrapProvider encryptionKeyWrapProvider)
+ public EncryptionCosmosClient(
+ CosmosClient cosmosClient,
+ IKeyEncryptionKeyResolver keyEncryptionKeyResolver,
+ string keyEncryptionKeyResolverName,
+ TimeSpan? keyCacheTimeToLive)
{
this.cosmosClient = cosmosClient ?? throw new ArgumentNullException(nameof(cosmosClient));
- this.EncryptionKeyWrapProvider = encryptionKeyWrapProvider ?? throw new ArgumentNullException(nameof(encryptionKeyWrapProvider));
+ this.KeyEncryptionKeyResolver = keyEncryptionKeyResolver ?? throw new ArgumentNullException(nameof(keyEncryptionKeyResolver));
+ this.KeyEncryptionKeyResolverName = keyEncryptionKeyResolverName ?? throw new ArgumentNullException(nameof(keyEncryptionKeyResolverName));
this.clientEncryptionKeyPropertiesCacheByKeyId = new AsyncCache();
+ this.EncryptionKeyStoreProviderImpl = new EncryptionKeyStoreProviderImpl(keyEncryptionKeyResolver, keyEncryptionKeyResolverName);
+
+ keyCacheTimeToLive ??= TimeSpan.FromHours(1);
+
+ if (EncryptionCosmosClient.EncryptionKeyCacheSemaphore.Wait(-1))
+ {
+ try
+ {
+ // We pick the minimum between the existing and passed in value given this is a static cache.
+ // This also means that the maximum cache duration is the originally initialized value for ProtectedDataEncryptionKey.TimeToLive which is 2 hours.
+ if (keyCacheTimeToLive < ProtectedDataEncryptionKey.TimeToLive)
+ {
+ ProtectedDataEncryptionKey.TimeToLive = keyCacheTimeToLive.Value;
+ }
+ }
+ finally
+ {
+ EncryptionCosmosClient.EncryptionKeyCacheSemaphore.Release(1);
+ }
+ }
}
- public EncryptionKeyWrapProvider EncryptionKeyWrapProvider { get; }
+ public EncryptionKeyStoreProviderImpl EncryptionKeyStoreProviderImpl { get; }
+
+ public IKeyEncryptionKeyResolver KeyEncryptionKeyResolver { get; }
+
+ public string KeyEncryptionKeyResolverName { get; }
public override CosmosClientOptions ClientOptions => this.cosmosClient.ClientOptions;
diff --git a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionCosmosClientExtensions.cs b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionCosmosClientExtensions.cs
index ad2077f3dc..164c796d8b 100644
--- a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionCosmosClientExtensions.cs
+++ b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionCosmosClientExtensions.cs
@@ -5,6 +5,7 @@
namespace Microsoft.Azure.Cosmos.Encryption
{
using System;
+ using global::Azure.Core.Cryptography;
using Microsoft.Data.Encryption.Cryptography;
///
@@ -16,15 +17,24 @@ public static class EncryptionCosmosClientExtensions
/// Get Cosmos Client with Encryption support for performing operations using client-side encryption.
///
/// Regular Cosmos Client.
- /// EncryptionKeyWrapProvider, provider that allows interaction with the master keys.
+ /// IKeyEncryptionKeyResolver that allows interaction with the key encryption keys.
+ /// Identifier of the resolver, eg. KeyEncryptionKeyResolverId.AzureKeyVault.
+ /// Time for which raw keys are cached in-memory. Defaults to 1 hour.
/// CosmosClient to perform operations supporting client-side encryption / decryption.
public static CosmosClient WithEncryption(
this CosmosClient cosmosClient,
- EncryptionKeyWrapProvider encryptionKeyWrapProvider)
+ IKeyEncryptionKeyResolver keyEncryptionKeyResolver,
+ string keyEncryptionKeyResolverId,
+ TimeSpan? keyCacheTimeToLive = null)
{
- if (encryptionKeyWrapProvider == null)
+ if (keyEncryptionKeyResolver == null)
{
- throw new ArgumentNullException(nameof(encryptionKeyWrapProvider));
+ throw new ArgumentNullException(nameof(keyEncryptionKeyResolver));
+ }
+
+ if (keyEncryptionKeyResolverId == null)
+ {
+ throw new ArgumentNullException(nameof(keyEncryptionKeyResolverId));
}
if (cosmosClient == null)
@@ -32,7 +42,7 @@ public static CosmosClient WithEncryption(
throw new ArgumentNullException(nameof(cosmosClient));
}
- return new EncryptionCosmosClient(cosmosClient, encryptionKeyWrapProvider);
+ return new EncryptionCosmosClient(cosmosClient, keyEncryptionKeyResolver, keyEncryptionKeyResolverId, keyCacheTimeToLive);
}
}
}
diff --git a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionDatabaseExtensions.cs b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionDatabaseExtensions.cs
index 417c9f3856..f81486b784 100644
--- a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionDatabaseExtensions.cs
+++ b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionDatabaseExtensions.cs
@@ -49,7 +49,7 @@ public static async Task CreateClientEncryptionKeyA
throw new ArgumentNullException(nameof(clientEncryptionKeyId));
}
- if (!string.Equals(dataEncryptionKeyAlgorithm, DataEncryptionKeyAlgorithm.AeadAes256CbcHmacSha256))
+ if (!string.Equals(dataEncryptionKeyAlgorithm, EncryptionAlgorithm.AeadAes256CbcHmacSha256))
{
throw new ArgumentException($"Invalid Encryption Algorithm '{dataEncryptionKeyAlgorithm}' passed. Please refer to https://aka.ms/CosmosClientEncryption for more details. ");
}
@@ -63,9 +63,7 @@ public static async Task CreateClientEncryptionKeyA
? 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))
+ if (!string.Equals(encryptionKeyWrapMetadata.Type, encryptionCosmosClient.KeyEncryptionKeyResolverName))
{
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. ");
}
@@ -73,7 +71,7 @@ public static async Task CreateClientEncryptionKeyA
KeyEncryptionKey keyEncryptionKey = KeyEncryptionKey.GetOrCreate(
encryptionKeyWrapMetadata.Name,
encryptionKeyWrapMetadata.Value,
- encryptionKeyWrapProvider.EncryptionKeyStoreProviderImpl);
+ encryptionCosmosClient.EncryptionKeyStoreProviderImpl);
ProtectedDataEncryptionKey protectedDataEncryptionKey = new ProtectedDataEncryptionKey(
clientEncryptionKeyId,
@@ -143,9 +141,7 @@ public static async Task RewrapClientEncryptionKeyA
? 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))
+ if (!string.Equals(newEncryptionKeyWrapMetadata.Type, encryptionCosmosClient.KeyEncryptionKeyResolverName))
{
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. ");
}
@@ -160,14 +156,14 @@ public static async Task RewrapClientEncryptionKeyA
KeyEncryptionKey keyEncryptionKey = KeyEncryptionKey.GetOrCreate(
clientEncryptionKeyProperties.EncryptionKeyWrapMetadata.Name,
clientEncryptionKeyProperties.EncryptionKeyWrapMetadata.Value,
- encryptionKeyWrapProvider.EncryptionKeyStoreProviderImpl);
+ encryptionCosmosClient.EncryptionKeyStoreProviderImpl);
byte[] unwrappedKey = keyEncryptionKey.DecryptEncryptionKey(clientEncryptionKeyProperties.WrappedDataEncryptionKey);
keyEncryptionKey = KeyEncryptionKey.GetOrCreate(
newEncryptionKeyWrapMetadata.Name,
newEncryptionKeyWrapMetadata.Value,
- encryptionKeyWrapProvider.EncryptionKeyStoreProviderImpl);
+ encryptionCosmosClient.EncryptionKeyStoreProviderImpl);
byte[] rewrappedKey = keyEncryptionKey.EncryptEncryptionKey(unwrappedKey);
diff --git a/Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/EncryptionKeyStoreProviderImpl.cs b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionKeyStoreProviderImpl.cs
similarity index 61%
rename from Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/EncryptionKeyStoreProviderImpl.cs
rename to Microsoft.Azure.Cosmos.Encryption/src/EncryptionKeyStoreProviderImpl.cs
index 18ca46c344..5b23d37635 100644
--- a/Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/EncryptionKeyStoreProviderImpl.cs
+++ b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionKeyStoreProviderImpl.cs
@@ -5,33 +5,36 @@
namespace Microsoft.Azure.Cosmos.Encryption
{
using System;
+ using global::Azure.Core.Cryptography;
using Microsoft.Data.Encryption.Cryptography;
///
/// The purpose/intention to introduce this class is to utilize the cache provide by the abstract class. This class basically
- /// redirects all the corresponding calls to 's overridden methods and thus allowing us
+ /// redirects all the corresponding calls to 's methods and thus allowing us
/// to utilize the virtual method to access the cache.
///
/// Note: Since and methods are not exposed, is not supported either.
///
///
/// The call hierarchy is as follows. Note, all core MDE API's used in internal cosmos encryption code are passed an EncryptionKeyStoreProviderImpl object.
- /// ProtectedDataEncryptionKey -> KeyEncryptionKey(containing EncryptionKeyStoreProviderImpl object) -> EncryptionKeyStoreProviderImpl.WrapKey -> this.EncryptionKeyWrapProvider.WrapKeyAsync
- /// ProtectedDataEncryptionKey -> KeyEncryptionKey(containing EncryptionKeyStoreProviderImpl object) -> EncryptionKeyStoreProviderImpl.UnWrapKey -> this.EncryptionKeyWrapProvider.UnwrapKeyAsync
+ /// ProtectedDataEncryptionKey -> KeyEncryptionKey(containing EncryptionKeyStoreProviderImpl object) -> EncryptionKeyStoreProviderImpl.WrapKey -> this.keyEncryptionKeyResolver.WrapKey
+ /// ProtectedDataEncryptionKey -> KeyEncryptionKey(containing EncryptionKeyStoreProviderImpl object) -> EncryptionKeyStoreProviderImpl.UnWrapKey -> this.keyEncryptionKeyResolver.UnwrapKey
///
///
internal class EncryptionKeyStoreProviderImpl : EncryptionKeyStoreProvider
{
- private readonly EncryptionKeyWrapProvider encryptionKeyWrapProvider;
+ private readonly IKeyEncryptionKeyResolver keyEncryptionKeyResolver;
- public EncryptionKeyStoreProviderImpl(EncryptionKeyWrapProvider encryptionKeyWrapProvider)
+ public EncryptionKeyStoreProviderImpl(IKeyEncryptionKeyResolver keyEncryptionKeyResolver, string providerName)
{
- this.encryptionKeyWrapProvider = encryptionKeyWrapProvider;
+ this.keyEncryptionKeyResolver = keyEncryptionKeyResolver;
+ this.ProviderName = providerName;
+ this.DataEncryptionKeyCacheTimeToLive = TimeSpan.Zero;
}
- public override string ProviderName => this.encryptionKeyWrapProvider.ProviderName;
+ public override string ProviderName { get; }
- public override byte[] UnwrapKey(string encryptionKeyId, Data.Encryption.Cryptography.KeyEncryptionKeyAlgorithm algorithm, byte[] encryptedKey)
+ public override byte[] UnwrapKey(string encryptionKeyId, KeyEncryptionKeyAlgorithm algorithm, byte[] encryptedKey)
{
// since we do not expose GetOrCreateDataEncryptionKey we first look up the cache.
// Cache miss results in call to UnWrapCore which updates the cache after UnwrapKeyAsync is called.
@@ -40,19 +43,27 @@ public override byte[] UnwrapKey(string encryptionKeyId, Data.Encryption.Cryptog
// delegate that is called by GetOrCreateDataEncryptionKey, which unwraps the key and updates the cache in case of cache miss.
byte[] UnWrapKeyCore()
{
- return this.encryptionKeyWrapProvider.UnwrapKeyAsync(encryptionKeyId, algorithm.ToString(), encryptedKey)
- .ConfigureAwait(false)
- .GetAwaiter()
- .GetResult();
+ return this.keyEncryptionKeyResolver
+ .Resolve(encryptionKeyId)
+ .UnwrapKey(EncryptionKeyStoreProviderImpl.GetNameForKeyEncryptionKeyAlgorithm(algorithm), encryptedKey);
}
}
- public override byte[] WrapKey(string encryptionKeyId, Data.Encryption.Cryptography.KeyEncryptionKeyAlgorithm algorithm, byte[] key)
+ public override byte[] WrapKey(string encryptionKeyId, KeyEncryptionKeyAlgorithm algorithm, byte[] key)
{
- return this.encryptionKeyWrapProvider.WrapKeyAsync(encryptionKeyId, algorithm.ToString(), key)
- .ConfigureAwait(false)
- .GetAwaiter()
- .GetResult();
+ return this.keyEncryptionKeyResolver
+ .Resolve(encryptionKeyId)
+ .WrapKey(EncryptionKeyStoreProviderImpl.GetNameForKeyEncryptionKeyAlgorithm(algorithm), key);
+ }
+
+ private static string GetNameForKeyEncryptionKeyAlgorithm(KeyEncryptionKeyAlgorithm algorithm)
+ {
+ if (algorithm == KeyEncryptionKeyAlgorithm.RSA_OAEP)
+ {
+ return "RSA-OAEP";
+ }
+
+ throw new InvalidOperationException(string.Format("Unexpected algorithm {0}", algorithm));
}
///
@@ -60,7 +71,7 @@ public override byte[] WrapKey(string encryptionKeyId, Data.Encryption.Cryptogra
///
public override byte[] Sign(string encryptionKeyId, bool allowEnclaveComputations)
{
- throw new NotSupportedException("The Sign operation is not supported. ");
+ throw new NotSupportedException("The Sign operation is not supported.");
}
///
@@ -68,7 +79,7 @@ public override byte[] Sign(string encryptionKeyId, bool allowEnclaveComputation
///
public override bool Verify(string encryptionKeyId, bool allowEnclaveComputations, byte[] signature)
{
- throw new NotSupportedException("The Verify operation is not supported. ");
+ throw new NotSupportedException("The Verify operation is not supported.");
}
}
}
diff --git a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionSettingForProperty.cs b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionSettingForProperty.cs
index bf7103faa2..582b92aa7c 100644
--- a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionSettingForProperty.cs
+++ b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionSettingForProperty.cs
@@ -50,7 +50,6 @@ public async Task BuildEncryptionAlgori
// Here a request is sent out to unwrap using the Master Key configured via the Key Encryption Key.
protectedDataEncryptionKey = await this.BuildProtectedDataEncryptionKeyAsync(
clientEncryptionKeyProperties,
- this.encryptionContainer.EncryptionCosmosClient.EncryptionKeyWrapProvider,
this.ClientEncryptionKeyId,
cancellationToken);
}
@@ -73,7 +72,6 @@ public async Task BuildEncryptionAlgori
// try to build the ProtectedDataEncryptionKey. If it fails, try to force refresh the gateway cache and get the latest client encryption key.
protectedDataEncryptionKey = await this.BuildProtectedDataEncryptionKeyAsync(
clientEncryptionKeyProperties,
- this.encryptionContainer.EncryptionCosmosClient.EncryptionKeyWrapProvider,
this.ClientEncryptionKeyId,
cancellationToken);
}
@@ -141,7 +139,6 @@ private async Task ForceRefreshGatewayCacheAndBuildP
ProtectedDataEncryptionKey protectedDataEncryptionKey = await this.BuildProtectedDataEncryptionKeyAsync(
clientEncryptionKeyProperties,
- this.encryptionContainer.EncryptionCosmosClient.EncryptionKeyWrapProvider,
this.ClientEncryptionKeyId,
cancellationToken);
@@ -150,7 +147,6 @@ private async Task ForceRefreshGatewayCacheAndBuildP
private async Task BuildProtectedDataEncryptionKeyAsync(
ClientEncryptionKeyProperties clientEncryptionKeyProperties,
- EncryptionKeyWrapProvider encryptionKeyWrapProvider,
string keyId,
CancellationToken cancellationToken)
{
@@ -161,7 +157,7 @@ private async Task BuildProtectedDataEncryptionKeyAs
KeyEncryptionKey keyEncryptionKey = KeyEncryptionKey.GetOrCreate(
clientEncryptionKeyProperties.EncryptionKeyWrapMetadata.Name,
clientEncryptionKeyProperties.EncryptionKeyWrapMetadata.Value,
- encryptionKeyWrapProvider.EncryptionKeyStoreProviderImpl);
+ this.encryptionContainer.EncryptionCosmosClient.EncryptionKeyStoreProviderImpl);
ProtectedDataEncryptionKey protectedDataEncryptionKey = ProtectedDataEncryptionKey.GetOrCreate(
keyId,
diff --git a/Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/EncryptionType.cs b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionType.cs
similarity index 100%
rename from Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/EncryptionType.cs
rename to Microsoft.Azure.Cosmos.Encryption/src/EncryptionType.cs
diff --git a/Microsoft.Azure.Cosmos.Encryption/src/KeyEncryptionKeyResolverName.cs b/Microsoft.Azure.Cosmos.Encryption/src/KeyEncryptionKeyResolverName.cs
new file mode 100644
index 0000000000..b37d050146
--- /dev/null
+++ b/Microsoft.Azure.Cosmos.Encryption/src/KeyEncryptionKeyResolverName.cs
@@ -0,0 +1,19 @@
+//------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------
+
+namespace Microsoft.Azure.Cosmos.Encryption
+{
+ using global::Azure.Core.Cryptography;
+
+ ///
+ /// Has constants for names of well-known implementations of .
+ ///
+ public static class KeyEncryptionKeyResolverName
+ {
+ ///
+ /// IKeyEncryptionKeyResolver implementation for keys in Azure Key Vault.
+ ///
+ public const string AzureKeyVault = "AZURE_KEY_VAULT";
+ }
+}
diff --git a/Microsoft.Azure.Cosmos.Encryption/src/MdeSrc/AzureKeyVaultProvider/AzureKeyVaultKeyStoreProvider.cs b/Microsoft.Azure.Cosmos.Encryption/src/MdeSrc/AzureKeyVaultProvider/AzureKeyVaultKeyStoreProvider.cs
deleted file mode 100644
index 2c01f4fb17..0000000000
--- a/Microsoft.Azure.Cosmos.Encryption/src/MdeSrc/AzureKeyVaultProvider/AzureKeyVaultKeyStoreProvider.cs
+++ /dev/null
@@ -1,352 +0,0 @@
-//------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------
-
-// This file isn't generated, but this comment is necessary to exclude it from StyleCop analysis.
-//
-
-using System;
-using System.Linq;
-using System.Text;
-using Azure.Core;
-using Azure.Security.KeyVault.Keys.Cryptography;
-using Microsoft.Data.Encryption.Cryptography;
-
-using static Microsoft.Data.Encryption.Resources.Strings;
-
-namespace Microsoft.Data.Encryption.AzureKeyVaultProvider
-{
- ///
- /// Implementation of key encryption key store provider that allows client applications to access data when a
- /// key encryption key is stored in Microsoft Azure Key Vault.
- ///
- internal class AzureKeyVaultKeyStoreProvider : EncryptionKeyStoreProvider
- {
- #region Properties
-
- ///
- /// Name of the Encryption Key Store Provider implemetation
- ///
- public override string ProviderName { get; } = "AZURE_KEY_VAULT";
-
- ///
- /// Key storage and cryptography client
- ///
- private KeyCryptographer KeyCryptographer { get; set; }
-
- ///
- /// Algorithm version
- ///
- private readonly static byte[] firstVersion = new byte[] { 0x01 };
-
- private readonly static KeyWrapAlgorithm keyWrapAlgorithm = KeyWrapAlgorithm.RsaOaep;
-
- ///
- /// List of Trusted Endpoints
- ///
- public readonly string[] TrustedEndPoints;
-
- #endregion
-
- #region Constructors
- ///
- /// Constructor that takes an implementation of Token Credential that is capable of providing an OAuth Token.
- ///
- ///
- public AzureKeyVaultKeyStoreProvider(TokenCredential tokenCredential) :
- this(tokenCredential, Constants.AzureKeyVaultPublicDomainNames)
- { }
-
- ///
- /// Constructor that takes an implementation of Token Credential that is capable of providing an OAuth Token and a trusted endpoint.
- ///
- /// Instance of an implementation of Token Credential that is capable of providing an OAuth Token.
- /// TrustedEndpoint is used to validate the key encryption key path.
- public AzureKeyVaultKeyStoreProvider(TokenCredential tokenCredential, string trustedEndPoint) :
- this(tokenCredential, new[] { trustedEndPoint })
- { }
-
- ///
- /// Constructor that takes an instance of an implementation of Token Credential that is capable of providing an OAuth Token
- /// and an array of trusted endpoints.
- ///
- /// Instance of an implementation of Token Credential that is capable of providing an OAuth Token
- /// TrustedEndpoints are used to validate the key encryption key path
- public AzureKeyVaultKeyStoreProvider(TokenCredential tokenCredential, string[] trustedEndPoints)
- {
- tokenCredential.ValidateNotNull(nameof(tokenCredential));
- trustedEndPoints.ValidateNotNull(nameof(trustedEndPoints));
- trustedEndPoints.ValidateNotEmpty(nameof(trustedEndPoints));
- trustedEndPoints.ValidateNotNullOrWhitespaceForEach(nameof(trustedEndPoints));
-
- KeyCryptographer = new KeyCryptographer(tokenCredential);
- TrustedEndPoints = trustedEndPoints;
- }
- #endregion
-
- #region Public methods
-
- ///
- /// Uses an asymmetric key identified by the key path to sign the key encryption key metadata consisting of (keyEncryptionKeyPath, allowEnclaveComputations bit, providerName).
- ///
- /// Identifier of an asymmetric key in Azure Key Vault.
- /// Indicates whether the key encryption key supports enclave computations.
- /// The signature of the key encryption key metadata.
- public override byte[] Sign(string encryptionKeyId, bool allowEnclaveComputations)
- {
- ValidateNonEmptyAKVPath(encryptionKeyId, isSystemOp: false);
-
- // Also validates key is of RSA type.
- KeyCryptographer.AddKey(encryptionKeyId);
- byte[] message = CompileKeyEncryptionKeyMetadata(encryptionKeyId, allowEnclaveComputations);
- return KeyCryptographer.SignData(message, encryptionKeyId);
- }
-
- ///
- /// Uses an asymmetric key identified by the key path to verify the key encryption key metadata consisting of (keyEncryptionKeyPath, allowEnclaveComputations bit, providerName).
- ///
- /// Identifier of an asymmetric key in Azure Key Vault
- /// Indicates whether the key encryption key supports enclave computations.
- /// The signature of the key encryption key metadata.
- /// Boolean indicating whether the key encryption key metadata can be verified based on the provided signature.
- public override bool Verify(string encryptionKeyId, bool allowEnclaveComputations, byte[] signature)
- {
- ValidateNonEmptyAKVPath(encryptionKeyId, isSystemOp: true);
-
- var key = Tuple.Create(encryptionKeyId, allowEnclaveComputations, signature.ToHexString());
- return GetOrCreateSignatureVerificationResult(key, VerifyKeyEncryptionKeyMetadata);
-
- bool VerifyKeyEncryptionKeyMetadata()
- {
- // Also validates key is of RSA type.
- KeyCryptographer.AddKey(encryptionKeyId);
- byte[] message = CompileKeyEncryptionKeyMetadata(encryptionKeyId, allowEnclaveComputations);
- return KeyCryptographer.VerifyData(message, signature, encryptionKeyId);
- }
- }
-
- ///
- /// This function uses the asymmetric key specified by the key path
- /// and decrypts an encrypted data dencryption key with RSA encryption algorithm.
- ///
- /// Identifier of an asymmetric key in Azure Key Vault
- /// The encryption algorithm.
- /// The ciphertext key.
- /// Plain text data encryption key
- public override byte[] UnwrapKey(string encryptionKeyId, KeyEncryptionKeyAlgorithm algorithm, byte[] encryptedKey)
- {
- // Validate the input parameters
- ValidateNonEmptyAKVPath(encryptionKeyId, isSystemOp: true);
- ValidateEncryptionAlgorithm(algorithm);
- encryptedKey.ValidateNotNull(nameof(encryptedKey));
- encryptedKey.ValidateNotEmpty(nameof(encryptedKey));
- ValidateVersionByte(encryptedKey[0], firstVersion[0]);
-
- return GetOrCreateDataEncryptionKey(encryptedKey.ToHexString(), DecryptEncryptionKey);
-
- byte[] DecryptEncryptionKey()
- {
- // Also validates whether the key is RSA one or not and then get the key size
- KeyCryptographer.AddKey(encryptionKeyId);
-
- int keySizeInBytes = KeyCryptographer.GetKeySize(encryptionKeyId);
-
- // Get key path length
- int currentIndex = firstVersion.Length;
- ushort keyPathLength = BitConverter.ToUInt16(encryptedKey, currentIndex);
- currentIndex += sizeof(ushort);
-
- // Get ciphertext length
- ushort cipherTextLength = BitConverter.ToUInt16(encryptedKey, currentIndex);
- currentIndex += sizeof(ushort);
-
- // Skip KeyPath
- // KeyPath exists only for troubleshooting purposes and doesnt need validation.
- currentIndex += keyPathLength;
-
- // validate the ciphertext length
- if (cipherTextLength != keySizeInBytes)
- {
- throw new MicrosoftDataEncryptionException(InvalidCiphertextLengthTemplate.FormatInvariant(cipherTextLength, keySizeInBytes, encryptionKeyId));
- }
-
- // Validate the signature length
- int signatureLength = encryptedKey.Length - currentIndex - cipherTextLength;
- if (signatureLength != keySizeInBytes)
- {
- throw new MicrosoftDataEncryptionException(InvalidSignatureLengthTemplate.FormatInvariant(signatureLength, keySizeInBytes, encryptionKeyId));
- }
-
- // Get ciphertext
- byte[] cipherText = encryptedKey.Skip(currentIndex).Take(cipherTextLength).ToArray();
- currentIndex += cipherTextLength;
-
- // Get signature
- byte[] signature = encryptedKey.Skip(currentIndex).Take(signatureLength).ToArray();
-
- // Compute the message to validate the signature
- byte[] message = encryptedKey.Take(encryptedKey.Length - signatureLength).ToArray();
-
- if (null == message)
- {
- throw new MicrosoftDataEncryptionException(NullHash);
- }
-
- if (!KeyCryptographer.VerifyData(message, signature, encryptionKeyId))
- {
- throw new MicrosoftDataEncryptionException(InvalidSignatureTemplate.FormatInvariant(encryptionKeyId));
- }
-
- return KeyCryptographer.UnwrapKey(keyWrapAlgorithm, cipherText, encryptionKeyId);
- }
- }
-
- ///
- /// This function uses the asymmetric key specified by the key path
- /// and encrypts an unencrypted data encryption key with RSA encryption algorithm.
- ///
- /// Identifier of an asymmetric key in Azure Key Vault
- /// The encryption algorithm.
- /// The plaintext key.
- /// Encrypted data encryption key
- public override byte[] WrapKey(string encryptionKeyId, KeyEncryptionKeyAlgorithm algorithm, byte[] key)
- {
- // Validate the input parameters
- ValidateNonEmptyAKVPath(encryptionKeyId, isSystemOp: true);
- ValidateEncryptionAlgorithm(algorithm);
- key.ValidateNotNull(nameof(key));
- ValidateDataEncryptionKeyNotEmpty(key);
-
- // Also validates whether the key is RSA one or not and then get the key size
- KeyCryptographer.AddKey(encryptionKeyId);
- int keySizeInBytes = KeyCryptographer.GetKeySize(encryptionKeyId);
-
- // Construct the encryptedDataEncryptionKey
- // Format is
- // firstVersion + keyPathLength + ciphertextLength + keyPath + ciphertext + signature
-
- // Get the Unicode encoded bytes of cultureinvariant lower case keyEncryptionKeyPath
- byte[] keyEncryptionKeyPathBytes = Encoding.Unicode.GetBytes(encryptionKeyId.ToLowerInvariant());
- byte[] keyPathLength = BitConverter.GetBytes((short)keyEncryptionKeyPathBytes.Length);
-
- // Encrypt the plain text
- byte[] cipherText = KeyCryptographer.WrapKey(keyWrapAlgorithm, key, encryptionKeyId);
- byte[] cipherTextLength = BitConverter.GetBytes((short)cipherText.Length);
-
- if (cipherText.Length != keySizeInBytes)
- {
- throw new MicrosoftDataEncryptionException(CipherTextLengthMismatch);
- }
-
- // Compute message
- // SHA-2-256(version + keyPathLength + ciphertextLength + keyPath + ciphertext)
- byte[] message = firstVersion.Concat(keyPathLength).Concat(cipherTextLength).Concat(keyEncryptionKeyPathBytes).Concat(cipherText).ToArray();
-
- // Sign the message
- byte[] signature = KeyCryptographer.SignData(message, encryptionKeyId);
-
- if (signature.Length != keySizeInBytes)
- {
- throw new MicrosoftDataEncryptionException(HashLengthMismatch);
- }
-
- ValidateSignature(encryptionKeyId, message, signature);
-
- return message.Concat(signature).ToArray();
- }
-
- #endregion
-
- #region Private methods
-
- private void ValidateDataEncryptionKeyNotEmpty(byte[] encryptionKey)
- {
- if (encryptionKey.Length == 0)
- {
- throw new MicrosoftDataEncryptionException(EmptyDataEncryptionKey);
- }
- }
-
- ///
- /// Checks if the Azure Key Vault key path is Empty or Null (and raises exception if they are).
- ///
- internal void ValidateNonEmptyAKVPath(string keyEncryptionKeyPath, bool isSystemOp)
- {
- // throw appropriate error if keyEncryptionKeyPath is null or empty
- if (string.IsNullOrWhiteSpace(keyEncryptionKeyPath))
- {
- string errorMessage = null == keyEncryptionKeyPath
- ? NullAkvPath
- : InvalidAkvPathTemplate.FormatInvariant(keyEncryptionKeyPath);
-
- if (isSystemOp)
- {
- throw new MicrosoftDataEncryptionException(errorMessage);
- }
-
- throw new MicrosoftDataEncryptionException(errorMessage);
- }
-
-
- if (!Uri.TryCreate(keyEncryptionKeyPath, UriKind.Absolute, out Uri parsedUri) || parsedUri.Segments.Length < 3)
- {
- // Return an error indicating that the AKV url is invalid.
- throw new MicrosoftDataEncryptionException(InvalidAkvUrlTemplate.FormatInvariant(keyEncryptionKeyPath));
- }
-
- // A valid URI.
- // Check if it is pointing to trusted endpoint.
- foreach (string trustedEndPoint in TrustedEndPoints)
- {
- if (parsedUri.Host.EndsWith(trustedEndPoint, StringComparison.OrdinalIgnoreCase))
- {
- return;
- }
- }
-
- // Return an error indicating that the AKV url is invalid.
- throw new MicrosoftDataEncryptionException(InvalidAkvKeyPathTrustedTemplate.FormatInvariant(keyEncryptionKeyPath, string.Join(", ", TrustedEndPoints.ToArray())));
- }
-
- private void ValidateSignature(string keyEncryptionKeyPath, byte[] message, byte[] signature)
- {
- if (!KeyCryptographer.VerifyData(message, signature, keyEncryptionKeyPath))
- {
- throw new MicrosoftDataEncryptionException(InvalidSignature);
- }
- }
-
- private byte[] CompileKeyEncryptionKeyMetadata(string keyEncryptionKeyPath, bool allowEnclaveComputations)
- {
- string keyEncryptionKeyMetadata = ProviderName + keyEncryptionKeyPath + allowEnclaveComputations;
- return Encoding.Unicode.GetBytes(keyEncryptionKeyMetadata.ToLowerInvariant());
- }
-
-
- internal static void ValidateEncryptionAlgorithm(KeyEncryptionKeyAlgorithm encryptionAlgorithm)
- {
- if (encryptionAlgorithm != KeyEncryptionKeyAlgorithm.RSA_OAEP)
- {
- throw new MicrosoftDataEncryptionException(InvalidKeyAlgorithm.FormatInvariant(encryptionAlgorithm, KeyEncryptionKeyAlgorithm.RSA_OAEP.ToString()));
- }
- }
-
- internal static void ValidateVersionByte(byte encryptedByte, byte firstVersionByte)
- {
- // Validate and decrypt the EncryptedDataEncryptionKey
- // Format is
- // version + keyPathLength + ciphertextLength + keyPath + ciphertext + signature
- //
- // keyPath is present in the encrypted data encryption key for identifying the original source of the asymmetric key pair and
- // we will not validate it against the data contained in the KEK metadata (keyEncryptionKeyPath).
-
- // Validate the version byte
- if (encryptedByte != firstVersionByte)
- {
- throw new MicrosoftDataEncryptionException(InvalidAlgorithmVersionTemplate.FormatInvariant(encryptedByte.ToString(@"X2"), firstVersionByte.ToString("X2")));
- }
- }
-
- #endregion
- }
-}
\ No newline at end of file
diff --git a/Microsoft.Azure.Cosmos.Encryption/src/MdeSrc/AzureKeyVaultProvider/Constants.cs b/Microsoft.Azure.Cosmos.Encryption/src/MdeSrc/AzureKeyVaultProvider/Constants.cs
deleted file mode 100644
index b8db49e2a2..0000000000
--- a/Microsoft.Azure.Cosmos.Encryption/src/MdeSrc/AzureKeyVaultProvider/Constants.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-//------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------
-
-// This file isn't generated, but this comment is necessary to exclude it from StyleCop analysis.
-//
-
-namespace Microsoft.Data.Encryption.AzureKeyVaultProvider
-{
- internal static class Constants
- {
- ///
- /// Azure Key Vault Domain Name
- ///
- internal static readonly string[] AzureKeyVaultPublicDomainNames = new string[] {
- @"vault.azure.net", // default
- @"vault.azure.cn", // Azure China
- @"vault.usgovcloudapi.net", // US Government
- @"vault.microsoftazure.de", // Azure Germany
- @"managedhsm.azure.net", // public HSM vault
- @"managedhsm.azure.cn", // Azure China HSM vault
- @"managedhsm.usgovcloudapi.net", // US Government HSM vault
- @"managedhsm.microsoftazure.de" // Azure Germany HSM vault
- };
- }
-}
diff --git a/Microsoft.Azure.Cosmos.Encryption/src/MdeSrc/AzureKeyVaultProvider/KeyCryptographer.cs b/Microsoft.Azure.Cosmos.Encryption/src/MdeSrc/AzureKeyVaultProvider/KeyCryptographer.cs
deleted file mode 100644
index 5e065861ee..0000000000
--- a/Microsoft.Azure.Cosmos.Encryption/src/MdeSrc/AzureKeyVaultProvider/KeyCryptographer.cs
+++ /dev/null
@@ -1,226 +0,0 @@
-//------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------
-
-// This file isn't generated, but this comment is necessary to exclude it from StyleCop analysis.
-//
-
-using Azure;
-using Azure.Core;
-using Azure.Security.KeyVault.Keys;
-using Azure.Security.KeyVault.Keys.Cryptography;
-using System;
-using System.Collections.Concurrent;
-using System.Threading.Tasks;
-
-using static Azure.Security.KeyVault.Keys.Cryptography.SignatureAlgorithm;
-using static Microsoft.Data.Encryption.Resources.Strings;
-
-namespace Microsoft.Data.Encryption.AzureKeyVaultProvider
-{
- internal class KeyCryptographer
- {
- ///
- /// TokenCredential to be used with the KeyClient
- ///
- private TokenCredential TokenCredential { get; set; }
-
- ///
- /// A mapping of the KeyClient objects to the corresponding Azure Key Vault URI
- ///
- private readonly ConcurrentDictionary _keyClientDictionary = new ConcurrentDictionary();
-
- ///
- /// Holds references to the fetch key tasks and maps them to their corresponding Azure Key Vault Key Identifier (URI).
- /// These tasks will be used for returning the key in the event that the fetch task has not finished depositing the
- /// key into the key dictionary.
- ///
- private readonly ConcurrentDictionary>> _keyFetchTaskDictionary = new ConcurrentDictionary>>();
-
- ///
- /// Holds references to the Azure Key Vault keys and maps them to their corresponding Azure Key Vault Key Identifier (URI).
- ///
- private readonly ConcurrentDictionary _keyDictionary = new ConcurrentDictionary();
-
- ///
- /// Holds references to the Azure Key Vault CryptographyClient objects and maps them to their corresponding Azure Key Vault Key Identifier (URI).
- ///
- private readonly ConcurrentDictionary _cryptoClientDictionary = new ConcurrentDictionary();
-
- ///
- /// Constructs a new KeyCryptographer
- ///
- ///
- internal KeyCryptographer(TokenCredential tokenCredential)
- {
- TokenCredential = tokenCredential;
- }
-
- ///
- /// Adds the key, specified by the Key Identifier URI, to the cache.
- ///
- ///
- internal void AddKey(string keyIdentifierUri)
- {
- if (TheKeyHasNotBeenCached(keyIdentifierUri))
- {
- ParseAKVPath(keyIdentifierUri, out Uri vaultUri, out string keyName, out string keyVersion);
- CreateKeyClient(vaultUri);
- FetchKey(vaultUri, keyName, keyVersion, keyIdentifierUri);
- }
-
- bool TheKeyHasNotBeenCached(string k) => !_keyDictionary.ContainsKey(k) && !_keyFetchTaskDictionary.ContainsKey(k);
- }
-
- ///
- /// Returns the key specified by the Key Identifier URI
- ///
- ///
- ///
- internal KeyVaultKey GetKey(string keyIdentifierUri)
- {
- if (_keyDictionary.ContainsKey(keyIdentifierUri))
- {
- _keyDictionary.TryGetValue(keyIdentifierUri, out KeyVaultKey key);
- return key;
- }
-
- if (_keyFetchTaskDictionary.ContainsKey(keyIdentifierUri))
- {
- _keyFetchTaskDictionary.TryGetValue(keyIdentifierUri, out Task> task);
- return Task.Run(() => task).GetAwaiter().GetResult();
- }
-
- // Not a public exception - not likely to occur.
- throw new MicrosoftDataEncryptionException(AzureKeyVaultKeyNotFound.Format(keyIdentifierUri));
- }
-
- ///
- /// Gets the public Key size in bytes.
- ///
- /// The key vault key identifier URI
- ///
- internal int GetKeySize(string keyIdentifierUri)
- {
- return GetKey(keyIdentifierUri).Key.N.Length;
- }
-
- ///
- /// Generates signature based on RSA PKCS#v1.5 scheme using a specified Azure Key Vault Key URL.
- ///
- /// The data to sign
- /// The key vault key identifier URI
- ///
- internal byte[] SignData(byte[] message, string keyIdentifierUri)
- {
- CryptographyClient cryptographyClient = GetCryptographyClient(keyIdentifierUri);
- return cryptographyClient.SignData(RS256, message).Signature;
- }
-
- internal bool VerifyData(byte[] message, byte[] signature, string keyIdentifierUri)
- {
- CryptographyClient cryptographyClient = GetCryptographyClient(keyIdentifierUri);
- return cryptographyClient.VerifyData(RS256, message, signature).IsValid;
- }
-
- internal byte[] UnwrapKey(KeyWrapAlgorithm keyWrapAlgorithm, byte[] encryptedKey, string keyIdentifierUri)
- {
- CryptographyClient cryptographyClient = GetCryptographyClient(keyIdentifierUri);
- return cryptographyClient.UnwrapKey(keyWrapAlgorithm, encryptedKey).Key;
- }
-
- internal byte[] WrapKey(KeyWrapAlgorithm keyWrapAlgorithm, byte[] key, string keyIdentifierUri)
- {
- CryptographyClient cryptographyClient = GetCryptographyClient(keyIdentifierUri);
- return cryptographyClient.WrapKey(keyWrapAlgorithm, key).EncryptedKey;
- }
-
- private CryptographyClient GetCryptographyClient(string keyIdentifierUri)
- {
- if (_cryptoClientDictionary.ContainsKey(keyIdentifierUri))
- {
- _cryptoClientDictionary.TryGetValue(keyIdentifierUri, out CryptographyClient client);
- return client;
- }
-
- CryptographyClient cryptographyClient = new CryptographyClient(GetKey(keyIdentifierUri).Id, TokenCredential);
- _cryptoClientDictionary.TryAdd(keyIdentifierUri, cryptographyClient);
-
- return cryptographyClient;
- }
-
- ///
- ///
- ///
- /// The Azure Key Vault URI
- /// The name of the Azure Key Vault key
- /// The version of the Azure Key Vault key
- /// The Azure Key Vault key identifier
- private void FetchKey(Uri vaultUri, string keyName, string keyVersion, string keyResourceUri)
- {
- Task> fetchKeyTask = FetchKeyFromKeyVault(vaultUri, keyName, keyVersion);
- _keyFetchTaskDictionary.AddOrUpdate(keyResourceUri, fetchKeyTask, (k, v) => fetchKeyTask);
-
- fetchKeyTask
- .ContinueWith(k => ValidateRsaKey(k.GetAwaiter().GetResult()))
- .ContinueWith(k => _keyDictionary.AddOrUpdate(keyResourceUri, k.GetAwaiter().GetResult(), (key, v) => k.GetAwaiter().GetResult()));
-
- Task.Run(() => fetchKeyTask);
- }
-
- ///
- /// Looks up the KeyClient object by it's URI and then fetches the key by name.
- ///
- /// The Azure Key Vault URI
- /// Then name of the key
- /// Then version of the key
- ///
- private Task> FetchKeyFromKeyVault(Uri vaultUri, string keyName, string keyVersion)
- {
- _keyClientDictionary.TryGetValue(vaultUri, out KeyClient keyClient);
- return keyClient.GetKeyAsync(keyName, keyVersion);
- }
-
- ///
- /// Validates that a key is of type RSA
- ///
- ///
- ///
- private KeyVaultKey ValidateRsaKey(KeyVaultKey key)
- {
- if (key.KeyType != KeyType.Rsa && key.KeyType != KeyType.RsaHsm)
- {
- throw new MicrosoftDataEncryptionException(NonRsaKeyTemplate.Format(key.KeyType));
- }
-
- return key;
- }
-
- ///
- /// Instantiates and adds a KeyClient to the KeyClient dictionary
- ///
- /// The Azure Key Vault URI
- private void CreateKeyClient(Uri vaultUri)
- {
- if (!_keyClientDictionary.ContainsKey(vaultUri))
- {
- _keyClientDictionary.TryAdd(vaultUri, new KeyClient(vaultUri, TokenCredential));
- }
- }
-
- ///
- /// Validates and parses the Azure Key Vault URI and key name.
- ///
- /// The Azure Key Vault key identifier
- /// The Azure Key Vault URI
- /// The name of the key
- /// The version of the key
- private void ParseAKVPath(string keyEncryptionKeyPath, out Uri vaultUri, out string keyEncryptionKeyName, out string keyEncryptionKeyVersion)
- {
- Uri masterKeyPathUri = new Uri(keyEncryptionKeyPath);
- vaultUri = new Uri(masterKeyPathUri.GetLeftPart(UriPartial.Authority));
- keyEncryptionKeyName = masterKeyPathUri.Segments[2];
- keyEncryptionKeyVersion = masterKeyPathUri.Segments.Length > 3 ? masterKeyPathUri.Segments[3] : null;
- }
- }
-}
diff --git a/Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/AzureKeyVaultKeyWrapProvider.cs b/Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/AzureKeyVaultKeyWrapProvider.cs
deleted file mode 100644
index 3945d380c1..0000000000
--- a/Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/AzureKeyVaultKeyWrapProvider.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-//------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------
-
-namespace Microsoft.Azure.Cosmos.Encryption
-{
- using System;
- using System.Threading.Tasks;
- using global::Azure.Core;
- using Microsoft.Data.Encryption.AzureKeyVaultProvider;
-
- ///
- /// Implementation of key encryption key store provider that allows client applications to access data when a
- /// key encryption key is stored in Microsoft Azure Key Vault.
- ///
- public sealed class AzureKeyVaultKeyWrapProvider : EncryptionKeyWrapProvider
- {
- private readonly AzureKeyVaultKeyStoreProvider azureKeyVaultKeyStoreProvider;
-
- ///
- /// Initializes a new instance of the class.
- /// Constructor that takes an implementation of Token Credential that is capable of providing an OAuth Token.
- ///
- /// returns token credentials.
- public AzureKeyVaultKeyWrapProvider(TokenCredential tokenCredential)
- {
- // just rely on cache managed via EncryptionKeyWrapProvider. Setting DataEncryptionKeyCacheTimeToLive to zero results in not using azureKeyVaultKeyWrapProvider cache.
- this.azureKeyVaultKeyStoreProvider = new AzureKeyVaultKeyStoreProvider(tokenCredential)
- {
- DataEncryptionKeyCacheTimeToLive = TimeSpan.Zero,
- };
- }
-
- ///
- /// Gets name of the Encryption Key Store Provider implementation.
- ///
- public override string ProviderName => this.azureKeyVaultKeyStoreProvider.ProviderName;
-
- ///
- /// This function uses the asymmetric key specified by the key path
- /// and decrypts an encrypted data dencryption key with RSA encryption algorithm.
- /// .
- /// Identifier of an asymmetric key in Azure Key Vault.
- /// The key encryption algorithm.
- /// The ciphertext key.
- /// Plain text data encryption key.
- public override Task UnwrapKeyAsync(string encryptionKeyId, string cosmosKeyEncryptionKeyAlgorithm, byte[] encryptedKey)
- {
- Data.Encryption.Cryptography.KeyEncryptionKeyAlgorithm keyEncryptionKeyAlgorithm = cosmosKeyEncryptionKeyAlgorithm switch
- {
- KeyEncryptionKeyAlgorithm.RsaOaep => Data.Encryption.Cryptography.KeyEncryptionKeyAlgorithm.RSA_OAEP,
- _ => throw new NotSupportedException("The specified KeyEncryptionAlgorithm is not supported. Please refer to https://aka.ms/CosmosClientEncryption for more details. "),
- };
-
- return Task.FromResult(this.azureKeyVaultKeyStoreProvider.UnwrapKey(encryptionKeyId, keyEncryptionKeyAlgorithm, encryptedKey));
- }
-
- ///
- /// This function uses the asymmetric key specified by the key path
- /// and encrypts an unencrypted data encryption key with RSA encryption algorithm.
- ///
- /// Identifier of an asymmetric key in Azure Key Vault.
- /// The key encryption algorithm.
- /// The plaintext key.
- /// Encrypted data encryption key.
- public override Task WrapKeyAsync(string encryptionKeyId, string cosmosKeyEncryptionKeyAlgorithm, byte[] key)
- {
- Data.Encryption.Cryptography.KeyEncryptionKeyAlgorithm keyEncryptionKeyAlgorithm = cosmosKeyEncryptionKeyAlgorithm switch
- {
- KeyEncryptionKeyAlgorithm.RsaOaep => Data.Encryption.Cryptography.KeyEncryptionKeyAlgorithm.RSA_OAEP,
- _ => throw new NotSupportedException("This specified KeyEncryptionAlgorithm is not supported. Please refer to https://aka.ms/CosmosClientEncryption for more details. "),
- };
-
- return Task.FromResult(this.azureKeyVaultKeyStoreProvider.WrapKey(encryptionKeyId, keyEncryptionKeyAlgorithm, key));
- }
- }
-}
diff --git a/Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/EncryptionKeyWrapProvider.cs b/Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/EncryptionKeyWrapProvider.cs
deleted file mode 100644
index 408f060a7c..0000000000
--- a/Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/EncryptionKeyWrapProvider.cs
+++ /dev/null
@@ -1,92 +0,0 @@
-//------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------
-
-namespace Microsoft.Azure.Cosmos.Encryption
-{
- using System;
- using System.Threading.Tasks;
- using Microsoft.Data.Encryption.Cryptography;
-
- ///
- /// Base class for all key store providers. A custom provider must derive from this
- /// class and override its member functions.
- ///
- public abstract class EncryptionKeyWrapProvider
- {
- internal EncryptionKeyWrapProvider()
- {
- this.EncryptionKeyStoreProviderImpl = new EncryptionKeyStoreProviderImpl(this);
- }
-
- ///
- /// Gets or sets the lifespan of the decrypted data encryption key in the cache.
- /// Once the timespan has elapsed, the decrypted data encryption key is discarded
- /// and must be revalidated.
- ///
- ///
- /// Internally, there is a cache of key encryption keys (once they are unwrapped).
- /// This is useful for rapidly decrypting multiple data values. The default value is 2 hours.
- /// Setting the to zero disables caching.
- ///
- public TimeSpan? DataEncryptionKeyCacheTimeToLive
- {
- get => this.EncryptionKeyStoreProviderImpl.DataEncryptionKeyCacheTimeToLive;
- set
- {
- this.EncryptionKeyStoreProviderImpl.DataEncryptionKeyCacheTimeToLive = value;
-
- // set the TTL for ProtectedDataEncryption, so that we have a uniform expiry of the KeyStoreProvider and ProtectedDataEncryption cache items.
- if (this.EncryptionKeyStoreProviderImpl.DataEncryptionKeyCacheTimeToLive.HasValue)
- {
- if (EncryptionCosmosClient.EncryptionKeyCacheSemaphore.Wait(-1))
- {
- try
- {
- // pick the min of the new value being set and ProtectedDataEncryptionKey's current TTL. Note ProtectedDataEncryptionKey TimeToLive is static
- // and results in various instances to share this value. Hence we pick up whatever is the min value. If a TimeSpan.Zero is across any one instance
- // it should be fine, since we look up the KeyStoreProvider cache. ProtectedDataEncryptionKey's own cache supersedes KeyStoreProvider cache, since it stores
- // the RootKey which is derived from unwrapped key(Data Encryption Key).
- // Note: DataEncryptionKeyCacheTimeToLive is nullable. When set to null this results in AbsoluteExpirationRelativeToNow to be set to null which caches forever.
- // whatever is the current set value for ProtectedDataEncryptionKey TimeToLive(is not nullable) would be min if null value is passed.
- if (TimeSpan.Compare(this.EncryptionKeyStoreProviderImpl.DataEncryptionKeyCacheTimeToLive.Value, ProtectedDataEncryptionKey.TimeToLive) < 0)
- {
- ProtectedDataEncryptionKey.TimeToLive = this.EncryptionKeyStoreProviderImpl.DataEncryptionKeyCacheTimeToLive.Value;
- }
- }
- finally
- {
- EncryptionCosmosClient.EncryptionKeyCacheSemaphore.Release(1);
- }
- }
- }
- }
- }
-
- ///
- /// Gets the unique name that identifies a particular implementation of the abstract .
- ///
- public abstract string ProviderName { get; }
-
- internal EncryptionKeyStoreProviderImpl EncryptionKeyStoreProviderImpl { get; }
-
- ///
- /// Unwraps the specified of a data encryption key. The encrypted value is expected to be encrypted using
- /// the key encryption key with the specified and using the specified .
- ///
- /// The key Id tells the provider where to find the key.
- /// The key encryption algorithm.
- /// The ciphertext key.
- /// The unwrapped data encryption key.
- public abstract Task UnwrapKeyAsync(string encryptionKeyId, string keyEncryptionKeyAlgorithm, byte[] encryptedKey);
-
- ///
- /// Wraps a data encryption key using the key encryption key with the specified and using the specified .
- ///
- /// The key Id tells the provider where to find the key.
- /// The key encryption algorithm.
- /// The plaintext key.
- /// The wrapped data encryption key.
- public abstract Task WrapKeyAsync(string encryptionKeyId, string keyEncryptionKeyAlgorithm, byte[] key);
- }
-}
diff --git a/Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/KeyEncryptionKeyAlgorithm.cs b/Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/KeyEncryptionKeyAlgorithm.cs
deleted file mode 100644
index 255000884f..0000000000
--- a/Microsoft.Azure.Cosmos.Encryption/src/MdeSupport/KeyEncryptionKeyAlgorithm.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-//------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------
-
-namespace Microsoft.Azure.Cosmos.Encryption
-{
- ///
- /// Represents the encryption algorithms supported for key encryption.
- ///
- public static class KeyEncryptionKeyAlgorithm
- {
- ///
- /// RSA public key cryptography algorithm with Optimal Asymmetric Encryption Padding (OAEP) padding.
- ///
- public const string RsaOaep = "RSA_OAEP";
- }
-}
diff --git a/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj b/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj
index 11c8344f7d..aa72dc9d65 100644
--- a/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj
+++ b/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj
@@ -34,7 +34,6 @@
-
diff --git a/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs b/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs
index 071f704bc2..2368e8e71d 100644
--- a/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs
+++ b/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs
@@ -15,6 +15,7 @@ namespace Microsoft.Azure.Cosmos.Encryption.EmulatorTests
using System.Threading;
using System.Threading.Tasks;
using global::Azure;
+ using global::Azure.Core.Cryptography;
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Cosmos.Encryption;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -33,22 +34,23 @@ public class MdeEncryptionTests
private static Database database;
private static Container encryptionContainer;
private static Container encryptionContainerForChangeFeed;
- private static TestEncryptionKeyWrapProvider testEncryptionKeyWrapProvider;
+ private static TestKeyEncryptionKeyResolver testKeyEncryptionKeyResolver;
[ClassInitialize]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "The ClassInitialize method takes a single parameter of type TestContext.")]
public static async Task ClassInitialize(TestContext context)
{
MdeEncryptionTests.client = TestCommon.CreateCosmosClient();
- testEncryptionKeyWrapProvider = new TestEncryptionKeyWrapProvider
- {
- DataEncryptionKeyCacheTimeToLive = null
- };
+ testKeyEncryptionKeyResolver = new TestKeyEncryptionKeyResolver();
+
+ metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(TestKeyEncryptionKeyResolver.Id, "key1", "tempmetadata1");
+ metadata2 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(TestKeyEncryptionKeyResolver.Id, "key2", "tempmetadata2");
- metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, "key1", "tempmetadata1");
- metadata2 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, "key2", "tempmetadata2");
+ MdeEncryptionTests.encryptionCosmosClient = MdeEncryptionTests.client.WithEncryption(
+ testKeyEncryptionKeyResolver,
+ TestKeyEncryptionKeyResolver.Id,
+ TimeSpan.Zero);
- MdeEncryptionTests.encryptionCosmosClient = MdeEncryptionTests.client.WithEncryption(testEncryptionKeyWrapProvider);
MdeEncryptionTests.database = await MdeEncryptionTests.encryptionCosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString());
await MdeEncryptionTests.CreateClientEncryptionKeyAsync(
@@ -60,10 +62,11 @@ await MdeEncryptionTests.CreateClientEncryptionKeyAsync(
metadata2);
- EncryptionKeyWrapMetadata revokedKekmetadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, "revokedKek", "revokedKek-metadata");
+ EncryptionKeyWrapMetadata revokedKekmetadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(TestKeyEncryptionKeyResolver.Id, "revokedKek", "revokedKek-metadata");
+
await database.CreateClientEncryptionKeyAsync(
"keywithRevokedKek",
- DataEncryptionKeyAlgorithm.AeadAes256CbcHmacSha256,
+ EncryptionAlgorithm.AeadAes256CbcHmacSha256,
revokedKekmetadata);
Collection paths = new Collection()
@@ -179,11 +182,18 @@ await database.CreateClientEncryptionKeyAsync(
await encryptionContainerForChangeFeed.InitializeEncryptionAsync();
}
+ [TestInitialize]
+ public void TestInitialize()
+ {
+ // Reset static cache TTL
+ Microsoft.Data.Encryption.Cryptography.ProtectedDataEncryptionKey.TimeToLive = TimeSpan.FromHours(2);
+ }
+
private static async Task CreateClientEncryptionKeyAsync(string cekId, Cosmos.EncryptionKeyWrapMetadata encryptionKeyWrapMetadata)
{
ClientEncryptionKeyResponse clientEncrytionKeyResponse = await database.CreateClientEncryptionKeyAsync(
cekId,
- DataEncryptionKeyAlgorithm.AeadAes256CbcHmacSha256,
+ EncryptionAlgorithm.AeadAes256CbcHmacSha256,
encryptionKeyWrapMetadata);
Assert.AreEqual(HttpStatusCode.Created, clientEncrytionKeyResponse.StatusCode);
@@ -235,7 +245,7 @@ public async Task EncryptionBulkCrud()
.WithBulkExecution(true)
.Build());
- CosmosClient encryptionCosmosClientWithBulk = clientWithBulk.WithEncryption(new TestEncryptionKeyWrapProvider());
+ CosmosClient encryptionCosmosClientWithBulk = clientWithBulk.WithEncryption(new TestKeyEncryptionKeyResolver(), TestKeyEncryptionKeyResolver.Id);
Database databaseWithBulk = encryptionCosmosClientWithBulk.GetDatabase(MdeEncryptionTests.database.Id);
Container encryptionContainerWithBulk = databaseWithBulk.GetContainer(MdeEncryptionTests.encryptionContainer.Id);
@@ -257,18 +267,18 @@ public async Task EncryptionCreateClientEncryptionKey()
{
string cekId = "anotherCek";
- EncryptionKeyWrapMetadata metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata1");
+ EncryptionKeyWrapMetadata metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(TestKeyEncryptionKeyResolver.Id, cekId, "testmetadata1");
ClientEncryptionKeyProperties clientEncryptionKeyProperties = await MdeEncryptionTests.CreateClientEncryptionKeyAsync(
cekId,
metadata1);
Assert.AreEqual(
- MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, name: cekId, value: metadata1.Value),
+ MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(TestKeyEncryptionKeyResolver.Id, name: cekId, value: metadata1.Value),
clientEncryptionKeyProperties.EncryptionKeyWrapMetadata);
// creating another key with same id should fail
- metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata2");
+ metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(TestKeyEncryptionKeyResolver.Id, cekId, "testmetadata2");
try
{
@@ -289,22 +299,22 @@ await MdeEncryptionTests.CreateClientEncryptionKeyAsync(
public async Task EncryptionRewrapClientEncryptionKey()
{
string cekId = "rewrapkeytest";
- EncryptionKeyWrapMetadata metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata1");
+ EncryptionKeyWrapMetadata metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(TestKeyEncryptionKeyResolver.Id, cekId, "testmetadata1");
ClientEncryptionKeyProperties clientEncryptionKeyProperties = await MdeEncryptionTests.CreateClientEncryptionKeyAsync(
cekId,
metadata1);
Assert.AreEqual(
- MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, name: cekId, value: metadata1.Value),
+ MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(TestKeyEncryptionKeyResolver.Id, name: cekId, value: metadata1.Value),
clientEncryptionKeyProperties.EncryptionKeyWrapMetadata);
- EncryptionKeyWrapMetadata updatedMetaData = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, metadata1 + "updatedmetadata");
+ EncryptionKeyWrapMetadata updatedMetaData = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(TestKeyEncryptionKeyResolver.Id, cekId, metadata1 + "updatedmetadata");
clientEncryptionKeyProperties = await MdeEncryptionTests.RewarpClientEncryptionKeyAsync(
cekId,
updatedMetaData);
Assert.AreEqual(
- MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, name: cekId, value: updatedMetaData.Value),
+ MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(TestKeyEncryptionKeyResolver.Id, name: cekId, value: updatedMetaData.Value),
clientEncryptionKeyProperties.EncryptionKeyWrapMetadata);
}
@@ -332,12 +342,9 @@ public async Task EncryptionCreateItemWithNullProperty()
CosmosClient clientWithNoCaching = TestCommon.CreateCosmosClient(builder => builder
.Build());
- TestEncryptionKeyWrapProvider testEncryptionKeyWrapProvider = new TestEncryptionKeyWrapProvider
- {
- DataEncryptionKeyCacheTimeToLive = TimeSpan.Zero
- };
+ TestKeyEncryptionKeyResolver testKeyEncryptionKeyResolver = new TestKeyEncryptionKeyResolver();
- CosmosClient encryptionCosmosClient = clientWithNoCaching.WithEncryption(testEncryptionKeyWrapProvider);
+ CosmosClient encryptionCosmosClient = clientWithNoCaching.WithEncryption(testKeyEncryptionKeyResolver, TestKeyEncryptionKeyResolver.Id, TimeSpan.Zero);
Database database = encryptionCosmosClient.GetDatabase(MdeEncryptionTests.database.Id);
Container encryptionContainer = database.GetContainer(MdeEncryptionTests.encryptionContainer.Id);
@@ -395,7 +402,7 @@ await MdeEncryptionTests.ValidateQueryResultsAsync(
expectedDoc: expectedDoc);
// no access to key.
- testEncryptionKeyWrapProvider.RevokeAccessSet = true;
+ testKeyEncryptionKeyResolver.RevokeAccessSet = true;
testDoc = TestDoc.Create();
@@ -409,7 +416,7 @@ await MdeEncryptionTests.ValidateQueryResultsAsync(
Assert.AreEqual(HttpStatusCode.Created, createResponse.StatusCode);
VerifyExpectedDocResponse(testDoc, createResponse.Resource);
- testEncryptionKeyWrapProvider.RevokeAccessSet = false;
+ testKeyEncryptionKeyResolver.RevokeAccessSet = false;
}
@@ -428,18 +435,18 @@ public async Task EncryptionResourceTokenAuthRestricted()
restrictedUserPermission.Token);
- CosmosClient encryptedclientForRestrictedUser = clientForRestrictedUser.WithEncryption(new TestEncryptionKeyWrapProvider());
+ CosmosClient encryptedclientForRestrictedUser = clientForRestrictedUser.WithEncryption(new TestKeyEncryptionKeyResolver(), TestKeyEncryptionKeyResolver.Id);
Database databaseForRestrictedUser = encryptedclientForRestrictedUser.GetDatabase(MdeEncryptionTests.database.Id);
try
{
string cekId = "testingcekID";
- EncryptionKeyWrapMetadata metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata1");
+ EncryptionKeyWrapMetadata metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(TestKeyEncryptionKeyResolver.Id, cekId, "testmetadata1");
ClientEncryptionKeyResponse clientEncrytionKeyResponse = await databaseForRestrictedUser.CreateClientEncryptionKeyAsync(
cekId,
- DataEncryptionKeyAlgorithm.AeadAes256CbcHmacSha256,
+ EncryptionAlgorithm.AeadAes256CbcHmacSha256,
metadata1);
Assert.Fail("CreateClientEncryptionKeyAsync should have failed due to restrictions");
}
@@ -450,7 +457,7 @@ public async Task EncryptionResourceTokenAuthRestricted()
try
{
string cekId = "testingcekID";
- EncryptionKeyWrapMetadata metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata1" + "updated");
+ EncryptionKeyWrapMetadata metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(TestKeyEncryptionKeyResolver.Id, cekId, "testmetadata1" + "updated");
ClientEncryptionKeyResponse clientEncrytionKeyResponse = await databaseForRestrictedUser.RewrapClientEncryptionKeyAsync(
cekId,
@@ -1001,7 +1008,7 @@ public async Task EncryptionValidatePolicyRefreshPostContainerDeleteWithBulk()
.WithBulkExecution(false)
.Build());
- CosmosClient otherEncryptionClient = otherClient.WithEncryption(new TestEncryptionKeyWrapProvider());
+ CosmosClient otherEncryptionClient = otherClient.WithEncryption(new TestKeyEncryptionKeyResolver(), TestKeyEncryptionKeyResolver.Id);
Database otherDatabase = otherEncryptionClient.GetDatabase(MdeEncryptionTests.database.Id);
Container otherEncryptionContainer = otherDatabase.GetContainer(encryptionContainerToDelete.Id);
@@ -1150,7 +1157,7 @@ public async Task EncryptionValidatePolicyRefreshPostContainerDeleteTransactionB
CosmosClient otherClient = TestCommon.CreateCosmosClient(builder => builder
.Build());
- CosmosClient otherEncryptionClient = otherClient.WithEncryption(new TestEncryptionKeyWrapProvider());
+ CosmosClient otherEncryptionClient = otherClient.WithEncryption(new TestKeyEncryptionKeyResolver(), TestKeyEncryptionKeyResolver.Id);
Database otherDatabase = otherEncryptionClient.GetDatabase(MdeEncryptionTests.database.Id);
Container otherEncryptionContainer = otherDatabase.GetContainer(encryptionContainerToDelete.Id);
@@ -1282,7 +1289,7 @@ public async Task EncryptionValidatePolicyRefreshPostContainerDeleteQuery()
CosmosClient otherClient = TestCommon.CreateCosmosClient(builder => builder
.Build());
- CosmosClient otherEncryptionClient = otherClient.WithEncryption(new TestEncryptionKeyWrapProvider());
+ CosmosClient otherEncryptionClient = otherClient.WithEncryption(new TestKeyEncryptionKeyResolver(), TestKeyEncryptionKeyResolver.Id);
Database otherDatabase = otherEncryptionClient.GetDatabase(MdeEncryptionTests.database.Id);
Container otherEncryptionContainer = otherDatabase.GetContainer(encryptionContainerToDelete.Id);
@@ -1397,7 +1404,7 @@ public async Task EncryptionValidatePolicyRefreshPostContainerDeletePatch()
CosmosClient otherClient = TestCommon.CreateCosmosClient(builder => builder
.Build());
- CosmosClient otherEncryptionClient = otherClient.WithEncryption(new TestEncryptionKeyWrapProvider());
+ CosmosClient otherEncryptionClient = otherClient.WithEncryption(new TestKeyEncryptionKeyResolver(), TestKeyEncryptionKeyResolver.Id);
Database otherDatabase = otherEncryptionClient.GetDatabase(MdeEncryptionTests.database.Id);
Container otherEncryptionContainer = otherDatabase.GetContainer(encryptionContainerToDelete.Id);
@@ -1544,18 +1551,15 @@ public async Task EncryptionValidatePolicyRefreshPostDatabaseDelete()
CosmosClient mainClient = TestCommon.CreateCosmosClient(builder => builder
.Build());
- TestEncryptionKeyWrapProvider testEncryptionKeyWrapProvider = new TestEncryptionKeyWrapProvider
- {
- DataEncryptionKeyCacheTimeToLive = TimeSpan.FromMinutes(30),
- };
+ TestKeyEncryptionKeyResolver testKeyEncryptionKeyResolver = new TestKeyEncryptionKeyResolver();
- EncryptionKeyWrapMetadata keyWrapMetadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, "myCek", "mymetadata1");
- CosmosClient encryptionCosmosClient = mainClient.WithEncryption(testEncryptionKeyWrapProvider);
+ EncryptionKeyWrapMetadata keyWrapMetadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(TestKeyEncryptionKeyResolver.Id, "myCek", "mymetadata1");
+ CosmosClient encryptionCosmosClient = mainClient.WithEncryption(testKeyEncryptionKeyResolver, TestKeyEncryptionKeyResolver.Id, TimeSpan.FromMinutes(30));
Database mainDatabase = await encryptionCosmosClient.CreateDatabaseAsync("databaseToBeDeleted");
ClientEncryptionKeyResponse clientEncrytionKeyResponse = await mainDatabase.CreateClientEncryptionKeyAsync(
keyWrapMetadata.Name,
- DataEncryptionKeyAlgorithm.AeadAes256CbcHmacSha256,
+ EncryptionAlgorithm.AeadAes256CbcHmacSha256,
keyWrapMetadata);
Collection originalPaths = new Collection()
@@ -1597,12 +1601,9 @@ public async Task EncryptionValidatePolicyRefreshPostDatabaseDelete()
CosmosClient otherClient1 = TestCommon.CreateCosmosClient(builder => builder
.Build());
- TestEncryptionKeyWrapProvider testEncryptionKeyWrapProvider2 = new TestEncryptionKeyWrapProvider
- {
- DataEncryptionKeyCacheTimeToLive = TimeSpan.Zero,
- };
+ TestKeyEncryptionKeyResolver testKeyEncryptionKeyResolver2 = new TestKeyEncryptionKeyResolver();
- CosmosClient otherEncryptionClient = otherClient1.WithEncryption(testEncryptionKeyWrapProvider2);
+ CosmosClient otherEncryptionClient = otherClient1.WithEncryption(testKeyEncryptionKeyResolver2, TestKeyEncryptionKeyResolver.Id, TimeSpan.Zero);
Database otherDatabase = otherEncryptionClient.GetDatabase(mainDatabase.Id);
Container otherEncryptionContainer = otherDatabase.GetContainer(encryptionContainerToDelete.Id);
@@ -1615,10 +1616,10 @@ public async Task EncryptionValidatePolicyRefreshPostDatabaseDelete()
mainDatabase = await encryptionCosmosClient.CreateDatabaseAsync("databaseToBeDeleted");
- keyWrapMetadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider2.ProviderName, "myCek", "mymetadata2");
+ keyWrapMetadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(TestKeyEncryptionKeyResolver.Id, "myCek", "mymetadata2");
clientEncrytionKeyResponse = await mainDatabase.CreateClientEncryptionKeyAsync(
keyWrapMetadata.Name,
- DataEncryptionKeyAlgorithm.AeadAes256CbcHmacSha256,
+ EncryptionAlgorithm.AeadAes256CbcHmacSha256,
keyWrapMetadata);
using (await mainDatabase.GetContainer(encryptionContainerToDelete.Id).DeleteContainerStreamAsync())
@@ -1723,12 +1724,9 @@ public async Task EncryptionValidatePolicyRefreshPostDatabaseDelete()
.WithBulkExecution(true)
.Build());
- TestEncryptionKeyWrapProvider testEncryptionKeyWrapProvider3 = new TestEncryptionKeyWrapProvider
- {
- DataEncryptionKeyCacheTimeToLive = TimeSpan.FromMinutes(30),
- };
+ TestKeyEncryptionKeyResolver testKeyEncryptionKeyResolver3 = new TestKeyEncryptionKeyResolver();
- CosmosClient otherEncryptionClient2 = otherClient2.WithEncryption(testEncryptionKeyWrapProvider3);
+ CosmosClient otherEncryptionClient2 = otherClient2.WithEncryption(testKeyEncryptionKeyResolver3, TestKeyEncryptionKeyResolver.Id, TimeSpan.FromMinutes(30));
Database otherDatabase2 = otherEncryptionClient2.GetDatabase(mainDatabase.Id);
Container otherEncryptionContainer3 = otherDatabase2.GetContainer(otherEncryptionContainer2.Id);
@@ -1808,68 +1806,15 @@ public void MdeEncryptionTypesContractTest()
CollectionAssert.AreEquivalent(mdeSupportedEncryptionTypes, cosmosSupportedEncryptionTypes);
}
- [TestMethod]
- public void MdeEncryptionAlgorithmsTypesContractTest()
- {
- string[] cosmosKeyEncryptionAlgorithms = typeof(KeyEncryptionKeyAlgorithm)
- .GetMembers(BindingFlags.Static | BindingFlags.Public)
- .Select(e => ((FieldInfo)e).GetValue(e).ToString())
- .ToArray();
-
- string[] mdeKeyEncryptionAlgorithms = typeof(Data.Encryption.Cryptography.KeyEncryptionKeyAlgorithm)
- .GetMembers(BindingFlags.Static | BindingFlags.Public)
- .Select(e => e.Name)
- .ToArray();
-
- if (mdeKeyEncryptionAlgorithms.Length > cosmosKeyEncryptionAlgorithms.Length)
- {
- HashSet missingKeyEncryptionAlgorithms = new HashSet(mdeKeyEncryptionAlgorithms);
- foreach (string algorithm in cosmosKeyEncryptionAlgorithms)
- {
- missingKeyEncryptionAlgorithms.Remove(algorithm);
- }
-
- Assert.Fail($"Missing key encryption algorithm support from CosmosKeyEncryptionKeyAlgorithm: {string.Join(";", missingKeyEncryptionAlgorithms)}");
- }
-
- CollectionAssert.AreEquivalent(mdeKeyEncryptionAlgorithms, cosmosKeyEncryptionAlgorithms);
-
- string[] cosmosDataEncryptionAlgorithms = typeof(DataEncryptionKeyAlgorithm)
- .GetMembers(BindingFlags.Static | BindingFlags.Public)
- .Select(e => ((FieldInfo)e).GetValue(e).ToString())
- .ToArray();
-
- string[] mdeDataEncryptionAlgorithms = typeof(Data.Encryption.Cryptography.DataEncryptionKeyAlgorithm)
- .GetMembers(BindingFlags.Static | BindingFlags.Public)
- .Select(e => e.Name)
- .ToArray();
-
- if (mdeDataEncryptionAlgorithms.Length > cosmosDataEncryptionAlgorithms.Length)
- {
- HashSet missingDataEncryptionAlgorithms = new HashSet(mdeDataEncryptionAlgorithms);
- foreach (string algorithm in cosmosDataEncryptionAlgorithms)
- {
- missingDataEncryptionAlgorithms.Remove(algorithm);
- }
-
- Assert.Fail($"Missing data encryption algorithm support from CosmosDataEncryptionKeyAlgorithm: {string.Join(";", missingDataEncryptionAlgorithms)}");
- }
-
- CollectionAssert.AreEquivalent(mdeDataEncryptionAlgorithms, cosmosDataEncryptionAlgorithms);
- }
-
[TestMethod]
public async Task VerifyKekRevokeHandling()
{
CosmosClient clientWithNoCaching = TestCommon.CreateCosmosClient(builder => builder
.Build());
- TestEncryptionKeyWrapProvider testEncryptionKeyWrapProvider = new TestEncryptionKeyWrapProvider
- {
- DataEncryptionKeyCacheTimeToLive = TimeSpan.Zero
- };
+ TestKeyEncryptionKeyResolver testKeyEncryptionKeyResolver = new TestKeyEncryptionKeyResolver();
- CosmosClient encryptionCosmosClient = clientWithNoCaching.WithEncryption(testEncryptionKeyWrapProvider);
+ CosmosClient encryptionCosmosClient = clientWithNoCaching.WithEncryption(testKeyEncryptionKeyResolver, TestKeyEncryptionKeyResolver.Id, TimeSpan.Zero);
Database database = encryptionCosmosClient.GetDatabase(MdeEncryptionTests.database.Id);
// Once a Dek gets cached and the Kek is revoked, calls to unwrap/wrap keys would fail since KEK is revoked.
@@ -1893,7 +1838,7 @@ public async Task VerifyKekRevokeHandling()
TestDoc testDoc1 = await MdeEncryptionTests.MdeCreateItemAsync(encryptionContainer);
- testEncryptionKeyWrapProvider.RevokeAccessSet = true;
+ testKeyEncryptionKeyResolver.RevokeAccessSet = true;
// try creating it and it should fail as it has been revoked.
try
@@ -1921,16 +1866,15 @@ await MdeEncryptionTests.ValidateQueryResultsAsync(
}
// for unwrap to succeed
- testEncryptionKeyWrapProvider.RevokeAccessSet = false;
+ testKeyEncryptionKeyResolver.RevokeAccessSet = false;
// lets rewrap it.
await database.RewrapClientEncryptionKeyAsync("keywithRevokedKek", MdeEncryptionTests.metadata2);
- testEncryptionKeyWrapProvider.RevokeAccessSet = true;
+ testKeyEncryptionKeyResolver.RevokeAccessSet = true;
// Should fail but will try to fetch the lastest from the Backend and updates the cache.
await MdeEncryptionTests.MdeCreateItemAsync(encryptionContainer);
- testEncryptionKeyWrapProvider.RevokeAccessSet = false;
- testEncryptionKeyWrapProvider.DataEncryptionKeyCacheTimeToLive = TimeSpan.FromMinutes(120);
+ testKeyEncryptionKeyResolver.RevokeAccessSet = false;
}
[TestMethod]
@@ -2210,7 +2154,7 @@ public async Task EncryptionTransactionalBatchWithCustomSerializer()
.WithCustomSerializer(customSerializer)
.Build());
- CosmosClient encryptionCosmosClientWithCustomSerializer = clientWithCustomSerializer.WithEncryption(new TestEncryptionKeyWrapProvider());
+ CosmosClient encryptionCosmosClientWithCustomSerializer = clientWithCustomSerializer.WithEncryption(new TestKeyEncryptionKeyResolver(), TestKeyEncryptionKeyResolver.Id);
Database databaseWithCustomSerializer = encryptionCosmosClientWithCustomSerializer.GetDatabase(MdeEncryptionTests.database.Id);
Container encryptionContainerWithCustomSerializer = databaseWithCustomSerializer.GetContainer(MdeEncryptionTests.encryptionContainer.Id);
@@ -2265,11 +2209,11 @@ await MdeEncryptionTests.ValidateQueryResultsAsync(
}
[TestMethod]
- public async Task ValidateCachingofProtectedDataEncryptionKey()
+ public async Task ValidateCachingOfProtectedDataEncryptionKey()
{
- // Default cache TTL 2 hours.
- TestEncryptionKeyWrapProvider newtestEncryptionKeyWrapProvider = new TestEncryptionKeyWrapProvider();
- CosmosClient newEncryptionClient = MdeEncryptionTests.client.WithEncryption(newtestEncryptionKeyWrapProvider);
+ // Default cache TTL 1 hours.
+ TestKeyEncryptionKeyResolver newtestKeyEncryptionKeyResolver = new TestKeyEncryptionKeyResolver();
+ CosmosClient newEncryptionClient = MdeEncryptionTests.client.WithEncryption(newtestKeyEncryptionKeyResolver, TestKeyEncryptionKeyResolver.Id);
Database database = newEncryptionClient.GetDatabase(MdeEncryptionTests.database.Id);
Container encryptionContainer = database.GetContainer(MdeEncryptionTests.encryptionContainer.Id);
@@ -2279,12 +2223,12 @@ public async Task ValidateCachingofProtectedDataEncryptionKey()
await MdeEncryptionTests.MdeCreateItemAsync(encryptionContainer);
}
- newtestEncryptionKeyWrapProvider.UnWrapKeyCallsCount.TryGetValue(metadata1.Value, out int unwrapcount);
+ newtestKeyEncryptionKeyResolver.UnWrapKeyCallsCount.TryGetValue(metadata1.Value, out int unwrapcount);
// expecting just one unwrap.
Assert.AreEqual(1, unwrapcount);
// no caching.
- newtestEncryptionKeyWrapProvider.DataEncryptionKeyCacheTimeToLive = TimeSpan.Zero;
+ newEncryptionClient = MdeEncryptionTests.client.WithEncryption(newtestKeyEncryptionKeyResolver, TestKeyEncryptionKeyResolver.Id, TimeSpan.Zero);
database = newEncryptionClient.GetDatabase(MdeEncryptionTests.database.Id);
@@ -2295,7 +2239,7 @@ public async Task ValidateCachingofProtectedDataEncryptionKey()
await MdeEncryptionTests.MdeCreateItemAsync(encryptionContainer);
}
- newtestEncryptionKeyWrapProvider.UnWrapKeyCallsCount.TryGetValue(metadata1.Value, out unwrapcount);
+ newtestKeyEncryptionKeyResolver.UnWrapKeyCallsCount.TryGetValue(metadata1.Value, out unwrapcount);
Assert.IsTrue(unwrapcount > 1, "The actual unwrap count was not greater than 1");
}
@@ -2447,8 +2391,8 @@ private async Task ValidateChangeFeedProcessorResponse(
Assert.AreEqual(changeFeedReturnedDocs.Count, 2);
- VerifyExpectedDocResponse(testDoc1, changeFeedReturnedDocs[changeFeedReturnedDocs.Count - 2]);
- VerifyExpectedDocResponse(testDoc2, changeFeedReturnedDocs[changeFeedReturnedDocs.Count - 1]);
+ VerifyExpectedDocResponse(testDoc1, changeFeedReturnedDocs[^2]);
+ VerifyExpectedDocResponse(testDoc2, changeFeedReturnedDocs[^1]);
if (leaseDatabase != null)
{
@@ -2495,8 +2439,8 @@ private async Task ValidateChangeFeedProcessorWithFeedHandlerResponse(
Assert.AreEqual(changeFeedReturnedDocs.Count, 2);
- VerifyExpectedDocResponse(testDoc1, changeFeedReturnedDocs[changeFeedReturnedDocs.Count - 2]);
- VerifyExpectedDocResponse(testDoc2, changeFeedReturnedDocs[changeFeedReturnedDocs.Count - 1]);
+ VerifyExpectedDocResponse(testDoc1, changeFeedReturnedDocs[^2]);
+ VerifyExpectedDocResponse(testDoc2, changeFeedReturnedDocs[^1]);
if (leaseDatabase != null)
{
@@ -2544,8 +2488,8 @@ private async Task ValidateChangeFeedProcessorWithManualCheckpointResponse(
Assert.AreEqual(changeFeedReturnedDocs.Count, 2);
- VerifyExpectedDocResponse(testDoc1, changeFeedReturnedDocs[changeFeedReturnedDocs.Count - 2]);
- VerifyExpectedDocResponse(testDoc2, changeFeedReturnedDocs[changeFeedReturnedDocs.Count - 1]);
+ VerifyExpectedDocResponse(testDoc1, changeFeedReturnedDocs[^2]);
+ VerifyExpectedDocResponse(testDoc2, changeFeedReturnedDocs[^1]);
if (leaseDatabase != null)
{
@@ -3303,64 +3247,97 @@ public Stream ToStream()
}
}
- internal class TestEncryptionKeyWrapProvider : EncryptionKeyWrapProvider
+ internal class TestKeyEncryptionKey : IKeyEncryptionKey
{
- readonly Dictionary keyinfo = new Dictionary
+ private static readonly Dictionary keyinfo = new Dictionary
{
{"tempmetadata1", 1},
{"tempmetadata2", 2},
};
- public bool RevokeAccessSet { get; set; }
+ private readonly TestKeyEncryptionKeyResolver resolver;
- public Dictionary WrapKeyCallsCount { get; set; }
-
- public Dictionary UnWrapKeyCallsCount { get; set; }
-
- public TestEncryptionKeyWrapProvider()
+ public TestKeyEncryptionKey(string keyId, TestKeyEncryptionKeyResolver resolver)
{
- this.WrapKeyCallsCount = new Dictionary();
- this.UnWrapKeyCallsCount = new Dictionary();
- this.RevokeAccessSet = false;
+ this.KeyId = keyId;
+ this.resolver = resolver;
}
- public override string ProviderName => "TESTKEYSTORE_VAULT";
+ public string KeyId { get; }
- public override Task UnwrapKeyAsync(string masterKeyPath, string keyEncryptionKeyAlgorithm, byte[] encryptedKey)
+ public byte[] UnwrapKey(string algorithm, ReadOnlyMemory encryptedKey, CancellationToken cancellationToken = default)
{
- if (masterKeyPath.Equals("revokedKek-metadata") && this.RevokeAccessSet)
+ if (this.KeyId.Equals("revokedKek-metadata") && this.resolver.RevokeAccessSet)
{
throw new RequestFailedException((int)HttpStatusCode.Forbidden, "Forbidden");
}
- if (!this.UnWrapKeyCallsCount.ContainsKey(masterKeyPath))
+ if (!this.resolver.UnWrapKeyCallsCount.ContainsKey(this.KeyId))
{
- this.UnWrapKeyCallsCount[masterKeyPath] = 1;
+ this.resolver.UnWrapKeyCallsCount[this.KeyId] = 1;
}
else
{
- this.UnWrapKeyCallsCount[masterKeyPath]++;
+ this.resolver.UnWrapKeyCallsCount[this.KeyId]++;
}
- this.keyinfo.TryGetValue(masterKeyPath, out int moveBy);
- byte[] plainkey = encryptedKey.Select(b => (byte)(b - moveBy)).ToArray();
- return Task.FromResult(plainkey);
+ keyinfo.TryGetValue(this.KeyId, out int moveBy);
+ byte[] plainkey = encryptedKey.ToArray().Select(b => (byte)(b - moveBy)).ToArray();
+ return plainkey;
+ }
+
+ public Task UnwrapKeyAsync(string algorithm, ReadOnlyMemory encryptedKey, CancellationToken cancellationToken = default)
+ {
+ return Task.FromResult(this.UnwrapKey(algorithm, encryptedKey, cancellationToken));
}
- public override Task WrapKeyAsync(string masterKeyPath, string keyEncryptionKeyAlgorithm, byte[] key)
+ public byte[] WrapKey(string algorithm, ReadOnlyMemory key, CancellationToken cancellationToken = default)
{
- if (!this.WrapKeyCallsCount.ContainsKey(masterKeyPath))
+ if (!this.resolver.WrapKeyCallsCount.ContainsKey(this.KeyId))
{
- this.WrapKeyCallsCount[masterKeyPath] = 1;
+ this.resolver.WrapKeyCallsCount[this.KeyId] = 1;
}
else
{
- this.WrapKeyCallsCount[masterKeyPath]++;
+ this.resolver.WrapKeyCallsCount[this.KeyId]++;
}
- this.keyinfo.TryGetValue(masterKeyPath, out int moveBy);
- byte[] encryptedkey = key.Select(b => (byte)(b + moveBy)).ToArray();
- return Task.FromResult(encryptedkey);
+ keyinfo.TryGetValue(this.KeyId, out int moveBy);
+ byte[] encryptedkey = key.ToArray().Select(b => (byte)(b + moveBy)).ToArray();
+ return encryptedkey;
+ }
+
+ public Task WrapKeyAsync(string algorithm, ReadOnlyMemory key, CancellationToken cancellationToken = default)
+ {
+ return Task.FromResult(this.WrapKey(algorithm, key, cancellationToken));
+ }
+ }
+
+ internal class TestKeyEncryptionKeyResolver : IKeyEncryptionKeyResolver
+ {
+ public static string Id => "TESTKEYSTORE_VAULT";
+
+ public bool RevokeAccessSet { get; set; }
+
+ public Dictionary WrapKeyCallsCount { get; set; }
+
+ public Dictionary UnWrapKeyCallsCount { get; set; }
+
+ public TestKeyEncryptionKeyResolver()
+ {
+ this.WrapKeyCallsCount = new Dictionary();
+ this.UnWrapKeyCallsCount = new Dictionary();
+ this.RevokeAccessSet = false;
+ }
+
+ public IKeyEncryptionKey Resolve(string keyId, CancellationToken cancellationToken = default)
+ {
+ return new TestKeyEncryptionKey(keyId, this);
+ }
+
+ public Task ResolveAsync(string keyId, CancellationToken cancellationToken = default)
+ {
+ return Task.FromResult(this.Resolve(keyId, cancellationToken));
}
}
diff --git a/Microsoft.Azure.Cosmos.Encryption/tests/Microsoft.Azure.Cosmos.Encryption.Tests/Contracts/DotNetSDKEncryptionAPI.json b/Microsoft.Azure.Cosmos.Encryption/tests/Microsoft.Azure.Cosmos.Encryption.Tests/Contracts/DotNetSDKEncryptionAPI.json
index 8792a2d59c..777fd87529 100644
--- a/Microsoft.Azure.Cosmos.Encryption/tests/Microsoft.Azure.Cosmos.Encryption.Tests/Contracts/DotNetSDKEncryptionAPI.json
+++ b/Microsoft.Azure.Cosmos.Encryption/tests/Microsoft.Azure.Cosmos.Encryption.Tests/Contracts/DotNetSDKEncryptionAPI.json
@@ -1,37 +1,6 @@
{
"Subclasses": {
- "Microsoft.Azure.Cosmos.Encryption.AzureKeyVaultKeyWrapProvider;Microsoft.Azure.Cosmos.Encryption.EncryptionKeyWrapProvider;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": {
- "Subclasses": {},
- "Members": {
- "System.String get_ProviderName()": {
- "Type": "Method",
- "Attributes": [],
- "MethodInfo": "System.String get_ProviderName();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- },
- "System.String ProviderName": {
- "Type": "Property",
- "Attributes": [],
- "MethodInfo": "System.String ProviderName;CanRead:True;CanWrite:False;System.String get_ProviderName();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- },
- "System.Threading.Tasks.Task`1[System.Byte[]] UnwrapKeyAsync(System.String, System.String, Byte[])": {
- "Type": "Method",
- "Attributes": [],
- "MethodInfo": "System.Threading.Tasks.Task`1[System.Byte[]] UnwrapKeyAsync(System.String, System.String, Byte[]);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- },
- "System.Threading.Tasks.Task`1[System.Byte[]] WrapKeyAsync(System.String, System.String, Byte[])": {
- "Type": "Method",
- "Attributes": [],
- "MethodInfo": "System.Threading.Tasks.Task`1[System.Byte[]] WrapKeyAsync(System.String, System.String, Byte[]);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- },
- "Void .ctor(Azure.Core.TokenCredential)": {
- "Type": "Constructor",
- "Attributes": [],
- "MethodInfo": "[Void .ctor(Azure.Core.TokenCredential), Void .ctor(Azure.Core.TokenCredential)]"
- }
- },
- "NestedTypes": {}
- },
- "Microsoft.Azure.Cosmos.Encryption.DataEncryptionKeyAlgorithm;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": {
+ "Microsoft.Azure.Cosmos.Encryption.EncryptionAlgorithm;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": {
"Subclasses": {},
"Members": {
"System.String AeadAes256CbcHmacSha256": {
@@ -80,12 +49,12 @@
"Microsoft.Azure.Cosmos.Encryption.EncryptionCosmosClientExtensions;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": {
"Subclasses": {},
"Members": {
- "Microsoft.Azure.Cosmos.CosmosClient WithEncryption(Microsoft.Azure.Cosmos.CosmosClient, Microsoft.Azure.Cosmos.Encryption.EncryptionKeyWrapProvider)[System.Runtime.CompilerServices.ExtensionAttribute()]": {
+ "Microsoft.Azure.Cosmos.CosmosClient WithEncryption(Microsoft.Azure.Cosmos.CosmosClient, Azure.Core.Cryptography.IKeyEncryptionKeyResolver, System.String, System.Nullable`1[System.TimeSpan])[System.Runtime.CompilerServices.ExtensionAttribute()]": {
"Type": "Method",
"Attributes": [
"ExtensionAttribute"
],
- "MethodInfo": "Microsoft.Azure.Cosmos.CosmosClient WithEncryption(Microsoft.Azure.Cosmos.CosmosClient, Microsoft.Azure.Cosmos.Encryption.EncryptionKeyWrapProvider);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
+ "MethodInfo": "Microsoft.Azure.Cosmos.CosmosClient WithEncryption(Microsoft.Azure.Cosmos.CosmosClient, Azure.Core.Cryptography.IKeyEncryptionKeyResolver, System.String, System.Nullable`1[System.TimeSpan]);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
}
},
"NestedTypes": {}
@@ -112,79 +81,6 @@
},
"NestedTypes": {}
},
- "Microsoft.Azure.Cosmos.Encryption.EncryptionKeyWrapProvider;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": {
- "Subclasses": {
- "Microsoft.Azure.Cosmos.Encryption.AzureKeyVaultKeyWrapProvider;Microsoft.Azure.Cosmos.Encryption.EncryptionKeyWrapProvider;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": {
- "Subclasses": {},
- "Members": {
- "System.String get_ProviderName()": {
- "Type": "Method",
- "Attributes": [],
- "MethodInfo": "System.String get_ProviderName();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- },
- "System.String ProviderName": {
- "Type": "Property",
- "Attributes": [],
- "MethodInfo": "System.String ProviderName;CanRead:True;CanWrite:False;System.String get_ProviderName();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- },
- "System.Threading.Tasks.Task`1[System.Byte[]] UnwrapKeyAsync(System.String, System.String, Byte[])": {
- "Type": "Method",
- "Attributes": [],
- "MethodInfo": "System.Threading.Tasks.Task`1[System.Byte[]] UnwrapKeyAsync(System.String, System.String, Byte[]);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- },
- "System.Threading.Tasks.Task`1[System.Byte[]] WrapKeyAsync(System.String, System.String, Byte[])": {
- "Type": "Method",
- "Attributes": [],
- "MethodInfo": "System.Threading.Tasks.Task`1[System.Byte[]] WrapKeyAsync(System.String, System.String, Byte[]);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- },
- "Void .ctor(Azure.Core.TokenCredential)": {
- "Type": "Constructor",
- "Attributes": [],
- "MethodInfo": "[Void .ctor(Azure.Core.TokenCredential), Void .ctor(Azure.Core.TokenCredential)]"
- }
- },
- "NestedTypes": {}
- }
- },
- "Members": {
- "System.Nullable`1[System.TimeSpan] DataEncryptionKeyCacheTimeToLive": {
- "Type": "Property",
- "Attributes": [],
- "MethodInfo": "System.Nullable`1[System.TimeSpan] DataEncryptionKeyCacheTimeToLive;CanRead:True;CanWrite:True;System.Nullable`1[System.TimeSpan] get_DataEncryptionKeyCacheTimeToLive();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_DataEncryptionKeyCacheTimeToLive(System.Nullable`1[System.TimeSpan]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- },
- "System.Nullable`1[System.TimeSpan] get_DataEncryptionKeyCacheTimeToLive()": {
- "Type": "Method",
- "Attributes": [],
- "MethodInfo": "System.Nullable`1[System.TimeSpan] get_DataEncryptionKeyCacheTimeToLive();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- },
- "System.String get_ProviderName()": {
- "Type": "Method",
- "Attributes": [],
- "MethodInfo": "System.String get_ProviderName();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- },
- "System.String ProviderName": {
- "Type": "Property",
- "Attributes": [],
- "MethodInfo": "System.String ProviderName;CanRead:True;CanWrite:False;System.String get_ProviderName();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- },
- "System.Threading.Tasks.Task`1[System.Byte[]] UnwrapKeyAsync(System.String, System.String, Byte[])": {
- "Type": "Method",
- "Attributes": [],
- "MethodInfo": "System.Threading.Tasks.Task`1[System.Byte[]] UnwrapKeyAsync(System.String, System.String, Byte[]);IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- },
- "System.Threading.Tasks.Task`1[System.Byte[]] WrapKeyAsync(System.String, System.String, Byte[])": {
- "Type": "Method",
- "Attributes": [],
- "MethodInfo": "System.Threading.Tasks.Task`1[System.Byte[]] WrapKeyAsync(System.String, System.String, Byte[]);IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- },
- "Void set_DataEncryptionKeyCacheTimeToLive(System.Nullable`1[System.TimeSpan])": {
- "Type": "Method",
- "Attributes": [],
- "MethodInfo": "Void set_DataEncryptionKeyCacheTimeToLive(System.Nullable`1[System.TimeSpan]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
- }
- },
- "NestedTypes": {}
- },
"Microsoft.Azure.Cosmos.Encryption.EncryptionType;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": {
"Subclasses": {},
"Members": {
@@ -201,13 +97,13 @@
},
"NestedTypes": {}
},
- "Microsoft.Azure.Cosmos.Encryption.KeyEncryptionKeyAlgorithm;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": {
+ "Microsoft.Azure.Cosmos.Encryption.KeyEncryptionKeyResolverName;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": {
"Subclasses": {},
"Members": {
- "System.String RsaOaep": {
+ "System.String AzureKeyVault": {
"Type": "Field",
"Attributes": [],
- "MethodInfo": "System.String RsaOaep;IsInitOnly:False;IsStatic:True;"
+ "MethodInfo": "System.String AzureKeyVault;IsInitOnly:False;IsStatic:True;"
}
},
"NestedTypes": {}