Skip to content

Commit 4a96b1c

Browse files
committed
age: include stderr when identity commands fail
Signed-off-by: Anthony Marquez <armarquez@gmail.com>
1 parent 86bc0b0 commit 4a96b1c

2 files changed

Lines changed: 67 additions & 0 deletions

File tree

‎age/command_test.go‎

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package age
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"os"
7+
"os/exec"
8+
"path/filepath"
9+
"strings"
10+
"testing"
11+
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
14+
)
15+
16+
func TestGetOutputFromCmd(t *testing.T) {
17+
const diagnostic = "cannot connect to 1Password app, make sure it is running"
18+
const secret = "disposable-key-output"
19+
tests := []struct {
20+
name string
21+
stderr string
22+
exitCode int
23+
wantSuffix string
24+
}{
25+
{"failure with stderr", diagnostic, 7, ": " + diagnostic},
26+
{"failure without stderr", "", 7, "exit status 7"},
27+
{"failure with whitespace stderr", " \n\t ", 7, "exit status 7"},
28+
{"failure with padded stderr", "\n" + diagnostic + "\n", 7, ": " + diagnostic},
29+
{"success without stderr", "", 0, ""},
30+
{"success with stderr", diagnostic, 0, ""},
31+
}
32+
for _, tt := range tests {
33+
t.Run(tt.name, func(t *testing.T) {
34+
script := filepath.Join(t.TempDir(), "key-command.sh")
35+
contents := fmt.Sprintf(
36+
"#!/bin/bash\nset -euo pipefail\n"+
37+
"printf '%%s' \"$TEST_KEY\"\nprintf '%%s' \"$TEST_ERROR\" >&2\nexit %d\n",
38+
tt.exitCode,
39+
)
40+
require.NoError(t, os.WriteFile(script, []byte(contents), 0o600))
41+
out, err := getOutputFromCmd(fmt.Sprintf("bash %q", script), []string{
42+
"TEST_KEY=" + secret,
43+
"TEST_ERROR=" + tt.stderr,
44+
})
45+
if tt.exitCode == 0 {
46+
require.NoError(t, err)
47+
assert.Equal(t, secret, string(out))
48+
return
49+
}
50+
require.Error(t, err)
51+
assert.Nil(t, out)
52+
assert.NotContains(t, err.Error(), secret)
53+
assert.Contains(t, err.Error(), "failed to execute command")
54+
assert.True(t, strings.HasSuffix(err.Error(), tt.wantSuffix), err.Error())
55+
var exitError *exec.ExitError
56+
require.True(t, errors.As(err, &exitError))
57+
assert.Equal(t, tt.exitCode, exitError.ExitCode())
58+
})
59+
}
60+
}

‎age/keysource.go‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,13 @@ func getOutputFromCmd(cmdString string, envVars []string) ([]byte, error) {
310310
}
311311
out, err = cmd.Output()
312312
if err != nil {
313+
var exitError *exec.ExitError
314+
if errors.As(err, &exitError) {
315+
stderr := bytes.TrimSpace(exitError.Stderr)
316+
if len(stderr) > 0 {
317+
return nil, fmt.Errorf("failed to execute command %s: %w: %s", cmdString, err, stderr)
318+
}
319+
}
313320
return nil, fmt.Errorf("failed to execute command %s: %w", cmdString, err)
314321
}
315322

0 commit comments

Comments
 (0)