diff --git a/eng/versioning/version_client.txt b/eng/versioning/version_client.txt
index 2cad87aa76af..2287e6a94a2e 100644
--- a/eng/versioning/version_client.txt
+++ b/eng/versioning/version_client.txt
@@ -27,3 +27,4 @@ com.azure:azure-storage-common;12.1.0;12.2.0-beta.1
com.azure:azure-storage-file-share;12.0.0;12.1.0-beta.1
com.azure:azure-storage-file-datalake;12.0.0-beta.7;12.0.0-beta.8
com.azure:azure-storage-queue;12.1.0;12.2.0-beta.1
+com.azure:azure-e2e;1.0.0-beta.1;1.0.0-beta.1
\ No newline at end of file
diff --git a/pom.client.xml b/pom.client.xml
index e538dd88b0c6..5f80c0d5bbc1 100644
--- a/pom.client.xml
+++ b/pom.client.xml
@@ -1236,5 +1236,6 @@
sdk/storage/azure-storage-file-share
sdk/storage/azure-storage-file-datalake
sdk/storage/azure-storage-queue
+ sdk/e2e
diff --git a/sdk/e2e/pom.xml b/sdk/e2e/pom.xml
new file mode 100644
index 000000000000..95ddeecb9233
--- /dev/null
+++ b/sdk/e2e/pom.xml
@@ -0,0 +1,78 @@
+
+
+ 4.0.0
+
+ com.azure
+ azure-e2e
+ 1.0.0-beta.1
+
+ Microsoft Azure client library end to end tests and samples
+ This module contains end to end tests and samples for Microsoft Azure client libraries.
+ https://github.com/Azure/azure-sdk-for-java
+
+
+ com.azure
+ azure-client-sdk-parent
+ 1.7.0
+ ../../pom.client.xml
+
+
+
+
+ com.azure
+ azure-core
+ 1.2.0-beta.1
+
+
+ com.azure
+ azure-core-http-netty
+ 1.2.0-beta.1
+
+
+ com.azure
+ azure-identity
+ 1.1.0-beta.1
+
+
+ com.azure
+ azure-security-keyvault-keys
+ 4.1.0-beta.1
+
+
+ com.azure
+ azure-security-keyvault-secrets
+ 4.1.0-beta.1
+
+
+ com.azure
+ azure-security-keyvault-certificates
+ 4.0.0-beta.7
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.28
+
+
+
+ com.azure
+ azure-core-test
+ 1.1.0-beta.1
+ test
+
+
+ junit
+ junit
+ 4.13-beta-3
+ test
+
+
+ io.projectreactor
+ reactor-test
+ 3.3.0.RELEASE
+ test
+
+
+
diff --git a/sdk/e2e/src/test/java/com/azure/endtoend/identity/ManagedIdentityCredentialLiveTest.java b/sdk/e2e/src/test/java/com/azure/endtoend/identity/ManagedIdentityCredentialLiveTest.java
new file mode 100644
index 000000000000..ece901c930ad
--- /dev/null
+++ b/sdk/e2e/src/test/java/com/azure/endtoend/identity/ManagedIdentityCredentialLiveTest.java
@@ -0,0 +1,198 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.endtoend.identity;
+
+import com.azure.core.credential.TokenRequestContext;
+import com.azure.core.util.Configuration;
+import com.azure.identity.ManagedIdentityCredential;
+import com.azure.identity.ManagedIdentityCredentialBuilder;
+import com.azure.identity.implementation.IdentityClient;
+import com.azure.identity.implementation.IdentityClientBuilder;
+import com.azure.security.keyvault.secrets.SecretClient;
+import com.azure.security.keyvault.secrets.SecretClientBuilder;
+import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
+import org.junit.Assert;
+import org.junit.Test;
+import reactor.test.StepVerifier;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+
+public class ManagedIdentityCredentialLiveTest {
+ private static final String AZURE_VAULT_URL = "AZURE_VAULT_URL";
+ private static final String VAULT_SECRET_NAME = "secret";
+ private static final Configuration CONFIGURATION = Configuration.getGlobalConfiguration().clone();
+
+ @Test
+ public void testMSIEndpointWithSystemAssigned() throws Exception {
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(Configuration.PROPERTY_MSI_ENDPOINT));
+ org.junit.Assume.assumeTrue(CONFIGURATION.get(Configuration.PROPERTY_AZURE_CLIENT_ID) == null);
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(AZURE_VAULT_URL));
+
+ IdentityClient client = new IdentityClientBuilder().build();
+ StepVerifier.create(client.authenticateToManagedIdentityEndpoint(
+ CONFIGURATION.get(Configuration.PROPERTY_MSI_ENDPOINT),
+ CONFIGURATION.get(Configuration.PROPERTY_MSI_SECRET),
+ new TokenRequestContext().addScopes("https://management.azure.com/.default")))
+ .expectNextMatches(accessToken -> accessToken != null && accessToken.getToken() != null)
+ .verifyComplete();
+ }
+
+ @Test
+ public void testMSIEndpointWithSystemAssignedAccessKeyVault() throws Exception {
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(Configuration.PROPERTY_MSI_ENDPOINT));
+ org.junit.Assume.assumeTrue(CONFIGURATION.get(Configuration.PROPERTY_AZURE_CLIENT_ID) == null);
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(AZURE_VAULT_URL));
+
+ ManagedIdentityCredential credential = new ManagedIdentityCredentialBuilder().build();
+
+ SecretClient client = new SecretClientBuilder()
+ .credential(credential)
+ .vaultUrl(CONFIGURATION.get(AZURE_VAULT_URL))
+ .buildClient();
+
+ KeyVaultSecret secret = client.getSecret(VAULT_SECRET_NAME);
+ Assert.assertNotNull(secret);
+ Assert.assertEquals(VAULT_SECRET_NAME, secret.getName());
+ Assert.assertNotNull(secret.getValue());
+ }
+
+ @Test
+ public void testMSIEndpointWithUserAssigned() throws Exception {
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(Configuration.PROPERTY_MSI_ENDPOINT));
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(Configuration.PROPERTY_AZURE_CLIENT_ID));
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(AZURE_VAULT_URL));
+
+ IdentityClient client = new IdentityClientBuilder()
+ .clientId(CONFIGURATION.get(Configuration.PROPERTY_AZURE_CLIENT_ID))
+ .build();
+ StepVerifier.create(client.authenticateToManagedIdentityEndpoint(
+ CONFIGURATION.get(Configuration.PROPERTY_MSI_ENDPOINT),
+ CONFIGURATION.get(Configuration.PROPERTY_MSI_SECRET),
+ new TokenRequestContext().addScopes("https://management.azure.com/.default")))
+ .expectNextMatches(accessToken -> accessToken != null && accessToken.getToken() != null)
+ .verifyComplete();
+ }
+
+ @Test
+ public void testMSIEndpointWithUserAssignedAccessKeyVault() throws Exception {
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(Configuration.PROPERTY_MSI_ENDPOINT));
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(Configuration.PROPERTY_AZURE_CLIENT_ID));
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(AZURE_VAULT_URL));
+
+ ManagedIdentityCredential credential = new ManagedIdentityCredentialBuilder()
+ .clientId(CONFIGURATION.get(Configuration.PROPERTY_AZURE_CLIENT_ID))
+ .build();
+
+ SecretClient client = new SecretClientBuilder()
+ .credential(credential)
+ .vaultUrl(CONFIGURATION.get(AZURE_VAULT_URL))
+ .buildClient();
+
+ KeyVaultSecret secret = client.getSecret(VAULT_SECRET_NAME);
+ Assert.assertNotNull(secret);
+ Assert.assertEquals(VAULT_SECRET_NAME, secret.getName());
+ Assert.assertNotNull(secret.getValue());
+ }
+
+ @Test
+ public void testIMDSEndpointWithSystemAssigned() throws Exception {
+ org.junit.Assume.assumeTrue(checkIMDSAvailable());
+ org.junit.Assume.assumeTrue(CONFIGURATION.get(Configuration.PROPERTY_AZURE_CLIENT_ID) == null);
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(AZURE_VAULT_URL));
+
+ IdentityClient client = new IdentityClientBuilder().build();
+ StepVerifier.create(client.authenticateToIMDSEndpoint(
+ new TokenRequestContext().addScopes("https://management.azure.com/.default")))
+ .expectNextMatches(accessToken -> accessToken != null && accessToken.getToken() != null)
+ .verifyComplete();
+ }
+
+ @Test
+ public void testIMDSEndpointWithSystemAssignedAccessKeyVault() throws Exception {
+ org.junit.Assume.assumeTrue(checkIMDSAvailable());
+ org.junit.Assume.assumeTrue(CONFIGURATION.get(Configuration.PROPERTY_AZURE_CLIENT_ID) == null);
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(AZURE_VAULT_URL));
+
+ ManagedIdentityCredential credential = new ManagedIdentityCredentialBuilder().build();
+
+ SecretClient client = new SecretClientBuilder()
+ .credential(credential)
+ .vaultUrl(CONFIGURATION.get(AZURE_VAULT_URL))
+ .buildClient();
+
+ KeyVaultSecret secret = client.getSecret(VAULT_SECRET_NAME);
+ Assert.assertNotNull(secret);
+ Assert.assertEquals(VAULT_SECRET_NAME, secret.getName());
+ Assert.assertNotNull(secret.getValue());
+ }
+
+ @Test
+ public void testIMDSEndpointWithUserAssigned() throws Exception {
+ org.junit.Assume.assumeTrue(checkIMDSAvailable());
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(Configuration.PROPERTY_AZURE_CLIENT_ID));
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(AZURE_VAULT_URL));
+
+ IdentityClient client = new IdentityClientBuilder()
+ .clientId(CONFIGURATION.get(Configuration.PROPERTY_AZURE_CLIENT_ID))
+ .build();
+ StepVerifier.create(client.authenticateToIMDSEndpoint(
+ new TokenRequestContext().addScopes("https://management.azure.com/.default")))
+ .expectNextMatches(accessToken -> accessToken != null && accessToken.getToken() != null)
+ .verifyComplete();
+ }
+
+ @Test
+ public void testIMDSEndpointWithUserAssignedAccessKeyVault() throws Exception {
+ org.junit.Assume.assumeTrue(checkIMDSAvailable());
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(Configuration.PROPERTY_AZURE_CLIENT_ID));
+ org.junit.Assume.assumeNotNull(CONFIGURATION.get(AZURE_VAULT_URL));
+
+ ManagedIdentityCredential credential = new ManagedIdentityCredentialBuilder()
+ .clientId(CONFIGURATION.get(Configuration.PROPERTY_AZURE_CLIENT_ID))
+ .build();
+
+ SecretClient client = new SecretClientBuilder()
+ .credential(credential)
+ .vaultUrl(CONFIGURATION.get(AZURE_VAULT_URL))
+ .buildClient();
+
+ KeyVaultSecret secret = client.getSecret(VAULT_SECRET_NAME);
+ Assert.assertNotNull(secret);
+ Assert.assertEquals(VAULT_SECRET_NAME, secret.getName());
+ Assert.assertNotNull(secret.getValue());
+ }
+
+ private boolean checkIMDSAvailable() {
+ StringBuilder payload = new StringBuilder();
+
+ try {
+ payload.append("api-version=");
+ payload.append(URLEncoder.encode("2018-02-01", "UTF-8"));
+ } catch (IOException exception) {
+ return false;
+ }
+
+ HttpURLConnection connection = null;
+
+ try {
+ URL url = new URL(String.format("http://169.254.169.254/metadata/identity/oauth2/token?%s",
+ payload.toString()));
+
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setConnectTimeout(500);
+ connection.connect();
+ return true;
+ } catch (Exception e) {
+ return false;
+ } finally {
+ if (connection != null) {
+ connection.disconnect();
+ }
+ }
+ }
+}
diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/AppServiceMsiCredential.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/AppServiceMsiCredential.java
index 4aa556a47550..7be7a475cb3f 100644
--- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/AppServiceMsiCredential.java
+++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/AppServiceMsiCredential.java
@@ -27,7 +27,7 @@ class AppServiceMsiCredential {
* @param identityClient The identity client to acquire a token with.
*/
AppServiceMsiCredential(String clientId, IdentityClient identityClient) {
- Configuration configuration = Configuration.getGlobalConfiguration();
+ Configuration configuration = Configuration.getGlobalConfiguration().clone();
this.msiEndpoint = configuration.get(Configuration.PROPERTY_MSI_ENDPOINT);
this.msiSecret = configuration.get(Configuration.PROPERTY_MSI_SECRET);
this.identityClient = identityClient;
diff --git a/sdk/identity/azure-identity/src/main/java/com/azure/identity/ManagedIdentityCredential.java b/sdk/identity/azure-identity/src/main/java/com/azure/identity/ManagedIdentityCredential.java
index 1cff3f761a17..8ccd89fa21ea 100644
--- a/sdk/identity/azure-identity/src/main/java/com/azure/identity/ManagedIdentityCredential.java
+++ b/sdk/identity/azure-identity/src/main/java/com/azure/identity/ManagedIdentityCredential.java
@@ -31,7 +31,7 @@ public final class ManagedIdentityCredential implements TokenCredential {
.clientId(clientId)
.identityClientOptions(identityClientOptions)
.build();
- Configuration configuration = Configuration.getGlobalConfiguration();
+ Configuration configuration = Configuration.getGlobalConfiguration().clone();
if (configuration.contains(Configuration.PROPERTY_MSI_ENDPOINT)) {
appServiceMSICredential = new AppServiceMsiCredential(clientId, identityClient);
virtualMachineMSICredential = null;