Skip to content
Merged
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 @@ -12,6 +12,7 @@
import org.testcontainers.DockerClientFactory;
import org.zeroturnaround.exec.InvalidResultException;
import org.zeroturnaround.exec.ProcessExecutor;
import org.zeroturnaround.exec.stream.LogOutputStream;

import java.io.ByteArrayInputStream;
import java.io.File;
Expand Down Expand Up @@ -273,7 +274,7 @@ private AuthConfig runCredentialProvider(String hostName, String helperOrStoreNa
}

final String credentialProgramName = getCredentialProgramName(helperOrStoreName);
final String data;
final CredentialOutput data;

log.debug(
"Executing docker credential provider: {} to locate auth config for: {}",
Expand All @@ -283,37 +284,38 @@ private AuthConfig runCredentialProvider(String hostName, String helperOrStoreNa

try {
data = runCredentialProgram(hostName, credentialProgramName);
} catch (InvalidResultException e) {
final String responseErrorMsg = extractCredentialProviderErrorMessage(e);

if (!StringUtils.isBlank(responseErrorMsg)) {
String credentialsNotFoundMsg = getGenericCredentialsNotFoundMsg(credentialProgramName);
if (credentialsNotFoundMsg != null && credentialsNotFoundMsg.equals(responseErrorMsg)) {
log.info(
"Credential helper/store ({}) does not have credentials for {}",
if (data.getStderr() != null && !data.getStderr().isEmpty()) {
final String responseErrorMsg = data.getStderr();

if (!StringUtils.isBlank(responseErrorMsg)) {
String credentialsNotFoundMsg = getGenericCredentialsNotFoundMsg(credentialProgramName);
if (credentialsNotFoundMsg != null && credentialsNotFoundMsg.equals(responseErrorMsg)) {
log.info(
"Credential helper/store ({}) does not have credentials for {}",
credentialProgramName,
hostName
);

return null;
}

log.debug(
"Failure running docker credential helper/store ({}) with output '{}'",
credentialProgramName,
hostName
responseErrorMsg
);

return null;
} else {
log.debug("Failure running docker credential helper/store ({})", credentialProgramName);
}

log.debug(
"Failure running docker credential helper/store ({}) with output '{}'",
credentialProgramName,
responseErrorMsg
);
} else {
log.debug("Failure running docker credential helper/store ({})", credentialProgramName);
throw new InvalidResultException(data.getStderr(), null);
}

throw e;
} catch (Exception e) {
log.debug("Failure running docker credential helper/store ({})", credentialProgramName);
throw e;
}

final JsonNode helperResponse = OBJECT_MAPPER.readTree(data);
final JsonNode helperResponse = OBJECT_MAPPER.readTree(data.getStdout());
log.debug("Credential helper/store provided auth config for: {}", hostName);

final String username = helperResponse.at("/Username").asText();
Expand Down Expand Up @@ -363,55 +365,81 @@ private String discoverCredentialsHelperNotFoundMessage(String credentialHelperN

String credentialsNotFoundMsg = null;
try {
runCredentialProgram(notExistentFakeHostName, credentialHelperName);
CredentialOutput data = runCredentialProgram(notExistentFakeHostName, credentialHelperName);

// should not reach here
log.warn(
"Failure running docker credential helper ({}) with fake call, expected 'credentials not found' response",
credentialHelperName
);
} catch (Exception e) {
if (e instanceof InvalidResultException) {
credentialsNotFoundMsg = extractCredentialProviderErrorMessage((InvalidResultException) e);
}
if (data.getStderr() != null && !data.getStderr().isEmpty()) {
credentialsNotFoundMsg = data.getStderr();

if (StringUtils.isBlank(credentialsNotFoundMsg)) {
log.warn(
"Failure running docker credential helper ({}) with fake call, expected 'credentials not found' response. Exception message: {}",
credentialHelperName,
e.getMessage()
);
} else {
log.debug(
"Got credentials not found error message from docker credential helper - {}",
credentialsNotFoundMsg
);
}
} catch (Exception e) {
log.warn(
"Failure running docker credential helper ({}) with fake call, expected 'credentials not found' response. Exception message: {}",
credentialHelperName,
e.getMessage()
);
}

return credentialsNotFoundMsg;
}

private String extractCredentialProviderErrorMessage(InvalidResultException invalidResultEx) {
if (invalidResultEx.getResult() != null && invalidResultEx.getResult().hasOutput()) {
return invalidResultEx.getResult().outputString().trim();
}
return null;
}

private String runCredentialProgram(String hostName, String credentialHelperName)
throws InvalidResultException, InterruptedException, TimeoutException, IOException {
private CredentialOutput runCredentialProgram(String hostName, String credentialHelperName)
throws InterruptedException, TimeoutException, IOException {
String[] command = SystemUtils.IS_OS_WINDOWS
? new String[] { "cmd", "/c", credentialHelperName, "get" }
: new String[] { credentialHelperName, "get" };
return new ProcessExecutor()
.command(command)
.redirectInput(new ByteArrayInputStream(hostName.getBytes()))
.readOutput(true)
.exitValueNormal()
.timeout(30, TimeUnit.SECONDS)
.execute()
.outputUTF8()
.trim();

StringBuffer stdout = new StringBuffer();
StringBuffer stderr = new StringBuffer();

try {
new ProcessExecutor()
.command(command)
.redirectInput(new ByteArrayInputStream(hostName.getBytes()))
.redirectOutput(
new LogOutputStream() {
@Override
protected void processLine(String line) {
stdout.append(line).append(System.lineSeparator());
}
}
)
.redirectError(
new LogOutputStream() {
@Override
protected void processLine(String line) {
stderr.append(line).append(System.lineSeparator());
}
}
)
.exitValueNormal()
.timeout(30, TimeUnit.SECONDS)
.execute();
} catch (InvalidResultException e) {}

return new CredentialOutput(stdout.toString(), stderr.toString());
}

static class CredentialOutput {

private final String stdout;

private final String stderr;

public CredentialOutput(String stdout, String stderr) {
this.stdout = stdout.trim();
this.stderr = stderr.trim();
}

public String getStdout() {
return this.stdout;
}

public String getStderr() {
return this.stderr;
}
}
}