com.aliyun.auth.credentials.provider.EcsRamRoleCredentialProvider Maven / Gradle / Ivy
The newest version!
package com.aliyun.auth.credentials.provider;
import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.ICredential;
import com.aliyun.auth.credentials.exception.*;
import com.aliyun.auth.credentials.http.*;
import com.aliyun.auth.credentials.utils.*;
import com.aliyun.core.utils.StringUtils;
import com.google.gson.Gson;
import java.time.Instant;
import java.util.Map;
public final class EcsRamRoleCredentialProvider extends HttpCredentialProvider {
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 String ECS_METADAT_FETCH_ERROR_MSG = "Failed to get RAM session credentials from ECS metadata service.";
private final String roleName;
private final String metadataServiceHost;
private final Boolean disableIMDSv1;
private final int connectionTimeout;
private final int readTimeout;
private final CompatibleUrlConnClient client;
private EcsRamRoleCredentialProvider(BuilderImpl builder) {
super(builder);
if (AuthUtils.isDisableECSMetaData()) {
throw new CredentialException("IMDS credentials is disabled.");
}
this.roleName = builder.roleName == null ? AuthUtils.getEnvironmentECSMetaData() : builder.roleName;
this.disableIMDSv1 = builder.disableIMDSv1 == null ? AuthUtils.getDisableECSIMDSv1() : builder.disableIMDSv1;
this.metadataServiceHost = builder.metadataServiceHost == null ? "100.100.100.200" : builder.metadataServiceHost;
this.connectionTimeout = builder.connectionTimeout == null ? 1000 : builder.connectionTimeout;
this.readTimeout = builder.readTimeout == null ? 1000 : builder.readTimeout;
this.client = new CompatibleUrlConnClient();
this.buildRefreshCache();
}
public static EcsRamRoleCredentialProvider create(String roleName) {
return builder().roleName(roleName).build();
}
public static Builder builder() {
return new BuilderImpl();
}
private String getMetadata(String url) {
HttpRequest request = new HttpRequest(url);
request.setSysMethod(MethodType.GET);
request.setSysConnectTimeout(connectionTimeout);
request.setSysReadTimeout(readTimeout);
HttpResponse response;
String metadataToken = this.getMetadataToken();
if (metadataToken != null) {
request.putHeaderParameter("X-aliyun-ecs-metadata-token", metadataToken);
}
try {
response = client.syncInvoke(request);
} catch (Exception e) {
throw new CredentialException("Failed to connect ECS Metadata Service: " + e);
}
if (response.getResponseCode() == 404) {
throw new CredentialException("The role name was not found in the instance.");
}
if (response.getResponseCode() != 200) {
throw new CredentialException(ECS_METADAT_FETCH_ERROR_MSG + " HttpCode=" + response.getResponseCode());
}
return response.getHttpContentString();
}
private String getMetadataToken() {
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", "21600");
HttpResponse response;
try {
response = client.syncInvoke(request);
} catch (Exception e) {
throw new CredentialException("Failed to connect ECS Metadata Service: " + e);
}
if (response.getResponseCode() != 200) {
throw new CredentialException("Failed to get token from ECS Metadata Service. HttpCode=" + response.getResponseCode() + ", ResponseMessage=" + response.getHttpContentString());
}
return new String(response.getHttpContent());
} catch (Exception ex) {
return throwErrorOrReturn(ex);
}
}
private String throwErrorOrReturn(Exception e) {
if (this.disableIMDSv1) {
throw new CredentialException("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;
}
@Override
public RefreshResult refreshCredentials() {
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);
Map result = new Gson().fromJson(jsonContent, Map.class);
if (!"Success".equals(result.get("Code"))) {
throw new CredentialException(ECS_METADAT_FETCH_ERROR_MSG);
}
if (!result.containsKey("AccessKeyId") || !result.containsKey("AccessKeySecret") || !result.containsKey("SecurityToken")) {
throw new CredentialException(String.format("Error retrieving credentials from IMDS result: %s.", jsonContent));
}
Instant expiration = ParameterHelper.getUTCDate(result.get("Expiration")).toInstant();
ICredential credential = Credential.builder()
.accessKeyId(result.get("AccessKeyId"))
.accessKeySecret(result.get("AccessKeySecret"))
.securityToken(result.get("SecurityToken"))
.build();
return RefreshResult.builder(credential)
.staleTime(getStaleTime(expiration))
.prefetchTime(getPrefetchTime(expiration))
.build();
}
@Override
public void close() {
super.close();
this.client.close();
}
public interface Builder extends HttpCredentialProvider.Builder {
Builder roleName(String roleSessionName);
Builder metadataServiceHost(String metadataServiceHost);
Builder disableIMDSv1(Boolean disableIMDSv1);
Builder connectionTimeout(Integer connectionTimeout);
Builder readTimeout(Integer readTimeout);
@Override
EcsRamRoleCredentialProvider build();
}
private static final class BuilderImpl
extends HttpCredentialProvider.BuilderImpl
implements Builder {
private String roleName;
private String metadataServiceHost;
private Boolean disableIMDSv1;
private Integer connectionTimeout;
private Integer readTimeout;
public Builder roleName(String roleName) {
this.roleName = roleName;
return this;
}
public Builder metadataServiceHost(String metadataServiceHost) {
this.metadataServiceHost = metadataServiceHost;
return this;
}
public Builder disableIMDSv1(Boolean disableIMDSv1) {
this.disableIMDSv1 = disableIMDSv1;
return this;
}
public Builder connectionTimeout(Integer connectionTimeout) {
this.connectionTimeout = connectionTimeout;
return this;
}
public Builder readTimeout(Integer readTimeout) {
this.readTimeout = readTimeout;
return this;
}
@Override
public EcsRamRoleCredentialProvider build() {
return new EcsRamRoleCredentialProvider(this);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy