mirror of https://github.com/borgbackup/borg.git
remove borg upgrade
This commit is contained in:
parent
3fbb297fd7
commit
dbae8e60eb
|
@ -60,7 +60,6 @@ Usage
|
||||||
usage/tar
|
usage/tar
|
||||||
|
|
||||||
usage/transfer
|
usage/transfer
|
||||||
usage/upgrade
|
|
||||||
usage/benchmark
|
usage/benchmark
|
||||||
|
|
||||||
usage/help
|
usage/help
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
.. include:: upgrade.rst.inc
|
|
||||||
|
|
||||||
Examples
|
|
||||||
~~~~~~~~
|
|
||||||
::
|
|
||||||
|
|
||||||
# Upgrade the borg repository to the most recent version.
|
|
||||||
$ borg upgrade -v /path/to/repo
|
|
||||||
making a hardlink copy in /path/to/repo.before-upgrade-2016-02-15-20:51:55
|
|
||||||
opening attic repository with borg and converting
|
|
||||||
no key file found for repository
|
|
||||||
converting repo index /path/to/repo/index.0
|
|
||||||
converting 1 segments...
|
|
||||||
converting borg 0.xx to borg current
|
|
||||||
no key file found for repository
|
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
.. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!
|
|
||||||
|
|
||||||
.. _borg_upgrade:
|
|
||||||
|
|
||||||
borg upgrade
|
|
||||||
------------
|
|
||||||
.. code-block:: none
|
|
||||||
|
|
||||||
borg [common options] upgrade [options]
|
|
||||||
|
|
||||||
.. only:: html
|
|
||||||
|
|
||||||
.. class:: borg-options-table
|
|
||||||
|
|
||||||
+-------------------------------------------------------+-----------------------+------------------------------------------------------------------------------------------------+
|
|
||||||
| **optional arguments** |
|
|
||||||
+-------------------------------------------------------+-----------------------+------------------------------------------------------------------------------------------------+
|
|
||||||
| | ``-n``, ``--dry-run`` | do not change repository |
|
|
||||||
+-------------------------------------------------------+-----------------------+------------------------------------------------------------------------------------------------+
|
|
||||||
| | ``--inplace`` | rewrite repository in place, with no chance of going back to older versions of the repository. |
|
|
||||||
+-------------------------------------------------------+-----------------------+------------------------------------------------------------------------------------------------+
|
|
||||||
| | ``--force`` | Force upgrade |
|
|
||||||
+-------------------------------------------------------+-----------------------+------------------------------------------------------------------------------------------------+
|
|
||||||
| | ``--tam`` | Enable manifest authentication (in key and cache) (Borg 1.0.9 and later). |
|
|
||||||
+-------------------------------------------------------+-----------------------+------------------------------------------------------------------------------------------------+
|
|
||||||
| | ``--disable-tam`` | Disable manifest authentication (in key and cache). |
|
|
||||||
+-------------------------------------------------------+-----------------------+------------------------------------------------------------------------------------------------+
|
|
||||||
| .. class:: borg-common-opt-ref |
|
|
||||||
| |
|
|
||||||
| :ref:`common_options` |
|
|
||||||
+-------------------------------------------------------+-----------------------+------------------------------------------------------------------------------------------------+
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<script type='text/javascript'>
|
|
||||||
$(document).ready(function () {
|
|
||||||
$('.borg-options-table colgroup').remove();
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
.. only:: latex
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
optional arguments
|
|
||||||
-n, --dry-run do not change repository
|
|
||||||
--inplace rewrite repository in place, with no chance of going back to older versions of the repository.
|
|
||||||
--force Force upgrade
|
|
||||||
--tam Enable manifest authentication (in key and cache) (Borg 1.0.9 and later).
|
|
||||||
--disable-tam Disable manifest authentication (in key and cache).
|
|
||||||
|
|
||||||
|
|
||||||
:ref:`common_options`
|
|
||||||
|
|
|
||||||
|
|
||||||
Description
|
|
||||||
~~~~~~~~~~~
|
|
||||||
|
|
||||||
Upgrade an existing, local Borg repository.
|
|
||||||
|
|
||||||
When you do not need borg upgrade
|
|
||||||
+++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
Not every change requires that you run ``borg upgrade``.
|
|
||||||
|
|
||||||
You do **not** need to run it when:
|
|
||||||
|
|
||||||
- moving your repository to a different place
|
|
||||||
- upgrading to another point release (like 1.0.x to 1.0.y),
|
|
||||||
except when noted otherwise in the changelog
|
|
||||||
- upgrading from 1.0.x to 1.1.x,
|
|
||||||
except when noted otherwise in the changelog
|
|
||||||
|
|
||||||
Borg 1.x.y upgrades
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
Use ``borg upgrade --tam REPO`` to require manifest authentication
|
|
||||||
introduced with Borg 1.0.9 to address security issues. This means
|
|
||||||
that modifying the repository after doing this with a version prior
|
|
||||||
to 1.0.9 will raise a validation error, so only perform this upgrade
|
|
||||||
after updating all clients using the repository to 1.0.9 or newer.
|
|
||||||
|
|
||||||
This upgrade should be done on each client for safety reasons.
|
|
||||||
|
|
||||||
If a repository is accidentally modified with a pre-1.0.9 client after
|
|
||||||
this upgrade, use ``borg upgrade --tam --force REPO`` to remedy it.
|
|
||||||
|
|
||||||
If you routinely do this you might not want to enable this upgrade
|
|
||||||
(which will leave you exposed to the security issue). You can
|
|
||||||
reverse the upgrade by issuing ``borg upgrade --disable-tam REPO``.
|
|
||||||
|
|
||||||
See
|
|
||||||
https://borgbackup.readthedocs.io/en/stable/changes.html#pre-1-0-9-manifest-spoofing-vulnerability
|
|
||||||
for details.
|
|
||||||
|
|
||||||
Borg 0.xx to Borg 1.x
|
|
||||||
+++++++++++++++++++++
|
|
||||||
|
|
||||||
This currently supports converting Borg 0.xx to 1.0.
|
|
||||||
|
|
||||||
Currently, only LOCAL repositories can be upgraded (issue #465).
|
|
||||||
|
|
||||||
Please note that ``borg create`` (since 1.0.0) uses bigger chunks by
|
|
||||||
default than old borg did, so the new chunks won't deduplicate
|
|
||||||
with the old chunks in the upgraded repository.
|
|
||||||
See ``--chunker-params`` option of ``borg create`` and ``borg recreate``.
|
|
|
@ -490,16 +490,6 @@ class Archiver:
|
||||||
if key.tam_required:
|
if key.tam_required:
|
||||||
tam_file = tam_required_file(repository)
|
tam_file = tam_required_file(repository)
|
||||||
open(tam_file, 'w').close()
|
open(tam_file, 'w').close()
|
||||||
logger.warning(
|
|
||||||
'\n'
|
|
||||||
'By default repositories initialized with this version will produce security\n'
|
|
||||||
'errors if written to with an older version (up to and including Borg 1.0.8).\n'
|
|
||||||
'\n'
|
|
||||||
'If you want to use these older versions, you can disable the check by running:\n'
|
|
||||||
'borg upgrade --disable-tam %s\n'
|
|
||||||
'\n'
|
|
||||||
'See https://borgbackup.readthedocs.io/en/stable/changes.html#pre-1-0-9-manifest-spoofing-vulnerability '
|
|
||||||
'for details about the security implications.', shlex.quote(path))
|
|
||||||
|
|
||||||
if key.NAME != 'plaintext':
|
if key.NAME != 'plaintext':
|
||||||
logger.warning(
|
logger.warning(
|
||||||
|
@ -1892,56 +1882,6 @@ class Archiver:
|
||||||
logger=logging.getLogger('borg.output.stats'))
|
logger=logging.getLogger('borg.output.stats'))
|
||||||
return self.exit_code
|
return self.exit_code
|
||||||
|
|
||||||
@with_repository(fake=('tam', 'disable_tam'), invert_fake=True, manifest=False, exclusive=True)
|
|
||||||
def do_upgrade(self, args, repository, manifest=None, key=None):
|
|
||||||
"""upgrade a repository from a previous version"""
|
|
||||||
if args.tam:
|
|
||||||
manifest, key = Manifest.load(repository, (Manifest.Operation.CHECK,), force_tam_not_required=args.force)
|
|
||||||
|
|
||||||
if not hasattr(key, 'change_passphrase'):
|
|
||||||
print('This repository is not encrypted, cannot enable TAM.')
|
|
||||||
return EXIT_ERROR
|
|
||||||
|
|
||||||
if not manifest.tam_verified or not manifest.config.get('tam_required', False):
|
|
||||||
# The standard archive listing doesn't include the archive ID like in borg 1.1.x
|
|
||||||
print('Manifest contents:')
|
|
||||||
for archive_info in manifest.archives.list(sort_by=['ts']):
|
|
||||||
print(format_archive(archive_info), '[%s]' % bin_to_hex(archive_info.id))
|
|
||||||
manifest.config['tam_required'] = True
|
|
||||||
manifest.write()
|
|
||||||
repository.commit(compact=False)
|
|
||||||
if not key.tam_required:
|
|
||||||
key.tam_required = True
|
|
||||||
key.change_passphrase(key._passphrase)
|
|
||||||
print('Key updated')
|
|
||||||
if hasattr(key, 'find_key'):
|
|
||||||
print('Key location:', key.find_key())
|
|
||||||
if not tam_required(repository):
|
|
||||||
tam_file = tam_required_file(repository)
|
|
||||||
open(tam_file, 'w').close()
|
|
||||||
print('Updated security database')
|
|
||||||
elif args.disable_tam:
|
|
||||||
manifest, key = Manifest.load(repository, Manifest.NO_OPERATION_CHECK, force_tam_not_required=True)
|
|
||||||
if tam_required(repository):
|
|
||||||
os.unlink(tam_required_file(repository))
|
|
||||||
if key.tam_required:
|
|
||||||
key.tam_required = False
|
|
||||||
key.change_passphrase(key._passphrase)
|
|
||||||
print('Key updated')
|
|
||||||
if hasattr(key, 'find_key'):
|
|
||||||
print('Key location:', key.find_key())
|
|
||||||
manifest.config['tam_required'] = False
|
|
||||||
manifest.write()
|
|
||||||
repository.commit(compact=False)
|
|
||||||
else:
|
|
||||||
# mainly for upgrades from borg 0.xx -> 1.0.
|
|
||||||
repo = BorgRepositoryUpgrader(args.location.path, create=False)
|
|
||||||
try:
|
|
||||||
repo.upgrade(args.dry_run, inplace=args.inplace, progress=args.progress)
|
|
||||||
except NotImplementedError as e:
|
|
||||||
print("warning: %s" % e)
|
|
||||||
return self.exit_code
|
|
||||||
|
|
||||||
@with_repository(cache=True, exclusive=True, compatibility=(Manifest.Operation.CHECK,))
|
@with_repository(cache=True, exclusive=True, compatibility=(Manifest.Operation.CHECK,))
|
||||||
def do_recreate(self, args, repository, manifest, key, cache):
|
def do_recreate(self, args, repository, manifest, key, cache):
|
||||||
"""Re-create archives"""
|
"""Re-create archives"""
|
||||||
|
@ -5070,74 +5010,6 @@ class Archiver:
|
||||||
subparser.add_argument('mountpoint', metavar='MOUNTPOINT', type=str,
|
subparser.add_argument('mountpoint', metavar='MOUNTPOINT', type=str,
|
||||||
help='mountpoint of the filesystem to umount')
|
help='mountpoint of the filesystem to umount')
|
||||||
|
|
||||||
# borg upgrade
|
|
||||||
upgrade_epilog = process_epilog("""
|
|
||||||
Upgrade an existing, local Borg repository.
|
|
||||||
|
|
||||||
When you do not need borg upgrade
|
|
||||||
+++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
Not every change requires that you run ``borg upgrade``.
|
|
||||||
|
|
||||||
You do **not** need to run it when:
|
|
||||||
|
|
||||||
- moving your repository to a different place
|
|
||||||
- upgrading to another point release (like 1.0.x to 1.0.y),
|
|
||||||
except when noted otherwise in the changelog
|
|
||||||
- upgrading from 1.0.x to 1.1.x,
|
|
||||||
except when noted otherwise in the changelog
|
|
||||||
|
|
||||||
Borg 1.x.y upgrades
|
|
||||||
+++++++++++++++++++
|
|
||||||
|
|
||||||
Use ``borg upgrade --tam REPO`` to require manifest authentication
|
|
||||||
introduced with Borg 1.0.9 to address security issues. This means
|
|
||||||
that modifying the repository after doing this with a version prior
|
|
||||||
to 1.0.9 will raise a validation error, so only perform this upgrade
|
|
||||||
after updating all clients using the repository to 1.0.9 or newer.
|
|
||||||
|
|
||||||
This upgrade should be done on each client for safety reasons.
|
|
||||||
|
|
||||||
If a repository is accidentally modified with a pre-1.0.9 client after
|
|
||||||
this upgrade, use ``borg upgrade --tam --force REPO`` to remedy it.
|
|
||||||
|
|
||||||
If you routinely do this you might not want to enable this upgrade
|
|
||||||
(which will leave you exposed to the security issue). You can
|
|
||||||
reverse the upgrade by issuing ``borg upgrade --disable-tam REPO``.
|
|
||||||
|
|
||||||
See
|
|
||||||
https://borgbackup.readthedocs.io/en/stable/changes.html#pre-1-0-9-manifest-spoofing-vulnerability
|
|
||||||
for details.
|
|
||||||
|
|
||||||
Borg 0.xx to Borg 1.x
|
|
||||||
+++++++++++++++++++++
|
|
||||||
|
|
||||||
This currently supports converting Borg 0.xx to 1.0.
|
|
||||||
|
|
||||||
Currently, only LOCAL repositories can be upgraded (issue #465).
|
|
||||||
|
|
||||||
Please note that ``borg create`` (since 1.0.0) uses bigger chunks by
|
|
||||||
default than old borg did, so the new chunks won't deduplicate
|
|
||||||
with the old chunks in the upgraded repository.
|
|
||||||
See ``--chunker-params`` option of ``borg create`` and ``borg recreate``.""")
|
|
||||||
subparser = subparsers.add_parser('upgrade', parents=[common_parser], add_help=False,
|
|
||||||
description=self.do_upgrade.__doc__,
|
|
||||||
epilog=upgrade_epilog,
|
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
||||||
help='upgrade repository format')
|
|
||||||
subparser.set_defaults(func=self.do_upgrade)
|
|
||||||
subparser.add_argument('-n', '--dry-run', dest='dry_run', action='store_true',
|
|
||||||
help='do not change repository')
|
|
||||||
subparser.add_argument('--inplace', dest='inplace', action='store_true',
|
|
||||||
help='rewrite repository in place, with no chance of going back '
|
|
||||||
'to older versions of the repository.')
|
|
||||||
subparser.add_argument('--force', dest='force', action='store_true',
|
|
||||||
help='Force upgrade')
|
|
||||||
subparser.add_argument('--tam', dest='tam', action='store_true',
|
|
||||||
help='Enable manifest authentication (in key and cache) (Borg 1.0.9 and later).')
|
|
||||||
subparser.add_argument('--disable-tam', dest='disable_tam', action='store_true',
|
|
||||||
help='Disable manifest authentication (in key and cache).')
|
|
||||||
|
|
||||||
# borg with-lock
|
# borg with-lock
|
||||||
with_lock_epilog = process_epilog("""
|
with_lock_epilog = process_epilog("""
|
||||||
This command runs a user-specified command while the repository lock is held.
|
This command runs a user-specified command while the repository lock is held.
|
||||||
|
|
|
@ -61,12 +61,7 @@ class UnsupportedKeyFormatError(Error):
|
||||||
|
|
||||||
class TAMRequiredError(IntegrityError):
|
class TAMRequiredError(IntegrityError):
|
||||||
__doc__ = textwrap.dedent("""
|
__doc__ = textwrap.dedent("""
|
||||||
Manifest is unauthenticated, but it is required for this repository.
|
Manifest is unauthenticated, but it is required for this repository. Is somebody attacking you?
|
||||||
|
|
||||||
This either means that you are under attack, or that you modified this repository
|
|
||||||
with a Borg version older than 1.0.9 after TAM authentication was enabled.
|
|
||||||
|
|
||||||
In the latter case, use "borg upgrade --tam --force '{}'" to re-authenticate the manifest.
|
|
||||||
""").strip()
|
""").strip()
|
||||||
traceback = False
|
traceback = False
|
||||||
|
|
||||||
|
|
|
@ -153,7 +153,7 @@ class Repository:
|
||||||
"""{} does not have a valid configuration. Check repo config [{}]."""
|
"""{} does not have a valid configuration. Check repo config [{}]."""
|
||||||
|
|
||||||
class AtticRepository(Error):
|
class AtticRepository(Error):
|
||||||
"""Attic repository detected. Please use borg < 1.3 to run "borg upgrade {}"."""
|
"""Attic repository detected. Please use borg <= 1.2 to run "borg upgrade {}"."""
|
||||||
|
|
||||||
class CheckNeeded(ErrorWithTraceback):
|
class CheckNeeded(ErrorWithTraceback):
|
||||||
"""Inconsistency detected. Please run "borg check {}"."""
|
"""Inconsistency detected. Please run "borg check {}"."""
|
||||||
|
|
|
@ -3888,21 +3888,6 @@ class ManifestAuthenticationTest(ArchiverTestCaseBase):
|
||||||
self.cmd(f'--repo={self.repository_location}', 'rcreate', '--encryption=repokey')
|
self.cmd(f'--repo={self.repository_location}', 'rcreate', '--encryption=repokey')
|
||||||
self.create_src_archive('archive1234')
|
self.create_src_archive('archive1234')
|
||||||
repository = Repository(self.repository_path, exclusive=True)
|
repository = Repository(self.repository_path, exclusive=True)
|
||||||
with repository:
|
|
||||||
shutil.rmtree(get_security_dir(bin_to_hex(repository.id)))
|
|
||||||
_, key = Manifest.load(repository, Manifest.NO_OPERATION_CHECK)
|
|
||||||
key.tam_required = False
|
|
||||||
key.change_passphrase(key._passphrase)
|
|
||||||
|
|
||||||
manifest = msgpack.unpackb(key.decrypt(Manifest.MANIFEST_ID, repository.get(Manifest.MANIFEST_ID)))
|
|
||||||
del manifest['tam']
|
|
||||||
repository.put(Manifest.MANIFEST_ID, key.encrypt(Manifest.MANIFEST_ID, msgpack.packb(manifest)))
|
|
||||||
repository.commit(compact=False)
|
|
||||||
output = self.cmd(f'--repo={self.repository_location}', 'rlist', '--debug')
|
|
||||||
assert 'archive1234' in output
|
|
||||||
assert 'TAM not found and not required' in output
|
|
||||||
# Run upgrade
|
|
||||||
self.cmd(f'--repo={self.repository_location}', 'upgrade', '--tam')
|
|
||||||
# Manifest must be authenticated now
|
# Manifest must be authenticated now
|
||||||
output = self.cmd(f'--repo={self.repository_location}', 'rlist', '--debug')
|
output = self.cmd(f'--repo={self.repository_location}', 'rlist', '--debug')
|
||||||
assert 'archive1234' in output
|
assert 'archive1234' in output
|
||||||
|
@ -3912,25 +3897,6 @@ class ManifestAuthenticationTest(ArchiverTestCaseBase):
|
||||||
# Fails
|
# Fails
|
||||||
with pytest.raises(TAMRequiredError):
|
with pytest.raises(TAMRequiredError):
|
||||||
self.cmd(f'--repo={self.repository_location}', 'rlist')
|
self.cmd(f'--repo={self.repository_location}', 'rlist')
|
||||||
# Force upgrade
|
|
||||||
self.cmd(f'--repo={self.repository_location}', 'upgrade', '--tam', '--force')
|
|
||||||
self.cmd(f'--repo={self.repository_location}', 'rlist')
|
|
||||||
|
|
||||||
def test_disable(self):
|
|
||||||
self.cmd(f'--repo={self.repository_location}', 'rcreate', '--encryption=repokey')
|
|
||||||
self.create_src_archive('archive1234')
|
|
||||||
self.cmd(f'--repo={self.repository_location}', 'upgrade', '--disable-tam')
|
|
||||||
repository = Repository(self.repository_path, exclusive=True)
|
|
||||||
self.spoof_manifest(repository)
|
|
||||||
assert not self.cmd(f'--repo={self.repository_location}', 'rlist')
|
|
||||||
|
|
||||||
def test_disable2(self):
|
|
||||||
self.cmd(f'--repo={self.repository_location}', 'rcreate', '--encryption=repokey')
|
|
||||||
self.create_src_archive('archive1234')
|
|
||||||
repository = Repository(self.repository_path, exclusive=True)
|
|
||||||
self.spoof_manifest(repository)
|
|
||||||
self.cmd(f'--repo={self.repository_location}', 'upgrade', '--disable-tam')
|
|
||||||
assert not self.cmd(f'--repo={self.repository_location}', 'rlist')
|
|
||||||
|
|
||||||
|
|
||||||
class RemoteArchiverTestCase(ArchiverTestCase):
|
class RemoteArchiverTestCase(ArchiverTestCase):
|
||||||
|
|
Loading…
Reference in New Issue