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

com.yahoo.athenz.zts.ZTSAccessTokenFileLoader Maven / Gradle / Ivy

package com.yahoo.athenz.zts;

import athenz.shade.zts.athenz.shade.zts.com.fasterxml.jackson.databind.ObjectMapper;
import com.yahoo.athenz.auth.token.AccessToken;
import com.yahoo.athenz.auth.token.jwts.JwtsSigningKeyResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.*;

public class ZTSAccessTokenFileLoader {

    private static final Logger LOG = LoggerFactory.getLogger(ZTSAccessTokenFileLoader.class);

    static public final String ACCESS_TOKEN_PATH_PROPERTY = "athenz.zts.client.accesstoken.path";
    static private final String DEFAULT_ACCESS_TOKEN_DIR_PATH = "/var/lib/sia/tokens/";
    static private final String ROLE_NAME_CONNECTOR = ",";
    static private final String DOMAIN_ROLE_CONNECTOR = ":role:";
    final private String path;
    private JwtsSigningKeyResolver accessSignKeyResolver;
    private ObjectMapper objectMapper = new ObjectMapper();
    private Map roleNameMap;

    public ZTSAccessTokenFileLoader(JwtsSigningKeyResolver resolver) {
        roleNameMap = new HashMap<>();
        accessSignKeyResolver = resolver;
        path = System.getProperty(ACCESS_TOKEN_PATH_PROPERTY, DEFAULT_ACCESS_TOKEN_DIR_PATH);
    }

    public void preload() {
        File dir = new File(path);

        // preload the map from the  -> 
        // expected dir should be //s
        // after preload the map, when we look up the access token,
        // the map will directly read the required file
        if (dir.exists() && dir.isDirectory()) {
            for (File domainDir: dir.listFiles()) {
                if (domainDir.isDirectory()) {
                    for (File tokenFile: domainDir.listFiles()) {
                        if (!tokenFile.isDirectory()) {
                            AccessTokenResponse accessTokenResponse = null;
                            try {
                                accessTokenResponse = objectMapper.readValue(tokenFile, AccessTokenResponse.class);
                            } catch (IOException e) {
                                LOG.error("Failed to load or parse token file: {}", tokenFile);
                            }

                            // if access token parsed fail, continue to scan tokens
                            if (accessTokenResponse == null) {
                                continue;
                            }

                            AccessTokenResponseCacheEntry cacheEntry = new AccessTokenResponseCacheEntry(accessTokenResponse);

                            // check access token is still valid
                            if (!cacheEntry.isExpired(-1)) {
                                addToRoleMap(domainDir.getName(), tokenFile.getName(), accessTokenResponse);
                            }
                        }
                    }
                }
            }
        }

    }

    // function load the access token from file
    public AccessTokenResponse lookupAccessTokenFromDisk(String domain, List rolesName) throws IOException {
        final String rolesStr = getRolesStr(domain, rolesName);
        final String fileName = roleNameMap.get(rolesStr);
        LOG.debug("Trying to fetch access token from disk for domain: {}, roleNames: {}, roleMap key: {}. file name: {}",
                domain, rolesName, rolesStr, fileName);
        if (fileName == null) {
            return null;
        }
        File tokenFile = new File(path + File.separator + domain + File.separator + fileName);

        return objectMapper.readValue(tokenFile, AccessTokenResponse.class);
    }

    static private String getRolesStr(String domain, List roleNames) {
        // in case the rolesName is immutable, make a copy of role name list
        if (roleNames == null || roleNames.isEmpty()) {
            //if no role name specific, should return all roles
            return domain + DOMAIN_ROLE_CONNECTOR + "*";
        }
        List roleNamesCopy = new ArrayList<>(roleNames);
        Collections.sort(roleNamesCopy);
        return domain + DOMAIN_ROLE_CONNECTOR + String.join(ROLE_NAME_CONNECTOR, roleNamesCopy);
    }

    private void addToRoleMap(String domain, String fileName, AccessTokenResponse accessTokenResponse) {
        // parse roles from access token
        final String token = accessTokenResponse.getAccess_token();

        try {
            AccessToken accessToken = new AccessToken(token, accessSignKeyResolver);
            List roleNames = accessToken.getScope();
            roleNameMap.put(getRolesStr(domain, roleNames), fileName);
        } catch (Exception e) {
            LOG.error("Got error to parse access token file {}, error: {}", fileName, e.getMessage());
            return;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy