@@ -25,33 +25,6 @@ pub struct EnrollmentJwtClaims {
2525 /// Suggested agent display name (optional hint).
2626 #[ serde( default ) ]
2727 pub jet_agent_name : Option < String > ,
28- /// QUIC endpoint (`host:port`) the agent should connect to for the tunnel.
29- ///
30- /// # Why the operator must supply this
31- ///
32- /// A running gateway has no way to discover the address its clients actually
33- /// route to: that is a view from outside the host, not from inside. The moment
34- /// there is any translation layer between the gateway and the agent, a
35- /// self-reported `conf.hostname:listen_port` will differ from what the agent
36- /// needs. Common cases:
37- ///
38- /// 1. **Docker / Kubernetes**: `conf.hostname` defaults to the container ID or
39- /// pod name, which is not resolvable outside the bridge/cluster network.
40- /// 2. **Split-horizon DNS / NAT**: the gateway knows itself by an internal
41- /// name that does not resolve (or resolves to a different IP) from the
42- /// agent's network.
43- /// 3. **HA behind a load balancer**: individual gateway nodes have per-node
44- /// hostnames, but agents must connect to the LB VIP or a stable DNS name.
45- ///
46- /// Rather than silently shipping a wrong self-report and hoping the operator
47- /// notices when tunnels fail, the gateway deliberately does NOT return a QUIC
48- /// endpoint from its enroll API. The operator — who designed the network —
49- /// supplies the correct address here when minting the enrollment JWT.
50- ///
51- /// Optional at the JWT level only because the `--quic-endpoint` CLI flag can
52- /// provide it instead. The agent refuses to start if neither is given.
53- #[ serde( default ) ]
54- pub jet_quic_endpoint : Option < String > ,
5528}
5629
5730/// Decode an enrollment JWT to extract agent-side configuration claims.
@@ -103,6 +76,7 @@ struct EnrollResponse {
10376 agent_id : Uuid ,
10477 client_cert_pem : String ,
10578 gateway_ca_cert_pem : String ,
79+ quic_endpoint : String ,
10680 server_spki_sha256 : String ,
10781}
10882
@@ -123,35 +97,17 @@ pub struct PersistedEnrollment {
12397/// * `enrollment_token` - JWT token for enrollment
12498/// * `agent_name` - Friendly name for this agent
12599/// * `advertise_subnets` - List of subnets to advertise (e.g., ["10.0.0.0/8"])
126- /// * `advertise_domains` - List of DNS domains to advertise (e.g., ["corp.example.com"]).
127- /// When non-empty, replaces any previously-persisted explicit domains; auto-detected
128- /// domains are still added on top at runtime if `auto_detect_domain` is enabled.
129- /// * `quic_endpoint` - QUIC endpoint (`host:port`) the agent should connect to for the
130- /// tunnel. The gateway does not report this: a running process cannot know the address
131- /// its clients actually route to (Docker/K8s, NAT, split-horizon DNS, LB VIP). The
132- /// operator supplies it via the `jet_quic_endpoint` JWT claim or the `--quic-endpoint`
133- /// CLI flag. See [`EnrollmentJwtClaims::jet_quic_endpoint`] for the full rationale.
134100pub async fn enroll_agent (
135101 gateway_url : & str ,
136102 enrollment_token : & str ,
137103 agent_name : & str ,
138104 advertise_subnets : Vec < String > ,
139- advertise_domains : Vec < String > ,
140- quic_endpoint : String ,
141105) -> Result < PersistedEnrollment > {
142106 // Generate key pair and CSR locally — the private key never leaves this machine.
143107 let ( key_pem, csr_pem) = generate_key_and_csr ( agent_name) ?;
144108
145109 let enroll_response = request_enrollment ( gateway_url, enrollment_token, agent_name, & csr_pem) . await ?;
146-
147- persist_enrollment_response (
148- agent_name,
149- advertise_subnets,
150- advertise_domains,
151- enroll_response,
152- quic_endpoint,
153- & key_pem,
154- )
110+ persist_enrollment_response ( agent_name, advertise_subnets, enroll_response, & key_pem)
155111}
156112
157113/// Generate an ECDSA P-256 key pair and a CSR containing the agent name as CN.
@@ -208,14 +164,13 @@ async fn request_enrollment(
208164fn persist_enrollment_response (
209165 agent_name : & str ,
210166 advertise_subnets : Vec < String > ,
211- advertise_domains : Vec < String > ,
212167 EnrollResponse {
213168 agent_id,
214169 client_cert_pem,
215170 gateway_ca_cert_pem,
171+ quic_endpoint,
216172 server_spki_sha256,
217173 } : EnrollResponse ,
218- quic_endpoint : String ,
219174 key_pem : & str ,
220175) -> Result < PersistedEnrollment > {
221176 let config_path = config:: get_conf_file_path ( ) ;
@@ -269,13 +224,7 @@ fn persist_enrollment_response(
269224 client_key_path : Some ( client_key_path. clone ( ) ) ,
270225 gateway_ca_cert_path : Some ( gateway_ca_path. clone ( ) ) ,
271226 advertise_subnets,
272- // CLI-supplied domains win; otherwise preserve any domains previously
273- // configured on disk (manual edit / earlier enrollment).
274- advertise_domains : if advertise_domains. is_empty ( ) {
275- existing_tunnel. map ( |t| t. advertise_domains . clone ( ) ) . unwrap_or_default ( )
276- } else {
277- advertise_domains
278- } ,
227+ advertise_domains : existing_tunnel. map ( |t| t. advertise_domains . clone ( ) ) . unwrap_or_default ( ) ,
279228 auto_detect_domain : existing_tunnel. map ( |t| t. auto_detect_domain ) . unwrap_or ( true ) ,
280229 heartbeat_interval_secs : Some ( 60 ) ,
281230 route_advertise_interval_secs : Some ( 30 ) ,
0 commit comments