steid

@jamesgill /

Rust1.4 KBCode·Blame·History·Raw
1//! The operator surface: routes a control plane drives, never a person.
2//!
3//! Authenticated by `STEID_OPERATOR_TOKEN` as a bearer token, compared in constant
4//! time. When no token is configured the surface does not exist — callers answer 404
5//! rather than 401, so an instance that was never given a token advertises nothing.
6
7use subtle::ConstantTimeEq;
8use topcoat::{
9 context::{Cx, app_context},
10 router::{header::AUTHORIZATION, headers},
11};
12
13use crate::application::AppConfig;
14
15/// Whether this request carries the operator token.
16///
17/// `false` both when no token is configured and when the presented one is wrong, so a
18/// caller cannot tell the two apart — the route answers 404 in either case.
19pub fn operator_authorized(cx: &Cx) -> bool {
20 let Some(expected) = app_context::<AppConfig>(cx)
21 .operator_token
22 .as_ref()
23 .map(crate::application::Secret::expose)
24 else {
25 return false;
26 };
27 let Some(presented) = bearer(cx) else {
28 return false;
29 };
30 // Length is compared by `ct_eq` too: two slices of different length are unequal
31 // without an early return that depends on where they differ.
32 presented.as_bytes().ct_eq(expected.as_bytes()).into()
33}
34
35fn bearer(cx: &Cx) -> Option<String> {
36 let header = headers(cx).get(AUTHORIZATION)?.to_str().ok()?;
37 let token = header.strip_prefix("Bearer ")?.trim();
38 (!token.is_empty()).then(|| token.to_owned())
39}