# The password this hive's squid self-check logs in to squid with, kept where # only root can read it. # # swarm-controller mints it at `swarm/hives//squid-selfcheck` # (`swarm_secret_client::proxy::selfcheck_path`). hive-c0re reads the same path # to put its hash in squid's users file; this root oneshot reads it under the # hive's own store identity and lands it as the systemd credential # `squid-selfcheck` imports (`/run/credstore/`, root, `0400`, tmpfs). # # A hive with no minted credential yet leaves the file alone and the self-check # reports `credential=absent`. { pkgs, lib, config, ... }: let hyperhiveCfg = config.services.hyperhive; hiveController = hyperhiveCfg.deploy.hive-controller; tls = hiveController.tls; baoCfg = hyperhiveCfg.swarm.bao; baoDeploy = hyperhiveCfg.deploy.bao; enabled = hiveController.enable && hiveController.hiveName != null && tls.baoHiveIdentityCertFile != null && tls.baoHiveIdentityKeyFile != null; credentialFile = "/run/credstore/${hyperhiveCfg.deploy.hive-controller.squid.selfcheck.credentialName}"; storeRetry = import ./lib/store-retry.nix { }; storeRefreshTimer = import ./lib/store-refresh-timer.nix { }; in { config = lib.mkIf enabled { systemd.services.squid-selfcheck-credential = { description = "Read the squid self-check's password from the swarm secret store"; wantedBy = [ "multi-user.target" ]; before = [ "squid-selfcheck.service" ]; wants = [ "network-online.target" ]; after = [ "network-online.target" "systemd-tmpfiles-setup.service" ]; path = [ baoDeploy.package pkgs.coreutils pkgs.gnugrep ]; environment = { BAO_ADDR = "https://${baoCfg.domain}:${toString baoCfg.port}"; BAO_CLIENT_CERT = tls.baoHiveIdentityCertFile; BAO_CLIENT_KEY = tls.baoHiveIdentityKeyFile; } // lib.optionalAttrs (baoDeploy.serverCaFile != null) { BAO_CACERT = baoDeploy.serverCaFile; }; # ./lib/store-retry.nix: the login fails for as long as the store is # sealed or down. inherit (storeRetry) startLimitBurst startLimitIntervalSec; serviceConfig = storeRetry.serviceConfig // { Type = "oneshot"; UMask = "0077"; SyslogIdentifier = "squid-selfcheck-credential"; TimeoutStartSec = "5min"; }; script = '' set -euo pipefail ${import ./lib/store-seeded-secret.nix { }} ${import ./lib/atomic-write-secret.nix { }} ${import ./lib/refresh-consumer.nix { }} install -d -m 0700 /run/credstore store_init store_login if [ "$STORE_UP" != 1 ]; then echo "could not read the squid self-check credential; ${credentialFile} stays as it is." >&2 exit 1 fi if ! value="$(store_bao kv get -field=value ${lib.escapeShellArg "secret/swarm/hives/${hiveController.hiveName}/squid-selfcheck"} 2>"$STORE_ERR")"; then if grep -qi 'no value found' "$STORE_ERR"; then echo "the swarm has not minted this hive's squid self-check credential yet; ${credentialFile} stays as it is." exit 0 fi cat "$STORE_ERR" >&2 exit 1 fi if [[ ! "$value" =~ ^[A-Za-z0-9_-]+$ ]]; then echo "the stored squid self-check credential is not one base64url word; ${credentialFile} stays as it is." >&2 exit 1 fi # Written only when the value changed, so the file keeps its mtime. if secret_differs ${credentialFile} "$value"; then atomic_write_secret 0400 root:root ${credentialFile} "$value" fi ''; }; systemd.timers.squid-selfcheck-credential = storeRefreshTimer "re-read the squid self-check's password"; }; }