Skip to content

Commit

Permalink
Fix docker credentials output (#9544)
Browse files Browse the repository at this point in the history
In #8007, docker credentials stdout and stderr are separated and
stderr has been used to display error messages. However, docker
credentials writes error messages to stdout. This commit, read the
process execution exit value for better handling and read stdout
for error messages.

Fixes #9478
  • Loading branch information
eddumelendez authored Nov 19, 2024
1 parent c01fc1b commit 964c6e6
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 37 deletions.
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.ProcessResult;
import org.zeroturnaround.exec.stream.LogOutputStream;

import java.io.ByteArrayInputStream;
Expand Down Expand Up @@ -284,8 +285,8 @@ private AuthConfig runCredentialProvider(String hostName, String helperOrStoreNa

try {
data = runCredentialProgram(hostName, credentialProgramName);
if (data.getStderr() != null && !data.getStderr().isEmpty()) {
final String responseErrorMsg = data.getStderr();
if (data.getExitValue() == 1) {
final String responseErrorMsg = data.getStdout();

if (!StringUtils.isBlank(responseErrorMsg)) {
String credentialsNotFoundMsg = getGenericCredentialsNotFoundMsg(credentialProgramName);
Expand All @@ -300,15 +301,16 @@ private AuthConfig runCredentialProvider(String hostName, String helperOrStoreNa
}

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

throw new InvalidResultException(data.getStderr(), null);
throw new InvalidResultException(data.getStdout(), null);
}
} catch (Exception e) {
log.debug("Failure running docker credential helper/store ({})", credentialProgramName);
Expand Down Expand Up @@ -367,8 +369,8 @@ private String discoverCredentialsHelperNotFoundMessage(String credentialHelperN
try {
CredentialOutput data = runCredentialProgram(notExistentFakeHostName, credentialHelperName);

if (data.getStderr() != null && !data.getStderr().isEmpty()) {
credentialsNotFoundMsg = data.getStderr();
if (data.getStdout() != null && !data.getStdout().isEmpty()) {
credentialsNotFoundMsg = data.getStdout();

log.debug(
"Got credentials not found error message from docker credential helper - {}",
Expand All @@ -395,50 +397,55 @@ private CredentialOutput runCredentialProgram(String hostName, String credential
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());
}
ProcessResult processResult = 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());
}
}
)
.redirectError(
new LogOutputStream() {
@Override
protected void processLine(String line) {
stderr.append(line).append(System.lineSeparator());
}
)
.exitValueNormal()
.timeout(30, TimeUnit.SECONDS)
.execute();
} catch (InvalidResultException e) {}
}
)
.timeout(30, TimeUnit.SECONDS)
.execute();
int exitValue = processResult.getExitValue();

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

static class CredentialOutput {

private final int exitValue;

private final String stdout;

private final String stderr;

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

public String getStdout() {
int getExitValue() {
return this.exitValue;
}

String getStdout() {
return this.stdout;
}

public String getStderr() {
String getStderr() {
return this.stderr;
}
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/test/resources/auth-config/docker-credential-fake
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ fi
read inputLine

if [ "$inputLine" = "registry2.example.com" ]; then
echo Fake credentials not found on credentials store \'$inputLine\' 1>&2
echo Fake credentials not found on credentials store \'$inputLine\' 0>&2
exit 1
fi
if [ "$inputLine" = "https://not.a.real.registry/url" ]; then
echo Fake credentials not found on credentials store \'$inputLine\' 1>&2
echo Fake credentials not found on credentials store \'$inputLine\' 0>&2
exit 1
fi

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ if not "%1" == "get" (
set /p inputLine=""

if "%inputLine%" == "registry2.example.com" (
echo Fake credentials not found on credentials store '%inputLine%' 1>&2
echo Fake credentials not found on credentials store '%inputLine%' 0>&2
exit 1
)
if "%inputLine%" == "https://not.a.real.registry/url" (
echo Fake credentials not found on credentials store '%inputLine%' 1>&2
echo Fake credentials not found on credentials store '%inputLine%' 0>&2
exit 1
)

Expand Down

0 comments on commit 964c6e6

Please sign in to comment.