diff --git a/docs/modules/azure.md b/docs/modules/azure.md
index 5e80270e90c..19c141c7639 100644
--- a/docs/modules/azure.md
+++ b/docs/modules/azure.md
@@ -5,14 +5,73 @@ This module is INCUBATING. While it is ready for use and operational in the curr
Testcontainers module for the Microsoft Azure's [SDK](https://github.com/Azure/azure-sdk-for-java).
-Currently, the module supports `CosmosDB` emulator. In order to use it, you should use the following class:
+Currently, the module supports `Azurite` and `CosmosDB` emulators. In order to use them, you should use the following classes:
Class | Container Image
-|-
+AzuriteContainer | [mcr.microsoft.com/azure-storage/azurite](https://github.com/microsoft/containerregistry)
CosmosDBEmulatorContainer | [mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator](https://github.com/microsoft/containerregistry)
## Usage example
+### Azurite Storage Emulator
+
+Start Azurite Emulator during a test:
+
+
+[Starting a Azurite container](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:emulatorContainer
+
+
+!!! note
+ SSL configuration is possible using the `withSsl(MountableFile, String)` and `withSsl(MountableFile, MountableFile)` methods.
+
+If the tested application needs to use more than one set of credentials, the container can be configured to use custom credentials.
+Please see some examples below.
+
+
+[Starting a Azurite Blob container with one account and two keys](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:withTwoAccountKeys
+
+
+
+[Starting a Azurite Blob container with more accounts and keys](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:withMoreAccounts
+
+
+#### Using with Blob
+
+Build Azure Blob client:
+
+
+[Build Azure Blob Service client](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:createBlobClient
+
+
+In case the application needs to use custom credentials, we can obtain them with a different method:
+
+
+[Obtain connection string with non-default credentials](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:useNonDefaultCredentials
+
+
+#### Using with Queue
+
+Build Azure Queue client:
+
+
+[Build Azure Queue Service client](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:createQueueClient
+
+
+!!! note
+ We can use custom credentials the same way as defined in the Blob section.
+
+#### Using with Table
+
+Build Azure Table client:
+
+
+[Build Azure Table Service client](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:createTableClient
+
+
+!!! note
+ We can use custom credentials the same way as defined in the Blob section.
+
### CosmosDB
Start Azure CosmosDB Emulator during a test:
diff --git a/modules/azure/build.gradle b/modules/azure/build.gradle
index d31a549abe5..c6cfb6738d0 100644
--- a/modules/azure/build.gradle
+++ b/modules/azure/build.gradle
@@ -7,4 +7,7 @@ dependencies {
testImplementation 'org.assertj:assertj-core:3.26.3'
testImplementation 'com.azure:azure-cosmos:4.63.3'
+ testImplementation 'com.azure:azure-storage-blob:12.29.0'
+ testImplementation 'com.azure:azure-storage-queue:12.24.0'
+ testImplementation 'com.azure:azure-data-tables:12.5.0'
}
diff --git a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java
new file mode 100644
index 00000000000..56c58df1f1d
--- /dev/null
+++ b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java
@@ -0,0 +1,167 @@
+package org.testcontainers.azure;
+
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.utility.DockerImageName;
+import org.testcontainers.utility.MountableFile;
+
+/**
+ * Testcontainers implementation for Azurite Emulator.
+ *
+ * Supported image: {@code mcr.microsoft.com/azure-storage/azurite}
+ *
+ * Exposed ports:
+ *
+ * - Blob: 10000
+ * - Queue: 10001
+ * - Table: 10002
+ *
+ */
+public class AzuriteContainer extends GenericContainer {
+
+ private static final String ALLOW_ALL_CONNECTIONS = "0.0.0.0";
+
+ private static final int DEFAULT_BLOB_PORT = 10000;
+
+ private static final int DEFAULT_QUEUE_PORT = 10001;
+
+ private static final int DEFAULT_TABLE_PORT = 10002;
+
+ private static final String CONNECTION_STRING_FORMAT =
+ "DefaultEndpointsProtocol=%s;AccountName=%s;AccountKey=%s;BlobEndpoint=%s://%s:%d/%s;QueueEndpoint=%s://%s:%d/%s;TableEndpoint=%s://%s:%d/%s;";
+
+ /**
+ * The account name of the default credentials.
+ */
+ private static final String WELL_KNOWN_ACCOUNT_NAME = "devstoreaccount1";
+
+ /**
+ * The account key of the default credentials.
+ */
+ private static final String WELL_KNOWN_ACCOUNT_KEY =
+ "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==";
+
+ private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse(
+ "mcr.microsoft.com/azure-storage/azurite"
+ );
+
+ private MountableFile cert = null;
+
+ private String certExtension = null;
+
+ private MountableFile key = null;
+
+ private String pwd = null;
+
+ /**
+ * @param dockerImageName specified docker image name to run
+ */
+ public AzuriteContainer(String dockerImageName) {
+ this(DockerImageName.parse(dockerImageName));
+ }
+
+ /**
+ * @param dockerImageName specified docker image name to run
+ */
+ public AzuriteContainer(DockerImageName dockerImageName) {
+ super(dockerImageName);
+ dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);
+ withExposedPorts(DEFAULT_BLOB_PORT, DEFAULT_QUEUE_PORT, DEFAULT_TABLE_PORT);
+ }
+
+ /**
+ * Configure SSL with a custom certificate and password.
+ *
+ * @param pfxCert The PFX certificate file
+ * @param password The password securing the certificate
+ * @return this
+ */
+ public AzuriteContainer withSsl(final MountableFile pfxCert, final String password) {
+ this.cert = pfxCert;
+ this.pwd = password;
+ this.certExtension = ".pfx";
+ return this;
+ }
+
+ /**
+ * Configure SSL with a custom certificate and private key.
+ *
+ * @param pemCert The PEM certificate file
+ * @param pemKey The PEM key file
+ * @return this
+ */
+ public AzuriteContainer withSsl(final MountableFile pemCert, final MountableFile pemKey) {
+ this.cert = pemCert;
+ this.key = pemKey;
+ this.certExtension = ".pem";
+ return this;
+ }
+
+ @Override
+ protected void configure() {
+ withCommand(getCommandLine());
+ if (this.cert != null) {
+ logger().info("Using path for cert file: '{}'", this.cert);
+ withCopyFileToContainer(this.cert, "/cert" + this.certExtension);
+ if (this.key != null) {
+ logger().info("Using path for key file: '{}'", this.key);
+ withCopyFileToContainer(this.key, "/key.pem");
+ }
+ }
+ }
+
+ /**
+ * Returns the connection string for the default credentials.
+ *
+ * @return connection string
+ */
+ public String getConnectionString() {
+ return getConnectionString(WELL_KNOWN_ACCOUNT_NAME, WELL_KNOWN_ACCOUNT_KEY);
+ }
+
+ /**
+ * Returns the connection string for the account name and key specified.
+ *
+ * @param accountName The name of the account
+ * @param accountKey The account key
+ * @return connection string
+ */
+ public String getConnectionString(final String accountName, final String accountKey) {
+ final String protocol = cert != null ? "https" : "http";
+ return String.format(
+ CONNECTION_STRING_FORMAT,
+ protocol,
+ accountName,
+ accountKey,
+ protocol,
+ getHost(),
+ getMappedPort(DEFAULT_BLOB_PORT),
+ accountName,
+ protocol,
+ getHost(),
+ getMappedPort(DEFAULT_QUEUE_PORT),
+ accountName,
+ protocol,
+ getHost(),
+ getMappedPort(DEFAULT_TABLE_PORT),
+ accountName
+ );
+ }
+
+ String getCommandLine() {
+ final StringBuilder args = new StringBuilder("azurite");
+ args.append(" --blobHost ").append(ALLOW_ALL_CONNECTIONS);
+ args.append(" --queueHost ").append(ALLOW_ALL_CONNECTIONS);
+ args.append(" --tableHost ").append(ALLOW_ALL_CONNECTIONS);
+ if (this.cert != null) {
+ args.append(" --cert ").append("/cert").append(this.certExtension);
+ if (this.pwd != null) {
+ args.append(" --pwd ").append(this.pwd);
+ } else {
+ args.append(" --key ").append("/key.pem");
+ }
+ }
+ final String cmd = args.toString();
+ logger().debug("Using command line: '{}'", cmd);
+ return cmd;
+ }
+}
diff --git a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java
new file mode 100644
index 00000000000..2bf0ad856d3
--- /dev/null
+++ b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java
@@ -0,0 +1,266 @@
+package org.testcontainers.azure;
+
+import com.azure.core.util.BinaryData;
+import com.azure.data.tables.TableClient;
+import com.azure.data.tables.TableServiceClient;
+import com.azure.data.tables.TableServiceClientBuilder;
+import com.azure.storage.blob.BlobClient;
+import com.azure.storage.blob.BlobContainerClient;
+import com.azure.storage.blob.BlobServiceClient;
+import com.azure.storage.blob.BlobServiceClientBuilder;
+import com.azure.storage.queue.QueueClient;
+import com.azure.storage.queue.QueueServiceClient;
+import com.azure.storage.queue.QueueServiceClientBuilder;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.testcontainers.utility.MountableFile;
+
+import java.util.Properties;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class AzuriteContainerTest {
+
+ private static final String PASSWORD = "changeit";
+
+ private static Properties originalSystemProperties;
+
+ @BeforeClass
+ public static void captureOriginalSystemProperties() {
+ originalSystemProperties = (Properties) System.getProperties().clone();
+ System.setProperty(
+ "javax.net.ssl.trustStore",
+ MountableFile.forClasspathResource("/keystore.pfx").getFilesystemPath()
+ );
+ System.setProperty("javax.net.ssl.trustStorePassword", PASSWORD);
+ System.setProperty("javax.net.ssl.trustStoreType", "PKCS12");
+ }
+
+ @AfterClass
+ public static void restoreOriginalSystemProperties() {
+ System.setProperties(originalSystemProperties);
+ }
+
+ @Test
+ public void testWithBlobServiceClient() {
+ try (
+ // emulatorContainer {
+ AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0")
+ // }
+ ) {
+ emulator.start();
+ assertThat(emulator.getConnectionString()).contains("BlobEndpoint=http://");
+ testBlob(emulator);
+ }
+ }
+
+ @Test
+ public void testWithQueueServiceClient() {
+ try (AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0")) {
+ emulator.start();
+ assertThat(emulator.getConnectionString()).contains("QueueEndpoint=http://");
+ testQueue(emulator);
+ }
+ }
+
+ @Test
+ public void testWithTableServiceClient() {
+ try (AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0")) {
+ emulator.start();
+ assertThat(emulator.getConnectionString()).contains("TableEndpoint=http://");
+ testTable(emulator);
+ }
+ }
+
+ @Test
+ public void testWithBlobServiceClientWithSslUsingPfx() {
+ try (
+ AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0")
+ .withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD)
+ ) {
+ emulator.start();
+ assertThat(emulator.getConnectionString()).contains("BlobEndpoint=https://");
+ testBlob(emulator);
+ }
+ }
+
+ @Test
+ public void testWithQueueServiceClientWithSslUsingPfx() {
+ try (
+ AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0")
+ .withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD)
+ ) {
+ emulator.start();
+ assertThat(emulator.getConnectionString()).contains("QueueEndpoint=https://");
+ testQueue(emulator);
+ }
+ }
+
+ @Test
+ public void testWithTableServiceClientWithSslUsingPfx() {
+ try (
+ AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0")
+ .withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD)
+ ) {
+ emulator.start();
+ assertThat(emulator.getConnectionString()).contains("TableEndpoint=https://");
+ testTable(emulator);
+ }
+ }
+
+ @Test
+ public void testWithBlobServiceClientWithSslUsingPem() {
+ try (
+ AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0")
+ .withSsl(
+ MountableFile.forClasspathResource("/certificate.pem"),
+ MountableFile.forClasspathResource("/key.pem")
+ )
+ ) {
+ emulator.start();
+ assertThat(emulator.getConnectionString()).contains("BlobEndpoint=https://");
+ testBlob(emulator);
+ }
+ }
+
+ @Test
+ public void testWithQueueServiceClientWithSslUsingPem() {
+ try (
+ AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0")
+ .withSsl(
+ MountableFile.forClasspathResource("/certificate.pem"),
+ MountableFile.forClasspathResource("/key.pem")
+ )
+ ) {
+ emulator.start();
+ assertThat(emulator.getConnectionString()).contains("QueueEndpoint=https://");
+ testQueue(emulator);
+ }
+ }
+
+ @Test
+ public void testWithTableServiceClientWithSslUsingPem() {
+ try (
+ AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0")
+ .withSsl(
+ MountableFile.forClasspathResource("/certificate.pem"),
+ MountableFile.forClasspathResource("/key.pem")
+ )
+ ) {
+ emulator.start();
+ assertThat(emulator.getConnectionString()).contains("TableEndpoint=https://");
+ testTable(emulator);
+ }
+ }
+
+ @Test
+ public void testTwoAccountKeysWithBlobServiceClient() {
+ try (
+ // withTwoAccountKeys {
+ AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0")
+ .withEnv("AZURITE_ACCOUNTS", "account1:key1:key2")
+ // }
+ ) {
+ emulator.start();
+
+ String connectionString1 = emulator.getConnectionString("account1", "key1");
+ // the second account will have access to the same container using a different key
+ String connectionString2 = emulator.getConnectionString("account1", "key2");
+
+ BlobServiceClient blobServiceClient1 = new BlobServiceClientBuilder()
+ .connectionString(connectionString1)
+ .buildClient();
+
+ BlobContainerClient containerClient1 = blobServiceClient1.createBlobContainer("test-container");
+ BlobClient blobClient1 = containerClient1.getBlobClient("test-blob.txt");
+ blobClient1.upload(BinaryData.fromString("content"));
+ boolean existsWithAccount1 = blobClient1.exists();
+ String contentWithAccount1 = blobClient1.downloadContent().toString();
+
+ BlobServiceClient blobServiceClient2 = new BlobServiceClientBuilder()
+ .connectionString(connectionString2)
+ .buildClient();
+ BlobContainerClient containerClient2 = blobServiceClient2.getBlobContainerClient("test-container");
+ BlobClient blobClient2 = containerClient2.getBlobClient("test-blob.txt");
+ boolean existsWithAccount2 = blobClient2.exists();
+ String contentWithAccount2 = blobClient2.downloadContent().toString();
+
+ assertThat(existsWithAccount1).isTrue();
+ assertThat(contentWithAccount1).isEqualTo("content");
+ assertThat(existsWithAccount2).isTrue();
+ assertThat(contentWithAccount2).isEqualTo("content");
+ }
+ }
+
+ @Test
+ public void testMultipleAccountsWithBlobServiceClient() {
+ try (
+ // withMoreAccounts {
+ AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0")
+ .withEnv("AZURITE_ACCOUNTS", "account1:key1;account2:key2")
+ // }
+ ) {
+ emulator.start();
+
+ // useNonDefaultCredentials {
+ String connectionString1 = emulator.getConnectionString("account1", "key1");
+ // the second account will not have access to the same container
+ String connectionString2 = emulator.getConnectionString("account2", "key2");
+ // }
+ BlobServiceClient blobServiceClient1 = new BlobServiceClientBuilder()
+ .connectionString(connectionString1)
+ .buildClient();
+
+ BlobContainerClient containerClient1 = blobServiceClient1.createBlobContainer("test-container");
+ BlobClient blobClient1 = containerClient1.getBlobClient("test-blob.txt");
+ blobClient1.upload(BinaryData.fromString("content"));
+ boolean existsWithAccount1 = blobClient1.exists();
+ String contentWithAccount1 = blobClient1.downloadContent().toString();
+
+ BlobServiceClient blobServiceClient2 = new BlobServiceClientBuilder()
+ .connectionString(connectionString2)
+ .buildClient();
+ BlobContainerClient containerClient2 = blobServiceClient2.createBlobContainer("test-container");
+ BlobClient blobClient2 = containerClient2.getBlobClient("test-blob.txt");
+ boolean existsWithAccount2 = blobClient2.exists();
+
+ assertThat(existsWithAccount1).isTrue();
+ assertThat(contentWithAccount1).isEqualTo("content");
+ assertThat(existsWithAccount2).isFalse();
+ }
+ }
+
+ private void testBlob(AzuriteContainer container) {
+ // createBlobClient {
+ BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
+ .connectionString(container.getConnectionString())
+ .buildClient();
+ // }
+ BlobContainerClient containerClient = blobServiceClient.createBlobContainer("test-container");
+
+ assertThat(containerClient.exists()).isTrue();
+ }
+
+ private void testQueue(AzuriteContainer container) {
+ // createQueueClient {
+ QueueServiceClient queueServiceClient = new QueueServiceClientBuilder()
+ .connectionString(container.getConnectionString())
+ .buildClient();
+ // }
+ QueueClient queueClient = queueServiceClient.createQueue("test-queue");
+
+ assertThat(queueClient.getQueueUrl()).isNotNull();
+ }
+
+ private void testTable(AzuriteContainer container) {
+ // createTableClient {
+ TableServiceClient tableServiceClient = new TableServiceClientBuilder()
+ .connectionString(container.getConnectionString())
+ .buildClient();
+ // }
+ TableClient tableClient = tableServiceClient.createTable("testtable");
+
+ assertThat(tableClient.getTableEndpoint()).isNotNull();
+ }
+}
diff --git a/modules/azure/src/test/resources/certificate.pem b/modules/azure/src/test/resources/certificate.pem
new file mode 100644
index 00000000000..30bedc29f45
--- /dev/null
+++ b/modules/azure/src/test/resources/certificate.pem
@@ -0,0 +1,23 @@
+Bag Attributes
+ friendlyName: localhost
+ localKeyID: 54 69 6D 65 20 31 37 33 34 37 32 32 33 32 31 33 31 39
+subject=CN = localhost
+issuer=CN = localhost
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAc+gAwIBAgIILe7i2bhRE5cwDQYJKoZIhvcNAQEMBQAwFDESMBAGA1UE
+AxMJbG9jYWxob3N0MB4XDTI0MTIyMDE5MTg0MVoXDTQ0MTIxNTE5MTg0MVowFDES
+MBAGA1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAoqYNmLl8IiIoYrXdcoWiMQaM0lOHcV9v3A/THMremHxsR+JPm3FIOAuilFcy
+my16kuXIWHfisPxUWr9Vbf8wP/WwZutoOofJrqmruZoorQcNLCs8mQweguRmL1ju
+/lDh/9bP626vP9OjwStC4UO4f8Jga8ENoH1U+j1RsIAswYnkk3YIN6YrYv66UvtH
+IfR0ERgid2LMBIM+2KD2zw4QRyqXH7Qvo7sCsxdYYHGa6GXfza4vgvce9kJwGqn5
+wiF0Uw9XQbr/LarnR2GCy020OB81KweQJNIh27FZSRLtT+XpsjDRcC2aLBd8CRHd
+hwO2zAPI04dLbLM5XAHlEdfT7wIDAQABoz0wOzAdBgNVHQ4EFgQUPqY5isb6Q11Q
+t6dbXYHEupxADdMwGgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMA0GCSqGSIb3
+DQEBDAUAA4IBAQA2katMXrTJBukiNh9yceLO/MewsxvU3KOO/O89ngfjhKXm9T8E
+RtENCmp7hLbj1Aj4PRZx3AbmUt9+tRu8fmrRXJQWgUDSHJWjDwSTBOaHcC5LDWSU
+Ex4co5Mnxvrimg7tqQg82Hw/yLH9j6gyTyh6v45QETP7IUkTZe4fg75/kPjng7Xg
+wp/QXFUx/f0dbvGRl2Fdgg0SnYFqHS3MFIjjFjv8SQlV7rZe+CD1Lxqy/Z6Fd/Fa
+33TzTuJeSAG43vdkGAvsNK/KdnxAW03T4l3pVHpNPcvsIvJUMeKOwYOjwHF/eowk
+tGrKbpUYFxUr9iKHTfu14t1oExhAsnda2Fcs
+-----END CERTIFICATE-----
diff --git a/modules/azure/src/test/resources/key.pem b/modules/azure/src/test/resources/key.pem
new file mode 100644
index 00000000000..7c635f5a278
--- /dev/null
+++ b/modules/azure/src/test/resources/key.pem
@@ -0,0 +1,32 @@
+Bag Attributes
+ friendlyName: localhost
+ localKeyID: 54 69 6D 65 20 31 37 33 34 37 32 32 33 32 31 33 31 39
+Key Attributes:
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCipg2YuXwiIihi
+td1yhaIxBozSU4dxX2/cD9Mcyt6YfGxH4k+bcUg4C6KUVzKbLXqS5chYd+Kw/FRa
+v1Vt/zA/9bBm62g6h8muqau5miitBw0sKzyZDB6C5GYvWO7+UOH/1s/rbq8/06PB
+K0LhQ7h/wmBrwQ2gfVT6PVGwgCzBieSTdgg3piti/rpS+0ch9HQRGCJ3YswEgz7Y
+oPbPDhBHKpcftC+juwKzF1hgcZroZd/Nri+C9x72QnAaqfnCIXRTD1dBuv8tqudH
+YYLLTbQ4HzUrB5Ak0iHbsVlJEu1P5emyMNFwLZosF3wJEd2HA7bMA8jTh0tsszlc
+AeUR19PvAgMBAAECggEAFT8dzZKFTawqnGJncBtWyZKyeJMiwUOXSCblDADQPRkb
+x/QfNA4DQhb7AOe3G6BAP8o2dqAKg9YiasxNq5XHRsOgbIFZ1zN/vAo7/X3OzHN8
+XAW138Q+hBiz5IF4js4gB5yXAokt6WeLH6O4E9cV1dKdZ9YLIqjcnee+sRC9R/a3
+CexqLfC6b77JFbtePfq+5cn2RiK540tO/4k+F+kfJtTg78Wf2RB3A0pBAunhPSd5
+eyjiSvOZtTcvl4GdYw9nKf24I1/WUvt9FH/r1XG0CM5iwuGodbBz1iSUDaQGi5Lf
+hFWofXt7eebgsPEKciG4xTyk51p9fy9y8asY+jCbkQKBgQDG2UqJToR8G4Fk6uaO
+/XJa15TibIwQDEota0OdlXg2ZR4864fkIBv+UTbymZEM/EBuSdMM1CUBDvYHcFQX
+Aj8p1LUyKP2QYwxV/OoPfJ5fBqxqONNR1fLFg7xCxnf9kSvsni2WFneQUrTDl8+7
+qnHm4IKPkAxZ4Orxl5qIBmlpGQKBgQDRZUL3cHIVLLg/aZACpo6SYDYg2bztXmz4
+lRk9j17q1uS83Umzd2lPFmSt/Nr85EKraxXZ/lYPKrP/r1pf1/35eXOWqmYBWgo/
+Hh7OzL12bhvv9UWEY/TvW+wNJNtXlJSjEFRN4tjoG2amYumyhwMO1lIulplUWvtw
+ymm8hDjeRwKBgCq7n60KVqZlMtWBNbMc/GpRUgmm0iLQwVApcQp4iLEH4gutgjKg
+Q+PPiENyhR2JSD9rVhO3s4warvzCQw/+x5wxvg7diEBzSL9h7tsNKOu6/2qEc8Vu
+eRHBUb/37ulrPUlIZPuQMHmvjHFMOrRV2MyJCwXXKxBVqafpsKfy2MxhAoGBAIHH
+Cswk6u/ouYDDwjeCVxatfp65lHhhb5RZhD09IIzYBwhu9gC+34veyyNydZ8LMa7g
+PbjQAzJ/OvQbEB4a1hPKjDMzBOmNjpAz8NAm4L4H3FTKZP16nhHDnPdAgpkzQzQV
+KMrk755bbTFuWH0HZIPLnT+2ou0/PltXeFUYdc59AoGBAIGfWgSOiw7aXbSQZFrO
+4S0v3VTwTaiGDVS4pkNRLlhEJUhy8+gbLv/zYDmFmGtqVhXTb/nd6DOdylp+W/HS
+8xNWBMWdlX/hVdSK7M0TdJvAaCaMidlquf5qZ2tGNNDeTUN1qbRH26pm8vdNZ3gr
+Y/WWJGo0iEmwyB8RcFhvNmuJ
+-----END PRIVATE KEY-----
diff --git a/modules/azure/src/test/resources/keystore.pfx b/modules/azure/src/test/resources/keystore.pfx
new file mode 100644
index 00000000000..3fd2975d3e8
Binary files /dev/null and b/modules/azure/src/test/resources/keystore.pfx differ