Skip to content

Commit

Permalink
Merge branch 'master' into pr/issue1197
Browse files Browse the repository at this point in the history
  • Loading branch information
rhuss authored Nov 21, 2019
2 parents 0f61b9c + 7add10f commit 18bedb5
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 50 deletions.
9 changes: 5 additions & 4 deletions doc/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
- Allow merging of image configurations using <imagesMap> ([#360](https://github.com/fabric8io/docker-maven-plugin/issues/360))
- Update to joda-time 2.10.4 (#706)
- Add docker:build support for 'network' option #1030
- Treat bridged and default network mode the same #1234
- Fix NPE when cacheFrom is missing from config #1274
- Fix healthy option regression introduced in 0.25.0 #1279
- Failure referencing a previous staged image in FROM clause #1264
- Treat bridged and default network mode the same (#1234)
- Fix NPE when cacheFrom is missing from config (#1274)
- Fix healthy option regression introduced in 0.25.0 (#1279)
- Deprecated "authToken" for ECR authentication in favor of "auth" (#1286)

* **0.31.0** (2019-08-10)
- Fix test cases on Windows ([#1220](https://github.com/fabric8io/docker-maven-plugin/issues/1220))
Expand Down Expand Up @@ -184,7 +185,7 @@ Please note that now filtering in an external Dockerfiles is switched on by defa
- Allow multi line matches in log output ([#628](https://github.com/fabric8io/docker-maven-plugin/issues/628))
- Add a wait condition on a healthcheck when starting up containers ([#719](https://github.com/fabric8io/docker-maven-plugin/issues/719))
- Don't use authentication from config when no "auth" is set ([#731](https://github.com/fabric8io/docker-maven-plugin/issues/731))

* **0.20.0** (2017-02-17)
- Removed `build-nofork` and `source-nofork` in favor for a more direct solution which prevents forking of the lifecycle. Please refer the documentation, chapter "Assembly" for more information about this.

Expand Down
2 changes: 1 addition & 1 deletion src/main/asciidoc/inc/_authentication.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ Note that for an ECR repository with URI `123456789012.dkr.ecr.eu-west-1.amazona
You can use any IAM access key with the necessary permissions in any of the locations mentioned above except `~/.docker/config.json`.
Use the IAM *Access key ID* as the username and the *Secret access key* as the password.
In case you're using temporary security credentials provided by the AWS Security Token Service (AWS STS), you have to provide the *security token* as well.
To do so, either specify the `docker.authToken` system property or provide an `<auth>` element alongside username & password in the `authConfig`.
To do so, either specify the `docker.auth` system property or provide an `<auth>` element alongside username & password in the `authConfig`.

In case you are running on an EC2 instance OR ECS with fargate deployment (OR ECS with EC2 with ECS_AWSVPC_BLOCK_IMDS as "true") that has an appropriate IAM role assigned
(e.g. a role that grants the AWS built-in policy _AmazonEC2ContainerRegistryPowerUser_)
Expand Down
26 changes: 16 additions & 10 deletions src/main/java/io/fabric8/maven/docker/access/AuthConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ public class AuthConfig {

public final static AuthConfig EMPTY_AUTH_CONFIG = new AuthConfig("", "", "", "");

public static final String AUTH_USERNAME = "username";
public static final String AUTH_PASSWORD = "password";
public static final String AUTH_EMAIL = "email";
public static final String AUTH_AUTH = "auth";
public static final String AUTH_IDENTITY_TOKEN = "identityToken";

private final String username;
private final String password;
private final String email;
Expand All @@ -27,11 +33,11 @@ public class AuthConfig {
private final String authEncoded;

public AuthConfig(Map<String,String> params) {
this(params.get("username"),
params.get("password"),
params.get("email"),
params.get("auth"),
params.get("identityToken"));
this(params.get(AUTH_USERNAME),
params.get(AUTH_PASSWORD),
params.get(AUTH_EMAIL),
params.get(AUTH_AUTH),
params.get(AUTH_IDENTITY_TOKEN));
}

public AuthConfig(String username, String password, String email, String auth) {
Expand Down Expand Up @@ -99,12 +105,12 @@ public String toHeaderValue() {
private String createAuthEncoded() {
JsonObject ret = new JsonObject();
if(identityToken != null) {
putNonNull(ret, "identitytoken", identityToken);
putNonNull(ret, AUTH_IDENTITY_TOKEN, identityToken);
} else {
putNonNull(ret, "username", username);
putNonNull(ret, "password", password);
putNonNull(ret, "email", email);
putNonNull(ret, "auth", auth);
putNonNull(ret, AUTH_USERNAME, username);
putNonNull(ret, AUTH_PASSWORD, password);
putNonNull(ret, AUTH_EMAIL, email);
putNonNull(ret, AUTH_AUTH, auth);
}

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import java.util.Map;
import java.util.TreeMap;

import io.fabric8.maven.docker.util.AuthConfigFactory;
import io.fabric8.maven.docker.access.AuthConfig;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugins.annotations.Parameter;

Expand All @@ -26,8 +26,12 @@ public class RegistryAuthConfiguration implements Serializable {
private String email;

@Parameter
@Deprecated
private String authToken;

@Parameter
private String auth;

public Map toMap() {
final Map authMap = new TreeMap<>();

Expand All @@ -38,16 +42,26 @@ public Map toMap() {
authMap.put("pull", pull);
}
if (StringUtils.isNotBlank(username)) {
authMap.put(AuthConfigFactory.AUTH_USERNAME, username);
authMap.put(AuthConfig.AUTH_USERNAME, username);
}
if (StringUtils.isNotBlank(password)) {
authMap.put(AuthConfigFactory.AUTH_PASSWORD, password);
authMap.put(AuthConfig.AUTH_PASSWORD, password);
}

if (StringUtils.isNotBlank(authToken) && StringUtils.isNotBlank(auth)) {
throw new IllegalStateException("For a registry configuration either 'auth' or 'authToken' (deprecated) can be specified but not both. Use only 'auth' and remove 'authToken' in the registry configuration");
}

if (StringUtils.isNotBlank(authToken)) {
authMap.put(AuthConfigFactory.AUTH_AUTHTOKEN, authToken);
authMap.put(AuthConfig.AUTH_AUTH, authToken);
}

if (StringUtils.isNotBlank(auth)) {
authMap.put(AuthConfig.AUTH_AUTH, auth);
}

if (StringUtils.isNotBlank(email)) {
authMap.put(AuthConfigFactory.AUTH_EMAIL,email);
authMap.put(AuthConfig.AUTH_EMAIL, email);
}
return authMap;
}
Expand Down
45 changes: 22 additions & 23 deletions src/main/java/io/fabric8/maven/docker/util/AuthConfigFactory.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
package io.fabric8.maven.docker.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import com.google.gson.JsonObject;

import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
Expand Down Expand Up @@ -38,7 +34,6 @@

import com.google.common.net.UrlEscapers;
import com.google.gson.Gson;
import com.google.gson.JsonObject;

import io.fabric8.maven.docker.access.AuthConfig;
import io.fabric8.maven.docker.access.ecr.EcrExtendedAuth;
Expand All @@ -51,12 +46,7 @@
*/
public class AuthConfigFactory {

// Properties for specifying username, password (can be encrypted), email and authtoken (not used yet)
// + whether to check for OpenShift authentication
public static final String AUTH_USERNAME = "username";
public static final String AUTH_PASSWORD = "password";
public static final String AUTH_EMAIL = "email";
public static final String AUTH_AUTHTOKEN = "authToken";
// Whether to check for OpenShift authentication
private static final String AUTH_USE_OPENSHIFT_AUTH = "useOpenShiftAuth";

static final String DOCKER_LOGIN_DEFAULT_REGISTRY = "https://index.docker.io/v1/";
Expand Down Expand Up @@ -371,21 +361,30 @@ private AuthConfig getAuthConfigFromECSTaskRole() throws IOException {

private AuthConfig getAuthConfigFromSystemProperties(LookupMode lookupMode) throws MojoExecutionException {
Properties props = System.getProperties();
String userKey = lookupMode.asSysProperty(AUTH_USERNAME);
String passwordKey = lookupMode.asSysProperty(AUTH_PASSWORD);
String userKey = lookupMode.asSysProperty(AuthConfig.AUTH_USERNAME);
String passwordKey = lookupMode.asSysProperty(AuthConfig.AUTH_PASSWORD);
if (props.containsKey(userKey)) {
if (!props.containsKey(passwordKey)) {
throw new MojoExecutionException("No " + passwordKey + " provided for username " + props.getProperty(userKey));
}
return new AuthConfig(props.getProperty(userKey),
decrypt(props.getProperty(passwordKey)),
props.getProperty(lookupMode.asSysProperty(AUTH_EMAIL)),
props.getProperty(lookupMode.asSysProperty(AUTH_AUTHTOKEN)));
props.getProperty(lookupMode.asSysProperty(AuthConfig.AUTH_EMAIL)),
getAuthProperty(props, lookupMode));
} else {
return null;
}
}

private String getAuthProperty(Properties props, LookupMode lookupMode) {
String authProp = props.getProperty(lookupMode.asSysProperty(AuthConfig.AUTH_AUTH));
if (authProp != null) {
return authProp;
}
// Fallback is deprecated AUTH_AUTHTOKEN property
return props.getProperty(lookupMode.asSysProperty("authToken"));
}

private AuthConfig getAuthConfigFromOpenShiftConfig(LookupMode lookupMode, Map authConfigMap) throws MojoExecutionException {
Properties props = System.getProperties();
String useOpenAuthModeProp = lookupMode.asSysProperty(AUTH_USE_OPENSHIFT_AUTH);
Expand All @@ -412,12 +411,12 @@ private AuthConfig getAuthConfigFromOpenShiftConfig(LookupMode lookupMode, Map a
private AuthConfig getAuthConfigFromPluginConfiguration(LookupMode lookupMode, Map authConfig) throws MojoExecutionException {
Map mapToCheck = getAuthConfigMapToCheck(lookupMode,authConfig);

if (mapToCheck != null && mapToCheck.containsKey(AUTH_USERNAME)) {
if (!mapToCheck.containsKey(AUTH_PASSWORD)) {
if (mapToCheck != null && mapToCheck.containsKey(AuthConfig.AUTH_USERNAME)) {
if (!mapToCheck.containsKey(AuthConfig.AUTH_PASSWORD)) {
throw new MojoExecutionException("No 'password' given while using <authConfig> in configuration for mode " + lookupMode);
}
Map<String, String> cloneConfig = new HashMap<>(mapToCheck);
cloneConfig.put(AUTH_PASSWORD, decrypt(cloneConfig.get(AUTH_PASSWORD)));
cloneConfig.put(AuthConfig.AUTH_PASSWORD, decrypt(cloneConfig.get(AuthConfig.AUTH_PASSWORD)));
return new AuthConfig(cloneConfig);
} else {
return null;
Expand Down Expand Up @@ -463,20 +462,20 @@ private AuthConfig getAuthConfigFromDockerConfig(String registry) throws MojoExe
}

if (dockerConfig.has("auths")) {
return extractAuthConfigFromAuths(registryToLookup, dockerConfig.getAsJsonObject("auths"));
return extractAuthConfigFromDockerConfigAuths(registryToLookup, dockerConfig.getAsJsonObject("auths"));
}

return null;
}

private AuthConfig extractAuthConfigFromAuths(String registryToLookup, JsonObject auths) {
private AuthConfig extractAuthConfigFromDockerConfigAuths(String registryToLookup, JsonObject auths) {
JsonObject credentials = getCredentialsNode(auths,registryToLookup);
if (credentials == null || !credentials.has("auth")) {
return null;
}
String auth = credentials.get("auth").getAsString();
String identityToken = credentials.has("identitytoken") ? credentials.get("identitytoken").getAsString() : null;
String email = credentials.has(AUTH_EMAIL) && !credentials.get(AUTH_EMAIL).isJsonNull() ? credentials.get(AUTH_EMAIL).getAsString() : null;
String email = credentials.has(AuthConfig.AUTH_EMAIL) && !credentials.get(AuthConfig.AUTH_EMAIL).isJsonNull() ? credentials.get(AuthConfig.AUTH_EMAIL).getAsString() : null;
return new AuthConfig(auth, email, identityToken);
}

Expand Down Expand Up @@ -613,8 +612,8 @@ private AuthConfig createAuthConfigFromServer(Server server) throws MojoExecutio
return new AuthConfig(
server.getUsername(),
decrypt(server.getPassword()),
extractFromServerConfiguration(server.getConfiguration(), AUTH_EMAIL),
extractFromServerConfiguration(server.getConfiguration(), "auth")
extractFromServerConfiguration(server.getConfiguration(), AuthConfig.AUTH_EMAIL),
extractFromServerConfiguration(server.getConfiguration(), AuthConfig.AUTH_AUTH)
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package io.fabric8.maven.docker.config;

import java.lang.reflect.Field;
import java.util.Map;

import org.junit.Test;
import static org.junit.Assert.*;

public class RegistryAuthConfigurationTest {

@Test
public void deprecatedAuthTokenTest() throws ReflectiveOperationException {
RegistryAuthConfiguration config = new RegistryAuthConfiguration();
setField(config, "authToken", "foo");
Map map = config.toMap();
assertNull(map.get("authToken"));
assertEquals("foo", map.get("auth"));
}

@Test
public void invalidAuthTokenConfigTest() throws ReflectiveOperationException {
RegistryAuthConfiguration config = new RegistryAuthConfiguration();
setField(config, "authToken", "foo");
setField(config, "auth", "bar");
try {
config.toMap();
fail("Should throw an exception because both 'auth' and 'authToken' is specified");
} catch (IllegalStateException exp) {

}
}

@Test
public void authTest() throws ReflectiveOperationException {
RegistryAuthConfiguration config = new RegistryAuthConfiguration();
setField(config, "auth", "bar");
Map map = config.toMap();
assertNull(map.get("authToken"));
assertEquals("bar", map.get("auth"));
}


private void setField(Object obj, String name, Object value) throws ReflectiveOperationException {
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}
}
14 changes: 7 additions & 7 deletions src/test/java/io/fabric8/maven/docker/util/AuthConfigTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ public class AuthConfigTest {
@Test
public void simpleConstructor() {
Map<String,String> map = new HashMap<String,String>();
map.put("username","roland");
map.put("password","#>secrets??");
map.put("email","roland@jolokia.org");
map.put(AuthConfig.AUTH_USERNAME,"roland");
map.put(AuthConfig.AUTH_PASSWORD,"#>secrets??");
map.put(AuthConfig.AUTH_EMAIL,"roland@jolokia.org");
AuthConfig config = new AuthConfig(map);
check(config);
}
Expand Down Expand Up @@ -53,9 +53,9 @@ private void check(AuthConfig config) {
String header = new String(Base64.decodeBase64(config.toHeaderValue()));

JsonObject data = JsonFactory.newJsonObject(header);
assertEquals("roland",data.get("username").getAsString());
assertEquals("#>secrets??",data.get("password").getAsString());
assertEquals("roland@jolokia.org",data.get("email").getAsString());
assertFalse(data.has("auth"));
assertEquals("roland",data.get(AuthConfig.AUTH_USERNAME).getAsString());
assertEquals("#>secrets??",data.get(AuthConfig.AUTH_PASSWORD).getAsString());
assertEquals("roland@jolokia.org",data.get(AuthConfig.AUTH_EMAIL).getAsString());
assertFalse(data.has(AuthConfig.AUTH_AUTH));
}
}

0 comments on commit 18bedb5

Please sign in to comment.