mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-12 08:29:06 +02:00
[management] Close the review's nitpicks on live model discovery
Five smaller points from the same review as the four already fixed. **The no-redirect policy had no test.** Every Fetch test injects an HTTPClient, which bypasses httpClient() and therefore the policy entirely, so nothing asserted that a 302 is refused — and the policy is a security control: a redirect moves the request to a host checkPublicHost never resolved. TestRedirectsAreNotFollowed drives the real constructor against an httptest server that redirects to the cloud metadata address, and asserts exactly one request leaves the client. **An injected client silently lost that policy.** Production is safe today only because NewManager passes a nil HTTPClient; any future non-test injection would have dropped the guarantee with no signal. An injected client that states no policy now inherits ours. Implemented by copying the client rather than assigning into it. Writing c.HTTPClient.CheckRedirect from httpClient() would mutate a struct shared by every request goroutine for the process's lifetime — a data race, and the exact hazard the same review's next point warns about. The copy shares the Transport, which is safe for concurrent use by design. **Two comments described things that were not true.** The manager's doc claimed reading a stored credential "is permission-checked as one"; there is no per-record Read check, just the single Create check, which covers it because Create is stronger and the lookup is account-scoped. Said that instead. The modelDiscovery field now records that it is shared across requests and must stay read-only after construction. **The handler test asserted neither the label contract nor the upstream.** The response omits label entirely when a vendor supplies none, and the dashboard falls back to the id on absence — an empty string would render a blank row. The fixture had no label-less model to prove it with (the review described one, but both existing entries carry labels), so this adds one. The upstream assertion matters because Bedrock's region is read back out of it. Also fixes the "blank catalog provide" subtest name.
This commit is contained in:
@@ -128,6 +128,10 @@ type managerImpl struct {
|
||||
// modelDiscovery queries vendors for the models a credential can reach.
|
||||
// A field rather than a package call so tests can drive it without
|
||||
// reaching the network.
|
||||
//
|
||||
// One instance serves every request for the process's lifetime, so its
|
||||
// fields must stay read-only after construction: lazy initialisation
|
||||
// inside Fetch or httpClient would race across request goroutines.
|
||||
modelDiscovery *modeldiscovery.Client
|
||||
|
||||
// reconcileCache holds the last set of synthesised proxy mappings
|
||||
@@ -182,12 +186,13 @@ func (m *managerImpl) GetProvider(ctx context.Context, accountID, userID, provid
|
||||
//
|
||||
// recordID, when set, names an existing provider whose stored credential and
|
||||
// upstream are used instead of the ones in req — so the dashboard can refresh
|
||||
// the list without ever holding the key. Reading a stored credential is a read
|
||||
// of that provider, and is permission-checked as one.
|
||||
// the list without ever holding the key.
|
||||
//
|
||||
// Gated on Create rather than Read: this spends the operator's credential
|
||||
// against a third party, which is not something a read-only role should be
|
||||
// able to make the server do.
|
||||
// able to make the server do. That one check also covers reading the stored
|
||||
// record — Create is strictly stronger than Read here, and the lookup is
|
||||
// scoped to accountID, so another account's record is never reachable.
|
||||
func (m *managerImpl) DiscoverProviderModels(ctx context.Context, accountID, userID string, req modeldiscovery.Request, recordID string) ([]modeldiscovery.Model, error) {
|
||||
if err := m.requirePermission(ctx, accountID, userID, modules.AgentNetworkProviders, operations.Create); err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user