1
0
mirror of https://github.com/juanfont/headscale.git synced 2025-08-14 13:51:01 +02:00

wire up policyv2 in integration testing

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
Kristoffer Dalby 2025-02-26 19:32:28 +01:00
parent 72049e94b1
commit b55a7d8b52
No known key found for this signature in database
5 changed files with 88 additions and 7 deletions

View File

@ -79,6 +79,7 @@ jobs:
- TestSSHIsBlockedInACL
- TestSSHUserOnlyIsolation
database: [postgres, sqlite]
policy: ["v1", "v2"]
env:
# Github does not allow us to access secrets in pull requests,
# so this env var is used to check if we have the secret or not.
@ -126,6 +127,7 @@ jobs:
if: steps.changed-files.outputs.files == 'true'
env:
USE_POSTGRES: ${{ matrix.database == 'postgres' && '1' || '0' }}
USE_POLICY_V2: ${{ matrix.policy == 'v2' && '1' || '0' }}
with:
attempt_limit: 5
command: |
@ -137,6 +139,7 @@ jobs:
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
--env HEADSCALE_INTEGRATION_POSTGRES=${{env.USE_POSTGRES}} \
--env HEADSCALE_EXPERIMENTAL_POLICY_V2=${{env.USE_POLICY_V2}} \
golang:1 \
go run gotest.tools/gotestsum@latest -- ./... \
-failfast \
@ -146,12 +149,12 @@ jobs:
- uses: actions/upload-artifact@v4
if: always() && steps.changed-files.outputs.files == 'true'
with:
name: ${{ matrix.test }}-${{matrix.database}}-logs
name: ${{ matrix.test }}-${{matrix.database}}-${{matrix.policy}}-logs
path: "control_logs/*.log"
- uses: actions/upload-artifact@v4
if: always() && steps.changed-files.outputs.files == 'true'
with:
name: ${{ matrix.test }}-${{matrix.database}}-pprof
name: ${{ matrix.test }}-${{matrix.database}}-${{matrix.policy}}-pprof
path: "control_logs/*.pprof.tar"
- name: Setup a blocking tmux session
if: ${{ env.HAS_TAILSCALE_SECRET }}

View File

@ -1097,6 +1097,9 @@ func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) {
},
Hosts: policyv1.Hosts{},
}
if usePolicyV2ForTest {
hsic.RewritePolicyToV2(&p)
}
pBytes, _ := json.Marshal(p)

View File

@ -1726,7 +1726,7 @@ func TestPolicyCommand(t *testing.T) {
defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{
"policy-user": 0,
"user1": 0,
}
err = scenario.CreateHeadscaleEnv(
@ -1751,9 +1751,12 @@ func TestPolicyCommand(t *testing.T) {
},
},
TagOwners: map[string][]string{
"tag:exists": {"policy-user"},
"tag:exists": {"user1"},
},
}
if usePolicyV2ForTest {
hsic.RewritePolicyToV2(&p)
}
pBytes, _ := json.Marshal(p)
@ -1794,7 +1797,11 @@ func TestPolicyCommand(t *testing.T) {
assert.Len(t, output.TagOwners, 1)
assert.Len(t, output.ACLs, 1)
assert.Equal(t, output.TagOwners["tag:exists"], []string{"policy-user"})
if usePolicyV2ForTest {
assert.Equal(t, output.TagOwners["tag:exists"], []string{"user1@"})
} else {
assert.Equal(t, output.TagOwners["tag:exists"], []string{"user1"})
}
}
func TestPolicyBrokenConfigCommand(t *testing.T) {
@ -1806,7 +1813,7 @@ func TestPolicyBrokenConfigCommand(t *testing.T) {
defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{
"policy-user": 1,
"user1": 1,
}
err = scenario.CreateHeadscaleEnv(
@ -1833,9 +1840,12 @@ func TestPolicyBrokenConfigCommand(t *testing.T) {
},
},
TagOwners: map[string][]string{
"tag:exists": {"policy-user"},
"tag:exists": {"user1"},
},
}
if usePolicyV2ForTest {
hsic.RewritePolicyToV2(&p)
}
pBytes, _ := json.Marshal(p)

View File

@ -71,6 +71,7 @@ type HeadscaleInContainer struct {
tlsKey []byte
filesInContainer []fileInContainer
postgres bool
policyV2 bool
}
// Option represent optional settings that can be given to a
@ -187,6 +188,14 @@ func WithPostgres() Option {
}
}
// WithPolicyV2 tells the integration test to use the new v2 filter.
func WithPolicyV2() Option {
return func(hsic *HeadscaleInContainer) {
hsic.policyV2 = true
hsic.env["HEADSCALE_EXPERIMENTAL_POLICY_V2"] = "1"
}
}
// WithIPAllocationStrategy sets the tests IP Allocation strategy.
func WithIPAllocationStrategy(strategy types.IPAllocationStrategy) Option {
return func(hsic *HeadscaleInContainer) {
@ -404,6 +413,10 @@ func New(
}
if hsic.aclPolicy != nil {
// Rewrite all user entries in the policy to have an @ at the end.
if hsic.policyV2 {
RewritePolicyToV2(hsic.aclPolicy)
}
data, err := json.Marshal(hsic.aclPolicy)
if err != nil {
return nil, fmt.Errorf("failed to marshal ACL Policy to JSON: %w", err)
@ -870,3 +883,50 @@ func (t *HeadscaleInContainer) SendInterrupt() error {
return nil
}
// TODO(kradalby): Remove this function when v1 is deprecated
func rewriteUsersToV2(strs []string) []string {
var result []string
userPattern := regexp.MustCompile(`^user\d+$`)
for _, username := range strs {
parts := strings.Split(username, ":")
if len(parts) == 0 {
result = append(result, username)
continue
}
firstPart := parts[0]
if userPattern.MatchString(firstPart) {
modifiedFirst := firstPart + "@"
if len(parts) > 1 {
rest := strings.Join(parts[1:], ":")
username = modifiedFirst + ":" + rest
} else {
username = modifiedFirst
}
}
result = append(result, username)
}
return result
}
// rewritePolicyToV2 rewrites the policy to v2 format.
// This mostly means adding the @ prefix to user names.
// replaces are done inplace
func RewritePolicyToV2(pol *policyv1.ACLPolicy) {
for idx := range pol.ACLs {
pol.ACLs[idx].Sources = rewriteUsersToV2(pol.ACLs[idx].Sources)
pol.ACLs[idx].Destinations = rewriteUsersToV2(pol.ACLs[idx].Destinations)
}
for idx := range pol.Groups {
pol.Groups[idx] = rewriteUsersToV2(pol.Groups[idx])
}
for idx := range pol.TagOwners {
pol.TagOwners[idx] = rewriteUsersToV2(pol.TagOwners[idx])
}
for idx := range pol.SSHs {
pol.SSHs[idx].Sources = rewriteUsersToV2(pol.SSHs[idx].Sources)
pol.SSHs[idx].Destinations = rewriteUsersToV2(pol.SSHs[idx].Destinations)
}
}

View File

@ -33,6 +33,7 @@ const (
)
var usePostgresForTest = envknob.Bool("HEADSCALE_INTEGRATION_POSTGRES")
var usePolicyV2ForTest = envknob.Bool("HEADSCALE_EXPERIMENTAL_POLICY_V2")
var (
errNoHeadscaleAvailable = errors.New("no headscale available")
@ -230,6 +231,10 @@ func (s *Scenario) Headscale(opts ...hsic.Option) (ControlServer, error) {
opts = append(opts, hsic.WithPostgres())
}
if usePolicyV2ForTest {
opts = append(opts, hsic.WithPolicyV2())
}
headscale, err := hsic.New(s.pool, s.network, opts...)
if err != nil {
return nil, fmt.Errorf("failed to create headscale container: %w", err)