config: use the environment variable which goes with --password-command
This commit is contained in:
parent
06df133159
commit
62dbdcdbcc
3 changed files with 33 additions and 60 deletions
|
@ -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
|
practice this should not cause a problem. Think of `--order-by` as
|
||||||
being more of a best efforts flag rather than a perfect ordering.
|
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 ###
|
### -P, --progress ###
|
||||||
|
|
||||||
This flag makes rclone update the stats in a static block in the
|
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
|
script should have a fully specified path name and not rely on any
|
||||||
environment variables. The script is supplied either via
|
environment variables. The script is supplied either via
|
||||||
`--password-command="..."` command line argument or via the
|
`--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
|
One useful example of this is using the `passwordstore` application
|
||||||
to retrieve the password:
|
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
|
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.
|
the config password considerably.
|
||||||
|
|
||||||
If you are running rclone inside a script, unless you are using the
|
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
|
password prompts. To do that, pass the parameter
|
||||||
`--ask-password=false` to rclone. This will make rclone fail instead
|
`--ask-password=false` to rclone. This will make rclone fail instead
|
||||||
of asking for a password if `RCLONE_CONFIG_PASS` doesn't contain
|
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
|
Developer options
|
||||||
|
|
|
@ -275,10 +275,6 @@ func loadConfigFile() (*goconfig.ConfigFile, error) {
|
||||||
|
|
||||||
if len(configKey) == 0 {
|
if len(configKey) == 0 {
|
||||||
pwc := fs.Config.PasswordCommand
|
pwc := fs.Config.PasswordCommand
|
||||||
|
|
||||||
if pwc == "" {
|
|
||||||
pwc = os.Getenv("RCLONE_CONFIG_PASS_COMMAND")
|
|
||||||
}
|
|
||||||
if pwc != "" {
|
if pwc != "" {
|
||||||
var stdout bytes.Buffer
|
var stdout bytes.Buffer
|
||||||
var stderr bytes.Buffer
|
var stderr bytes.Buffer
|
||||||
|
@ -291,7 +287,7 @@ func loadConfigFile() (*goconfig.ConfigFile, error) {
|
||||||
|
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
// One does not always get the stderr returned in the wrapped error.
|
// 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 != "" {
|
if ers := strings.TrimSpace(stderr.String()); ers != "" {
|
||||||
fs.Errorf(nil, "--password-command stderr: %s", ers)
|
fs.Errorf(nil, "--password-command stderr: %s", ers)
|
||||||
}
|
}
|
||||||
|
@ -357,7 +353,7 @@ func loadConfigFile() (*goconfig.ConfigFile, error) {
|
||||||
} else {
|
} else {
|
||||||
if len(configKey) == 0 {
|
if len(configKey) == 0 {
|
||||||
if usingPasswordCommand {
|
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 {
|
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")
|
return nil, errors.New("unable to decrypt configuration and not allowed to ask for password - set RCLONE_CONFIG_PASS to your configuration password")
|
||||||
|
|
|
@ -270,15 +270,24 @@ func TestConfigLoadEncrypted(t *testing.T) {
|
||||||
assert.Equal(t, expect, keys)
|
assert.Equal(t, expect, keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
func expectConfigValid(t *testing.T) {
|
func TestConfigLoadEncryptedWithValidPassCommand(t *testing.T) {
|
||||||
var err error
|
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
|
configKey = nil // reset password
|
||||||
|
|
||||||
c, err := loadConfigFile()
|
c, err := loadConfigFile()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Not sure why there is no "RCLONE_ENCRYPT_V0" here...
|
|
||||||
sections := c.GetSectionList()
|
sections := c.GetSectionList()
|
||||||
var expect = []string{"nounc", "unc"}
|
var expect = []string{"nounc", "unc"}
|
||||||
assert.Equal(t, expect, sections)
|
assert.Equal(t, expect, sections)
|
||||||
|
@ -288,64 +297,24 @@ func expectConfigValid(t *testing.T) {
|
||||||
assert.Equal(t, expect, keys)
|
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) {
|
func TestConfigLoadEncryptedWithInvalidPassCommand(t *testing.T) {
|
||||||
oldConfigPath := ConfigPath
|
oldConfigPath := ConfigPath
|
||||||
oldConfig := fs.Config
|
oldConfig := fs.Config
|
||||||
ConfigPath = "./testdata/encrypted.conf"
|
ConfigPath = "./testdata/encrypted.conf"
|
||||||
|
// using fs.Config.PasswordCommand, incorrect password
|
||||||
|
fs.Config.PasswordCommand = "echo asdf-blurfl"
|
||||||
defer func() {
|
defer func() {
|
||||||
ConfigPath = oldConfigPath
|
ConfigPath = oldConfigPath
|
||||||
configKey = nil // reset password
|
configKey = nil // reset password
|
||||||
fs.Config = oldConfig
|
fs.Config = oldConfig
|
||||||
|
fs.Config.PasswordCommand = ""
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// using fs.Config.PasswordCommand, incorrect password
|
configKey = nil // reset password
|
||||||
fs.Config.PasswordCommand = "echo asdf-blurfl"
|
|
||||||
expectConfigInvalid(t)
|
|
||||||
fs.Config.PasswordCommand = ""
|
|
||||||
|
|
||||||
var err error
|
_, err := loadConfigFile()
|
||||||
|
require.Error(t, err)
|
||||||
err = os.Setenv("RCLONE_CONFIG_PASS_COMMAND", "echo asdf-blurfl")
|
assert.Contains(t, err.Error(), "using --password-command derived password")
|
||||||
require.NoError(t, err)
|
|
||||||
expectConfigInvalid(t)
|
|
||||||
|
|
||||||
err = os.Unsetenv("RCLONE_CONFIG_PASS_COMMAND")
|
|
||||||
require.NoError(t, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigLoadEncryptedFailures(t *testing.T) {
|
func TestConfigLoadEncryptedFailures(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue