Skip to content

Commit

Permalink
Add Identity end to end web jobs test (#8191)
Browse files Browse the repository at this point in the history
Add Identity end to end web jobs test
  • Loading branch information
g2vinay authored Feb 18, 2020
1 parent c972980 commit 45e83f7
Show file tree
Hide file tree
Showing 6 changed files with 278 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@
<!-- Report AMQP retry attempts in static withRetry method. -->
<suppress checks="com.azure.tools.checkstyle.checks.GoodLoggingCheck" files="com.azure.core.amqp.implementation.RetryUtil.java"/>

<!-- The Identity Azure Platform End to tend Test.-->
<suppress checks="com.azure.tools.checkstyle.checks.GoodLoggingCheck" files="com.azure.endtoend.identity.IdentityTest.java"/>
<suppress checks="com.azure.tools.checkstyle.checks.GoodLoggingCheck" files="com.azure.endtoend.identity.WebJobsIdentityTest.java"/>

<!-- Use the logger in a Utility static method. -->
<suppress checks="com.azure.tools.checkstyle.checks.GoodLoggingCheck" files="com.azure.ai.textanalytics.Transforms.java" />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,16 @@
<Method name="endTracingSpan"/>
<Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"/>
</Match>

<!-- Incorrect flagging, error will be thrown if value is null -->
<Match>
<Class name="com.azure.endtoend.identity.WebJobsIdentityTest"/>
<Or>
<Method name="testMSIEndpointWithSystemAssigned"/>
<Method name="testMSIEndpointWithUserAssigned"/>
</Or>
<Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"/>
</Match>

<!-- Incorrect flagging, if the response is null a StorageException would have been thrown -->
<Match>
Expand Down
31 changes: 31 additions & 0 deletions sdk/e2e/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,35 @@
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2</version> <!-- {x-version-update;org.apache.maven.plugins:maven-assembly-plugin;external_dependency} -->
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>
com.azure.endtoend.identity.IdentityTest
</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.endtoend.identity;

import com.azure.core.util.Configuration;
import com.azure.core.util.CoreUtils;

import java.util.Locale;

/**
* Runs Identity end to end test on specified Azure Platform.
*/
public class IdentityTest {
private static final String AZURE_IDENTITY_TEST_PLATFORM = "AZURE_IDENTITY_TEST_PLATFORM";
private static final Configuration CONFIGURATION = Configuration.getGlobalConfiguration().clone();

/**
* Runs the Web jobs identity tests
* @param args the command line arguments
* @throws IllegalStateException if AZURE_IDENTITY_TEST_PLATFORM is not set to "user" or "system"
*/
public static void main(String[] args) throws IllegalStateException {
if (CoreUtils.isNullOrEmpty(CONFIGURATION.get(AZURE_IDENTITY_TEST_PLATFORM))) {
throw new IllegalStateException("Identity Test platform is not set. Set environemnt "
+ "variable AZURE_IDENTITY_TEST_PLATFORM to webjobs");
}

String platform = CONFIGURATION.get(AZURE_IDENTITY_TEST_PLATFORM).toLowerCase(Locale.ENGLISH);
switch (platform) {
case "webjobs":
WebJobsIdentityTest webJobsIdentityTest = new WebJobsIdentityTest();
webJobsIdentityTest.run();
break;
default:
throw (new IllegalStateException("Invalid Test Platform is configured for AZURE_IDENTITY_TEST_PLATFORM."
+ "Possible value is webjobs."));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.endtoend.identity;

import com.azure.core.credential.AccessToken;
import com.azure.core.credential.TokenRequestContext;
import com.azure.core.util.Configuration;
import com.azure.core.util.CoreUtils;
import com.azure.core.util.logging.ClientLogger;
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 reactor.core.publisher.Mono;

import java.time.format.DateTimeFormatter;
import java.util.Locale;

/**
* Runs Identity MSI and IMDS endpoints test in Azure Web Jobs.
*/
class WebJobsIdentityTest {
private static final String VAULT_SECRET_NAME = "secret";
private static final String AZURE_WEBJOBS_TEST_MODE = "AZURE_WEBJOBS_TEST_MODE";
private static final String AZURE_VAULT_URL = "AZURE_VAULT_URL";
private static final Configuration CONFIGURATION = Configuration.getGlobalConfiguration().clone();
private final ClientLogger logger = new ClientLogger(WebJobsIdentityTest.class);

/**
* Runs the Web jobs identity tests
* @throws IllegalStateException if AZURE_WEBJOBS_TEST_MODE is not set to "user" or "system"
*/
void run() throws IllegalStateException {
if (CoreUtils.isNullOrEmpty(CONFIGURATION.get(AZURE_WEBJOBS_TEST_MODE))) {
throw logger.logExceptionAsError(new IllegalStateException("Webjobs Test mode is not set. Set environemnt "
+ "variable AZURE_WEBJOBS_TEST_MODE to user or system"));
}

String mode = CONFIGURATION.get(AZURE_WEBJOBS_TEST_MODE).toLowerCase(Locale.ENGLISH);
WebJobsIdentityTest identityTest = new WebJobsIdentityTest();
switch (mode) {
case "user":
identityTest.testMSIEndpointWithUserAssigned();
identityTest.testMSIEndpointWithUserAssignedAccessKeyVault();
break;
case "system":
identityTest.testMSIEndpointWithSystemAssigned();
identityTest.testMSIEndpointWithSystemAssignedAccessKeyVault();
break;
default:
throw logger.logExceptionAsError(
new IllegalStateException("Invalid Test mode is configured AZURE_WEBJOBS_TEST_MODE. "
+ "Possible values are user or system."));
}

}

private void testMSIEndpointWithSystemAssigned() {
assertConfigPresence(Configuration.PROPERTY_MSI_ENDPOINT,
"testMSIEndpointWithSystemAssigned - MSIEndpoint not configured in the environment.");
assertConfigPresence(Configuration.PROPERTY_MSI_SECRET,
"testMSIEndpointWithSystemAssigned - MSISecret not configured in the environment.");
IdentityClient client = new IdentityClientBuilder().build();
AccessToken accessToken = client.authenticateToManagedIdentityEndpoint(
CONFIGURATION.get(Configuration.PROPERTY_MSI_ENDPOINT),
CONFIGURATION.get(Configuration.PROPERTY_MSI_SECRET),
new TokenRequestContext().addScopes("https://management.azure.com/.default"))
.flatMap(token -> {
if (token == null || token.getToken() == null) {
return Mono.error(logger.logExceptionAsError(new IllegalStateException(
"Access Token not returned from System Assigned Identity")));
} else {
return Mono.just(token);
}
}).block();
System.out.printf("Received token with length %d and expiry at %s %n "
+ "testMSIEndpointWithSystemAssigned - Succeeded %n",
accessToken.getToken().length(), accessToken.getExpiresAt().format(DateTimeFormatter.ISO_DATE_TIME));
}

private void testMSIEndpointWithSystemAssignedAccessKeyVault() {
assertConfigPresence(Configuration.PROPERTY_MSI_ENDPOINT,
"testMSIEndpointWithSystemAssignedKeyVault - MSIEndpoint not configured in the environment.");
assertConfigNotPresent(Configuration.PROPERTY_AZURE_CLIENT_ID,
"testMSIEndpointWithSystemAssignedKeyVault - Client id"
+ " should not be configured in the environment.");
assertConfigPresence(AZURE_VAULT_URL,
"testMSIEndpointWithSystemAssigned - Vault URL is not configured in the environment.");

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);
System.out.printf("testMSIEndpointWithSystemAssignedAccessKeyVault - "
+ "Retrieved Secret with name %s and value %s %n",
secret.getName(), secret.getValue());
assertExpectedValue(VAULT_SECRET_NAME, secret.getName(),
"SUCCESS: Secret matched - testMSIEndpointWithSystemAssignedAccessKeyVault succeeded",
"Error: Secret name didn't match expected name - "
+ "testMSIEndpointWithSystemAssignedAccessKeyVault failed");
}

private void testMSIEndpointWithUserAssigned() {
assertConfigPresence(Configuration.PROPERTY_MSI_ENDPOINT,
"testMSIEndpointWithUserAssigned - MSIEndpoint not configured in the environment.");
assertConfigPresence(Configuration.PROPERTY_AZURE_CLIENT_ID,
"testMSIEndpointWithUserAssigned - Client is not configured in the environment.");
assertConfigPresence(AZURE_VAULT_URL,
"testMSIEndpointWithUserAssigned - Vault URL is not configured in the environment.");

IdentityClient client = new IdentityClientBuilder()
.clientId(CONFIGURATION.get(Configuration.PROPERTY_AZURE_CLIENT_ID))
.build();

AccessToken accessToken = client.authenticateToManagedIdentityEndpoint(
CONFIGURATION.get(Configuration.PROPERTY_MSI_ENDPOINT),
CONFIGURATION.get(Configuration.PROPERTY_MSI_SECRET),
new TokenRequestContext().addScopes("https://management.azure.com/.default"))
.flatMap(token -> {
if (token == null || token.getToken() == null) {
return Mono.error(logger.logExceptionAsError(new IllegalStateException(
"Access Token not returned from System Assigned Identity")));
} else {
return Mono.just(token);
}
}).block();
System.out.printf("Received token with length %d and expiry at %s %n "
+ "testMSIEndpointWithUserAssigned - succeeded %n",
accessToken.getToken().length(), accessToken.getExpiresAt().format(DateTimeFormatter.ISO_DATE_TIME));
}

private void testMSIEndpointWithUserAssignedAccessKeyVault() {
assertConfigPresence(Configuration.PROPERTY_MSI_ENDPOINT,
"testMSIEndpointWithUserAssignedKeyVault - MSIEndpoint not configured in the environment.");
assertConfigPresence(Configuration.PROPERTY_AZURE_CLIENT_ID,
"testMSIEndpointWithUserAssignedKeyVault - Client is not configured in the environment.");
assertConfigPresence(AZURE_VAULT_URL,
"testMSIEndpointWithUserAssignedKeyVault - Vault URL is not configured in the environment.");

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);
System.out.printf("testMSIEndpointWithSystemAssignedAccessKeyVault - "
+ "Retrieved Secret with name %s and value %s %n",
secret.getName(), secret.getValue());
assertExpectedValue(VAULT_SECRET_NAME, secret.getName(),
"SUCCESS: Secret matched - testMSIEndpointWithUserAssignedAccessKeyVault - succeeded",
"Error: Secret name didn't match expected name - testMSIEndpointWithUserAssignedAccessKeyVault - failed");
}

private void assertExpectedValue(String expected, String actual, String success, String faiure) {
if (expected.equals(actual)) {
System.out.println(success);
return;
}
System.out.println(faiure);
}


private void assertConfigPresence(String identitfer, String errorMessage) {
if (CoreUtils.isNullOrEmpty(CONFIGURATION.get(identitfer))) {
throw logger.logExceptionAsError(new IllegalStateException(errorMessage));
}
}

private void assertConfigNotPresent(String identitfer, String errorMessage) {
if (!CoreUtils.isNullOrEmpty(CONFIGURATION.get(identitfer))) {
throw logger.logExceptionAsError(new IllegalStateException(errorMessage));
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

/**
* This package contains the classes to run Identity MSI and IMDS endpoints test in Azure Web Jobs.
*/
package com.azure.endtoend.identity;

0 comments on commit 45e83f7

Please sign in to comment.