Skip to main content
RunBook Academy

← All checklists in Backup & DR

Quarterlybdr-repository-security

Backup repository security

20 items ·14 critical ·6 warn ·0 info

How to use

Quarterly, with the repository host in front of you rather than the configuration repository that is supposed to describe it. The review asks one question in twenty forms: is this repository defended as a system, with its own identities, its own patch level and its own recovery plan, or is it treated as a destination that backups are written to?

Several items say proven by attempt, and those are the ones that carry the review. Run the command with the credential the item names, then record the exit status and the message word for word. An access matrix in a design document describes what somebody intended. An exit status describes what the repository will actually do at three in the morning while somebody is destroying it.

Where the numbers come from

The identity list comes from the repository host itself — the forced commands in authorized_keys, the REST server’s user file, the object store’s policies — never from the configuration management that is meant to produce them. Where the two disagree, the host is the authority and the disagreement is a finding.

The delete result comes from performing the delete. Borg 1.4.0’s repository append_only setting is the control most often cited at this point, and the capture behind this course measured what it does:

Data-loss riskthree deletions against a repository with append_only = 1
$ borg delete /work/aorepo::day1
  
>>> exit code: 0
$ borg delete /work/aorepo::day2
>>> exit code: 0
$ borg delete /work/aorepo::day3
>>> exit code: 0

--- what the attacker now sees ---
(empty)

Three deletions, exit code 0 each time, and an empty archive listing. Upstream states the position without ambiguity: the setting affects only the low-level structure of the repository, and delete, prune and reads are still allowed. What it forbids is compaction, which leaves 41M of segments on disk and makes the damage reversible by rolling the transaction log back on the repository host. That is a genuine boundary — the compromised client cannot reach the server’s filesystem — but it is not the boundary the phrase “append-only” is usually read as describing, and it closes the moment a compaction pass runs.

The escrow number comes from using the escrow, not from confirming the envelope exists. Adding a second passphrase gives the recovery team an unlock path that production never holds:

Configuration changea second passphrase added to the same repository
$ restic key add --new-password-file /work/recovery-pass
  saved new key with ID 66c34166d8443d16e8c5899fe3f792e749cb24fa3a90ac90bbe8348979b57d90
>>> exit code: 0

Access this needs

Read access to the repository host’s identity configuration, its logs and its package state. One non-production client credential to run the attempt items with, and a disposable archive named rbdr-probe to aim the delete attempt at, so that proving the control costs nothing.

The escrow items need the custodian’s participation, which has to be arranged before the review rather than during it — and if that person cannot be reached in a quarter, that is the finding, because they cannot be reached during an incident either.

What the review produces

A dated record naming the reviewer; a table of every credential with its owner, its repository and what it is able to do; and the verbatim exit status and message of every attempt item. Attach the quotation from the vendor documentation for whatever the estate calls append-only, so the next reviewer argues with the vendor rather than with the previous reviewer.

Each failing item becomes a finding with a named owner and a date. A failing critical item is a blocker: it means the copies do not survive the compromise of what they are copies of.

Sign-off

  • Reviewer: ____
  • Date: ____
  • Repository system owner: ____
  • Key custodian (escrow items): ____

Critical14 items

  1. sudo grep -o "restrict-to-repository [^ ]*" /home/rbdr-borg/.ssh/authorized_keys | sort -u
  2. BORG_RSH="ssh -i /root/.ssh/rbdr-client-a" borg list rbdr-borg@rbdr-repo01:/srv/rbdr/repos/rbdr-client-b; echo "exit $?"
  3. borg delete rbdr-borg@rbdr-repo01:/srv/rbdr/repos/rbdr-client-a::rbdr-probe; echo "exit $?"
  4. systemctl cat rbdr-retention.timer
  5. journalctl -u ssh --since "90 days ago" | grep rbdr-borg | tail -n 20
  6. grep -rn "PASSWORD_FILE\|BORG_PASSPHRASE" /etc/systemd/system/rbdr-backup.service
  7. restic --password-file /srv/rbdr/recovery-pass --repo /srv/rbdr/repos/rbdr-client-a snapshots
  8. find /srv/rbdr /root \( -name "*paper-key*" -o -name "*key-backup*" \) 2>/dev/null
  9. borg config /srv/rbdr/repos/rbdr-client-a append_only
  10. apt list --upgradable 2>/dev/null | tail -n 20

Warning6 items

  1. borg prune --list --dry-run --keep-daily=1 /srv/rbdr/repos/rbdr-client-a
  2. borg list /srv/rbdr/repos/rbdr-client-a | wc -l
  3. stat -c "%U %a %n" /etc/rbdr/passphrase
  4. sudo nft list ruleset | grep -B2 -A6 rbdr-repo