From bc74d3f13e854468e9d6cc2e4bbec40e5391328f Mon Sep 17 00:00:00 2001 From: Boris Bera Date: Wed, 28 Aug 2024 11:21:01 -0400 Subject: [PATCH] Add option to crash `autorestic` when key is missing instead of generating a new key (#383) * feat(backend): add requireKey option to backend This option will prevent `autorestic` from generating a key and will cause it to crash instead. This is intended for use cases where you want to provision the key yourself and don't want `autorestic` to accidentally generate one for you. * doc(backend): document requireKey --- docs/pages/backend/index.md | 22 ++++++++++++++++++++++ go.mod | 5 ++++- go.sum | 7 ++++--- internal/backend.go | 18 +++++++++++------- internal/backend_test.go | 13 +++++++++++++ 5 files changed, 54 insertions(+), 11 deletions(-) diff --git a/docs/pages/backend/index.md b/docs/pages/backend/index.md index cfe2f80..01a14fa 100644 --- a/docs/pages/backend/index.md +++ b/docs/pages/backend/index.md @@ -16,3 +16,25 @@ backends: ## Types We restic supports multiple types of backends. See the [full list](/backend/available) for details. + +## Avoid Generating Keys + +By default, `autorestic` will generate a key for every backend if none is defined. This is done by updating your config file with the key. + +In cases where you want to provide the key yourself, you can ensure that `autorestic` doesn't accidentally generate one for you by setting `requireKey: true`. + +Example: + +```yaml | .autorestic.yml +version: 2 + +backends: + foo: + type: local + path: /data/my/backups + # Alternatively, you can set the key through the `AUTORESTIC_FOO_RESTIC_PASSWORD` environment variable. + key: ... your key here ... + requireKey: true +``` + +With this setting, if a key is missing, `autorestic` will crash instead of generating a new key and updating your config file. diff --git a/go.mod b/go.mod index a024ecc..8b1d3e9 100644 --- a/go.mod +++ b/go.mod @@ -11,9 +11,11 @@ require ( github.com/robfig/cron v1.2.0 github.com/spf13/cobra v1.4.0 github.com/spf13/viper v1.11.0 + github.com/stretchr/testify v1.9.0 ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect @@ -23,6 +25,7 @@ require ( github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/pelletier/go-toml v1.9.4 // indirect github.com/pelletier/go-toml/v2 v2.0.0-beta.8 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/cast v1.4.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect @@ -32,5 +35,5 @@ require ( golang.org/x/text v0.3.8 // indirect gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 733fdc0..68e0cb6 100644 --- a/go.sum +++ b/go.sum @@ -182,8 +182,9 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -487,8 +488,8 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/backend.go b/internal/backend.go index 8f1981e..985e6c2 100644 --- a/internal/backend.go +++ b/internal/backend.go @@ -18,13 +18,14 @@ type BackendRest struct { } type Backend struct { - name string - Type string `mapstructure:"type,omitempty"` - Path string `mapstructure:"path,omitempty"` - Key string `mapstructure:"key,omitempty"` - Env map[string]string `mapstructure:"env,omitempty"` - Rest BackendRest `mapstructure:"rest,omitempty"` - Options Options `mapstructure:"options,omitempty"` + name string + Type string `mapstructure:"type,omitempty"` + Path string `mapstructure:"path,omitempty"` + Key string `mapstructure:"key,omitempty"` + RequireKey bool `mapstructure:"requireKey,omitempty"` + Env map[string]string `mapstructure:"env,omitempty"` + Rest BackendRest `mapstructure:"rest,omitempty"` + Options Options `mapstructure:"options,omitempty"` } func GetBackend(name string) (Backend, bool) { @@ -104,6 +105,9 @@ func (b Backend) validate() error { // Check if key is set in environment env, _ := b.getEnv() if _, found := env["RESTIC_PASSWORD"]; !found { + if b.RequireKey { + return fmt.Errorf("backend %s requires a key but none was provided", b.name) + } // No key set in config file or env => generate random key and save file key := generateRandomKey() b.Key = key diff --git a/internal/backend_test.go b/internal/backend_test.go index a97c7cd..a24afe0 100644 --- a/internal/backend_test.go +++ b/internal/backend_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/spf13/viper" + "github.com/stretchr/testify/assert" ) func TestGenerateRepo(t *testing.T) { @@ -222,4 +223,16 @@ func TestValidate(t *testing.T) { } assertEqual(t, err.Error(), "Backend \"foo\" has no \"path\"") }) + + t.Run("require key with no key", func(t *testing.T) { + b := Backend{ + name: "foo", + Type: "local", + Path: "~/foo/bar", + RequireKey: true, + } + err := b.validate() + fmt.Printf("error: %v\n", err) + assert.EqualError(t, err, "backend foo requires a key but none was provided") + }) }