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;