Added BORG_PASSCOMMAND environment variable (#2573)

This commit is contained in:
TuXicc 2017-05-31 19:25:21 +02:00 committed by enkore
parent 02689174ab
commit 578b76af3a
4 changed files with 39 additions and 9 deletions

View File

@ -257,11 +257,11 @@ Security
How can I specify the encryption passphrase programmatically? How can I specify the encryption passphrase programmatically?
------------------------------------------------------------- -------------------------------------------------------------
The encryption passphrase can be specified programmatically using the The encryption passphrase or a command to retrieve the passphrase can be
`BORG_PASSPHRASE` environment variable. This is convenient when setting up specified programmatically using the `BORG_PASSPHRASE` or `BORG_PASSCOMMAND`
automated encrypted backups. Another option is to use environment variables. This is convenient when setting up automated encrypted
key file based encryption with a blank passphrase. See backups. Another option is to use key file based encryption with a blank passphrase.
:ref:`encrypted_repos` for more details. See :ref:`encrypted_repos` for more details.
.. _password_env: .. _password_env:
.. note:: Be careful how you set the environment; using the ``env`` .. note:: Be careful how you set the environment; using the ``env``

View File

@ -86,6 +86,8 @@ backed up and that the ``prune`` command is keeping and deleting the correct bac
# Setting this, so you won't be asked for your repository passphrase: # Setting this, so you won't be asked for your repository passphrase:
export BORG_PASSPHRASE='XYZl0ngandsecurepa_55_phrasea&&123' export BORG_PASSPHRASE='XYZl0ngandsecurepa_55_phrasea&&123'
# or this to ask an external program to supply the passphrase:
export BORG_PASSCOMMAND='pass show backup'
# some helpers and error handling: # some helpers and error handling:
function info () { echo -e "\n"`date` $@"\n" >&2; } function info () { echo -e "\n"`date` $@"\n" >&2; }

View File

@ -131,12 +131,20 @@ General:
can either leave it away or abbreviate as `::`, if a positional parameter is required. can either leave it away or abbreviate as `::`, if a positional parameter is required.
BORG_PASSPHRASE BORG_PASSPHRASE
When set, use the value to answer the passphrase question for encrypted repositories. When set, use the value to answer the passphrase question for encrypted repositories.
It is used when a passphrase is needed to access a encrypted repo as well as when a new It is used when a passphrase is needed to access an encrypted repo as well as when a new
passphrase should be initially set when initializing an encrypted repo. passphrase should be initially set when initializing an encrypted repo.
See also BORG_NEW_PASSPHRASE. See also BORG_NEW_PASSPHRASE.
BORG_PASSCOMMAND
When set, use the standard output of the command (trailing newlines are stripped) to answer the
passphrase question for encrypted repositories.
It is used when a passphrase is needed to access an encrypted repo as well as when a new
passphrase should be initially set when initializing an encrypted repo.
If BORG_PASSPHRASE is also set, it takes precedence.
See also BORG_NEW_PASSPHRASE.
BORG_NEW_PASSPHRASE BORG_NEW_PASSPHRASE
When set, use the value to answer the passphrase question when a **new** passphrase is asked for. When set, use the value to answer the passphrase question when a **new** passphrase is asked for.
This variable is checked first. If it is not set, BORG_PASSPHRASE will be checked also. This variable is checked first. If it is not set, BORG_PASSPHRASE and BORG_PASSCOMMAND will also
be checked.
Main usecase for this is to fully automate ``borg change-passphrase``. Main usecase for this is to fully automate ``borg change-passphrase``.
BORG_DISPLAY_PASSPHRASE BORG_DISPLAY_PASSPHRASE
When set, use the value to answer the "display the passphrase for verification" question when defining a new passphrase for encrypted repositories. When set, use the value to answer the "display the passphrase for verification" question when defining a new passphrase for encrypted repositories.

View File

@ -3,6 +3,7 @@ import getpass
import os import os
import sys import sys
import textwrap import textwrap
import subprocess
from binascii import a2b_base64, b2a_base64, hexlify from binascii import a2b_base64, b2a_base64, hexlify
from hashlib import sha256, sha512, pbkdf2_hmac from hashlib import sha256, sha512, pbkdf2_hmac
from hmac import HMAC, compare_digest from hmac import HMAC, compare_digest
@ -29,7 +30,11 @@ PREFIX = b'\0' * 8
class PassphraseWrong(Error): class PassphraseWrong(Error):
"""passphrase supplied in BORG_PASSPHRASE is incorrect""" """passphrase supplied in BORG_PASSPHRASE or by BORG_PASSCOMMAND is incorrect."""
class PasscommandFailure(Error):
"""passcommand supplied in BORG_PASSCOMMAND failed: {}"""
class PasswordRetriesExceeded(Error): class PasswordRetriesExceeded(Error):
@ -413,7 +418,22 @@ class Passphrase(str):
@classmethod @classmethod
def env_passphrase(cls, default=None): def env_passphrase(cls, default=None):
return cls._env_passphrase('BORG_PASSPHRASE', default) passphrase = cls._env_passphrase('BORG_PASSPHRASE', default)
if passphrase is not None:
return passphrase
passphrase = cls.env_passcommand()
if passphrase is not None:
return passphrase
@classmethod
def env_passcommand(cls, default=None):
passcommand = os.environ.get('BORG_PASSCOMMAND', None)
if passcommand is not None:
try:
passphrase = subprocess.check_output(passcommand.split(), universal_newlines=True)
except (subprocess.CalledProcessError, FileNotFoundError) as e:
raise PasscommandFailure(e)
return cls(passphrase.rstrip('\n'))
@classmethod @classmethod
def env_new_passphrase(cls, default=None): def env_new_passphrase(cls, default=None):