Merge pull request 'Give the privileged tier a working v1 to v2 path, and link the upgrade docs' (#22) from upgrade-path-privileged into main
Reviewed-on: #22 Reviewed-by: branderson <brad@branderson.io>
This commit was merged in pull request #22.
This commit is contained in:
@@ -43,6 +43,9 @@ For *why* any of this is necessary - what a CI run adds over a sandbox, and
|
||||
why no approval gate is offered - see [dejima's `docs/ci.md`](https://gitbox.branderson.io/dejima/dejima/src/branch/main/docs/ci.md). You do
|
||||
not need it to follow this.
|
||||
|
||||
**Already have a runner?** [Updating an existing runner](#updating-an-existing-runner)
|
||||
is the path forward: check its version, then walk the notes in order.
|
||||
|
||||
**Early development. Not ready to be depended on.** Nothing here has been
|
||||
through outside review, an external audit, or adversarial testing by anyone but
|
||||
the person who wrote it. Every security property this describes is a claim
|
||||
@@ -55,6 +58,35 @@ where to report a vulnerability rather than in a public issue.
|
||||
|
||||
[](https://gitbox.branderson.io/dejima/dejima)
|
||||
|
||||
## Updating an existing runner
|
||||
|
||||
**Check what it is at**, from a checkout rather than the installed copy:
|
||||
|
||||
```sh
|
||||
git -C ~/dejima-ci-hardener pull
|
||||
cd ~/dejima-ci-hardener
|
||||
sudo ./bin/dejima-ci-upgrade set-tier confined # or privileged, once per host
|
||||
sudo ./bin/dejima-ci-upgrade status
|
||||
```
|
||||
|
||||
That names every version this runner is missing. **Do them in order** — each
|
||||
note assumes the one before it.
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| [upgrades/](upgrades/) | One note per version: the console work, the guest work, and what it costs |
|
||||
| [docs/upgrading.md](docs/upgrading.md) | The process, including the seven steps a guest-side change takes when a rollback is going to rebuild the machine |
|
||||
|
||||
**From a checkout, not the installed copy**, for two reasons: an installed copy
|
||||
knows only the versions that existed when it was installed, and on a privileged
|
||||
host there may be no installed copy at all — `install.sh` does not run there.
|
||||
|
||||
**Recording a version is itself a guest-side change**, so on a runner it is
|
||||
thrown away at the next rollback unless it is baked into the snapshot. The
|
||||
console work is not: hypervisor rules are in force either way. `docs/upgrading.md`
|
||||
covers the choice; `status` re-runs each upgrade's check before calling its work
|
||||
outstanding, so a rebuilt runner is not told to redo something already done.
|
||||
|
||||
## Do not install this next to dejima
|
||||
|
||||
This runs on a machine whose job is to execute untrusted code. dejima runs on
|
||||
|
||||
@@ -535,6 +535,17 @@ elif [ "$ROLE" = privileged ]; then
|
||||
say " installed /usr/local/sbin/dejima-ci-runners"
|
||||
say " installed /usr/local/sbin/dejima-ci-upgrade"
|
||||
say " recorded /etc/dejima-ci/state (tier=privileged)"
|
||||
|
||||
# This runs under sudo, so its PATH is the one the operator's later sudo
|
||||
# commands get. Without a secure_path in sudoers, sudo inherits a non-root
|
||||
# PATH, and Debian leaves every sbin off that - so a correct install ends
|
||||
# with every documented command reporting "command not found".
|
||||
if [ "$(command -v dejima-ci-upgrade 2>/dev/null)" != /usr/local/sbin/dejima-ci-upgrade ]; then
|
||||
say
|
||||
say " NOTE: /usr/local/sbin is not on the PATH sudo gives you here, so"
|
||||
say " 'sudo dejima-ci-upgrade ...' will not be found. Use the full path,"
|
||||
say " or add a secure_path to sudoers that includes it."
|
||||
fi
|
||||
say
|
||||
/usr/local/sbin/dejima-ci-runners --role privileged || \
|
||||
say " runner setup did not finish - re-run: sudo dejima-ci-runners --role privileged"
|
||||
|
||||
+2
-1
@@ -9,7 +9,8 @@ where the second one lives.
|
||||
| [building-a-runner.md](building-a-runner.md) | The build, inside the VM: the Debian install, addressing, one bootstrap command, `install.sh`'s settings, and the runners. The same on any hypervisor and for both tiers. Start at your hypervisor's page and it sends you here |
|
||||
| [reference.md](reference.md) | The two settings named `docker.sock`, `CONFIG_FILE` and why an edit can appear to do nothing, the `/data` volume, compose networks against job networks, whether several runners should share a job network, why the privileged runner is separate, why public egress is not restricted on the node, why the resolver is set per-runner, the cache server |
|
||||
| [threat-model.md](threat-model.md) | The adversary, where each tier's boundary sits, blast radius by layer, and what was rejected |
|
||||
| [upgrading.md](upgrading.md) | Moving a runner that already exists to a newer version, why the two halves are counted separately, and the seven steps a guest-side change takes when a rollback is going to rebuild the machine |
|
||||
| [upgrading.md](upgrading.md) | Moving a runner that already exists to a newer version, why the two halves are counted separately, and the seven steps a guest-side change takes when a rollback is going to rebuild the machine. Start at [Updating](../README.md#updating-an-existing-runner) |
|
||||
| [../upgrades/](../upgrades/) | One note per version: what an operator does in the console and in the guest to reach it |
|
||||
| [../proxmox/README.md](../proxmox/README.md) | The node-side half on Proxmox: the VM, the datacenter firewall, the security group and the order its rules go in, and all three snapshot moments including the scheduled rollback |
|
||||
| [../proxmox/firewall.fw.template](../proxmox/firewall.fw.template) | The same node firewall as one annotated file, easier to review in one piece than as a table. Reference, not something to install |
|
||||
| [../examples/](../examples/) | The annotated templates `dejima-ci-runners` renders into `~/runners`. Every setting carries the reasoning for its value, which the generated copies do not - read them here rather than reading what lands on the host |
|
||||
|
||||
+20
@@ -858,6 +858,26 @@ say "are in the host's namespace, no bridge is in front of them, and the rules"
|
||||
say "installed here do not filter them. That is the privileged tier, and it"
|
||||
say "belongs on its own machine - see the README."
|
||||
say
|
||||
# Reachability, not just existence.
|
||||
#
|
||||
# Everything installs to /usr/local/sbin and every instruction in this
|
||||
# repository reads `sudo dejima-ci-...`. That works only where sudoers sets a
|
||||
# secure_path including sbin; without one, sudo inherits the caller's PATH, and
|
||||
# Debian leaves every sbin directory off a non-root PATH. The result is a
|
||||
# correct install whose documented commands all report "command not found",
|
||||
# which reads as a broken install rather than as a PATH.
|
||||
#
|
||||
# This runs under sudo, so its own PATH is the one those later commands will
|
||||
# get. Asking `command -v` here is therefore the real question rather than a
|
||||
# proxy for it.
|
||||
if [ "$(command -v dejima-ci-allowlist 2>/dev/null)" != "$BIN_DIR/dejima-ci-allowlist" ]; then
|
||||
say
|
||||
say " NOTE: $BIN_DIR is not on the PATH sudo gives you here, so"
|
||||
say " 'sudo dejima-ci-allowlist ...' will not be found. Either use the full"
|
||||
say " path, as $BIN_DIR/dejima-ci-allowlist, or add a secure_path to"
|
||||
say " sudoers that includes it. Nothing about the install is wrong."
|
||||
fi
|
||||
|
||||
say "Files this installer owns, for later reference:"
|
||||
say " config $CONFIG"
|
||||
say " allowlist $out (generated - do not hand-edit)"
|
||||
|
||||
@@ -6,6 +6,11 @@ same on any hypervisor.
|
||||
|
||||
## The whole job
|
||||
|
||||
**Already have a runner?** This page builds one. To bring an existing VM
|
||||
forward, start at [Updating](../README.md#updating-an-existing-runner) — the
|
||||
upgrade notes name the rules to change rather than having you re-read the table
|
||||
below.
|
||||
|
||||
Four steps, and the two pages interleave — follow this order rather than either
|
||||
page top to bottom.
|
||||
|
||||
|
||||
@@ -276,6 +276,21 @@ stub_check() {
|
||||
|| { echo "bootstrap does not record tier=privileged"; false; }
|
||||
}
|
||||
|
||||
@test "the hand-install recipe writes where bootstrap writes" {
|
||||
# v2 gives a privileged operator three install commands, because install.sh
|
||||
# does not run on that tier and re-running bootstrap on a built machine
|
||||
# redoes runner setup. Those commands duplicate bootstrap's, so they can
|
||||
# drift from it - and a tool installed to the wrong path is a tool that is
|
||||
# not there, reported as "not installed here" three sections later.
|
||||
branch=$(awk '/elif \[ "\$ROLE" = privileged \]/,/^else$/' "$REPO/bin/dejima-ci-bootstrap")
|
||||
for dest in /usr/local/sbin/dejima-ci-upgrade /usr/local/share/dejima-ci/upgrades; do
|
||||
printf '%s' "$branch" | grep -qF "$dest" \
|
||||
|| { echo "bootstrap no longer installs to $dest"; false; }
|
||||
grep -qF "$dest" "$REPO/upgrades/0002-ipv6-lan-boundary.md" \
|
||||
|| { echo "v2's hand-install recipe no longer names $dest"; false; }
|
||||
done
|
||||
}
|
||||
|
||||
@test "every version from 1 to VERSION has an upgrade note" {
|
||||
newest=$(tr -d '[:space:]' < "$REPO/VERSION")
|
||||
for v in $(seq 1 "$newest"); do
|
||||
|
||||
@@ -114,21 +114,44 @@ So there are two honest ways to do this, and no third.
|
||||
If you want the record to survive, it takes the same sequence any guest-side
|
||||
change takes — [the seven steps](../docs/upgrading.md#a-guest-side-upgrade-is-not-one-step).
|
||||
|
||||
And if you are doing the cycle anyway, **run `install.sh` while you are in
|
||||
it** (confined tier only). It puts `dejima-ci-upgrade` and these notes on the
|
||||
box, so later versions can be read and recorded without a checkout. Doing the
|
||||
dance for `mark-node` alone and skipping the install would be the expensive half
|
||||
of the work for the smaller half of the benefit.
|
||||
**Install the tool in the same cycle.** A record that survives a rollback is
|
||||
worth little if the program that reads it does not, and the cycle is the
|
||||
expensive part either way.
|
||||
|
||||
**The full path, immediately after installing.** These programs go to
|
||||
`/usr/local/sbin`, and `sudo` reaches that only if your `sudoers` sets a
|
||||
`secure_path` including it — without one, `sudo` inherits your own PATH, and
|
||||
Debian leaves every `sbin` off a non-root PATH. `sudo printenv PATH` says which
|
||||
you have. Naming the path here costs nothing and works either way.
|
||||
|
||||
**Confined tier**, where `install.sh` does it:
|
||||
|
||||
```sh
|
||||
# ... after rolling back to the clean snapshot, per the seven steps
|
||||
cd ~/dejima-ci-hardener && git pull
|
||||
sudo ./install.sh # confined tier only
|
||||
sudo dejima-ci-upgrade set-tier confined
|
||||
sudo dejima-ci-upgrade mark-node 2
|
||||
sudo ./install.sh
|
||||
sudo /usr/local/sbin/dejima-ci-upgrade set-tier confined
|
||||
sudo /usr/local/sbin/dejima-ci-upgrade mark-node 2
|
||||
# ... then re-snapshot and repoint the rollback job
|
||||
```
|
||||
|
||||
**Privileged tier**, where nothing does. `install.sh` does not run here — that
|
||||
is the grant the tier exists for — so the tool arrives only by
|
||||
`dejima-ci-bootstrap`, and re-running that on a built machine also redoes runner
|
||||
setup. The three commands it uses for this part are enough on their own:
|
||||
|
||||
```sh
|
||||
# ... after rolling back to the clean snapshot, per the seven steps
|
||||
cd ~/dejima-ci-hardener && git pull
|
||||
sudo install -m 0755 bin/dejima-ci-upgrade /usr/local/sbin/dejima-ci-upgrade
|
||||
sudo install -d -m 0755 /usr/local/share/dejima-ci/upgrades
|
||||
sudo install -m 0644 upgrades/*.md /usr/local/share/dejima-ci/upgrades/
|
||||
sudo /usr/local/sbin/dejima-ci-upgrade set-tier privileged
|
||||
sudo /usr/local/sbin/dejima-ci-upgrade mark-node 2
|
||||
# ... then re-snapshot and repoint the rollback job
|
||||
```
|
||||
|
||||
|
||||
### Or: skip it, and let the check answer for you
|
||||
|
||||
Perfectly reasonable, and probably right for v2 specifically. The console work
|
||||
|
||||
Reference in New Issue
Block a user