wip snapshot after account logout; squash into the unit commit
check / check (push) Waiting to run

Model: fable-5-1
This commit is contained in:
2026-10-08 00:13:24 +00:00
parent e35cd4a045
commit fec2ddfb7c
25 changed files with 1160 additions and 1196 deletions
+79
View File
@@ -0,0 +1,79 @@
package cli
import (
"errors"
"fmt"
"os"
"github.com/spf13/afero"
"golang.org/x/term"
"sneak.berlin/go/mfer/internal/log"
"sneak.berlin/go/mfer/mfer"
)
// envSignKeyPassphrase names the environment variable holding the
// passphrase of a protected signing key.
//
//nolint:gosec // G101: the name of a variable, not a credential
const envSignKeyPassphrase = "MFER_SIGN_KEY_PASSPHRASE"
// errNoPassphrase indicates a protected signing key whose passphrase is
// neither in the environment nor can be asked for on a terminal.
var errNoPassphrase = errors.New(
"signing key is protected: set " + envSignKeyPassphrase + " to its passphrase")
// signingOptions returns the signing options for the OpenPGP secret key in
// the file path. The passphrase of a protected key comes from
// MFER_SIGN_KEY_PASSPHRASE, or else from the terminal on stdin.
func (mfa *CLIApp) signingOptions(path string) (*mfer.SigningOptions, error) {
secretKey, err := afero.ReadFile(mfa.Fs, path)
if err != nil {
return nil, fmt.Errorf("read signing key: %w", err)
}
protected, err := mfer.SecretKeyIsProtected(secretKey)
if err != nil {
return nil, fmt.Errorf("%s: %w", path, err)
}
log.Infof("signing manifest with the OpenPGP key in %s", path)
opts := &mfer.SigningOptions{SecretKey: secretKey}
if !protected {
return opts, nil
}
opts.Passphrase, err = mfa.readPassphrase(path)
if err != nil {
return nil, err
}
return opts, nil
}
// readPassphrase returns MFER_SIGN_KEY_PASSPHRASE when it is set, or else
// asks for the passphrase of the key in the file path on the terminal on
// stdin.
func (mfa *CLIApp) readPassphrase(path string) ([]byte, error) {
passphrase := os.Getenv(envSignKeyPassphrase)
if passphrase != "" {
return []byte(passphrase), nil
}
stdin, ok := mfa.Stdin.(*os.File)
if !ok || !term.IsTerminal(int(stdin.Fd())) {
return nil, errNoPassphrase
}
_, _ = fmt.Fprintf(mfa.Stderr, "Passphrase for %s: ", path)
typed, err := term.ReadPassword(int(stdin.Fd()))
_, _ = fmt.Fprintln(mfa.Stderr)
if err != nil {
return nil, fmt.Errorf("read passphrase: %w", err)
}
return typed, nil
}