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

com.github.dockerjava.core.AuthConfigFile Maven / Gradle / Ivy

There is a newer version: 3.4.1
Show newest version
package com.github.dockerjava.core;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.dockerjava.api.model.AuthConfig;
import com.github.dockerjava.api.model.AuthConfigurations;

public class AuthConfigFile {
    private static final ObjectMapper MAPPER = new ObjectMapper();

    private static final TypeReference> CONFIG_CFG_MAP_TYPE =
        new TypeReference>() {
        };

    private static final TypeReference>> CONFIG_JSON_MAP_TYPE =
        new TypeReference>>() {
        };
    private static final String AUTHS_PROPERTY = "auths";

    private final Map authConfigMap;

    public AuthConfigFile() {
        authConfigMap = new HashMap<>();
    }

    void addConfig(AuthConfig config) {
        authConfigMap.put(config.getRegistryAddress(), config);
    }

    public AuthConfig resolveAuthConfig(String hostname) {
        if (StringUtils.isEmpty(hostname) || AuthConfig.DEFAULT_SERVER_ADDRESS.equals(hostname)) {
            return authConfigMap.get(AuthConfig.DEFAULT_SERVER_ADDRESS);
        }
        AuthConfig c = authConfigMap.get(hostname);
        if (c != null) {
            return c;
        }

        // Maybe they have a legacy config file, we will iterate the keys converting
        // them to the new format and testing
        String normalizedHostname = convertToHostname(hostname);
        for (Map.Entry entry : authConfigMap.entrySet()) {
            String registry = entry.getKey();
            AuthConfig config = entry.getValue();
            if (convertToHostname(registry).equals(normalizedHostname)) {
                return config;
            }
        }
        return null;
    }

    public AuthConfigurations getAuthConfigurations() {
        final AuthConfigurations authConfigurations = new AuthConfigurations();
        for (Map.Entry authConfigEntry : authConfigMap.entrySet()) {
            authConfigurations.addConfig(authConfigEntry.getValue());
        }

        return authConfigurations;
    }

    // CHECKSTYLE:OFF
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((authConfigMap == null) ? 0 : authConfigMap.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        AuthConfigFile other = (AuthConfigFile) obj;
        if (authConfigMap == null) {
            if (other.authConfigMap != null)
                return false;
        } else if (!authConfigMap.equals(other.authConfigMap))
            return false;
        return true;
    }

    // CHECKSTYLE:ON

    @Override
    public String toString() {
        return "AuthConfigFile [authConfigMap=" + authConfigMap + "]";
    }

    public static AuthConfigFile loadConfig(File confFile) throws IOException {
        AuthConfigFile configFile = new AuthConfigFile();
        if (!confFile.exists()) {
            return new AuthConfigFile();
        }

        Map configMap = null;
        /*
        Registry v2 expects config expects config.json while v2 expects .dockercfg
        The only difference between them is that config.json wraps "auths" around the AuthConfig
         */
        try {
            // try registry version 2
            final ObjectNode node = filterNonAuthsFromJSON(confFile);
            Map>  configJson = MAPPER.convertValue(node, CONFIG_JSON_MAP_TYPE);
            if (configJson != null && !configJson.isEmpty()) {
                configMap = configJson.get(AUTHS_PROPERTY);
            }

        } catch (IOException e1) {
            try {
                // try registry version 1
                configMap = MAPPER.readValue(confFile, CONFIG_CFG_MAP_TYPE);
            } catch (IOException e2) {
                // pass
            }
        }

        if (configMap != null) {
            for (Map.Entry entry : configMap.entrySet()) {
                AuthConfig authConfig = entry.getValue();
                final String auth = authConfig.getAuth();
                if (auth == null) continue;

                decodeAuth(auth, authConfig);
                authConfig.withAuth(null);
                authConfig.withRegistryAddress(entry.getKey());
                configFile.addConfig(authConfig);
            }
        } else {
            List authFileContent = FileUtils.readLines(confFile);
            if (authFileContent.size() < 2) {
                throw new IOException("The Auth Config file is empty");
            }
            AuthConfig config = new AuthConfig();
            String[] origAuth = authFileContent.get(0).split(" = ");
            if (origAuth.length != 2) {
                throw new IOException("Invalid Auth config file");
            }
            decodeAuth(origAuth[1], config);

            String[] origEmail = authFileContent.get(1).split(" = ");
            if (origEmail.length != 2) {
                throw new IOException("Invalid Auth config file");
            }
            config.withEmail(origEmail[1]);
            configFile.addConfig(config);
        }
        return configFile;

    }

    private static ObjectNode filterNonAuthsFromJSON(final File confFile) throws IOException {
        final ObjectNode node = MAPPER.readValue(confFile, ObjectNode.class);
        if (!node.has(AUTHS_PROPERTY)) {
            throw new IOException("No Auth Config contained");
        }
        node.retain(AUTHS_PROPERTY);
        return node;
    }

    static void decodeAuth(String auth, AuthConfig config) throws IOException {
        String str = new String(Base64.decodeBase64(auth), Charset.forName("UTF-8"));
        String[] parts = str.split(":", 2);
        if (parts.length != 2) {
            throw new IOException("Invalid auth configuration file");
        }
        config.withUsername(parts[0]);
        config.withPassword(parts[1]);
    }

    static String convertToHostname(String server) {
        String stripped = server;
        if (server.startsWith("http://")) {
            stripped = server.substring(7);
        } else if (server.startsWith("https://")) {
            stripped = server.substring(8);
        }
        String[] numParts = stripped.split("/", 2);
        return numParts[0];
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy