restic-windows-backup icon indicating copy to clipboard operation
restic-windows-backup copied to clipboard

Use email authentication based on credentials file instead of plain text

Open innovara opened this issue 10 months ago • 2 comments

In its initial form this PR is a proof of concept to find out if the change is compatible with the maintainer's vision for the project.

I have been using on production environments a function for PowerShell scripts to avoid having passwords stored in plain text. It provides encryption but not a strong security. It works well on small deployments where you don't want to leave a password in plain sight on a file for the average end user, which is already an improvement over the present implementation.

The first time you run the script manually, when sending the email a window pops up with the email username pre-populated and you only have to enter the password, which will be then saved on a file, encrypted. From then on, you don't have to type the password again. This step, and generating a random $Key and store it in secrets.ps1, could be done on install.ps1 for convenience and added security.

It is also not intrinsically incompatible with preserving the existing functionality adding a setting for the end user to indicate their preference.

At this point I haven't made any effort to adapt the code to the style of this project or any of the above but I am happy to take it further should this change be something you would consider for merging.

innovara avatar Feb 03 '25 12:02 innovara

I'm open to the idea. I've not done any deep research on the best practices in Windows PowerShell for credential management. I think if we're going to explore a solution like this, I'd like the scope to include protecting everything in the secrets.ps1 file. i.e. not just email username/password, but also the various authorization keys for external services and the restic backup password.

Ideally, it'd be flexible enough that it'd work for whatever restic backend is in use. Maybe having something that encrypts the entire secrets.ps1, and decrypts and loads the variables safely when the script runs?

One challenge may be that the Task Scheduler script is running as the SYSTEM user, so if we use Windows Credential Manager to store things, we'd have to make sure to do so in a way that the SYSTEM user can access them.

Leaving these here as sources / thoughts for implementation: https://danielschwensen.github.io/2023-03-23-Securely_Storing_and_Using_Credentials_in_PowerShell_Scripts/ https://learn.microsoft.com/en-us/powershell/utility-modules/secretmanagement/how-to/manage-secretstore?view=ps-modules

kmwoley avatar Feb 03 '25 18:02 kmwoley

Yeah, the Windows task running with the SYSTEM user adds some complexity to more sophisticated solutions. Of the two links, the SecretStore vault seems the more flexible option but the installation is going to become more complex I think. Worth investigating nonetheless.

Meanwhile, I leave a snippet here that could be used to generate the random string per host on installation, in the context of the simplistic approach used to open this PR.

# Generate random $Key to encrypt email password
$Key = New-Object System.Collections.Generic.List[System.Object]
for ($i = 1; $i -le 24; $i++) {
  $Key.Add((Get-Random -Minimum 0 -Maximum 255))
}

Write-Host "`$ResticEmailKey=[byte]$($Key -join ",")"

At some point it also crossed my mind that SQLite would be ideal to store the logs and possibly could store secrets, but that would be a major refactoring and a big undertaking so I just brushed the thought aside.

innovara avatar Feb 04 '25 11:02 innovara