/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.docker.client;
import com.google.inject.Inject;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.commons.json.JsonHelper;
import org.eclipse.che.plugin.docker.client.dto.AuthConfig;
import org.eclipse.che.plugin.docker.client.dto.AuthConfigs;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import static com.google.common.collect.Sets.newHashSet;
/**
* Class for preparing auth header value for docker registry.
*
* @author Mykola Morhun
*/
public class DockerRegistryAuthResolver {
public static final Set<String> DEFAULT_REGISTRY_SYNONYMS = Collections.unmodifiableSet(newHashSet(null,
"",
"docker.io",
"index.docker.io",
"https://index.docker.io",
"https://index.docker.io/v1",
"https://index.docker.io/v1/"));
public static final String DEFAULT_REGISTRY = "https://index.docker.io/v1/";
private final InitialAuthConfig initialAuthConfig;
private final DockerRegistryDynamicAuthResolver dynamicAuthResolver;
@Inject
public DockerRegistryAuthResolver(InitialAuthConfig initialAuthConfig,
DockerRegistryDynamicAuthResolver dynamicAuthResolver) {
this.initialAuthConfig = initialAuthConfig;
this.dynamicAuthResolver = dynamicAuthResolver;
}
/**
* Looks for auth credentials for specified registry and encode it in base64.
* First searches in the passed params and then in the configured credentials.
* If nothing found, empty encoded json will be returned.
*
* @param registry
* registry to which API call will be applied
* @param paramAuthConfigs
* credentials for provided registry
* @return base64 encoded X-Registry-Auth header value
*/
public String getXRegistryAuthHeaderValue(@Nullable String registry, @Nullable AuthConfigs paramAuthConfigs) {
AuthConfig authConfig = getAuthConfigForRegistry(registry, paramAuthConfigs);
String authConfigJson;
if (authConfig == null) {
// empty auth config
authConfigJson = "{}";
} else {
authConfigJson = JsonHelper.toJson(authConfig);
}
return Base64.getEncoder().encodeToString(authConfigJson.getBytes());
}
/**
* Builds list of auth configs.
* Adds auth configs from current API call and from initial auth config.
*
* @param paramAuthConfigs
* auth header values for provided registry
* @return base64 encoded X-Registry-Config header value
*/
public String getXRegistryConfigHeaderValue(@Nullable AuthConfigs paramAuthConfigs) {
Map<String, AuthConfig> authConfigs = new HashMap<>();
authConfigs.putAll(initialAuthConfig.getAuthConfigs().getConfigs());
if (paramAuthConfigs != null && paramAuthConfigs.getConfigs() != null) {
authConfigs.putAll(paramAuthConfigs.getConfigs());
}
authConfigs.putAll(dynamicAuthResolver.getXRegistryConfig());
authConfigs = normalizeDockerHubRegistryUrl(authConfigs);
return Base64.getEncoder().encodeToString(JsonHelper.toJson(authConfigs).getBytes());
}
/**
* Returns authorization header value for basic auth method for given registry.
* If registry is not configured empty string will be returned.
*
* @param registry
* registry to which auth config should be found
* @param paramAuthConfigs
* additional auth configs per this request
* @return authorization header value for basic auth method or empty string if registry isn't configured
*/
public String getBasicAuthHeaderValue(@Nullable String registry, @Nullable AuthConfigs paramAuthConfigs) {
AuthConfig authConfig = getAuthConfigForRegistry(registry, paramAuthConfigs);
if (authConfig != null) {
return "Basic " + Base64.getEncoder().encodeToString((authConfig.getUsername() + ':' + authConfig.getPassword()).getBytes());
}
return "";
}
/**
* Looks for auth configuration for given registry.
* If given registry is not configured then null will be returned.
*
* @param registry
* registry to which auth config should be found
* @param paramAuthConfigs
* additional auth configs
* @return auth config for given registry or null is it isn't configured
*/
private AuthConfig getAuthConfigForRegistry(@Nullable String registry, @Nullable AuthConfigs paramAuthConfigs) {
String normalizedRegistry = DEFAULT_REGISTRY_SYNONYMS.contains(registry) ? DEFAULT_REGISTRY : registry;
AuthConfig authConfig = null;
if (paramAuthConfigs != null && paramAuthConfigs.getConfigs() != null) {
authConfig = normalizeDockerHubRegistryUrl(paramAuthConfigs.getConfigs()).get(normalizedRegistry);
}
if (authConfig == null) {
authConfig = normalizeDockerHubRegistryUrl(initialAuthConfig.getAuthConfigs().getConfigs()).get(normalizedRegistry);
}
if (authConfig == null) {
authConfig = dynamicAuthResolver.getXRegistryAuth(registry);
}
return authConfig;
}
private Map<String, AuthConfig> normalizeDockerHubRegistryUrl(Map<String, AuthConfig> authConfigs) {
for (String defaultRegistryAlias : DEFAULT_REGISTRY_SYNONYMS) {
if (authConfigs.containsKey(defaultRegistryAlias)) {
Map<String, AuthConfig> normalizedAuthConfigMap = new HashMap<>(authConfigs);
normalizedAuthConfigMap.put(DEFAULT_REGISTRY, normalizedAuthConfigMap.remove(defaultRegistryAlias));
return normalizedAuthConfigMap;
}
}
return authConfigs;
}
}