Introduction
This article explains how to use the Windows PowerShell to store your configuration file password securely in a file and let rclone use it without user interaction.
As explained in the official documentation, Rclone's configuration file contains information for logging in to your cloud services and should therefore be kept in a secure location. As an additional optional security measure rclone lets you encrypt the configuration file. The downside of this is that you will be prompted for the password every time you run an rclone command. You can avoid this by setting the password as the value of environment variable RCLONE_CONFIG_PASS
, but you may not want to have it in clear text in an environment variable.
As of release 1.51, rclone can be configured to execute a command and read the password from its standard output. The command can be specified in command-line argument --password-command
or environment variable RCLONE_PASSWORD_COMMAND
. Windows PowerShell includes built-in support for encryption via the SecureString
type. This .NET type is intended for sensitive string data that should not be kept as plain text in process memory, but this is not the important feature here. Instead we can utilize the fact that a SecureString
can be easily transformed into a regular String
type - and then the content is in encrypted form. The best part of this is that the encryption is based on a built-in component in Windows (Data Protection API, see notes below) which automatically manages the encryption key, so you will not have to enter or figure out how to mange a key or password to encrypt or decrypt!
There are probably several third party solutions that can be used with the --password-command
to achieve the same thing, e.g. Gpg4win (GNU Privacy Guard, GnuPG, for Windows) can be used with symmetric cipher and an agent utility (gpg-agent) which caches the password between invocations. The advantage of using Windows PowerShell is that everything you need is included in Windows.
Example 1
Step 1: Store encrypted password file
Create a file containing your password in encrypted form (for the purpose of this example, C:\Path\To\Password.sec
), by entering entering it interactively in a secure prompt:
Read-Host -Prompt 'Enter rclone configuration password' -AsSecureString | ConvertFrom-SecureString | Out-File -LiteralPath 'C:\Path\To\Password.sec' -NoNewline
Step 2: Create script for decrypting password file
Create a PowerShell script (for the purpose of this example, C:\Path\To\Password.ps1
), to return the decrypted password from the file you created in the previous step (notice how the same file is referenced in the -LiteralPath parameter):
New-Object -TypeName System.Net.NetworkCredential -ArgumentList '', (Get-Content -LiteralPath 'C:\Path\To\Password.sec' -Raw | ConvertTo-SecureString) | Select-Object -ExpandProperty Password
Step 3: Encrypt rclone configuration file
If you already have encrypted your rclone configuration file using the password entered in step 1, you can move directly to step 3. If not, you can now enable encryption. When doing that, you can instruct rclone to run powershell and execute the script created in the previous step, i.e. let it automatically read and decrypt the password from the encrypted file, with the command:
rclone --password-command "powershell -NoProfile -File C:\Path\To\Password.ps1" config encryption set
Step 4: Test
Run a test command, where you instruct rclone to run powershell and execute the script created in step 2 instead of prompting for the password when decrypting the configuration file:
rclone -vv --password-command "powershell -NoProfile -File C:\Path\To\Password.ps1" about remote:
Step 5: Use
As tested in previous step, the password command can be supplied as a command-line argument, which is appropriate for your rclone commands in other scripts. But for your interactive use it is not very convenient (unless you have a very long password it would probably be quicker just to drop it and enter the password when rclone prompts for it). To make sure the command is automatically included in your every rclone commands you can store it in environment variable RCLONE_PASSWORD_COMMAND
instead - set it to value powershell C:\Path\To\Password.ps1
From now on you can execute rclone commands without having to enter your configuration file password ever again.
Example 2
Instead of doing as in example 1 above, separating the two operations of (1) encrypting password and storing it in file, and (2) reading the file and decrypting the password, we can write a combined all-in-one PowerShell code block: It checks if the password file exists, if it does not then prompts the user to enter the configuration password which is then stored encrypted in the file. Later it will just read and decrypt this file without user interaction. The code can be stored in a PowerShell script file and referred to like in example 1 above, but also it can be specified directly as command line argument to powershell.exe.
Base PowerShell code:
[Console]::OutputEncoding = [Text.Encoding]::UTF8
if (-not (Test-Path -LiteralPath 'C:\Path\To\Password.sec'))
{
Read-Host -Prompt 'Enter rclone configuration password' -AsSecureString | ConvertFrom-SecureString | Out-File -LiteralPath 'C:\Path\To\Password.sec' -NoNewline
}
New-Object -TypeName System.Net.NetworkCredential -ArgumentList '', (Get-Content -LiteralPath 'C:\Path\To\Password.sec' -Raw | ConvertTo-SecureString) | Select-Object -ExpandProperty Password
It can be condensed into a single-liner that can be supplied directly as command-line argument powershell.exe:
powershell -NoProfile -Command [Console]::OutputEncoding = [Text.Encoding]::UTF8; if (-not (Test-Path -LiteralPath 'C:\Path\To\Password.sec')) { Read-Host -Prompt 'Enter rclone configuration password' -AsSecureString | ConvertFrom-SecureString | Out-File -LiteralPath 'C:\Path\To\Password.sec' -NoNewline } New-Object -TypeName System.Net.NetworkCredential -ArgumentList '', (Get-Content -LiteralPath 'C:\Path\To\Password.sec' -Raw | ConvertTo-SecureString) | Select-Object -ExpandProperty Password
To make sure the command is automatically executed for every rclone command, you can now just store this entire string as the value of environment variable RCLONE_PASSWORD_COMMAND
. You can also supply it to rclone command-line argument --password-command with double quotes around it: rclone lsd remote: --password-command "powershell -NoProfile -Command [Console]::OutputEncoding ..."
. If you want to set the environment variable from command prompt or a batch script remember to escape the |'
characters into ^|
, like this:
SET RCLONE_PASSWORD_COMMAND=powershell -NoProfile -Command [Console]::OutputEncoding = [Text.Encoding]::UTF8; if (-not (Test-Path -LiteralPath 'C:\Path\To\Password.sec')) { Read-Host -Prompt 'Enter rclone configuration password' -AsSecureString ^| ConvertFrom-SecureString ^| Out-File -LiteralPath 'C:\Path\To\Password.sec' -NoNewline } New-Object -TypeName System.Net.NetworkCredential -ArgumentList '', (Get-Content -LiteralPath 'C:\Path\To\Password.sec' -Raw ^| ConvertTo-SecureString) ^| Select-Object -ExpandProperty Password
Notes
Alternative password input
Looking back at example 1 step 1, instead of relying on interactively prompting for the password when creating the encrypted file, an alternative approach is to use a command where the password (for the purpose of this example, password123
) is given in plain text:
ConvertTo-SecureString -String "password123" -AsPlainText -Force | ConvertFrom-SecureString | Out-File -LiteralPath 'C:\Path\To\Password.sec' -NoNewline
This is obviously a less secure approach, as the plain text password is visible on your shell, and will probably also be recorded in your shell history.
Another alternative is to, instead of run a command with the actual password, run a command that generates a password for you. In the following example we use a .NET method for generating secure passwords, and we are requesting a password of length 12 with 2 non-alphanumeric characters in it:
Add-Type -AssemblyName System.Web
ConvertTo-SecureString -String ([System.Web.Security.Membership]::GeneratePassword(12, 2)) -AsPlainText -Force | ConvertFrom-SecureString | Out-File -LiteralPath 'C:\Path\To\Password.sec' -NoNewline
Since you don't know the password in advance with this approach, you obviously cannot encrypt the rclone configuration first, but need to use the password decrypted from the file when doing that, exactly how it is described in step 3.
Encryption
Encryption is based on the Data Protection API (DPAPI) component in Windows, which it uses to protect various passwords, certificate private keys, and other sensitive data. It is a symmetric encryption using key derived from the current user account. One of the main advantages of using DPAPI, is that it handles the otherwise difficult problem of explicitly generating and storing a cryptographic key.
Note that the encrypted content can only be decrypted with the same user account, and in most cases only from the same computer (with possible exception of a domain user account with a roaming profile). Also if you reinstall Windows (on a non-domain joined computer) you will not be able to decrypt the file.
Non-ASCII characters
If your password contain non-ascii characters (like German 'ü' or Norwegian 'ø') you will probably have to force UTF-8 encoded console output from the PowerShell executable. PowerShell defaults to writing standard output using the legacy OEM code page, for compatibility with the windows console, and Rclone assumes the data is UTF-8 encoded when reading the command output.
Rclone will report the following error if a mismatch occurs:
incorrect password: password contains invalid utf8 characters
The solution is to execute the following statement in your PowerShell script to ensure UTF-8 encoded output:
[Console]::OutputEncoding = [Text.Encoding]::UTF8