1
0
mirror of https://github.com/getsops/sops.git synced 2026-02-05 12:45:21 +01:00

use common function to read password

Signed-off-by: Tomasz Duda <tomaszduda23@gmail.com>
This commit is contained in:
Tomasz Duda
2025-02-22 13:55:12 +01:00
parent 6baf3b4c75
commit 2d144cd25c
3 changed files with 15 additions and 68 deletions

View File

@@ -15,7 +15,6 @@ import (
"filippo.io/age/agessh"
"filippo.io/age/armor"
"github.com/sirupsen/logrus"
"golang.org/x/term"
gpgagent "github.com/getsops/gopgagent"
"github.com/getsops/sops/v3/logging"
@@ -370,28 +369,11 @@ func (key *MasterKey) loadIdentities() (ParsedIdentities, error) {
Passphrase: func() (string, error) {
conn, err := gpgagent.NewConn()
if err != nil {
fmt.Fprintf(os.Stderr, "Enter passphrase for identity '%s':", n)
var pass string
if term.IsTerminal(int(os.Stdout.Fd())) {
p, err = term.ReadPassword(int(os.Stdout.Fd()))
if err == nil {
pass = string(p)
}
} else {
reader := bufio.NewReader(os.Stdin)
pass, err = reader.ReadString('\n')
if err == io.EOF {
err = nil
}
}
passphrase, err := readPassphrase("Enter passphrase for identity " + n + ":")
if err != nil {
return "", fmt.Errorf("could not read passphrase: %v", err)
return "", err
}
fmt.Fprintln(os.Stderr)
return pass, nil
return string(passphrase), nil
}
defer func(conn *gpgagent.Conn) {
if err := conn.Close(); err != nil {

View File

@@ -2,7 +2,6 @@ package age
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -520,10 +519,7 @@ func TestMasterKey_Identities_Passphrase(t *testing.T) {
t.Setenv(SopsAgeKeyEnv, mockEncryptedIdentity)
//blocks calling gpg-agent
os.Unsetenv("XDG_RUNTIME_DIR")
funcDefer, _ := mockStdin(t, mockIdentityPassphrase)
defer funcDefer()
t.Setenv(SopsAgePasswordEnv, mockIdentityPassphrase)
got, err := key.Decrypt()
assert.NoError(t, err)
@@ -542,9 +538,7 @@ func TestMasterKey_Identities_Passphrase(t *testing.T) {
t.Setenv(SopsAgeKeyFileEnv, keyPath)
//blocks calling gpg-agent
os.Unsetenv("XDG_RUNTIME_DIR")
funcDefer, _ := mockStdin(t, mockIdentityPassphrase)
defer funcDefer()
t.Setenv(SopsAgePasswordEnv, mockIdentityPassphrase)
got, err := key.Decrypt()
assert.NoError(t, err)
@@ -556,9 +550,7 @@ func TestMasterKey_Identities_Passphrase(t *testing.T) {
t.Setenv(SopsAgeKeyEnv, mockEncryptedIdentity)
//blocks calling gpg-agent
os.Unsetenv("XDG_RUNTIME_DIR")
funcDefer, _ := mockStdin(t, mockIdentityPassphrase)
defer funcDefer()
t.Setenv(SopsAgePasswordEnv, mockIdentityPassphrase)
got, err := key.Decrypt()
assert.Error(t, err)
@@ -566,39 +558,3 @@ func TestMasterKey_Identities_Passphrase(t *testing.T) {
assert.Nil(t, got)
})
}
// mockStdin is a helper function that lets the test pretend dummyInput as os.Stdin.
// It will return a function for `defer` to clean up after the test.
//
// Note: `ioutil.TempFile` should be replaced to `os.CreateTemp` for Go v1.16 or higher.
func mockStdin(t *testing.T, dummyInput string) (funcDefer func(), err error) {
t.Helper()
oldOsStdin := os.Stdin
fmt.Println(t.TempDir(), t.Name())
tmpfile, err := ioutil.TempFile(t.TempDir(), strings.Replace(t.Name(), "/", "_", -1))
if err != nil {
return nil, err
}
content := []byte(dummyInput)
if _, err := tmpfile.Write(content); err != nil {
return nil, err
}
if _, err := tmpfile.Seek(0, 0); err != nil {
return nil, err
}
// Set stdin to the temp file
os.Stdin = tmpfile
return func() {
// clean up
os.Stdin = oldOsStdin
os.Remove(tmpfile.Name())
}, nil
}

View File

@@ -18,9 +18,18 @@ import (
"golang.org/x/term"
)
const (
SopsAgePasswordEnv = "SOPS_AGE_PASSWORD"
)
// readPassphrase reads a passphrase from the terminal. It does not read from a
// non-terminal stdin, so it does not check stdinInUse.
func readPassphrase(prompt string) ([]byte, error) {
password := os.Getenv(SopsAgePasswordEnv)
if password != "" {
return []byte(password), nil
}
var in, out *os.File
if runtime.GOOS == "windows" {
var err error