mirror of
https://github.com/juanfont/headscale.git
synced 2025-03-20 20:44:19 -04:00
test: fix TestDERPVerifyEndpoint
- `tailscale debug derp` use random node private key
This commit is contained in:
parent
103b069f1f
commit
d604663121
@ -1,11 +1,10 @@
|
|||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/juanfont/headscale/hscontrol/util"
|
"github.com/juanfont/headscale/hscontrol/util"
|
||||||
@ -13,7 +12,11 @@ import (
|
|||||||
"github.com/juanfont/headscale/integration/hsic"
|
"github.com/juanfont/headscale/integration/hsic"
|
||||||
"github.com/juanfont/headscale/integration/integrationutil"
|
"github.com/juanfont/headscale/integration/integrationutil"
|
||||||
"github.com/juanfont/headscale/integration/tsic"
|
"github.com/juanfont/headscale/integration/tsic"
|
||||||
|
"tailscale.com/derp"
|
||||||
|
"tailscale.com/derp/derphttp"
|
||||||
|
"tailscale.com/net/netmon"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
|
"tailscale.com/types/key"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDERPVerifyEndpoint(t *testing.T) {
|
func TestDERPVerifyEndpoint(t *testing.T) {
|
||||||
@ -45,23 +48,24 @@ func TestDERPVerifyEndpoint(t *testing.T) {
|
|||||||
)
|
)
|
||||||
assertNoErr(t, err)
|
assertNoErr(t, err)
|
||||||
|
|
||||||
|
derpRegion := tailcfg.DERPRegion{
|
||||||
|
RegionCode: "test-derpverify",
|
||||||
|
RegionName: "TestDerpVerify",
|
||||||
|
Nodes: []*tailcfg.DERPNode{
|
||||||
|
{
|
||||||
|
Name: "TestDerpVerify",
|
||||||
|
RegionID: 900,
|
||||||
|
HostName: derper.GetHostname(),
|
||||||
|
STUNPort: derper.GetSTUNPort(),
|
||||||
|
STUNOnly: false,
|
||||||
|
DERPPort: derper.GetDERPPort(),
|
||||||
|
InsecureForTests: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
derpMap := tailcfg.DERPMap{
|
derpMap := tailcfg.DERPMap{
|
||||||
Regions: map[int]*tailcfg.DERPRegion{
|
Regions: map[int]*tailcfg.DERPRegion{
|
||||||
900: {
|
900: &derpRegion,
|
||||||
RegionID: 900,
|
|
||||||
RegionCode: "test-derpverify",
|
|
||||||
RegionName: "TestDerpVerify",
|
|
||||||
Nodes: []*tailcfg.DERPNode{
|
|
||||||
{
|
|
||||||
Name: "TestDerpVerify",
|
|
||||||
RegionID: 900,
|
|
||||||
HostName: derper.GetHostname(),
|
|
||||||
STUNPort: derper.GetSTUNPort(),
|
|
||||||
STUNOnly: false,
|
|
||||||
DERPPort: derper.GetDERPPort(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,21 +80,40 @@ func TestDERPVerifyEndpoint(t *testing.T) {
|
|||||||
allClients, err := scenario.ListTailscaleClients()
|
allClients, err := scenario.ListTailscaleClients()
|
||||||
assertNoErrListClients(t, err)
|
assertNoErrListClients(t, err)
|
||||||
|
|
||||||
for _, client := range allClients {
|
fakeKey := key.NewNode()
|
||||||
report, err := client.DebugDERPRegion("test-derpverify")
|
DERPVerify(t, fakeKey, derpRegion, false)
|
||||||
assertNoErr(t, err)
|
|
||||||
successful := false
|
|
||||||
for _, line := range report.Info {
|
|
||||||
if strings.Contains(line, "Successfully established a DERP connection with node") {
|
|
||||||
successful = true
|
|
||||||
|
|
||||||
break
|
for _, client := range allClients {
|
||||||
}
|
nodeKey, err := client.GetNodePrivateKey()
|
||||||
}
|
assertNoErr(t, err)
|
||||||
if !successful {
|
DERPVerify(t, *nodeKey, derpRegion, true)
|
||||||
stJSON, err := json.Marshal(report)
|
}
|
||||||
assertNoErr(t, err)
|
}
|
||||||
t.Errorf("Client %s could not establish a DERP connection: %s", client.Hostname(), string(stJSON))
|
|
||||||
}
|
func DERPVerify(
|
||||||
|
t *testing.T,
|
||||||
|
nodeKey key.NodePrivate,
|
||||||
|
region tailcfg.DERPRegion,
|
||||||
|
expectSuccess bool,
|
||||||
|
) {
|
||||||
|
IntegrationSkip(t)
|
||||||
|
|
||||||
|
c := derphttp.NewRegionClient(nodeKey, t.Logf, netmon.NewStatic(), func() *tailcfg.DERPRegion {
|
||||||
|
return ®ion
|
||||||
|
})
|
||||||
|
var result error
|
||||||
|
if err := c.Connect(context.Background()); err != nil {
|
||||||
|
result = fmt.Errorf("client Connect: %w", err)
|
||||||
|
}
|
||||||
|
if m, err := c.Recv(); err != nil {
|
||||||
|
result = fmt.Errorf("client first Recv: %w", err)
|
||||||
|
} else if v, ok := m.(derp.ServerInfoMessage); !ok {
|
||||||
|
result = fmt.Errorf("client first Recv was unexpected type %T", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if expectSuccess && result != nil {
|
||||||
|
t.Fatalf("DERP verify failed unexpectedly for client %s. Expected success but got error: %v", nodeKey.Public(), result)
|
||||||
|
} else if !expectSuccess && result == nil {
|
||||||
|
t.Fatalf("DERP verify succeeded unexpectedly for client %s. Expected failure but it succeeded.", nodeKey.Public())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/juanfont/headscale/integration/tsic"
|
"github.com/juanfont/headscale/integration/tsic"
|
||||||
"tailscale.com/ipn/ipnstate"
|
"tailscale.com/ipn/ipnstate"
|
||||||
"tailscale.com/net/netcheck"
|
"tailscale.com/net/netcheck"
|
||||||
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/netmap"
|
"tailscale.com/types/netmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,6 +32,7 @@ type TailscaleClient interface {
|
|||||||
Status(...bool) (*ipnstate.Status, error)
|
Status(...bool) (*ipnstate.Status, error)
|
||||||
Netmap() (*netmap.NetworkMap, error)
|
Netmap() (*netmap.NetworkMap, error)
|
||||||
DebugDERPRegion(region string) (*ipnstate.DebugDERPRegionReport, error)
|
DebugDERPRegion(region string) (*ipnstate.DebugDERPRegionReport, error)
|
||||||
|
GetNodePrivateKey() (*key.NodePrivate, error)
|
||||||
Netcheck() (*netcheck.Report, error)
|
Netcheck() (*netcheck.Report, error)
|
||||||
WaitForNeedsLogin() error
|
WaitForNeedsLogin() error
|
||||||
WaitForRunning() error
|
WaitForRunning() error
|
||||||
|
@ -24,7 +24,10 @@ import (
|
|||||||
"github.com/ory/dockertest/v3/docker"
|
"github.com/ory/dockertest/v3/docker"
|
||||||
"tailscale.com/ipn"
|
"tailscale.com/ipn"
|
||||||
"tailscale.com/ipn/ipnstate"
|
"tailscale.com/ipn/ipnstate"
|
||||||
|
"tailscale.com/ipn/store/mem"
|
||||||
"tailscale.com/net/netcheck"
|
"tailscale.com/net/netcheck"
|
||||||
|
"tailscale.com/paths"
|
||||||
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/netmap"
|
"tailscale.com/types/netmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1149,3 +1152,29 @@ func (t *TailscaleInContainer) ReadFile(path string) ([]byte, error) {
|
|||||||
|
|
||||||
return out.Bytes(), nil
|
return out.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *TailscaleInContainer) GetNodePrivateKey() (*key.NodePrivate, error) {
|
||||||
|
state, err := t.ReadFile(paths.DefaultTailscaledStateFile())
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read state file: %w", err)
|
||||||
|
}
|
||||||
|
store := &mem.Store{}
|
||||||
|
if err = store.LoadFromJSON(state); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to unmarshal state file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
currentProfileKey, err := store.ReadState(ipn.CurrentProfileStateKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read current profile state key: %w", err)
|
||||||
|
}
|
||||||
|
currentProfile, err := store.ReadState(ipn.StateKey(currentProfileKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read current profile state: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &ipn.Prefs{}
|
||||||
|
if err = json.Unmarshal(currentProfile, &p); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to unmarshal current profile state: %w", err)
|
||||||
|
}
|
||||||
|
return &p.Persist.PrivateNodeKey, nil
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user