69 lines
1.8 KiB
Go
69 lines
1.8 KiB
Go
|
|
package cmd
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"io"
|
||
|
|
"os"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
"github.com/spf13/cobra"
|
||
|
|
"golang.org/x/term"
|
||
|
|
)
|
||
|
|
|
||
|
|
// readSecretValue resolves the value for a secret/token flag from, in order:
|
||
|
|
// 1. --body (inline; visible in shell history)
|
||
|
|
// 2. --body-file (file path, or "-" for stdin)
|
||
|
|
// 3. interactive TTY prompt (hidden)
|
||
|
|
// 4. piped stdin
|
||
|
|
//
|
||
|
|
// Trailing whitespace (including the final newline common in heredocs and
|
||
|
|
// `echo ... | fgj ...`) is trimmed. An empty resolved value is rejected so we
|
||
|
|
// never silently write an empty secret.
|
||
|
|
func readSecretValue(cmd *cobra.Command, label string) (string, error) {
|
||
|
|
if v, _ := cmd.Flags().GetString("body"); v != "" {
|
||
|
|
return strings.TrimRight(v, "\r\n"), nil
|
||
|
|
}
|
||
|
|
|
||
|
|
if path, _ := cmd.Flags().GetString("body-file"); path != "" {
|
||
|
|
var raw []byte
|
||
|
|
var err error
|
||
|
|
if path == "-" {
|
||
|
|
raw, err = io.ReadAll(ios.In)
|
||
|
|
} else {
|
||
|
|
raw, err = os.ReadFile(path)
|
||
|
|
}
|
||
|
|
if err != nil {
|
||
|
|
return "", fmt.Errorf("failed to read secret from %q: %w", path, err)
|
||
|
|
}
|
||
|
|
value := strings.TrimRight(string(raw), "\r\n")
|
||
|
|
if value == "" {
|
||
|
|
return "", fmt.Errorf("secret value from %q is empty", path)
|
||
|
|
}
|
||
|
|
return value, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
if ios.IsStdinTTY() {
|
||
|
|
fmt.Fprintf(ios.ErrOut, "Value for %s: ", label)
|
||
|
|
pw, err := term.ReadPassword(int(os.Stdin.Fd()))
|
||
|
|
fmt.Fprintln(ios.ErrOut)
|
||
|
|
if err != nil {
|
||
|
|
return "", fmt.Errorf("failed to read secret: %w", err)
|
||
|
|
}
|
||
|
|
value := strings.TrimRight(string(pw), "\r\n")
|
||
|
|
if value == "" {
|
||
|
|
return "", fmt.Errorf("secret value is empty")
|
||
|
|
}
|
||
|
|
return value, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
raw, err := io.ReadAll(ios.In)
|
||
|
|
if err != nil {
|
||
|
|
return "", fmt.Errorf("failed to read secret from stdin: %w", err)
|
||
|
|
}
|
||
|
|
value := strings.TrimRight(string(raw), "\r\n")
|
||
|
|
if value == "" {
|
||
|
|
return "", fmt.Errorf("secret value from stdin is empty")
|
||
|
|
}
|
||
|
|
return value, nil
|
||
|
|
}
|