mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-27 00:59:07 +02:00
[management] Keep the ingress address contract and the ownership fallback
Two follow-ups to canonicalizing the proxy address. netip accepts a zoned literal where net.ParseIP did not, so "fe80::1%eth0" started passing validation and would have been stored as a cluster key. An address scoped to one host's interface cannot name a cluster others reach, so zones are rejected, as before. Making the ownership query exact also left the bootstrap check without a fallback for rows written before canonicalization: a foreign cluster stored as "BYOP.Account2.Example.com" no longer matches the normalized address, reads as never declared, and the pin it should refuse goes through. Split the two callers instead of choosing between them. IsClusterAddressConflicting stays exact for the per-connect path that needs the index; HasProxyOutsideAccountAtHost folds case for the bootstrap, which runs once per account and is the only thing standing between it and pinning its immutable endpoint to somebody else's cluster. The settings delete guard already made that trade for the same reason. Restores the foreign-casing case that went with the exact query, and adds the zone cases to the ingress test.
This commit is contained in:
@@ -899,7 +899,7 @@ func (m *managerImpl) validateGatewayCluster(ctx context.Context, accountID, clu
|
||||
// so a proxy row elsewhere for this address can only be another
|
||||
// account's BYOP cluster: its proxies filter foreign mappings out on
|
||||
// delivery, making the pin dead on arrival.
|
||||
foreign, err := m.store.IsClusterAddressConflicting(ctx, clusterAddr, accountID)
|
||||
foreign, err := m.store.HasProxyOutsideAccountAtHost(ctx, clusterAddr, accountID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("check proxy cluster ownership: %w", err)
|
||||
}
|
||||
|
||||
@@ -402,6 +402,19 @@ func TestCreateSettingsMatchesClusterCasing(t *testing.T) {
|
||||
assert.Equal(t, "eu.proxy.example.com", created.ProxyAddress)
|
||||
})
|
||||
|
||||
t.Run("foreign cluster is still foreign", func(t *testing.T) {
|
||||
f := newBootstrapFixture(t)
|
||||
f.seedProxy(t, "proxy1", "account2", "BYOP.Account2.Example.com", ptrTo(true))
|
||||
f.expectPermission("account1", "user1", modules.AgentNetworkSettings, operations.Create, true)
|
||||
|
||||
_, err := f.createSettings(ctx, "account1", "user1", "byop.account2.example.com", "")
|
||||
require.Error(t, err, "another account's cluster must be refused whatever its casing")
|
||||
var sErr *status.Error
|
||||
require.ErrorAs(t, err, &sErr)
|
||||
assert.Equal(t, status.InvalidArgument, sErr.Type())
|
||||
assert.Contains(t, err.Error(), "not available to this account")
|
||||
})
|
||||
|
||||
t.Run("non-private cluster is still refused", func(t *testing.T) {
|
||||
f := newBootstrapFixture(t)
|
||||
f.seedProxy(t, "proxy1", "", "Central.Example.com", ptrTo(false))
|
||||
|
||||
Reference in New Issue
Block a user