Injectable current service principal

This commit is contained in:
Ignasi Barrera 2017-12-01 11:54:58 +01:00
parent 7368d58ad9
commit 6c759930d7
11 changed files with 399 additions and 60 deletions

View File

@ -20,30 +20,34 @@ import java.io.Closeable;
import javax.ws.rs.PathParam;
import org.jclouds.azurecompute.arm.features.JobApi;
import org.jclouds.azurecompute.arm.features.LocationApi;
import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
import org.jclouds.azurecompute.arm.features.StorageAccountApi;
import org.jclouds.azurecompute.arm.features.SubnetApi;
import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
import org.jclouds.azurecompute.arm.features.VirtualMachineScaleSetApi;
import org.jclouds.azurecompute.arm.features.VMSizeApi;
import org.jclouds.azurecompute.arm.features.OSImageApi;
import org.jclouds.azurecompute.arm.features.DeploymentApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
import org.jclouds.azurecompute.arm.domain.ServicePrincipal;
import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
import org.jclouds.azurecompute.arm.features.DeploymentApi;
import org.jclouds.azurecompute.arm.features.DiskApi;
import org.jclouds.azurecompute.arm.features.ImageApi;
import org.jclouds.azurecompute.arm.features.MetricsApi;
import org.jclouds.azurecompute.arm.features.JobApi;
import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
import org.jclouds.azurecompute.arm.features.LocationApi;
import org.jclouds.azurecompute.arm.features.MetricDefinitionsApi;
import org.jclouds.azurecompute.arm.features.MetricsApi;
import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
import org.jclouds.azurecompute.arm.features.OSImageApi;
import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
import org.jclouds.azurecompute.arm.features.StorageAccountApi;
import org.jclouds.azurecompute.arm.features.SubnetApi;
import org.jclouds.azurecompute.arm.features.VMSizeApi;
import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
import org.jclouds.azurecompute.arm.features.VirtualMachineScaleSetApi;
import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
import org.jclouds.rest.annotations.Delegate;
import com.google.common.base.Supplier;
import com.google.inject.Provides;
/**
* The Azure Resource Manager API is a REST API for managing your services and deployments.
* <p>
@ -237,4 +241,10 @@ public interface AzureComputeApi extends Closeable {
*/
@Delegate
MetricDefinitionsApi getMetricsDefinitionsApi(@PathParam("resourceid") String resourceid);
/**
* Returns the information about the current service principal.
*/
@Provides
Supplier<ServicePrincipal> getServicePrincipal();
}

View File

@ -37,28 +37,29 @@ import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
import java.net.URI;
import java.util.Properties;
import org.jclouds.azurecompute.arm.config.AzureComputeHttpApiModule.CurrentServicePrincipal;
import org.jclouds.azurecompute.arm.domain.Region;
import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
import org.jclouds.azurecompute.arm.features.DeploymentApi;
import org.jclouds.azurecompute.arm.features.DiskApi;
import org.jclouds.azurecompute.arm.features.ImageApi;
import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
import org.jclouds.azurecompute.arm.features.LocationApi;
import org.jclouds.azurecompute.arm.features.MetricDefinitionsApi;
import org.jclouds.azurecompute.arm.features.MetricsApi;
import org.jclouds.azurecompute.arm.features.NetworkInterfaceCardApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityGroupApi;
import org.jclouds.azurecompute.arm.features.NetworkSecurityRuleApi;
import org.jclouds.azurecompute.arm.features.OSImageApi;
import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
import org.jclouds.azurecompute.arm.features.PublicIPAddressApi;
import org.jclouds.azurecompute.arm.features.ResourceGroupApi;
import org.jclouds.azurecompute.arm.features.ResourceProviderApi;
import org.jclouds.azurecompute.arm.features.StorageAccountApi;
import org.jclouds.azurecompute.arm.features.SubnetApi;
import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
import org.jclouds.azurecompute.arm.features.VMSizeApi;
import org.jclouds.azurecompute.arm.features.VirtualMachineApi;
import org.jclouds.azurecompute.arm.features.LoadBalancerApi;
import org.jclouds.azurecompute.arm.features.AvailabilitySetApi;
import org.jclouds.azurecompute.arm.features.DiskApi;
import org.jclouds.azurecompute.arm.features.ImageApi;
import org.jclouds.azurecompute.arm.features.MetricDefinitionsApi;
import org.jclouds.azurecompute.arm.features.MetricsApi;
import org.jclouds.azurecompute.arm.features.VirtualMachineScaleSetApi;
import org.jclouds.azurecompute.arm.features.VirtualNetworkApi;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.internal.BaseProviderMetadata;
@ -124,7 +125,8 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
properties.put(API_VERSION_PREFIX + MetricDefinitionsApi.class.getSimpleName(), "2017-05-01-preview");
properties.put(API_VERSION_PREFIX + MetricsApi.class.getSimpleName(), "2016-09-01");
properties.put(API_VERSION_PREFIX + VirtualMachineScaleSetApi.class.getSimpleName(), "2017-03-30");
properties.put(API_VERSION_PREFIX + CurrentServicePrincipal.class.getSimpleName(), "1.6");
return properties;
}

View File

@ -16,7 +16,24 @@
*/
package org.jclouds.azurecompute.arm.config;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
import java.net.URI;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import org.jclouds.azurecompute.arm.AzureComputeApi;
import org.jclouds.azurecompute.arm.domain.ServicePrincipal;
import org.jclouds.azurecompute.arm.filters.ApiVersionFilter;
import org.jclouds.azurecompute.arm.handlers.AzureComputeErrorHandler;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.annotation.ClientError;
@ -24,15 +41,31 @@ import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.location.suppliers.ImplicitLocationSupplier;
import org.jclouds.location.suppliers.implicit.FirstRegion;
import org.jclouds.oauth.v2.config.OAuthConfigFactory;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.OnlyElement;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.config.HttpApiModule;
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.name.Named;
@ConfiguresHttpApi
public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
private static final Pattern OAUTH_TENANT_PATTERN = Pattern
.compile("https://login.microsoftonline.com/([^/]+)/oauth2/token");
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(AzureComputeErrorHandler.class);
@ -46,10 +79,58 @@ public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
bind(ImplicitLocationSupplier.class).to(FirstRegion.class).in(Scopes.SINGLETON);
}
@Override
protected void configure() {
super.configure();
bindHttpApi(binder(), CurrentServicePrincipal.class);
bind(OAuthScopes.class).toInstance(OAuthScopes.NoScopes.create());
bind(OAuthConfigFactory.class).to(AzureOAuthConfigFactory.class).in(Scopes.SINGLETON);
}
@Provides
@Singleton
@Tenant
protected String provideTenant(@Named("oauth.endpoint") final String oauthEndpoint) {
Matcher m = OAUTH_TENANT_PATTERN.matcher(oauthEndpoint);
if (!m.matches()) {
throw new IllegalArgumentException("Could not parse tenantId from: " + oauthEndpoint);
}
return m.group(1);
}
@Provides
@Singleton
@GraphRBAC
protected Supplier<URI> graphRBACEndpoint(@Tenant String tenantId) {
return Suppliers.ofInstance(URI.create(GraphRBAC.ENDPOINT + tenantId));
}
@Provides
@Singleton
protected Supplier<ServicePrincipal> provideServicePrincipal(final CurrentServicePrincipal currentServicePrincipal,
AtomicReference<AuthorizationException> authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
// This supplier must be defensive against any auth exception.
return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
new Supplier<ServicePrincipal>() {
@Override
public ServicePrincipal get() {
return currentServicePrincipal.get();
}
}, seconds, TimeUnit.SECONDS);
}
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
@Endpoint(GraphRBAC.class)
@OAuthResource(GraphRBAC.ENDPOINT)
public interface CurrentServicePrincipal {
@Named("servicePrincipal:get")
@GET
@Path("/servicePrincipals")
@QueryParams(keys = "$filter", values = "appId eq '{jclouds.identity}'")
@SelectJson("value")
@OnlyElement
ServicePrincipal get();
}
}

View File

@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.config;
import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
import org.jclouds.http.HttpRequest;
import org.jclouds.oauth.v2.config.OAuthConfigFactory;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.inject.Inject;
import com.google.inject.name.Named;
public class AzureOAuthConfigFactory implements OAuthConfigFactory {
private final OAuthScopes scopes;
@Named(AUDIENCE)
@Inject(optional = true)
private String audience;
@Named(RESOURCE)
@Inject(optional = true)
private String resource;
@Inject
AzureOAuthConfigFactory(OAuthScopes scopes) {
this.scopes = scopes;
}
@Override
public OAuthConfig forRequest(HttpRequest input) {
OAuthResource customResource = null;
if (input instanceof GeneratedHttpRequest) {
GeneratedHttpRequest request = (GeneratedHttpRequest) input;
customResource = request.getInvocation().getInvokable().getAnnotation(OAuthResource.class);
if (customResource == null) {
customResource = request.getInvocation().getInvokable().getDeclaringClass()
.getAnnotation(OAuthResource.class);
}
}
String oauthResource = customResource != null ? customResource.value() : resource;
return OAuthConfig.create(scopes.forRequest(input), audience, oauthResource);
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Provides the Graph RBAC API endpoint for the current tenant.
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Qualifier
public @interface GraphRBAC {
String ENDPOINT = "https://graph.windows.net/";
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Configures a custom OAuth resource for certain APIs and methods.
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.METHOD })
@Qualifier
public @interface OAuthResource {
String value();
}

View File

@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Qualifies an object that describes the current tenant.
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Qualifier
public @interface Tenant {
}

View File

@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.domain;
import java.util.Date;
import java.util.List;
import javax.annotation.Nullable;
import org.jclouds.json.SerializedNames;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
@AutoValue
public abstract class ServicePrincipal {
@Nullable public abstract String appId();
@Nullable public abstract Date deletionTimestamp();
@Nullable public abstract String displayName();
public abstract String objectId();
public abstract String objectType();
public abstract List<String> servicePrincipalNames();
@SerializedNames({ "appId", "deletionTimestamp", "displayName", "objectId", "objectType", "servicePrincipalNames" })
public static ServicePrincipal create(String appId, Date deletionTimestamp, String displayName, String objectId,
String objectType, List<String> servicePrincipalNames) {
List<String> servicePrincipals = servicePrincipalNames != null ? ImmutableList.copyOf(servicePrincipalNames)
: ImmutableList.<String> of();
return builder().appId(appId).deletionTimestamp(deletionTimestamp).displayName(displayName).objectId(objectId)
.objectType(objectType).servicePrincipalNames(servicePrincipals).build();
}
public abstract Builder toBuilder();
public static Builder builder() {
return new AutoValue_ServicePrincipal.Builder();
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder appId(String appId);
public abstract Builder deletionTimestamp(Date deletionTimestamp);
public abstract Builder displayName(String displayName);
public abstract Builder objectId(String objectId);
public abstract Builder objectType(String objectType);
public abstract Builder servicePrincipalNames(List<String> servicePrincipalNames);
public abstract ServicePrincipal build();
}
}

View File

@ -70,49 +70,35 @@ public abstract class VirtualMachineScaleSetIpConfigurationProperties {
final String applicationGatewayBackendAddressPools)
{
return builder()
.publicIPAddressConfiguration(publicIPAddressConfiguration)
.subnet(subnet)
.privateIPAddressVersion(privateIPAddressVersion)
.lbBackendAddressPools(loadBalancerBackendAddressPools)
.lbInboundNatPools(loadBalancerInboundNatPools)
.applicationGatewayBackendAddressPools(applicationGatewayBackendAddressPools)
.build();
.publicIPAddressConfiguration(publicIPAddressConfiguration)
.subnet(subnet)
.privateIPAddressVersion(privateIPAddressVersion)
.loadBalancerBackendAddressPools(
loadBalancerBackendAddressPools != null ? ImmutableList.copyOf(loadBalancerBackendAddressPools)
: ImmutableList.<IdReference> of())
.loadBalancerInboundNatPools(
loadBalancerInboundNatPools != null ? ImmutableList.copyOf(loadBalancerInboundNatPools)
: ImmutableList.<IdReference> of())
.applicationGatewayBackendAddressPools(applicationGatewayBackendAddressPools).build();
}
public abstract Builder toBuilder();
public static Builder builder() {
return new AutoValue_VirtualMachineScaleSetIpConfigurationProperties.Builder()
.lbBackendAddressPools(null)
.lbInboundNatPools(null);
return new AutoValue_VirtualMachineScaleSetIpConfigurationProperties.Builder();
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder publicIPAddressConfiguration(VirtualMachineScaleSetPublicIPAddressConfiguration publicIPAddressConfiguration);
public abstract Builder subnet(Subnet subnet);
public abstract Builder loadBalancerBackendAddressPools(List<IdReference> loadBalancerBackendAddressPools);
public abstract Builder loadBalancerInboundNatPools(List<IdReference> loadBalancerInboundNatPools);
public abstract Builder privateIPAddressVersion(String privateIPAddressVersion);
public Builder lbBackendAddressPools(List<IdReference> loadBalancerBackendAddressPools) {
return loadBalancerBackendAddressPools(loadBalancerBackendAddressPools != null ? ImmutableList
.copyOf(loadBalancerBackendAddressPools) : ImmutableList.<IdReference>of());
}
public Builder lbInboundNatPools(List<IdReference> loadBalancerInboundNatPools) {
return loadBalancerInboundNatPools(loadBalancerInboundNatPools != null ? ImmutableList
.copyOf(loadBalancerInboundNatPools) : ImmutableList.<IdReference>of());
}
public abstract Builder applicationGatewayBackendAddressPools(String applicationGatewayBackendAddressPools);
public abstract VirtualMachineScaleSetIpConfigurationProperties build();
}
}

View File

@ -249,14 +249,14 @@ public abstract class VirtualMachineScaleSetOSProfile {
.adminPassword(adminPassword)
.linuxConfiguration(linuxConfiguration)
.windowsConfiguration(windowsConfiguration)
._secrets(secrets)
.secrets(secrets != null ? ImmutableList.copyOf(secrets) : ImmutableList.<Secrets> of())
.build();
}
public abstract Builder toBuilder();
public static Builder builder() {
return new AutoValue_VirtualMachineScaleSetOSProfile.Builder()._secrets(null);
return new AutoValue_VirtualMachineScaleSetOSProfile.Builder();
}
@AutoValue.Builder
@ -268,10 +268,6 @@ public abstract class VirtualMachineScaleSetOSProfile {
public abstract Builder windowsConfiguration(WindowsConfiguration windowsConfiguration);
public abstract Builder secrets(List<Secrets> secrets);
public Builder _secrets(List<Secrets> secrets) {
return secrets(secrets != null ? ImmutableList.copyOf(secrets) : ImmutableList.<Secrets>of());
}
public abstract VirtualMachineScaleSetOSProfile build();
}
}

View File

@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azurecompute.arm.features;
import static org.testng.Assert.assertEquals;
import org.jclouds.azurecompute.arm.domain.ServicePrincipal;
import org.jclouds.azurecompute.arm.internal.BaseAzureComputeApiLiveTest;
import org.testng.annotations.Test;
@Test(groups = "live", testName = "CurrentServicePrincipalApiLiveTest", singleThreaded = true)
public class CurrentServicePrincipalApiLiveTest extends BaseAzureComputeApiLiveTest {
@Test
public void testGetCurrentServicePrincipal() {
ServicePrincipal currentUser = api.getServicePrincipal().get();
assertEquals(currentUser.appId(), identity);
}
}