fix: generate AuthBridge routes in separate ConfigMap with correct format - #517
fix: generate AuthBridge routes in separate ConfigMap with correct format#517Alan-Cha wants to merge 9 commits into
Conversation
AuthBridge's token-exchange plugin in proxy-sidecar mode expects routes
to be loaded from an external file, not inlined in config.yaml. Inline
routes cause unmarshal errors at runtime.
Changes:
- Generate routes.yaml in separate authbridge-routes-<crName> ConfigMap
- Set config.routes to {file: "/etc/authproxy/routes.yaml"} instead of inline array
- Add overrideRoutesConfigMapInVolumes() to mount per-agent routes ConfigMap
- Update ensurePerAgentConfigMap() to return both config and routes CM names
Fixes: rossoctl/rossoctl#2334
Signed-off-by: Alan Cha <Alan.cha1@ibm.com>
Routes must use AuthBridge's flat YAML structure:
- host: "hostname" (flat field, not nested under destination)
- target_audience: "audience" (single string, not audiences array)
Previous bug generated AgentRuntime CRD format:
- destination:
host: "hostname"
audiences:
- "audience"
This caused AuthBridge to fail loading routes, resulting in
"no matching route" errors even though routes.yaml existed.
The router strips ports before matching, so routes should not include
ports in the host field.
Signed-off-by: Alan Cha <Alan.cha1@ibm.com>
The function now returns (configCMName, routesCMName, error) instead of (configCMName, error). Update all test callers to handle the new signature. Assisted-By: Claude Code Signed-off-by: Alan Cha <Alan.cha1@ibm.com>
…ormat The test was checking for inline routes in config.yaml, but the implementation now generates routes in a separate ConfigMap and references it via file path. Updated test to: - Verify config.yaml contains routes file reference - Fetch the separate routes ConfigMap - Parse routes.yaml from that ConfigMap - Check for flat route format (host + target_audience) instead of nested format Assisted-By: Claude Code Signed-off-by: Alan Cha <Alan.cha1@ibm.com>
clawgenti
left a comment
There was a problem hiding this comment.
Fixes two real bugs (inline routes crash + wrong route format) and the approach is clean. A few items worth addressing before merge.
- Silent audience truncation: when , only is used with no warning; operators who specify multiple audiences will silently lose the extras.
- Shadowed
errvariable (line 1353):var err errorinside theif agentRuntime != nilblock shadows the named returnerr, so a marshal failure there won't set the named return — the error is still returned via the explicitreturn "", "", err, but this is fragile and should use the named return directly. overrideRoutesConfigMapInVolumeshas no unit test: the newvolume_builder.gofunction follows the same pattern asoverrideAuthBridgeConfigMapInVolumesbut lacks a corresponding test case.
Reviewed by clawgenti using the github-pr-review skill
…warning **Path constants:** - Define AuthProxyMountPath and AuthProxyRoutesFile in namespace_config.go - Replace all hardcoded "/etc/authproxy" and "/etc/authproxy/routes.yaml" strings - Improves maintainability by centralizing path definitions **Multiple audiences validation:** - Add warning log when AgentRuntime.spec.auth.outbound route has >1 audience - Only first audience is used (AuthBridge limitation) - Addresses issue #518 Assisted-By: Claude Code Signed-off-by: Alan Cha <Alan.cha1@ibm.com>
…ride test **Shadowed variable fix:** - Remove `var err error` inside agentRuntime block (line 1363) - Use the function's named return parameter directly - Prevents fragile error handling where marshal failure might not propagate **Test coverage:** - Add TestOverrideRoutesConfigMapInVolumes following the pattern of TestOverrideEnvoyConfigMapInVolumes - Verifies volume swap without mutation - Checks that Optional is set to false for per-agent routes Addresses review comments from #517 Assisted-By: Claude Code Signed-off-by: Alan Cha <Alan.cha1@ibm.com>
|
All review comments addressed in commit 9eb2aaf: ✅ Silent audience truncation - Already fixed in d4a121a. Added warning log when multiple audiences specified: if len(outboundRoute.Audiences) > 1 {
mutatorLog.Info("multiple audiences specified but only first will be used",
"namespace", namespace, "crName", crName,
"route", outboundRoute.Destination.Host,
"audiences", outboundRoute.Audiences,
"using", outboundRoute.Audiences[0])
}Also filed issue #518 for tracking. ✅ Shadowed ✅ Missing unit test - Added
|
Signed-off-by: Alan Cha <Alan.cha1@ibm.com>
…ride test **Shadowed variable fix:** - Remove `var err error` inside agentRuntime block (line 1363) - Use the function's named return parameter directly - Prevents fragile error handling where marshal failure might not propagate **Test coverage:** - Add TestOverrideRoutesConfigMapInVolumes following the pattern of TestOverrideEnvoyConfigMapInVolumes - Verifies volume swap without mutation - Checks that Optional is set to false for per-agent routes Addresses review comments from #517 Assisted-By: Claude Code Signed-off-by: Alan Cha <Alan.cha1@ibm.com>
9eb2aaf to
2bf20d8
Compare
clawgenti
left a comment
There was a problem hiding this comment.
Refactors AuthBridge routes from inline config.yaml injection to a separate ConfigMap, replacing hardcoded paths with named constants — clean and well-structured change overall.
Findings:
- Silent truncation of multiple audiences (only
Audiences[0]used) with a warn log but no error return — callers with multiple audiences will silently lose entries. HostRegexis mapped to thehostfield with a comment noting the semantic mismatch; this is a behavioral change with no fallback or error.
Reviewed by clawgenti using the github-pr-review skill
| // target_audience is a single string, not array | ||
| // Take first audience if multiple specified | ||
| if len(outboundRoute.Audiences) > 0 { | ||
| route["target_audience"] = outboundRoute.Audiences[0] |
There was a problem hiding this comment.
Only the first audience is used and the rest are silently dropped — the warning log is good but callers relying on multiple audiences (possible today or via future API extensions) will get no error. Consider returning an error or at minimum documenting this limitation in the field's godoc/API type. Tracking issue #518 is referenced, but that issue should probably be linked in the AgentRuntime CRD validation too.
| } | ||
| if outboundRoute.Destination.HostRegex != "" { | ||
| // AuthBridge router doesn't support hostRegex - use glob pattern in host field | ||
| route["host"] = outboundRoute.Destination.HostRegex |
There was a problem hiding this comment.
Mapping HostRegex directly to the host field is a silent semantic change: a regex pattern (e.g. .*\.team1\.svc\.cluster\.local) will be passed where AuthBridge expects a glob. If AuthBridge doesn't support regex syntax at all, this will silently fail to match at runtime with no observable error at admission time. Consider validating the regex-to-glob conversion or adding a more explicit warning/event.
…yRoutesConfigMapName constant Addresses goconst linter error - use existing constant instead of repeating the string literal 3+ times. Assisted-By: Claude Code Signed-off-by: Alan Cha <Alan.cha1@ibm.com>
clawgenti
left a comment
There was a problem hiding this comment.
All three items from the previous review have been addressed cleanly: shadowed err is gone, the audience-truncation warning is in place, and overrideRoutesConfigMapInVolumes has a proper unit test. One residual suggestion below.
HostRegexis silently coerced tohost(line 1341): a regex pattern is put in a field that AuthBridge expects as a glob. These are semantically different — a regex like.*\.team1\.svc\.cluster\.localwill not match as a glob. The comment acknowledges the mismatch but takes no action. Worth either (a) rejectingHostRegexroutes with a clear error/warning, or (b) documenting the expected glob syntax in the CRD field itself so callers know they must supply a glob, not a regex.
Reviewed by clawgenti using the github-pr-review skill
| } | ||
| if outboundRoute.Destination.HostRegex != "" { | ||
| // AuthBridge router doesn't support hostRegex - use glob pattern in host field | ||
| route["host"] = outboundRoute.Destination.HostRegex |
There was a problem hiding this comment.
suggestion: HostRegex is being stored verbatim in the host field, but AuthBridge's router matches host as a glob, not a regex. A regex like .*\.team1\.svc\.cluster\.local won't match as a glob (*.team1.svc.cluster.local would). Consider logging a more actionable warning here (e.g. "HostRegex is not supported; treating value as a glob — ensure it uses glob syntax") or returning an error to surface the mismatch to the operator early.
…ntax) The CRD field is named "hostRegex" but AuthBridge expects glob patterns (github.com/gobwas/glob), not regex. Users who follow the CRD documentation will provide patterns that don't match. Added warning log to help users discover the mismatch: - Log when hostRegex is used - Explain that glob syntax is expected (*.example.com) - Reference that regex syntax won't work (.*\.example\.com) Filed issue #520 to track fixing the CRD documentation/field name. Addresses review comment from #517 Assisted-By: Claude Code Signed-off-by: Alan Cha <Alan.cha1@ibm.com>
|
Review comment addressed in commit c9f1708: ✅ HostRegex glob vs regex mismatch - Added warning log when mutatorLog.Info("hostRegex field is mapped to AuthBridge glob pattern (not regex)",
"namespace", namespace, "crName", crName,
"hostRegex", outboundRoute.Destination.HostRegex,
"note", "use glob syntax like '*.team1.svc.cluster.local', not regex '.*\\.team1\\.svc\\.cluster\\.local'")Also filed issue #520 to track fixing the CRD field documentation/name. The field name is misleading - it should be Why not error/reject? No examples currently use |
clawgenti
left a comment
There was a problem hiding this comment.
All previous review findings have been addressed: the hostRegex→glob semantic mismatch now has a clear warning log and issue #520 filed for the CRD documentation fix. CI is green across all completed checks. All checks pass. Ready for human review.
Reviewed by clawgenti using the github-pr-review skill
Test Coverage UpdateFiled issue #521 to track adding E2E tests for runtime token exchange verification. Current coverage (this PR):
Follow-up (issue #521):
The manual E2E test from this PR's development confirmed everything works (routes match, token exchange happens, agent successfully calls tool), but we need automated E2E tests in the test suite to catch regressions. |
Summary
Fixes two bugs in AuthBridge route generation from AgentRuntime
spec.auth.outbound:routing.Routeformat instead of AgentRuntime CRD formatBug 1: Routes Architecture
Problem: AuthBridge crashed with "cannot unmarshal array into Go struct field" when routes were inline in config.yaml
Root Cause: AuthBridge's token-exchange plugin in proxy-sidecar mode expects routes loaded from an external file, not inline in the config
Solution:
authbridge-routes-<crName>ConfigMaproutes: {file: "/etc/authproxy/routes.yaml"}in config.yamlBug 2: Routes Format
Problem: Routes didn't match even after Bug 1 was fixed - AuthBridge logged "no matching route"
Root Cause: Operator generated routes in AgentRuntime CRD format, but AuthBridge expects
routing.RouteformatWrong format (AgentRuntime CRD):
Correct format (AuthBridge routing.Route):
Solution: Changed route generation to use flat AuthBridge format with:
hostfield (not nested underdestination)target_audiencestring (notaudiencesarray)Testing
Complete E2E test on fresh Kind cluster verified:
Files Modified
operator/internal/webhook/injector/pod_mutator.go: Route generation and ConfigMap creationoperator/internal/webhook/injector/volume_builder.go: AddedoverrideRoutesConfigMapInVolumesfunctionRelated Issues
Fixes rossoctl/rossoctl#2334
Assisted-By: Claude Code