NM-291: feat(egress): add preset catalog API and server-side CIDR res…#4006
NM-291: feat(egress): add preset catalog API and server-side CIDR res…#4006abhishek9686 wants to merge 9 commits into
Conversation
…olution Introduce GET /api/v1/egress/presets with embedded extras plus generated AWS region presets. Support optional preset_id on egress create/update to apply catalog defaults and resolve CIDRs from AWS ip-ranges, GitHub meta, and Fastly when available. Add preset_id and static_domain_ans on schema.Egress; skip overwriting domain_ans from host EgressUpdate when static_domain_ans is set. Add Jenkins to extras catalog and tests for apply/resolvers and host guard. Update swagger for preset_id, static fields, and presets endpoint.
|
Tenki Code Review - Complete Files Reviewed: 15 By Severity:
This PR introduces a well-structured egress preset catalog with sensible allowlisting, but two medium-severity issues warrant attention: preset CIDR resolution failures are silently swallowed (degrading behavior with no operator visibility), and the resolution is performed synchronously in HTTP handlers with a 45-second independent timeout that ignores request cancellation. Files Reviewed (15 files) |
There was a problem hiding this comment.
Overview
The PR adds an egress preset catalog (GET /api/v1/egress/presets) and allows creating/updating egress resources from a preset ID. The implementation is well-structured: a compile-time–embedded catalog, an allowlist-gated CIDR resolver, sync.Once for lazy initialization, and a StaticDomainAns flag to prevent host check-in from overwriting server-resolved CIDRs.
Issues Found
1. Silent CIDR resolution failure
In both createEgress and updateEgress, the error from logic.ResolveEgressPresetCIDRs is silently discarded:
if c, err := logic.ResolveEgressPresetCIDRs(http.DefaultClient, p); err == nil && len(c) > 0 {
resolvedCIDRs = c
}When the upstream (AWS, GitHub, Fastly) returns an error or non-200, the egress is created with StaticDomainAns=false and an empty DomainAns. The client receives a 200 OK with no indication that the preset CIDRs were not applied. This silent fallback to host-resolved behavior may confuse operators who expect static routing rules from the preset.
2. Synchronous outbound HTTP fetch blocks the handler
ResolveEgressPresetCIDRs is called synchronously in the HTTP handler for POST and PUT /api/v1/egress. Each resolver internally uses context.WithTimeout(context.Background(), 45s) — not the incoming r.Context(). Consequences:
- A slow or unreachable upstream stalls the handler goroutine for up to 45 seconds.
- Client cancellation (connection close, client-side timeout) does not cancel the outbound fetch.
- The HTTP server in
controllers/controller.gohas noWriteTimeout, so the connection stays open the entire duration. - The AWS
ip-ranges.jsonpayload is ~1.5 MB, adding latency from download and JSON decode.
Positive Observations
- The
isFetchableCIDRSourceallowlist correctly prevents arbitrary URL fetches even if the embedded catalog were somehow tampered with. - The
StaticDomainAnsguard inshouldApplyEgressDomainAnsUpdatecorrectly protects server-resolved CIDRs from being overwritten during host check-in. - The
sync.Oncepattern for catalog initialization is correct and thread-safe. - Test coverage for the new helpers is solid, including fixture-based tests for AWS and GitHub resolvers.
…olution
Introduce GET /api/v1/egress/presets with embedded extras plus generated AWS region presets. Support optional preset_id on egress create/update to apply catalog defaults and resolve CIDRs from AWS ip-ranges, GitHub meta, and Fastly when available.
Add preset_id and static_domain_ans on schema.Egress; skip overwriting domain_ans from host EgressUpdate when static_domain_ans is set. Add Jenkins to extras catalog and tests for apply/resolvers and host guard.
Update swagger for preset_id, static fields, and presets endpoint.
Describe your changes
Provide Issue ticket number if applicable/not in title
Provide testing steps
Checklist before requesting a review