Skip to main content

compute_certificate

Compute TLS certificate lifecycle: CSR generation and Hub-issued cert renewal.

Once a compute has heartbeated with a private IP address, the hub registers a "compute" record and returns a computeId/domain pair (see BitfountHub.do_pod_heartbeat). This module builds a CSR for that domain, submits it to BitfountHub.request_compute_certificate, polls BitfountHub.get_compute_certificate until issued, persists the result, and later detects when the issued certificate is two-thirds of the way through its validity period so a renewal can be requested. If the hub hands back a new computeId/domain pair; a persisted certificate for the old domain is treated as absent (rather than just not-yet- due-for-renewal) so a certificate for the new domain is requested straight away instead of waiting out the old one's remaining validity.

Module

Functions

build_csr_pem

def build_csr_pem(private_key: RSAPrivateKey, domain: str)> str:

Builds a PEM-encoded certificate signing request for domain.

The hub requires the CSR's public key to be RSA, its subject common name to equal domain exactly, and exactly one subject alternative name (a DNS name equal to domain).

Arguments

  • private_key: The RSA private key to sign the CSR with. Its public key is embedded in the CSR.
  • domain: The domain the certificate is being requested for (the domain returned alongside computeId from the heartbeat).

Returns The PEM-encoded CSR.

certificate_domain

def certificate_domain(certificate_pem: str)> str | None:

Returns the leaf certificate's subject common name, or None if absent.

build_csr_pem sets the CSR's common name to the domain it was issued for, and the hub is required to preserve it, so this is what identifies which domain a persisted certificate belongs to.

Arguments

  • certificate_pem: A PEM-encoded certificate (the leaf certificate is sufficient; any following CA bundle entries are ignored).

certificate_validity

def certificate_validity(    certificate_pem: str,)> tuple[datetime.datetime, datetime.datetime]:

Returns the (not-valid-before, not-valid-after) UTC datetimes.

Arguments

  • certificate_pem: A PEM-encoded certificate (the leaf certificate is sufficient; any following CA bundle entries are ignored).

renewal_due_at

def renewal_due_at(    not_before: datetime, not_after: datetime, fraction: float = 0.6666666666666666,)> datetime.datetime:

Returns the point at which a certificate should be renewed.

Defaults to two-thirds of the way through the certificate's validity period. This is the same heuristic used by ACME clients.

Classes

ComputeCertificateManager

class ComputeCertificateManager(    hub: BitfountHub, key_directory: Path, private_key: RSAPrivateKey,):

Manages the lifecycle of a compute's hub-issued TLS certificate.

Persists the issued certificate (leaf + CA bundle) alongside the pod's existing RSA identity key, under key_directory / "compute.pem".

Arguments

  • hub: The BitfountHub client to request/poll certificates through.
  • key_directory: The pod's key directory (the same directory pod_rsa.pem lives in).
  • private_key: The pod's existing RSA identity key. Reused as the CSR key rather than generating a separate one.

Variables

  • fullchain_path : pathlib.Path - Path to the persisted leaf-certificate + CA-bundle PEM file.
  • tls_keyfile_path : pathlib.Path - Path to a PEM/PKCS8 copy of the private key, for TLS.

    Written lazily, on first access. ComputeCertificateManager is constructed for every pod regardless of whether TLS is ever actually used, and callers (e.g. tests) may pass a mocked private_key.

Methods


current_fullchain_path

def current_fullchain_path(self)> pathlib.Path | None:

Returns fullchain_path if a certificate is already persisted.

poll

def poll(self, compute_id: str | None, domain: str | None)> None:

Runs one idempotent certificate-lifecycle tick.

Safe to call repeatedly (e.g. from a background thread). Never raises: hub/network failures are logged and left for the next tick, matching how Pod._pod_heartbeat handles the same failure modes.

Arguments

  • compute_id: The compute worker ID from the most recent heartbeat response, or None if not yet known.
  • domain: The domain from the most recent heartbeat response, or None if not yet known.