JCLOUDS-1441: Enables support for ARM regions in China

Adds new china regions

Fixes pattern matching for China provider oauth string

Modifies test for oauth string

overrides jclouds.oauth.resource property for tests

Graph and Vault API Endpoints need to be configurable

jclouds.oauth.resource is not mandatory

Adapted Endpoints for APIs GraphRBAC and Vault

Adds unit test for china oauth endpoint check

Minor fix to regular expression
This commit is contained in:
Dani Estevez 2018-08-10 12:15:44 -04:00
parent 88f44a6d8e
commit a07ab5a982
10 changed files with 146 additions and 74 deletions

View File

@ -54,7 +54,12 @@ import com.google.inject.name.Named;
public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
private static final Pattern OAUTH_TENANT_PATTERN = Pattern
.compile("https://login.microsoft(?:online)?.com/([^/]+)/oauth2/token");
.compile("https://login.(microsoft(?:online)?.com|chinacloudapi.cn)/([^/]+)/oauth2/token");
private static final Pattern CHINA_OAUTH_ENDPOINT_PATTERN = Pattern
.compile("https://login.chinacloudapi.cn/([^/]+)/oauth2/token");
public static final String IS_CHINA_ENDPOINT = "jclouds.isChinaEndpoint";
@Override
protected void bindErrorHandlers() {
@ -92,7 +97,14 @@ public class AzureComputeHttpApiModule extends HttpApiModule<AzureComputeApi> {
if (!m.matches()) {
throw new IllegalArgumentException("Could not parse tenantId from: " + oauthEndpoint);
}
return m.group(1);
return m.group(2);
}
@Provides
@Singleton
@Named(IS_CHINA_ENDPOINT)
protected final boolean isChinaEndpoint(@Named("oauth.endpoint") final String oauthEndpoint) {
return CHINA_OAUTH_ENDPOINT_PATTERN.matcher(oauthEndpoint).matches();
}
@Provides

View File

@ -16,6 +16,7 @@
*/
package org.jclouds.azurecompute.arm.config;
import static org.jclouds.azurecompute.arm.config.AzureComputeHttpApiModule.IS_CHINA_ENDPOINT;
import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
@ -29,7 +30,7 @@ import com.google.inject.name.Named;
public class AzureOAuthConfigFactory implements OAuthConfigFactory {
private final OAuthScopes scopes;
@Named(AUDIENCE)
@Inject(optional = true)
private String audience;
@ -38,6 +39,10 @@ public class AzureOAuthConfigFactory implements OAuthConfigFactory {
@Inject(optional = true)
private String resource;
@Named(IS_CHINA_ENDPOINT)
@Inject(optional = true)
private boolean isChinaEndpoint;
@Inject
AzureOAuthConfigFactory(OAuthScopes scopes) {
this.scopes = scopes;
@ -54,7 +59,9 @@ public class AzureOAuthConfigFactory implements OAuthConfigFactory {
.getAnnotation(OAuthResource.class);
}
}
String oauthResource = customResource != null ? customResource.value() : resource;
String oauthResource = customResource == null ?
resource :
(isChinaEndpoint ? customResource.chinaEndpoint() : customResource.value());
return OAuthConfig.create(scopes.forRequest(input), audience, oauthResource);
}
}

View File

@ -16,13 +16,15 @@
*/
package org.jclouds.azurecompute.arm.config;
import static org.jclouds.azurecompute.arm.config.AzureComputeHttpApiModule.IS_CHINA_ENDPOINT;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.net.URI;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Qualifier;
import com.google.common.base.Supplier;
@ -35,19 +37,22 @@ import com.google.common.base.Supplier;
@Qualifier
public @interface GraphRBAC {
String ENDPOINT = "https://graph.windows.net/";
String STANDARD_ENDPOINT = "https://graph.windows.net/";
String CHINA_ENDPOINT = "https://graph.chinacloudapi.cn/";
static class GraphRBACForTenant implements Supplier<URI> {
private final String tenantId;
private final boolean isChinaEndpoint;
@Inject
GraphRBACForTenant(@Tenant String tenantId) {
GraphRBACForTenant(@Tenant String tenantId, @Named(IS_CHINA_ENDPOINT) boolean isChinaEndpoint) {
this.tenantId = tenantId;
this.isChinaEndpoint = isChinaEndpoint;
}
@Override
public URI get() {
return URI.create(GraphRBAC.ENDPOINT + tenantId);
return URI.create((isChinaEndpoint ? CHINA_ENDPOINT : STANDARD_ENDPOINT) + tenantId);
}
}

View File

@ -20,7 +20,6 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
@ -30,6 +29,8 @@ import javax.inject.Qualifier;
@Target(value = { ElementType.TYPE, ElementType.METHOD })
@Qualifier
public @interface OAuthResource {
String value();
String chinaEndpoint();
}

View File

@ -60,7 +60,9 @@ public enum Region {
SOUTH_INDIA("South India", "IN-TN"),
WEST_INDIA("West India", "IN-MH"),
CHINA_EAST("China East", "CN-SH"),
CHINA_EAST_2("China East 2", "CN-SH"),
CHINA_NORTH("China North", "CN-BJ"),
CHINA_NORTH_2("China North 2", "CN-BJ"),
CANADA_CENTRAL("Canada Central", "CA-ON"),
CANADA_EAST("Canada East", "CA-QC"),
FRANCE_CENTRAL("France Central", "FR-IDF"),

View File

@ -37,7 +37,7 @@ import com.google.inject.name.Named;
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
@Endpoint(GraphRBAC.class)
@OAuthResource(GraphRBAC.ENDPOINT)
@OAuthResource(value = GraphRBAC.STANDARD_ENDPOINT, chinaEndpoint = GraphRBAC.CHINA_ENDPOINT)
public interface GraphRBACApi {
@Named("servicePrincipal:get")

View File

@ -19,7 +19,6 @@ package org.jclouds.azurecompute.arm.features;
import java.net.URI;
import java.util.List;
import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@ -30,8 +29,6 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import com.google.common.base.Function;
import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
@ -75,15 +72,21 @@ import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PATCH;
import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
import org.jclouds.rest.annotations.ParamParser;
import com.google.common.base.Function;
@RequestFilters({ OAuthFilter.class, ApiVersionFilter.class })
@Consumes(MediaType.APPLICATION_JSON)
public interface VaultApi {
String VAULT_API_STANDARD_ENDPOINT = "https://vault.azure.net";
String VAULT_API_CHINA_ENDPOINT = "https://vault.azure.cn";
static class PrependSlashOrEmptyString implements Function<Object, String> {
public String apply(Object from) {
if ((from == null) || (from.toString().length() == 0)) {
@ -146,14 +149,14 @@ public interface VaultApi {
@GET
@Fallback(EmptyListOnNotFoundOr404.class)
@Path("/keys")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
List<Key> listKeys(@EndpointParam URI keyVaultUri);
@Named("key:create")
@POST
@MapBinder(BindToJsonPayload.class)
@Path("/keys/{keyName}/create")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
KeyBundle createKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName,
@Nullable @PayloadParam("attributes") KeyAttributes attributes,
@Nullable @PayloadParam("crv") String curveName, @Nullable @PayloadParam("key_ops") List<String> keyOps,
@ -164,7 +167,7 @@ public interface VaultApi {
@PUT
@MapBinder(BindToJsonPayload.class)
@Path("/keys/{keyName}")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
KeyBundle importKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName,
@PayloadParam("Hsm") boolean hsm, @Nullable @PayloadParam("attributes") KeyAttributes attributes,
@Nullable @PayloadParam("key") JsonWebKey key, @Nullable @PayloadParam("tags") Map<String, String> tags);
@ -173,14 +176,14 @@ public interface VaultApi {
@GET
@Path("/keys/{keyName}")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
KeyBundle getKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
@Named("key:delete")
@DELETE
@Path("/keys/{keyName}")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
DeletedKeyBundle deleteKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
@Named("key:get_versions")
@ -188,14 +191,14 @@ public interface VaultApi {
@SelectJson("value")
@Path("/keys/{keyName}/versions")
@Fallback(EmptyListOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
List<Key> getKeyVersions(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
@Named("key:update")
@PATCH
@MapBinder(BindToJsonPayload.class)
@Path("/keys/{keyName}{keyVersion}")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
KeyBundle updateKey(@EndpointParam URI vaultBaseUrl,
@PathParam("keyName") String keyName,
@Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
@ -207,14 +210,14 @@ public interface VaultApi {
@POST
@SelectJson("value")
@Path("/keys/{keyName}/backup")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
String backupKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
@Named("key:restore")
@POST
@MapBinder(BindToJsonPayload.class)
@Path("/keys/restore")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
KeyBundle restoreKey(@EndpointParam URI vaultBaseUrl, @PayloadParam("value") String keyInfo);
// Soft-delete key operations
@ -223,27 +226,27 @@ public interface VaultApi {
@SelectJson("value")
@Path("/deletedkeys")
@Fallback(EmptyListOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
List<DeletedKeyBundle> listDeletedKeys(@EndpointParam URI vaultBaseUrl);
@Named("key:get_deleted")
@GET
@Path("/deletedkeys/{keyName}")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
DeletedKeyBundle getDeletedKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
@Named("key:recover_deleted")
@POST
@Path("/deletedkeys/{keyName}/recover")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
KeyBundle recoverDeletedKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
@Named("key:purge_deleted")
@DELETE
@Path("/deletedkeys/{keyName}")
@Fallback(FalseOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
boolean purgeDeletedKey(@EndpointParam URI vaultBaseUrl, @PathParam("keyName") String keyName);
// Key cryptographic operations
@ -251,7 +254,7 @@ public interface VaultApi {
@POST
@Path("/keys/{keyName}{keyVersion}/encrypt")
@MapBinder(BindToJsonPayload.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
KeyOperationResult encrypt(@EndpointParam URI vaultBaseUrl,
@PathParam("keyName") String keyName,
@Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
@ -262,7 +265,7 @@ public interface VaultApi {
@POST
@Path("/keys/{keyName}{keyVersion}/decrypt")
@MapBinder(BindToJsonPayload.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
KeyOperationResult decrypt(@EndpointParam URI vaultBaseUrl,
@PathParam("keyName") String keyName,
@Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
@ -273,7 +276,7 @@ public interface VaultApi {
@POST
@Path("/keys/{keyName}{keyVersion}/sign")
@MapBinder(BindToJsonPayload.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
KeyOperationResult sign(@EndpointParam URI vaultBaseUrl,
@PathParam("keyName") String keyName,
@Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
@ -284,7 +287,7 @@ public interface VaultApi {
@POST
@Path("/keys/{keyName}{keyVersion}/verify")
@MapBinder(BindToJsonPayload.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
boolean verify(@EndpointParam URI vaultBaseUrl,
@PathParam("keyName") String keyName,
@Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
@ -296,7 +299,7 @@ public interface VaultApi {
@POST
@Path("/keys/{keyName}{keyVersion}/wrapkey")
@MapBinder(BindToJsonPayload.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
KeyOperationResult wrap(@EndpointParam URI vaultBaseUrl,
@PathParam("keyName") String keyName,
@Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
@ -307,7 +310,7 @@ public interface VaultApi {
@POST
@Path("/keys/{keyName}{keyVersion}/unwrapkey")
@MapBinder(BindToJsonPayload.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
KeyOperationResult unwrap(@EndpointParam URI vaultBaseUrl,
@PathParam("keyName") String keyName,
@Nullable @PathParam("keyVersion") @ParamParser(PrependSlashOrEmptyString.class) String keyVersion,
@ -320,14 +323,14 @@ public interface VaultApi {
@GET
@Fallback(EmptyListOnNotFoundOr404.class)
@Path("/secrets")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
List<Secret> listSecrets(@EndpointParam URI keyVaultUri);
@Named("secret:set")
@PUT
@MapBinder(BindToJsonPayload.class)
@Path("/secrets/{secretName}")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
SecretBundle setSecret(@EndpointParam URI keyVaultUri, @PathParam("secretName") String secretName,
@Nullable @PayloadParam("attributes") SecretAttributes attributes,
@Nullable @PayloadParam("contentType") String contentType,
@ -337,7 +340,7 @@ public interface VaultApi {
@GET
@Path("/secrets/{secretName}{secretVersion}")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
SecretBundle getSecret(@EndpointParam URI vaultBaseUrl,
@PathParam("secretName") String secretName,
@Nullable @PathParam("secretVersion") @ParamParser(PrependSlashOrEmptyString.class) String secretVersion);
@ -346,7 +349,7 @@ public interface VaultApi {
@DELETE
@Path("/secrets/{secretName}")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
DeletedSecretBundle deleteSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
@Named("secret:get_versions")
@ -354,14 +357,14 @@ public interface VaultApi {
@SelectJson("value")
@Path("/secrets/{secretName}/versions")
@Fallback(EmptyListOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
List<Secret> getSecretVersions(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
@Named("secret:update")
@PATCH
@MapBinder(BindToJsonPayload.class)
@Path("/secrets/{secretName}{secretVersion}")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
SecretBundle updateSecret(@EndpointParam URI vaultBaseUrl,
@PathParam("secretName") String secretName,
@Nullable @PathParam("secretVersion") @ParamParser(PrependSlashOrEmptyString.class) String secretVersion,
@ -373,14 +376,14 @@ public interface VaultApi {
@POST
@SelectJson("value")
@Path("/secrets/{secretName}/backup")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
String backupSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
@Named("secret:restore")
@POST
@MapBinder(BindToJsonPayload.class)
@Path("/secrets/restore")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
SecretBundle restoreSecret(@EndpointParam URI vaultBaseUrl, @PayloadParam("value") String secretInfo);
// Soft-delete secret operations
@ -389,27 +392,27 @@ public interface VaultApi {
@SelectJson("value")
@Path("/deletedsecrets")
@Fallback(EmptyListOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
List<DeletedSecretBundle> listDeletedSecrets(@EndpointParam URI vaultBaseUrl);
@Named("secret:get_deleted")
@GET
@Path("/deletedsecrets/{secretName}")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
DeletedSecretBundle getDeletedSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
@Named("secret:recover_deleted")
@POST
@Path("/deletedsecrets/{secretName}/recover")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
SecretBundle recoverDeletedSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
@Named("secret:purge_deleted")
@DELETE
@Path("/deletedsecrets/{secretName}")
@Fallback(FalseOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
boolean purgeDeletedSecret(@EndpointParam URI vaultBaseUrl, @PathParam("secretName") String secretName);
// Certificate operations
@ -417,7 +420,7 @@ public interface VaultApi {
@POST
@MapBinder(BindToJsonPayload.class)
@Path("/certificates/{certificateName}/create")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
CertificateOperation createCertificate(@EndpointParam URI vaultBaseUrl,
@PathParam("certificateName") String certificateName,
@Nullable @PayloadParam("attributes") CertificateAttributes attributes,
@ -428,7 +431,7 @@ public interface VaultApi {
@GET
@Path("/certificates/{certificateName}{certificateVersion}")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
CertificateBundle getCertificate(@EndpointParam URI vaultBaseUrl,
@PathParam("certificateName") String certificateName,
@Nullable @PathParam("certificateVersion") @ParamParser(PrependSlashOrEmptyString.class) String certificateVersion);
@ -437,7 +440,7 @@ public interface VaultApi {
@DELETE
@Path("/certificates/{certificateName}")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
DeletedCertificateBundle deleteCertificate(@EndpointParam URI vaultBaseUrl,
@PathParam("certificateName") String certificateName);
@ -446,7 +449,7 @@ public interface VaultApi {
@SelectJson("value")
@Path("/certificates")
@Fallback(EmptyListOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
List<Certificate> getCertificates(@EndpointParam URI vaultBaseUrl);
@Named("certificate:list_deleted")
@ -454,21 +457,21 @@ public interface VaultApi {
@SelectJson("value")
@Path("/deletedcertificates")
@Fallback(EmptyListOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
List<DeletedCertificate> getDeletedCertificates(@EndpointParam URI vaultBaseUrl);
@Named("certificate:get_deleted")
@GET
@Path("/deletedcertificates/{certificateName}")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
DeletedCertificateBundle getDeletedCertificate(@EndpointParam URI vaultBaseUrl,
@PathParam("certificateName") String certificateName);
@Named("certificate:recover_deleted")
@POST
@Path("/deletedcertificates/{certificateName}/recover")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
CertificateBundle recoverDeletedCertificate(@EndpointParam URI vaultBaseUrl,
@PathParam("certificateName") String certificateName);
@ -476,7 +479,7 @@ public interface VaultApi {
@DELETE
@Path("/deletedcertificates/{certificateName}")
@Fallback(FalseOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
boolean purgeDeletedCertificate(@EndpointParam URI vaultBaseUrl, @PathParam("certificateName") String certificateName);
@Named("certificate:get_versions")
@ -484,7 +487,7 @@ public interface VaultApi {
@SelectJson("value")
@Path("/certificates/{certificateName}/versions")
@Fallback(EmptyListOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
List<Certificate> getCertificateVersions(@EndpointParam URI vaultBaseUrl,
@PathParam("certificateName") String certificateName);
@ -492,7 +495,7 @@ public interface VaultApi {
@PATCH
@MapBinder(BindToJsonPayload.class)
@Path("/certificates/{certificateName}{certificateVersion}")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
CertificateBundle updateCertificate(@EndpointParam URI vaultBaseUrl,
@PathParam("certificateName") String certificateName,
@Nullable @PathParam("certificateVersion") @ParamParser(PrependSlashOrEmptyString.class) String certificateVersion,
@ -504,7 +507,7 @@ public interface VaultApi {
@POST
@MapBinder(BindToJsonPayload.class)
@Path("/certificates/{certificateName}/import")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
CertificateBundle importCertificate(@EndpointParam URI vaultBaseUrl,
@PathParam("certificateName") String certificateName,
@Nullable @PayloadParam("attributes") CertificateAttributes attributes,
@ -515,7 +518,7 @@ public interface VaultApi {
@POST
@MapBinder(BindToJsonPayload.class)
@Path("/certificates/{certificateName}/pending/merge")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
CertificateBundle mergeCertificate(@EndpointParam URI vaultBaseUrl,
@PathParam("certificateName") String certificateName,
@Nullable @PayloadParam("attributes") CertificateAttributes attributes,
@ -525,7 +528,7 @@ public interface VaultApi {
@GET
@Path("/certificates/{certificateName}/pending")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
CertificateOperation getCertificateOperation(@EndpointParam URI vaultBaseUrl,
@PathParam("certificateName") String certificateName);
@ -533,7 +536,7 @@ public interface VaultApi {
@PATCH
@Path("/certificates/{certificateName}/pending")
@MapBinder(BindToJsonPayload.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
CertificateOperation updateCertificateOperation(@EndpointParam URI vaultBaseUrl,
@PathParam("certificateName") String certificateName,
@PayloadParam("cancellation_requested") boolean cancellationRequested);
@ -542,7 +545,7 @@ public interface VaultApi {
@DELETE
@Path("/certificates/{certificateName}/pending")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
CertificateOperation deleteCertificateOperation(@EndpointParam URI vaultBaseUrl,
@PathParam("certificateName") String certificateName);
@ -550,7 +553,7 @@ public interface VaultApi {
@PUT
@Path("/certificates/issuers/{issuerName}")
@MapBinder(BindToJsonPayload.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
IssuerBundle setCertificateIssuer(@EndpointParam URI vaultBaseUrl, @PathParam("issuerName") String issuerName,
@Nullable @PayloadParam("attributes") IssuerAttributes attributes,
@Nullable @PayloadParam("credentials") IssuerCredentials credentials,
@ -562,21 +565,21 @@ public interface VaultApi {
@SelectJson("value")
@Path("/certificates/issuers")
@Fallback(EmptyListOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
List<CertificateIssuer> getCertificateIssuers(@EndpointParam URI vaultBaseUrl);
@Named("certificate:get_issuer")
@GET
@Path("/certificates/issuers/{issuerName}")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
IssuerBundle getCertificateIssuer(@EndpointParam URI vaultBaseUrl, @PathParam("issuerName") String issuerName);
@Named("certificate:update_issuer")
@PATCH
@Path("/certificates/issuers/{issuerName}")
@MapBinder(BindToJsonPayload.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
IssuerBundle updateCertificateIssuer(@EndpointParam URI vaultBaseUrl, @PathParam("issuerName") String issuerName,
@Nullable @PayloadParam("attributes") IssuerAttributes attributes,
@Nullable @PayloadParam("credentials") IssuerCredentials credentials,
@ -587,35 +590,35 @@ public interface VaultApi {
@DELETE
@Path("/certificates/issuers/{issuerName}")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
IssuerBundle deleteCertificateIssuer(@EndpointParam URI vaultBaseUrl, @PathParam("issuerName") String issuerName);
@Named("certificate:get_contacts")
@GET
@Path("/certificates/contacts")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
Contacts getCertificateContacts(@EndpointParam URI vaultBaseUrl);
@Named("certificate:set_contacts")
@PUT
@Path("/certificates/contacts")
@MapBinder(BindToJsonPayload.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
Contacts setCertificateContacts(@EndpointParam URI vaultBaseUrl, @PayloadParam("contacts") List<Contact> contacts);
@Named("certificate:delete_contacts")
@DELETE
@Path("/certificates/contacts")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
Contacts deleteCertificateContacts(@EndpointParam URI vaultBaseUrl);
@Named("certificate:get_policy")
@GET
@Path("/certificates/{certificateName}/policy")
@Fallback(NullOnNotFoundOr404.class)
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
CertificatePolicy getCertificatePolicy(@EndpointParam URI vaultBaseUrl,
@PathParam("certificateName") String certificateName);
@ -623,7 +626,7 @@ public interface VaultApi {
@PATCH
@MapBinder(BindToJsonPayload.class)
@Path("/certificates/{certificateName}/policy")
@OAuthResource("https://vault.azure.net")
@OAuthResource(value = VAULT_API_STANDARD_ENDPOINT, chinaEndpoint = VAULT_API_CHINA_ENDPOINT)
CertificatePolicy updateCertificatePolicy(@EndpointParam URI vaultBaseUrl,
@PathParam("certificateName") String certificateName,
@Nullable @PayloadParam("attributes") CertificateAttributes attributes,

View File

@ -0,0 +1,38 @@
/*
* 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.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "IsChinaEndpointTest")
public class IsChinaEndpointTest {
@Test
public void testIsChinaEndpoint() {
AzureComputeHttpApiModule module = new AzureComputeHttpApiModule();
assertTrue(module.isChinaEndpoint("https://login.chinacloudapi.cn/tenantId/oauth2/token"));
assertFalse(module.isChinaEndpoint("http://login.chinacloudapi.cn/tenantId/oauth2/token"));
assertFalse(module.isChinaEndpoint("https://login.chinacloudapi.cn/otherpaths/not/oauth"));
assertFalse(module.isChinaEndpoint("https://login.microsoftonline.com/tenantId/oauth2/token"));
assertFalse(module.isChinaEndpoint("https://login.microsoft.com/otherpaths/not/oauth"));
}
}

View File

@ -30,12 +30,15 @@ public class ParseTenantIdTest {
assertEquals(module.provideTenant("https://login.microsoftonline.com/tenantId/oauth2/token"), "tenantId");
assertEquals(module.provideTenant("https://login.microsoft.com/tenant2/oauth2/token"), "tenant2");
assertEquals(module.provideTenant("https://login.chinacloudapi.cn/tenantId/oauth2/token"), "tenantId");
assertEquals(module.provideTenant("https://login.chinacloudapi.cn/tenant2/oauth2/token"), "tenant2");
assertInvalid(module, "https://login.microsoftonline.com/a/b/c/oauth2/token");
assertInvalid(module, "https://login.microsoft.com/a/b/c/oauth2/token");
assertInvalid(module, "https://login.microsoftonline.com//oauth2/token");
assertInvalid(module, "https://login.microsoft.com//oauth2/token");
assertInvalid(module, "https://login.microsoftabc.com/tenant/oauth2/token");
assertInvalid(module, "https://login.chinacloudapi.cn/a/b/c/oauth2/token");
assertInvalid(module, "https://login.chinacloudapi.cn//oauth2/token");
}
private static void assertInvalid(AzureComputeHttpApiModule module, String endpoint) {

View File

@ -17,7 +17,6 @@
package org.jclouds.azurecompute.arm.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.TIMEOUT_RESOURCE_DELETED;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_CERTIFICATE_DELETE_STATUS;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_CERTIFICATE_OPERATION_STATUS;
@ -28,6 +27,7 @@ import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_K
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_SECRET_DELETE_STATUS;
import static org.jclouds.azurecompute.arm.config.AzureComputeProperties.VAULT_SECRET_RECOVERABLE_STATUS;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
import static org.jclouds.oauth.v2.config.OAuthProperties.RESOURCE;
import static org.jclouds.util.Predicates2.retry;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
@ -166,6 +166,7 @@ public class BaseAzureComputeApiLiveTest extends BaseApiLiveTest<AzureComputeApi
// for oauth
AzureLiveTestUtils.defaultProperties(properties);
checkNotNull(setIfTestSystemPropertyPresent(properties, "oauth.endpoint"), "test.oauth.endpoint");
setIfTestSystemPropertyPresent(properties, RESOURCE);
return properties;
}