chore: fail server startup on invalid DERP map (#10536)

This commit is contained in:
Dean Sheather 2023-11-06 23:04:07 +10:00 committed by GitHub
parent 5b9e26a13f
commit 95e5419626
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 2 deletions

View File

@ -1755,3 +1755,22 @@ func TestConnectToPostgres(t *testing.T) {
})
require.NoError(t, sqlDB.PingContext(ctx))
}
func TestServer_InvalidDERP(t *testing.T) {
t.Parallel()
// Try to start a server with the built-in DERP server disabled and no
// external DERP map.
inv, _ := clitest.New(t,
"server",
"--in-memory",
"--http-address", ":0",
"--access-url", "http://example.com",
"--derp-server-enable=false",
"--derp-server-stun-addresses", "disable",
"--block-direct-connections",
)
err := inv.Run()
require.Error(t, err)
require.ErrorContains(t, err, "A valid DERP map is required for networking to work")
}

View File

@ -130,6 +130,25 @@ func NewDERPMap(ctx context.Context, region *tailcfg.DERPRegion, stunAddrs []str
}
}
// Fail if the DERP map has no regions or no DERP nodes.
badDerpMapMsg := "A valid DERP map is required for networking to work. You must either supply your own DERP map or use the built-in DERP server"
if len(derpMap.Regions) == 0 {
return nil, xerrors.New("DERP map has no regions. " + badDerpMapMsg)
}
foundValidNode := false
regionLoop:
for _, region := range derpMap.Regions {
for _, node := range region.Nodes {
if !node.STUNOnly {
foundValidNode = true
break regionLoop
}
}
}
if !foundValidNode {
return nil, xerrors.New("DERP map has no DERP nodes. " + badDerpMapMsg)
}
return derpMap, nil
}

View File

@ -33,7 +33,10 @@ func TestNewDERPMap(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
data, _ := json.Marshal(&tailcfg.DERPMap{
Regions: map[int]*tailcfg.DERPRegion{
1: {},
1: {
RegionID: 1,
Nodes: []*tailcfg.DERPNode{{}},
},
},
})
_, _ = w.Write(data)
@ -66,7 +69,9 @@ func TestNewDERPMap(t *testing.T) {
localPath := filepath.Join(t.TempDir(), "derp.json")
content, err := json.Marshal(&tailcfg.DERPMap{
Regions: map[int]*tailcfg.DERPRegion{
1: {},
1: {
Nodes: []*tailcfg.DERPNode{{}},
},
},
})
require.NoError(t, err)
@ -131,4 +136,29 @@ func TestNewDERPMap(t *testing.T) {
// region.
require.EqualValues(t, -1, derpMap.Regions[3].Nodes[0].STUNPort)
})
t.Run("RequireRegions", func(t *testing.T) {
t.Parallel()
_, err := tailnet.NewDERPMap(context.Background(), nil, nil, "", "", false)
require.Error(t, err)
require.ErrorContains(t, err, "DERP map has no regions")
})
t.Run("RequireDERPNodes", func(t *testing.T) {
t.Parallel()
// No nodes.
_, err := tailnet.NewDERPMap(context.Background(), &tailcfg.DERPRegion{}, nil, "", "", false)
require.Error(t, err)
require.ErrorContains(t, err, "DERP map has no DERP nodes")
// No DERP nodes.
_, err = tailnet.NewDERPMap(context.Background(), &tailcfg.DERPRegion{
Nodes: []*tailcfg.DERPNode{
{
STUNOnly: true,
},
},
}, nil, "", "", false)
require.Error(t, err)
require.ErrorContains(t, err, "DERP map has no DERP nodes")
})
}