config: use the environment variable which goes with --password-command

This commit is contained in:
Nick Craig-Wood 2020-01-23 13:54:18 +00:00
parent 06df133159
commit 62dbdcdbcc
3 changed files with 33 additions and 60 deletions

View File

@ -880,6 +880,14 @@ Rclone will do its best to transfer the best file it has so in
practice this should not cause a problem. Think of `--order-by` as
being more of a best efforts flag rather than a perfect ordering.
### --password-command=STRING ###
This flag supplies a program which should supply the config password
when run. This is an alternative to rclone prompting for the password
or setting the `RCLONE_CONFIG_PASS` variable.
See the [Configuration Encryption](#configuration-encryption) for more info.
### -P, --progress ###
This flag makes rclone update the stats in a static block in the
@ -1361,13 +1369,13 @@ which will retrieve the password and print on standard output. This
script should have a fully specified path name and not rely on any
environment variables. The script is supplied either via
`--password-command="..."` command line argument or via the
`RCLONE_CONFIG_PASS_COMMAND` environment variable.
`RCLONE_PASSWORD_COMMAND` environment variable.
One useful example of this is using the `passwordstore` application
to retrieve the password:
```
export RCLONE_CONFIG_PASS_COMMAND="pass rclone/config"
export RCLONE_PASSWORD_COMMAND="pass rclone/config"
```
If the `passwordstore` password manager holds the password for the
@ -1381,11 +1389,11 @@ script method of supplying the password enhances the security of
the config password considerably.
If you are running rclone inside a script, unless you are using the
`RCLONE_CONFIG_PASS_COMMAND` method, you might want to disable
`--password-command` method, you might want to disable
password prompts. To do that, pass the parameter
`--ask-password=false` to rclone. This will make rclone fail instead
of asking for a password if `RCLONE_CONFIG_PASS` doesn't contain
a valid password, and `RCLONE_CONFIG_PASS_COMMAND` has not been supplied.
a valid password, and `--password-command` has not been supplied.
Developer options

View File

@ -275,10 +275,6 @@ func loadConfigFile() (*goconfig.ConfigFile, error) {
if len(configKey) == 0 {
pwc := fs.Config.PasswordCommand
if pwc == "" {
pwc = os.Getenv("RCLONE_CONFIG_PASS_COMMAND")
}
if pwc != "" {
var stdout bytes.Buffer
var stderr bytes.Buffer
@ -291,7 +287,7 @@ func loadConfigFile() (*goconfig.ConfigFile, error) {
if err := cmd.Run(); err != nil {
// One does not always get the stderr returned in the wrapped error.
fs.Errorf(nil, "Using RCLONE_CONFIG_PASS_COMMAND returned: %v", err)
fs.Errorf(nil, "Using --password-command returned: %v", err)
if ers := strings.TrimSpace(stderr.String()); ers != "" {
fs.Errorf(nil, "--password-command stderr: %s", ers)
}
@ -357,7 +353,7 @@ func loadConfigFile() (*goconfig.ConfigFile, error) {
} else {
if len(configKey) == 0 {
if usingPasswordCommand {
return nil, errors.New("using password command derived password, unable to decrypt configuration")
return nil, errors.New("using --password-command derived password, unable to decrypt configuration")
}
if !fs.Config.AskPassword {
return nil, errors.New("unable to decrypt configuration and not allowed to ask for password - set RCLONE_CONFIG_PASS to your configuration password")

View File

@ -270,15 +270,24 @@ func TestConfigLoadEncrypted(t *testing.T) {
assert.Equal(t, expect, keys)
}
func expectConfigValid(t *testing.T) {
var err error
func TestConfigLoadEncryptedWithValidPassCommand(t *testing.T) {
oldConfigPath := ConfigPath
oldConfig := fs.Config
ConfigPath = "./testdata/encrypted.conf"
// using fs.Config.PasswordCommand, correct password
fs.Config.PasswordCommand = "echo asdf"
defer func() {
ConfigPath = oldConfigPath
configKey = nil // reset password
fs.Config = oldConfig
fs.Config.PasswordCommand = ""
}()
configKey = nil // reset password
c, err := loadConfigFile()
require.NoError(t, err)
// Not sure why there is no "RCLONE_ENCRYPT_V0" here...
sections := c.GetSectionList()
var expect = []string{"nounc", "unc"}
assert.Equal(t, expect, sections)
@ -288,64 +297,24 @@ func expectConfigValid(t *testing.T) {
assert.Equal(t, expect, keys)
}
func expectConfigInvalid(t *testing.T) {
var err error
configKey = nil // reset password
_, err = loadConfigFile()
require.Error(t, err)
}
func TestConfigLoadEncryptedWithValidPassCommand(t *testing.T) {
oldConfigPath := ConfigPath
oldConfig := fs.Config
ConfigPath = "./testdata/encrypted.conf"
defer func() {
ConfigPath = oldConfigPath
configKey = nil // reset password
fs.Config = oldConfig
}()
// using fs.Config.PasswordCommand, correct password
fs.Config.PasswordCommand = "echo asdf"
expectConfigValid(t)
var err error
// using "RCLONE_CONFIG_PASS_COMMAND"
err = os.Setenv("RCLONE_CONFIG_PASS_COMMAND", "echo asdf")
require.NoError(t, err)
expectConfigValid(t)
err = os.Unsetenv("RCLONE_CONFIG_PASS_COMMAND")
require.NoError(t, err)
}
func TestConfigLoadEncryptedWithInvalidPassCommand(t *testing.T) {
oldConfigPath := ConfigPath
oldConfig := fs.Config
ConfigPath = "./testdata/encrypted.conf"
// using fs.Config.PasswordCommand, incorrect password
fs.Config.PasswordCommand = "echo asdf-blurfl"
defer func() {
ConfigPath = oldConfigPath
configKey = nil // reset password
fs.Config = oldConfig
fs.Config.PasswordCommand = ""
}()
// using fs.Config.PasswordCommand, incorrect password
fs.Config.PasswordCommand = "echo asdf-blurfl"
expectConfigInvalid(t)
fs.Config.PasswordCommand = ""
configKey = nil // reset password
var err error
err = os.Setenv("RCLONE_CONFIG_PASS_COMMAND", "echo asdf-blurfl")
require.NoError(t, err)
expectConfigInvalid(t)
err = os.Unsetenv("RCLONE_CONFIG_PASS_COMMAND")
require.NoError(t, err)
_, err := loadConfigFile()
require.Error(t, err)
assert.Contains(t, err.Error(), "using --password-command derived password")
}
func TestConfigLoadEncryptedFailures(t *testing.T) {