2. Establish Auth target identity and trust
The Auth Site needs two distinct trust relationships before its first signed policy can load. Its distribution target key authenticates the bundle agent to Control. The Control bundle signer public key lets Auth verify what Control published. A client’s request-signing key is created later.
Previous: Register and verify an Auth Site. Next: Install and activate Auth.
Register the target’s public key
Section titled “Register the target’s public key”Use the exact environment, fleet, site and distribution-target IDs read from Control. Download
and checksum-verify a released CLI archive before running it. The
inspected public CLI archive is v0.2.5; check the release reference
again when performing this step.
In an owner-only working directory:
umask 077./trustplane auth-plane init \ --target-id '<DISTRIBUTION_TARGET_ID>' \ --environment-id '<ENVIRONMENT_ID>' \ --fleet-id '<FLEET_ID>' \ --site-id '<SITE_ID>' \ --private-key-out ./target-private-key \ --registration-out ./auth-site-registration.jsonauth-plane init creates a persistent Ed25519 private-key file and a public registration
document bound to these four IDs. The private file must be mode 0600; on macOS check with
stat -f '%Lp' ./target-private-key, or on Linux with stat -c '%a' ./target-private-key.
Inspect auth-site-registration.json without printing private material. Upload/register only
that public document in Control’s Bootstrap Auth Site target-key step. Compare Control’s
derived fingerprint with the local public fingerprint. Keep the same private key for the Auth
deployment; Control must never receive it. A mismatch is a stop condition.
Define the first protected endpoint
Section titled “Define the first protected endpoint”In the selected, ownership-verified Auth Site’s first-run flow, name the API that Auth will
front, confirm the Auth-facing surface URL, choose Exact path matching, enter the full
protected path, select Read only (GET / HEAD), and save Create protected surface. In
the isolated tutorial, the API was First-run echo API and the full path was
/tutorial/echo (not /echo). The read-only preset materialized two operations, GET and
HEAD, for that one exact path. Open Protected Surfaces → Inspect → Operations to confirm
the selected site, active/verified surface, path and methods.
This registers a Control access rule; it does not implement the private backend, deploy Auth, or grant any client access. The private echo backend is installed in chapter 3. A client key and grant come in chapter 4. Control’s automatic initial deny-all generation requires this authorable surface and a paired Auth agent capability. The Protected Surfaces reference explains its readiness states.
Pin Control’s public signing root before Auth starts
Section titled “Pin Control’s public signing root before Auth starts”The bundle agent requires --control-signing-public-key-file at startup. Control never gives
the tenant the signer private key. The tenant admin can obtain the public half from the
site’s own Bootstrap handoff before starting Auth:
- Tenant-admin pre-publication: In the same selected site, complete the client, narrow
GET/HEAD /tutorial/echopolicy and public-key registration in Chapter 4 before installing Auth. The client private key stays with the workload. In Auth Site Detail → Readiness, use Publish safe recovery version for this exact site and read back the promoted bundle version. This action publishes configuration; it does not prove an Auth instance has loaded it. In Bootstrap, require areadysite-scoped handoff, matching environment/fleet/site/target IDs, a nonempty Control signer fingerprint, and the public-key download. Download the exact public-key file and bootstrap ZIP. A tenant admin uses their ordinary Control session; no super-admin credential is involved. A pre-start promotion may be signed but lack the paired bundle-set ID, because Auth has not yet reported itstrustplane.bundle-set.v1capability. The handoff is still the verified source of the public signer key. When Auth first polls, it reports that capability; Control then reconciles and promotes a paired package. The waiting agent retries until the paired package loads. Do not treat the pre-start handoff as proof that Auth is activated. - Deny-all-first deployment: If Auth starts with no client key or grant, independently provision the configured Control signer public key and fingerprint; the signed paired deny-all package follows after Auth reports capability. This path needs that public-root handoff from whoever operates the Control signer for the deployment. The site-scoped download available after promotion serves as a consistency check, not the source for that first start.
For either sequence, place only the public key in control-signing-public-key and verify both
its Ed25519 format and fingerprint before making a Kubernetes Secret. Control’s fingerprint is
the SHA-256 of the decoded 32-byte public key; the handoff also supplies the SHA-256 of the
base64url file bytes. Enter the two expected values from the selected site’s trusted
Bootstrap readback, or from the deployment operator’s independently checked record for the
deny-all-first path:
export TP_EXPECTED_SIGNER_FINGERPRINT='sha256:<64 hex digits from Control or operator>'export TP_EXPECTED_SIGNER_FILE_SHA256='sha256:<64 hex digits from Control or operator>'python3 - <<'PY'import base64import hashlibimport osimport refrom pathlib import Path
raw_file = Path("control-signing-public-key").read_bytes()text = raw_file.decode("ascii").strip()if not re.fullmatch(r"[A-Za-z0-9_-]+", text): raise SystemExit("Signer file is not raw base64url Ed25519 public key text")key = base64.b64decode(text + "=" * (-len(text) % 4), altchars=b"-_", validate=True)if len(key) != 32: raise SystemExit("Signer public key is not 32 bytes")fingerprint = "sha256:" + hashlib.sha256(key).hexdigest()file_hash = "sha256:" + hashlib.sha256(raw_file).hexdigest()if fingerprint != os.environ["TP_EXPECTED_SIGNER_FINGERPRINT"]: raise SystemExit("Decoded signer fingerprint does not match")if file_hash != os.environ["TP_EXPECTED_SIGNER_FILE_SHA256"]: raise SystemExit("Signer file checksum does not match")print("Control signer public key format and both hashes match")PYStop if the selected-site handoff is unavailable, the source record cannot be independently trusted, the file fails validation, or the two hashes disagree. Do not substitute the Auth target public key or a client public key. After Auth loads its first package, compare the site-scoped ZIP’s public key byte-for-byte with the pinned startup file.
Next: Show the real Auth configuration, installation and exact activation.