Skip to content

os-image/desktop: deliver the node's egress CA into the guest trust stores #187

Description

@CMGS

An intercept rule terminates TLS at the node's CA (sandboxd/egress/ca.go), so a guest that does not trust that CA sees a certificate error on every intercepted host. Nothing in the image closes that gap: os-image/base/24.04/Dockerfile:28 installs ca-certificates, which is the public bundle, and there is no drop point for the node's own root.

That makes intercept: true an image property rather than a policy one. Standing up a desktop fleet with interception hit it directly: enabling it meant rebuilding the desktop image with the CA in it and reimporting the template, which has to be scheduled against an idle pool. It also caps what the runtime policy revision in #188 can ever do — no amount of hot-reloading lets a host turn interception on for a guest that will reject the leaf.

Baking a fixed certificate into the layer is the wrong fix. egress_ca is operator-supplied per deployment (sandboxd/config/config.go:109-119 — a root bundle plus a node intermediate), so a cert compiled into the published image is either wrong for every other deployment or a shared root across all of them.

The delivery channel already exists. MarkLane writes /etc/silkd-lane into a guest over vsock through silkdWriteFile (sandboxd/engine/lane.go:16-20), and the desktop image's guest-proxy unit already waits on that file (os-image/desktop/24.04/Dockerfile:154-167). The node's root PEM can travel the same way, at the same point in the claim or refill path, so the published image stays generic and the deployment supplies its own root.

What the image side needs:

  1. A unit that waits for the dropped root the way guest-proxy waits for the lane verdict, installs it under /usr/local/share/ca-certificates/ and runs update-ca-certificates, and is a no-op when the file never arrives — so an image on a node without egress_ca boots unchanged.
  2. The same root in the NSS databases: Chrome and Firefox do not read the system store. That is certutil -A -d sql:<profile>/pki/nssdb against the profiles the image seeds, not a profile the user creates later.
  3. Ordering against the browsers — the trust refresh has to finish before a seeded browser first launches, or the first navigation still fails.

Acceptance: on a pool with an intercept rule, a cold claim reaches an intercepted HTTPS host from both curl and the seeded browser with no certificate error, and the audit log records the request as intercepted. On a node with no egress_ca, the same image boots to a desktop whose trust store is byte-identical to today's.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions