diff --git a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/AuthConstant.java b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/AuthConstant.java index 364929a543..f051ecb108 100644 --- a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/AuthConstant.java +++ b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/AuthConstant.java @@ -3,6 +3,8 @@ public class AuthConstant { public static final String SYSTEM_ACCESSKEYID = "alibabacloud.accessKeyId"; public static final String SYSTEM_ACCESSKEYSECRET = "alibabacloud.accessKeyIdSecret"; + public static final String SYSTEM_ACCESSKEY_SECRET = "alibabacloud.accessKeySecret"; + public static final String SYSTEM_SESSION_TOKEN = "alibabacloud.sessionToken"; public static final String DEFAULT_CREDENTIALS_FILE_PATH = System.getProperty("user.home") + "/.alibabacloud/credentials.ini"; @@ -11,6 +13,7 @@ public class AuthConstant { public static final String INI_TYPE = "type"; public static final String INI_TYPE_RAM = "ecs_ram_role"; public static final String INI_TYPE_ARN = "ram_role_arn"; + public static final String INI_TYPE_OIDC = "oidc_role_arn"; public static final String INI_TYPE_KEY_PAIR = "rsa_key_pair"; public static final String INI_PUBLIC_KEY_ID = "public_key_id"; public static final String INI_PRIVATE_KEY_FILE = "private_key_file"; @@ -19,6 +22,8 @@ public class AuthConstant { public static final String INI_ROLE_SESSION_NAME = "role_session_name"; public static final String INI_ROLE_ARN = "role_arn"; public static final String INI_POLICY = "policy"; + public static final String INI_OIDC_PROVIDER_ARN = "oidc_provider_arn"; + public static final String INI_OIDC_TOKEN_FILE_PATH = "oidc_token_file_path"; public static final long TSC_VALID_TIME_SECONDS = 3600L; public static final String DEFAULT_REGION = "region_id"; public static final String INI_ENABLE = "enable"; diff --git a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/CLIProfileCredentialsProvider.java b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/CLIProfileCredentialsProvider.java new file mode 100644 index 0000000000..98aa6d16a3 --- /dev/null +++ b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/CLIProfileCredentialsProvider.java @@ -0,0 +1,271 @@ +package com.aliyuncs.auth; + +import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.utils.AuthUtils; +import com.aliyuncs.utils.StringUtils; +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.List; + +public class CLIProfileCredentialsProvider implements AlibabaCloudCredentialsProvider { + private final String CLI_CREDENTIALS_CONFIG_PATH = System.getProperty("user.home") + + "/.aliyun/config.json"; + private volatile AlibabaCloudCredentialsProvider credentialsProvider; + private volatile String currentProfileName; + private final Object credentialsProviderLock = new Object(); + + private CLIProfileCredentialsProvider(Builder builder) { + this.currentProfileName = builder.profileName == null ? System.getenv("ALIBABA_CLOUD_PROFILE") : builder.profileName; + } + + public static Builder builder() { + return new Builder(); + } + + @Override + public AlibabaCloudCredentials getCredentials() throws ClientException { + if (AuthUtils.isDisableCLIProfile()) { + throw new ClientException("CLI credentials file is disabled."); + } + Config config = null; + try { + config = parseProfile(CLI_CREDENTIALS_CONFIG_PATH); + } catch (IOException e) { + throw new ClientException("Unable to get profile from CLI credentials file: " + e); + } + if (null == config) { + throw new ClientException("Unable to get profile from empty CLI credentials file."); + } + String refreshedProfileName = System.getenv("ALIBABA_CLOUD_PROFILE"); + if (shouldReloadCredentialsProvider(refreshedProfileName)) { + synchronized (credentialsProviderLock) { + if (shouldReloadCredentialsProvider(refreshedProfileName)) { + if (!StringUtils.isEmpty(refreshedProfileName)) { + this.currentProfileName = refreshedProfileName; + } + this.credentialsProvider = reloadCredentialsProvider(config, this.currentProfileName); + } + } + } + return this.credentialsProvider.getCredentials(); + } + + AlibabaCloudCredentialsProvider reloadCredentialsProvider(Config config, String profileName) throws ClientException { + String currentProfileName = !StringUtils.isEmpty(profileName) ? profileName : config.getCurrent(); + List profiles = config.getProfiles(); + if (profiles != null && !profiles.isEmpty()) { + for (Profile profile : profiles) { + if (!StringUtils.isEmpty(profile.getName()) && profile.getName().equals(currentProfileName)) { + String mode = profile.getMode(); + + if ("AK".equals(mode)) { + return new StaticCredentialsProvider( + new BasicCredentials(profile.getAccessKeyId(), profile.getAccessKeySecret())); + } else if ("RamRoleArn".equals(mode)) { + AlibabaCloudCredentialsProvider innerProvider = new StaticCredentialsProvider( + new BasicCredentials(profile.getAccessKeyId(), profile.getAccessKeySecret())); + return STSAssumeRoleSessionCredentialsProvider.builder() + .credentialsProvider(innerProvider) + .durationSeconds(profile.getDurationSeconds()) + .roleArn(profile.getRoleArn()) + .roleSessionName(profile.getRoleSessionName()) + .stsRegionId(profile.getStsRegionId()) + .enableVpc(profile.getEnableVpc()) + .policy(profile.getPolicy()) + .externalId(profile.getExternalId()) + .build(); + } else if ("EcsRamRole".equals(mode)) { + return InstanceProfileCredentialsProvider.builder() + .roleName(profile.getRamRoleName()) + .build(); + } else if ("OIDC".equals(mode)) { + return OIDCCredentialsProvider.builder() + .durationSeconds(profile.getDurationSeconds()) + .roleArn(profile.getRoleArn()) + .roleSessionName(profile.getRoleSessionName()) + .oidcProviderArn(profile.getOidcProviderArn()) + .oidcTokenFilePath(profile.getOidcTokenFile()) + .stsRegionId(profile.getStsRegionId()) + .enableVpc(profile.getEnableVpc()) + .policy(profile.getPolicy()) + .build(); + } else if ("ChainableRamRoleArn".equals(mode)) { + AlibabaCloudCredentialsProvider previousProvider = reloadCredentialsProvider(config, profile.getSourceProfile()); + return STSAssumeRoleSessionCredentialsProvider.builder() + .credentialsProvider(previousProvider) + .durationSeconds(profile.getDurationSeconds()) + .roleArn(profile.getRoleArn()) + .roleSessionName(profile.getRoleSessionName()) + .stsRegionId(profile.getStsRegionId()) + .enableVpc(profile.getEnableVpc()) + .policy(profile.getPolicy()) + .externalId(profile.getExternalId()) + .build(); + } else { + throw new ClientException(String.format("Unsupported profile mode '%s' form CLI credentials file.", mode)); + } + } + } + } + throw new ClientException(String.format("Unable to get profile with '%s' form CLI credentials file.", currentProfileName)); + } + + Config parseProfile(String configFilePath) throws ClientException, IOException { + File configFile = new File(configFilePath); + if (!configFile.exists() || !configFile.isFile() || !configFile.canRead()) { + throw new ClientException(String.format("Unable to open credentials file: %s.", configFile.getAbsolutePath())); + } + Gson gson = new Gson(); + BufferedReader br = null; + try { + br = new BufferedReader(new FileReader(configFile)); + StringBuilder sb = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + sb.append(line); + } + String jsonContent = sb.toString(); + return gson.fromJson(jsonContent, Config.class); + } catch (Exception e) { + throw new ClientException(String.format("Failed to parse credential form CLI credentials file: %s.", configFile.getAbsolutePath())); + } finally { + if (br != null) { + br.close(); + } + } + } + + boolean shouldReloadCredentialsProvider(String profileName) { + return this.credentialsProvider == null || (!StringUtils.isEmpty(this.currentProfileName) && !StringUtils.isEmpty(profileName) && !this.currentProfileName.equals(profileName)); + } + + String getProfileName() { + return this.currentProfileName; + } + + static final class Builder { + private String profileName; + + public Builder profileName(String profileName) { + this.profileName = profileName; + return this; + } + + CLIProfileCredentialsProvider build() { + return new CLIProfileCredentialsProvider(this); + } + } + + static class Config { + @SerializedName("current") + private String current; + @SerializedName("profiles") + private List profiles; + + public String getCurrent() { + return current; + } + + public List getProfiles() { + return profiles; + } + } + + static class Profile { + @SerializedName("name") + private String name; + @SerializedName("mode") + private String mode; + @SerializedName("access_key_id") + private String accessKeyId; + @SerializedName("access_key_secret") + private String accessKeySecret; + @SerializedName("ram_role_arn") + private String roleArn; + @SerializedName("ram_session_name") + private String roleSessionName; + @SerializedName("expired_seconds") + private Integer durationSeconds; + @SerializedName("sts_region") + private String stsRegionId; + @SerializedName("enable_vpc") + private Boolean enableVpc; + @SerializedName("ram_role_name") + private String ramRoleName; + @SerializedName("oidc_token_file") + private String oidcTokenFile; + @SerializedName("oidc_provider_arn") + private String oidcProviderArn; + @SerializedName("source_profile") + private String sourceProfile; + @SerializedName("policy") + private String policy; + @SerializedName("external_id") + private String externalId; + + public String getName() { + return name; + } + + public String getMode() { + return mode; + } + + public String getAccessKeyId() { + return accessKeyId; + } + + public String getAccessKeySecret() { + return accessKeySecret; + } + + public String getRoleArn() { + return roleArn; + } + + public String getRoleSessionName() { + return roleSessionName; + } + + public Integer getDurationSeconds() { + return durationSeconds; + } + + public String getStsRegionId() { + return stsRegionId; + } + + public Boolean getEnableVpc() { + return enableVpc; + } + + public String getRamRoleName() { + return ramRoleName; + } + + public String getOidcTokenFile() { + return oidcTokenFile; + } + + public String getOidcProviderArn() { + return oidcProviderArn; + } + + public String getSourceProfile() { + return sourceProfile; + } + + public String getPolicy() { + return policy; + } + + public String getExternalId() { + return externalId; + } + } +} diff --git a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/DefaultCredentialsProvider.java b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/DefaultCredentialsProvider.java index 796fa6665f..f6aae1bb6d 100644 --- a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/DefaultCredentialsProvider.java +++ b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/DefaultCredentialsProvider.java @@ -12,47 +12,75 @@ public class DefaultCredentialsProvider implements AlibabaCloudCredentialsProvid private List defaultProviders = new ArrayList(); private static final List USER_CONFIGURATION_PROVIDERS = new Vector(); + private volatile AlibabaCloudCredentialsProvider lastUsedCredentialsProvider; + private final Boolean reuseLastProviderEnabled; public DefaultCredentialsProvider() throws ClientException { + this.reuseLastProviderEnabled = true; + createDefaultChain(); + } + + private DefaultCredentialsProvider(Builder builder) { + this.reuseLastProviderEnabled = builder.reuseLastProviderEnabled; + createDefaultChain(); + } + + public static Builder builder() { + return new Builder(); + } + + private void createDefaultChain() { defaultProviders.add(new SystemPropertiesCredentialsProvider()); defaultProviders.add(new EnvironmentVariableCredentialsProvider()); - // Add oidc credentials provider - String oidcProviderArn = System.getenv("ALIBABA_CLOUD_OIDC_PROVIDER_ARN"); - String roleArn = System.getenv("ALIBABA_CLOUD_ROLE_ARN"); - String oidcTokenFile = System.getenv("ALIBABA_CLOUD_OIDC_TOKEN_FILE"); - if (!StringUtils.isEmpty(oidcProviderArn) && !StringUtils.isEmpty(oidcTokenFile) && !StringUtils.isEmpty(roleArn)) { - defaultProviders.add(new OIDCCredentialsProvider(roleArn, oidcProviderArn, oidcTokenFile, "java-sdk-v1-default-rsn", null)); + if (AuthUtils.environmentEnableOIDC()) { + defaultProviders.add(OIDCCredentialsProvider.builder().build()); } - + defaultProviders.add(CLIProfileCredentialsProvider.builder().build()); defaultProviders.add(new ProfileCredentialsProvider()); - String roleName = AuthUtils.getEnvironmentECSMetaData(); - if (roleName != null) { - if (roleName.isEmpty()) { - throw new ClientException("Environment variable roleName('ALIBABA_CLOUD_ECS_METADATA') cannot be empty"); - } - defaultProviders.add(new InstanceProfileCredentialsProvider(roleName)); + if (!AuthUtils.isDisableECSMetaData()) { + defaultProviders.add(InstanceProfileCredentialsProvider.builder().build()); + } + String uri = AuthUtils.getEnvironmentCredentialsURI(); + if (!StringUtils.isEmpty(uri)) { + defaultProviders.add(URLCredentialsProvider.builder() + .credentialsURI(uri) + .build()); } } @Override public AlibabaCloudCredentials getCredentials() throws ClientException { + if (this.reuseLastProviderEnabled && this.lastUsedCredentialsProvider != null) { + return this.lastUsedCredentialsProvider.getCredentials(); + } AlibabaCloudCredentials credential; + List errorMessages = new ArrayList(); if (USER_CONFIGURATION_PROVIDERS.size() > 0) { for (AlibabaCloudCredentialsProvider provider : USER_CONFIGURATION_PROVIDERS) { - credential = provider.getCredentials(); - if (null != credential) { - return credential; + try { + credential = provider.getCredentials(); + if (null != credential) { + this.lastUsedCredentialsProvider = provider; + return credential; + } + } catch (Exception e) { + errorMessages.add(provider.getClass().getName() + ": " + e.getMessage()); } } } for (AlibabaCloudCredentialsProvider provider : defaultProviders) { - credential = provider.getCredentials(); - if (null != credential) { - return credential; + try { + credential = provider.getCredentials(); + if (null != credential) { + this.lastUsedCredentialsProvider = provider; + return credential; + } + } catch (Exception e) { + errorMessages.add(provider.getClass().getName() + ": " + e.getMessage()); } } - throw new ClientException("not found credentials"); + throw new ClientException("Unable to load credentials from any of the providers in the chain: " + errorMessages); } public static boolean addCredentialsProvider(AlibabaCloudCredentialsProvider provider) { @@ -70,4 +98,17 @@ public static boolean containsCredentialsProvider(AlibabaCloudCredentialsProvide public static void clearCredentialsProvider() { DefaultCredentialsProvider.USER_CONFIGURATION_PROVIDERS.clear(); } + + public static final class Builder { + private Boolean reuseLastProviderEnabled = true; + + public Builder reuseLastProviderEnabled(Boolean reuseLastProviderEnabled) { + this.reuseLastProviderEnabled = reuseLastProviderEnabled; + return this; + } + + DefaultCredentialsProvider build() { + return new DefaultCredentialsProvider(this); + } + } } diff --git a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/ECSMetadataServiceCredentialsFetcher.java b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/ECSMetadataServiceCredentialsFetcher.java index 036572ea86..b0ea7f87c0 100644 --- a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/ECSMetadataServiceCredentialsFetcher.java +++ b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/ECSMetadataServiceCredentialsFetcher.java @@ -9,26 +9,41 @@ import com.aliyuncs.http.HttpResponse; import com.aliyuncs.http.MethodType; import com.aliyuncs.http.clients.CompatibleUrlConnClient; +import com.aliyuncs.utils.StringUtils; import com.google.gson.JsonObject; import com.google.gson.JsonParser; public class ECSMetadataServiceCredentialsFetcher { private static final String URL_IN_ECS_METADATA = "/latest/meta-data/ram/security-credentials/"; + private static final String URL_IN_METADATA_TOKEN = "/latest/api/token"; private static final int DEFAULT_TIMEOUT_IN_MILLISECONDS = 1000; private static final String ECS_METADATA_FETCH_ERROR_MSG = "Failed to get RAM session credentials from ECS metadata service."; private static final int DEFAULT_ECS_SESSION_TOKEN_DURATION_SECONDS = 3600 * 6; private URL credentialUrl; private String roleName; private String metadataServiceHost = "100.100.100.200"; - private int connectionTimeoutInMilliseconds; + private final boolean disableIMDSv1; + private final int metadataTokenDuration = 21600; + private int connectionTimeout; + private int readTimeout; public ECSMetadataServiceCredentialsFetcher() { - this.connectionTimeoutInMilliseconds = DEFAULT_TIMEOUT_IN_MILLISECONDS; + this.connectionTimeout = DEFAULT_TIMEOUT_IN_MILLISECONDS; + this.readTimeout = DEFAULT_TIMEOUT_IN_MILLISECONDS; + this.disableIMDSv1 = false; } + public ECSMetadataServiceCredentialsFetcher(String roleName, Boolean disableIMDSv1, Integer connectionTimeout, Integer readTimeout) { + this.connectionTimeout = connectionTimeout == null ? 1000 : connectionTimeout; + this.readTimeout = readTimeout == null ? 1000 : readTimeout; + this.disableIMDSv1 = disableIMDSv1 == null ? false : disableIMDSv1; + this.roleName = roleName; + } + + @Deprecated public void setRoleName(String roleName) { if (null == roleName) { - throw new NullPointerException("You must specify a valid role name."); + throw new IllegalArgumentException("You must specify a valid role name."); } this.roleName = roleName; setCredentialUrl(); @@ -42,6 +57,7 @@ private void setCredentialUrl() { } } + @Deprecated public ECSMetadataServiceCredentialsFetcher withECSMetadataServiceHost(String host) { System.err.println("withECSMetadataServiceHost() method is only for testing, please don't use it"); this.metadataServiceHost = host; @@ -49,24 +65,39 @@ public ECSMetadataServiceCredentialsFetcher withECSMetadataServiceHost(String ho return this; } + @Deprecated public ECSMetadataServiceCredentialsFetcher withConnectionTimeout(int milliseconds) { - this.connectionTimeoutInMilliseconds = milliseconds; + this.connectionTimeout = milliseconds; + this.readTimeout = milliseconds; return this; } + @Deprecated public String getMetadata() throws ClientException { - HttpRequest request = new HttpRequest(credentialUrl.toString()); + return getMetadata(credentialUrl.toString()); + } + + private String getMetadata(String url) throws ClientException { + HttpRequest request = new HttpRequest(url); request.setSysMethod(MethodType.GET); - request.setSysConnectTimeout(connectionTimeoutInMilliseconds); - request.setSysReadTimeout(connectionTimeoutInMilliseconds); - HttpResponse response; + request.setSysConnectTimeout(connectionTimeout); + request.setSysReadTimeout(readTimeout); + String metadataToken = this.getMetadataToken(); + if (metadataToken != null) { + request.putHeaderParameter("X-aliyun-ecs-metadata-token", metadataToken); + } + HttpResponse response; try { response = CompatibleUrlConnClient.compatibleGetResponse(request); } catch (Exception e) { throw new ClientException("Failed to connect ECS Metadata Service: " + e.toString()); } + if (response.getStatus() == HttpURLConnection.HTTP_NOT_FOUND) { + throw new ClientException("The role name was not found in the instance."); + } + if (response.getStatus() != HttpURLConnection.HTTP_OK) { throw new ClientException(ECS_METADATA_FETCH_ERROR_MSG + " HttpCode=" + response.getStatus()); } @@ -75,7 +106,11 @@ public String getMetadata() throws ClientException { } public InstanceProfileCredentials fetch() throws ClientException { - String jsonContent = getMetadata(); + String roleName = this.roleName; + if (StringUtils.isEmpty(this.roleName)) { + roleName = getMetadata("http://" + metadataServiceHost + URL_IN_ECS_METADATA); + } + String jsonContent = getMetadata("http://" + metadataServiceHost + URL_IN_ECS_METADATA + roleName); JsonObject jsonObject = JsonParser.parseString(jsonContent).getAsJsonObject(); if (!jsonObject.has("Code") || !jsonObject.has("AccessKeyId") || !jsonObject.has("AccessKeySecret") || !jsonObject .has("SecurityToken") || !jsonObject.has("Expiration")) { @@ -86,11 +121,11 @@ public InstanceProfileCredentials fetch() throws ClientException { throw new ClientException(ECS_METADATA_FETCH_ERROR_MSG); } return new InstanceProfileCredentials( - jsonObject.get("AccessKeyId").getAsString(), - jsonObject.get("AccessKeySecret").getAsString(), - jsonObject.get("SecurityToken").getAsString(), - jsonObject.get("Expiration").getAsString(), - DEFAULT_ECS_SESSION_TOKEN_DURATION_SECONDS); + jsonObject.get("AccessKeyId").getAsString(), + jsonObject.get("AccessKeySecret").getAsString(), + jsonObject.get("SecurityToken").getAsString(), + jsonObject.get("Expiration").getAsString(), + DEFAULT_ECS_SESSION_TOKEN_DURATION_SECONDS); } public InstanceProfileCredentials fetch(int retryTimes) throws ClientException { @@ -105,4 +140,34 @@ public InstanceProfileCredentials fetch(int retryTimes) throws ClientException { } throw new ClientException("Failed to connect ECS Metadata Service: Max retry times exceeded."); } + + private String getMetadataToken() throws ClientException { + try { + HttpRequest request = new HttpRequest("http://" + metadataServiceHost + URL_IN_METADATA_TOKEN); + request.setSysMethod(MethodType.PUT); + request.setSysConnectTimeout(connectionTimeout); + request.setSysReadTimeout(readTimeout); + request.putHeaderParameter("X-aliyun-ecs-metadata-token-ttl-seconds", String.valueOf(this.metadataTokenDuration)); + HttpResponse response; + try { + response = CompatibleUrlConnClient.compatibleGetResponse(request); + ; + } catch (Exception e) { + throw new ClientException("Failed to connect ECS Metadata Service: " + e); + } + if (response.getStatus() != HttpURLConnection.HTTP_OK) { + throw new ClientException("Failed to get token from ECS Metadata Service. HttpCode=" + response.getStatus() + ", ResponseMessage=" + response.getHttpContentString()); + } + return new String(response.getHttpContent()); + } catch (Exception ex) { + return throwErrorOrReturn(ex); + } + } + + private String throwErrorOrReturn(Exception e) throws ClientException { + if (this.disableIMDSv1) { + throw new ClientException("Failed to get token from ECS Metadata Service, and fallback to IMDS v1 is disabled via the disableIMDSv1 configuration is turned on. Original error: " + e.getMessage()); + } + return null; + } } \ No newline at end of file diff --git a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/EnvironmentVariableCredentialsProvider.java b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/EnvironmentVariableCredentialsProvider.java index e9e75d5c9d..3fbe645bbf 100644 --- a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/EnvironmentVariableCredentialsProvider.java +++ b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/EnvironmentVariableCredentialsProvider.java @@ -2,6 +2,7 @@ import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.utils.AuthUtils; +import com.aliyuncs.utils.StringUtils; public class EnvironmentVariableCredentialsProvider implements AlibabaCloudCredentialsProvider { @Override @@ -12,14 +13,15 @@ public AlibabaCloudCredentials getCredentials() throws ClientException { String accessKeyId = AuthUtils.getEnvironmentAccessKeyId(); String accessKeySecret = AuthUtils.getEnvironmentAccessKeySecret(); - if (accessKeyId == null || accessKeySecret == null) { - return null; + String securityToken = AuthUtils.getEnvironmentSecurityToken(); + if (StringUtils.isEmpty(accessKeyId)) { + throw new ClientException("Environment variable accessKeyId cannot be empty."); } - if (accessKeyId.isEmpty()) { - throw new ClientException("Environment variable accessKeyId cannot be empty"); + if (StringUtils.isEmpty(accessKeySecret)) { + throw new ClientException("Environment variable accessKeySecret cannot be empty."); } - if (accessKeySecret.isEmpty()) { - throw new ClientException("Environment variable accessKeySecret cannot be empty"); + if (!StringUtils.isEmpty(securityToken)) { + return new BasicSessionCredentials(accessKeyId, accessKeySecret, securityToken); } return new BasicCredentials(accessKeyId, accessKeySecret); } diff --git a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/InstanceProfileCredentialsProvider.java b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/InstanceProfileCredentialsProvider.java index da6a373fb5..76da0e8245 100644 --- a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/InstanceProfileCredentialsProvider.java +++ b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/InstanceProfileCredentialsProvider.java @@ -1,6 +1,7 @@ package com.aliyuncs.auth; import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.utils.AuthUtils; public class InstanceProfileCredentialsProvider implements AlibabaCloudCredentialsProvider { @@ -25,6 +26,23 @@ public InstanceProfileCredentialsProvider withFetcher(ECSMetadataServiceCredenti return this; } + private InstanceProfileCredentialsProvider(BuilderImpl builder) { + if (AuthUtils.isDisableECSMetaData()) { + throw new IllegalArgumentException("IMDS credentials is disabled."); + } + this.roleName = builder.roleName == null ? AuthUtils.getEnvironmentECSMetaData() : builder.roleName; + boolean disableIMDSv1 = builder.disableIMDSv1 == null ? AuthUtils.getDisableECSIMDSv1() : builder.disableIMDSv1; + this.fetcher = new ECSMetadataServiceCredentialsFetcher( + roleName, + disableIMDSv1, + builder.connectionTimeout, + builder.readTimeout); + } + + public static Builder builder() { + return new BuilderImpl(); + } + @Override public AlibabaCloudCredentials getCredentials() throws ClientException { if (credentials == null || credentials.isExpired()) { @@ -41,4 +59,52 @@ public AlibabaCloudCredentials getCredentials() throws ClientException { } return credentials; } + + public interface Builder { + Builder roleName(String roleName); + + Builder disableIMDSv1(Boolean disableIMDSv1); + + Builder connectionTimeout(Integer connectionTimeout); + + Builder readTimeout(Integer readTimeout); + + InstanceProfileCredentialsProvider build(); + } + + private static final class BuilderImpl implements Builder { + private String roleName; + private Boolean disableIMDSv1; + private Integer connectionTimeout; + private Integer readTimeout; + + @Override + public Builder roleName(String roleName) { + this.roleName = roleName; + return this; + } + + @Override + public Builder disableIMDSv1(Boolean disableIMDSv1) { + this.disableIMDSv1 = disableIMDSv1; + return this; + } + + @Override + public Builder connectionTimeout(Integer connectionTimeout) { + this.connectionTimeout = connectionTimeout; + return this; + } + + @Override + public Builder readTimeout(Integer readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + @Override + public InstanceProfileCredentialsProvider build() { + return new InstanceProfileCredentialsProvider(this); + } + } } \ No newline at end of file diff --git a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/OIDCCredentialsProvider.java b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/OIDCCredentialsProvider.java index 7ba4584762..a6a70a5a13 100644 --- a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/OIDCCredentialsProvider.java +++ b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/OIDCCredentialsProvider.java @@ -4,9 +4,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Date; - -import java.io.FileInputStream; -import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; @@ -72,29 +69,31 @@ void setPolicy(String policy) { private String stsEndpoint; private long durationSeconds; + private int connectTimeout; + private int readTimeout; // inner cache private BasicSessionCredentials credentials; public OIDCCredentialsProvider(String roleArn, String providerArn, String oidcTokenFilePath, String roleSessionName, String regionId) throws ClientException { - this.roleArn = !StringUtils.isEmpty(roleArn) ? roleArn : System.getenv("ALIBABA_CLOUD_ROLE_ARN"); + this.roleArn = !StringUtils.isEmpty(roleArn) ? roleArn : AuthUtils.getEnvironmentRoleArn(); if (StringUtils.isEmpty(this.roleArn)) { throw new ClientException("roleArn does not exist and env ALIBABA_CLOUD_ROLE_ARN is null."); } - this.oidcProviderArn = !StringUtils.isEmpty(providerArn) ? providerArn : System.getenv("ALIBABA_CLOUD_OIDC_PROVIDER_ARN"); + this.oidcProviderArn = !StringUtils.isEmpty(providerArn) ? providerArn : AuthUtils.getEnvironmentOIDCProviderArn(); if (StringUtils.isEmpty(this.oidcProviderArn)) { throw new ClientException("OIDCProviderArn does not exist and env ALIBABA_CLOUD_OIDC_PROVIDER_ARN is null."); } - this.oidcTokenFilePath = !StringUtils.isEmpty(oidcTokenFilePath) ? oidcTokenFilePath : System.getenv("ALIBABA_CLOUD_OIDC_TOKEN_FILE"); + this.oidcTokenFilePath = !StringUtils.isEmpty(oidcTokenFilePath) ? oidcTokenFilePath : AuthUtils.getEnvironmentOIDCTokenFilePath(); if (StringUtils.isEmpty(this.oidcTokenFilePath)) { throw new ClientException("OIDCTokenFilePath does not exist and env ALIBABA_CLOUD_OIDC_TOKEN_FILE is null."); } - this.roleSessionName = !StringUtils.isEmpty(roleSessionName) ? roleSessionName : System.getenv("ALIBABA_CLOUD_ROLE_SESSION_NAME"); + this.roleSessionName = !StringUtils.isEmpty(roleSessionName) ? roleSessionName : AuthUtils.getEnvironmentRoleSessionName(); if (StringUtils.isEmpty(this.roleSessionName)) { - this.roleSessionName = "DEFAULT_ROLE_SESSION_NAME_FOR_JAVA_SDK_V1"; + this.roleSessionName = "aliyun-java-sdk-" + System.currentTimeMillis(); } if (StringUtils.isEmpty(regionId)) { @@ -104,6 +103,49 @@ public OIDCCredentialsProvider(String roleArn, String providerArn, String oidcTo } this.durationSeconds = 3600L; + this.connectTimeout = 5000; + this.readTimeout = 10000; + } + + private OIDCCredentialsProvider(Builder builder) { + this.roleSessionName = builder.roleSessionName == null ? !StringUtils.isEmpty(AuthUtils.getEnvironmentRoleSessionName()) ? + AuthUtils.getEnvironmentRoleSessionName() : "aliyun-java-sdk-" + System.currentTimeMillis() : builder.roleSessionName; + this.durationSeconds = builder.durationSeconds == null ? 3600 : builder.durationSeconds; + if (this.durationSeconds < 900) { + throw new IllegalArgumentException("Session duration should be in the range of 900s - max session duration."); + } + + this.roleArn = builder.roleArn == null ? AuthUtils.getEnvironmentRoleArn() : builder.roleArn; + if (StringUtils.isEmpty(this.roleArn)) { + throw new IllegalArgumentException("RoleArn or environment variable ALIBABA_CLOUD_ROLE_ARN cannot be empty."); + } + + this.oidcProviderArn = builder.oidcProviderArn == null ? AuthUtils.getEnvironmentOIDCProviderArn() : builder.oidcProviderArn; + if (StringUtils.isEmpty(this.oidcProviderArn)) { + throw new IllegalArgumentException("OIDCProviderArn or environment variable ALIBABA_CLOUD_OIDC_PROVIDER_ARN cannot be empty."); + } + + this.oidcTokenFilePath = builder.oidcTokenFilePath == null ? AuthUtils.getEnvironmentOIDCTokenFilePath() : builder.oidcTokenFilePath; + if (StringUtils.isEmpty(this.oidcTokenFilePath)) { + throw new IllegalArgumentException("OIDCTokenFilePath or environment variable ALIBABA_CLOUD_OIDC_TOKEN_FILE cannot be empty."); + } + + this.policy = builder.policy; + this.connectTimeout = builder.connectionTimeout == null ? 5000 : builder.connectionTimeout; + this.readTimeout = builder.readTimeout == null ? 10000 : builder.readTimeout; + + String prefix = builder.enableVpc != null ? (builder.enableVpc ? "sts-vpc" : "sts") : AuthUtils.isEnableVpcEndpoint() ? "sts-vpc" : "sts"; + if (!StringUtils.isEmpty(builder.stsRegionId)) { + this.stsEndpoint = String.format("https://%s.%s.aliyuncs.com", prefix, builder.stsRegionId); + } else if (!StringUtils.isEmpty(AuthUtils.getEnvironmentSTSRegion())) { + this.stsEndpoint = String.format("https://%s.%s.aliyuncs.com", prefix, AuthUtils.getEnvironmentSTSRegion()); + } else { + this.stsEndpoint = "https://sts.aliyuncs.com"; + } + } + + public static Builder builder() { + return new Builder(); } @Override @@ -147,8 +189,8 @@ private String invokeAssumeRoleWithOIDC() throws ClientException { HttpRequest httpRequest = new HttpRequest(url); httpRequest.setSysMethod(MethodType.POST); httpRequest.setHttpContentType(FormatType.FORM); - httpRequest.setSysConnectTimeout(1000); - httpRequest.setSysReadTimeout(3000); + httpRequest.setSysConnectTimeout(connectTimeout); + httpRequest.setSysReadTimeout(readTimeout); httpRequest.putHeaderParameter("UserAgent", UserAgentConfig.resolve(null, null)); String oidcToken = AuthUtils.readFile(oidcTokenFilePath); if (oidcToken == null) { @@ -161,7 +203,9 @@ private String invokeAssumeRoleWithOIDC() throws ClientException { body.put("OIDCProviderArn", this.oidcProviderArn); body.put("OIDCToken", oidcToken); body.put("RoleSessionName", this.roleSessionName); - body.put("Policy", this.policy); + if (policy != null) { + body.put("Policy", this.policy); + } StringBuilder content = new StringBuilder(); @@ -203,4 +247,71 @@ private String invokeAssumeRoleWithOIDC() throws ClientException { return new String(response.getHttpContent()); } + + public static final class Builder { + private String roleSessionName; + private Integer durationSeconds; + private String roleArn; + private String oidcProviderArn; + private String oidcTokenFilePath; + private String policy; + private Integer connectionTimeout; + private Integer readTimeout; + private String stsRegionId; + private Boolean enableVpc; + + public Builder roleSessionName(String roleSessionName) { + this.roleSessionName = roleSessionName; + return this; + } + + public Builder durationSeconds(Integer durationSeconds) { + this.durationSeconds = durationSeconds; + return this; + } + + public Builder roleArn(String roleArn) { + this.roleArn = roleArn; + return this; + } + + public Builder oidcProviderArn(String oidcProviderArn) { + this.oidcProviderArn = oidcProviderArn; + return this; + } + + public Builder oidcTokenFilePath(String oidcTokenFilePath) { + this.oidcTokenFilePath = oidcTokenFilePath; + return this; + } + + public Builder policy(String policy) { + this.policy = policy; + return this; + } + + public Builder connectionTimeout(Integer connectionTimeout) { + this.connectionTimeout = connectionTimeout; + return this; + } + + public Builder readTimeout(Integer readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + public Builder stsRegionId(String stsRegionId) { + this.stsRegionId = stsRegionId; + return this; + } + + public Builder enableVpc(Boolean enableVpc) { + this.enableVpc = enableVpc; + return this; + } + + public OIDCCredentialsProvider build() { + return new OIDCCredentialsProvider(this); + } + } } diff --git a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/ProfileCredentialsProvider.java b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/ProfileCredentialsProvider.java index c32398046e..a6ffeae94d 100644 --- a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/ProfileCredentialsProvider.java +++ b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/ProfileCredentialsProvider.java @@ -75,10 +75,13 @@ private AlibabaCloudCredentials createCredential(Map clientConfi if (AuthConstant.INI_TYPE_RAM.equals(configType)) { return getInstanceProfileCredentials(clientConfig, factory); } + if (AuthConstant.INI_TYPE_OIDC.equals(configType)) { + return getSTSOIDCRoleSessionCredentials(clientConfig, factory); + } String accessKeyId = clientConfig.get(AuthConstant.INI_ACCESS_KEY_ID); String accessKeySecret = clientConfig.get(AuthConstant.INI_ACCESS_KEY_IDSECRET); if (StringUtils.isEmpty(accessKeyId) || StringUtils.isEmpty(accessKeySecret)) { - return null; + throw new ClientException("The configured access_key_id or access_key_secret is empty."); } return new BasicCredentials(accessKeyId, accessKeySecret); } @@ -104,6 +107,30 @@ private AlibabaCloudCredentials getSTSAssumeRoleSessionCredentials(Map clientConfig, + CredentialsProviderFactory factory) throws ClientException { + String roleSessionName = clientConfig.get(AuthConstant.INI_ROLE_SESSION_NAME); + String roleArn = clientConfig.get(AuthConstant.INI_ROLE_ARN); + String OIDCProviderArn = clientConfig.get(AuthConstant.INI_OIDC_PROVIDER_ARN); + String OIDCTokenFilePath = clientConfig.get(AuthConstant.INI_OIDC_TOKEN_FILE_PATH); + String policy = clientConfig.get(AuthConstant.INI_POLICY); + if (StringUtils.isEmpty(roleArn)) { + throw new ClientException("The configured role_arn is empty."); + } + if (StringUtils.isEmpty(OIDCProviderArn)) { + throw new ClientException("The configured oidc_provider_arn is empty."); + } + OIDCCredentialsProvider provider = factory.createCredentialsProvider( + OIDCCredentialsProvider.builder() + .roleArn(roleArn) + .roleSessionName(roleSessionName) + .oidcProviderArn(OIDCProviderArn) + .oidcTokenFilePath(OIDCTokenFilePath) + .policy(policy) + .build()); + return provider.getCredentials(); + } + private AlibabaCloudCredentials getSTSGetSessionAccessKeyCredentials(Map clientConfig, CredentialsProviderFactory factory) throws ClientException { diff --git a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/STSAssumeRoleSessionCredentialsProvider.java b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/STSAssumeRoleSessionCredentialsProvider.java index 075128ede9..6e73b82a6d 100644 --- a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/STSAssumeRoleSessionCredentialsProvider.java +++ b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/STSAssumeRoleSessionCredentialsProvider.java @@ -8,6 +8,8 @@ import com.aliyuncs.exceptions.ServerException; import com.aliyuncs.profile.DefaultProfile; import com.aliyuncs.profile.IClientProfile; +import com.aliyuncs.utils.AuthUtils; +import com.aliyuncs.utils.StringUtils; /** * This implementation of AlibabaCloudCredentialsProvider accesses Alibaba Cloud STS service to assume a Role and get @@ -22,7 +24,7 @@ public class STSAssumeRoleSessionCredentialsProvider implements AlibabaCloudCred /** * The arn of the role to be assumed. */ - private final String roleArn; + private String roleArn; /** * For test * To know how many rounds AssumeRole has been called @@ -42,7 +44,14 @@ public class STSAssumeRoleSessionCredentialsProvider implements AlibabaCloudCred private long roleSessionDurationSeconds; private String policy; + private String externalId; private BasicSessionCredentials credentials = null; + /** + * Unit of millisecond + */ + private int connectTimeout; + private int readTimeout; + private String stsEndpoint; public STSAssumeRoleSessionCredentialsProvider(AlibabaCloudCredentials longLivedCredentials, @@ -60,6 +69,8 @@ public STSAssumeRoleSessionCredentialsProvider(AlibabaCloudCredentialsProvider l this.roleSessionName = getNewRoleSessionName(); this.stsClient = new DefaultAcsClient(clientProfile, longLivedCredentialsProvider); this.roleSessionDurationSeconds = DEFAULT_DURATION_SECONDS; + this.connectTimeout = 5000; + this.readTimeout = 10000; } public STSAssumeRoleSessionCredentialsProvider(String accessKeyId, String accessKeySecret, String roleSessionName, @@ -69,6 +80,8 @@ public STSAssumeRoleSessionCredentialsProvider(String accessKeyId, String access DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret); this.stsClient = new DefaultAcsClient(profile); this.roleSessionDurationSeconds = AuthConstant.TSC_VALID_TIME_SECONDS; + this.connectTimeout = 5000; + this.readTimeout = 10000; } public STSAssumeRoleSessionCredentialsProvider(String accessKeyId, String accessKeySecret, String roleSessionName, @@ -87,9 +100,9 @@ public STSAssumeRoleSessionCredentialsProvider withRoleSessionName(String roleSe } public STSAssumeRoleSessionCredentialsProvider withRoleSessionDurationSeconds(long roleSessionDurationSeconds) { - if (roleSessionDurationSeconds < 900 || roleSessionDurationSeconds > 3600) { + if (roleSessionDurationSeconds < 900) { throw new IllegalArgumentException( - "Assume Role session duration should be in the range of 15min - 1Hr"); + "Assume Role session duration should be in the range of 15min - max"); } this.roleSessionDurationSeconds = roleSessionDurationSeconds; return this; @@ -100,6 +113,52 @@ public STSAssumeRoleSessionCredentialsProvider withSTSClient(IAcsClient client) return this; } + private STSAssumeRoleSessionCredentialsProvider(Builder builder) { + this.roleSessionName = builder.roleSessionName == null ? !StringUtils.isEmpty(AuthUtils.getEnvironmentRoleSessionName()) ? + AuthUtils.getEnvironmentRoleSessionName() : getNewRoleSessionName() : builder.roleSessionName; + this.roleSessionDurationSeconds = builder.durationSeconds == null ? 3600 : builder.durationSeconds; + if (this.roleSessionDurationSeconds < 900) { + throw new IllegalArgumentException("Session duration should be in the range of 900s - max session duration."); + } + + this.roleArn = builder.roleArn == null ? AuthUtils.getEnvironmentRoleArn() : builder.roleArn; + if (StringUtils.isEmpty(this.roleArn)) { + throw new IllegalArgumentException("RoleArn or environment variable ALIBABA_CLOUD_ROLE_ARN cannot be empty."); + } + this.policy = builder.policy; + this.externalId = builder.externalId; + this.connectTimeout = builder.connectionTimeout == null ? 5000 : builder.connectionTimeout; + this.readTimeout = builder.readTimeout == null ? 10000 : builder.readTimeout; + + String prefix = builder.enableVpc != null ? (builder.enableVpc ? "sts-vpc" : "sts") : AuthUtils.isEnableVpcEndpoint() ? "sts-vpc" : "sts"; + if (!StringUtils.isEmpty(builder.stsRegionId)) { + this.stsEndpoint = String.format("%s.%s.aliyuncs.com", prefix, builder.stsRegionId); + } else if (!StringUtils.isEmpty(AuthUtils.getEnvironmentSTSRegion())) { + this.stsEndpoint = String.format("%s.%s.aliyuncs.com", prefix, AuthUtils.getEnvironmentSTSRegion()); + } else { + this.stsEndpoint = "sts.aliyuncs.com"; + } + + DefaultProfile profile = DefaultProfile.getProfile(builder.stsRegionId); + + + if (null != builder.credentialsProvider) { + this.stsClient = new DefaultAcsClient(profile, builder.credentialsProvider); + } else if (!StringUtils.isEmpty(builder.securityToken)) { + AlibabaCloudCredentialsProvider credentialsProvider = new StaticCredentialsProvider( + new BasicSessionCredentials(builder.accessKeyId, builder.accessKeySecret, builder.securityToken)); + this.stsClient = new DefaultAcsClient(profile, credentialsProvider); + } else { + AlibabaCloudCredentialsProvider credentialsProvider = new StaticCredentialsProvider( + new BasicCredentials(builder.accessKeyId, builder.accessKeySecret)); + this.stsClient = new DefaultAcsClient(profile, credentialsProvider); + } + } + + public static Builder builder() { + return new Builder(); + } + @Override public AlibabaCloudCredentials getCredentials() throws ClientException, ServerException { if (credentials == null || credentials.willSoonExpire()) { @@ -116,9 +175,17 @@ private BasicSessionCredentials getNewSessionCredentials() throws ClientExceptio assumeRoleRequest.setRoleArn(roleArn); assumeRoleRequest.setRoleSessionName(roleSessionName); assumeRoleRequest.setDurationSeconds(roleSessionDurationSeconds); - if (null != policy){ + assumeRoleRequest.setSysConnectTimeout(connectTimeout); + assumeRoleRequest.setSysReadTimeout(readTimeout); + if (!StringUtils.isEmpty(stsEndpoint)) { + assumeRoleRequest.setSysEndpoint(stsEndpoint); + } + if (null != policy) { assumeRoleRequest.setPolicy(policy); } + if (null != externalId) { + assumeRoleRequest.setExternalId(externalId); + } AssumeRoleResponse response = stsClient.getAcsResponse(assumeRoleRequest); return new BasicSessionCredentials( response.getCredentials().getAccessKeyId(), @@ -127,4 +194,89 @@ private BasicSessionCredentials getNewSessionCredentials() throws ClientExceptio roleSessionDurationSeconds ); } + + public static final class Builder { + private String roleSessionName; + private Integer durationSeconds; + private String roleArn; + private String policy; + private Integer connectionTimeout; + private Integer readTimeout; + private String stsRegionId; + private Boolean enableVpc; + private String accessKeyId; + private String accessKeySecret; + private String securityToken; + private AlibabaCloudCredentialsProvider credentialsProvider; + private String externalId; + + public Builder roleSessionName(String roleSessionName) { + this.roleSessionName = roleSessionName; + return this; + } + + public Builder durationSeconds(Integer durationSeconds) { + this.durationSeconds = durationSeconds; + return this; + } + + public Builder roleArn(String roleArn) { + this.roleArn = roleArn; + return this; + } + + public Builder policy(String policy) { + this.policy = policy; + return this; + } + + public Builder connectionTimeout(Integer connectionTimeout) { + this.connectionTimeout = connectionTimeout; + return this; + } + + public Builder readTimeout(Integer readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + public Builder stsRegionId(String stsRegionId) { + this.stsRegionId = stsRegionId; + return this; + } + + public Builder enableVpc(Boolean enableVpc) { + this.enableVpc = enableVpc; + return this; + } + + public Builder accessKeyId(String accessKeyId) { + this.accessKeyId = accessKeyId; + return this; + } + + public Builder accessKeySecret(String accessKeySecret) { + this.accessKeySecret = accessKeySecret; + return this; + } + + public Builder securityToken(String securityToken) { + this.securityToken = securityToken; + return this; + } + + public Builder credentialsProvider(AlibabaCloudCredentialsProvider credentialsProvider) { + this.credentialsProvider = credentialsProvider; + return this; + } + + public Builder externalId(String externalId) { + this.externalId = externalId; + return this; + } + + public STSAssumeRoleSessionCredentialsProvider build() { + return new STSAssumeRoleSessionCredentialsProvider(this); + } + } } \ No newline at end of file diff --git a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/SystemPropertiesCredentialsProvider.java b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/SystemPropertiesCredentialsProvider.java index b4584fa0f3..748040ad9c 100644 --- a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/SystemPropertiesCredentialsProvider.java +++ b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/SystemPropertiesCredentialsProvider.java @@ -1,22 +1,31 @@ package com.aliyuncs.auth; import com.aliyuncs.exceptions.ClientException; -import com.aliyuncs.exceptions.ServerException; import com.aliyuncs.utils.AuthUtils; import com.aliyuncs.utils.StringUtils; public class SystemPropertiesCredentialsProvider implements AlibabaCloudCredentialsProvider { @Override - public AlibabaCloudCredentials getCredentials() throws ClientException, ServerException { + public AlibabaCloudCredentials getCredentials() throws ClientException { if (!"default".equals(AuthUtils.getClientType())) { return null; } String accessKeyId = System.getProperty(AuthConstant.SYSTEM_ACCESSKEYID); - String accessKeySecret = System.getProperty(AuthConstant.SYSTEM_ACCESSKEYSECRET); - if (StringUtils.isEmpty(accessKeyId) || StringUtils.isEmpty(accessKeySecret)) { - return null; + String accessKeySecret = System.getProperty(AuthConstant.SYSTEM_ACCESSKEY_SECRET); + if (!StringUtils.isEmpty(System.getProperty(AuthConstant.SYSTEM_ACCESSKEYSECRET))) { + accessKeySecret = System.getProperty(AuthConstant.SYSTEM_ACCESSKEYSECRET); + } + String securityToken = System.getProperty(AuthConstant.SYSTEM_SESSION_TOKEN); + if (StringUtils.isEmpty(accessKeyId)) { + throw new ClientException("System property alibabacloud.accessKeyId cannot be empty."); + } + if (StringUtils.isEmpty(accessKeySecret)) { + throw new ClientException("System property alibabacloud.accessKeySecret cannot be empty."); + } + if (!StringUtils.isEmpty(securityToken)) { + return new BasicSessionCredentials(accessKeyId, accessKeySecret, securityToken); } return new BasicCredentials(accessKeyId, accessKeySecret); diff --git a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/URLCredentialsProvider.java b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/URLCredentialsProvider.java new file mode 100644 index 0000000000..223ce24cd2 --- /dev/null +++ b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/URLCredentialsProvider.java @@ -0,0 +1,123 @@ +package com.aliyuncs.auth; + +import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.http.HttpRequest; +import com.aliyuncs.http.HttpResponse; +import com.aliyuncs.http.MethodType; +import com.aliyuncs.http.clients.CompatibleUrlConnClient; +import com.aliyuncs.utils.AuthUtils; +import com.aliyuncs.utils.ParameterHelper; +import com.aliyuncs.utils.StringUtils; +import com.google.gson.Gson; + +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.text.ParseException; +import java.util.Map; + +public class URLCredentialsProvider implements AlibabaCloudCredentialsProvider { + + private final URL credentialsURI; + /** + * Unit of millisecond + */ + private final int connectTimeout; + private final int readTimeout; + + private URLCredentialsProvider(Builder builder) { + String credentialsURI = builder.credentialsURI == null ? AuthUtils.getEnvironmentCredentialsURI() : builder.credentialsURI; + if (StringUtils.isEmpty(credentialsURI)) { + throw new IllegalArgumentException("Credential URI or environment variable ALIBABA_CLOUD_CREDENTIALS_URI cannot be empty."); + } + try { + this.credentialsURI = new URL(credentialsURI); + } catch (MalformedURLException e) { + throw new IllegalArgumentException("Credential URI is not valid."); + } + this.connectTimeout = builder.connectionTimeout == null ? 5000 : builder.connectionTimeout; + this.readTimeout = builder.readTimeout == null ? 10000 : builder.readTimeout; + } + + public static Builder builder() { + return new Builder(); + } + + @Override + public AlibabaCloudCredentials getCredentials() throws ClientException { + HttpRequest request = new HttpRequest(this.credentialsURI.toString()); + request.setSysMethod(MethodType.GET); + request.setSysConnectTimeout(connectTimeout); + request.setSysReadTimeout(readTimeout); + HttpResponse response; + + try { + response = CompatibleUrlConnClient.compatibleGetResponse(request); + } catch (Exception e) { + throw new ClientException("Failed to connect Server: " + e); + } + + if (response.getStatus() != HttpURLConnection.HTTP_OK) { + throw new ClientException("Failed to get credentials from server: " + this.credentialsURI + + "\nHttpCode=" + response.getStatus() + + "\nHttpRAWContent=" + response.getHttpContentString()); + } + + Gson gson = new Gson(); + Map map; + try { + map = gson.fromJson(response.getHttpContentString(), Map.class); + } catch (Exception e) { + throw new ClientException("Failed to parse credentials from server: " + this.credentialsURI + + "\nHttpCode=" + response.getStatus() + + "\nHttpRAWContent=" + response.getHttpContentString()); + } + if (null == map || !map.containsKey("Code") || !map.get("Code").equals("Success")) { + throw new ClientException(String.format("Error retrieving credentials from url: %s, result: %s.", this.credentialsURI, response.getHttpContentString())); + } + if (!map.containsKey("AccessKeyId") || !map.containsKey("AccessKeySecret") || !map.containsKey("SecurityToken") || !map.containsKey("Expiration")) { + throw new ClientException(String.format("Error retrieving credentials from url: %s, result: %s.", this.credentialsURI, response.getHttpContentString())); + } + long expiration; + try { + expiration = ParameterHelper.parseISO8601(map.get("Expiration")).getTime(); + } catch (ParseException e) { + throw new ClientException(String.format("Error retrieving credentials expiration time from url: %s, result: %s.", this.credentialsURI, response.getHttpContentString())); + } + String accessKeyId = map.get("AccessKeyId"); + String accessKeySecret = map.get("AccessKeySecret"); + String securityToken = map.get("SecurityToken"); + return new BasicSessionCredentials(accessKeyId, accessKeySecret, securityToken, expiration - System.currentTimeMillis()); + } + + public static final class Builder { + + private String credentialsURI; + private Integer connectionTimeout; + private Integer readTimeout; + + public Builder credentialsURI(URL credentialsURI) { + this.credentialsURI = credentialsURI.toString(); + return this; + } + + public Builder credentialsURI(String credentialsURI) { + this.credentialsURI = credentialsURI; + return this; + } + + public Builder connectionTimeout(Integer connectionTimeout) { + this.connectionTimeout = connectionTimeout; + return this; + } + + public Builder readTimeout(Integer readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + public URLCredentialsProvider build() { + return new URLCredentialsProvider(this); + } + } +} \ No newline at end of file diff --git a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/sts/AssumeRoleRequest.java b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/sts/AssumeRoleRequest.java index 6ffeff738c..38b1671b49 100644 --- a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/sts/AssumeRoleRequest.java +++ b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/sts/AssumeRoleRequest.java @@ -26,6 +26,7 @@ public class AssumeRoleRequest extends RpcAcsRequest { private Long durationSeconds; private String policy; + private String externalId; private String roleArn; private String roleSessionName; @@ -52,6 +53,15 @@ public void setPolicy(String policy) { putQueryParameter("Policy", policy); } + public String getExternalId() { + return this.externalId; + } + + public void setExternalId(String externalId) { + this.externalId = externalId; + putQueryParameter("ExternalId", externalId); + } + public String getRoleArn() { return this.roleArn; } diff --git a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/utils/AuthUtils.java b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/utils/AuthUtils.java index c12477f9fb..4ea3fc3ca7 100644 --- a/aliyun-java-sdk-core/src/main/java/com/aliyuncs/utils/AuthUtils.java +++ b/aliyun-java-sdk-core/src/main/java/com/aliyuncs/utils/AuthUtils.java @@ -3,13 +3,25 @@ import java.io.FileInputStream; import java.io.IOException; - public class AuthUtils { private static volatile String clientType = System.getenv("ALIBABA_CLOUD_PROFILE"); private static volatile String environmentAccessKeyId; private static volatile String environmentAccesskeySecret; + private static volatile String environmentSecurityToken; private static volatile String environmentECSMetaData; + private static volatile Boolean disableECSIMDSv1; private static volatile String environmentCredentialsFile; + private static volatile String environmentRoleArn; + private static volatile String environmentRoleSessionName; + private static volatile String environmentOIDCProviderArn; + private static volatile String environmentOIDCTokenFilePath; + private static volatile String privateKey; + private static volatile String OIDCToken; + private static volatile Boolean disableCLIProfile; + private static volatile Boolean disableECSMetaData; + private static volatile String environmentCredentialsURI; + private static volatile Boolean enableVpcEndpoint; + private static volatile String environmentSTSRegion; public static String readFile(String filePath) { @@ -78,6 +90,16 @@ public static void setEnvironmentAccessKeySecret(String environmentAccesskeySecr AuthUtils.environmentAccesskeySecret = environmentAccesskeySecret; } + public static String getEnvironmentSecurityToken() { + return null == AuthUtils.environmentSecurityToken ? + System.getenv("ALIBABA_CLOUD_SECURITY_TOKEN") + : AuthUtils.environmentSecurityToken; + } + + public static void setEnvironmentSecurityToken(String environmentSecurityToken) { + AuthUtils.environmentSecurityToken = environmentSecurityToken; + } + public static String getEnvironmentECSMetaData() { if (null == AuthUtils.environmentECSMetaData) { return System.getenv("ALIBABA_CLOUD_ECS_METADATA"); @@ -101,4 +123,122 @@ public static String getEnvironmentCredentialsFile() { public static void setEnvironmentCredentialsFile(String environmentCredentialsFile) { AuthUtils.environmentCredentialsFile = environmentCredentialsFile; } + + public static void disableECSIMDSv1(boolean disableECSIMDSv1) { + AuthUtils.disableECSIMDSv1 = disableECSIMDSv1; + } + + public static boolean getDisableECSIMDSv1() { + if (null != AuthUtils.disableECSIMDSv1) { + return AuthUtils.disableECSIMDSv1; + } else if (null != System.getenv("ALIBABA_CLOUD_IMDSV1_DISABLED")) { + return Boolean.parseBoolean(System.getenv("ALIBABA_CLOUD_IMDSV1_DISABLED")); + } + return false; + } + + public static void setEnvironmentRoleArn(String environmentRoleArn) { + AuthUtils.environmentRoleArn = environmentRoleArn; + } + + public static String getEnvironmentRoleArn() { + return null == AuthUtils.environmentRoleArn ? + System.getenv("ALIBABA_CLOUD_ROLE_ARN") + : AuthUtils.environmentRoleArn; + } + + public static void setEnvironmentRoleSessionName(String environmentRoleSessionName) { + AuthUtils.environmentRoleSessionName = environmentRoleSessionName; + } + + public static String getEnvironmentRoleSessionName() { + return null == AuthUtils.environmentRoleSessionName ? + System.getenv("ALIBABA_CLOUD_ROLE_SESSION_NAME") + : AuthUtils.environmentRoleSessionName; + } + + public static void setEnvironmentOIDCProviderArn(String environmentOIDCProviderArn) { + AuthUtils.environmentOIDCProviderArn = environmentOIDCProviderArn; + } + + public static String getEnvironmentOIDCProviderArn() { + return null == AuthUtils.environmentOIDCProviderArn ? + System.getenv("ALIBABA_CLOUD_OIDC_PROVIDER_ARN") + : AuthUtils.environmentOIDCProviderArn; + } + + public static void setEnvironmentOIDCTokenFilePath(String environmentOIDCTokenFilePath) { + AuthUtils.environmentOIDCTokenFilePath = environmentOIDCTokenFilePath; + } + + public static String getEnvironmentOIDCTokenFilePath() { + return null == AuthUtils.environmentOIDCTokenFilePath ? + System.getenv("ALIBABA_CLOUD_OIDC_TOKEN_FILE") + : AuthUtils.environmentOIDCTokenFilePath; + } + + public static boolean environmentEnableOIDC() { + return !StringUtils.isEmpty(getEnvironmentRoleArn()) + && !StringUtils.isEmpty(getEnvironmentOIDCProviderArn()) + && !StringUtils.isEmpty(getEnvironmentOIDCTokenFilePath()); + } + + public static void disableCLIProfile(boolean disableCLIProfile) { + AuthUtils.disableCLIProfile = disableCLIProfile; + } + + public static boolean isDisableCLIProfile() { + if (null != AuthUtils.disableCLIProfile) { + return AuthUtils.disableCLIProfile; + } else if (null != System.getenv("ALIBABA_CLOUD_CLI_PROFILE_DISABLED")) { + return Boolean.parseBoolean(System.getenv("ALIBABA_CLOUD_CLI_PROFILE_DISABLED")); + } + return false; + } + + public static void disableECSMetaData(boolean disableECSMetaData) { + AuthUtils.disableECSMetaData = disableECSMetaData; + } + + public static boolean isDisableECSMetaData() { + if (null != AuthUtils.disableECSMetaData) { + return AuthUtils.disableECSMetaData; + } else if (null != System.getenv("ALIBABA_CLOUD_ECS_METADATA_DISABLED")) { + return Boolean.parseBoolean(System.getenv("ALIBABA_CLOUD_ECS_METADATA_DISABLED")); + } + return false; + } + + public static void setEnvironmentCredentialsURI(String environmentCredentialsURI) { + AuthUtils.environmentCredentialsURI = environmentCredentialsURI; + } + + public static String getEnvironmentCredentialsURI() { + return null == AuthUtils.environmentCredentialsURI ? + System.getenv("ALIBABA_CLOUD_CREDENTIALS_URI") + : AuthUtils.environmentCredentialsURI; + } + + public static void enableVpcEndpoint(boolean enableVpcEndpoint) { + AuthUtils.enableVpcEndpoint = enableVpcEndpoint; + } + + public static boolean isEnableVpcEndpoint() { + if (null != AuthUtils.enableVpcEndpoint) { + return AuthUtils.enableVpcEndpoint; + } else if (null != System.getenv("ALIBABA_CLOUD_VPC_ENDPOINT_ENABLED")) { + return Boolean.parseBoolean(System.getenv("ALIBABA_CLOUD_VPC_ENDPOINT_ENABLED")); + } + return false; + } + + public static void setEnvironmentSTSRegion(String environmentSTSRegion) { + AuthUtils.environmentSTSRegion = environmentSTSRegion; + } + + public static String getEnvironmentSTSRegion() { + return null == AuthUtils.environmentSTSRegion ? + System.getenv("ALIBABA_CLOUD_STS_REGION") + : AuthUtils.environmentSTSRegion; + } } diff --git a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/DefaultAcsClientTest.java b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/DefaultAcsClientTest.java index d091f62fce..6b12516575 100644 --- a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/DefaultAcsClientTest.java +++ b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/DefaultAcsClientTest.java @@ -494,9 +494,14 @@ public void testDoActionEndpointTestabilityException1() throws ClientException, @Test public void testDoActionEndpointTestabilityException2() throws ClientException, IllegalArgumentException, SecurityException { - System.setProperty("alibabacloud.accessKeyId", "test"); - System.setProperty("alibabacloud.accessKeyIdSecret", "test"); - DefaultAcsClient client = new DefaultAcsClient("test"); + Credential credential = mock(Credential.class); + when(credential.getSecurityToken()).thenReturn(null); + when(credential.getAccessKeyId()).thenReturn("test"); + when(credential.getAccessSecret()).thenReturn("test"); + DefaultProfile profile = mock(DefaultProfile.class); + when(profile.getCredential()).thenReturn(credential); + when(profile.getRegionId()).thenReturn("test"); + DefaultAcsClient client = new DefaultAcsClient(profile); DefaultEndpointResolver endpointResolver = mock(DefaultEndpointResolver.class); client.setEndpointResolver(endpointResolver); String endPoint = "endpoint-test.exception.com"; diff --git a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/CLIProfileCredentialsProviderTest.java b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/CLIProfileCredentialsProviderTest.java new file mode 100644 index 0000000000..df08fa0bc0 --- /dev/null +++ b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/CLIProfileCredentialsProviderTest.java @@ -0,0 +1,169 @@ +package com.aliyuncs.auth; + +import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.utils.AuthUtils; +import com.google.gson.Gson; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; + +public class CLIProfileCredentialsProviderTest { + + @Test + public void getProfileNameTest() { + CLIProfileCredentialsProvider provider = CLIProfileCredentialsProvider.builder().build(); + Assert.assertNull(provider.getProfileName()); + provider = CLIProfileCredentialsProvider.builder() + .profileName("AK") + .build(); + Assert.assertEquals("AK", provider.getProfileName()); + } + + @Test + public void shouldReloadCredentialsProviderTest() { + CLIProfileCredentialsProvider provider = CLIProfileCredentialsProvider.builder().build(); + Assert.assertTrue(provider.shouldReloadCredentialsProvider("")); + } + + @Test + public void disableCLIProfileTest() { + boolean isDisableCLIProfile = AuthUtils.isDisableCLIProfile(); + AuthUtils.disableCLIProfile(true); + CLIProfileCredentialsProvider provider = CLIProfileCredentialsProvider.builder().build(); + try { + provider.getCredentials(); + Assert.fail(); + } catch (ClientException e) { + Assert.assertEquals("CLI credentials file is disabled.", e.getMessage()); + } + AuthUtils.disableCLIProfile(isDisableCLIProfile); + } + + @Test + public void parseProfileTest() throws ClientException, IOException { + CLIProfileCredentialsProvider provider = CLIProfileCredentialsProvider.builder().build(); + try { + provider.parseProfile("./not_exist_config.json"); + Assert.fail(); + } catch (ClientException e) { + Assert.assertTrue(e.getMessage().contains("Unable to open credentials file")); + } + try { + String configPath = CLIProfileCredentialsProviderTest.class.getClassLoader(). + getResource("invalid_cli_config.json").getPath(); + provider.parseProfile(configPath); + Assert.fail(); + } catch (ClientException e) { + Assert.assertTrue(e.getMessage().contains("Failed to parse credential form CLI credentials file")); + } + + String configPath = CLIProfileCredentialsProviderTest.class.getClassLoader(). + getResource("empty_file.json").getPath(); + CLIProfileCredentialsProvider.Config config = provider.parseProfile(configPath); + Assert.assertNull(config); + + configPath = CLIProfileCredentialsProviderTest.class.getClassLoader(). + getResource("mock_empty_cli_config.json").getPath(); + config = provider.parseProfile(configPath); + Assert.assertNull(config.getCurrent()); + Assert.assertNull(config.getProfiles()); + + configPath = CLIProfileCredentialsProviderTest.class.getClassLoader(). + getResource("full_cli_config.json").getPath(); + config = provider.parseProfile(configPath); + Assert.assertEquals("AK", config.getCurrent()); + Assert.assertEquals(5, config.getProfiles().size()); + Assert.assertEquals("[{\"name\":\"AK\",\"mode\":\"AK\",\"access_key_id\":\"access_key_id\",\"access_key_secret\":\"access_key_secret\"},{\"name\":\"RamRoleArn\",\"mode\":\"RamRoleArn\",\"access_key_id\":\"access_key_id\",\"access_key_secret\":\"access_key_secret\",\"ram_role_arn\":\"ram_role_arn\",\"ram_session_name\":\"ram_session_name\",\"expired_seconds\":3600,\"sts_region\":\"cn-hangzhou\"},{\"name\":\"EcsRamRole\",\"mode\":\"EcsRamRole\",\"ram_role_name\":\"ram_role_name\"},{\"name\":\"OIDC\",\"mode\":\"OIDC\",\"ram_role_arn\":\"ram_role_arn\",\"ram_session_name\":\"ram_session_name\",\"expired_seconds\":3600,\"sts_region\":\"cn-hangzhou\",\"oidc_token_file\":\"path/to/oidc/file\",\"oidc_provider_arn\":\"oidc_provider_arn\"},{\"name\":\"ChainableRamRoleArn\",\"mode\":\"ChainableRamRoleArn\",\"ram_role_arn\":\"ram_role_arn\",\"ram_session_name\":\"ram_session_name\",\"expired_seconds\":3600,\"sts_region\":\"cn-hangzhou\",\"source_profile\":\"AK\"}]", new Gson().toJson(config.getProfiles())); + } + + @Test + public void reloadCredentialsProviderTest() throws ClientException, IOException { + CLIProfileCredentialsProvider provider = CLIProfileCredentialsProvider.builder().build(); + String configPath = CLIProfileCredentialsProviderTest.class.getClassLoader(). + getResource(".aliyun/config.json").getPath(); + CLIProfileCredentialsProvider.Config config = provider.parseProfile(configPath); + try { + provider.reloadCredentialsProvider(config, "inexist"); + Assert.fail(); + } catch (ClientException e) { + Assert.assertEquals("Unable to get profile with 'inexist' form CLI credentials file.", e.getMessage()); + } + + AlibabaCloudCredentialsProvider credentialsProvider = provider.reloadCredentialsProvider(config, "AK"); + Assert.assertTrue(credentialsProvider instanceof StaticCredentialsProvider); + BasicCredentials credential = (BasicCredentials) credentialsProvider.getCredentials(); + Assert.assertEquals("akid", credential.getAccessKeyId()); + Assert.assertEquals("secret", credential.getAccessKeySecret()); + + credentialsProvider = provider.reloadCredentialsProvider(config, "RamRoleArn"); + Assert.assertTrue(credentialsProvider instanceof STSAssumeRoleSessionCredentialsProvider); + try { + credentialsProvider.getCredentials(); + Assert.fail(); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("InvalidAccessKeyId.NotFound")); + } + + try { + provider.reloadCredentialsProvider(config, "Invalid_RamRoleArn"); + Assert.fail(); + } catch (IllegalArgumentException e) { + Assert.assertEquals("Access key ID cannot be null.", e.getMessage()); + } + + credentialsProvider = provider.reloadCredentialsProvider(config, "EcsRamRole"); + Assert.assertTrue(credentialsProvider instanceof InstanceProfileCredentialsProvider); + + credentialsProvider = provider.reloadCredentialsProvider(config, "OIDC"); + Assert.assertTrue(credentialsProvider instanceof OIDCCredentialsProvider); + + credentialsProvider = provider.reloadCredentialsProvider(config, "ChainableRamRoleArn"); + Assert.assertTrue(credentialsProvider instanceof STSAssumeRoleSessionCredentialsProvider); + + try { + provider.reloadCredentialsProvider(config, "ChainableRamRoleArn2"); + Assert.fail(); + } catch (ClientException e) { + Assert.assertEquals("Unable to get profile with 'InvalidSource' form CLI credentials file.", e.getMessage()); + } + + try { + provider.reloadCredentialsProvider(config, "Unsupported"); + Assert.fail(); + } catch (ClientException e) { + Assert.assertEquals("Unsupported profile mode 'Unsupported' form CLI credentials file.", e.getMessage()); + } + } + + @Test + public void getCredentialsTest() throws ClientException { + String homePath = System.getProperty("user.home"); + String configPath = CLIProfileCredentialsProviderTest.class.getClassLoader(). + getResource(".aliyun/config.json").getPath(); + System.setProperty("user.home", configPath.replace("/.aliyun/config.json", "")); + CLIProfileCredentialsProvider provider = CLIProfileCredentialsProvider.builder().build(); + BasicCredentials credential = (BasicCredentials) provider.getCredentials(); + Assert.assertEquals("akid", credential.getAccessKeyId()); + Assert.assertEquals("secret", credential.getAccessKeySecret()); + + provider = CLIProfileCredentialsProvider.builder().profileName("inexist").build(); + try { + provider.getCredentials(); + Assert.fail(); + } catch (ClientException e) { + Assert.assertEquals("Unable to get profile with 'inexist' form CLI credentials file.", e.getMessage()); + } + + provider = CLIProfileCredentialsProvider.builder().profileName("RamRoleArn").build(); + try { + provider.getCredentials(); + Assert.fail(); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("InvalidAccessKeyId.NotFound")); + } + + System.setProperty("user.home", homePath); + } + +} diff --git a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/DefaultCredentialsProviderTest.java b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/DefaultCredentialsProviderTest.java index 05648d56b2..0d1e056b3e 100644 --- a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/DefaultCredentialsProviderTest.java +++ b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/DefaultCredentialsProviderTest.java @@ -5,7 +5,16 @@ import org.junit.Assert; import org.junit.Test; +import java.lang.reflect.Field; + public class DefaultCredentialsProviderTest { + static class CredentialsProviderForTest implements AlibabaCloudCredentialsProvider { + @Override + public AlibabaCloudCredentials getCredentials() { + return new BasicCredentials("", ""); + } + } + @Test public void userConfigurationProvidersTest() { SystemPropertiesCredentialsProvider provider = new SystemPropertiesCredentialsProvider(); @@ -21,16 +30,13 @@ public void userConfigurationProvidersTest() { } @Test - public void getCredentialsTest() throws ClientException { - DefaultCredentialsProvider provider = new DefaultCredentialsProvider(); + public void getCredentialsTest() throws ClientException, NoSuchFieldException, IllegalAccessException { + DefaultCredentialsProvider provider = DefaultCredentialsProvider.builder() + .reuseLastProviderEnabled(false) + .build(); + new DefaultCredentialsProvider(); AuthUtils.setEnvironmentECSMetaData(""); - try { - new DefaultCredentialsProvider(); - Assert.fail(); - } catch (ClientException e) { - Assert.assertEquals("Environment variable roleName('ALIBABA_CLOUD_ECS_METADATA') cannot be empty", - e.getMessage()); - } + new DefaultCredentialsProvider(); AuthUtils.setEnvironmentAccessKeyId("test"); AuthUtils.setEnvironmentAccessKeySecret("test"); @@ -58,11 +64,44 @@ public AlibabaCloudCredentials getCredentials() { AuthUtils.setEnvironmentAccessKeySecret(null); System.setProperty(AuthConstant.SYSTEM_ACCESSKEYID, ""); AuthUtils.setEnvironmentCredentialsFile(null); + // Clear the contents of the global credentials.ini + Field field = ProfileCredentialsProvider.class.getDeclaredField("ini"); + field.setAccessible(true); + field.set(ProfileCredentialsProvider.class, null); try { provider.getCredentials(); + Assert.fail(); } catch (ClientException e) { - Assert.assertEquals("not found credentials", e.getMessage()); + Assert.assertTrue(e.getMessage().contains("Unable to load credentials from any of the providers in the chain")); } + + AuthUtils.setEnvironmentRoleArn("test"); + AuthUtils.setEnvironmentOIDCProviderArn("test"); + AuthUtils.setEnvironmentOIDCTokenFilePath("test"); + Assert.assertTrue(AuthUtils.environmentEnableOIDC()); + provider = new DefaultCredentialsProvider(); + try { + provider.getCredentials(); + Assert.fail(); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("Read OIDC token failed")); + } + AuthUtils.setEnvironmentRoleArn(null); + AuthUtils.setEnvironmentOIDCProviderArn(null); + AuthUtils.setEnvironmentOIDCTokenFilePath(null); + Assert.assertFalse(AuthUtils.environmentEnableOIDC()); + + AuthUtils.setEnvironmentCredentialsURI("http://test"); + provider = new DefaultCredentialsProvider(); + try { + provider.getCredentials(); + Assert.fail(); + } catch (ClientException e) { + Assert.assertTrue(e.getMessage().contains("Failed to connect Server")); + } + + AuthUtils.setEnvironmentCredentialsURI(null); + DefaultCredentialsProvider.clearCredentialsProvider(); } @Test @@ -86,4 +125,50 @@ public void setClientTypeTest() { Assert.assertEquals("test", AuthUtils.getClientType()); AuthUtils.setClientType("default"); } + + @Test + public void reuseLastProviderEnabledTest() throws NoSuchFieldException, IllegalAccessException, ClientException { + AuthUtils.setEnvironmentAccessKeyId("test"); + AuthUtils.setEnvironmentAccessKeySecret("test"); + DefaultCredentialsProvider provider = new DefaultCredentialsProvider(); + BasicCredentials credential = (BasicCredentials) provider.getCredentials(); + Assert.assertEquals("test", credential.getAccessKeyId()); + Assert.assertEquals("test", credential.getAccessKeySecret()); + + Field providerField = DefaultCredentialsProvider.class.getDeclaredField("lastUsedCredentialsProvider"); + providerField.setAccessible(true); + Field reuseEnableField = DefaultCredentialsProvider.class.getDeclaredField("reuseLastProviderEnabled"); + reuseEnableField.setAccessible(true); + + Assert.assertTrue(providerField.get(provider) instanceof EnvironmentVariableCredentialsProvider); + Assert.assertTrue((Boolean) reuseEnableField.get(provider)); + + DefaultCredentialsProvider.addCredentialsProvider(new CredentialsProviderForTest()); + credential = (BasicCredentials) provider.getCredentials(); + Assert.assertEquals("test", credential.getAccessKeyId()); + Assert.assertEquals("test", credential.getAccessKeySecret()); + Assert.assertTrue(providerField.get(provider) instanceof EnvironmentVariableCredentialsProvider); + Assert.assertTrue((Boolean) reuseEnableField.get(provider)); + + DefaultCredentialsProvider.clearCredentialsProvider(); + provider = DefaultCredentialsProvider.builder() + .reuseLastProviderEnabled(false) + .build(); + credential = (BasicCredentials) provider.getCredentials(); + Assert.assertEquals("test", credential.getAccessKeyId()); + Assert.assertEquals("test", credential.getAccessKeySecret()); + Assert.assertTrue(providerField.get(provider) instanceof EnvironmentVariableCredentialsProvider); + Assert.assertFalse((Boolean) reuseEnableField.get(provider)); + + DefaultCredentialsProvider.addCredentialsProvider(new CredentialsProviderForTest()); + credential = (BasicCredentials) provider.getCredentials(); + Assert.assertEquals("", credential.getAccessKeyId()); + Assert.assertEquals("", credential.getAccessKeySecret()); + Assert.assertTrue(providerField.get(provider) instanceof CredentialsProviderForTest); + Assert.assertFalse((Boolean) reuseEnableField.get(provider)); + + AuthUtils.setEnvironmentAccessKeyId(null); + AuthUtils.setEnvironmentAccessKeySecret(null); + DefaultCredentialsProvider.clearCredentialsProvider(); + } } diff --git a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/ECSMetadataServiceCredentialsFetcherTest.java b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/ECSMetadataServiceCredentialsFetcherTest.java index f32e23376e..593f6d670c 100644 --- a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/ECSMetadataServiceCredentialsFetcherTest.java +++ b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/ECSMetadataServiceCredentialsFetcherTest.java @@ -1,9 +1,5 @@ package com.aliyuncs.auth; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; @@ -24,6 +20,8 @@ import com.aliyuncs.http.HttpResponse; import com.aliyuncs.http.clients.CompatibleUrlConnClient; +import static org.mockito.Mockito.*; + @RunWith(PowerMockRunner.class) @PrepareForTest(CompatibleUrlConnClient.class) public class ECSMetadataServiceCredentialsFetcherTest { @@ -45,7 +43,7 @@ public void constructorTest() { @Test public void setNullRoleName() { - thrown.expect(NullPointerException.class); + thrown.expect(IllegalArgumentException.class); ECSMetadataServiceCredentialsFetcher fetcher = new ECSMetadataServiceCredentialsFetcher(); Assert.assertNotNull(fetcher); fetcher.setRoleName(null); @@ -253,4 +251,44 @@ public void fetch3TimesThrowClientException2() throws IOException, ClientExcepti fetcher.setRoleName("role"); fetcher.fetch(-1); } + + @Test + public void fetchWithMetadaToken() throws ClientException, IOException { + PowerMockito.mockStatic(CompatibleUrlConnClient.class); + BDDMockito.given(CompatibleUrlConnClient.compatibleGetResponse(any(HttpRequest.class))).willThrow(new RuntimeException("test")); + ECSMetadataServiceCredentialsFetcher fetcher = new ECSMetadataServiceCredentialsFetcher(); + try { + fetcher.fetch(); + Assert.fail(); + } catch (ClientException e) { + Assert.assertEquals("Failed to connect ECS Metadata Service: java.lang.RuntimeException: test", + e.getMessage()); + } + ECSMetadataServiceCredentialsFetcher v2Fetcher = new ECSMetadataServiceCredentialsFetcher("", true, 900, 1200); + try { + v2Fetcher.fetch(); + Assert.fail(); + } catch (ClientException e) { + Assert.assertEquals("Failed to get token from ECS Metadata Service, and fallback to IMDS v1 is disabled via the disableIMDSv1 configuration is turned on. Original error: Failed to connect ECS Metadata Service: java.lang.RuntimeException: test", + e.getMessage()); + } + HttpResponse response = mock(HttpResponse.class); + when(response.getStatus()).thenReturn(HttpURLConnection.HTTP_INTERNAL_ERROR); + BDDMockito.given(CompatibleUrlConnClient.compatibleGetResponse(any(HttpRequest.class))).willReturn(response); + try { + fetcher.fetch(); + Assert.fail(); + } catch (ClientException e) { + Assert.assertEquals("Failed to get RAM session credentials from ECS metadata service. HttpCode=500", + e.getMessage()); + } + try { + v2Fetcher.fetch(); + Assert.fail(); + } catch (ClientException e) { + Assert.assertEquals("Failed to get token from ECS Metadata Service, and fallback to IMDS v1 is disabled via the disableIMDSv1 configuration is turned on. Original error: Failed to get token from ECS Metadata Service. HttpCode=500, ResponseMessage=null", + e.getMessage()); + } + + } } diff --git a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/EnvironmentVariableCredentialsProviderTest.java b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/EnvironmentVariableCredentialsProviderTest.java index 5475559dd4..1cac147889 100644 --- a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/EnvironmentVariableCredentialsProviderTest.java +++ b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/EnvironmentVariableCredentialsProviderTest.java @@ -15,8 +15,20 @@ public void getCredentialsTest() throws ClientException { Assert.assertNull(provider.getCredentials()); AuthUtils.setClientType("default"); + try { + provider.getCredentials(); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("Environment variable accessKeyId cannot be empty.", e.getMessage()); + } + AuthUtils.setEnvironmentAccessKeyId("accessKeyIdTest"); - Assert.assertNull(provider.getCredentials()); + try { + provider.getCredentials(); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("Environment variable accessKeySecret cannot be empty.", e.getMessage()); + } AuthUtils.setEnvironmentAccessKeySecret("accessKeyIdTest"); AlibabaCloudCredentials credential = provider.getCredentials(); @@ -26,14 +38,19 @@ public void getCredentialsTest() throws ClientException { Assert.assertEquals("accessKeyIdTest", accessKeySecret); AuthUtils.setEnvironmentAccessKeyId(null); - Assert.assertNull(provider.getCredentials()); + try { + provider.getCredentials(); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("Environment variable accessKeyId cannot be empty.", e.getMessage()); + } AuthUtils.setEnvironmentAccessKeyId(""); try { provider.getCredentials(); Assert.fail(); } catch (ClientException e){ - Assert.assertEquals("Environment variable accessKeyId cannot be empty", e.getMessage()); + Assert.assertEquals("Environment variable accessKeyId cannot be empty.", e.getMessage()); } AuthUtils.setEnvironmentAccessKeyId("a"); AuthUtils.setEnvironmentAccessKeySecret(""); @@ -41,10 +58,17 @@ public void getCredentialsTest() throws ClientException { provider.getCredentials(); Assert.fail(); } catch (ClientException e){ - Assert.assertEquals("Environment variable accessKeySecret cannot be empty", e.getMessage()); + Assert.assertEquals("Environment variable accessKeySecret cannot be empty.", e.getMessage()); } + AuthUtils.setEnvironmentAccessKeySecret("secret"); + AuthUtils.setEnvironmentSecurityToken("token"); + BasicSessionCredentials basicSessionCredentials = (BasicSessionCredentials)provider.getCredentials(); + Assert.assertEquals("a", basicSessionCredentials.getAccessKeyId()); + Assert.assertEquals("secret", basicSessionCredentials.getAccessKeySecret()); + Assert.assertEquals("token", basicSessionCredentials.getSessionToken()); AuthUtils.setEnvironmentAccessKeyId(null); AuthUtils.setEnvironmentAccessKeySecret(null); + AuthUtils.setEnvironmentSecurityToken(null); } } diff --git a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/InstanceProfileCredentialsProviderTest.java b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/InstanceProfileCredentialsProviderTest.java index 3ad02e6aa6..2b92baef6e 100644 --- a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/InstanceProfileCredentialsProviderTest.java +++ b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/InstanceProfileCredentialsProviderTest.java @@ -1,6 +1,7 @@ package com.aliyuncs.auth; import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.utils.AuthUtils; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; @@ -29,6 +30,24 @@ public void constructorNormalNullPointerExceptionTest() { Assert.assertNull(provider); } + @Test + public void builderTest() { + AuthUtils.disableECSMetaData(true); + try { + InstanceProfileCredentialsProvider.builder() + .roleName("test") + .readTimeout(2000) + .connectionTimeout(2000) + .disableIMDSv1(false) + .build(); + Assert.fail(); + } catch (IllegalArgumentException e) { + Assert.assertEquals("IMDS credentials is disabled.", + e.getMessage()); + } + AuthUtils.disableECSMetaData(false); + } + @Test public void withFetcherTest() { final String roleName = "roleName"; diff --git a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/OIDCCredentialsProviderTest.java b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/OIDCCredentialsProviderTest.java index 84e0003eb2..ce1a0df1d3 100644 --- a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/OIDCCredentialsProviderTest.java +++ b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/OIDCCredentialsProviderTest.java @@ -3,10 +3,13 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import com.aliyuncs.utils.AuthUtils; import org.junit.Assert; import org.junit.Test; import org.junit.function.ThrowingRunnable; +import java.lang.reflect.Field; + import com.aliyuncs.exceptions.ClientException; public class OIDCCredentialsProviderTest { @@ -37,7 +40,124 @@ public void constructorOIDCCredentialsProvider() throws ClientException { } @Test - public void emtptyRoleArnTest() throws ClientException { + public void builderTest() throws IllegalAccessException, NoSuchFieldException { + OIDCCredentialsProvider provider; + try { + OIDCCredentialsProvider.builder().build(); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("RoleArn or environment variable ALIBABA_CLOUD_ROLE_ARN cannot be empty.", e.getMessage()); + } + + try { + OIDCCredentialsProvider.builder() + .roleArn("test") + .build(); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("OIDCProviderArn or environment variable ALIBABA_CLOUD_OIDC_PROVIDER_ARN cannot be empty.", e.getMessage()); + } + + try { + OIDCCredentialsProvider.builder() + .roleArn("test") + .oidcProviderArn("test") + .build(); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("OIDCTokenFilePath or environment variable ALIBABA_CLOUD_OIDC_TOKEN_FILE cannot be empty.", e.getMessage()); + } + + try { + OIDCCredentialsProvider.builder() + .durationSeconds(100) + .build(); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("Session duration should be in the range of 900s - max session duration.", e.getMessage()); + } + + provider = OIDCCredentialsProvider.builder() + .roleArn("test") + .oidcProviderArn("test") + .oidcTokenFilePath("OIDCToken.txt") + .build(); + Class clazz = provider.getClass(); + Field field = clazz.getDeclaredField("stsEndpoint"); + field.setAccessible(true); + Assert.assertEquals("https://sts.aliyuncs.com", field.get(provider)); + + AuthUtils.setEnvironmentSTSRegion("cn-beijing"); + provider = OIDCCredentialsProvider.builder() + .roleArn("test") + .oidcProviderArn("test") + .oidcTokenFilePath("OIDCToken.txt") + .build(); + Assert.assertEquals("https://sts.cn-beijing.aliyuncs.com", field.get(provider)); + + provider = OIDCCredentialsProvider.builder() + .roleArn("test") + .oidcProviderArn("test") + .oidcTokenFilePath("OIDCToken.txt") + .stsRegionId("cn-hangzhou") + .build(); + Assert.assertEquals("https://sts.cn-hangzhou.aliyuncs.com", field.get(provider)); + + AuthUtils.enableVpcEndpoint(true); + provider = OIDCCredentialsProvider.builder() + .roleArn("test") + .oidcProviderArn("test") + .oidcTokenFilePath("OIDCToken.txt") + .stsRegionId("cn-hangzhou") + .build(); + Assert.assertEquals("https://sts-vpc.cn-hangzhou.aliyuncs.com", field.get(provider)); + + provider = OIDCCredentialsProvider.builder() + .roleArn("test") + .oidcProviderArn("test") + .oidcTokenFilePath("OIDCToken.txt") + .stsRegionId("cn-hangzhou") + .enableVpc(true) + .build(); + Assert.assertEquals("https://sts-vpc.cn-hangzhou.aliyuncs.com", field.get(provider)); + + AuthUtils.setEnvironmentSTSRegion(null); + AuthUtils.enableVpcEndpoint(false); + + String filePath = OIDCCredentialsProviderTest.class.getClassLoader().getResource("oidctoken").getPath(); + provider = OIDCCredentialsProvider.builder() + .roleArn("test") + .oidcProviderArn("test") + .oidcTokenFilePath(filePath) + .durationSeconds(1000) + .roleSessionName("test") + .policy("test") + .connectionTimeout(2000) + .readTimeout(2000) + .build(); + Field connectTimeoutField = clazz.getDeclaredField("connectTimeout"); + connectTimeoutField.setAccessible(true); + Field readTimeoutField = clazz.getDeclaredField("readTimeout"); + readTimeoutField.setAccessible(true); + Field durationSecondsField = clazz.getDeclaredField("durationSeconds"); + durationSecondsField.setAccessible(true); + Assert.assertEquals(2000, connectTimeoutField.get(provider)); + Assert.assertEquals(2000, readTimeoutField.get(provider)); + Assert.assertEquals(1000, Integer.parseInt(String.valueOf(durationSecondsField.get(provider)))); + Assert.assertEquals("test", provider.getRoleArn()); + Assert.assertEquals("test", provider.getRoleSessionName()); + Assert.assertEquals("test", provider.getPolicy()); + Assert.assertEquals("https://sts.aliyuncs.com", field.get(provider)); + try { + provider.getCredentials(); + Assert.fail(); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("AuthenticationFail.NoPermission")); + } + } + + @Test + public void emptyRoleArnTest() throws ClientException { ClientException ex = Assert.assertThrows(ClientException.class, new ThrowingRunnable() { @Override public void run() throws Throwable { @@ -87,8 +207,8 @@ public void run() throws IllegalAccessException, InvocationTargetException { parseCredentials.invoke(null, "{}", 3600L); } }); - - ClientException cause = (ClientException)ex.getCause(); + + ClientException cause = (ClientException) ex.getCause(); Assert.assertEquals("AssumeRoleWithOIDC failed: {}", cause.getMessage()); } @@ -101,8 +221,8 @@ public void run() throws IllegalAccessException, InvocationTargetException { parseCredentials.invoke(null, "", 3600L); } }); - - ClientException cause = (ClientException)ex.getCause(); + + ClientException cause = (ClientException) ex.getCause(); Assert.assertEquals("Invalid JSON", cause.getMessage()); } @@ -110,7 +230,7 @@ public void run() throws IllegalAccessException, InvocationTargetException { public void parseCredentialsWithCredentialsTest() throws NoSuchMethodException, SecurityException, IllegalAccessException, InvocationTargetException { final Method parseCredentials = OIDCCredentialsProvider.class.getDeclaredMethod("parseCredentials", String.class, long.class); parseCredentials.setAccessible(true); - BasicSessionCredentials c = (BasicSessionCredentials)parseCredentials.invoke(null, "{\"Credentials\": {\"AccessKeyId\": \"sts_ak_id\",\"AccessKeySecret\": \"sts_ak_secret\", \"SecurityToken\": \"securitytoken\",\"Expiration\": \"2021-10-20T04:27:09Z\"}}", 3600L); + BasicSessionCredentials c = (BasicSessionCredentials) parseCredentials.invoke(null, "{\"Credentials\": {\"AccessKeyId\": \"sts_ak_id\",\"AccessKeySecret\": \"sts_ak_secret\", \"SecurityToken\": \"securitytoken\",\"Expiration\": \"2021-10-20T04:27:09Z\"}}", 3600L); Assert.assertEquals("sts_ak_id", c.getAccessKeyId()); Assert.assertEquals("sts_ak_secret", c.getAccessKeySecret()); Assert.assertEquals("securitytoken", c.getSessionToken()); diff --git a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/ProfileCredentialsProviderTest.java b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/ProfileCredentialsProviderTest.java index 81d747b65a..9a4a67d506 100644 --- a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/ProfileCredentialsProviderTest.java +++ b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/ProfileCredentialsProviderTest.java @@ -70,7 +70,19 @@ public void createCredentialTest() throws NoSuchMethodException, InvocationTarge client.clear(); client.put(AuthConstant.INI_ACCESS_KEY_ID, AuthConstant.INI_TYPE_RAM); client.put(AuthConstant.INI_TYPE, "access_key"); - Assert.assertNull(createCredential.invoke(provider, client, factory)); + try { + createCredential.invoke(provider, client, factory); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("The configured access_key_id or access_key_secret is empty.", + e.getCause().getLocalizedMessage()); + } + + client.clear(); + client.put(AuthConstant.INI_ACCESS_KEY_ID, AuthConstant.INI_TYPE_RAM); + client.put(AuthConstant.INI_ACCESS_KEY_IDSECRET, AuthConstant.INI_TYPE_RAM); + client.put(AuthConstant.INI_TYPE, "access_key"); + Assert.assertNotNull(createCredential.invoke(provider, client, factory)); } @Test @@ -116,6 +128,50 @@ public void getSTSAssumeRoleSessionCredentialsTest() throws NoSuchMethodExceptio } } + @Test + public void getSTSOIDCRoleSessionCredentialsTest() throws NoSuchMethodException { + ProfileCredentialsProvider provider = new ProfileCredentialsProvider(); + Class providerClass = ProfileCredentialsProvider.class; + Method createCredential = providerClass.getDeclaredMethod( + "createCredential", Map.class, CredentialsProviderFactory.class); + createCredential.setAccessible(true); + CredentialsProviderFactory factory = new CredentialsProviderFactory(); + Map client = new HashMap(); + client.put(AuthConstant.INI_TYPE, AuthConstant.INI_TYPE_OIDC); + try { + createCredential.invoke(provider, client, factory); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("The configured role_arn is empty.", + e.getCause().getLocalizedMessage()); + } + + try { + client.put(AuthConstant.INI_ACCESS_KEY_ID, AuthConstant.INI_TYPE_ARN); + createCredential.invoke(provider, client, factory); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("The configured role_arn is empty.", + e.getCause().getLocalizedMessage()); + } + try { + client.put(AuthConstant.INI_ACCESS_KEY_IDSECRET, AuthConstant.INI_TYPE_ARN); + createCredential.invoke(provider, client, factory); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("The configured role_arn is empty.", + e.getCause().getLocalizedMessage()); + } + try { + client.put(AuthConstant.INI_ROLE_ARN, AuthConstant.INI_TYPE_ARN); + createCredential.invoke(provider, client, factory); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("The configured oidc_provider_arn is empty.", + e.getCause().getLocalizedMessage()); + } + } + @Test public void getSTSGetSessionAccessKeyCredentialsTest() throws NoSuchMethodException { ProfileCredentialsProvider provider = new ProfileCredentialsProvider(); @@ -167,6 +223,24 @@ public void createCredentialsProviderTest() throws thenReturn(stsAssumeRoleSessionCredentialsProvider); Assert.assertNull(createCredential.invoke(profileCredentialsProvider, client, factory)); + client.clear(); + client.put(AuthConstant.INI_TYPE, AuthConstant.INI_TYPE_OIDC); + client.put(AuthConstant.INI_ACCESS_KEY_ID, AuthConstant.INI_ACCESS_KEY_ID); + client.put(AuthConstant.INI_ACCESS_KEY_IDSECRET, AuthConstant.INI_ACCESS_KEY_IDSECRET); + client.put(AuthConstant.INI_ROLE_SESSION_NAME, AuthConstant.INI_ROLE_SESSION_NAME); + client.put(AuthConstant.INI_ROLE_ARN, AuthConstant.INI_TYPE_ARN); + client.put(AuthConstant.INI_OIDC_PROVIDER_ARN, AuthConstant.INI_OIDC_PROVIDER_ARN); + client.put(AuthConstant.INI_OIDC_TOKEN_FILE_PATH, ProfileCredentialsProviderTest.class.getClassLoader(). + getResource("oidctoken").getPath()); + client.put(AuthConstant.DEFAULT_REGION, AuthConstant.DEFAULT_REGION); + + OIDCCredentialsProvider oidcRoleArnCredentialProvider = + Mockito.mock(OIDCCredentialsProvider.class); + Mockito.when(oidcRoleArnCredentialProvider.getCredentials()).thenReturn(null); + Mockito.when(factory.createCredentialsProvider(Mockito.any(OIDCCredentialsProvider.class))). + thenReturn(oidcRoleArnCredentialProvider); + Assert.assertNull(createCredential.invoke(profileCredentialsProvider, client, factory)); + client.clear(); client.put(AuthConstant.INI_TYPE, AuthConstant.INI_TYPE_KEY_PAIR); client.put(AuthConstant.INI_PUBLIC_KEY_ID, AuthConstant.INI_TYPE_KEY_PAIR); diff --git a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/STSAssumeRoleSessionCredentialsProviderTest.java b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/STSAssumeRoleSessionCredentialsProviderTest.java index ddf21af81a..d1c65a48cc 100644 --- a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/STSAssumeRoleSessionCredentialsProviderTest.java +++ b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/STSAssumeRoleSessionCredentialsProviderTest.java @@ -6,6 +6,7 @@ import com.aliyuncs.auth.sts.AssumeRoleResponse; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.profile.IClientProfile; +import com.aliyuncs.utils.AuthUtils; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; @@ -129,7 +130,7 @@ public void withRoleSessionDurationSecondsSmallerThan900Seconds() { @Test public void withRoleSessionDurationSecondsLargerThan3600Seconds() { thrown.expect(IllegalArgumentException.class); - long duration = 3601; + long duration = 899; AlibabaCloudCredentials credentials = mock(AlibabaCloudCredentials.class); String roleArn = "roleArn"; IClientProfile clientProfile = mock(IClientProfile.class); @@ -192,4 +193,116 @@ public void getCredentialsReturnPreviousCredentials() throws ClientException { AlibabaCloudCredentials credentials3 = provider.getCredentials(); Assert.assertEquals(credentials2, credentials3); } + + @Test + public void builderTest() throws IllegalAccessException, NoSuchFieldException { + STSAssumeRoleSessionCredentialsProvider originalProvider; + try { + STSAssumeRoleSessionCredentialsProvider.builder().build(); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("RoleArn or environment variable ALIBABA_CLOUD_ROLE_ARN cannot be empty.", e.getMessage()); + } + + try { + STSAssumeRoleSessionCredentialsProvider.builder() + .durationSeconds(100) + .build(); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("Session duration should be in the range of 900s - max session duration.", e.getMessage()); + } + + originalProvider = STSAssumeRoleSessionCredentialsProvider.builder() + .accessKeyId("test") + .accessKeySecret("test") + .securityToken("test") + .roleArn("test") + .build(); + Class clazz = originalProvider.getClass(); + Field field = clazz.getDeclaredField("stsEndpoint"); + field.setAccessible(true); + Assert.assertEquals("sts.aliyuncs.com", field.get(originalProvider)); + + AuthUtils.setEnvironmentSTSRegion("cn-beijing"); + originalProvider = STSAssumeRoleSessionCredentialsProvider.builder() + .accessKeyId("test") + .accessKeySecret("test") + .securityToken("test") + .roleArn("test") + .build(); + Assert.assertEquals("sts.cn-beijing.aliyuncs.com", field.get(originalProvider)); + + originalProvider = STSAssumeRoleSessionCredentialsProvider.builder() + .accessKeyId("test") + .accessKeySecret("test") + .securityToken("test") + .stsRegionId("cn-hangzhou") + .roleArn("test") + .build(); + Assert.assertEquals("sts.cn-hangzhou.aliyuncs.com", field.get(originalProvider)); + + AuthUtils.enableVpcEndpoint(true); + originalProvider = STSAssumeRoleSessionCredentialsProvider.builder() + .accessKeyId("test") + .accessKeySecret("test") + .securityToken("test") + .stsRegionId("cn-hangzhou") + .roleArn("test") + .build(); + Assert.assertEquals("sts-vpc.cn-hangzhou.aliyuncs.com", field.get(originalProvider)); + + originalProvider = STSAssumeRoleSessionCredentialsProvider.builder() + .accessKeyId("test") + .accessKeySecret("test") + .securityToken("test") + .stsRegionId("cn-hangzhou") + .enableVpc(true) + .roleArn("test") + .build(); + Assert.assertEquals("sts-vpc.cn-hangzhou.aliyuncs.com", field.get(originalProvider)); + + AuthUtils.setEnvironmentSTSRegion(null); + AuthUtils.enableVpcEndpoint(false); + + originalProvider = STSAssumeRoleSessionCredentialsProvider.builder() + .accessKeyId("test") + .accessKeySecret("test") + .durationSeconds(1000) + .roleArn("test") + .roleSessionName("test") + .policy("test") + .externalId("test") + .connectionTimeout(2000) + .readTimeout(2000) + .build(); + Field connectTimeoutField = clazz.getDeclaredField("connectTimeout"); + connectTimeoutField.setAccessible(true); + Field readTimeoutField = clazz.getDeclaredField("readTimeout"); + readTimeoutField.setAccessible(true); + Field durationSecondsField = clazz.getDeclaredField("roleSessionDurationSeconds"); + durationSecondsField.setAccessible(true); + Assert.assertEquals(2000, connectTimeoutField.get(originalProvider)); + Assert.assertEquals(2000, readTimeoutField.get(originalProvider)); + Assert.assertEquals(1000, Integer.parseInt(String.valueOf(durationSecondsField.get(originalProvider)))); + Assert.assertEquals("sts.aliyuncs.com", field.get(originalProvider)); + try { + originalProvider.getCredentials(); + Assert.fail(); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("InvalidAccessKeyId.NotFound")); + } + + STSAssumeRoleSessionCredentialsProvider provider = STSAssumeRoleSessionCredentialsProvider.builder() + .credentialsProvider(originalProvider) + .durationSeconds(1000) + .roleArn("test") + .build(); + try { + provider.getCredentials(); + Assert.fail(); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("InvalidAccessKeyId.NotFound")); + } + } } diff --git a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/SystemPropertiesCredentialsProviderTest.java b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/SystemPropertiesCredentialsProviderTest.java index 10c69b476e..6c419cceac 100644 --- a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/SystemPropertiesCredentialsProviderTest.java +++ b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/SystemPropertiesCredentialsProviderTest.java @@ -9,25 +9,52 @@ public class SystemPropertiesCredentialsProviderTest { @Test public void getCredentialsTest() throws ClientException { + System.setProperty(AuthConstant.SYSTEM_ACCESSKEYSECRET, ""); + System.setProperty(AuthConstant.SYSTEM_ACCESSKEYID, ""); SystemPropertiesCredentialsProvider provider = new SystemPropertiesCredentialsProvider(); AuthUtils.setClientType("aa"); Assert.assertNull(provider.getCredentials()); AuthUtils.setClientType("default"); + try { + provider.getCredentials(); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("System property alibabacloud.accessKeyId cannot be empty.", e.getMessage()); + } + System.setProperty(AuthConstant.SYSTEM_ACCESSKEYSECRET, ""); System.setProperty(AuthConstant.SYSTEM_ACCESSKEYID, "accessKeyIdTest"); - Assert.assertNull(provider.getCredentials()); + try { + provider.getCredentials(); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("System property alibabacloud.accessKeySecret cannot be empty.", e.getMessage()); + } - System.setProperty(AuthConstant.SYSTEM_ACCESSKEYSECRET, "accessKeyIdTest"); + System.setProperty(AuthConstant.SYSTEM_ACCESSKEY_SECRET, "accessKeyIdTest"); AlibabaCloudCredentials credential = provider.getCredentials(); String accessKeyId = credential.getAccessKeyId(); String accessKeySecret = credential.getAccessKeySecret(); Assert.assertEquals("accessKeyIdTest", accessKeyId); Assert.assertEquals("accessKeyIdTest", accessKeySecret); - System.setProperty(AuthConstant.SYSTEM_ACCESSKEYID, ""); - Assert.assertNull(provider.getCredentials()); + System.setProperty(AuthConstant.SYSTEM_ACCESSKEYSECRET, "accessKeySecretTest"); + credential = provider.getCredentials(); + accessKeyId = credential.getAccessKeyId(); + accessKeySecret = credential.getAccessKeySecret(); + Assert.assertEquals("accessKeyIdTest", accessKeyId); + Assert.assertEquals("accessKeySecretTest", accessKeySecret); + System.setProperty(AuthConstant.SYSTEM_SESSION_TOKEN, "sessionTokenTest"); + BasicSessionCredentials basicSessionCredentials = (BasicSessionCredentials) provider.getCredentials(); + Assert.assertEquals("accessKeyIdTest", basicSessionCredentials.getAccessKeyId()); + Assert.assertEquals("accessKeySecretTest", basicSessionCredentials.getAccessKeySecret()); + Assert.assertEquals("sessionTokenTest", basicSessionCredentials.getSessionToken()); + + System.setProperty(AuthConstant.SYSTEM_ACCESSKEYID, ""); + System.setProperty(AuthConstant.SYSTEM_ACCESSKEY_SECRET, ""); System.setProperty(AuthConstant.SYSTEM_ACCESSKEYSECRET, ""); + System.setProperty(AuthConstant.SYSTEM_SESSION_TOKEN, ""); } } diff --git a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/URLCredentialsProviderTest.java b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/URLCredentialsProviderTest.java new file mode 100644 index 0000000000..c58f484cdb --- /dev/null +++ b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/URLCredentialsProviderTest.java @@ -0,0 +1,95 @@ +package com.aliyuncs.auth; + +import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.http.HttpRequest; +import com.aliyuncs.http.HttpResponse; +import com.aliyuncs.http.clients.CompatibleUrlConnClient; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.BDDMockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(CompatibleUrlConnClient.class) +public class URLCredentialsProviderTest { + + @Test + public void constructorTest() throws MalformedURLException, NoSuchFieldException, IllegalAccessException { + URLCredentialsProvider provider; + + try { + URLCredentialsProvider.builder().build(); + Assert.fail(); + } catch (Exception e) { + Assert.assertEquals("Credential URI or environment variable ALIBABA_CLOUD_CREDENTIALS_URI cannot be empty.", + e.getMessage()); + } + + provider = URLCredentialsProvider.builder() + .credentialsURI(new URL("http://test1")) + .credentialsURI("http://test2") + .readTimeout(2000) + .connectionTimeout(2000) + .build(); + Class clazz = provider.getClass(); + Field urlField = clazz.getDeclaredField("credentialsURI"); + urlField.setAccessible(true); + Field connectTimeoutField = clazz.getDeclaredField("connectTimeout"); + connectTimeoutField.setAccessible(true); + Field readTimeoutField = clazz.getDeclaredField("readTimeout"); + readTimeoutField.setAccessible(true); + Assert.assertEquals(2000, connectTimeoutField.get(provider)); + Assert.assertEquals(2000, readTimeoutField.get(provider)); + Assert.assertEquals("http://test2", ((URL) urlField.get(provider)).toString()); + } + + @Test + public void getCredentials() throws IOException, ClientException { + URLCredentialsProvider provider = URLCredentialsProvider.builder() + .credentialsURI("http://test") + .readTimeout(2000) + .connectionTimeout(2000) + .build(); + + HttpResponse response = mock(HttpResponse.class); + when(response.getStatus()).thenReturn(HttpURLConnection.HTTP_OK); + String content = "{\"Code\":\"Success\", \"AccessKeyId\":\"test\", " + + "\"AccessKeySecret\":\"test\", \"SecurityToken\":\"test\", \"Expiration\":\"2019-08-08T11:11:11Z\"}"; + when(response.getHttpContentString()).thenReturn(content); + PowerMockito.mockStatic(CompatibleUrlConnClient.class); + BDDMockito.given(CompatibleUrlConnClient.compatibleGetResponse(any(HttpRequest.class))).willReturn(response); + BasicSessionCredentials credentials = (BasicSessionCredentials) provider.getCredentials(); + Assert.assertEquals("test", credentials.getAccessKeyId()); + Assert.assertEquals("test", credentials.getAccessKeySecret()); + Assert.assertEquals("test", credentials.getSessionToken()); + + when(response.getStatus()).thenReturn(HttpURLConnection.HTTP_OK); + content = "error"; + when(response.getHttpContentString()).thenReturn(content); + PowerMockito.mockStatic(CompatibleUrlConnClient.class); + BDDMockito.given(CompatibleUrlConnClient.compatibleGetResponse(any(HttpRequest.class))).willReturn(response); + + try { + provider.getCredentials(); + Assert.fail(); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("Failed to parse credentials from server: http://test\n" + + "HttpCode=200\n" + + "HttpRAWContent=error")); + } + } + +} \ No newline at end of file diff --git a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/V3SignatureComposerTest.java b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/V3SignatureComposerTest.java index 1650987ccb..b8eda42ffd 100644 --- a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/V3SignatureComposerTest.java +++ b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/V3SignatureComposerTest.java @@ -1,20 +1,14 @@ package com.aliyuncs.auth; -import com.aliyuncs.http.FormatType; import com.aliyuncs.http.MethodType; import org.junit.Assert; import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; import java.util.HashMap; import java.util.Map; import static org.mockito.Mockito.mock; -@RunWith(PowerMockRunner.class) -@PrepareForTest(FormatType.class) public class V3SignatureComposerTest { @Test diff --git a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/sts/AssumeRoleRequestTest.java b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/sts/AssumeRoleRequestTest.java index d0cd64d3bf..8232715e99 100644 --- a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/sts/AssumeRoleRequestTest.java +++ b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/auth/sts/AssumeRoleRequestTest.java @@ -27,6 +27,12 @@ public void testAssumeRoleRequest() { request.setPolicy("policy"); Assert.assertEquals("policy", request.getPolicy()); Assert.assertEquals("policy", request.getSysQueryParameters().get("Policy")); + // externalId + Assert.assertNull(request.getExternalId()); + Assert.assertNull(request.getSysQueryParameters().get("ExternalId")); + request.setExternalId("externalId"); + Assert.assertEquals("externalId", request.getExternalId()); + Assert.assertEquals("externalId", request.getSysQueryParameters().get("ExternalId")); // roleSessionName Assert.assertNull(request.getRoleSessionName()); Assert.assertNull(request.getSysQueryParameters().get("RoleSessionName")); diff --git a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/utils/AuthUtilsTest.java b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/utils/AuthUtilsTest.java index f15930f446..fe2856b41a 100644 --- a/aliyun-java-sdk-core/src/test/java/com/aliyuncs/utils/AuthUtilsTest.java +++ b/aliyun-java-sdk-core/src/test/java/com/aliyuncs/utils/AuthUtilsTest.java @@ -12,4 +12,91 @@ public void getPrivateKeyTest(){ String privateKey = AuthUtils.getPrivateKey(path); Assert.assertNotNull(privateKey); } + + @Test + public void environmentTest() { + Assert.assertNull(AuthUtils.getEnvironmentAccessKeyId()); + AuthUtils.setEnvironmentAccessKeyId("test"); + Assert.assertEquals("test", AuthUtils.getEnvironmentAccessKeyId()); + AuthUtils.setEnvironmentAccessKeyId(null); + + Assert.assertNull(AuthUtils.getEnvironmentAccessKeySecret()); + AuthUtils.setEnvironmentAccessKeySecret("test"); + Assert.assertEquals("test", AuthUtils.getEnvironmentAccessKeySecret()); + AuthUtils.setEnvironmentAccessKeySecret(null); + + AuthUtils.setEnvironmentCredentialsFile("test"); + Assert.assertEquals("test", AuthUtils.getEnvironmentCredentialsFile()); + AuthUtils.setEnvironmentCredentialsFile(null); + Assert.assertNull(AuthUtils.getEnvironmentCredentialsFile()); + + Assert.assertNull(AuthUtils.getEnvironmentECSMetaData()); + AuthUtils.setEnvironmentECSMetaData("test"); + Assert.assertEquals("test", AuthUtils.getEnvironmentECSMetaData()); + AuthUtils.setEnvironmentECSMetaData(null); + Assert.assertFalse(AuthUtils.environmentEnableOIDC()); + + Assert.assertFalse(AuthUtils.getDisableECSIMDSv1()); + AuthUtils.disableECSIMDSv1(true); + Assert.assertTrue(AuthUtils.getDisableECSIMDSv1()); + AuthUtils.disableECSIMDSv1(false); + Assert.assertFalse(AuthUtils.getDisableECSIMDSv1()); + + Assert.assertNull(AuthUtils.getEnvironmentRoleArn()); + AuthUtils.setEnvironmentRoleArn("test"); + Assert.assertEquals("test", AuthUtils.getEnvironmentRoleArn()); + Assert.assertFalse(AuthUtils.environmentEnableOIDC()); + + Assert.assertNull(AuthUtils.getEnvironmentOIDCProviderArn()); + AuthUtils.setEnvironmentOIDCProviderArn("test"); + Assert.assertEquals("test", AuthUtils.getEnvironmentOIDCProviderArn()); + Assert.assertFalse(AuthUtils.environmentEnableOIDC()); + + Assert.assertNull(AuthUtils.getEnvironmentOIDCTokenFilePath()); + AuthUtils.setEnvironmentOIDCTokenFilePath("test"); + Assert.assertEquals("test", AuthUtils.getEnvironmentOIDCTokenFilePath()); + Assert.assertTrue(AuthUtils.environmentEnableOIDC()); + + AuthUtils.setEnvironmentRoleArn(null); + AuthUtils.setEnvironmentOIDCProviderArn(null); + AuthUtils.setEnvironmentOIDCTokenFilePath(null); + Assert.assertFalse(AuthUtils.environmentEnableOIDC()); + + Assert.assertNull(AuthUtils.getEnvironmentRoleSessionName()); + AuthUtils.setEnvironmentRoleSessionName("test"); + Assert.assertEquals("test", AuthUtils.getEnvironmentRoleSessionName()); + AuthUtils.setEnvironmentRoleSessionName(null); + + Assert.assertNull(AuthUtils.getEnvironmentSTSRegion()); + AuthUtils.setEnvironmentSTSRegion("test"); + Assert.assertEquals("test", AuthUtils.getEnvironmentSTSRegion()); + AuthUtils.setEnvironmentSTSRegion(null); + + Assert.assertFalse(AuthUtils.isDisableECSMetaData()); + AuthUtils.disableECSMetaData(true); + Assert.assertTrue(AuthUtils.isDisableECSMetaData()); + AuthUtils.disableECSMetaData(false); + Assert.assertFalse(AuthUtils.isDisableECSMetaData()); + + Assert.assertFalse(AuthUtils.isEnableVpcEndpoint()); + AuthUtils.enableVpcEndpoint(true); + Assert.assertTrue(AuthUtils.isEnableVpcEndpoint()); + AuthUtils.enableVpcEndpoint(false); + Assert.assertFalse(AuthUtils.isEnableVpcEndpoint()); + + Assert.assertFalse(AuthUtils.isDisableCLIProfile()); + AuthUtils.disableCLIProfile(true); + Assert.assertTrue(AuthUtils.isDisableCLIProfile()); + AuthUtils.disableCLIProfile(false); + Assert.assertFalse(AuthUtils.isDisableCLIProfile()); + } + + @Test + public void clientTypeTest() { + AuthUtils.setClientType(null); + Assert.assertEquals("default", AuthUtils.getClientType()); + AuthUtils.setClientType("test"); + Assert.assertEquals("test", AuthUtils.getClientType()); + AuthUtils.setClientType(null); + } } diff --git a/aliyun-java-sdk-core/src/test/resources/.aliyun/config.json b/aliyun-java-sdk-core/src/test/resources/.aliyun/config.json new file mode 100644 index 0000000000..b190355c8d --- /dev/null +++ b/aliyun-java-sdk-core/src/test/resources/.aliyun/config.json @@ -0,0 +1,50 @@ +{ + "current": "AK", + "profiles": [ + { + "name": "AK", + "mode": "AK", + "access_key_id": "akid", + "access_key_secret": "secret" + }, + { + "name": "RamRoleArn", + "mode": "RamRoleArn", + "access_key_id": "akid", + "access_key_secret": "secret", + "ram_role_arn": "arn" + }, + { + "name": "Invalid_RamRoleArn", + "mode": "RamRoleArn" + + }, + { + "name": "EcsRamRole", + "mode": "EcsRamRole", + "ram_role_name": "rolename" + }, + { + "name": "OIDC", + "mode": "OIDC", + "ram_role_arn": "role_arn", + "oidc_token_file": "path/to/oidc/file", + "oidc_provider_arn": "provider_arn" + }, + { + "name": "ChainableRamRoleArn", + "mode": "ChainableRamRoleArn", + "ram_role_arn": "arn", + "source_profile": "AK" + }, + { + "name": "ChainableRamRoleArn2", + "mode": "ChainableRamRoleArn", + "source_profile": "InvalidSource" + }, + { + "name": "Unsupported", + "mode": "Unsupported" + } + ] +} \ No newline at end of file diff --git a/aliyun-java-sdk-core/src/test/resources/empty_file.json b/aliyun-java-sdk-core/src/test/resources/empty_file.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aliyun-java-sdk-core/src/test/resources/full_cli_config.json b/aliyun-java-sdk-core/src/test/resources/full_cli_config.json new file mode 100644 index 0000000000..360aabf92c --- /dev/null +++ b/aliyun-java-sdk-core/src/test/resources/full_cli_config.json @@ -0,0 +1,45 @@ +{ + "current": "AK", + "profiles": [ + { + "name": "AK", + "mode": "AK", + "access_key_id": "access_key_id", + "access_key_secret": "access_key_secret" + }, + { + "name": "RamRoleArn", + "mode": "RamRoleArn", + "access_key_id": "access_key_id", + "access_key_secret": "access_key_secret", + "ram_role_arn": "ram_role_arn", + "ram_session_name": "ram_session_name", + "expired_seconds": 3600, + "sts_region": "cn-hangzhou" + }, + { + "name": "EcsRamRole", + "mode": "EcsRamRole", + "ram_role_name": "ram_role_name" + }, + { + "name": "OIDC", + "mode": "OIDC", + "ram_role_arn": "ram_role_arn", + "oidc_token_file": "path/to/oidc/file", + "oidc_provider_arn": "oidc_provider_arn", + "ram_session_name": "ram_session_name", + "expired_seconds": 3600, + "sts_region": "cn-hangzhou" + }, + { + "name": "ChainableRamRoleArn", + "mode": "ChainableRamRoleArn", + "source_profile": "AK", + "ram_role_arn": "ram_role_arn", + "ram_session_name": "ram_session_name", + "expired_seconds": 3600, + "sts_region": "cn-hangzhou" + } + ] +} \ No newline at end of file diff --git a/aliyun-java-sdk-core/src/test/resources/invalid_cli_config.json b/aliyun-java-sdk-core/src/test/resources/invalid_cli_config.json new file mode 100644 index 0000000000..e4fd6fad78 --- /dev/null +++ b/aliyun-java-sdk-core/src/test/resources/invalid_cli_config.json @@ -0,0 +1 @@ +invalid config \ No newline at end of file diff --git a/aliyun-java-sdk-core/src/test/resources/mock_empty_cli_config.json b/aliyun-java-sdk-core/src/test/resources/mock_empty_cli_config.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/aliyun-java-sdk-core/src/test/resources/mock_empty_cli_config.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/java-sdk-function-test/src/test/java/com/aliyuncs/CredentialsTest.java b/java-sdk-function-test/src/test/java/com/aliyuncs/CredentialsTest.java index 3110f3f2bd..ef0d194090 100644 --- a/java-sdk-function-test/src/test/java/com/aliyuncs/CredentialsTest.java +++ b/java-sdk-function-test/src/test/java/com/aliyuncs/CredentialsTest.java @@ -52,6 +52,6 @@ public void oidcProviderForDefaultCredentialsProviderTest() throws ClientExcepti GetCallerIdentityResponse response = client.getAcsResponse(request); Assert.assertNotNull(response); Assert.assertEquals("AssumedRoleUser", response.getIdentityType()); - Assert.assertTrue(response.getArn().endsWith("/java-sdk-v1-default-rsn")); + Assert.assertTrue(response.getArn().contains("oidc-role-for-java-sdk-v1-ci")); } }