forked from TrueCloudLab/restic
Add option to read the password from a file
This commit is contained in:
parent
791f73e0db
commit
65afeba19a
4 changed files with 59 additions and 25 deletions
|
@ -20,9 +20,12 @@ func (cmd CmdInit) Execute(args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.global.password == "" {
|
if cmd.global.password == "" {
|
||||||
cmd.global.password = cmd.global.ReadPasswordTwice(
|
cmd.global.password, err = cmd.global.ReadPasswordTwice(
|
||||||
"enter password for new backend: ",
|
"enter password for new backend: ",
|
||||||
"enter password again: ")
|
"enter password again: ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s := repository.New(be)
|
s := repository.New(be)
|
||||||
|
|
|
@ -56,9 +56,9 @@ func (cmd CmdKey) listKeys(s *repository.Repository) error {
|
||||||
return tab.Write(cmd.global.stdout)
|
return tab.Write(cmd.global.stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd CmdKey) getNewPassword() string {
|
func (cmd CmdKey) getNewPassword() (string, error) {
|
||||||
if cmd.newPassword != "" {
|
if cmd.newPassword != "" {
|
||||||
return cmd.newPassword
|
return cmd.newPassword, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd.global.ReadPasswordTwice(
|
return cmd.global.ReadPasswordTwice(
|
||||||
|
@ -67,7 +67,12 @@ func (cmd CmdKey) getNewPassword() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd CmdKey) addKey(repo *repository.Repository) error {
|
func (cmd CmdKey) addKey(repo *repository.Repository) error {
|
||||||
id, err := repository.AddKey(repo, cmd.getNewPassword(), repo.Key())
|
pw, err := cmd.getNewPassword()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := repository.AddKey(repo, pw, repo.Key())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Fatalf("creating new key failed: %v\n", err)
|
return errors.Fatalf("creating new key failed: %v\n", err)
|
||||||
}
|
}
|
||||||
|
@ -92,7 +97,12 @@ func (cmd CmdKey) deleteKey(repo *repository.Repository, name string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd CmdKey) changePassword(repo *repository.Repository) error {
|
func (cmd CmdKey) changePassword(repo *repository.Repository) error {
|
||||||
id, err := repository.AddKey(repo, cmd.getNewPassword(), repo.Key())
|
pw, err := cmd.getNewPassword()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := repository.AddKey(repo, pw, repo.Key())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Fatalf("creating new key failed: %v\n", err)
|
return errors.Fatalf("creating new key failed: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"restic"
|
"restic"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -28,11 +29,12 @@ var compiledAt = "unknown time"
|
||||||
|
|
||||||
// GlobalOptions holds all those options that can be set for every command.
|
// GlobalOptions holds all those options that can be set for every command.
|
||||||
type GlobalOptions struct {
|
type GlobalOptions struct {
|
||||||
Repo string `short:"r" long:"repo" description:"Repository directory to backup to/restore from"`
|
Repo string `short:"r" long:"repo" description:"Repository directory to backup to/restore from"`
|
||||||
CacheDir string ` long:"cache-dir" description:"Directory to use as a local cache"`
|
PasswordFile string `short:"p" long:"password-file" description:"Read the repository password from a file"`
|
||||||
Quiet bool `short:"q" long:"quiet" default:"false" description:"Do not output comprehensive progress report"`
|
CacheDir string ` long:"cache-dir" description:"Directory to use as a local cache"`
|
||||||
NoLock bool ` long:"no-lock" default:"false" description:"Do not lock the repo, this allows some operations on read-only repos."`
|
Quiet bool `short:"q" long:"quiet" default:"false" description:"Do not output comprehensive progress report"`
|
||||||
Options []string `short:"o" long:"option" description:"Specify options in the form 'foo.key=value'"`
|
NoLock bool ` long:"no-lock" default:"false" description:"Do not lock the repo, this allows some operations on read-only repos."`
|
||||||
|
Options []string `short:"o" long:"option" description:"Specify options in the form 'foo.key=value'"`
|
||||||
|
|
||||||
password string
|
password string
|
||||||
stdout io.Writer
|
stdout io.Writer
|
||||||
|
@ -185,7 +187,7 @@ func readPassword(in io.Reader) (password string, err error) {
|
||||||
buf = buf[:n]
|
buf = buf[:n]
|
||||||
|
|
||||||
if err != nil && errors.Cause(err) != io.ErrUnexpectedEOF {
|
if err != nil && errors.Cause(err) != io.ErrUnexpectedEOF {
|
||||||
return "", err
|
return "", errors.Wrap(err, "ReadFull")
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.TrimRight(string(buf), "\r\n"), nil
|
return strings.TrimRight(string(buf), "\r\n"), nil
|
||||||
|
@ -199,15 +201,25 @@ func readPasswordTerminal(in *os.File, out io.Writer, prompt string) (password s
|
||||||
buf, err := terminal.ReadPassword(int(in.Fd()))
|
buf, err := terminal.ReadPassword(int(in.Fd()))
|
||||||
fmt.Fprintln(out)
|
fmt.Fprintln(out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", errors.Wrap(err, "ReadPassword")
|
||||||
}
|
}
|
||||||
|
|
||||||
password = string(buf)
|
password = string(buf)
|
||||||
return password, nil
|
return password, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadPassword reads the password from stdin.
|
// ReadPassword reads the password from a password file, the environment
|
||||||
func (o GlobalOptions) ReadPassword(prompt string) string {
|
// variable RESTIC_PASSWORD or prompts the user.
|
||||||
|
func (o GlobalOptions) ReadPassword(prompt string) (string, error) {
|
||||||
|
if o.PasswordFile != "" {
|
||||||
|
s, err := ioutil.ReadFile(o.PasswordFile)
|
||||||
|
return strings.TrimSpace(string(s)), errors.Wrap(err, "Readfile")
|
||||||
|
}
|
||||||
|
|
||||||
|
if pwd := os.Getenv("RESTIC_PASSWORD"); pwd != "" {
|
||||||
|
return pwd, nil
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
password string
|
password string
|
||||||
err error
|
err error
|
||||||
|
@ -220,26 +232,33 @@ func (o GlobalOptions) ReadPassword(prompt string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
o.Exitf(2, "unable to read password: %v", err)
|
return "", errors.Wrap(err, "unable to read password")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(password) == 0 {
|
if len(password) == 0 {
|
||||||
o.Exitf(1, "an empty password is not a password")
|
return "", errors.Fatal("an empty password is not a password")
|
||||||
}
|
}
|
||||||
|
|
||||||
return password
|
return password, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadPasswordTwice calls ReadPassword two times and returns an error when the
|
// ReadPasswordTwice calls ReadPassword two times and returns an error when the
|
||||||
// passwords don't match.
|
// passwords don't match.
|
||||||
func (o GlobalOptions) ReadPasswordTwice(prompt1, prompt2 string) string {
|
func (o GlobalOptions) ReadPasswordTwice(prompt1, prompt2 string) (string, error) {
|
||||||
pw1 := o.ReadPassword(prompt1)
|
pw1, err := o.ReadPassword(prompt1)
|
||||||
pw2 := o.ReadPassword(prompt2)
|
if err != nil {
|
||||||
if pw1 != pw2 {
|
return "", err
|
||||||
o.Exitf(1, "passwords do not match")
|
}
|
||||||
|
pw2, err := o.ReadPassword(prompt2)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return pw1
|
if pw1 != pw2 {
|
||||||
|
return "", errors.Fatal("passwords do not match")
|
||||||
|
}
|
||||||
|
|
||||||
|
return pw1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxKeys = 20
|
const maxKeys = 20
|
||||||
|
@ -258,7 +277,10 @@ func (o GlobalOptions) OpenRepository() (*repository.Repository, error) {
|
||||||
s := repository.New(be)
|
s := repository.New(be)
|
||||||
|
|
||||||
if o.password == "" {
|
if o.password == "" {
|
||||||
o.password = o.ReadPassword("enter password for repository: ")
|
o.password, err = o.ReadPassword("enter password for repository: ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.SearchKey(o.password, maxKeys)
|
err = s.SearchKey(o.password, maxKeys)
|
||||||
|
|
|
@ -28,7 +28,6 @@ func main() {
|
||||||
// defer profile.Start(profile.MemProfileRate(100000), profile.ProfilePath(".")).Stop()
|
// defer profile.Start(profile.MemProfileRate(100000), profile.ProfilePath(".")).Stop()
|
||||||
// defer profile.Start(profile.CPUProfile, profile.ProfilePath(".")).Stop()
|
// defer profile.Start(profile.CPUProfile, profile.ProfilePath(".")).Stop()
|
||||||
globalOpts.Repo = os.Getenv("RESTIC_REPOSITORY")
|
globalOpts.Repo = os.Getenv("RESTIC_REPOSITORY")
|
||||||
globalOpts.password = os.Getenv("RESTIC_PASSWORD")
|
|
||||||
|
|
||||||
debug.Log("restic", "main %#v", os.Args)
|
debug.Log("restic", "main %#v", os.Args)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue