package com.alipay.easysdk.kms.aliyun.credentials.provider; import com.alipay.easysdk.kms.aliyun.credentials.EcsRamRoleCredentials; import com.alipay.easysdk.kms.aliyun.credentials.exceptions.CredentialException; import com.alipay.easysdk.kms.aliyun.credentials.http.CompatibleUrlConnClient; import com.alipay.easysdk.kms.aliyun.credentials.http.HttpRequest; import com.alipay.easysdk.kms.aliyun.credentials.http.HttpResponse; import com.alipay.easysdk.kms.aliyun.credentials.http.MethodType; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class ECSMetadataServiceCredentialsFetcher { private static final String URL_IN_ECS_METADATA = "/latest/meta-data/ram/security-credentials/"; private static final int DEFAULT_TIMEOUT_IN_MILLISECONDS = 1000; private static final String ECS_METADAT_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; public ECSMetadataServiceCredentialsFetcher() { this.connectionTimeoutInMilliseconds = DEFAULT_TIMEOUT_IN_MILLISECONDS; } public void setRoleName(String roleName) { if (null == roleName) { throw new NullPointerException("You must specifiy a valid role name."); } this.roleName = roleName; setCredentialUrl(); } private void setCredentialUrl() { try { this.credentialUrl = new URL("http://" + metadataServiceHost + URL_IN_ECS_METADATA + roleName); } catch (MalformedURLException e) { throw new IllegalArgumentException(e.toString()); } } public ECSMetadataServiceCredentialsFetcher withECSMetadataServiceHost(String host) { System.err.println("withECSMetadataServiceHost() method is only for testing, please don't use it"); this.metadataServiceHost = host; setCredentialUrl(); return this; } public ECSMetadataServiceCredentialsFetcher withConnectionTimeout(int milliseconds) { this.connectionTimeoutInMilliseconds = milliseconds; return this; } public String getMetadata() throws CredentialException { HttpRequest request = new HttpRequest(credentialUrl.toString()); request.setMethod(MethodType.GET); request.setConnectTimeout(connectionTimeoutInMilliseconds); request.setReadTimeout(connectionTimeoutInMilliseconds); HttpResponse response; try { response = CompatibleUrlConnClient.compatibleGetResponse(request); } catch (Exception e) { throw new CredentialException("Failed to connect ECS Metadata Service: " + e.toString()); } if (response.getStatus() != HttpURLConnection.HTTP_OK) { throw new CredentialException(ECS_METADAT_FETCH_ERROR_MSG + " HttpCode=" + response.getStatus()); } return new String(response.getHttpContent()); } public EcsRamRoleCredentials fetch() throws CredentialException { String jsonContent = getMetadata(); JsonObject jsonObject = null; jsonObject = new JsonParser().parse(jsonContent).getAsJsonObject(); if (jsonObject.has("Code") && jsonObject.has("AccessKeyId") && jsonObject.has("AccessKeySecret") && jsonObject .has("SecurityToken") && jsonObject.has("Expiration")) { } else { throw new CredentialException("Invalid json got from ECS Metadata service."); } if (!"Success".equals(jsonObject.get("Code").getAsString())) { throw new CredentialException(ECS_METADAT_FETCH_ERROR_MSG); } return new EcsRamRoleCredentials(jsonObject.get("AccessKeyId").getAsString(), jsonObject.get( "AccessKeySecret").getAsString(), jsonObject.get("SecurityToken").getAsString(), jsonObject.get( "Expiration").getAsString(), DEFAULT_ECS_SESSION_TOKEN_DURATION_SECONDS); } public EcsRamRoleCredentials fetch(int retryTimes) throws CredentialException { for (int i = 0; i <= retryTimes; i++) { try { return fetch(); } catch (CredentialException e) { if (i == retryTimes) { throw e; } } } throw new CredentialException("Failed to connect ECS Metadata Service: Max retry times exceeded."); } }