Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions pkg/add_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"path/filepath"

"github.com/spf13/cobra"
"gomodules.xyz/flags"
"gomodules.xyz/restic"
core "k8s.io/api/core/v1"
"k8s.io/klog/v2"
Expand All @@ -38,8 +37,6 @@ func NewCmdAddKey(opt *keyOptions) *cobra.Command {
Args: cobra.ExactArgs(1),
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
flags.EnsureRequiredFlags(cmd, "new-password-file")

repoName := args[0]

var err error
Expand Down Expand Up @@ -86,6 +83,12 @@ func NewCmdAddKey(opt *keyOptions) *cobra.Command {
return err
}

cleanup, err := opt.preparePasswordFile()
if err != nil {
return err
}
defer cleanup()

if yes {
return opt.addResticKeyViaPod(&operatorPod)
}
Expand All @@ -97,7 +100,11 @@ func NewCmdAddKey(opt *keyOptions) *cobra.Command {
cmd.Flags().StringVar(&opt.Host, "host", opt.Host, "Host for the new key")
cmd.Flags().StringVar(&opt.User, "user", opt.User, "User for the new key")
cmd.Flags().StringVar(&opt.File, "new-password-file", opt.File, "File from which to read the new password")
cmd.Flags().StringVar(&opt.newPassword, "new-password", opt.newPassword, "New password for the restic repository (inline). Note: this exposes the password in shell history and the process list; prefer --new-password-stdin or --new-password-file")
cmd.Flags().BoolVar(&opt.newPasswordStdin, "new-password-stdin", opt.newPasswordStdin, "Read the new password from stdin (e.g. echo '<password>' | kubectl kubestash pw add ...)")
cmd.Flags().StringSliceVar(&opt.paths, "paths", opt.paths, "List of component paths (restic repositories) to add the new password")
cmd.MarkFlagsMutuallyExclusive("new-password-file", "new-password", "new-password-stdin")
cmd.MarkFlagsOneRequired("new-password-file", "new-password", "new-password-stdin")

return cmd
}
Expand Down
48 changes: 45 additions & 3 deletions pkg/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package pkg

import (
"fmt"
"io"
"os"
"os/exec"
"os/user"
Expand All @@ -36,9 +37,50 @@ import (

type keyOptions struct {
restic.KeyOptions
config *rest.Config
repo *storageapi.Repository
paths []string
config *rest.Config
repo *storageapi.Repository
paths []string
newPassword string
newPasswordStdin bool
}

func (opt *keyOptions) preparePasswordFile() (func(), error) {
noop := func() {}

// --new-password-file: use the provided file directly.
if opt.File != "" {
return noop, nil
}

f, err := os.CreateTemp("", "kubestash-newpw-")
if err != nil {
return noop, fmt.Errorf("failed to create temp password file: %w", err)
}

var data []byte
if opt.newPasswordStdin {
data, err = io.ReadAll(os.Stdin)
if err != nil {
_ = f.Close()
_ = os.Remove(f.Name())
return noop, fmt.Errorf("failed to read new password from stdin: %w", err)
}
} else {
data = []byte(opt.newPassword)
}

if _, err := f.Write(data); err != nil {
_ = f.Close()
_ = os.Remove(f.Name())
return noop, fmt.Errorf("failed to write temp password file: %w", err)
}
if err := f.Close(); err != nil {
_ = os.Remove(f.Name())
return noop, fmt.Errorf("failed to close temp password file: %w", err)
}

opt.File = f.Name()
return func() { _ = os.Remove(f.Name()) }, nil
}

func NewCmdKey(clientGetter genericclioptions.RESTClientGetter) *cobra.Command {
Expand Down
10 changes: 10 additions & 0 deletions pkg/update_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ func NewCmdUpdateKey(opt *keyOptions) *cobra.Command {
return err
}

cleanup, err := opt.preparePasswordFile()
if err != nil {
return err
}
defer cleanup()

if yes {
return opt.updateResticKeyViaPod(&operatorPod)
}
Expand All @@ -92,7 +98,11 @@ func NewCmdUpdateKey(opt *keyOptions) *cobra.Command {
}

cmd.Flags().StringVar(&opt.File, "new-password-file", opt.File, "File from which to read the new password")
cmd.Flags().StringVar(&opt.newPassword, "new-password", opt.newPassword, "New password for the restic repository (inline). Note: this exposes the password in shell history and the process list; prefer --new-password-stdin or --new-password-file")
cmd.Flags().BoolVar(&opt.newPasswordStdin, "new-password-stdin", opt.newPasswordStdin, "Read the new password from stdin (e.g. echo '<password>' | kubectl kubestash pw update ...)")
cmd.Flags().StringSliceVar(&opt.paths, "paths", opt.paths, "List of component paths (restic repositories) to update the password")
cmd.MarkFlagsMutuallyExclusive("new-password-file", "new-password", "new-password-stdin")
cmd.MarkFlagsOneRequired("new-password-file", "new-password", "new-password-stdin")

return cmd
}
Expand Down
Loading