Commit a7d21ac
committed
fix(a2a): address PR #3704 review findings — security, observability, type design
Security-critical:
- Resolve A2A task lookup ambiguity: Rust runtime pre-resolves agent from
URL path and injects agent_id into task-method proxy params; Python
service refuses to guess when (task_id, no agent_id) matches multiple
rows. Prevents cross-agent task read/cancel via shared task_id.
- Encrypt push webhook auth_token at rest via services_auth.encode_auth;
new list_push_configs_for_dispatch returns decrypted tokens for the
trusted Rust sidecar only. Fixes secret-at-rest leak.
- Upsert semantics on push-config re-registration: mutable fields
(auth_token, events, enabled) update in place instead of silently
keeping stale config. Key rotations now take effect.
- Fail-closed on query-param auth decrypt failure (matches header path).
- Refuse empty/missing A2A_RUST_AUTH_SECRET at startup; add cross-field
RuntimeConfig validation (retry budget, TTL ordering, session TTL).
- Feature-flag gate on internal A2A endpoints: reject trusted requests
when MCPGATEWAY_A2A_ENABLED=false (defense-in-depth).
- events/flush rejects events for unknown task_ids (400) to prevent
visibility bypass.
Observability:
- logger.exception on _authorize_internal_a2a_method errors.
- logger.warning on agent-visibility denial across 7 internal endpoints.
- warn! on JSON parse failures in 4 proxy sites (server.rs) and
malformed Last-Event-ID headers.
- warn! on session fingerprint mismatch (security-relevant signal).
- MetricsCollector.webhook_retry_exhausted counter + record method.
- Log Rust-cache invalidation scheduling failures instead of silent pass.
- Rollback-after-failure in task persistence now logs and calls invalidate.
Type design / schema:
- New A2ATaskState enum with terminal-state validator on A2ATaskUpdate.
- Unknown task-state protocol values now warn (passed through for
forward-compat).
- Alembic: tenant=String(255), icon_url=String(767) match the ORM
(prevents Postgres VARCHAR-length drift between fresh and migrated DBs).
- Rename two A2A migration files to hash-first convention matching the
rest of the project.
- trust.rs doc/comment clarifies the header is SHA256, not HMAC.
- BTreeMap for query-param merge ensures deterministic ordering.
- encode_auth_context uses .expect() — empty header would look anonymous.
Test coverage:
- Deny-path regressions for internal A2A endpoints: RBAC denied,
wrong-team, feature-disabled (20 new cases).
- Rust↔Python bridge: ConnectError/ConnectTimeout/ReadTimeout/PoolTimeout
now wrap as RustA2ARuntimeError with correct is_timeout flag.
- Push config: encryption round-trip, token rotation, upsert semantics,
undecryptable-legacy heal path, dispatch-listing SQL visibility scope.
- Rust concurrency: session concurrent lookup/invalidate leaves storage
consistent; concurrent create produces unique IDs; queue overflow
under concurrent producers rejects with Full.
- RuntimeConfig cross-field validation (5 scenarios).
- Rust push: webhook retry-exhaustion metric increments.
- Binary startup refuses without auth_secret.
- select_downstream_agent: ORDER BY name + enabled filter assertions.
Deferred to follow-up issues:
- Typestate wrappers for trust-boundary types (#4233)
- SSE client-disconnect integration test (#4234)
Signed-off-by: Jonathan Springer <jps@s390x.com>1 parent dddd41d commit a7d21ac
File tree
24 files changed
+1648
-261
lines changed- crates/a2a_runtime
- src
- tests
- mcpgateway
- alembic/versions
- services
- tests/unit/mcpgateway
- services
24 files changed
+1648
-261
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| |||
5136 | 5136 | | |
5137 | 5137 | | |
5138 | 5138 | | |
5139 | | - | |
| 5139 | + | |
5140 | 5140 | | |
5141 | 5141 | | |
5142 | 5142 | | |
5143 | 5143 | | |
5144 | 5144 | | |
5145 | 5145 | | |
5146 | 5146 | | |
5147 | | - | |
| 5147 | + | |
5148 | 5148 | | |
5149 | 5149 | | |
5150 | 5150 | | |
5151 | 5151 | | |
5152 | 5152 | | |
5153 | 5153 | | |
5154 | 5154 | | |
5155 | | - | |
| 5155 | + | |
5156 | 5156 | | |
5157 | 5157 | | |
5158 | 5158 | | |
5159 | 5159 | | |
5160 | 5160 | | |
5161 | 5161 | | |
5162 | 5162 | | |
5163 | | - | |
| 5163 | + | |
5164 | 5164 | | |
5165 | 5165 | | |
5166 | 5166 | | |
| |||
7502 | 7502 | | |
7503 | 7503 | | |
7504 | 7504 | | |
7505 | | - | |
| 7505 | + | |
7506 | 7506 | | |
7507 | 7507 | | |
7508 | 7508 | | |
7509 | 7509 | | |
7510 | 7510 | | |
7511 | 7511 | | |
7512 | 7512 | | |
7513 | | - | |
| 7513 | + | |
7514 | 7514 | | |
7515 | 7515 | | |
7516 | 7516 | | |
7517 | 7517 | | |
7518 | 7518 | | |
7519 | 7519 | | |
7520 | 7520 | | |
7521 | | - | |
| 7521 | + | |
7522 | 7522 | | |
7523 | 7523 | | |
7524 | 7524 | | |
7525 | 7525 | | |
7526 | 7526 | | |
7527 | 7527 | | |
7528 | 7528 | | |
7529 | | - | |
| 7529 | + | |
7530 | 7530 | | |
7531 | 7531 | | |
7532 | 7532 | | |
7533 | 7533 | | |
7534 | 7534 | | |
7535 | 7535 | | |
7536 | 7536 | | |
7537 | | - | |
| 7537 | + | |
7538 | 7538 | | |
7539 | 7539 | | |
7540 | 7540 | | |
7541 | 7541 | | |
7542 | 7542 | | |
7543 | 7543 | | |
7544 | 7544 | | |
7545 | | - | |
| 7545 | + | |
7546 | 7546 | | |
7547 | 7547 | | |
7548 | 7548 | | |
7549 | 7549 | | |
7550 | 7550 | | |
7551 | 7551 | | |
7552 | 7552 | | |
7553 | | - | |
| 7553 | + | |
7554 | 7554 | | |
7555 | 7555 | | |
7556 | 7556 | | |
7557 | 7557 | | |
7558 | 7558 | | |
7559 | 7559 | | |
7560 | 7560 | | |
7561 | | - | |
| 7561 | + | |
7562 | 7562 | | |
7563 | 7563 | | |
7564 | 7564 | | |
7565 | 7565 | | |
7566 | 7566 | | |
7567 | 7567 | | |
7568 | 7568 | | |
7569 | | - | |
| 7569 | + | |
7570 | 7570 | | |
7571 | 7571 | | |
7572 | 7572 | | |
7573 | 7573 | | |
7574 | 7574 | | |
7575 | 7575 | | |
7576 | 7576 | | |
7577 | | - | |
| 7577 | + | |
7578 | 7578 | | |
7579 | 7579 | | |
7580 | 7580 | | |
7581 | 7581 | | |
7582 | 7582 | | |
7583 | 7583 | | |
7584 | 7584 | | |
7585 | | - | |
7586 | | - | |
7587 | | - | |
7588 | | - | |
7589 | | - | |
7590 | | - | |
7591 | | - | |
7592 | | - | |
7593 | | - | |
| 7585 | + | |
7594 | 7586 | | |
7595 | 7587 | | |
7596 | 7588 | | |
7597 | 7589 | | |
7598 | 7590 | | |
7599 | 7591 | | |
7600 | 7592 | | |
7601 | | - | |
| 7593 | + | |
7602 | 7594 | | |
7603 | 7595 | | |
7604 | 7596 | | |
7605 | 7597 | | |
7606 | 7598 | | |
7607 | 7599 | | |
7608 | 7600 | | |
7609 | | - | |
| 7601 | + | |
7610 | 7602 | | |
7611 | 7603 | | |
7612 | 7604 | | |
7613 | 7605 | | |
7614 | 7606 | | |
7615 | 7607 | | |
7616 | 7608 | | |
7617 | | - | |
| 7609 | + | |
7618 | 7610 | | |
7619 | 7611 | | |
7620 | 7612 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
131 | 131 | | |
132 | 132 | | |
133 | 133 | | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
134 | 139 | | |
135 | | - | |
136 | | - | |
| 140 | + | |
137 | 141 | | |
138 | 142 | | |
139 | 143 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
202 | 202 | | |
203 | 203 | | |
204 | 204 | | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
205 | 260 | | |
206 | 261 | | |
207 | 262 | | |
| |||
287 | 342 | | |
288 | 343 | | |
289 | 344 | | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
290 | 399 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
56 | 76 | | |
57 | 77 | | |
58 | 78 | | |
| |||
131 | 151 | | |
132 | 152 | | |
133 | 153 | | |
134 | | - | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
135 | 158 | | |
136 | 159 | | |
137 | 160 | | |
| |||
288 | 311 | | |
289 | 312 | | |
290 | 313 | | |
291 | | - | |
| 314 | + | |
292 | 315 | | |
293 | 316 | | |
294 | 317 | | |
| |||
353 | 376 | | |
354 | 377 | | |
355 | 378 | | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
356 | 403 | | |
357 | 404 | | |
358 | 405 | | |
| |||
0 commit comments