Skip to content

Commit

Permalink
[github #4555][devops #1765500] support multiple tenants(within same …
Browse files Browse the repository at this point in the history
…account) for Azure Cli authentication and refactor
  • Loading branch information
wangmingliang-ms committed Sep 11, 2020
1 parent cc3d95e commit d2b771e
Show file tree
Hide file tree
Showing 10 changed files with 438 additions and 484 deletions.
1 change: 0 additions & 1 deletion PluginsAndFeatures/azure-toolkit-for-intellij/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ configurations {
apply plugin: 'java'

dependencies {
compile group: 'org.apache.commons', name: 'commons-exec', version: '1.3'
compile 'com.microsoft.sqlserver:mssql-jdbc:6.4.0.jre8'
compile 'commons-io:commons-io:2.7'
compile group: 'org.apache.commons', name: 'commons-text', version: '1.8'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

import com.microsoft.azure.common.logging.Log;
import com.microsoft.azure.common.utils.TextUtils;
import com.microsoft.intellij.util.CommandUtils;
import com.microsoft.azuretools.utils.CommandUtils;

import java.io.File;
import java.io.IOException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@
import com.microsoft.azuretools.telemetry.TelemetryConstants;
import com.microsoft.azuretools.telemetrywrapper.Operation;
import com.microsoft.azuretools.telemetrywrapper.TelemetryManager;
import com.microsoft.azuretools.utils.CommandUtils;
import com.microsoft.intellij.runner.AzureRunProfileState;
import com.microsoft.intellij.runner.RunProcessHandler;
import com.microsoft.intellij.runner.functions.core.FunctionUtils;
import com.microsoft.intellij.runner.functions.core.JsonUtils;
import com.microsoft.intellij.util.CommandUtils;
import com.microsoft.intellij.util.ReadStreamLineThread;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
Expand Down Expand Up @@ -186,7 +186,8 @@ private void validateFunctionRuntime(RunProcessHandler processHandler) throws Az

private ComparableVersion getFuncVersion() throws IOException {
final File func = new File(functionRunConfiguration.getFuncPath());
final String funcVersion = CommandUtils.executeCommandAndGetOutput(func.getAbsolutePath(), new String[]{"-v"}, func.getParentFile());
final String funcVersion = CommandUtils.executeCommandAndGetOutput(func.getAbsolutePath(),
new String[]{"-v"}, func.getParentFile());
if (StringUtils.isEmpty(funcVersion)) {
return null;
}
Expand Down
4 changes: 4 additions & 0 deletions Utils/azuretools-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-annotations</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,55 @@

package com.microsoft.azuretools.sdkmanage;

import com.microsoft.azure.management.Azure;
import com.microsoft.azure.management.applicationinsights.v2015_05_01.implementation.InsightsManager;
import com.microsoft.azure.management.appplatform.v2019_05_01_preview.implementation.AppPlatformManager;
import com.microsoft.azure.management.resources.Subscription;
import com.microsoft.azure.management.resources.Tenant;
import com.microsoft.azuretools.adauth.PromptBehavior;
import com.microsoft.azuretools.adauth.StringUtils;
import com.microsoft.azuretools.authmanage.AdAuthManagerBuilder;
import com.microsoft.azuretools.authmanage.AzureManagerFactory;
import com.microsoft.azuretools.authmanage.BaseADAuthManager;
import com.microsoft.azuretools.authmanage.CommonSettings;
import com.microsoft.azuretools.authmanage.Environment;
import com.microsoft.azuretools.authmanage.RefreshableTokenCredentials;
import com.microsoft.azuretools.authmanage.SubscriptionManager;
import com.microsoft.azuretools.authmanage.SubscriptionManagerPersist;
import com.microsoft.azuretools.authmanage.models.AuthMethodDetails;
import com.microsoft.azuretools.telemetry.TelemetryInterceptor;
import com.microsoft.azuretools.utils.AzureRegisterProviderNamespaces;
import com.microsoft.azuretools.utils.Pair;
import rx.Observable;

import java.io.IOException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;
import java.util.Objects;

import static com.microsoft.azuretools.Constants.FILE_NAME_SUBSCRIPTIONS_DETAILS_AT;
import static org.apache.commons.lang3.StringUtils.isBlank;

public class AccessTokenAzureManager extends AzureManagerBase {
private final BaseADAuthManager delegateADAuthManager;

static {
settings.setSubscriptionsDetailsFileName(FILE_NAME_SUBSCRIPTIONS_DETAILS_AT);
}

public AccessTokenAzureManager(final BaseADAuthManager delegateADAuthManager) {
this.delegateADAuthManager = delegateADAuthManager;
}

@Override
public String getAccessToken(String tid, String resource, PromptBehavior promptBehavior) throws IOException {
return delegateADAuthManager.getAccessToken(tid, resource, promptBehavior);
}

@Override
public String getCurrentUserId() throws IOException {
return delegateADAuthManager.getAccountEmail();
}

@Override
protected String getCurrentTenantId() {
return delegateADAuthManager.getCommonTenantId();
}

protected boolean isSignedIn() {
return Objects.nonNull(this.delegateADAuthManager);
}

@Override
public void drop() throws IOException {
super.drop();
delegateADAuthManager.signOut();
}

public static class AccessTokenAzureManagerFactory implements AzureManagerFactory, AdAuthManagerBuilder {
private final BaseADAuthManager adAuthManager;

Expand Down Expand Up @@ -86,167 +104,4 @@ public BaseADAuthManager getInstance() {
return adAuthManager;
}
}

private static final Logger LOGGER = Logger.getLogger(AccessTokenAzureManager.class.getName());
private final SubscriptionManager subscriptionManager;
private final BaseADAuthManager delegateADAuthManager;

public AccessTokenAzureManager(final BaseADAuthManager delegateADAuthManager) {
this.delegateADAuthManager = delegateADAuthManager;
this.subscriptionManager = new SubscriptionManagerPersist(this);
}

@Override
public SubscriptionManager getSubscriptionManager() {
return subscriptionManager;
}

@Override
public void drop() throws IOException {
subscriptionManager.cleanSubscriptions();
delegateADAuthManager.signOut();
}

private static Settings settings;

static {
settings = new Settings();
settings.setSubscriptionsDetailsFileName(FILE_NAME_SUBSCRIPTIONS_DETAILS_AT);
}

@Override
public Azure getAzure(String sid) throws IOException {
if (sidToAzureMap.containsKey(sid)) {
return sidToAzureMap.get(sid);
}
String tid = subscriptionManager.getSubscriptionTenant(sid);
Azure azure = authTid(tid).withSubscription(sid);
// TODO: remove this call after Azure SDK properly implements handling of unregistered provider namespaces
AzureRegisterProviderNamespaces.registerAzureNamespaces(azure);
sidToAzureMap.put(sid, azure);
return azure;
}

@Override
public AppPlatformManager getAzureSpringCloudClient(String sid) {
return sidToAzureSpringCloudManagerMap.computeIfAbsent(sid, s -> {
String tid = subscriptionManager.getSubscriptionTenant(sid);
return authSpringCloud(sid, tid);
});
}

@Override
public InsightsManager getInsightsManager(String sid) {
return sidToInsightsManagerMap.computeIfAbsent(sid, s -> {
String tid = subscriptionManager.getSubscriptionTenant(sid);
return authApplicationInsights(sid, tid);
});
}

@Override
public List<Subscription> getSubscriptions() throws IOException {
List<Subscription> sl = new LinkedList<Subscription>();
// could be multi tenant - return all subscriptions for the current account
List<Tenant> tl = getTenants(delegateADAuthManager.getCommonTenantId());
for (Tenant t : tl) {
sl.addAll(getSubscriptions(t.tenantId()));
}
return sl;
}

@Override
public List<Pair<Subscription, Tenant>> getSubscriptionsWithTenant() throws IOException {
List<Pair<Subscription, Tenant>> stl = new LinkedList<>();
for (Tenant t : getTenants(delegateADAuthManager.getCommonTenantId())) {
String tid = t.tenantId();
for (Subscription s : getSubscriptions(tid)) {
stl.add(new Pair<Subscription, Tenant>(s, t));
}
}
return stl;
}

@Override
public Settings getSettings() {
return settings;
}

public List<Subscription> getSubscriptions(String tid) throws IOException {
List<Subscription> sl = authTid(tid).subscriptions().listAsync()
.onErrorResumeNext(err -> {
LOGGER.warning(err.getMessage());

return Observable.empty();
})
.toList()
.toBlocking()
.singleOrDefault(Collections.emptyList());

return sl;
}

public List<Tenant> getTenants(String tid) throws IOException {
List<Tenant> tl = authTid(tid).tenants().listAsync()
.onErrorResumeNext(err -> {
LOGGER.warning(err.getMessage());

return Observable.empty();
})
.toList()
.toBlocking()
.singleOrDefault(Collections.emptyList());

return tl;
}

// public static Azure.Authenticated auth(String accessToken) throws Exception {
// return Azure.configure().authenticate(getTokenCredentials(accessToken));
// }

// private static TokenCredentials getTokenCredentials(String token) throws Exception {
// return null;
// }

private Azure.Authenticated authTid(String tid) throws IOException {
return Azure.configure()
.withInterceptor(new TelemetryInterceptor())
.withUserAgent(CommonSettings.USER_AGENT)
.authenticate(new RefreshableTokenCredentials(this, tid));
}

private AppPlatformManager authSpringCloud(String sid, String tid) {
return buildAzureManager(AppPlatformManager.configure())
.authenticate(new RefreshableTokenCredentials(this, tid), sid);
}

private InsightsManager authApplicationInsights(String sid, String tid) {
return buildAzureManager(InsightsManager.configure())
.authenticate(new RefreshableTokenCredentials(this, tid), sid);
}

@Override
public String getCurrentUserId() throws IOException {
return delegateADAuthManager.getAccountEmail();
}

@Override
public String getAccessToken(String tid, String resource, PromptBehavior promptBehavior) throws IOException {
return delegateADAuthManager.getAccessToken(tid, resource, promptBehavior);
}

@Override
public String getManagementURI() throws IOException {
// environments other than global cloud are not supported for interactive login for now
return CommonSettings.getAdEnvironment().resourceManagerEndpoint();
}

public String getStorageEndpointSuffix() {
return CommonSettings.getAdEnvironment().storageEndpointSuffix();
}

@Override
public Environment getEnvironment() {
return CommonSettings.getEnvironment();
}

}
Loading

0 comments on commit d2b771e

Please sign in to comment.