(
endpoint: &str,
plain_channel: &Channel,
sa_path: &str,
)
| 281 | } |
| 282 | |
| 283 | async fn acquire_k8s_sandbox_token( |
| 284 | endpoint: &str, |
| 285 | plain_channel: &Channel, |
| 286 | sa_path: &str, |
| 287 | ) -> Result<String> { |
| 288 | let sa_token = std::fs::read_to_string(sa_path) |
| 289 | .into_diagnostic() |
| 290 | .wrap_err_with(|| format!("failed to read K8s SA token from {sa_path}"))? |
| 291 | .trim() |
| 292 | .to_string(); |
| 293 | info!(endpoint = %endpoint, "exchanging K8s ServiceAccount token for sandbox JWT"); |
| 294 | // The bootstrap exchange uses a one-off interceptor pinned to the |
| 295 | // SA token; the resulting gateway JWT becomes the value in the |
| 296 | // shared `TOKEN_SLOT` once `connect_channel` returns. |
| 297 | let bootstrap_slot: TokenSlot = Arc::new(RwLock::new( |
| 298 | AsciiMetadataValue::try_from(format!("Bearer {sa_token}")) |
| 299 | .into_diagnostic() |
| 300 | .wrap_err("SA token contained characters not valid for a header value")?, |
| 301 | )); |
| 302 | let interceptor = AuthInterceptor::new(bootstrap_slot); |
| 303 | let bootstrap = InterceptedService::new(plain_channel.clone(), interceptor); |
| 304 | let mut client = OpenShellClient::new(bootstrap); |
| 305 | let resp = client |
| 306 | .issue_sandbox_token(IssueSandboxTokenRequest {}) |
| 307 | .await |
| 308 | .into_diagnostic() |
| 309 | .wrap_err("IssueSandboxToken bootstrap exchange failed")?; |
| 310 | Ok(resp.into_inner().token) |
| 311 | } |
| 312 | |
| 313 | /// Build an authenticated channel for direct external use (e.g. the |
| 314 | /// long-lived `supervisor_session` control stream). |
no test coverage detected