mirror of
https://github.com/borgbackup/borg.git
synced 2025-03-03 10:17:40 +00:00
internals: rewrite manifest & feature flags
This commit is contained in:
parent
71495b90e0
commit
36bdc9d15e
2 changed files with 111 additions and 12 deletions
|
@ -294,22 +294,119 @@ More on how this helps security in :ref:`security_structural_auth`.
|
|||
The manifest
|
||||
~~~~~~~~~~~~
|
||||
|
||||
The manifest is an object with an all-zero key that references all the
|
||||
archives. It contains:
|
||||
The manifest is the root of the object hierarchy. It references
|
||||
all archives in a repository, and thus all data in it.
|
||||
Since no object references it, it cannot be stored under its ID key.
|
||||
Instead, the manifest has a fixed all-zero key.
|
||||
|
||||
* Manifest version
|
||||
* A list of archive infos
|
||||
* timestamp
|
||||
* config
|
||||
The manifest is rewritten each time an archive is created, deleted,
|
||||
or modified. It looks like this:
|
||||
|
||||
Each archive info contains:
|
||||
.. code-block:: python
|
||||
|
||||
* name
|
||||
* id
|
||||
* time
|
||||
{
|
||||
b'version': 1,
|
||||
b'timestamp': b'2017-05-05T12:42:23.042864',
|
||||
b'item_keys': [b'acl_access', b'acl_default', ...],
|
||||
b'config': {},
|
||||
b'archives': {
|
||||
b'archive name': {
|
||||
b'id': b'<32 byte binary object ID>',
|
||||
b'time': b'2017-05-05T12:42:22.942864',
|
||||
},
|
||||
},
|
||||
b'tam': ...,
|
||||
}
|
||||
|
||||
It is the last object stored, in the last segment, and is replaced
|
||||
each time an archive is added, modified or deleted.
|
||||
The *version* field can be either 1 or 2. The versions differ in the
|
||||
way feature flags are handled, described below.
|
||||
|
||||
The *timestamp* field was used to avoid a certain class of replay attack.
|
||||
It is still used for that purpose, however, the newer replay protection
|
||||
introduced in Borg 1.1 includes all reply attacks. Thus it is not strictly
|
||||
necessary any more.
|
||||
|
||||
*item_keys* is a list containing all Item_ keys that may be encountered in
|
||||
the repository. It is used by *borg check*, which verifies that all keys
|
||||
in all items are a subset of these keys. Thus, an older version of *borg check*
|
||||
supporting this mechanism can correctly detect keys introduced in later versions.
|
||||
|
||||
The *tam* key is part of the :ref:`tertiary authentication mechanism <tam_description>`
|
||||
(formerly known as "tertiary authentication for metadata") and authenticates
|
||||
the manifest, since an ID check is not possible.
|
||||
|
||||
*config* is a general-purpose location for additional metadata. All versions
|
||||
of Borg preserve its contents (it may have been a better place for *item_keys*,
|
||||
which is not preserved by unaware Borg versions).
|
||||
|
||||
.. rubric:: Feature flags
|
||||
|
||||
Feature flags are used to add features to data structures without causing
|
||||
corruption if older versions are used to access or modify them.
|
||||
|
||||
The *config* key stores the feature flags enabled on a repository:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
config = {
|
||||
b'feature_flags': {
|
||||
b'read': {
|
||||
b'mandatory': [b'some_feature'],
|
||||
},
|
||||
b'check': {
|
||||
b'mandatory': [b'other_feature'],
|
||||
}
|
||||
b'write': ...,
|
||||
b'delete': ...
|
||||
},
|
||||
}
|
||||
|
||||
The top-level distinction for feature flags is the operation the client intends
|
||||
to perform,
|
||||
|
||||
| the *read* operation includes extraction and listing of archives,
|
||||
| the *write* operation includes creating new archives,
|
||||
| the *delete* (archives) operation,
|
||||
| the *check* operation requires full understanding of everything in the repository.
|
||||
|
|
||||
|
||||
These are weakly set-ordered; *check* will include everything required for *delete*,
|
||||
*delete* will likely include *write* and *read*. However, *read* may require more
|
||||
features than *write* (due to ID-based deduplication, *write* does not necessarily
|
||||
require reading/understanding repository contents).
|
||||
|
||||
Each operation can contain several sets of feature flags. Only one set,
|
||||
the *mandatory* set is currently defined.
|
||||
|
||||
Upon reading the manifest, the Borg client has already determined which operation
|
||||
is to be performed. If feature flags are found in the manifest, the set
|
||||
of feature flags supported by the client is compared to the mandatory set
|
||||
found in the manifest. If any unsupported flags are found (i.e. the mandatory set is
|
||||
a superset of the features supported by the Borg client used), the operation
|
||||
is aborted with a *MandatoryFeatureUnsupported* error:
|
||||
|
||||
Unsupported repository feature(s) {'some_feature'}. A newer version of borg is required to access this repository.
|
||||
|
||||
Older Borg releases do not have this concept and do not perform feature flags checks.
|
||||
These can be locked out with manifest version 2. Thus, the only difference between
|
||||
manifest versions 1 and 2 is that the latter is only accepted by Borg releases
|
||||
implementing feature flags.
|
||||
|
||||
.. rubric:: Defined feature flags
|
||||
|
||||
Currently no feature flags are defined.
|
||||
|
||||
From currently planned features, some examples follow,
|
||||
these may/may not be implemented and purely serve as examples.
|
||||
|
||||
- A mandatory *read* feature could be using a different encryption scheme (e.g. session keys).
|
||||
This may not be mandatory for the *write* operation - reading data is not strictly required for
|
||||
creating an archive.
|
||||
- Any additions to the way chunks are referenced (e.g. to support larger archives) would
|
||||
become a mandatory *delete* and *check* feature; *delete* implies knowing correct
|
||||
reference counts, so all object references need to be understood. *check* must
|
||||
discover the entire object graph as well, otherwise the "orphan chunks check"
|
||||
could delete data still in use.
|
||||
|
||||
.. _archive:
|
||||
|
||||
|
|
|
@ -63,6 +63,8 @@ in a particular part of its own data structure assigns this meaning.
|
|||
This results in a directed acyclic graph of authentication from the manifest
|
||||
to the data chunks of individual files.
|
||||
|
||||
.. _tam_description:
|
||||
|
||||
.. rubric:: Authenticating the manifest
|
||||
|
||||
Since the manifest has a fixed ID (000...000) the aforementioned authentication
|
||||
|
|
Loading…
Reference in a new issue