Skip to content

Commit

Permalink
tests: add integration test for DERP verify endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
ArcticLampyrid committed Aug 7, 2024
1 parent a8f091f commit a3839a5
Show file tree
Hide file tree
Showing 10 changed files with 674 additions and 110 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test-integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ jobs:
- TestNodeRenameCommand
- TestNodeMoveCommand
- TestPolicyCommand
- TestDERPVerifyEndpoint
- TestDERPServerScenario
- TestPingAllByIP
- TestPingAllByIPPublicDERP
Expand Down
19 changes: 19 additions & 0 deletions Dockerfile.derper
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# For testing purposes only

FROM golang:1.22-alpine AS build-env

WORKDIR /go/src

RUN apk add --no-cache git
ARG VERSION_BRANCH=main
RUN git clone https://github.com/tailscale/tailscale.git --branch=$VERSION_BRANCH --depth=1
WORKDIR /go/src/tailscale

ARG TARGETARCH
RUN GOARCH=$TARGETARCH go install -v ./cmd/derper

FROM alpine:3.18
RUN apk add --no-cache ca-certificates iptables iproute2 ip6tables curl

COPY --from=build-env /go/bin/* /usr/local/bin/
ENTRYPOINT [ "/usr/local/bin/derper" ]
111 changes: 111 additions & 0 deletions integration/derp_verify_endpoint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package integration

import (
"encoding/json"
"fmt"
"net"
"strconv"
"strings"
"testing"

"github.com/juanfont/headscale/hscontrol/util"
"github.com/juanfont/headscale/integration/dsic"
"github.com/juanfont/headscale/integration/hsic"
"github.com/juanfont/headscale/integration/integrationutil"
"github.com/juanfont/headscale/integration/tsic"
)

func TestDERPVerifyEndpoint(t *testing.T) {
IntegrationSkip(t)

// Generate random hostname for the headscale instance
hash, err := util.GenerateRandomStringDNSSafe(6)
assertNoErr(t, err)
testName := "derpverify"
hostname := fmt.Sprintf("hs-%s-%s", testName, hash)

headscalePort := 8080

// Create cert for headscale
certHeadscale, keyHeadscale, err := integrationutil.CreateCertificate(hostname)
assertNoErr(t, err)

scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
defer scenario.Shutdown()

spec := map[string]int{
"user1": 10,
}

derper, err := scenario.CreateDERPServer("head",
dsic.WithCACert(certHeadscale),
dsic.WithVerifyClientURL(fmt.Sprintf("https://%s/verify", net.JoinHostPort(hostname, strconv.Itoa(headscalePort)))),
)
assertNoErr(t, err)

derpConfig := "regions:\n"
derpConfig += " 900:\n"
derpConfig += " regionid: 900\n"
derpConfig += " regioncode: test-derpverify\n"
derpConfig += " regionname: TestDerpVerify\n"
derpConfig += " nodes:\n"
derpConfig += " - name: TestDerpVerify\n"
derpConfig += " regionid: 900\n"
derpConfig += " hostname: " + derper.GetHostname() + "\n"
derpConfig += " stunport: " + derper.GetSTUNPort() + "\n"
derpConfig += " stunonly: false\n"
derpConfig += " derpport: " + derper.GetDERPPort() + "\n"

headscale, err := scenario.Headscale(
hsic.WithHostname(hostname),
hsic.WithPort(headscalePort),
hsic.WithCustomTLS(certHeadscale, keyHeadscale),
hsic.WithHostnameAsServerURL(),
hsic.WithCustomDERPServerOnly([]byte(derpConfig)),
)
assertNoErrHeadscaleEnv(t, err)

for userName, clientCount := range spec {
err = scenario.CreateUser(userName)
if err != nil {
t.Fatalf("failed to create user %s: %s", userName, err)
}

err = scenario.CreateTailscaleNodesInUser(userName, "all", clientCount, tsic.WithCACert(derper.GetCert()))
if err != nil {
t.Fatalf("failed to create tailscale nodes in user %s: %s", userName, err)
}

key, err := scenario.CreatePreAuthKey(userName, true, true)
if err != nil {
t.Fatalf("failed to create pre-auth key for user %s: %s", userName, err)
}

err = scenario.RunTailscaleUp(userName, headscale.GetEndpoint(), key.GetKey())
if err != nil {
t.Fatalf("failed to run tailscale up for user %s: %s", userName, err)
}
}

allClients, err := scenario.ListTailscaleClients()
assertNoErrListClients(t, err)

for _, client := range allClients {
report, err := client.DebugDERPRegion("test-derpverify")
assertNoErr(t, err)
successful := false
for _, line := range report.Info {
if strings.Contains(line, "Successfully established a DERP connection with node") {
successful = true

break
}
}
if !successful {
stJSON, err := json.Marshal(report)
assertNoErr(t, err)
t.Errorf("Client %s could not establish a DERP connection: %s", client.Hostname(), string(stJSON))
}
}
}
Loading

0 comments on commit a3839a5

Please sign in to comment.