mirror of
https://github.com/juanfont/headscale.git
synced 2026-03-18 23:44:07 +01:00
integration: standardize test infrastructure options
Make embedded DERP server and TLS the default configuration for all integration tests, replacing the per-test opt-in model that led to inconsistent and flaky test behavior. Infrastructure changes: - DefaultConfigEnv() includes embedded DERP server settings - New() auto-generates a proper CA + server TLS certificate pair - CA cert is installed into container trust stores and returned by GetCert() so clients and internal tools (curl) trust the server - CreateCertificate() now returns (caCert, cert, key) instead of discarding the CA certificate - Add WithPublicDERP() and WithoutTLS() opt-out options - Remove WithTLS(), WithEmbeddedDERPServerOnly(), and WithDERPAsIP() since all their behavior is now the default or unnecessary Test cleanup: - Remove all redundant WithTLS/WithEmbeddedDERPServerOnly/WithDERPAsIP calls from test files - Give every test a unique WithTestName by parameterizing aclScenario, sshScenario, and derpServerScenario helpers - Add WithTestName to tests that were missing it - Document all non-standard options with inline comments explaining why each is needed Updates #3139
This commit is contained in:
@@ -58,6 +58,7 @@ var veryLargeDestination = []policyv2.AliasWithPorts{
|
||||
func aclScenario(
|
||||
t *testing.T,
|
||||
policy *policyv2.Policy,
|
||||
testName string,
|
||||
clientsPerUser int,
|
||||
) *Scenario {
|
||||
t.Helper()
|
||||
@@ -81,9 +82,7 @@ func aclScenario(
|
||||
tsic.WithDockerWorkdir("/"),
|
||||
},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("acl"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithTestName(testName),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -305,6 +304,7 @@ func TestACLHostsInNetMapTable(t *testing.T) {
|
||||
|
||||
err = scenario.CreateHeadscaleEnv(
|
||||
[]tsic.Option{},
|
||||
hsic.WithTestName("aclnetmap"),
|
||||
hsic.WithACLPolicy(&testCase.policy),
|
||||
)
|
||||
|
||||
@@ -351,6 +351,7 @@ func TestACLAllowUser80Dst(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"acl-allowuser80",
|
||||
1,
|
||||
)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
@@ -414,6 +415,7 @@ func TestACLDenyAllPort80(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"acl-denyport80",
|
||||
4,
|
||||
)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
@@ -462,6 +464,7 @@ func TestACLAllowUserDst(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"acl-allowuserdst",
|
||||
2,
|
||||
)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
@@ -524,6 +527,7 @@ func TestACLAllowStarDst(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"acl-allowstar",
|
||||
2,
|
||||
)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
@@ -591,6 +595,7 @@ func TestACLNamedHostsCanReachBySubnet(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"acl-namedsubnet",
|
||||
3,
|
||||
)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
@@ -743,6 +748,7 @@ func TestACLNamedHostsCanReach(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
scenario := aclScenario(t,
|
||||
&testCase.policy,
|
||||
"acl-namedreach",
|
||||
2,
|
||||
)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
@@ -1044,7 +1050,7 @@ func TestACLDevice1CanAccessDevice2(t *testing.T) {
|
||||
|
||||
for name, testCase := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
scenario := aclScenario(t, &testCase.policy, 1)
|
||||
scenario := aclScenario(t, &testCase.policy, "acl-dev1dev2", 1)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
test1ip := netip.MustParseAddr("100.64.0.1")
|
||||
@@ -1159,7 +1165,7 @@ func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) {
|
||||
tsic.WithDockerWorkdir("/"),
|
||||
},
|
||||
hsic.WithTestName("policyreload"),
|
||||
hsic.WithPolicyMode(types.PolicyModeDB),
|
||||
hsic.WithPolicyMode(types.PolicyModeDB), // test updates policy at runtime via CLI
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -1290,6 +1296,7 @@ func TestACLAutogroupMember(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"acl-agmember",
|
||||
2,
|
||||
)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
@@ -1383,8 +1390,6 @@ func TestACLAutogroupTagged(t *testing.T) {
|
||||
headscale, err := scenario.Headscale(
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("acl-autogroup-tagged"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -1430,7 +1435,10 @@ func TestACLAutogroupTagged(t *testing.T) {
|
||||
network = networks[0]
|
||||
}
|
||||
|
||||
// Create the tailscale node with appropriate options
|
||||
// Create the tailscale node with appropriate options.
|
||||
// CACert and HeadscaleName are passed explicitly because
|
||||
// nodes created via CreateTailscaleNode are not part of
|
||||
// the standard CreateHeadscaleEnv flow.
|
||||
opts := []tsic.Option{
|
||||
tsic.WithCACert(headscale.GetCert()),
|
||||
tsic.WithHeadscaleName(headscale.GetHostname()),
|
||||
@@ -1698,8 +1706,6 @@ func TestACLAutogroupSelf(t *testing.T) {
|
||||
},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("acl-autogroup-self"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -1721,7 +1727,10 @@ func TestACLAutogroupSelf(t *testing.T) {
|
||||
authKey, err := scenario.CreatePreAuthKeyWithTags(routerUser.GetId(), true, false, []string{"tag:router-node"})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create router node (tags come from the PreAuthKey)
|
||||
// Create router node (tags come from the PreAuthKey).
|
||||
// CACert and HeadscaleName are passed explicitly because
|
||||
// nodes created via tsic.New are not part of the standard
|
||||
// CreateHeadscaleEnv flow.
|
||||
routerClient, err := tsic.New(
|
||||
scenario.Pool(),
|
||||
"unstable",
|
||||
@@ -1917,9 +1926,7 @@ func TestACLPolicyPropagationOverTime(t *testing.T) {
|
||||
tsic.WithDockerWorkdir("/"),
|
||||
},
|
||||
hsic.WithTestName("aclpropagation"),
|
||||
hsic.WithPolicyMode(types.PolicyModeDB),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithPolicyMode(types.PolicyModeDB), // test updates policy at runtime via CLI
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -2738,8 +2745,6 @@ func TestACLTagPropagation(t *testing.T) {
|
||||
},
|
||||
hsic.WithACLPolicy(tt.policy),
|
||||
hsic.WithTestName("acl-tag-"+tt.name),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -2926,8 +2931,6 @@ func TestACLTagPropagationPortSpecific(t *testing.T) {
|
||||
},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("acl-tag-port-specific"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -3090,8 +3093,6 @@ func TestACLGroupWithUnknownUser(t *testing.T) {
|
||||
},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("acl-unknown-user"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -3192,8 +3193,6 @@ func TestACLGroupAfterUserDeletion(t *testing.T) {
|
||||
},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("acl-deleted-user"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithPolicyMode(types.PolicyModeDB), // Use DB mode so policy persists after user deletion
|
||||
)
|
||||
require.NoError(t, err)
|
||||
@@ -3386,9 +3385,7 @@ func TestACLGroupDeletionExactReproduction(t *testing.T) {
|
||||
},
|
||||
hsic.WithACLPolicy(initialPolicy),
|
||||
hsic.WithTestName("acl-exact-repro"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithPolicyMode(types.PolicyModeDB),
|
||||
hsic.WithPolicyMode(types.PolicyModeDB), // test updates policy at runtime via CLI
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -3565,9 +3562,7 @@ func TestACLDynamicUnknownUserAddition(t *testing.T) {
|
||||
},
|
||||
hsic.WithACLPolicy(validPolicy),
|
||||
hsic.WithTestName("acl-dynamic-unknown"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithPolicyMode(types.PolicyModeDB),
|
||||
hsic.WithPolicyMode(types.PolicyModeDB), // test updates policy at runtime via CLI
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -3723,9 +3718,7 @@ func TestACLDynamicUnknownUserRemoval(t *testing.T) {
|
||||
},
|
||||
hsic.WithACLPolicy(policyWithUnknown),
|
||||
hsic.WithTestName("acl-unknown-removal"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithPolicyMode(types.PolicyModeDB),
|
||||
hsic.WithPolicyMode(types.PolicyModeDB), // test updates policy at runtime via CLI
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
@@ -435,7 +435,6 @@ func TestGRPCAuthenticationBypass(t *testing.T) {
|
||||
err = scenario.CreateHeadscaleEnv(
|
||||
[]tsic.Option{},
|
||||
hsic.WithTestName("grpcauthtest"),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithConfigEnv(map[string]string{
|
||||
// Enable gRPC on the standard port
|
||||
"HEADSCALE_GRPC_LISTEN_ADDR": "0.0.0.0:50443",
|
||||
@@ -560,7 +559,6 @@ func TestCLIWithConfigAuthenticationBypass(t *testing.T) {
|
||||
err = scenario.CreateHeadscaleEnv(
|
||||
[]tsic.Option{},
|
||||
hsic.WithTestName("cliconfigauth"),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithConfigEnv(map[string]string{
|
||||
"HEADSCALE_GRPC_LISTEN_ADDR": "0.0.0.0:50443",
|
||||
}),
|
||||
|
||||
@@ -35,14 +35,7 @@ func TestAuthKeyLogoutAndReloginSameUser(t *testing.T) {
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
opts := []hsic.Option{
|
||||
hsic.WithTestName("pingallbyip"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithDERPAsIP(),
|
||||
}
|
||||
if https {
|
||||
opts = append(opts, []hsic.Option{
|
||||
hsic.WithTLS(),
|
||||
}...)
|
||||
hsic.WithTestName("authkey-relogsame"),
|
||||
}
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, opts...)
|
||||
@@ -241,8 +234,6 @@ func TestAuthKeyLogoutAndReloginNewUser(t *testing.T) {
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{},
|
||||
hsic.WithTestName("keyrelognewuser"),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithDERPAsIP(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -375,13 +366,7 @@ func TestAuthKeyLogoutAndReloginSameUserExpiredKey(t *testing.T) {
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
opts := []hsic.Option{
|
||||
hsic.WithTestName("pingallbyip"),
|
||||
hsic.WithDERPAsIP(),
|
||||
}
|
||||
if https {
|
||||
opts = append(opts, []hsic.Option{
|
||||
hsic.WithTLS(),
|
||||
}...)
|
||||
hsic.WithTestName("authkey-rlogexpired"),
|
||||
}
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, opts...)
|
||||
@@ -503,7 +488,7 @@ func TestAuthKeyDeleteKey(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("delkey"), hsic.WithTLS(), hsic.WithDERPAsIP())
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("delkey"))
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
headscale, err := scenario.Headscale()
|
||||
@@ -621,7 +606,6 @@ func TestAuthKeyLogoutAndReloginRoutesPreserved(t *testing.T) {
|
||||
tsic.WithExtraLoginArgs([]string{"--advertise-routes=" + advertiseRoute}),
|
||||
},
|
||||
hsic.WithTestName("routelogout"),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithACLPolicy(
|
||||
&policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
|
||||
@@ -51,11 +51,13 @@ func TestOIDCAuthenticationPingAll(t *testing.T) {
|
||||
"HEADSCALE_OIDC_CLIENT_SECRET_PATH": "${CREDENTIALS_DIRECTORY_TEST}/hs_client_oidc_secret",
|
||||
}
|
||||
|
||||
// OIDC tests configure the mock OIDC provider via environment
|
||||
// variables and inject the client secret as a file. This
|
||||
// pattern is shared by all OIDC integration tests.
|
||||
err = scenario.CreateHeadscaleEnvWithLoginURL(
|
||||
nil,
|
||||
hsic.WithTestName("oidcauthping"),
|
||||
hsic.WithConfigEnv(oidcMap),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithFileInContainer("/tmp/hs_client_oidc_secret", []byte(scenario.mockOIDC.ClientSecret())),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
@@ -374,7 +376,6 @@ func TestOIDC024UserCreation(t *testing.T) {
|
||||
nil,
|
||||
hsic.WithTestName("oidcmigration"),
|
||||
hsic.WithConfigEnv(oidcMap),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithFileInContainer("/tmp/hs_client_oidc_secret", []byte(scenario.mockOIDC.ClientSecret())),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
@@ -432,7 +433,6 @@ func TestOIDCAuthenticationWithPKCE(t *testing.T) {
|
||||
nil,
|
||||
hsic.WithTestName("oidcauthpkce"),
|
||||
hsic.WithConfigEnv(oidcMap),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithFileInContainer("/tmp/hs_client_oidc_secret", []byte(scenario.mockOIDC.ClientSecret())),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
@@ -487,12 +487,9 @@ func TestOIDCReloginSameNodeNewUser(t *testing.T) {
|
||||
|
||||
err = scenario.CreateHeadscaleEnvWithLoginURL(
|
||||
nil,
|
||||
hsic.WithTestName("oidcauthrelog"),
|
||||
hsic.WithTestName("oidc-authrelog"),
|
||||
hsic.WithConfigEnv(oidcMap),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithFileInContainer("/tmp/hs_client_oidc_secret", []byte(scenario.mockOIDC.ClientSecret())),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithDERPAsIP(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -899,11 +896,9 @@ func TestOIDCFollowUpUrl(t *testing.T) {
|
||||
|
||||
err = scenario.CreateHeadscaleEnvWithLoginURL(
|
||||
nil,
|
||||
hsic.WithTestName("oidcauthrelog"),
|
||||
hsic.WithTestName("oidc-followup"),
|
||||
hsic.WithConfigEnv(oidcMap),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithFileInContainer("/tmp/hs_client_oidc_secret", []byte(scenario.mockOIDC.ClientSecret())),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -1011,9 +1006,7 @@ func TestOIDCMultipleOpenedLoginUrls(t *testing.T) {
|
||||
nil,
|
||||
hsic.WithTestName("oidcauthrelog"),
|
||||
hsic.WithConfigEnv(oidcMap),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithFileInContainer("/tmp/hs_client_oidc_secret", []byte(scenario.mockOIDC.ClientSecret())),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -1145,10 +1138,7 @@ func TestOIDCReloginSameNodeSameUser(t *testing.T) {
|
||||
nil,
|
||||
hsic.WithTestName("oidcsameuser"),
|
||||
hsic.WithConfigEnv(oidcMap),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithFileInContainer("/tmp/hs_client_oidc_secret", []byte(scenario.mockOIDC.ClientSecret())),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithDERPAsIP(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1373,10 +1363,7 @@ func TestOIDCExpiryAfterRestart(t *testing.T) {
|
||||
nil,
|
||||
hsic.WithTestName("oidcexpiry"),
|
||||
hsic.WithConfigEnv(oidcMap),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithFileInContainer("/tmp/hs_client_oidc_secret", []byte(scenario.mockOIDC.ClientSecret())),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithDERPAsIP(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1524,7 +1511,6 @@ func TestOIDCACLPolicyOnJoin(t *testing.T) {
|
||||
},
|
||||
hsic.WithTestName("oidcaclpolicy"),
|
||||
hsic.WithConfigEnv(oidcMap),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithFileInContainer("/tmp/hs_client_oidc_secret", []byte(scenario.mockOIDC.ClientSecret())),
|
||||
hsic.WithACLPolicy(
|
||||
&policyv2.Policy{
|
||||
@@ -1801,10 +1787,7 @@ func TestOIDCReloginSameUserRoutesPreserved(t *testing.T) {
|
||||
},
|
||||
hsic.WithTestName("oidcrouterelogin"),
|
||||
hsic.WithConfigEnv(oidcMap),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithFileInContainer("/tmp/hs_client_oidc_secret", []byte(scenario.mockOIDC.ClientSecret())),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithDERPAsIP(),
|
||||
hsic.WithACLPolicy(
|
||||
&policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
|
||||
@@ -32,9 +32,6 @@ func TestAuthWebFlowAuthenticationPingAll(t *testing.T) {
|
||||
err = scenario.CreateHeadscaleEnvWithLoginURL(
|
||||
nil,
|
||||
hsic.WithTestName("webauthping"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithDERPAsIP(),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -73,8 +70,6 @@ func TestAuthWebFlowLogoutAndReloginSameUser(t *testing.T) {
|
||||
err = scenario.CreateHeadscaleEnvWithLoginURL(
|
||||
nil,
|
||||
hsic.WithTestName("weblogout"),
|
||||
hsic.WithDERPAsIP(),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -239,8 +234,6 @@ func TestAuthWebFlowLogoutAndReloginNewUser(t *testing.T) {
|
||||
err = scenario.CreateHeadscaleEnvWithLoginURL(
|
||||
nil,
|
||||
hsic.WithTestName("webflowrelnewuser"),
|
||||
hsic.WithDERPAsIP(),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ func TestUserCommand(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clins"))
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("cli-user"))
|
||||
require.NoError(t, err)
|
||||
|
||||
headscale, err := scenario.Headscale()
|
||||
@@ -588,9 +588,7 @@ func TestPreAuthKeyCorrectUserLoggedInCommand(t *testing.T) {
|
||||
|
||||
err = scenario.CreateHeadscaleEnv(
|
||||
[]tsic.Option{},
|
||||
hsic.WithTestName("clipak"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithTestName("cli-paklogin"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -699,8 +697,6 @@ func TestTaggedNodesCLIOutput(t *testing.T) {
|
||||
err = scenario.CreateHeadscaleEnv(
|
||||
[]tsic.Option{},
|
||||
hsic.WithTestName("tagcli"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -811,7 +807,7 @@ func TestApiKeyCommand(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clins"))
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("cli-apikey"))
|
||||
require.NoError(t, err)
|
||||
|
||||
headscale, err := scenario.Headscale()
|
||||
@@ -1058,7 +1054,7 @@ func TestNodeCommand(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clins"))
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("cli-node"))
|
||||
require.NoError(t, err)
|
||||
|
||||
headscale, err := scenario.Headscale()
|
||||
@@ -1319,7 +1315,7 @@ func TestNodeExpireCommand(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clins"))
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("cli-nodeexpire"))
|
||||
require.NoError(t, err)
|
||||
|
||||
headscale, err := scenario.Headscale()
|
||||
@@ -1454,7 +1450,7 @@ func TestNodeRenameCommand(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("clins"))
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{}, hsic.WithTestName("cli-noderename"))
|
||||
require.NoError(t, err)
|
||||
|
||||
headscale, err := scenario.Headscale()
|
||||
@@ -1634,9 +1630,9 @@ func TestPolicyCommand(t *testing.T) {
|
||||
|
||||
err = scenario.CreateHeadscaleEnv(
|
||||
[]tsic.Option{},
|
||||
hsic.WithTestName("clins"),
|
||||
hsic.WithTestName("cli-policy"),
|
||||
hsic.WithConfigEnv(map[string]string{
|
||||
"HEADSCALE_POLICY_MODE": "database",
|
||||
"HEADSCALE_POLICY_MODE": "database", // test sets/gets policy via CLI
|
||||
}),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
@@ -1719,9 +1715,9 @@ func TestPolicyBrokenConfigCommand(t *testing.T) {
|
||||
|
||||
err = scenario.CreateHeadscaleEnv(
|
||||
[]tsic.Option{},
|
||||
hsic.WithTestName("clins"),
|
||||
hsic.WithTestName("cli-policybad"),
|
||||
hsic.WithConfigEnv(map[string]string{
|
||||
"HEADSCALE_POLICY_MODE": "database",
|
||||
"HEADSCALE_POLICY_MODE": "database", // test sets invalid policy via CLI
|
||||
}),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -32,7 +32,7 @@ func TestDERPVerifyEndpoint(t *testing.T) {
|
||||
headscalePort := 8080
|
||||
|
||||
// Create cert for headscale
|
||||
certHeadscale, keyHeadscale, err := integrationutil.CreateCertificate(hostname)
|
||||
caHeadscale, certHeadscale, keyHeadscale, err := integrationutil.CreateCertificate(hostname)
|
||||
require.NoError(t, err)
|
||||
|
||||
spec := ScenarioSpec{
|
||||
@@ -46,7 +46,7 @@ func TestDERPVerifyEndpoint(t *testing.T) {
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
derper, err := scenario.CreateDERPServer("head",
|
||||
dsic.WithCACert(certHeadscale),
|
||||
dsic.WithCACert(caHeadscale),
|
||||
dsic.WithVerifyClientURL(fmt.Sprintf("https://%s/verify", net.JoinHostPort(hostname, strconv.Itoa(headscalePort)))),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
@@ -72,10 +72,18 @@ func TestDERPVerifyEndpoint(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
// WithHostname is used instead of WithTestName because the hostname
|
||||
// must match the pre-generated TLS certificate created above.
|
||||
// The test name "derpverify" is embedded in the hostname variable.
|
||||
//
|
||||
// WithCACert passes the external DERP server's certificate so
|
||||
// tailscale clients trust it. WithCustomTLS and WithDERPConfig
|
||||
// configure headscale to use the external DERP server created
|
||||
// above instead of the default embedded one.
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{tsic.WithCACert(derper.GetCert())},
|
||||
hsic.WithHostname(hostname),
|
||||
hsic.WithPort(headscalePort),
|
||||
hsic.WithCustomTLS(certHeadscale, keyHeadscale),
|
||||
hsic.WithCustomTLS(caHeadscale, certHeadscale, keyHeadscale),
|
||||
hsic.WithDERPConfig(derpMap))
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
|
||||
@@ -104,8 +104,6 @@ func TestResolveMagicDNSExtraRecordsPath(t *testing.T) {
|
||||
"HEADSCALE_DNS_EXTRA_RECORDS_PATH": erPath,
|
||||
}),
|
||||
hsic.WithFileInContainer(erPath, b),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ type DERPServerInContainer struct {
|
||||
stunPort int
|
||||
derpPort int
|
||||
caCerts [][]byte
|
||||
tlsCACert []byte
|
||||
tlsCert []byte
|
||||
tlsKey []byte
|
||||
withExtraHosts []string
|
||||
@@ -160,22 +161,27 @@ func New(
|
||||
hostname = fmt.Sprintf("derp-%s-%s", strings.ReplaceAll(version, ".", "-"), hash)
|
||||
}
|
||||
|
||||
tlsCert, tlsKey, err := integrationutil.CreateCertificate(hostname)
|
||||
tlsCACert, tlsCert, tlsKey, err := integrationutil.CreateCertificate(hostname)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating certificates for headscale test: %w", err)
|
||||
return nil, fmt.Errorf("creating certificates for derp test: %w", err)
|
||||
}
|
||||
|
||||
dsic := &DERPServerInContainer{
|
||||
version: version,
|
||||
hostname: hostname,
|
||||
pool: pool,
|
||||
networks: networks,
|
||||
tlsCert: tlsCert,
|
||||
tlsKey: tlsKey,
|
||||
stunPort: 3478, //nolint
|
||||
derpPort: 443, //nolint
|
||||
version: version,
|
||||
hostname: hostname,
|
||||
pool: pool,
|
||||
networks: networks,
|
||||
tlsCACert: tlsCACert,
|
||||
tlsCert: tlsCert,
|
||||
tlsKey: tlsKey,
|
||||
stunPort: 3478, //nolint
|
||||
derpPort: 443, //nolint
|
||||
}
|
||||
|
||||
// Install the CA cert so the DERP server trusts its own certificate
|
||||
// and any headscale CA certs passed via WithCACert.
|
||||
dsic.caCerts = append(dsic.caCerts, tlsCACert)
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(dsic)
|
||||
}
|
||||
@@ -297,9 +303,10 @@ func (t *DERPServerInContainer) Shutdown() error {
|
||||
return t.pool.Purge(t.container)
|
||||
}
|
||||
|
||||
// GetCert returns the TLS certificate of the DERPer instance.
|
||||
// GetCert returns the CA certificate that clients should trust to
|
||||
// verify this DERP server's TLS certificate.
|
||||
func (t *DERPServerInContainer) GetCert() []byte {
|
||||
return t.tlsCert
|
||||
return t.tlsCACert
|
||||
}
|
||||
|
||||
// Hostname returns the hostname of the DERPer instance.
|
||||
|
||||
@@ -28,7 +28,7 @@ func TestDERPServerScenario(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
derpServerScenario(t, spec, false, func(scenario *Scenario) {
|
||||
derpServerScenario(t, spec, "derp-tcp", false, func(scenario *Scenario) {
|
||||
allClients, err := scenario.ListTailscaleClients()
|
||||
requireNoErrListClients(t, err)
|
||||
t.Logf("checking %d clients for websocket connections", len(allClients))
|
||||
@@ -78,7 +78,7 @@ func TestDERPServerWebsocketScenario(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
derpServerScenario(t, spec, true, func(scenario *Scenario) {
|
||||
derpServerScenario(t, spec, "derp-ws", true, func(scenario *Scenario) {
|
||||
allClients, err := scenario.ListTailscaleClients()
|
||||
requireNoErrListClients(t, err)
|
||||
t.Logf("checking %d clients for websocket connections", len(allClients))
|
||||
@@ -103,6 +103,7 @@ func TestDERPServerWebsocketScenario(t *testing.T) {
|
||||
func derpServerScenario(
|
||||
t *testing.T,
|
||||
spec ScenarioSpec,
|
||||
testName string,
|
||||
websocket bool,
|
||||
furtherAssertions ...func(*Scenario),
|
||||
) {
|
||||
@@ -117,11 +118,11 @@ func derpServerScenario(
|
||||
[]tsic.Option{
|
||||
tsic.WithWebsocketDERP(websocket),
|
||||
},
|
||||
hsic.WithTestName("derpserver"),
|
||||
hsic.WithTestName(testName),
|
||||
// Expose STUN port for DERP NAT traversal.
|
||||
hsic.WithExtraPorts([]string{"3478/udp"}),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
// DERP clients expect the server on the standard HTTPS port.
|
||||
hsic.WithPort(443),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithConfigEnv(map[string]string{
|
||||
"HEADSCALE_DERP_AUTO_UPDATE_ENABLED": "true",
|
||||
"HEADSCALE_DERP_UPDATE_FREQUENCY": "10s",
|
||||
|
||||
@@ -41,8 +41,9 @@ func TestPingAllByIP(t *testing.T) {
|
||||
err = scenario.CreateHeadscaleEnv(
|
||||
[]tsic.Option{},
|
||||
hsic.WithTestName("pingallbyip"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
// All other tests use the default sequential allocation.
|
||||
// This test uses random allocation to ensure it does not
|
||||
// break basic connectivity.
|
||||
hsic.WithIPAllocationStrategy(types.IPAllocationStrategyRandom),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
@@ -102,6 +103,12 @@ func TestPingAllByIPPublicDERP(t *testing.T) {
|
||||
err = scenario.CreateHeadscaleEnv(
|
||||
[]tsic.Option{},
|
||||
hsic.WithTestName("pingallbyippubderp"),
|
||||
// Explicitly use public DERP relays instead of the embedded
|
||||
// DERP server to verify connectivity through Tailscale's
|
||||
// infrastructure. TLS is disabled because the headscale
|
||||
// server does not need to terminate TLS for this test.
|
||||
hsic.WithPublicDERP(),
|
||||
hsic.WithoutTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -128,6 +135,8 @@ func TestEphemeral(t *testing.T) {
|
||||
testEphemeralWithOptions(t, hsic.WithTestName("ephemeral"))
|
||||
}
|
||||
|
||||
// TestEphemeralInAlternateTimezone verifies that ephemeral node
|
||||
// expiry works correctly when the server runs in a non-UTC timezone.
|
||||
func TestEphemeralInAlternateTimezone(t *testing.T) {
|
||||
testEphemeralWithOptions(
|
||||
t,
|
||||
@@ -387,8 +396,6 @@ func TestTaildrop(t *testing.T) {
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{},
|
||||
hsic.WithTestName("taildrop"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1403,9 +1410,6 @@ func TestPingAllByIPManyUpDown(t *testing.T) {
|
||||
err = scenario.CreateHeadscaleEnv(
|
||||
[]tsic.Option{},
|
||||
hsic.WithTestName("pingallbyipmany"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithDERPAsIP(),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1512,8 +1516,6 @@ func Test2118DeletingOnlineNodePanics(t *testing.T) {
|
||||
err = scenario.CreateHeadscaleEnv(
|
||||
[]tsic.Option{},
|
||||
hsic.WithTestName("deletenocrash"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
|
||||
@@ -28,11 +28,24 @@ func DefaultConfigEnv() map[string]string {
|
||||
"HEADSCALE_PRIVATE_KEY_PATH": "/tmp/private.key",
|
||||
"HEADSCALE_NOISE_PRIVATE_KEY_PATH": "/tmp/noise_private.key",
|
||||
"HEADSCALE_METRICS_LISTEN_ADDR": "0.0.0.0:9090",
|
||||
"HEADSCALE_DERP_URLS": "https://controlplane.tailscale.com/derpmap/default",
|
||||
"HEADSCALE_DERP_AUTO_UPDATE_ENABLED": "false",
|
||||
"HEADSCALE_DERP_UPDATE_FREQUENCY": "1m",
|
||||
"HEADSCALE_DEBUG_PORT": "40000",
|
||||
|
||||
// Embedded DERP is the default for test isolation.
|
||||
// Tests should not depend on external DERP infrastructure.
|
||||
// Use WithPublicDERP() to opt out for tests that explicitly
|
||||
// need public DERP relays.
|
||||
"HEADSCALE_DERP_URLS": "",
|
||||
"HEADSCALE_DERP_AUTO_UPDATE_ENABLED": "false",
|
||||
"HEADSCALE_DERP_UPDATE_FREQUENCY": "1m",
|
||||
"HEADSCALE_DERP_SERVER_ENABLED": "true",
|
||||
"HEADSCALE_DERP_SERVER_REGION_ID": "999",
|
||||
"HEADSCALE_DERP_SERVER_REGION_CODE": "headscale",
|
||||
"HEADSCALE_DERP_SERVER_REGION_NAME": "Headscale Embedded DERP",
|
||||
"HEADSCALE_DERP_SERVER_STUN_LISTEN_ADDR": "0.0.0.0:3478",
|
||||
"HEADSCALE_DERP_SERVER_PRIVATE_KEY_PATH": "/tmp/derp.key",
|
||||
"DERP_DEBUG_LOGS": "true",
|
||||
"DERP_PROBER_DEBUG_LOGS": "true",
|
||||
|
||||
// a bunch of tests (ACL/Policy) rely on predictable IP alloc,
|
||||
// so ensure the sequential alloc is used by default.
|
||||
"HEADSCALE_PREFIXES_ALLOCATION": string(types.IPAllocationStrategySequential),
|
||||
|
||||
@@ -82,8 +82,10 @@ type HeadscaleInContainer struct {
|
||||
hostPortBindings map[string][]string
|
||||
aclPolicy *policyv2.Policy
|
||||
env map[string]string
|
||||
tlsCACert []byte
|
||||
tlsCert []byte
|
||||
tlsKey []byte
|
||||
noTLS bool
|
||||
filesInContainer []fileInContainer
|
||||
postgres bool
|
||||
policyMode types.PolicyMode
|
||||
@@ -115,24 +117,24 @@ func WithCACert(cert []byte) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithTLS creates certificates and enables HTTPS.
|
||||
func WithTLS() Option {
|
||||
// WithoutTLS disables the default TLS configuration.
|
||||
// Most tests should not need this. Use only for tests that
|
||||
// explicitly need to test non-TLS behavior.
|
||||
func WithoutTLS() Option {
|
||||
return func(hsic *HeadscaleInContainer) {
|
||||
cert, key, err := integrationutil.CreateCertificate(hsic.hostname)
|
||||
if err != nil {
|
||||
log.Fatalf("creating certificates for headscale test: %s", err)
|
||||
}
|
||||
|
||||
hsic.tlsCert = cert
|
||||
hsic.tlsKey = key
|
||||
hsic.noTLS = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithCustomTLS uses the given certificates for the Headscale instance.
|
||||
func WithCustomTLS(cert, key []byte) Option {
|
||||
// The caCert is installed into the container's trust store and returned
|
||||
// by GetCert() so that clients can trust this server.
|
||||
func WithCustomTLS(caCert, cert, key []byte) Option {
|
||||
return func(hsic *HeadscaleInContainer) {
|
||||
hsic.tlsCACert = caCert
|
||||
hsic.tlsCert = cert
|
||||
hsic.tlsKey = key
|
||||
hsic.caCerts = append(hsic.caCerts, caCert)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,25 +218,20 @@ func WithIPAllocationStrategy(strategy types.IPAllocationStrategy) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithEmbeddedDERPServerOnly configures Headscale to start
|
||||
// and only use the embedded DERP server.
|
||||
// It requires WithTLS and WithHostnameAsServerURL to be
|
||||
// set.
|
||||
//
|
||||
//nolint:goconst // env var values like "true" and "headscale" are clearer inline
|
||||
func WithEmbeddedDERPServerOnly() Option {
|
||||
// WithPublicDERP disables the embedded DERP server and restores
|
||||
// the default public DERP relay configuration. Use this for tests
|
||||
// that explicitly need to test public DERP behavior.
|
||||
func WithPublicDERP() Option {
|
||||
return func(hsic *HeadscaleInContainer) {
|
||||
hsic.env["HEADSCALE_DERP_URLS"] = ""
|
||||
hsic.env["HEADSCALE_DERP_SERVER_ENABLED"] = "true"
|
||||
hsic.env["HEADSCALE_DERP_SERVER_REGION_ID"] = "999"
|
||||
hsic.env["HEADSCALE_DERP_SERVER_REGION_CODE"] = "headscale"
|
||||
hsic.env["HEADSCALE_DERP_SERVER_REGION_NAME"] = "Headscale Embedded DERP"
|
||||
hsic.env["HEADSCALE_DERP_SERVER_STUN_LISTEN_ADDR"] = "0.0.0.0:3478"
|
||||
hsic.env["HEADSCALE_DERP_SERVER_PRIVATE_KEY_PATH"] = "/tmp/derp.key"
|
||||
|
||||
// Envknob for enabling DERP debug logs
|
||||
hsic.env["DERP_DEBUG_LOGS"] = "true"
|
||||
hsic.env["DERP_PROBER_DEBUG_LOGS"] = "true"
|
||||
hsic.env["HEADSCALE_DERP_URLS"] = "https://controlplane.tailscale.com/derpmap/default"
|
||||
hsic.env["HEADSCALE_DERP_SERVER_ENABLED"] = "false"
|
||||
delete(hsic.env, "HEADSCALE_DERP_SERVER_REGION_ID")
|
||||
delete(hsic.env, "HEADSCALE_DERP_SERVER_REGION_CODE")
|
||||
delete(hsic.env, "HEADSCALE_DERP_SERVER_REGION_NAME")
|
||||
delete(hsic.env, "HEADSCALE_DERP_SERVER_STUN_LISTEN_ADDR")
|
||||
delete(hsic.env, "HEADSCALE_DERP_SERVER_PRIVATE_KEY_PATH")
|
||||
delete(hsic.env, "DERP_DEBUG_LOGS")
|
||||
delete(hsic.env, "DERP_PROBER_DEBUG_LOGS")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,14 +279,6 @@ func WithTimezone(timezone string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithDERPAsIP enables using IP address instead of hostname for DERP server.
|
||||
// This is useful for integration tests where DNS resolution may be unreliable.
|
||||
func WithDERPAsIP() Option {
|
||||
return func(hsic *HeadscaleInContainer) {
|
||||
hsic.env["HEADSCALE_DEBUG_DERP_USE_IP"] = "1"
|
||||
}
|
||||
}
|
||||
|
||||
// buildEntrypoint builds the container entrypoint command based on configuration.
|
||||
// It constructs proper wait conditions instead of fixed sleeps:
|
||||
// 1. Wait for network to be ready
|
||||
@@ -367,6 +356,26 @@ func New(
|
||||
opt(hsic)
|
||||
}
|
||||
|
||||
// TLS is enabled by default for all integration tests.
|
||||
// Generate a self-signed certificate if TLS was not explicitly
|
||||
// disabled via WithoutTLS() and no custom cert was provided
|
||||
// via WithCustomTLS().
|
||||
if !hsic.noTLS && len(hsic.tlsCert) == 0 {
|
||||
caCert, cert, key, err := integrationutil.CreateCertificate(hsic.hostname)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating default TLS certificates: %w", err)
|
||||
}
|
||||
|
||||
hsic.tlsCACert = caCert
|
||||
hsic.tlsCert = cert
|
||||
hsic.tlsKey = key
|
||||
|
||||
// Install the CA cert into the headscale container's trust
|
||||
// store so that tools like curl trust the server's own
|
||||
// certificate.
|
||||
hsic.caCerts = append(hsic.caCerts, caCert)
|
||||
}
|
||||
|
||||
log.Println("NAME: ", hsic.hostname)
|
||||
|
||||
portProto := fmt.Sprintf("%d/tcp", hsic.port)
|
||||
@@ -1030,9 +1039,10 @@ func (t *HeadscaleInContainer) getEndpoint(useIP bool) string {
|
||||
return "http://" + hostEndpoint
|
||||
}
|
||||
|
||||
// GetCert returns the public certificate of the HeadscaleInContainer.
|
||||
// GetCert returns the CA certificate that clients should trust to
|
||||
// verify this server's TLS certificate.
|
||||
func (t *HeadscaleInContainer) GetCert() []byte {
|
||||
return t.tlsCert
|
||||
return t.tlsCACert
|
||||
}
|
||||
|
||||
// GetHostname returns the hostname of the HeadscaleInContainer.
|
||||
|
||||
@@ -120,7 +120,11 @@ func FetchPathFromContainer(
|
||||
}
|
||||
|
||||
// nolint
|
||||
func CreateCertificate(hostname string) ([]byte, []byte, error) {
|
||||
// CreateCertificate generates a CA certificate and a server certificate
|
||||
// signed by that CA for the given hostname. It returns the CA certificate
|
||||
// PEM (for trust stores), server certificate PEM, and server private key
|
||||
// PEM.
|
||||
func CreateCertificate(hostname string) (caCertPEM, certPEM, keyPEM []byte, err error) {
|
||||
// From:
|
||||
// https://shaneutt.com/blog/golang-ca-and-signed-cert-go/
|
||||
|
||||
@@ -144,7 +148,27 @@ func CreateCertificate(hostname string) ([]byte, []byte, error) {
|
||||
|
||||
caPrivKey, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
caBytes, err := x509.CreateCertificate(
|
||||
rand.Reader,
|
||||
ca,
|
||||
ca,
|
||||
&caPrivKey.PublicKey,
|
||||
caPrivKey,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
caPEM := new(bytes.Buffer)
|
||||
err = pem.Encode(caPEM, &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: caBytes,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
cert := &x509.Certificate{
|
||||
@@ -165,7 +189,7 @@ func CreateCertificate(hostname string) ([]byte, []byte, error) {
|
||||
|
||||
certPrivKey, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
certBytes, err := x509.CreateCertificate(
|
||||
@@ -176,30 +200,28 @@ func CreateCertificate(hostname string) ([]byte, []byte, error) {
|
||||
caPrivKey,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
certPEM := new(bytes.Buffer)
|
||||
|
||||
err = pem.Encode(certPEM, &pem.Block{
|
||||
serverCertPEM := new(bytes.Buffer)
|
||||
err = pem.Encode(serverCertPEM, &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: certBytes,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
certPrivKeyPEM := new(bytes.Buffer)
|
||||
|
||||
err = pem.Encode(certPrivKeyPEM, &pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(certPrivKey),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return certPEM.Bytes(), certPrivKeyPEM.Bytes(), nil
|
||||
return caPEM.Bytes(), serverCertPEM.Bytes(), certPrivKeyPEM.Bytes(), nil
|
||||
}
|
||||
|
||||
func BuildExpectedOnlineMap(all map[types.NodeID][]tailcfg.MapResponse) map[types.NodeID]map[types.NodeID]bool {
|
||||
|
||||
@@ -55,7 +55,7 @@ func TestEnablingRoutes(t *testing.T) {
|
||||
|
||||
err = scenario.CreateHeadscaleEnv(
|
||||
[]tsic.Option{tsic.WithAcceptRoutes()},
|
||||
hsic.WithTestName("clienableroute"))
|
||||
hsic.WithTestName("rt-enable"))
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
allClients, err := scenario.ListTailscaleClients()
|
||||
@@ -261,9 +261,7 @@ func TestHASubnetRouterFailover(t *testing.T) {
|
||||
|
||||
err = scenario.CreateHeadscaleEnv(
|
||||
[]tsic.Option{tsic.WithAcceptRoutes()},
|
||||
hsic.WithTestName("clienableroute"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithTestName("rt-hafailover"),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1363,7 +1361,7 @@ func TestSubnetRouteACL(t *testing.T) {
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{
|
||||
tsic.WithAcceptRoutes(),
|
||||
}, hsic.WithTestName("clienableroute"), hsic.WithACLPolicy(
|
||||
}, hsic.WithTestName("rt-subnetacl"), hsic.WithACLPolicy(
|
||||
&policyv2.Policy{
|
||||
Groups: policyv2.Groups{
|
||||
policyv2.Group("group:admins"): []policyv2.Username{policyv2.Username(user + "@")},
|
||||
@@ -1616,7 +1614,7 @@ func TestEnablingExitRoutes(t *testing.T) {
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{
|
||||
tsic.WithExtraLoginArgs([]string{"--advertise-exit-node"}),
|
||||
}, hsic.WithTestName("clienableroute"))
|
||||
}, hsic.WithTestName("rt-exitroute"))
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
allClients, err := scenario.ListTailscaleClients()
|
||||
@@ -1729,9 +1727,7 @@ func TestSubnetRouterMultiNetwork(t *testing.T) {
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{tsic.WithAcceptRoutes()},
|
||||
hsic.WithTestName("clienableroute"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithTestName("rt-multinet"),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1884,9 +1880,7 @@ func TestSubnetRouterMultiNetworkExitNode(t *testing.T) {
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{},
|
||||
hsic.WithTestName("clienableroute"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithTestName("rt-multinetexit"),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -2306,10 +2300,8 @@ func TestAutoApproveMultiNetwork(t *testing.T) {
|
||||
|
||||
opts := []hsic.Option{
|
||||
hsic.WithTestName("autoapprovemulti"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithACLPolicy(pol),
|
||||
hsic.WithPolicyMode(polMode),
|
||||
hsic.WithPolicyMode(polMode), // test iterates over file and DB policy modes
|
||||
}
|
||||
|
||||
tsOpts := []tsic.Option{
|
||||
@@ -3026,7 +3018,7 @@ func TestSubnetRouteACLFiltering(t *testing.T) {
|
||||
tsic.WithAcceptRoutes(),
|
||||
}, hsic.WithTestName("routeaclfilter"),
|
||||
hsic.WithACLPolicy(aclPolicy),
|
||||
hsic.WithPolicyMode(types.PolicyModeDB),
|
||||
hsic.WithPolicyMode(types.PolicyModeDB), // test updates policy at runtime via CLI
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/juanfont/headscale/integration/dockertestutil"
|
||||
"github.com/juanfont/headscale/integration/hsic"
|
||||
"github.com/juanfont/headscale/integration/tsic"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -40,7 +41,7 @@ func TestHeadscale(t *testing.T) {
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
t.Run("start-headscale", func(t *testing.T) {
|
||||
headscale, err := scenario.Headscale()
|
||||
headscale, err := scenario.Headscale(hsic.WithTestName("scenariohs"))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create start headcale: %s", err)
|
||||
}
|
||||
@@ -89,7 +90,7 @@ func TestTailscaleNodesJoiningHeadcale(t *testing.T) {
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
t.Run("start-headscale", func(t *testing.T) {
|
||||
headscale, err := scenario.Headscale()
|
||||
headscale, err := scenario.Headscale(hsic.WithTestName("scenariojoin"))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create start headcale: %s", err)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func isSSHNoAccessStdError(stderr string) bool {
|
||||
strings.Contains(stderr, "tailnet policy does not permit you to SSH")
|
||||
}
|
||||
|
||||
func sshScenario(t *testing.T, policy *policyv2.Policy, clientsPerUser int) *Scenario {
|
||||
func sshScenario(t *testing.T, policy *policyv2.Policy, testName string, clientsPerUser int) *Scenario {
|
||||
t.Helper()
|
||||
|
||||
spec := ScenarioSpec{
|
||||
@@ -50,7 +50,7 @@ func sshScenario(t *testing.T, policy *policyv2.Policy, clientsPerUser int) *Sce
|
||||
tsic.WithDockerWorkdir("/"),
|
||||
},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("ssh"),
|
||||
hsic.WithTestName(testName),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -95,6 +95,7 @@ func TestSSHOneUserToAll(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"ssh-onetoall",
|
||||
len(MustTestVersions),
|
||||
)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
@@ -168,6 +169,7 @@ func TestSSHMultipleUsersAllToAll(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"ssh-multiall",
|
||||
len(MustTestVersions),
|
||||
)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
@@ -242,6 +244,7 @@ func TestSSHNoSSHConfigured(t *testing.T) {
|
||||
},
|
||||
SSHs: []policyv2.SSH{},
|
||||
},
|
||||
"ssh-nosshcfg",
|
||||
len(MustTestVersions),
|
||||
)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
@@ -293,6 +296,7 @@ func TestSSHIsBlockedInACL(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"ssh-blocked",
|
||||
len(MustTestVersions),
|
||||
)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
@@ -354,6 +358,7 @@ func TestSSHUserOnlyIsolation(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"ssh-isolation",
|
||||
len(MustTestVersions),
|
||||
)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
@@ -571,6 +576,7 @@ func TestSSHAutogroupSelf(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"ssh-agself",
|
||||
2, // 2 clients per user
|
||||
)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
@@ -811,7 +817,7 @@ func findNewSSHCheckAuthID(
|
||||
func TestSSHOneUserToOneCheckModeCLI(t *testing.T) {
|
||||
IntegrationSkip(t)
|
||||
|
||||
scenario := sshScenario(t, sshCheckPolicy(), 1)
|
||||
scenario := sshScenario(t, sshCheckPolicy(), "ssh-checkcli", 1)
|
||||
// defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
allClients, err := scenario.ListTailscaleClients()
|
||||
@@ -920,7 +926,6 @@ func TestSSHOneUserToOneCheckModeOIDC(t *testing.T) {
|
||||
hsic.WithACLPolicy(sshCheckPolicy()),
|
||||
hsic.WithTestName("sshcheckoidc"),
|
||||
hsic.WithConfigEnv(oidcMap),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithFileInContainer(
|
||||
"/tmp/hs_client_oidc_secret",
|
||||
[]byte(scenario.mockOIDC.ClientSecret()),
|
||||
@@ -1087,7 +1092,7 @@ func TestSSHCheckModeCheckPeriodCLI(t *testing.T) {
|
||||
IntegrationSkip(t)
|
||||
|
||||
// 1 minute is the documented minimum checkPeriod
|
||||
scenario := sshScenario(t, sshCheckPolicyWithPeriod(time.Minute), 1)
|
||||
scenario := sshScenario(t, sshCheckPolicyWithPeriod(time.Minute), "ssh-checkperiod", 1)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
allClients, err := scenario.ListTailscaleClients()
|
||||
@@ -1182,7 +1187,7 @@ func TestSSHCheckModeAutoApprove(t *testing.T) {
|
||||
IntegrationSkip(t)
|
||||
|
||||
// 5 minute checkPeriod — long enough not to expire during test
|
||||
scenario := sshScenario(t, sshCheckPolicyWithPeriod(5*time.Minute), 1)
|
||||
scenario := sshScenario(t, sshCheckPolicyWithPeriod(5*time.Minute), "ssh-autoapprove", 1)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
allClients, err := scenario.ListTailscaleClients()
|
||||
@@ -1247,7 +1252,7 @@ func TestSSHCheckModeAutoApprove(t *testing.T) {
|
||||
func TestSSHCheckModeNegativeCLI(t *testing.T) {
|
||||
IntegrationSkip(t)
|
||||
|
||||
scenario := sshScenario(t, sshCheckPolicy(), 1)
|
||||
scenario := sshScenario(t, sshCheckPolicy(), "ssh-negcli", 1)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
allClients, err := scenario.ListTailscaleClients()
|
||||
@@ -1509,7 +1514,6 @@ func TestSSHLocalpart(t *testing.T) {
|
||||
hsic.WithTestName("sshlocalpart"),
|
||||
hsic.WithACLPolicy(tt.policy),
|
||||
hsic.WithConfigEnv(oidcMap),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithFileInContainer("/tmp/hs_client_oidc_secret", []byte(scenario.mockOIDC.ClientSecret())),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -138,7 +138,6 @@ func TestTagsAuthKeyWithTagRequestDifferentTag(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-authkey-diff"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -213,7 +212,6 @@ func TestTagsAuthKeyWithTagNoAdvertiseFlag(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-authkey-inherit"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -286,7 +284,6 @@ func TestTagsAuthKeyWithTagCannotAddViaCLI(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-authkey-noadd"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -387,7 +384,6 @@ func TestTagsAuthKeyWithTagCannotChangeViaCLI(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-authkey-nochange"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -484,7 +480,6 @@ func TestTagsAuthKeyWithTagAdminOverrideReauthPreserves(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-authkey-admin"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -612,7 +607,6 @@ func TestTagsAuthKeyWithTagCLICannotModifyAdminTags(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-authkey-noadmin"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -735,7 +729,6 @@ func TestTagsAuthKeyWithoutTagCannotRequestTags(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-nokey-req"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -807,7 +800,6 @@ func TestTagsAuthKeyWithoutTagRegisterNoTags(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-nokey-noreg"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -877,7 +869,6 @@ func TestTagsAuthKeyWithoutTagCannotAddViaCLI(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-nokey-noadd"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -977,7 +968,6 @@ func TestTagsAuthKeyWithoutTagCLINoOpAfterAdminWithReset(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-nokey-reset"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1098,7 +1088,6 @@ func TestTagsAuthKeyWithoutTagCLINoOpAfterAdminWithEmptyAdvertise(t *testing.T)
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-nokey-empty"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1218,7 +1207,6 @@ func TestTagsAuthKeyWithoutTagCLICannotReduceAdminMultiTag(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-nokey-reduce"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1340,7 +1328,6 @@ func TestTagsUserLoginOwnedTagAtRegistration(t *testing.T) {
|
||||
},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-webauth-owned"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1411,7 +1398,6 @@ func TestTagsUserLoginNonExistentTagAtRegistration(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-webauth-nonexist"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1484,7 +1470,6 @@ func TestTagsUserLoginUnownedTagAtRegistration(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-webauth-unowned"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1554,7 +1539,6 @@ func TestTagsUserLoginAddTagViaCLIReauth(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-webauth-addtag"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1646,7 +1630,6 @@ func TestTagsUserLoginRemoveTagViaCLIReauth(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-webauth-rmtag"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1738,7 +1721,6 @@ func TestTagsUserLoginCLINoOpAfterAdminAssignment(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-webauth-adminwin"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1856,7 +1838,6 @@ func TestTagsUserLoginCLICannotRemoveAdminTags(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-webauth-norem"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -1974,7 +1955,6 @@ func TestTagsAuthKeyWithTagRequestNonExistentTag(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-authkey-nonexist"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -2045,7 +2025,6 @@ func TestTagsAuthKeyWithTagRequestUnownedTag(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-authkey-unowned"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -2120,7 +2099,6 @@ func TestTagsAuthKeyWithoutTagRequestNonExistentTag(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-nokey-nonexist"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -2191,7 +2169,6 @@ func TestTagsAuthKeyWithoutTagRequestUnownedTag(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-nokey-unowned"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -2266,7 +2243,6 @@ func TestTagsAdminAPICannotSetNonExistentTag(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-admin-nonexist"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -2339,7 +2315,6 @@ func TestTagsAdminAPICanSetUnownedTag(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-admin-unowned"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -2428,7 +2403,6 @@ func TestTagsAdminAPICannotRemoveAllTags(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-admin-empty"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -2546,7 +2520,6 @@ func TestTagsIssue2978ReproTagReplacement(t *testing.T) {
|
||||
},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-issue-2978"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -2752,7 +2725,6 @@ func TestTagsAdminAPICannotSetInvalidFormat(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-admin-invalid"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -2853,7 +2825,6 @@ func TestTagsUserLoginReauthWithEmptyTagsRemovesAllTags(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-reauth-untag-2979-"+tc.testName),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -3008,7 +2979,6 @@ func TestTagsAuthKeyWithoutUserInheritsTags(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-authkey-no-user-inherit"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -3080,7 +3050,6 @@ func TestTagsAuthKeyWithoutUserRejectsAdvertisedTags(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-authkey-no-user-reject-advertise"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
@@ -3147,7 +3116,6 @@ func TestTagsAuthKeyConvertToUserViaCLIRegister(t *testing.T) {
|
||||
[]tsic.Option{},
|
||||
hsic.WithACLPolicy(policy),
|
||||
hsic.WithTestName("tags-authkey-to-user-cli-3038"),
|
||||
hsic.WithTLS(),
|
||||
)
|
||||
requireNoErrHeadscaleEnv(t, err)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user