package com.microsoft.azure.credentials;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.azure.AzureEnvironment;
import com.microsoft.azure.management.apigeneration.Beta;
import com.microsoft.rest.serializer.JacksonAdapter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@Beta
public final class AzureCliCredentials extends AzureTokenCredentials {
private static final ObjectMapper MAPPER = new JacksonAdapter().serializer().setDateFormat(new SimpleDateFormat("yyyy-MM-dd hh:mm:ssssss"));
private Map<String, AzureCliSubscription> subscriptions;
private File azureProfile;
private File accessTokens;
private Lock lock = new ReentrantLock();
private AzureCliCredentials() {
super(null, null);
subscriptions = new ConcurrentHashMap<>();
}
private synchronized void loadAccessTokens() throws IOException {
try {
AzureCliSubscription.Wrapper wrapper = MAPPER.readValue(azureProfile, AzureCliSubscription.Wrapper.class);
List<AzureCliToken> tokens = MAPPER.readValue(accessTokens, new TypeReference<List<AzureCliToken>>() { });
while (wrapper == null || tokens == null || tokens.isEmpty() || wrapper.subscriptions == null || wrapper.subscriptions.isEmpty()) {
System.err.println("Please login in Azure CLI and press any key to continue after you've successfully logged in.");
System.in.read();
wrapper = MAPPER.readValue(azureProfile, AzureCliSubscription.Wrapper.class);
tokens = MAPPER.readValue(accessTokens, new TypeReference<List<AzureCliToken>>() { });
}
for (AzureCliSubscription subscription : wrapper.subscriptions) {
for (AzureCliToken token : tokens) {
if (subscription.isServicePrincipal() == token.isServicePrincipal()
&& subscription.userName().equalsIgnoreCase(token.user())
&& subscription.tenant().equalsIgnoreCase(token.tenant())) {
subscriptions.put(subscription.id(), subscription.withToken(token));
if (subscription.isDefault()) {
withDefaultSubscriptionId(subscription.id());
}
}
}
}
} catch (IOException e) {
System.err.println(String.format("Cannot read files %s and %s. Are you logged in Azure CLI?", azureProfile.getAbsolutePath(), accessTokens.getAbsolutePath()));
throw e;
}
}
public static AzureCliCredentials create() throws IOException {
return create(
Paths.get(System.getProperty("user.home"), ".azure", "azureProfile.json").toFile(),
Paths.get(System.getProperty("user.home"), ".azure", "accessTokens.json").toFile());
}
public static AzureCliCredentials create(File azureProfile, File accessTokens) throws IOException {
AzureCliCredentials credentials = new AzureCliCredentials();
credentials.azureProfile = azureProfile;
credentials.accessTokens = accessTokens;
credentials.loadAccessTokens();
return credentials;
}
public String clientId() {
return subscriptions.get(defaultSubscriptionId()).clientId();
}
@Override
public String domain() {
return subscriptions.get(defaultSubscriptionId()).tenant();
}
public AzureEnvironment environment() {
return subscriptions.get(defaultSubscriptionId()).environment();
}
public Map<String, AzureCliSubscription> subscriptions() {
return Collections.unmodifiableMap(subscriptions);
}
@Override
public synchronized String getToken(String resource) throws IOException {
String token = subscriptions.get(defaultSubscriptionId()).credentialInstance().getToken(resource);
if (token == null) {
System.err.println("Please login in Azure CLI and press any key to continue after you've successfully logged in.");
System.in.read();
loadAccessTokens();
token = subscriptions.get(defaultSubscriptionId()).credentialInstance().getToken(resource);
}
return token;
}
}