Runs the admin server until `shutdown` is cancelled.
(
pool: PostgresStorePool,
config: AdminConfig,
shutdown: CancellationToken,
)
| 221 | |
| 222 | /// Runs the admin server until `shutdown` is cancelled. |
| 223 | pub(crate) async fn run_admin_server( |
| 224 | pool: PostgresStorePool, |
| 225 | config: AdminConfig, |
| 226 | shutdown: CancellationToken, |
| 227 | ) -> Result<(), Report<GraphError>> { |
| 228 | let jwt_validator = match (config.jwt.jwks_url, config.jwt.audience, config.jwt.issuer) { |
| 229 | (Some(jwks_url), Some(audience), Some(issuer)) => { |
| 230 | if config.unsafe_allow_dev_authentication { |
| 231 | // Clap `conflicts_with` should prevent this, but guard against it anyway. |
| 232 | return Err(Report::new(GraphError).attach( |
| 233 | "--unsafe-allow-dev-authentication cannot be used with JWT authentication. \ |
| 234 | Remove the flag or the JWT configuration.", |
| 235 | )); |
| 236 | } |
| 237 | tracing::info!(%jwks_url, "JWT authentication enabled for admin API"); |
| 238 | Some(Arc::new(JwtValidator::new(JwtValidatorConfig { |
| 239 | jwks_url, |
| 240 | audience, |
| 241 | issuer, |
| 242 | jwks_cache_ttl: Duration::from_secs(config.jwt.jwks_cache_ttl_secs), |
| 243 | jwks_refresh_cooldown: Duration::from_secs(config.jwt.jwks_refresh_cooldown_secs), |
| 244 | http_timeout: Duration::from_secs(config.jwt.http_timeout_secs), |
| 245 | allowed_algorithms: config.jwt.allowed_algorithms, |
| 246 | }))) |
| 247 | } |
| 248 | (None, None, None) if config.unsafe_allow_dev_authentication => { |
| 249 | tracing::warn!( |
| 250 | "--unsafe-allow-dev-authentication is set -- header-based authentication is \ |
| 251 | enabled without verification. DO NOT use this in production." |
| 252 | ); |
| 253 | None |
| 254 | } |
| 255 | (None, None, None) => { |
| 256 | return Err(Report::new(GraphError).attach( |
| 257 | "no JWT authentication configured and --unsafe-allow-dev-authentication is not \ |
| 258 | set. Either configure JWT (--jwt-jwks-url, --jwt-audience, --jwt-issuer) or pass \ |
| 259 | --unsafe-allow-dev-authentication for local development.", |
| 260 | )); |
| 261 | } |
| 262 | _ => { |
| 263 | // Clap `requires` should prevent this, but guard against it anyway. |
| 264 | return Err(Report::new(GraphError).attach( |
| 265 | "partial JWT configuration: --jwt-jwks-url, --jwt-audience, and --jwt-issuer must \ |
| 266 | all be provided together", |
| 267 | )); |
| 268 | } |
| 269 | }; |
| 270 | |
| 271 | let kratos_admin_url = config.external_services.kratos_admin_url.ok_or_else(|| { |
| 272 | Report::new(GraphError).attach( |
| 273 | "--kratos-admin-url (HASH_KRATOS_ADMIN_URL) is required when running the admin server", |
| 274 | ) |
| 275 | })?; |
| 276 | let hydra_admin_url = config.external_services.hydra_admin_url.ok_or_else(|| { |
| 277 | Report::new(GraphError).attach( |
| 278 | "--hydra-admin-url (HASH_HYDRA_ADMIN_URL) is required when running the admin server", |
| 279 | ) |
| 280 | })?; |
no test coverage detected