Files
keyfunc/internal/cli/ssh/install.go
clawbot b9c8631788
All checks were successful
check / check (push) Successful in 2m30s
The ssh install and ssh to commands (closes #2)
keyfunc ssh install appends the public line on a host through the system ssh, only when absent, feeding the line on standard input; keyfunc ssh to serves the derived key from an in-process agent on a private socket and runs the system ssh with it, the private key never on disk. Two review rounds; the second passed with no findings.

Model: opus-5 (implementation and review); fable-5-1 (landing)
2026-09-07 18:49:42 +02:00

97 lines
2.6 KiB
Go

package ssh
import (
"fmt"
"os/exec"
"slices"
"strings"
"github.com/spf13/cobra"
)
// script is what runs on the host. It reads the key line from its own
// standard input, so the line never appears on a command line, where
// anyone else on the host could read it out of the process list. It
// contains no single quote, so the whole of it travels through ssh
// inside one pair of them. The umask keeps anything it makes to the
// owner from the start; the modes are then set outright, whatever the
// umask on the host turns out to be. A file whose last line has no
// newline at its end gets one before the key line goes on, so that the
// two do not run into each other.
const script = `
set -e
umask 077
directory="$HOME/.ssh"
file="$directory/authorized_keys"
if [ ! -d "$directory" ]; then
mkdir -p "$directory"
chmod 700 "$directory"
fi
if [ ! -f "$file" ]; then
: > "$file"
chmod 600 "$file"
fi
IFS= read -r line
if grep -q -x -F -e "$line" "$file"; then
echo "already present"
else
if [ -s "$file" ] && [ -n "$(tail -c 1 "$file")" ]; then
printf "\n" >> "$file"
fi
printf "%s\n" "$line" >> "$file"
echo "added"
fi
`
// install returns the command that adds the public key to a host.
func install() *cobra.Command {
cmd := &cobra.Command{
Use: "install <[user@]host> [-- ssh options...]",
Short: "add the public key to a host's authorized_keys",
Long: "Runs the system ssh to the host, which makes ~/.ssh and " +
"~/.ssh/authorized_keys there if they are missing and adds " +
"the public key unless the same line is already in the " +
"file. Anything after -- is given to ssh unchanged.",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
key, comment, err := derived(cmd)
if err != nil {
return err
}
line, err := key.Line(comment)
if err != nil {
return err
}
return send(cmd, args[0], args[1:], line)
},
}
addComment(cmd)
return cmd
}
// send runs ssh to the host with the user's options, gives it the
// script to run there, and writes the key line to its standard input.
// What the host says, added or already present, is passed straight on.
func send(cmd *cobra.Command, host string, options []string, line string) error {
argv := slices.Concat(options, []string{
host, "/bin/sh -c '" + script + "'",
})
//nolint:gosec // the options are the user's own, meant for ssh
command := exec.CommandContext(cmd.Context(), "ssh", argv...)
command.Stdin = strings.NewReader(line + "\n")
command.Stdout = cmd.OutOrStdout()
command.Stderr = cmd.ErrOrStderr()
err := command.Run()
if err != nil {
return fmt.Errorf("running ssh: %w", err)
}
return nil
}