scope the cache access to hive-core: client-side nix copy, daemon trusts only the key
This commit is contained in:
parent
ecd4445680
commit
dab7768869
1 changed files with 365 additions and 271 deletions
|
|
@ -1,21 +1,27 @@
|
|||
# The binary-cache facts the host's nix daemon and hive-priv (root) trust, kept
|
||||
# where only root can change them.
|
||||
# The binary-cache facts the host's nix daemon, hive-priv (root) and hive-c0re
|
||||
# use, kept where only root can change them.
|
||||
#
|
||||
# hive-c0re downloads an agent's closure from the swarm cache through the
|
||||
# host's nix daemon, and hive-priv applies it only if the swarm's key signed
|
||||
# it. What decides whether a download is accepted — which cache the daemon
|
||||
# lets an unprivileged client name, and which key must have signed it — must
|
||||
# not come from a file the unprivileged hive-c0re writes, or a compromised
|
||||
# hive-c0re could have root accept a closure from a cache of its own. So:
|
||||
# hive-c0re pulls an agent's closure from the swarm cache with its own
|
||||
# `nix copy --from`: the client does the HTTP fetch with the pull token, and
|
||||
# hands the NAR to the host's nix daemon, which stores it only if a key in its
|
||||
# `trusted-public-keys` signed it. hive-priv applies a closure only if the
|
||||
# swarm's key signed it. What decides that must not come from a file the
|
||||
# unprivileged hive-c0re writes. So:
|
||||
#
|
||||
# - the cache's address is this host's configuration
|
||||
# ({option}`services.hyperhive.swarm.attic.domain` and `cache`);
|
||||
# ({option}`services.hyperhive.swarm.attic.domain` and `cache`), handed to
|
||||
# hive-c0re in its unit's environment;
|
||||
# - the cache's public key and the pull token are read from the store by a root
|
||||
# oneshot, `hive-priv-cache-facts`, under this hive's own store identity. The
|
||||
# key and the token land in `/run/hyperhive-priv/attic/` (root, `0700`; files
|
||||
# `0600`), and the address, the key and the netrc's path in a nix.conf
|
||||
# fragment, `/run/hyperhive-nix/cache.conf`, which the host's nix.conf
|
||||
# includes (`!include`, so a host whose unit has not run yet still starts).
|
||||
# `0600`). The key also lands in a nix.conf fragment,
|
||||
# `/run/hyperhive-nix/cache.conf`, as `extra-trusted-public-keys`, which the
|
||||
# host's nix.conf includes (`!include`, so a host whose unit has not run yet
|
||||
# still starts). The fragment names no substituter and no netrc, so a client
|
||||
# of the daemon that is not hive-c0re (an agent container on `nixBuilds =
|
||||
# host`) cannot fetch from the cache or send the token;
|
||||
# - the token also lands in `/run/hyperhive-nix/netrc`, `root:hive-core 0640`:
|
||||
# the one place hive-core, and nothing else unprivileged, can read it.
|
||||
#
|
||||
# hive-c0re keeps its own copies under `/run/hyperhive/attic/` for the probe,
|
||||
# which only reports.
|
||||
|
|
@ -47,7 +53,7 @@ let
|
|||
dir = "/run/hyperhive-priv/attic";
|
||||
confDir = "/run/hyperhive-nix";
|
||||
confFile = "${confDir}/cache.conf";
|
||||
url = "https://${atticCfg.domain}/${atticCfg.cache}";
|
||||
clientNetrc = "${confDir}/netrc";
|
||||
|
||||
# Where the store runs on this host, the first login waits for its container.
|
||||
# No `wants`: a pull would start the container mid-switch on the old closure.
|
||||
|
|
@ -66,6 +72,10 @@ in
|
|||
# `!include` tolerates a fragment that does not exist yet.
|
||||
nix.extraOptions = "!include ${confFile}";
|
||||
|
||||
# The address hive-c0re names to `nix copy --from`; no request chooses it.
|
||||
systemd.services.hive-c0re.environment.HIVE_C0RE_CACHE_URL =
|
||||
"https://${atticCfg.domain}/${atticCfg.cache}";
|
||||
|
||||
systemd.services.hive-priv-cache-facts = {
|
||||
description = "Read the swarm cache's public key and pull token for the host's nix daemon and hive-priv";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
|
@ -101,7 +111,8 @@ in
|
|||
script = import ./lib/attic-root-facts.nix { inherit lib; } {
|
||||
hive = hiveController.hiveName;
|
||||
host = atticCfg.domain;
|
||||
inherit dir url confFile;
|
||||
inherit dir confFile clientNetrc;
|
||||
clientGroup = config.users.users.hive-core.group;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue