Skip to content

Commit

Permalink
Added support for username and password tokens in dockercfg auth
Browse files Browse the repository at this point in the history
  • Loading branch information
tpokki committed Aug 2, 2021
1 parent dfd4efa commit 479a5df
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -140,25 +140,34 @@ Optional<Credential> retrieve(DockerConfig dockerConfig, Consumer<LogEvent> logg

// Lastly, find defined auth.
AuthTemplate auth = dockerConfig.getAuthFor(registryAlias);
if (auth != null && auth.getAuth() != null) {
// 'auth' is a basic authentication token that should be parsed back into credentials
String usernameColonPassword =
new String(Base64.decodeBase64(auth.getAuth()), StandardCharsets.UTF_8);
String username = usernameColonPassword.substring(0, usernameColonPassword.indexOf(":"));
String password = usernameColonPassword.substring(usernameColonPassword.indexOf(":") + 1);
logger.accept(
LogEvent.info("Docker config auths section defines credentials for " + registryAlias));
if (auth.getIdentityToken() != null
// These username and password checks may be unnecessary, but doing so to restrict the
// scope only to the Azure behavior to maintain maximum backward-compatibilty.
&& username.equals("00000000-0000-0000-0000-000000000000")
&& password.isEmpty()) {
if (auth != null) {
if (auth.getAuth() != null) {
// 'auth' is a basic authentication token that should be parsed back into credentials
String usernameColonPassword =
new String(Base64.decodeBase64(auth.getAuth()), StandardCharsets.UTF_8);
String username = usernameColonPassword.substring(0, usernameColonPassword.indexOf(":"));
String password = usernameColonPassword.substring(usernameColonPassword.indexOf(":") + 1);
logger.accept(
LogEvent.info("Using 'identityToken' in Docker config auth for " + registryAlias));
return Optional.of(
Credential.from(Credential.OAUTH2_TOKEN_USER_NAME, auth.getIdentityToken()));
LogEvent.info(
"Docker config auths section defines credentials for " + registryAlias));
if (auth.getIdentityToken() != null
// These username and password checks may be unnecessary, but doing so to restrict the
// scope only to the Azure behavior to maintain maximum backward-compatibilty.
&& username.equals("00000000-0000-0000-0000-000000000000")
&& password.isEmpty()) {
logger.accept(
LogEvent.info("Using 'identityToken' in Docker config auth for " + registryAlias));
return Optional.of(
Credential.from(Credential.OAUTH2_TOKEN_USER_NAME, auth.getIdentityToken()));
}
return Optional.of(Credential.from(username, password));
} else if (auth.getUsername() != null && auth.getPassword() != null) {
logger.accept(
LogEvent.info(
"Docker config auths section defines username and password for "
+ registryAlias));
return Optional.of(Credential.from(auth.getUsername(), auth.getPassword()));
}
return Optional.of(Credential.from(username, password));
}
}
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
* "auths": {
* "registry": {
* "auth": "username:password string in base64",
* "username": "..."
* "password": "..."
* "identityToken": "..."
* },
* "anotherregistry": {},
Expand Down Expand Up @@ -66,6 +68,10 @@ public static class AuthTemplate implements JsonTemplate {

@Nullable private String auth;

@Nullable private String username;

@Nullable private String password;

// Both "identitytoken" and "identityToken" have been observed. For example,
// https://github.com/GoogleContainerTools/jib/issues/2488
// https://github.com/spotify/docker-client/issues/580
Expand All @@ -76,6 +82,16 @@ public String getAuth() {
return auth;
}

@Nullable
public String getUsername() {
return username;
}

@Nullable
public String getPassword() {
return password;
}

@Nullable
public String getIdentityToken() {
return identityToken;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,36 @@ public void testRetrieve_hasAuth() throws IOException {
"Docker config auths section defines credentials for some other registry"));
}

@Test
public void testRetrieve_authTakesPrecedenceOverUsernameAndPassword() throws IOException {
DockerConfigCredentialRetriever dockerConfigCredentialRetriever =
DockerConfigCredentialRetriever.create("auth and userpw registry", dockerConfigFile);

Optional<Credential> credentials = dockerConfigCredentialRetriever.retrieve(mockLogger);
Assert.assertTrue(credentials.isPresent());
Assert.assertEquals("some", credentials.get().getUsername());
Assert.assertEquals("auth", credentials.get().getPassword());
Mockito.verify(mockLogger)
.accept(
LogEvent.info(
"Docker config auths section defines credentials for auth and userpw registry"));
}

@Test
public void testRetrieve_hasAuthWithUsernameAndPassword() throws IOException {
DockerConfigCredentialRetriever dockerConfigCredentialRetriever =
DockerConfigCredentialRetriever.create("userpw registry", dockerConfigFile);

Optional<Credential> credentials = dockerConfigCredentialRetriever.retrieve(mockLogger);
Assert.assertTrue(credentials.isPresent());
Assert.assertEquals("someuser", credentials.get().getUsername());
Assert.assertEquals("somepw", credentials.get().getPassword());
Mockito.verify(mockLogger)
.accept(
LogEvent.info(
"Docker config auths section defines username and password for userpw registry"));
}

@Test
public void testRetrieve_hasAuth_legacyConfigFormat() throws IOException, URISyntaxException {
dockerConfigFile = Paths.get(Resources.getResource("core/json/legacy_dockercfg").toURI());
Expand Down
4 changes: 3 additions & 1 deletion jib-core/src/test/resources/core/json/dockerconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
"auths":{
"some other registry":{"auth":"c29tZTpvdGhlcjphdXRo"},
"some registry":{"auth":"c29tZTphdXRo","password":"ignored"},
"auth and userpw registry":{"auth":"c29tZTphdXRo","username":"ignored","password":"ignored"},
"userpw registry":{"username":"someuser","password":"somepw"},
"https://registry":{"auth":"dG9rZW4="},

"example.com":{"auth":"should not match example"},
Expand All @@ -21,4 +23,4 @@

"another.example.com.in.helpers":"should not match example"
}
}
}

0 comments on commit 479a5df

Please sign in to comment.