All checks were successful
check / check (push) Successful in 2m30s
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)
128 lines
2.6 KiB
Go
128 lines
2.6 KiB
Go
// Package ssh groups the commands that derive ed25519 SSH keys.
|
|
package ssh
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"git.eeqj.de/sneak/keyfunc/internal/cli/options"
|
|
"git.eeqj.de/sneak/keyfunc/internal/derive"
|
|
"git.eeqj.de/sneak/keyfunc/internal/sshkey"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
// Command returns the ssh command and everything under it.
|
|
func Command() *cobra.Command {
|
|
group := &cobra.Command{
|
|
Use: "ssh",
|
|
Short: "derive ed25519 SSH keys",
|
|
}
|
|
|
|
group.AddCommand(public(), private(), install(), to())
|
|
|
|
return group
|
|
}
|
|
|
|
// public returns the command that prints the authorized_keys line.
|
|
func public() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "pub",
|
|
Short: "print the public key as an authorized_keys line",
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
key, comment, err := derived(cmd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
line, err := key.Line(comment)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return write(cmd, line+"\n")
|
|
},
|
|
}
|
|
|
|
addComment(cmd)
|
|
|
|
return cmd
|
|
}
|
|
|
|
// private returns the command that prints the private key.
|
|
func private() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "priv",
|
|
Short: "print the unencrypted private key in OpenSSH format",
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
key, comment, err := derived(cmd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
block, err := key.Block(comment)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return write(cmd, block)
|
|
},
|
|
}
|
|
|
|
addComment(cmd)
|
|
|
|
return cmd
|
|
}
|
|
|
|
// write sends the text to wherever the command's output goes.
|
|
func write(cmd *cobra.Command, text string) error {
|
|
_, err := fmt.Fprint(cmd.OutOrStdout(), text)
|
|
if err != nil {
|
|
return fmt.Errorf("writing the key: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// addComment gives a command its comment flag.
|
|
func addComment(cmd *cobra.Command) {
|
|
cmd.Flags().String(
|
|
"comment", "",
|
|
"comment on the key; keyfunc/ssh/<index> when not given",
|
|
)
|
|
}
|
|
|
|
// derived returns the key for this run and the comment to put on it.
|
|
func derived(cmd *cobra.Command) (*sshkey.Key, string, error) {
|
|
index, err := options.Index(cmd)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
|
|
words, err := options.Mnemonic(cmd)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
|
|
material, err := derive.Bytes(words, sshkey.Application, index)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
|
|
key, err := sshkey.New(material)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
|
|
comment, err := cmd.Flags().GetString("comment")
|
|
if err != nil {
|
|
return nil, "", fmt.Errorf("reading the comment: %w", err)
|
|
}
|
|
|
|
if comment == "" {
|
|
comment = fmt.Sprintf("keyfunc/ssh/%d", index)
|
|
}
|
|
|
|
return key, comment, nil
|
|
}
|