Browse Source

Merge pull request #1878 from ThomasWaldmann/borg-new-passphrase

implement BORG_NEW_PASSPHRASE, fixes #1768
enkore 8 years ago
parent
commit
50b97665c8
3 changed files with 37 additions and 2 deletions
  1. 16 0
      docs/usage.rst
  2. 13 2
      src/borg/key.py
  3. 8 0
      src/borg/testsuite/archiver.py

+ 16 - 0
docs/usage.rst

@@ -144,6 +144,13 @@ General:
         can either leave it away or abbreviate as `::`, if a positional parameter is required.
     BORG_PASSPHRASE
         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
+        passphrase should be initially set when initializing an encrypted repo.
+        See also BORG_NEW_PASSPHRASE.
+    BORG_NEW_PASSPHRASE
+        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.
+        Main usecase for this is to fully automate ``borg change-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.
     BORG_LOGGING_CONF
@@ -649,6 +656,15 @@ Examples
     Remember your passphrase. Your data will be inaccessible without it.
     Key updated
 
+Fully automated using environment variables:
+
+::
+
+    $ BORG_NEW_PASSPHRASE=old borg init repo
+    # now "old" is the current passphrase.
+    $ BORG_PASSPHRASE=old BORG_NEW_PASSPHRASE=new borg change-passphrase repo
+    # now "new" is the current passphrase.
+
 
 .. include:: usage/serve.rst.inc
 

+ 13 - 2
src/borg/key.py

@@ -247,11 +247,19 @@ class AESKeyBase(KeyBase):
 
 class Passphrase(str):
     @classmethod
-    def env_passphrase(cls, default=None):
-        passphrase = os.environ.get('BORG_PASSPHRASE', default)
+    def _env_passphrase(cls, env_var, default=None):
+        passphrase = os.environ.get(env_var, default)
         if passphrase is not None:
             return cls(passphrase)
 
+    @classmethod
+    def env_passphrase(cls, default=None):
+        return cls._env_passphrase('BORG_PASSPHRASE', default)
+
+    @classmethod
+    def env_new_passphrase(cls, default=None):
+        return cls._env_passphrase('BORG_NEW_PASSPHRASE', default)
+
     @classmethod
     def getpass(cls, prompt):
         return cls(getpass.getpass(prompt))
@@ -276,6 +284,9 @@ class Passphrase(str):
 
     @classmethod
     def new(cls, allow_empty=False):
+        passphrase = cls.env_new_passphrase()
+        if passphrase is not None:
+            return passphrase
         passphrase = cls.env_passphrase()
         if passphrase is not None:
             return passphrase

+ 8 - 0
src/borg/testsuite/archiver.py

@@ -1363,6 +1363,14 @@ class ArchiverTestCase(ArchiverTestCaseBase):
         size, csize = self._get_sizes('lzma', compressible=False)
         assert csize >= size
 
+    def test_change_passphrase(self):
+        self.cmd('init', self.repository_location)
+        os.environ['BORG_NEW_PASSPHRASE'] = 'newpassphrase'
+        # here we have both BORG_PASSPHRASE and BORG_NEW_PASSPHRASE set:
+        self.cmd('change-passphrase', self.repository_location)
+        os.environ['BORG_PASSPHRASE'] = 'newpassphrase'
+        self.cmd('list', self.repository_location)
+
     def test_break_lock(self):
         self.cmd('init', self.repository_location)
         self.cmd('break-lock', self.repository_location)