/// <summary> /// Initializes a new instance of the <see cref="AzureKeyVaultKeyWrapProvider"/> class. /// Constructor that takes an implementation of Token Credential that is capable of providing an OAuth Token. /// </summary> /// <param name="tokenCredential"> returns token credentials. </param> 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, }; }
public void TokenCredentialWorks() { AzureKeyVaultKeyStoreProvider akvProvider = new AzureKeyVaultKeyStoreProvider(new ClientSecretCredential(tenantId, clientId, clientSecret)); byte[] encryptedCek = akvProvider.WrapKey(keyEncryptionKeyPath, EncryptionAlgorithm, ColumnEncryptionKey); byte[] decryptedCek = akvProvider.UnwrapKey(keyEncryptionKeyPath, EncryptionAlgorithm, encryptedCek); Assert.Equal(ColumnEncryptionKey, decryptedCek); }
public void BackwardCompatibilityWithAuthenticationCallbackWorks() { AzureKeyVaultKeyStoreProvider akvProvider = new AzureKeyVaultKeyStoreProvider(AzureActiveDirectoryAuthenticationCallback); byte[] encryptedCek = akvProvider.WrapKey(keyEncryptionKeyPath, EncryptionAlgorithm, ColumnEncryptionKey); byte[] decryptedCek = akvProvider.UnwrapKey(keyEncryptionKeyPath, EncryptionAlgorithm, encryptedCek); Assert.Equal(ColumnEncryptionKey, decryptedCek); }
public void IsCompatibleWithProviderUsingLegacyClient() { AzureKeyVaultKeyStoreProvider newAkvProvider = new AzureKeyVaultKeyStoreProvider(new ClientSecretCredential(tenantId, clientId, clientSecret)); SqlColumnEncryptionAzureKeyVaultProvider oldAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(AzureActiveDirectoryAuthenticationCallback); byte[] encryptedCekWithNewProvider = newAkvProvider.WrapKey(keyEncryptionKeyPath, EncryptionAlgorithm, ColumnEncryptionKey); byte[] decryptedCekWithOldProvider = oldAkvProvider.DecryptColumnEncryptionKey(keyEncryptionKeyPath, EncryptionAlgorithm.ToString(), encryptedCekWithNewProvider); Assert.Equal(ColumnEncryptionKey, decryptedCekWithOldProvider); byte[] encryptedCekWithOldProvider = oldAkvProvider.EncryptColumnEncryptionKey(keyEncryptionKeyPath, EncryptionAlgorithm.ToString(), ColumnEncryptionKey); byte[] decryptedCekWithNewProvider = newAkvProvider.UnwrapKey(keyEncryptionKeyPath, EncryptionAlgorithm, encryptedCekWithOldProvider); Assert.Equal(ColumnEncryptionKey, decryptedCekWithNewProvider); }
// <Main> public static async Task Main(string[] _) { try { // Read the Cosmos endpointUrl and authorizationKey from configuration. // These values are available from the Azure Management Portal on the Cosmos Account Blade under "Keys". // Keep these values in a safe and secure location. Together they provide administrative access to your Cosmos account. IConfigurationRoot configuration = new ConfigurationBuilder() .AddJsonFile("appSettings.json") .Build(); // Get the Akv Master Key Path. MasterKeyUrl = configuration["MasterKeyUrl"]; if (string.IsNullOrEmpty(MasterKeyUrl)) { throw new ArgumentNullException("Please specify a valid Azure Key Path in the appSettings.json"); } // Get the Token Credential that is capable of providing an OAuth Token. TokenCredential tokenCredential = GetTokenCredential(configuration); AzureKeyVaultKeyStoreProvider azureKeyVaultKeyStoreProvider = new AzureKeyVaultKeyStoreProvider(tokenCredential); Program.client = Program.CreateClientInstance(configuration, azureKeyVaultKeyStoreProvider); await Program.AdminSetupAsync(client, azureKeyVaultKeyStoreProvider); await Program.RunDemoAsync(); } catch (CosmosException cre) { Console.WriteLine(cre.ToString()); } catch (Exception e) { Exception baseException = e.GetBaseException(); Console.WriteLine("Message: {0} Error: {1}", baseException.Message, e); } finally { Console.WriteLine("End of demo, press any key to exit."); Console.ReadKey(); await Program.CleanupAsync(); } }
// </Main> private static CosmosClient CreateClientInstance(IConfigurationRoot configuration, AzureKeyVaultKeyStoreProvider azureKeyVaultKeyStoreProvider) { string endpoint = configuration["EndPointUrl"]; if (string.IsNullOrEmpty(endpoint)) { throw new ArgumentNullException("Please specify a valid endpoint in the appSettings.json"); } string authKey = configuration["AuthorizationKey"]; if (string.IsNullOrEmpty(authKey) || string.Equals(authKey, "Super secret key")) { throw new ArgumentException("Please specify a valid AuthorizationKey in the appSettings.json"); } CosmosClient encryptionCosmosClient = new CosmosClient(endpoint, authKey); // enable encryption support on the cosmos client. return(encryptionCosmosClient.WithEncryption(azureKeyVaultKeyStoreProvider)); }
/// <summary> /// Administrative operations - create the database, container, and generate the necessary client encryption keys. /// These are initializations and are expected to be invoked only once - do not invoke these before every item request. /// </summary> private static async Task AdminSetupAsync(CosmosClient client, AzureKeyVaultKeyStoreProvider azureKeyVaultKeyStoreProvider) { Database database = await client.CreateDatabaseIfNotExistsAsync(Program.encryptedDatabaseId); // Delete the existing container to prevent create item conflicts. using (await database.GetContainer(Program.encryptedContainerId).DeleteContainerStreamAsync()) { } Console.WriteLine("The demo will create a 1000 RU/s container, press any key to continue."); Console.ReadKey(); // Create the Client Encryption Keys for Encrypting the configured Paths. await database.CreateClientEncryptionKeyAsync( "key1", DataEncryptionKeyAlgorithm.AEAD_AES_256_CBC_HMAC_SHA256, new EncryptionKeyWrapMetadata(azureKeyVaultKeyStoreProvider.ProviderName, "akvMasterKey", MasterKeyUrl)); await database.CreateClientEncryptionKeyAsync( "key2", DataEncryptionKeyAlgorithm.AEAD_AES_256_CBC_HMAC_SHA256, new EncryptionKeyWrapMetadata(azureKeyVaultKeyStoreProvider.ProviderName, "akvMasterKey", MasterKeyUrl)); // Configure the required Paths to be Encrypted with appropriate settings. ClientEncryptionIncludedPath path1 = new ClientEncryptionIncludedPath() { Path = "/SubTotal", ClientEncryptionKeyId = "key1", EncryptionType = EncryptionType.Deterministic.ToString(), EncryptionAlgorithm = DataEncryptionKeyAlgorithm.AEAD_AES_256_CBC_HMAC_SHA256.ToString() }; // non primitive data type.Leaves get encrypted. ClientEncryptionIncludedPath path2 = new ClientEncryptionIncludedPath() { Path = "/Items", ClientEncryptionKeyId = "key2", EncryptionType = EncryptionType.Deterministic.ToString(), EncryptionAlgorithm = DataEncryptionKeyAlgorithm.AEAD_AES_256_CBC_HMAC_SHA256.ToString() }; ClientEncryptionIncludedPath path3 = new ClientEncryptionIncludedPath() { Path = "/OrderDate", ClientEncryptionKeyId = "key1", EncryptionType = EncryptionType.Deterministic.ToString(), EncryptionAlgorithm = DataEncryptionKeyAlgorithm.AEAD_AES_256_CBC_HMAC_SHA256.ToString() }; // Create a container with the appropriate partition key definition (we choose the "AccountNumber" property here) and throughput (we choose 1000 here). // Configure the Client Encryption Key Policy with required paths to be encrypted. await database.DefineContainer(Program.encryptedContainerId, "/AccountNumber") .WithClientEncryptionPolicy() .WithIncludedPath(path1) .WithIncludedPath(path2) .WithIncludedPath(path3) .Attach() .CreateAsync(throughput: 1000); // gets a Container with Encryption Support. containerWithEncryption = await database.GetContainer(Program.encryptedContainerId).InitializeEncryptionAsync(); }