swarm-controller: validate create_agent's name via hive_types::Ident
This commit is contained in:
parent
1d31bb6e80
commit
7577d149cf
3 changed files with 19 additions and 2 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -4590,6 +4590,7 @@ dependencies = [
|
|||
"futures-util",
|
||||
"hive-jobq",
|
||||
"hive-jobq-wire",
|
||||
"hive-types",
|
||||
"reqwest 0.13.1",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ futures-util.workspace = true
|
|||
# same shape `hive-c0re/src/job_queue/scheduler.rs` uses over its own graph.
|
||||
hive-jobq.workspace = true
|
||||
hive-jobq-wire.workspace = true
|
||||
# Validates `POST /api/agents`' `name` before it becomes `agent`/`repo`
|
||||
# everywhere downstream — see `create_agent`'s doc comment for why this is
|
||||
# defense-in-depth, not the only gate (per an argus review finding).
|
||||
hive-types.workspace = true
|
||||
# `auth`'s bridge client — same crate the bridge itself uses to define the
|
||||
# request/response shape, so the two ends cannot drift. `forge.rs` also
|
||||
# uses this directly for `StatusCode` in its error-classification helpers.
|
||||
|
|
|
|||
|
|
@ -508,12 +508,21 @@ struct CreateAgentResponse {
|
|||
/// `SwarmNodeKind` variants have: each node kind's `dead_code` bound is
|
||||
/// the whole reason the executor arm and this endpoint had to land in the
|
||||
/// same change as the variant, not as a follow-up.
|
||||
///
|
||||
/// `name` is validated with [`hive_types::Ident::parse`] before it becomes
|
||||
/// `agent`/`repo` anywhere downstream — not the *only* gate (`CreateIdentity`
|
||||
/// runs first and validates server-side too), but the upstream check is a
|
||||
/// few hops removed from where an unvalidated name would do damage
|
||||
/// (`forge::seed_agent_config` interpolates `agent` into a nix comment
|
||||
/// line). Flagged in review as safe today but fragile if a second caller
|
||||
/// of these nodes ever appears; validating here closes it locally.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/agents",
|
||||
request_body = CreateAgentRequest,
|
||||
responses(
|
||||
(status = 200, description = "job chain queued", body = CreateAgentResponse),
|
||||
(status = 400, description = "`name` is not a valid identifier", body = String),
|
||||
(status = 500, description = "the job chain could not be queued", body = String),
|
||||
),
|
||||
tag = "agents"
|
||||
|
|
@ -522,12 +531,15 @@ async fn create_agent(
|
|||
State(state): State<AppState>,
|
||||
Json(req): Json<CreateAgentRequest>,
|
||||
) -> Result<Json<CreateAgentResponse>, (axum::http::StatusCode, String)> {
|
||||
let agent = hive_types::Ident::parse(&req.name)
|
||||
.map_err(|reason| (axum::http::StatusCode::BAD_REQUEST, reason.to_owned()))?
|
||||
.into_string();
|
||||
let repo = agent.clone();
|
||||
|
||||
let mut sched = state
|
||||
.jobq
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let agent = req.name;
|
||||
let repo = agent.clone();
|
||||
let ids = sched
|
||||
.insert_job(None, |b| {
|
||||
let create_identity = b.node(SwarmNodeKind::CreateIdentity {
|
||||
|
|
|
|||
Loading…
Reference in a new issue