Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for username and password tokens in dockercfg auth #3365

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"
}
}
}