Obtain launch measurements

Prepare approved node and router identity policies from build and deployment records, and keep the external CDS image and configuration pin separate.

Prepare the expected identities before deploying c8s. On AMD SEV-SNP, the image pin contains a SHA-384 launch digest. On Intel TDX, it contains the firmware measurement (MRTD) together with runtime measurement registers RTMR[1] and RTMR[2] from the same build. An MRTD-only pin leaves the guest kernel and rootfs unmeasured by that policy.

Image measurements alone do not pin mutable policy or deployment configuration. Keep the node identities admitted by the Certificate Distribution Service (CDS), the router's node identity, and the external CDS's own image/configuration identity separate. See the trust root for their trust boundaries.

Prerequisites

  • The c8s CLI on your workstation's PATH.
  • Approved image and deployment records from your image producer or operator. Retain the exact build's manifest and boot artifacts together, including the selected SEV-SNP vCPU variant when applicable. A manifest's presence does not establish its provenance.
  • For managed Azure nodes without a compatible build manifest, the complete policies described under Node CVMs on stock Azure images.

Derive policies for measured c8s images

Use this path when you have the image producer's reviewed manifest.json. For an existing deployment, obtain its retained launch policies from the operator; generating new launch keys creates a different identity.

Extract the image values

c8s measurements derive '<NODE_MANIFEST_JSON>' --tee '<NODE_TEE>' \
  --out node-images.json
c8s measurements lint node-images.json

Replace <NODE_MANIFEST_JSON> with the exact node build's manifest path and <NODE_TEE> with sev-snp or tdx, matching that build. A build directory containing manifest.json also works. --tee selects the platform when the manifest contains both.

The command converts manifest values into a JSON image policy: one entry per SEV-SNP vCPU variant, or a TDX entry containing MRTD, RTMR[1], and RTMR[2]. Multiple inputs must use the same platform. Successful linting prints ok: with the platform and image count; it checks the policy format, not the build's provenance or measurement calculation.

Retain node-images.json to inspect the extracted image values. The next step reads the manifest again and generates policies with the new deployment's launch-key bindings.

For an independent calculation, use the exact build's firmware, kernel, initrd, command line, and platform-specific launch procedure. A tool such as sev-snp-measure is a possible SEV-SNP calculation tool, but a generic kernel invocation is not a verified recipe for the current IGVM artifacts. Obtain the producer's procedure and compare its result with the manifest's matching vCPU variant. On TDX, compare the whole MRTD/RTMR[1]/RTMR[2] tuple. See independent recomputation.

Bind a new node deployment and its CDS

For a new cluster using the measured c8s node image, generate its launch bundle. This example uses SEV-SNP for both the node and CDS:

c8s node launch-config new --out node-bundle --cluster-id '<CLUSTER_ID>' \
  --image-manifest '<NODE_MANIFEST_JSON>' --vcpus '<NODE_VCPU_COUNT>' \
  --cds-address '<CDS_HOST>:8443' \
  --cds-image-manifest '<CDS_MANIFEST_JSON>' --cds-platform sev-snp \
  --cds-vcpus '<CDS_VCPU_COUNT>' \
  --cds-node-cidr '<NODE_CIDR>' --cds-allowlist-seed '<COMPONENT_SEED_JSON>'

Replace the placeholders with these prepared inputs:

  • <CLUSTER_ID>: the cluster name you assign, as an RFC 1123 label.
  • <NODE_MANIFEST_JSON> and <CDS_MANIFEST_JSON>: manifests from the approved node and CDS build bundles. The CDS runs in its own confidential VM (CVM).
  • <NODE_VCPU_COUNT> and <CDS_VCPU_COUNT>: supported counts from the respective manifests. Retain the matching IGVM boot artifacts for launch.
  • <CDS_HOST>: the planned CDS DNS name or IPv4 address, reachable by its clients on TCP 8443.
  • <NODE_CIDR>: the subnet holding node inventory addresses CDS may contact. Repeat --cds-node-cidr for additional subnets; exclude the baked image's pod and service ranges, 10.52.0.0/16 and 10.53.0.0/16.
  • <COMPONENT_SEED_JSON>: the matching release's allowlist-seed-snp.json, supplied with your approved node build inputs.

node-bundle must not exist. The command generates launch keys, join credentials, a signed c8s-launch/v2 server document, and these policy artifacts:

  • server.json binds the node image and server launch key. Use it for the router when the router runs on that server.
  • peers.json binds the node image under the server and agent launch keys. Review the whole admitted set, including the agent identity even when this command creates only a server.
  • cds-config.yaml is the external CDS's c8s-cds/v1 launch configuration. It includes the node policy, operator public key, component seed, and inventory subnets.
  • cds-pin.json binds the CDS image and the exact cds-config.yaml bytes. Keep this pin separate from server.json and peers.json.

Protect the generated private keys and join credentials. The CDS configuration is host-readable and carries public inputs; keep private keys and secrets out of it. Optional tenant workloads enter the generator through --tenant-workloads, which adds them to the CDS configuration.

For TDX nodes, supply their manifest, omit --vcpus, and use the matching release's allowlist-seed-tdx.json for <COMPONENT_SEED_JSON>. Obtain that seed with your approved node build inputs. For a TDX CDS, use its manifest, --cds-platform tdx, and omit --cds-vcpus. The CDS and nodes can use different platforms; the component seed matches the nodes. See the node CVM launch contract for agents, launch-media bindings, and the remaining launch inputs.

Check and retain the generated policies

c8s measurements lint node-bundle/server.json
c8s measurements lint node-bundle/peers.json
c8s measurements lint node-bundle/cds-pin.json

Require each command to succeed, then review the image values and launch bindings against your intended deployment. Retain the policies with the approved manifests and launch inputs. Linting establishes that the documents parse; live attestation establishes whether a target matches them.

Node CVMs on stock Azure images

For AKS or another Azure node image without a compatible build manifest, obtain two complete JSON image policies from your trusted image producer or deployment operator before preparing the external CDS or installing c8s:

  • nodes-policy.json: the exact set of node launch identities CDS may admit.
  • router-pin.json: the identities acceptable for nodes hosting the router. Reuse the node policy only when its entire set is acceptable for the router.

Require the provider-specific image values and applicable launch bindings for your deployed node image and configuration. On TDX, require the full MRTD/RTMR[1]/RTMR[2] tuple. The manifest conversion above requires a compatible producer manifest; this guide does not establish an Azure-specific procedure for calculating these policies from a stock image. If your producer or operator cannot supply approved values, this prerequisite remains unmet.

c8s measurements lint nodes-policy.json
c8s measurements lint router-pin.json

Successful parsing does not approve those identities. Independently review their provenance and deployment scope. A running node's report can show observed values for comparison; accepting those values solely because that node reports them is trust-on-first-use. Do not use a responder's own claimed policy to approve it. Review replacement values through the same process when the provider changes the node image.

Pass nodes-policy.json to c8s cds config new --node-pins as part of Install c8s. That procedure generates the separate CDS configuration and cds-pin.json, launches and verifies CDS, retains the mesh CA, and installs using --cds-address with --cds-pin.

Check each target against its own policy

After launch, check the external CDS with its own pin and the independently intended current node set:

c8s cds verify 'https://<CDS_HOST>:8443' \
  --image-policy-file '<CDS_PIN_JSON>' --served-policy-file '<NODE_POLICY_JSON>'

<CDS_HOST> is the actual external CDS endpoint. <CDS_PIN_JSON> is the generated CDS image/configuration pin: node-bundle/cds-pin.json for the measured-node path, or cds-bootstrap/cds-pin.json from the installation procedure. <NODE_POLICY_JSON> is node-bundle/peers.json or your approved nodes-policy.json, provided it still describes the intended current set. The measured configuration supplies singleton CDS's node policy and the default for high-availability (HA) Genesis, the signed initialization decree that starts the HA cluster. Genesis can select another set, and later signed commands can change it. When either selects a different set, use the independently approved current node policy instead of the generated initial policy. --served-policy-file explicitly compares that live served set; the CDS identity check alone does not perform this comparison.

For the router, retain mesh-ca.pem through the pinned CDS CA procedure, replacing cds-pin.json in that procedure with the <CDS_PIN_JSON> path selected above. Then verify with the approved router-node policy:

c8s verify 'https://<ROUTER_ADDRESS>:443' --kind lb \
  --server-name '<ROUTER_SNI_NAME>' \
  --image-policy-file '<ROUTER_POLICY_JSON>' --mesh-ca mesh-ca.pem

Replace <ROUTER_ADDRESS> with the router's reachable address and <ROUTER_SNI_NAME> with its TLS Server Name Indication (SNI) name, such as its configured certificate hostname. --server-name selects SNI; this command does not check certificate hostname equality. <ROUTER_POLICY_JSON> is node-bundle/server.json for the baked server's router, or your approved router-pin.json. Use a direct network path or a load balancer that passes TLS through to the router. Keep the CDS pin for the CDS check.

Require verification exit code 0 and inspect warnings. Router discovery evidence describes certificate issuance and is not fresh evidence from this verification attempt. See Verify a deployment for fresh checks, verdict scope, and failure handling.