All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.aliyun.openservices.ons.api.impl.rocketmq.StsSessionCredentialsProvider Maven / Gradle / Ivy

package com.aliyun.openservices.ons.api.impl.rocketmq;

import com.alibaba.ons.open.trace.core.utils.JsonUtils;
import com.aliyun.openservices.ons.api.impl.auth.StsCredentials;
import com.aliyun.openservices.ons.api.impl.authority.SessionCredentials;
import com.aliyun.openservices.ons.api.impl.authority.SessionCredentialsProvider;
import com.aliyun.openservices.ons.api.impl.util.ClientLoggerUtil;
import com.aliyun.openservices.shade.com.alibaba.rocketmq.common.ThreadFactoryImpl;
import com.aliyun.openservices.shade.com.alibaba.rocketmq.common.utils.HttpTinyClient;
import com.aliyun.openservices.shade.com.alibaba.rocketmq.logging.InternalLogger;
import com.fasterxml.jackson.databind.JsonNode;

import java.text.SimpleDateFormat;
import java.util.TimeZone;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class StsSessionCredentialsProvider implements SessionCredentialsProvider {
    private static final String URL_ECS_RAM_ROLE = "http://100.100.100.200/latest/meta-data/Ram/security-credentials/";
    private final static InternalLogger LOGGER = ClientLoggerUtil.getClientLogger();

    private static final long DEFAULT_REFRESH_INTERVAL_MILLIS = 30L * 60 * 60L * 1000L;
    private static final long MIN_REFRESH_INTERVAL_MILLIS = 5000L;
    private static final long HTTP_TIMEOUT_MILLIS = 3000L;

    private final ONSClientAbstract client;
    private final String ramRoleName;
    private final SessionCredentials sessionCredentials;

    private final ScheduledExecutorService scheduledExecutorService =
            new ScheduledThreadPoolExecutor(1, new ThreadFactoryImpl("ONSRamRoleStsTokenUpdater"));

    public StsSessionCredentialsProvider(ONSClientAbstract client, String ramRoleName) {
        this.client = client;
        this.ramRoleName = ramRoleName;
        this.sessionCredentials = new SessionCredentials(client.sessionCredentials);
        refreshToken(ramRoleName);
    }

    private void refreshToken(String ramRoleName) {
        StsCredentials stsCredentials = fetchStsCredentialsByRamRole(ramRoleName);
        if (stsCredentials != null) {
            sessionCredentials.setAccessKey(stsCredentials.getAccessKeyId());
            sessionCredentials.setSecretKey(stsCredentials.getAccessKeySecret());
            sessionCredentials.setSecurityToken(stsCredentials.getSecurityToken());
            // Replace sessionCredentials in ons client.
            client.sessionCredentials = sessionCredentials;
            LOGGER.info("update sts credentials success, ramRoleName={}", ramRoleName);
            dispatchTokenRefreshTask(stsCredentials);
        } else {
            dispatchTokenRefreshTask(ramRoleName, MIN_REFRESH_INTERVAL_MILLIS);
        }
    }

    private void dispatchTokenRefreshTask(final StsCredentials stsCredentials) {
        long now = System.currentTimeMillis();
        long interval = stsCredentials.getExpiration() - now;
        long delay = interval > DEFAULT_REFRESH_INTERVAL_MILLIS ?
                stsCredentials.getExpiration() - now - DEFAULT_REFRESH_INTERVAL_MILLIS :
                Math.max(MIN_REFRESH_INTERVAL_MILLIS, (stsCredentials.getExpiration() - now) / 2);
        dispatchTokenRefreshTask(stsCredentials.getRamRoleName(), delay);
    }

    private void dispatchTokenRefreshTask(final String ramRoleName, long delay) {
        scheduledExecutorService.schedule(new Runnable() {
            @Override
            public void run() {
                try {
                    refreshToken(ramRoleName);
                } catch (Throwable t) {
                    LOGGER.error("Unexpected exception raised while refreshing sts token, ramRoleName={}",
                            ramRoleName, t);
                }
            }
        }, delay, TimeUnit.MILLISECONDS);
    }

    private StsCredentials fetchStsCredentialsByRamRole(String ramRoleName) {
        try {
            HttpTinyClient.HttpResult result = HttpTinyClient.httpGet(URL_ECS_RAM_ROLE + ramRoleName,
                    null, null, "UTF-8", HTTP_TIMEOUT_MILLIS);
            if (200 != result.code || null == result.content || "".equals(result.content)) {
                LOGGER.error("fetch sts credentials by ram role[ " + ramRoleName + " ] error. please set right ram role");
            }
            JsonNode jsonNode = JsonUtils.mapper.readTree(result.content);

            StsCredentials stsCredentials = new StsCredentials();
            stsCredentials.setRamRoleName(ramRoleName);
            stsCredentials.setAccessKeyId(jsonNode.get("AccessKeyId").asText());
            stsCredentials.setAccessKeySecret(jsonNode.get("AccessKeySecret").asText());
            stsCredentials.setSecurityToken(jsonNode.get("SecurityToken").asText());

            SimpleDateFormat utcFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
            utcFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
            stsCredentials.setExpiration(utcFormatter.parse(jsonNode.get("Expiration").asText()).getTime());

            return stsCredentials;
        } catch (Exception e) {
            LOGGER.error("fetch sts credentials by ram role[ " + ramRoleName + " ] error", e);
        }
        return null;
    }

    @Override
    public SessionCredentials getSessionCredentials() {
        return client.sessionCredentials;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy