Compare commits

..

1 Commits

Author SHA1 Message Date
Juan Font
4b4200e8a5 Add ko-fi sponsor button 2022-12-22 17:14:06 +01:00
107 changed files with 3431 additions and 5522 deletions

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestAuthKeyLogoutAndRelogin
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestAuthKeyLogoutAndRelogin$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestAuthWebFlowAuthenticationPingAll
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestAuthWebFlowAuthenticationPingAll$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestAuthWebFlowLogoutAndRelogin
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestAuthWebFlowLogoutAndRelogin$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestCreateTailscale
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestCreateTailscale$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestEnablingRoutes
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestEnablingRoutes$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestHeadscale
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestHeadscale$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestNamespaceCommand
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestNamespaceCommand$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestOIDCAuthenticationPingAll
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestOIDCAuthenticationPingAll$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestOIDCExpireNodes
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestOIDCExpireNodes$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestPingAllByHostname
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestPingAllByHostname$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestPingAllByIP
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestPingAllByIP$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestPreAuthKeyCommand
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestPreAuthKeyCommand$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestPreAuthKeyCommandReusableEphemeral
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestPreAuthKeyCommandReusableEphemeral$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestPreAuthKeyCommandWithoutExpiry
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestPreAuthKeyCommandWithoutExpiry$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestResolveMagicDNS
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestResolveMagicDNS$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestSSHIsBlockedInACL
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestSSHIsBlockedInACL$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestSSHMultipleNamespacesAllToAll
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestSSHMultipleNamespacesAllToAll$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestSSHNoSSHConfigured
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestSSHNoSSHConfigured$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestSSHOneNamespaceAllToAll
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestSSHOneNamespaceAllToAll$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestSSNamespaceOnlyIsolation
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestSSNamespaceOnlyIsolation$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestTaildrop
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestTaildrop$"

View File

@@ -1,47 +0,0 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - TestTailscaleNodesJoiningHeadcale
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestTailscaleNodesJoiningHeadcale$"

View File

@@ -0,0 +1,35 @@
name: Integration Test v2 - kradalby
on: [pull_request]
jobs:
integration-test-v2-kradalby:
runs-on: [self-hosted, linux, x64, nixos, docker]
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
# We currently only run one job at the time, so make sure
# we just wipe all containers and all networks.
- name: Clean up Docker
if: steps.changed-files.outputs.any_changed == 'true'
run: |
docker kill $(docker ps -q) || true
docker network prune -f || true
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: nix develop --command -- make test_integration_v2_general

View File

@@ -1 +0,0 @@
.github/workflows/test-integration-v2*

View File

@@ -1,14 +1,6 @@
# CHANGELOG
## 0.19.0 (2022-11-26)
### BREAKING
- Rename Namespace to User [#1144](https://github.com/juanfont/headscale/pull/1144)
- **BACKUP your database before upgrading**
- Command line flags previously taking `--namespace` or `-n` will now require `--user` or `-u`
## 0.18.0 (2022-01-14)
## 0.18.x (2022-xx-xx)
### Changes
@@ -17,11 +9,6 @@
- Set `db_ssl` to false by default [#1052](https://github.com/juanfont/headscale/pull/1052)
- Fix duplicate nodes due to incorrect implementation of the protocol [#1058](https://github.com/juanfont/headscale/pull/1058)
- Report if a machine is online in CLI more accurately [#1062](https://github.com/juanfont/headscale/pull/1062)
- Added config option for custom DNS records [#1035](https://github.com/juanfont/headscale/pull/1035)
- Expire nodes based on OIDC token expiry [#1067](https://github.com/juanfont/headscale/pull/1067)
- Remove ephemeral nodes on logout [#1098](https://github.com/juanfont/headscale/pull/1098)
- Performance improvements in ACLs [#1129](https://github.com/juanfont/headscale/pull/1129)
- OIDC client secret can be passed via a file [#1127](https://github.com/juanfont/headscale/pull/1127)
## 0.17.1 (2022-12-05)

View File

@@ -26,7 +26,7 @@ dev: lint test build
test:
@go test $(TAGS) -short -coverprofile=coverage.out ./...
test_integration: test_integration_cli test_integration_derp test_integration_v2_general
test_integration: test_integration_cli test_integration_derp test_integration_oidc test_integration_v2_general
test_integration_cli:
docker network rm $$(docker network ls --filter name=headscale --quiet) || true

36
acls.go
View File

@@ -424,7 +424,7 @@ func parseProtocol(protocol string) ([]int, bool, error) {
}
// expandalias has an input of either
// - a user
// - a namespace
// - a group
// - a tag
// and transform these in IPAddresses.
@@ -444,12 +444,12 @@ func expandAlias(
Msg("Expanding")
if strings.HasPrefix(alias, "group:") {
users, err := expandGroup(aclPolicy, alias, stripEmailDomain)
namespaces, err := expandGroup(aclPolicy, alias, stripEmailDomain)
if err != nil {
return ips, err
}
for _, n := range users {
nodes := filterMachinesByUser(machines, n)
for _, n := range namespaces {
nodes := filterMachinesByNamespace(machines, n)
for _, node := range nodes {
ips = append(ips, node.IPAddresses.ToStringSlice()...)
}
@@ -485,8 +485,8 @@ func expandAlias(
}
// filter out machines per tag owner
for _, user := range owners {
machines := filterMachinesByUser(machines, user)
for _, namespace := range owners {
machines := filterMachinesByNamespace(machines, namespace)
for _, machine := range machines {
hi := machine.GetHostInfo()
if contains(hi.RequestTags, alias) {
@@ -498,8 +498,8 @@ func expandAlias(
return ips, nil
}
// if alias is a user
nodes := filterMachinesByUser(machines, alias)
// if alias is a namespace
nodes := filterMachinesByNamespace(machines, alias)
nodes = excludeCorrectlyTaggedNodes(aclPolicy, nodes, alias, stripEmailDomain)
for _, n := range nodes {
@@ -532,20 +532,20 @@ func expandAlias(
}
// excludeCorrectlyTaggedNodes will remove from the list of input nodes the ones
// that are correctly tagged since they should not be listed as being in the user
// we assume in this function that we only have nodes from 1 user.
// that are correctly tagged since they should not be listed as being in the namespace
// we assume in this function that we only have nodes from 1 namespace.
func excludeCorrectlyTaggedNodes(
aclPolicy ACLPolicy,
nodes []Machine,
user string,
namespace string,
stripEmailDomain bool,
) []Machine {
out := []Machine{}
tags := []string{}
for tag := range aclPolicy.TagOwners {
owners, _ := expandTagOwners(aclPolicy, user, stripEmailDomain)
ns := append(owners, user)
if contains(ns, user) {
owners, _ := expandTagOwners(aclPolicy, namespace, stripEmailDomain)
ns := append(owners, namespace)
if contains(ns, namespace) {
tags = append(tags, tag)
}
}
@@ -619,10 +619,10 @@ func expandPorts(portsStr string, needsWildcard bool) (*[]tailcfg.PortRange, err
return &ports, nil
}
func filterMachinesByUser(machines []Machine, user string) []Machine {
func filterMachinesByNamespace(machines []Machine, namespace string) []Machine {
out := []Machine{}
for _, machine := range machines {
if machine.User.Name == user {
if machine.Namespace.Name == namespace {
out = append(out, machine)
}
}
@@ -630,7 +630,7 @@ func filterMachinesByUser(machines []Machine, user string) []Machine {
return out
}
// expandTagOwners will return a list of user. An owner can be either a user or a group
// expandTagOwners will return a list of namespace. An owner can be either a namespace or a group
// a group cannot be composed of groups.
func expandTagOwners(
aclPolicy ACLPolicy,
@@ -661,7 +661,7 @@ func expandTagOwners(
return owners, nil
}
// expandGroup will return the list of user inside the group
// expandGroup will return the list of namespace inside the group
// after some validation.
func expandGroup(
aclPolicy ACLPolicy,

View File

@@ -77,10 +77,10 @@ func (s *Suite) TestInvalidAction(c *check.C) {
func (s *Suite) TestSshRules(c *check.C) {
envknob.Setenv("HEADSCALE_EXPERIMENTAL_FEATURE_SSH", "1")
user, err := app.CreateUser("user1")
namespace, err := app.CreateNamespace("user1")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("user1", "testmachine")
@@ -98,7 +98,7 @@ func (s *Suite) TestSshRules(c *check.C) {
DiscoKey: "faa",
Hostname: "testmachine",
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.1")},
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
HostInfo: HostInfo(hostInfo),
@@ -187,10 +187,10 @@ func (s *Suite) TestInvalidTagOwners(c *check.C) {
// match properly the IP's of the related hosts. The owner is valid and the tag is also valid.
// the tag is matched in the Sources section.
func (s *Suite) TestValidExpandTagOwnersInSources(c *check.C) {
user, err := app.CreateUser("user1")
namespace, err := app.CreateNamespace("user1")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("user1", "testmachine")
@@ -208,7 +208,7 @@ func (s *Suite) TestValidExpandTagOwnersInSources(c *check.C) {
DiscoKey: "faa",
Hostname: "testmachine",
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.1")},
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
HostInfo: HostInfo(hostInfo),
@@ -237,10 +237,10 @@ func (s *Suite) TestValidExpandTagOwnersInSources(c *check.C) {
// match properly the IP's of the related hosts. The owner is valid and the tag is also valid.
// the tag is matched in the Destinations section.
func (s *Suite) TestValidExpandTagOwnersInDestinations(c *check.C) {
user, err := app.CreateUser("user1")
namespace, err := app.CreateNamespace("user1")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("user1", "testmachine")
@@ -258,7 +258,7 @@ func (s *Suite) TestValidExpandTagOwnersInDestinations(c *check.C) {
DiscoKey: "faa",
Hostname: "testmachine",
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.1")},
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
HostInfo: HostInfo(hostInfo),
@@ -284,13 +284,13 @@ func (s *Suite) TestValidExpandTagOwnersInDestinations(c *check.C) {
}
// need a test with:
// tag on a host that isn't owned by a tag owners. So the user
// tag on a host that isn't owned by a tag owners. So the namespace
// of the host should be valid.
func (s *Suite) TestInvalidTagValidUser(c *check.C) {
user, err := app.CreateUser("user1")
func (s *Suite) TestInvalidTagValidNamespace(c *check.C) {
namespace, err := app.CreateNamespace("user1")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("user1", "testmachine")
@@ -308,7 +308,7 @@ func (s *Suite) TestInvalidTagValidUser(c *check.C) {
DiscoKey: "faa",
Hostname: "testmachine",
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.1")},
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
HostInfo: HostInfo(hostInfo),
@@ -333,13 +333,13 @@ func (s *Suite) TestInvalidTagValidUser(c *check.C) {
}
// tag on a host is owned by a tag owner, the tag is valid.
// an ACL rule is matching the tag to a user. It should not be valid since the
// an ACL rule is matching the tag to a namespace. It should not be valid since the
// host should be tied to the tag now.
func (s *Suite) TestValidTagInvalidUser(c *check.C) {
user, err := app.CreateUser("user1")
func (s *Suite) TestValidTagInvalidNamespace(c *check.C) {
namespace, err := app.CreateNamespace("user1")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("user1", "webserver")
@@ -357,7 +357,7 @@ func (s *Suite) TestValidTagInvalidUser(c *check.C) {
DiscoKey: "faa",
Hostname: "webserver",
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.1")},
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
HostInfo: HostInfo(hostInfo),
@@ -376,7 +376,7 @@ func (s *Suite) TestValidTagInvalidUser(c *check.C) {
DiscoKey: "faab",
Hostname: "user",
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.2")},
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
HostInfo: HostInfo(hostInfo2),
@@ -467,14 +467,14 @@ func (s *Suite) TestPortWildcardYAML(c *check.C) {
c.Assert(rules[0].SrcIPs[0], check.Equals, "*")
}
func (s *Suite) TestPortUser(c *check.C) {
user, err := app.CreateUser("testuser")
func (s *Suite) TestPortNamespace(c *check.C) {
namespace, err := app.CreateNamespace("testnamespace")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("testuser", "testmachine")
_, err = app.GetMachine("testnamespace", "testmachine")
c.Assert(err, check.NotNil)
ips, _ := app.getAvailableIPs()
machine := Machine{
@@ -483,7 +483,7 @@ func (s *Suite) TestPortUser(c *check.C) {
NodeKey: "bar",
DiscoKey: "faa",
Hostname: "testmachine",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: ips,
AuthKeyID: uint(pak.ID),
@@ -491,7 +491,7 @@ func (s *Suite) TestPortUser(c *check.C) {
app.db.Save(&machine)
err = app.LoadACLPolicy(
"./tests/acls/acl_policy_basic_user_as_user.hujson",
"./tests/acls/acl_policy_basic_namespace_as_user.hujson",
)
c.Assert(err, check.IsNil)
@@ -513,13 +513,13 @@ func (s *Suite) TestPortUser(c *check.C) {
}
func (s *Suite) TestPortGroup(c *check.C) {
user, err := app.CreateUser("testuser")
namespace, err := app.CreateNamespace("testnamespace")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("testuser", "testmachine")
_, err = app.GetMachine("testnamespace", "testmachine")
c.Assert(err, check.NotNil)
ips, _ := app.getAvailableIPs()
machine := Machine{
@@ -528,7 +528,7 @@ func (s *Suite) TestPortGroup(c *check.C) {
NodeKey: "bar",
DiscoKey: "faa",
Hostname: "testmachine",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: ips,
AuthKeyID: uint(pak.ID),
@@ -689,7 +689,7 @@ func Test_expandTagOwners(t *testing.T) {
wantErr: false,
},
{
name: "expand with user and group",
name: "expand with namespace and group",
args: args{
aclPolicy: ACLPolicy{
Groups: Groups{"group:foo": []string{"user1", "user2"}},
@@ -843,10 +843,10 @@ func Test_expandPorts(t *testing.T) {
}
}
func Test_listMachinesInUser(t *testing.T) {
func Test_listMachinesInNamespace(t *testing.T) {
type args struct {
machines []Machine
user string
machines []Machine
namespace string
}
tests := []struct {
name string
@@ -854,54 +854,54 @@ func Test_listMachinesInUser(t *testing.T) {
want []Machine
}{
{
name: "1 machine in user",
name: "1 machine in namespace",
args: args{
machines: []Machine{
{User: User{Name: "joe"}},
{Namespace: Namespace{Name: "joe"}},
},
user: "joe",
namespace: "joe",
},
want: []Machine{
{User: User{Name: "joe"}},
{Namespace: Namespace{Name: "joe"}},
},
},
{
name: "3 machines, 2 in user",
name: "3 machines, 2 in namespace",
args: args{
machines: []Machine{
{ID: 1, User: User{Name: "joe"}},
{ID: 2, User: User{Name: "marc"}},
{ID: 3, User: User{Name: "marc"}},
{ID: 1, Namespace: Namespace{Name: "joe"}},
{ID: 2, Namespace: Namespace{Name: "marc"}},
{ID: 3, Namespace: Namespace{Name: "marc"}},
},
user: "marc",
namespace: "marc",
},
want: []Machine{
{ID: 2, User: User{Name: "marc"}},
{ID: 3, User: User{Name: "marc"}},
{ID: 2, Namespace: Namespace{Name: "marc"}},
{ID: 3, Namespace: Namespace{Name: "marc"}},
},
},
{
name: "5 machines, 0 in user",
name: "5 machines, 0 in namespace",
args: args{
machines: []Machine{
{ID: 1, User: User{Name: "joe"}},
{ID: 2, User: User{Name: "marc"}},
{ID: 3, User: User{Name: "marc"}},
{ID: 4, User: User{Name: "marc"}},
{ID: 5, User: User{Name: "marc"}},
{ID: 1, Namespace: Namespace{Name: "joe"}},
{ID: 2, Namespace: Namespace{Name: "marc"}},
{ID: 3, Namespace: Namespace{Name: "marc"}},
{ID: 4, Namespace: Namespace{Name: "marc"}},
{ID: 5, Namespace: Namespace{Name: "marc"}},
},
user: "mickael",
namespace: "mickael",
},
want: []Machine{},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if got := filterMachinesByUser(test.args.machines, test.args.user); !reflect.DeepEqual(
if got := filterMachinesByNamespace(test.args.machines, test.args.namespace); !reflect.DeepEqual(
got,
test.want,
) {
t.Errorf("listMachinesInUser() = %v, want %v", got, test.want)
t.Errorf("listMachinesInNamespace() = %v, want %v", got, test.want)
}
})
}
@@ -947,25 +947,25 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
aclPolicy: ACLPolicy{
@@ -985,25 +985,25 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
aclPolicy: ACLPolicy{
@@ -1071,7 +1071,7 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1082,7 +1082,7 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1093,13 +1093,13 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
},
aclPolicy: ACLPolicy{
@@ -1119,25 +1119,25 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
aclPolicy: ACLPolicy{
@@ -1160,27 +1160,27 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
ForcedTags: []string{"tag:hr-webserver"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
ForcedTags: []string{"tag:hr-webserver"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
aclPolicy: ACLPolicy{},
@@ -1198,14 +1198,14 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
ForcedTags: []string{"tag:hr-webserver"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1216,13 +1216,13 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
aclPolicy: ACLPolicy{
@@ -1236,7 +1236,7 @@ func Test_expandAlias(t *testing.T) {
wantErr: false,
},
{
name: "list host in user without correctly tagged servers",
name: "list host in namespace without correctly tagged servers",
args: args{
alias: "joe",
machines: []Machine{
@@ -1244,7 +1244,7 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1255,7 +1255,7 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1266,13 +1266,13 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
},
aclPolicy: ACLPolicy{
@@ -1308,7 +1308,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
type args struct {
aclPolicy ACLPolicy
nodes []Machine
user string
namespace string
stripEmailDomain bool
}
tests := []struct {
@@ -1328,7 +1328,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1339,7 +1339,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1350,16 +1350,16 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
},
user: "joe",
namespace: "joe",
stripEmailDomain: true,
},
want: []Machine{
{
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.4")},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
},
},
@@ -1379,7 +1379,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1390,7 +1390,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1401,16 +1401,16 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
},
user: "joe",
namespace: "joe",
stripEmailDomain: true,
},
want: []Machine{
{
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.4")},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
},
},
@@ -1425,7 +1425,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1436,23 +1436,23 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
ForcedTags: []string{"tag:accountant-webserver"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
},
user: "joe",
namespace: "joe",
stripEmailDomain: true,
},
want: []Machine{
{
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.4")},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
},
},
@@ -1467,7 +1467,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "hr-web1",
@@ -1478,7 +1478,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "hr-web2",
@@ -1489,10 +1489,10 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
},
user: "joe",
namespace: "joe",
stripEmailDomain: true,
},
want: []Machine{
@@ -1500,7 +1500,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "hr-web1",
@@ -1511,7 +1511,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "hr-web2",
@@ -1522,7 +1522,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
},
},
@@ -1532,7 +1532,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
got := excludeCorrectlyTaggedNodes(
test.args.aclPolicy,
test.args.nodes,
test.args.user,
test.args.namespace,
test.args.stripEmailDomain,
)
if !reflect.DeepEqual(got, test.want) {

View File

@@ -34,7 +34,7 @@ type Groups map[string][]string
// Hosts are alias for IP addresses or subnets.
type Hosts map[string]netip.Prefix
// TagOwners specify what users (users?) are allow to use certain tags.
// TagOwners specify what users (namespaces?) are allow to use certain tags.
type TagOwners map[string][]string
// ACLTest is not implemented, but should be use to check if a certain rule is allowed.
@@ -44,7 +44,7 @@ type ACLTest struct {
Deny []string `json:"deny,omitempty" yaml:"deny,omitempty"`
}
// AutoApprovers specify which users (users?), groups or tags have their advertised routes
// AutoApprovers specify which users (namespaces?), groups or tags have their advertised routes
// or exit node status automatically enabled.
type AutoApprovers struct {
Routes map[string][]string `json:"routes" yaml:"routes"`
@@ -119,7 +119,7 @@ func (policy ACLPolicy) IsZero() bool {
return false
}
// Returns the list of autoApproving users, groups or tags for a given IPPrefix.
// Returns the list of autoApproving namespaces, groups or tags for a given IPPrefix.
func (autoApprovers *AutoApprovers) GetRouteApprovers(
prefix netip.Prefix,
) ([]string, error) {

2
api.go
View File

@@ -78,7 +78,7 @@ var registerWebAPITemplate = template.Must(
<p>
Run the command below in the headscale server to add this machine to your network:
</p>
<pre><code>headscale nodes register --user USERNAME --key {{.Key}}</code></pre>
<pre><code>headscale -n NAMESPACE nodes register --key {{.Key}}</code></pre>
</body>
</html>
`))

View File

@@ -29,7 +29,7 @@ type APIKey struct {
LastSeen *time.Time
}
// CreateAPIKey creates a new ApiKey in a user, and returns it.
// CreateAPIKey creates a new ApiKey in a namespace, and returns it.
func (h *Headscale) CreateAPIKey(
expiration *time.Time,
) (string, *APIKey, error) {
@@ -64,7 +64,7 @@ func (h *Headscale) CreateAPIKey(
return keyStr, &key, nil
}
// ListAPIKeys returns the list of ApiKeys for a user.
// ListAPIKeys returns the list of ApiKeys for a namespace.
func (h *Headscale) ListAPIKeys() ([]APIKey, error) {
keys := []APIKey{}
if err := h.db.Find(&keys).Error; err != nil {

95
app.go
View File

@@ -162,7 +162,6 @@ func NewHeadscale(cfg *Config) (*Headscale, error) {
aclRules: tailcfg.FilterAllowAll, // default allowall
registrationCache: registrationCache,
pollNetMapStreamWG: sync.WaitGroup{},
lastStateChange: xsync.NewMapOf[time.Time](),
}
err = app.initDB()
@@ -218,15 +217,6 @@ func (h *Headscale) expireEphemeralNodes(milliSeconds int64) {
}
}
// expireExpiredMachines expires machines that have an explicit expiry set
// after that expiry time has passed.
func (h *Headscale) expireExpiredMachines(milliSeconds int64) {
ticker := time.NewTicker(time.Duration(milliSeconds) * time.Millisecond)
for range ticker.C {
h.expireExpiredMachinesWorker()
}
}
func (h *Headscale) failoverSubnetRoutes(milliSeconds int64) {
ticker := time.NewTicker(time.Duration(milliSeconds) * time.Millisecond)
for range ticker.C {
@@ -238,27 +228,28 @@ func (h *Headscale) failoverSubnetRoutes(milliSeconds int64) {
}
func (h *Headscale) expireEphemeralNodesWorker() {
users, err := h.ListUsers()
namespaces, err := h.ListNamespaces()
if err != nil {
log.Error().Err(err).Msg("Error listing users")
log.Error().Err(err).Msg("Error listing namespaces")
return
}
for _, user := range users {
machines, err := h.ListMachinesByUser(user.Name)
for _, namespace := range namespaces {
machines, err := h.ListMachinesInNamespace(namespace.Name)
if err != nil {
log.Error().
Err(err).
Str("user", user.Name).
Msg("Error listing machines in user")
Str("namespace", namespace.Name).
Msg("Error listing machines in namespace")
return
}
expiredFound := false
for _, machine := range machines {
if machine.isEphemeral() && machine.LastSeen != nil &&
if machine.AuthKey != nil && machine.LastSeen != nil &&
machine.AuthKey.Ephemeral &&
time.Now().
After(machine.LastSeen.Add(h.cfg.EphemeralNodeInactivityTimeout)) {
expiredFound = true
@@ -282,53 +273,6 @@ func (h *Headscale) expireEphemeralNodesWorker() {
}
}
func (h *Headscale) expireExpiredMachinesWorker() {
users, err := h.ListUsers()
if err != nil {
log.Error().Err(err).Msg("Error listing users")
return
}
for _, user := range users {
machines, err := h.ListMachinesByUser(user.Name)
if err != nil {
log.Error().
Err(err).
Str("user", user.Name).
Msg("Error listing machines in user")
return
}
expiredFound := false
for index, machine := range machines {
if machine.isExpired() &&
machine.Expiry.After(h.getLastStateChange(user)) {
expiredFound = true
err := h.ExpireMachine(&machines[index])
if err != nil {
log.Error().
Err(err).
Str("machine", machine.Hostname).
Str("name", machine.GivenName).
Msg("🤮 Cannot expire machine")
} else {
log.Info().
Str("machine", machine.Hostname).
Str("name", machine.GivenName).
Msg("Machine successfully expired")
}
}
}
if expiredFound {
h.setLastStateChangeToNow()
}
}
}
func (h *Headscale) grpcAuthenticationInterceptor(ctx context.Context,
req interface{},
info *grpc.UnaryServerInfo,
@@ -550,7 +494,6 @@ func (h *Headscale) Serve() error {
}
go h.expireEphemeralNodes(updateInterval)
go h.expireExpiredMachines(updateInterval)
go h.failoverSubnetRoutes(updateInterval)
@@ -908,31 +851,31 @@ func (h *Headscale) setLastStateChangeToNow() {
now := time.Now().UTC()
users, err := h.ListUsers()
namespaces, err := h.ListNamespaces()
if err != nil {
log.Error().
Caller().
Err(err).
Msg("failed to fetch all users, failing to update last changed state.")
Msg("failed to fetch all namespaces, failing to update last changed state.")
}
for _, user := range users {
lastStateUpdate.WithLabelValues(user.Name, "headscale").Set(float64(now.Unix()))
for _, namespace := range namespaces {
lastStateUpdate.WithLabelValues(namespace.Name, "headscale").Set(float64(now.Unix()))
if h.lastStateChange == nil {
h.lastStateChange = xsync.NewMapOf[time.Time]()
}
h.lastStateChange.Store(user.Name, now)
h.lastStateChange.Store(namespace.Name, now)
}
}
func (h *Headscale) getLastStateChange(users ...User) time.Time {
func (h *Headscale) getLastStateChange(namespaces ...Namespace) time.Time {
times := []time.Time{}
// getLastStateChange takes a list of users as a "filter", if no users
// are past, then use the entier list of users and look for the last update
if len(users) > 0 {
for _, user := range users {
if lastChange, ok := h.lastStateChange.Load(user.Name); ok {
// getLastStateChange takes a list of namespaces as a "filter", if no namespaces
// are past, then use the entier list of namespaces and look for the last update
if len(namespaces) > 0 {
for _, namespace := range namespaces {
if lastChange, ok := h.lastStateChange.Load(namespace.Name); ok {
times = append(times, lastChange)
}
}

View File

@@ -1,114 +0,0 @@
package main
//go:generate go run ./main.go
import (
"bytes"
"fmt"
"log"
"os"
"text/template"
)
var (
jobFileNameTemplate = `test-integration-v2-%s.yaml`
jobTemplate = template.Must(template.New("jobTemplate").Parse(`
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
name: Integration Test v2 - {{.Name}}
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v34
with:
files: |
*.nix
go.*
**/*.go
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
run: |
nix develop --command -- docker run \
--tty --rm \
--volume ~/.cache/hs-integration-go:/go \
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^{{.Name}}$"
`))
)
const workflowFilePerm = 0o600
func main() {
type testConfig struct {
Name string
}
// TODO(kradalby): automatic fetch tests at runtime
tests := []string{
"TestAuthKeyLogoutAndRelogin",
"TestAuthWebFlowAuthenticationPingAll",
"TestAuthWebFlowLogoutAndRelogin",
"TestCreateTailscale",
"TestEnablingRoutes",
"TestHeadscale",
"TestUserCommand",
"TestOIDCAuthenticationPingAll",
"TestOIDCExpireNodes",
"TestPingAllByHostname",
"TestPingAllByIP",
"TestPreAuthKeyCommand",
"TestPreAuthKeyCommandReusableEphemeral",
"TestPreAuthKeyCommandWithoutExpiry",
"TestResolveMagicDNS",
"TestSSHIsBlockedInACL",
"TestSSHMultipleUsersAllToAll",
"TestSSHNoSSHConfigured",
"TestSSHOneUserAllToAll",
"TestSSUserOnlyIsolation",
"TestTaildrop",
"TestTailscaleNodesJoiningHeadcale",
}
for _, test := range tests {
var content bytes.Buffer
if err := jobTemplate.Execute(&content, testConfig{
Name: test,
}); err != nil {
log.Fatalf("failed to render template: %s", err)
}
path := "../../.github/workflows/" + fmt.Sprintf(jobFileNameTemplate, test)
err := os.WriteFile(path, content.Bytes(), workflowFilePerm)
if err != nil {
log.Fatalf("failed to write github job: %s", err)
}
}
}

View File

@@ -27,14 +27,8 @@ func init() {
if err != nil {
log.Fatal().Err(err).Msg("")
}
createNodeCmd.Flags().StringP("user", "u", "", "User")
createNodeCmd.Flags().StringP("namespace", "n", "", "User")
createNodeNamespaceFlag := createNodeCmd.Flags().Lookup("namespace")
createNodeNamespaceFlag.Deprecated = deprecateNamespaceMessage
createNodeNamespaceFlag.Hidden = true
err = createNodeCmd.MarkFlagRequired("user")
createNodeCmd.Flags().StringP("namespace", "n", "", "Namespace")
err = createNodeCmd.MarkFlagRequired("namespace")
if err != nil {
log.Fatal().Err(err).Msg("")
}
@@ -61,9 +55,9 @@ var createNodeCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
user, err := cmd.Flags().GetString("user")
namespace, err := cmd.Flags().GetString("namespace")
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error getting user: %s", err), output)
ErrorOutput(err, fmt.Sprintf("Error getting namespace: %s", err), output)
return
}
@@ -116,10 +110,10 @@ var createNodeCmd = &cobra.Command{
}
request := &v1.DebugCreateMachineRequest{
Key: machineKey,
Name: name,
User: user,
Routes: routes,
Key: machineKey,
Name: name,
Namespace: namespace,
Routes: routes,
}
response, err := client.DebugCreateMachine(ctx, request)

View File

@@ -16,11 +16,10 @@ const (
errMockOidcClientIDNotDefined = Error("MOCKOIDC_CLIENT_ID not defined")
errMockOidcClientSecretNotDefined = Error("MOCKOIDC_CLIENT_SECRET not defined")
errMockOidcPortNotDefined = Error("MOCKOIDC_PORT not defined")
accessTTL = 10 * time.Minute
refreshTTL = 60 * time.Minute
)
var accessTTL = 2 * time.Minute
func init() {
rootCmd.AddCommand(mockOidcCmd)
}
@@ -55,16 +54,6 @@ func mockOIDC() error {
if portStr == "" {
return errMockOidcPortNotDefined
}
accessTTLOverride := os.Getenv("MOCKOIDC_ACCESS_TTL")
if accessTTLOverride != "" {
newTTL, err := time.ParseDuration(accessTTLOverride)
if err != nil {
return err
}
accessTTL = newTTL
}
log.Info().Msgf("Access token TTL: %s", accessTTL)
port, err := strconv.Atoi(portStr)
if err != nil {

View File

@@ -13,26 +13,26 @@ import (
)
func init() {
rootCmd.AddCommand(userCmd)
userCmd.AddCommand(createUserCmd)
userCmd.AddCommand(listUsersCmd)
userCmd.AddCommand(destroyUserCmd)
userCmd.AddCommand(renameUserCmd)
rootCmd.AddCommand(namespaceCmd)
namespaceCmd.AddCommand(createNamespaceCmd)
namespaceCmd.AddCommand(listNamespacesCmd)
namespaceCmd.AddCommand(destroyNamespaceCmd)
namespaceCmd.AddCommand(renameNamespaceCmd)
}
const (
errMissingParameter = headscale.Error("missing parameters")
)
var userCmd = &cobra.Command{
Use: "users",
Short: "Manage the users of Headscale",
Aliases: []string{"user", "namespace", "namespaces", "ns"},
var namespaceCmd = &cobra.Command{
Use: "namespaces",
Short: "Manage the namespaces of Headscale",
Aliases: []string{"namespace", "ns", "user", "users"},
}
var createUserCmd = &cobra.Command{
var createNamespaceCmd = &cobra.Command{
Use: "create NAME",
Short: "Creates a new user",
Short: "Creates a new namespace",
Aliases: []string{"c", "new"},
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
@@ -44,7 +44,7 @@ var createUserCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
userName := args[0]
namespaceName := args[0]
ctx, client, conn, cancel := getHeadscaleCLIClient()
defer cancel()
@@ -52,15 +52,15 @@ var createUserCmd = &cobra.Command{
log.Trace().Interface("client", client).Msg("Obtained gRPC client")
request := &v1.CreateUserRequest{Name: userName}
request := &v1.CreateNamespaceRequest{Name: namespaceName}
log.Trace().Interface("request", request).Msg("Sending CreateUser request")
response, err := client.CreateUser(ctx, request)
log.Trace().Interface("request", request).Msg("Sending CreateNamespace request")
response, err := client.CreateNamespace(ctx, request)
if err != nil {
ErrorOutput(
err,
fmt.Sprintf(
"Cannot create user: %s",
"Cannot create namespace: %s",
status.Convert(err).Message(),
),
output,
@@ -69,13 +69,13 @@ var createUserCmd = &cobra.Command{
return
}
SuccessOutput(response.User, "User created", output)
SuccessOutput(response.Namespace, "Namespace created", output)
},
}
var destroyUserCmd = &cobra.Command{
var destroyNamespaceCmd = &cobra.Command{
Use: "destroy NAME",
Short: "Destroys a user",
Short: "Destroys a namespace",
Aliases: []string{"delete"},
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
@@ -87,17 +87,17 @@ var destroyUserCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
userName := args[0]
namespaceName := args[0]
request := &v1.GetUserRequest{
Name: userName,
request := &v1.GetNamespaceRequest{
Name: namespaceName,
}
ctx, client, conn, cancel := getHeadscaleCLIClient()
defer cancel()
defer conn.Close()
_, err := client.GetUser(ctx, request)
_, err := client.GetNamespace(ctx, request)
if err != nil {
ErrorOutput(
err,
@@ -113,8 +113,8 @@ var destroyUserCmd = &cobra.Command{
if !force {
prompt := &survey.Confirm{
Message: fmt.Sprintf(
"Do you want to remove the user '%s' and any associated preauthkeys?",
userName,
"Do you want to remove the namespace '%s' and any associated preauthkeys?",
namespaceName,
),
}
err := survey.AskOne(prompt, &confirm)
@@ -124,14 +124,14 @@ var destroyUserCmd = &cobra.Command{
}
if confirm || force {
request := &v1.DeleteUserRequest{Name: userName}
request := &v1.DeleteNamespaceRequest{Name: namespaceName}
response, err := client.DeleteUser(ctx, request)
response, err := client.DeleteNamespace(ctx, request)
if err != nil {
ErrorOutput(
err,
fmt.Sprintf(
"Cannot destroy user: %s",
"Cannot destroy namespace: %s",
status.Convert(err).Message(),
),
output,
@@ -139,16 +139,16 @@ var destroyUserCmd = &cobra.Command{
return
}
SuccessOutput(response, "User destroyed", output)
SuccessOutput(response, "Namespace destroyed", output)
} else {
SuccessOutput(map[string]string{"Result": "User not destroyed"}, "User not destroyed", output)
SuccessOutput(map[string]string{"Result": "Namespace not destroyed"}, "Namespace not destroyed", output)
}
},
}
var listUsersCmd = &cobra.Command{
var listNamespacesCmd = &cobra.Command{
Use: "list",
Short: "List all the users",
Short: "List all the namespaces",
Aliases: []string{"ls", "show"},
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
@@ -157,13 +157,13 @@ var listUsersCmd = &cobra.Command{
defer cancel()
defer conn.Close()
request := &v1.ListUsersRequest{}
request := &v1.ListNamespacesRequest{}
response, err := client.ListUsers(ctx, request)
response, err := client.ListNamespaces(ctx, request)
if err != nil {
ErrorOutput(
err,
fmt.Sprintf("Cannot get users: %s", status.Convert(err).Message()),
fmt.Sprintf("Cannot get namespaces: %s", status.Convert(err).Message()),
output,
)
@@ -171,19 +171,19 @@ var listUsersCmd = &cobra.Command{
}
if output != "" {
SuccessOutput(response.Users, "", output)
SuccessOutput(response.Namespaces, "", output)
return
}
tableData := pterm.TableData{{"ID", "Name", "Created"}}
for _, user := range response.GetUsers() {
for _, namespace := range response.GetNamespaces() {
tableData = append(
tableData,
[]string{
user.GetId(),
user.GetName(),
user.GetCreatedAt().AsTime().Format("2006-01-02 15:04:05"),
namespace.GetId(),
namespace.GetName(),
namespace.GetCreatedAt().AsTime().Format("2006-01-02 15:04:05"),
},
)
}
@@ -200,9 +200,9 @@ var listUsersCmd = &cobra.Command{
},
}
var renameUserCmd = &cobra.Command{
var renameNamespaceCmd = &cobra.Command{
Use: "rename OLD_NAME NEW_NAME",
Short: "Renames a user",
Short: "Renames a namespace",
Aliases: []string{"mv"},
Args: func(cmd *cobra.Command, args []string) error {
expectedArguments := 2
@@ -219,17 +219,17 @@ var renameUserCmd = &cobra.Command{
defer cancel()
defer conn.Close()
request := &v1.RenameUserRequest{
request := &v1.RenameNamespaceRequest{
OldName: args[0],
NewName: args[1],
}
response, err := client.RenameUser(ctx, request)
response, err := client.RenameNamespace(ctx, request)
if err != nil {
ErrorOutput(
err,
fmt.Sprintf(
"Cannot rename user: %s",
"Cannot rename namespace: %s",
status.Convert(err).Message(),
),
output,
@@ -238,6 +238,6 @@ var renameUserCmd = &cobra.Command{
return
}
SuccessOutput(response.User, "User renamed", output)
SuccessOutput(response.Namespace, "Namespace renamed", output)
},
}

View File

@@ -19,24 +19,12 @@ import (
func init() {
rootCmd.AddCommand(nodeCmd)
listNodesCmd.Flags().StringP("user", "u", "", "Filter by user")
listNodesCmd.Flags().StringP("namespace", "n", "", "Filter by namespace")
listNodesCmd.Flags().BoolP("tags", "t", false, "Show tags")
listNodesCmd.Flags().StringP("namespace", "n", "", "User")
listNodesNamespaceFlag := listNodesCmd.Flags().Lookup("namespace")
listNodesNamespaceFlag.Deprecated = deprecateNamespaceMessage
listNodesNamespaceFlag.Hidden = true
nodeCmd.AddCommand(listNodesCmd)
registerNodeCmd.Flags().StringP("user", "u", "", "User")
registerNodeCmd.Flags().StringP("namespace", "n", "", "User")
registerNodeNamespaceFlag := registerNodeCmd.Flags().Lookup("namespace")
registerNodeNamespaceFlag.Deprecated = deprecateNamespaceMessage
registerNodeNamespaceFlag.Hidden = true
err := registerNodeCmd.MarkFlagRequired("user")
registerNodeCmd.Flags().StringP("namespace", "n", "", "Namespace")
err := registerNodeCmd.MarkFlagRequired("namespace")
if err != nil {
log.Fatalf(err.Error())
}
@@ -75,14 +63,9 @@ func init() {
log.Fatalf(err.Error())
}
moveNodeCmd.Flags().StringP("user", "u", "", "New user")
moveNodeCmd.Flags().StringP("namespace", "n", "", "New namespace")
moveNodeCmd.Flags().StringP("namespace", "n", "", "User")
moveNodeNamespaceFlag := moveNodeCmd.Flags().Lookup("namespace")
moveNodeNamespaceFlag.Deprecated = deprecateNamespaceMessage
moveNodeNamespaceFlag.Hidden = true
err = moveNodeCmd.MarkFlagRequired("user")
err = moveNodeCmd.MarkFlagRequired("namespace")
if err != nil {
log.Fatalf(err.Error())
}
@@ -110,9 +93,9 @@ var registerNodeCmd = &cobra.Command{
Short: "Registers a machine to your network",
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
user, err := cmd.Flags().GetString("user")
namespace, err := cmd.Flags().GetString("namespace")
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error getting user: %s", err), output)
ErrorOutput(err, fmt.Sprintf("Error getting namespace: %s", err), output)
return
}
@@ -133,8 +116,8 @@ var registerNodeCmd = &cobra.Command{
}
request := &v1.RegisterMachineRequest{
Key: machineKey,
User: user,
Key: machineKey,
Namespace: namespace,
}
response, err := client.RegisterMachine(ctx, request)
@@ -163,9 +146,9 @@ var listNodesCmd = &cobra.Command{
Aliases: []string{"ls", "show"},
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
user, err := cmd.Flags().GetString("user")
namespace, err := cmd.Flags().GetString("namespace")
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error getting user: %s", err), output)
ErrorOutput(err, fmt.Sprintf("Error getting namespace: %s", err), output)
return
}
@@ -181,7 +164,7 @@ var listNodesCmd = &cobra.Command{
defer conn.Close()
request := &v1.ListMachinesRequest{
User: user,
Namespace: namespace,
}
response, err := client.ListMachines(ctx, request)
@@ -201,7 +184,7 @@ var listNodesCmd = &cobra.Command{
return
}
tableData, err := nodesToPtables(user, showTags, response.Machines)
tableData, err := nodesToPtables(namespace, showTags, response.Machines)
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error converting to table: %s", err), output)
@@ -405,7 +388,7 @@ var deleteNodeCmd = &cobra.Command{
var moveNodeCmd = &cobra.Command{
Use: "move",
Short: "Move node to another user",
Short: "Move node to another namespace",
Aliases: []string{"mv"},
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
@@ -421,11 +404,11 @@ var moveNodeCmd = &cobra.Command{
return
}
user, err := cmd.Flags().GetString("user")
namespace, err := cmd.Flags().GetString("namespace")
if err != nil {
ErrorOutput(
err,
fmt.Sprintf("Error getting user: %s", err),
fmt.Sprintf("Error getting namespace: %s", err),
output,
)
@@ -456,7 +439,7 @@ var moveNodeCmd = &cobra.Command{
moveRequest := &v1.MoveMachineRequest{
MachineId: identifier,
User: user,
Namespace: namespace,
}
moveResponse, err := client.MoveMachine(ctx, moveRequest)
@@ -473,12 +456,12 @@ var moveNodeCmd = &cobra.Command{
return
}
SuccessOutput(moveResponse.Machine, "Node moved to another user", output)
SuccessOutput(moveResponse.Machine, "Node moved to another namespace", output)
},
}
func nodesToPtables(
currentUser string,
currentNamespace string,
showTags bool,
machines []*v1.Machine,
) (pterm.TableData, error) {
@@ -488,11 +471,10 @@ func nodesToPtables(
"Name",
"MachineKey",
"NodeKey",
"User",
"Namespace",
"IP addresses",
"Ephemeral",
"Last seen",
"Expiration",
"Online",
"Expired",
}
@@ -519,12 +501,8 @@ func nodesToPtables(
}
var expiry time.Time
var expiryTime string
if machine.Expiry != nil {
expiry = machine.Expiry.AsTime()
expiryTime = expiry.Format("2006-01-02 15:04:05")
} else {
expiryTime = "N/A"
}
var machineKey key.MachinePublic
@@ -577,12 +555,12 @@ func nodesToPtables(
}
validTags = strings.TrimLeft(validTags, ",")
var user string
if currentUser == "" || (currentUser == machine.User.Name) {
user = pterm.LightMagenta(machine.User.Name)
var namespace string
if currentNamespace == "" || (currentNamespace == machine.Namespace.Name) {
namespace = pterm.LightMagenta(machine.Namespace.Name)
} else {
// Shared into this user
user = pterm.LightYellow(machine.User.Name)
// Shared into this namespace
namespace = pterm.LightYellow(machine.Namespace.Name)
}
var IPV4Address string
@@ -601,11 +579,10 @@ func nodesToPtables(
machine.GetGivenName(),
machineKey.ShortString(),
nodeKey.ShortString(),
user,
namespace,
strings.Join([]string{IPV4Address, IPV6Address}, ", "),
strconv.FormatBool(ephemeral),
lastSeenTime,
expiryTime,
online,
expired,
}

View File

@@ -20,14 +20,8 @@ const (
func init() {
rootCmd.AddCommand(preauthkeysCmd)
preauthkeysCmd.PersistentFlags().StringP("user", "u", "", "User")
preauthkeysCmd.PersistentFlags().StringP("namespace", "n", "", "User")
pakNamespaceFlag := preauthkeysCmd.PersistentFlags().Lookup("namespace")
pakNamespaceFlag.Deprecated = deprecateNamespaceMessage
pakNamespaceFlag.Hidden = true
err := preauthkeysCmd.MarkPersistentFlagRequired("user")
preauthkeysCmd.PersistentFlags().StringP("namespace", "n", "", "Namespace")
err := preauthkeysCmd.MarkPersistentFlagRequired("namespace")
if err != nil {
log.Fatal().Err(err).Msg("")
}
@@ -52,14 +46,14 @@ var preauthkeysCmd = &cobra.Command{
var listPreAuthKeys = &cobra.Command{
Use: "list",
Short: "List the preauthkeys for this user",
Short: "List the preauthkeys for this namespace",
Aliases: []string{"ls", "show"},
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
user, err := cmd.Flags().GetString("user")
namespace, err := cmd.Flags().GetString("namespace")
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error getting user: %s", err), output)
ErrorOutput(err, fmt.Sprintf("Error getting namespace: %s", err), output)
return
}
@@ -69,7 +63,7 @@ var listPreAuthKeys = &cobra.Command{
defer conn.Close()
request := &v1.ListPreAuthKeysRequest{
User: user,
Namespace: namespace,
}
response, err := client.ListPreAuthKeys(ctx, request)
@@ -149,14 +143,14 @@ var listPreAuthKeys = &cobra.Command{
var createPreAuthKeyCmd = &cobra.Command{
Use: "create",
Short: "Creates a new preauthkey in the specified user",
Short: "Creates a new preauthkey in the specified namespace",
Aliases: []string{"c", "new"},
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
user, err := cmd.Flags().GetString("user")
namespace, err := cmd.Flags().GetString("namespace")
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error getting user: %s", err), output)
ErrorOutput(err, fmt.Sprintf("Error getting namespace: %s", err), output)
return
}
@@ -168,11 +162,11 @@ var createPreAuthKeyCmd = &cobra.Command{
log.Trace().
Bool("reusable", reusable).
Bool("ephemeral", ephemeral).
Str("user", user).
Str("namespace", namespace).
Msg("Preparing to create preauthkey")
request := &v1.CreatePreAuthKeyRequest{
User: user,
Namespace: namespace,
Reusable: reusable,
Ephemeral: ephemeral,
AclTags: tags,
@@ -231,9 +225,9 @@ var expirePreAuthKeyCmd = &cobra.Command{
},
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
user, err := cmd.Flags().GetString("user")
namespace, err := cmd.Flags().GetString("namespace")
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error getting user: %s", err), output)
ErrorOutput(err, fmt.Sprintf("Error getting namespace: %s", err), output)
return
}
@@ -243,8 +237,8 @@ var expirePreAuthKeyCmd = &cobra.Command{
defer conn.Close()
request := &v1.ExpirePreAuthKeyRequest{
User: user,
Key: args[0],
Namespace: namespace,
Key: args[0],
}
response, err := client.ExpirePreAuthKey(ctx, request)

View File

@@ -12,15 +12,10 @@ import (
"github.com/tcnksm/go-latest"
)
const (
deprecateNamespaceMessage = "use --user"
)
var cfgFile string = ""
func init() {
if len(os.Args) > 1 &&
(os.Args[1] == "version" || os.Args[1] == "mockoidc" || os.Args[1] == "completion") {
if len(os.Args) > 1 && (os.Args[1] == "version" || os.Args[1] == "mockoidc" || os.Args[1] == "completion") {
return
}

View File

@@ -63,11 +63,6 @@ noise:
# List of IP prefixes to allocate tailaddresses from.
# Each prefix consists of either an IPv4 or IPv6 address,
# and the associated prefix length, delimited by a slash.
# While this looks like it can take arbitrary values, it
# needs to be within IP ranges supported by the Tailscale
# client.
# IPv6: https://github.com/tailscale/tailscale/blob/22ebb25e833264f58d7c3f534a8b166894a89536/net/tsaddr/tsaddr.go#LL81C52-L81C71
# IPv4: https://github.com/tailscale/tailscale/blob/22ebb25e833264f58d7c3f534a8b166894a89536/net/tsaddr/tsaddr.go#L33
ip_prefixes:
- fd7a:115c:a1e0::/48
- 100.64.0.0/10
@@ -240,17 +235,6 @@ dns_config:
# Search domains to inject.
domains: []
# Extra DNS records
# so far only A-records are supported (on the tailscale side)
# See https://github.com/juanfont/headscale/blob/main/docs/dns-records.md#Limitations
# extra_records:
# - name: "grafana.myvpn.example.com"
# type: "A"
# value: "100.64.0.3"
#
# # you can also put it in one line
# - { name: "prometheus.myvpn.example.com", type: "A", value: "100.64.0.3" }
# Whether to use [MagicDNS](https://tailscale.com/kb/1081/magicdns/).
# Only works if there is at least a nameserver defined.
magic_dns: true
@@ -258,7 +242,7 @@ dns_config:
# Defines the base domain to create the hostnames for MagicDNS.
# `base_domain` must be a FQDNs, without the trailing dot.
# The FQDN of the hosts will be
# `hostname.user.base_domain` (e.g., _myhost.myuser.example.com_).
# `hostname.namespace.base_domain` (e.g., _myhost.mynamespace.example.com_).
base_domain: example.com
# Unix socket used for the CLI to connect without authentication
@@ -276,11 +260,6 @@ unix_socket_permission: "0770"
# issuer: "https://your-oidc.issuer.com/path"
# client_id: "your-oidc-client-id"
# client_secret: "your-oidc-client-secret"
# # Alternatively, set `client_secret_path` to read the secret from the file.
# # It resolves environment variables, making integration to systemd's
# # `LoadCredential` straightforward:
# client_secret_path: "${CREDENTIALS_DIRECTORY}/oidc_client_secret"
# # client_secret and client_secret_path are mutually exclusive.
#
# Customize the scopes used in the OIDC flow, defaults to "openid", "profile" and "email" and add custom query
# parameters to the Authorize Endpoint request. Scopes default to "openid", "profile" and "email".
@@ -301,9 +280,9 @@ unix_socket_permission: "0770"
# - alice@example.com
#
# If `strip_email_domain` is set to `true`, the domain part of the username email address will be removed.
# This will transform `first-name.last-name@example.com` to the user `first-name.last-name`
# This will transform `first-name.last-name@example.com` to the namespace `first-name.last-name`
# If `strip_email_domain` is set to `false` the domain part will NOT be removed resulting to the following
# user: `first-name.last-name.example.com`
# namespace: `first-name.last-name.example.com`
#
# strip_email_domain: true

View File

@@ -6,7 +6,6 @@ import (
"io/fs"
"net/netip"
"net/url"
"os"
"strings"
"time"
@@ -27,8 +26,6 @@ const (
TextLogFormat = "text"
)
var errOidcMutuallyExclusive = errors.New("oidc_client_secret and oidc_client_secret_path are mutually exclusive")
// Config contains the initial Headscale configuration.
type Config struct {
ServerURL string
@@ -411,7 +408,7 @@ func GetDNSConfig() (*tailcfg.DNSConfig, string) {
}
if viper.IsSet("dns_config.restricted_nameservers") {
if len(dnsConfig.Resolvers) > 0 {
if len(dnsConfig.Nameservers) > 0 {
dnsConfig.Routes = make(map[string][]*dnstype.Resolver)
restrictedDNS := viper.GetStringMapStringSlice(
"dns_config.restricted_nameservers",
@@ -443,7 +440,7 @@ func GetDNSConfig() (*tailcfg.DNSConfig, string) {
if viper.IsSet("dns_config.domains") {
domains := viper.GetStringSlice("dns_config.domains")
if len(dnsConfig.Resolvers) > 0 {
if len(dnsConfig.Nameservers) > 0 {
dnsConfig.Domains = domains
} else if domains != nil {
log.Warn().
@@ -451,20 +448,6 @@ func GetDNSConfig() (*tailcfg.DNSConfig, string) {
}
}
if viper.IsSet("dns_config.extra_records") {
var extraRecords []tailcfg.DNSRecord
err := viper.UnmarshalKey("dns_config.extra_records", &extraRecords)
if err != nil {
log.Error().
Str("func", "getDNSConfig").
Err(err).
Msgf("Could not parse dns_config.extra_records")
}
dnsConfig.ExtraRecords = extraRecords
}
if viper.IsSet("dns_config.magic_dns") {
dnsConfig.Proxied = viper.GetBool("dns_config.magic_dns")
}
@@ -531,19 +514,6 @@ func GetHeadscaleConfig() (*Config, error) {
Msgf("'ip_prefixes' not configured, falling back to default: %v", prefixes)
}
oidcClientSecret := viper.GetString("oidc.client_secret")
oidcClientSecretPath := viper.GetString("oidc.client_secret_path")
if oidcClientSecretPath != "" && oidcClientSecret != "" {
return nil, errOidcMutuallyExclusive
}
if oidcClientSecretPath != "" {
secretBytes, err := os.ReadFile(os.ExpandEnv(oidcClientSecretPath))
if err != nil {
return nil, err
}
oidcClientSecret = string(secretBytes)
}
return &Config{
ServerURL: viper.GetString("server_url"),
Addr: viper.GetString("listen_addr"),
@@ -596,7 +566,7 @@ func GetHeadscaleConfig() (*Config, error) {
),
Issuer: viper.GetString("oidc.issuer"),
ClientID: viper.GetString("oidc.client_id"),
ClientSecret: oidcClientSecret,
ClientSecret: viper.GetString("oidc.client_secret"),
Scope: viper.GetStringSlice("oidc.scope"),
ExtraParams: viper.GetStringMapString("oidc.extra_params"),
AllowedDomains: viper.GetStringSlice("oidc.allowed_domains"),

20
db.go
View File

@@ -41,16 +41,6 @@ func (h *Headscale) initDB() error {
db.Exec(`create extension if not exists "uuid-ossp";`)
}
_ = db.Migrator().RenameTable("namespaces", "users")
err = db.AutoMigrate(&User{})
if err != nil {
return err
}
_ = db.Migrator().RenameColumn(&Machine{}, "namespace_id", "user_id")
_ = db.Migrator().RenameColumn(&PreAuthKey{}, "namespace_id", "user_id")
_ = db.Migrator().RenameColumn(&Machine{}, "ip_address", "ip_addresses")
_ = db.Migrator().RenameColumn(&Machine{}, "name", "hostname")
@@ -120,10 +110,7 @@ func (h *Headscale) initDB() error {
continue
}
err = db.Preload("Machine").
Where("machine_id = ? AND prefix = ?", machine.ID, IPPrefix(prefix)).
First(&Route{}).
Error
err = db.Preload("Machine").Where("machine_id = ? AND prefix = ?", machine.ID, IPPrefix(prefix)).First(&Route{}).Error
if err == nil {
log.Info().
Str("enabled_route", prefix.String()).
@@ -197,6 +184,11 @@ func (h *Headscale) initDB() error {
return err
}
err = db.AutoMigrate(&Namespace{})
if err != nil {
return err
}
err = db.AutoMigrate(&PreAuthKey{})
if err != nil {
return err

14
dns.go
View File

@@ -190,23 +190,23 @@ func getMapResponseDNSConfig(
) *tailcfg.DNSConfig {
var dnsConfig *tailcfg.DNSConfig = dnsConfigOrig.Clone()
if dnsConfigOrig != nil && dnsConfigOrig.Proxied { // if MagicDNS is enabled
// Only inject the Search Domain of the current user - shared nodes should use their full FQDN
// Only inject the Search Domain of the current namespace - shared nodes should use their full FQDN
dnsConfig.Domains = append(
dnsConfig.Domains,
fmt.Sprintf(
"%s.%s",
machine.User.Name,
machine.Namespace.Name,
baseDomain,
),
)
userSet := mapset.NewSet[User]()
userSet.Add(machine.User)
namespaceSet := mapset.NewSet[Namespace]()
namespaceSet.Add(machine.Namespace)
for _, p := range peers {
userSet.Add(p.User)
namespaceSet.Add(p.Namespace)
}
for _, user := range userSet.ToSlice() {
dnsRoute := fmt.Sprintf("%v.%v", user.Name, baseDomain)
for _, namespace := range namespaceSet.ToSlice() {
dnsRoute := fmt.Sprintf("%v.%v", namespace.Name, baseDomain)
dnsConfig.Routes[dnsRoute] = nil
}
} else {

View File

@@ -112,17 +112,17 @@ func (s *Suite) TestMagicDNSRootDomainsIPv6SingleMultiple(c *check.C) {
}
func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
userShared1, err := app.CreateUser("shared1")
namespaceShared1, err := app.CreateNamespace("shared1")
c.Assert(err, check.IsNil)
userShared2, err := app.CreateUser("shared2")
namespaceShared2, err := app.CreateNamespace("shared2")
c.Assert(err, check.IsNil)
userShared3, err := app.CreateUser("shared3")
namespaceShared3, err := app.CreateNamespace("shared3")
c.Assert(err, check.IsNil)
preAuthKeyInShared1, err := app.CreatePreAuthKey(
userShared1.Name,
namespaceShared1.Name,
false,
false,
nil,
@@ -131,7 +131,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
c.Assert(err, check.IsNil)
preAuthKeyInShared2, err := app.CreatePreAuthKey(
userShared2.Name,
namespaceShared2.Name,
false,
false,
nil,
@@ -140,7 +140,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
c.Assert(err, check.IsNil)
preAuthKeyInShared3, err := app.CreatePreAuthKey(
userShared3.Name,
namespaceShared3.Name,
false,
false,
nil,
@@ -149,7 +149,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
c.Assert(err, check.IsNil)
PreAuthKey2InShared1, err := app.CreatePreAuthKey(
userShared1.Name,
namespaceShared1.Name,
false,
false,
nil,
@@ -157,7 +157,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
)
c.Assert(err, check.IsNil)
_, err = app.GetMachine(userShared1.Name, "test_get_shared_nodes_1")
_, err = app.GetMachine(namespaceShared1.Name, "test_get_shared_nodes_1")
c.Assert(err, check.NotNil)
machineInShared1 := &Machine{
@@ -166,15 +166,15 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
NodeKey: "686824e749f3b7f2a5927ee6c1e422aee5292592d9179a271ed7b3e659b44a66",
DiscoKey: "686824e749f3b7f2a5927ee6c1e422aee5292592d9179a271ed7b3e659b44a66",
Hostname: "test_get_shared_nodes_1",
UserID: userShared1.ID,
User: *userShared1,
NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.1")},
AuthKeyID: uint(preAuthKeyInShared1.ID),
}
app.db.Save(machineInShared1)
_, err = app.GetMachine(userShared1.Name, machineInShared1.Hostname)
_, err = app.GetMachine(namespaceShared1.Name, machineInShared1.Hostname)
c.Assert(err, check.IsNil)
machineInShared2 := &Machine{
@@ -183,15 +183,15 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
NodeKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
DiscoKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
Hostname: "test_get_shared_nodes_2",
UserID: userShared2.ID,
User: *userShared2,
NamespaceID: namespaceShared2.ID,
Namespace: *namespaceShared2,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.2")},
AuthKeyID: uint(preAuthKeyInShared2.ID),
}
app.db.Save(machineInShared2)
_, err = app.GetMachine(userShared2.Name, machineInShared2.Hostname)
_, err = app.GetMachine(namespaceShared2.Name, machineInShared2.Hostname)
c.Assert(err, check.IsNil)
machineInShared3 := &Machine{
@@ -200,15 +200,15 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
NodeKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
DiscoKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
Hostname: "test_get_shared_nodes_3",
UserID: userShared3.ID,
User: *userShared3,
NamespaceID: namespaceShared3.ID,
Namespace: *namespaceShared3,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.3")},
AuthKeyID: uint(preAuthKeyInShared3.ID),
}
app.db.Save(machineInShared3)
_, err = app.GetMachine(userShared3.Name, machineInShared3.Hostname)
_, err = app.GetMachine(namespaceShared3.Name, machineInShared3.Hostname)
c.Assert(err, check.IsNil)
machine2InShared1 := &Machine{
@@ -217,8 +217,8 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
NodeKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
DiscoKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
Hostname: "test_get_shared_nodes_4",
UserID: userShared1.ID,
User: *userShared1,
NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.4")},
AuthKeyID: uint(PreAuthKey2InShared1.ID),
@@ -245,31 +245,31 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
c.Assert(len(dnsConfig.Routes), check.Equals, 3)
domainRouteShared1 := fmt.Sprintf("%s.%s", userShared1.Name, baseDomain)
domainRouteShared1 := fmt.Sprintf("%s.%s", namespaceShared1.Name, baseDomain)
_, ok := dnsConfig.Routes[domainRouteShared1]
c.Assert(ok, check.Equals, true)
domainRouteShared2 := fmt.Sprintf("%s.%s", userShared2.Name, baseDomain)
domainRouteShared2 := fmt.Sprintf("%s.%s", namespaceShared2.Name, baseDomain)
_, ok = dnsConfig.Routes[domainRouteShared2]
c.Assert(ok, check.Equals, true)
domainRouteShared3 := fmt.Sprintf("%s.%s", userShared3.Name, baseDomain)
domainRouteShared3 := fmt.Sprintf("%s.%s", namespaceShared3.Name, baseDomain)
_, ok = dnsConfig.Routes[domainRouteShared3]
c.Assert(ok, check.Equals, true)
}
func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
userShared1, err := app.CreateUser("shared1")
namespaceShared1, err := app.CreateNamespace("shared1")
c.Assert(err, check.IsNil)
userShared2, err := app.CreateUser("shared2")
namespaceShared2, err := app.CreateNamespace("shared2")
c.Assert(err, check.IsNil)
userShared3, err := app.CreateUser("shared3")
namespaceShared3, err := app.CreateNamespace("shared3")
c.Assert(err, check.IsNil)
preAuthKeyInShared1, err := app.CreatePreAuthKey(
userShared1.Name,
namespaceShared1.Name,
false,
false,
nil,
@@ -278,7 +278,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
c.Assert(err, check.IsNil)
preAuthKeyInShared2, err := app.CreatePreAuthKey(
userShared2.Name,
namespaceShared2.Name,
false,
false,
nil,
@@ -287,7 +287,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
c.Assert(err, check.IsNil)
preAuthKeyInShared3, err := app.CreatePreAuthKey(
userShared3.Name,
namespaceShared3.Name,
false,
false,
nil,
@@ -296,7 +296,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
c.Assert(err, check.IsNil)
preAuthKey2InShared1, err := app.CreatePreAuthKey(
userShared1.Name,
namespaceShared1.Name,
false,
false,
nil,
@@ -304,7 +304,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
)
c.Assert(err, check.IsNil)
_, err = app.GetMachine(userShared1.Name, "test_get_shared_nodes_1")
_, err = app.GetMachine(namespaceShared1.Name, "test_get_shared_nodes_1")
c.Assert(err, check.NotNil)
machineInShared1 := &Machine{
@@ -313,15 +313,15 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
NodeKey: "686824e749f3b7f2a5927ee6c1e422aee5292592d9179a271ed7b3e659b44a66",
DiscoKey: "686824e749f3b7f2a5927ee6c1e422aee5292592d9179a271ed7b3e659b44a66",
Hostname: "test_get_shared_nodes_1",
UserID: userShared1.ID,
User: *userShared1,
NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.1")},
AuthKeyID: uint(preAuthKeyInShared1.ID),
}
app.db.Save(machineInShared1)
_, err = app.GetMachine(userShared1.Name, machineInShared1.Hostname)
_, err = app.GetMachine(namespaceShared1.Name, machineInShared1.Hostname)
c.Assert(err, check.IsNil)
machineInShared2 := &Machine{
@@ -330,15 +330,15 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
NodeKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
DiscoKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
Hostname: "test_get_shared_nodes_2",
UserID: userShared2.ID,
User: *userShared2,
NamespaceID: namespaceShared2.ID,
Namespace: *namespaceShared2,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.2")},
AuthKeyID: uint(preAuthKeyInShared2.ID),
}
app.db.Save(machineInShared2)
_, err = app.GetMachine(userShared2.Name, machineInShared2.Hostname)
_, err = app.GetMachine(namespaceShared2.Name, machineInShared2.Hostname)
c.Assert(err, check.IsNil)
machineInShared3 := &Machine{
@@ -347,15 +347,15 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
NodeKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
DiscoKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
Hostname: "test_get_shared_nodes_3",
UserID: userShared3.ID,
User: *userShared3,
NamespaceID: namespaceShared3.ID,
Namespace: *namespaceShared3,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.3")},
AuthKeyID: uint(preAuthKeyInShared3.ID),
}
app.db.Save(machineInShared3)
_, err = app.GetMachine(userShared3.Name, machineInShared3.Hostname)
_, err = app.GetMachine(namespaceShared3.Name, machineInShared3.Hostname)
c.Assert(err, check.IsNil)
machine2InShared1 := &Machine{
@@ -364,8 +364,8 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
NodeKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
DiscoKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
Hostname: "test_get_shared_nodes_4",
UserID: userShared1.ID,
User: *userShared1,
NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.4")},
AuthKeyID: uint(preAuthKey2InShared1.ID),

View File

@@ -12,7 +12,6 @@ please ask on [Discord](https://discord.gg/c84AZQhmpx) instead of opening an Iss
- [Running headscale on Linux](running-headscale-linux.md)
- [Control headscale remotely](remote-cli.md)
- [Using a Windows client with headscale](windows-client.md)
- [Configuring OIDC](oidc.md)
### References
@@ -30,7 +29,6 @@ written by community members. It is _not_ verified by `headscale` developers.
- [Running headscale in a container](running-headscale-container.md)
- [Running headscale on OpenBSD](running-headscale-openbsd.md)
- [Running headscale behind a reverse proxy](reverse-proxy.md)
- [Set Custom DNS records](dns-records.md)
## Misc
@@ -39,12 +37,12 @@ written by community members. It is _not_ verified by `headscale` developers.
Headscale implements the same policy ACLs as Tailscale.com, adapted to the self-hosted environment.
For instance, instead of referring to users when defining groups you must
use users (which are the equivalent to user/logins in Tailscale.com).
use namespaces (which are the equivalent to user/logins in Tailscale.com).
Please check https://tailscale.com/kb/1018/acls/, and `./tests/acls/` in this repo for working examples.
When using ACL's the User borders are no longer applied. All machines
whichever the User have the ability to communicate with other hosts as
When using ACL's the Namespace borders are no longer applied. All machines
whichever the Namespace have the ability to communicate with other hosts as
long as the ACL's permits this exchange.
The [ACLs](acls.md) document should help understand a fictional case of setting

View File

@@ -29,17 +29,17 @@ servers.
## ACL setup
Note: Users will be created automatically when users authenticate with the
Note: Namespaces will be created automatically when users authenticate with the
Headscale server.
ACLs could be written either on [huJSON](https://github.com/tailscale/hujson)
or YAML. Check the [test ACLs](../tests/acls) for further information.
When registering the servers we will need to add the flag
`--advertise-tags=tag:<tag1>,tag:<tag2>`, and the user that is
`--advertise-tags=tag:<tag1>,tag:<tag2>`, and the user (namespace) that is
registering the server should be allowed to do it. Since anyone can add tags to
a server they can register, the check of the tags is done on headscale server
and only valid tags are applied. A tag is valid if the user that is
and only valid tags are applied. A tag is valid if the namespace that is
registering it is allowed to do it.
Here are the ACL's to implement the same permissions as above:
@@ -164,8 +164,8 @@ Here are the ACL's to implement the same permissions as above:
"dst": ["tag:dev-app-servers:80,443"]
},
// We still have to allow internal users communications since nothing guarantees that each user have
// their own users.
// We still have to allow internal namespaces communications since nothing guarantees that each user have
// their own namespaces.
{ "action": "accept", "src": ["boss"], "dst": ["boss:*"] },
{ "action": "accept", "src": ["dev1"], "dst": ["dev1:*"] },
{ "action": "accept", "src": ["dev2"], "dst": ["dev2:*"] },

View File

@@ -1,83 +0,0 @@
# Setting custom DNS records
## Goal
This documentation has the goal of showing how a user can set custom DNS records with `headscale`s magic dns.
An example use case is to serve apps on the same host via a reverse proxy like NGINX, in this case a Prometheus monitoring stack. This allows to nicely access the service with "http://grafana.myvpn.example.com" instead of the hostname and portnum combination "http://hostname-in-magic-dns.myvpn.example.com:3000".
## Setup
### 1. Change the configuration
1. Change the `config.yaml` to contain the desired records like so:
```yaml
dns_config:
...
extra_records:
- name: "prometheus.myvpn.example.com"
type: "A"
value: "100.64.0.3"
- name: "grafana.myvpn.example.com"
type: "A"
value: "100.64.0.3"
...
```
2. Restart your headscale instance.
Beware of the limitations listed later on!
### 2. Verify that the records are set
You can use a DNS querying tool of your choice on one of your hosts to verify that your newly set records are actually available in MagicDNS, here we used [`dig`](https://man.archlinux.org/man/dig.1.en):
```
$ dig grafana.myvpn.example.com
; <<>> DiG 9.18.10 <<>> grafana.myvpn.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44054
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;grafana.myvpn.example.com. IN A
;; ANSWER SECTION:
grafana.myvpn.example.com. 593 IN A 100.64.0.3
;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Sat Dec 31 11:46:55 CET 2022
;; MSG SIZE rcvd: 66
```
### 3. Optional: Setup the reverse proxy
The motivating example here was to be able to access internal monitoring services on the same host without specifying a port:
```
server {
listen 80;
listen [::]:80;
server_name grafana.myvpn.example.com;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
## Limitations
[Not all types of records are supported](https://github.com/tailscale/tailscale/blob/6edf357b96b28ee1be659a70232c0135b2ffedfd/ipn/ipnlocal/local.go#L2989-L3007), especially no CNAME records.

View File

@@ -1,6 +1,6 @@
# Glossary
| Term | Description |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| Machine | A machine is a single entity connected to `headscale`, typically an installation of Tailscale. Also known as **Node** |
| Namespace | A namespace was a logical grouping of machines "owned" by the same entity, in Tailscale, this is typically a User (This is now called user) |
| Term | Description |
| --------- | --------------------------------------------------------------------------------------------------------------------- |
| Machine | A machine is a single entity connected to `headscale`, typically an installation of Tailscale. Also known as **Node** |
| Namespace | A namespace is a logical grouping of machines "owned" by the same entity, in Tailscale, this is typically a User |

View File

@@ -1,141 +0,0 @@
# Configuring Headscale to use OIDC authentication
In order to authenticate users through a centralized solution one must enable the OIDC integration.
Known limitations:
- No dynamic ACL support
- OIDC groups cannot be used in ACLs
## Basic configuration
In your `config.yaml`, customize this to your liking:
```yaml
oidc:
# Block further startup until the OIDC provider is healthy and available
only_start_if_oidc_is_available: true
# Specified by your OIDC provider
issuer: "https://your-oidc.issuer.com/path"
# Specified/generated by your OIDC provider
client_id: "your-oidc-client-id"
client_secret: "your-oidc-client-secret"
# alternatively, set `client_secret_path` to read the secret from the file.
# It resolves environment variables, making integration to systemd's
# `LoadCredential` straightforward:
#client_secret_path: "${CREDENTIALS_DIRECTORY}/oidc_client_secret"
# Customize the scopes used in the OIDC flow, defaults to "openid", "profile" and "email" and add custom query
# parameters to the Authorize Endpoint request. Scopes default to "openid", "profile" and "email".
scope: ["openid", "profile", "email", "custom"]
# Optional: Passed on to the browser login request used to tweak behaviour for the OIDC provider
extra_params:
domain_hint: example.com
# Optional: List allowed principal domains and/or users. If an authenticated user's domain is not in this list,
# the authentication request will be rejected.
allowed_domains:
- example.com
# Optional. Note that groups from Keycloak have a leading '/'.
allowed_groups:
- /headscale
# Optional.
allowed_users:
- alice@example.com
# If `strip_email_domain` is set to `true`, the domain part of the username email address will be removed.
# This will transform `first-name.last-name@example.com` to the user `first-name.last-name`
# If `strip_email_domain` is set to `false` the domain part will NOT be removed resulting to the following
# user: `first-name.last-name.example.com`
strip_email_domain: true
```
## Azure AD example
In order to integrate Headscale with Azure Active Directory, we'll need to provision an App Registration with the correct scopes and redirect URI. Here with Terraform:
```hcl
resource "azuread_application" "headscale" {
display_name = "Headscale"
sign_in_audience = "AzureADMyOrg"
fallback_public_client_enabled = false
required_resource_access {
// Microsoft Graph
resource_app_id = "00000003-0000-0000-c000-000000000000"
resource_access {
// scope: profile
id = "14dad69e-099b-42c9-810b-d002981feec1"
type = "Scope"
}
resource_access {
// scope: openid
id = "37f7f235-527c-4136-accd-4a02d197296e"
type = "Scope"
}
resource_access {
// scope: email
id = "64a6cdd6-aab1-4aaf-94b8-3cc8405e90d0"
type = "Scope"
}
}
web {
# Points at your running Headscale instance
redirect_uris = ["https://headscale.example.com/oidc/callback"]
implicit_grant {
access_token_issuance_enabled = false
id_token_issuance_enabled = true
}
}
group_membership_claims = ["SecurityGroup"]
optional_claims {
# Expose group memberships
id_token {
name = "groups"
}
}
}
resource "azuread_application_password" "headscale-application-secret" {
display_name = "Headscale Server"
application_object_id = azuread_application.headscale.object_id
}
resource "azuread_service_principal" "headscale" {
application_id = azuread_application.headscale.application_id
}
resource "azuread_service_principal_password" "headscale" {
service_principal_id = azuread_service_principal.headscale.id
end_date_relative = "44640h"
}
output "headscale_client_id" {
value = azuread_application.headscale.application_id
}
output "headscale_client_secret" {
value = azuread_application_password.headscale-application-secret.value
}
```
And in your Headscale `config.yaml`:
```yaml
oidc:
issuer: "https://login.microsoftonline.com/<tenant-UUID>/v2.0"
client_id: "<client-id-from-terraform>"
client_secret: "<client-secret-from-terraform>"
# Optional: add "groups"
scope: ["openid", "profile", "email"]
extra_params:
# Use your own domain, associated with Azure AD
domain_hint: example.com
# Optional: Force the Azure AD account picker
prompt: select_account
```

View File

@@ -98,34 +98,3 @@ spec:
upgrade_configs:
- upgrade_type: tailscale-control-protocol
```
## Caddy
The following Caddyfile is all that is necessary to use Caddy as a reverse proxy for headscale, in combination with the `config.yaml` specifications above to disable headscale's built in TLS. Replace values as necessary - `<YOUR_SERVER_NAME>` should be the FQDN at which headscale will be served, and `<IP:PORT>` should be the IP address and port where headscale is running. In most cases, this will be `localhost:8080`.
```
<YOUR_SERVER_NAME> {
reverse_proxy <IP:PORT>
}
```
Caddy v2 will [automatically](https://caddyserver.com/docs/automatic-https) provision a certficate for your domain/subdomain, force HTTPS, and proxy websockets - no further configuration is necessary.
For a slightly more complex configuration which utilizes Docker containers to manage Caddy, Headscale, and Headscale-UI, [Guru Computing's guide](https://blog.gurucomputing.com.au/smart-vpns-with-headscale/) is an excellent reference.
## Apache
The following minimal Apache config will proxy traffic to the Headscale instance on `<IP:PORT>`. Note that `upgrade=any` is required as a parameter for `ProxyPass` so that WebSockets traffic whose `Upgrade` header value is not equal to `WebSocket` (i. e. Tailscale Control Protocol) is forwarded correctly. See the [Apache docs](https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html) for more information on this.
```
<VirtualHost *:443>
ServerName <YOUR_SERVER_NAME>
ProxyPreserveHost On
ProxyPass / http://<IP:PORT>/ upgrade=any
SSLEngine On
SSLCertificateFile <PATH_TO_CERT>
SSLCertificateKeyFile <PATH_CERT_KEY>
</VirtualHost>
```

View File

@@ -101,11 +101,11 @@ Verify `headscale` is available:
curl http://127.0.0.1:9090/metrics
```
6. Create a user ([tailnet](https://tailscale.com/kb/1136/tailnet/)):
6. Create a namespace ([tailnet](https://tailscale.com/kb/1136/tailnet/)):
```shell
docker exec headscale \
headscale users create myfirstuser
headscale namespaces create myfirstnamespace
```
### Register a machine (normal login)
@@ -120,7 +120,7 @@ To register a machine when running `headscale` in a container, take the headscal
```shell
docker exec headscale \
headscale --user myfirstuser nodes register --key <YOU_+MACHINE_KEY>
headscale --namespace myfirstnamespace nodes register --key <YOU_+MACHINE_KEY>
```
### Register machine using a pre authenticated key
@@ -129,7 +129,7 @@ Generate a key using the command line:
```shell
docker exec headscale \
headscale --user myfirstuser preauthkeys create --reusable --expiration 24h
headscale --namespace myfirstnamespace preauthkeys create --reusable --expiration 24h
```
This will return a pre-authenticated key that can be used to connect a node to `headscale` during the `tailscale` command:

View File

@@ -78,10 +78,10 @@ Verify `headscale` is available:
curl http://127.0.0.1:9090/metrics
```
8. Create a user ([tailnet](https://tailscale.com/kb/1136/tailnet/)):
8. Create a namespace ([tailnet](https://tailscale.com/kb/1136/tailnet/)):
```shell
headscale users create myfirstuser
headscale namespaces create myfirstnamespace
```
### Register a machine (normal login)
@@ -95,7 +95,7 @@ tailscale up --login-server YOUR_HEADSCALE_URL
Register the machine:
```shell
headscale --user myfirstuser nodes register --key <YOU_+MACHINE_KEY>
headscale --namespace myfirstnamespace nodes register --key <YOU_+MACHINE_KEY>
```
### Register machine using a pre authenticated key
@@ -103,7 +103,7 @@ headscale --user myfirstuser nodes register --key <YOU_+MACHINE_KEY>
Generate a key using the command line:
```shell
headscale --user myfirstuser preauthkeys create --reusable --expiration 24h
headscale --namespace myfirstnamespace preauthkeys create --reusable --expiration 24h
```
This will return a pre-authenticated key that can be used to connect a node to `headscale` during the `tailscale` command:

View File

@@ -116,10 +116,10 @@ Verify `headscale` is available:
curl http://127.0.0.1:9090/metrics
```
6. Create a user ([tailnet](https://tailscale.com/kb/1136/tailnet/)):
6. Create a namespace ([tailnet](https://tailscale.com/kb/1136/tailnet/)):
```shell
headscale users create myfirstuser
headscale namespaces create myfirstnamespace
```
### Register a machine (normal login)
@@ -133,7 +133,7 @@ tailscale up --login-server YOUR_HEADSCALE_URL
Register the machine:
```shell
headscale --user myfirstuser nodes register --key <YOU_+MACHINE_KEY>
headscale --namespace myfirstnamespace nodes register --key <YOU_+MACHINE_KEY>
```
### Register machine using a pre authenticated key
@@ -141,7 +141,7 @@ headscale --user myfirstuser nodes register --key <YOU_+MACHINE_KEY>
Generate a key using the command line:
```shell
headscale --user myfirstuser preauthkeys create --reusable --expiration 24h
headscale --namespace myfirstnamespace preauthkeys create --reusable --expiration 24h
```
This will return a pre-authenticated key that can be used to connect a node to `headscale` during the `tailscale` command:

View File

@@ -33,7 +33,7 @@
# When updating go.mod or go.sum, a new sha will need to be calculated,
# update this if you have a mismatch after doing a change to thos files.
vendorSha256 = "sha256-8p5NFxXKaZPsW4B6NMzfi0pqfVroIahSgA0fukvB3JI=";
vendorSha256 = "sha256-SuKT+b8g6xEK15ry2IAmpS/vwDG+zJqK9nfsWpHNXuU=";
ldflags = ["-s" "-w" "-X github.com/juanfont/headscale/cmd/headscale/cli.Version=v${version}"];
};

View File

@@ -7,12 +7,11 @@
package v1
import (
reflect "reflect"
sync "sync"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (
@@ -423,19 +422,17 @@ func file_headscale_v1_apikey_proto_rawDescGZIP() []byte {
return file_headscale_v1_apikey_proto_rawDescData
}
var (
file_headscale_v1_apikey_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
file_headscale_v1_apikey_proto_goTypes = []interface{}{
(*ApiKey)(nil), // 0: headscale.v1.ApiKey
(*CreateApiKeyRequest)(nil), // 1: headscale.v1.CreateApiKeyRequest
(*CreateApiKeyResponse)(nil), // 2: headscale.v1.CreateApiKeyResponse
(*ExpireApiKeyRequest)(nil), // 3: headscale.v1.ExpireApiKeyRequest
(*ExpireApiKeyResponse)(nil), // 4: headscale.v1.ExpireApiKeyResponse
(*ListApiKeysRequest)(nil), // 5: headscale.v1.ListApiKeysRequest
(*ListApiKeysResponse)(nil), // 6: headscale.v1.ListApiKeysResponse
(*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp
}
)
var file_headscale_v1_apikey_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_headscale_v1_apikey_proto_goTypes = []interface{}{
(*ApiKey)(nil), // 0: headscale.v1.ApiKey
(*CreateApiKeyRequest)(nil), // 1: headscale.v1.CreateApiKeyRequest
(*CreateApiKeyResponse)(nil), // 2: headscale.v1.CreateApiKeyResponse
(*ExpireApiKeyRequest)(nil), // 3: headscale.v1.ExpireApiKeyRequest
(*ExpireApiKeyResponse)(nil), // 4: headscale.v1.ExpireApiKeyResponse
(*ListApiKeysRequest)(nil), // 5: headscale.v1.ListApiKeysRequest
(*ListApiKeysResponse)(nil), // 6: headscale.v1.ListApiKeysResponse
(*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp
}
var file_headscale_v1_apikey_proto_depIdxs = []int32{
7, // 0: headscale.v1.ApiKey.expiration:type_name -> google.protobuf.Timestamp
7, // 1: headscale.v1.ApiKey.created_at:type_name -> google.protobuf.Timestamp

View File

@@ -7,12 +7,11 @@
package v1
import (
reflect "reflect"
sync "sync"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (
@@ -925,24 +924,22 @@ func file_headscale_v1_device_proto_rawDescGZIP() []byte {
return file_headscale_v1_device_proto_rawDescData
}
var (
file_headscale_v1_device_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
file_headscale_v1_device_proto_goTypes = []interface{}{
(*Latency)(nil), // 0: headscale.v1.Latency
(*ClientSupports)(nil), // 1: headscale.v1.ClientSupports
(*ClientConnectivity)(nil), // 2: headscale.v1.ClientConnectivity
(*GetDeviceRequest)(nil), // 3: headscale.v1.GetDeviceRequest
(*GetDeviceResponse)(nil), // 4: headscale.v1.GetDeviceResponse
(*DeleteDeviceRequest)(nil), // 5: headscale.v1.DeleteDeviceRequest
(*DeleteDeviceResponse)(nil), // 6: headscale.v1.DeleteDeviceResponse
(*GetDeviceRoutesRequest)(nil), // 7: headscale.v1.GetDeviceRoutesRequest
(*GetDeviceRoutesResponse)(nil), // 8: headscale.v1.GetDeviceRoutesResponse
(*EnableDeviceRoutesRequest)(nil), // 9: headscale.v1.EnableDeviceRoutesRequest
(*EnableDeviceRoutesResponse)(nil), // 10: headscale.v1.EnableDeviceRoutesResponse
nil, // 11: headscale.v1.ClientConnectivity.LatencyEntry
(*timestamppb.Timestamp)(nil), // 12: google.protobuf.Timestamp
}
)
var file_headscale_v1_device_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
var file_headscale_v1_device_proto_goTypes = []interface{}{
(*Latency)(nil), // 0: headscale.v1.Latency
(*ClientSupports)(nil), // 1: headscale.v1.ClientSupports
(*ClientConnectivity)(nil), // 2: headscale.v1.ClientConnectivity
(*GetDeviceRequest)(nil), // 3: headscale.v1.GetDeviceRequest
(*GetDeviceResponse)(nil), // 4: headscale.v1.GetDeviceResponse
(*DeleteDeviceRequest)(nil), // 5: headscale.v1.DeleteDeviceRequest
(*DeleteDeviceResponse)(nil), // 6: headscale.v1.DeleteDeviceResponse
(*GetDeviceRoutesRequest)(nil), // 7: headscale.v1.GetDeviceRoutesRequest
(*GetDeviceRoutesResponse)(nil), // 8: headscale.v1.GetDeviceRoutesResponse
(*EnableDeviceRoutesRequest)(nil), // 9: headscale.v1.EnableDeviceRoutesRequest
(*EnableDeviceRoutesResponse)(nil), // 10: headscale.v1.EnableDeviceRoutesResponse
nil, // 11: headscale.v1.ClientConnectivity.LatencyEntry
(*timestamppb.Timestamp)(nil), // 12: google.protobuf.Timestamp
}
var file_headscale_v1_device_proto_depIdxs = []int32{
11, // 0: headscale.v1.ClientConnectivity.latency:type_name -> headscale.v1.ClientConnectivity.LatencyEntry
1, // 1: headscale.v1.ClientConnectivity.client_supports:type_name -> headscale.v1.ClientSupports

View File

@@ -7,11 +7,10 @@
package v1
import (
reflect "reflect"
_ "google.golang.org/genproto/googleapis/api/annotations"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
)
const (
@@ -28,148 +27,155 @@ var file_headscale_v1_headscale_proto_rawDesc = []byte{
0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c,
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x1c, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x68, 0x65, 0x61, 0x64,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76,
0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x1a, 0x1a, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31,
0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19,
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75,
0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x68, 0x65, 0x61, 0x64, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x32, 0x96, 0x17, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x63, 0x0a, 0x07, 0x47, 0x65, 0x74,
0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65,
0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f,
0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x68,
0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61,
0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65,
0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a, 0x22, 0x0c, 0x2f, 0x61, 0x70, 0x69,
0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x12, 0x82, 0x01, 0x0a, 0x0a, 0x52, 0x65, 0x6e,
0x61, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63,
0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x55, 0x73, 0x65,
0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x55, 0x73,
0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x2b, 0x22, 0x29, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72,
0x2f, 0x7b, 0x6f, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x2f, 0x72, 0x65, 0x6e, 0x61,
0x6d, 0x65, 0x2f, 0x7b, 0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x6c, 0x0a,
0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x68, 0x65,
0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74,
0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65,
0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x2a, 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f,
0x75, 0x73, 0x65, 0x72, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x62, 0x0a, 0x09, 0x4c,
0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x1e, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x0e, 0x12, 0x0c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x12,
0x80, 0x01, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74,
0x68, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65,
0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74,
0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x65,
0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, 0x01, 0x2a, 0x22, 0x12,
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b,
0x65, 0x79, 0x12, 0x87, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65,
0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63,
0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65,
0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78,
0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01,
0x2a, 0x22, 0x19, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75,
0x74, 0x68, 0x6b, 0x65, 0x79, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x12, 0x7a, 0x0a, 0x0f,
0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x12,
0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x68, 0x65, 0x61, 0x64,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63,
0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65,
0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1a, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76,
0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19,
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69,
0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x81, 0x18, 0x0a, 0x10, 0x48, 0x65,
0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x77,
0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x21,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65,
0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f,
0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x7c, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x3a,
0x01, 0x2a, 0x22, 0x11, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65,
0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x96, 0x01, 0x0a, 0x0f, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65,
0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4e,
0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52,
0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x22, 0x2e,
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
0x65, 0x2f, 0x7b, 0x6f, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x2f, 0x72, 0x65, 0x6e,
0x61, 0x6d, 0x65, 0x2f, 0x7b, 0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x80,
0x01, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
0x63, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61,
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x2a, 0x18, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31,
0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65,
0x7d, 0x12, 0x76, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
0x63, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65,
0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f,
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x10, 0x43, 0x72,
0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x25,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72,
0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75,
0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, 0x01, 0x2a, 0x22, 0x12, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76,
0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65, 0x79, 0x12, 0x87, 0x01, 0x0a,
0x10, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65,
0x79, 0x12, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65,
0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72,
0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x22, 0x19, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65, 0x79, 0x2f,
0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x12, 0x7a, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72,
0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65,
0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68,
0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72,
0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65, 0x79, 0x12, 0x89, 0x01, 0x0a, 0x12, 0x44, 0x65, 0x62,
0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12,
0x27, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44,
0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65,
0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f,
0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2f, 0x6d, 0x61, 0x63,
0x68, 0x69, 0x6e, 0x65, 0x12, 0x75, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69,
0x6e, 0x65, 0x12, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f,
0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b,
0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x74, 0x0a, 0x07, 0x53,
0x65, 0x74, 0x54, 0x61, 0x67, 0x73, 0x12, 0x1c, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65,
0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21,
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f,
0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x74, 0x61, 0x67,
0x73, 0x12, 0x80, 0x01, 0x0a, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x63,
0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65,
0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73,
0x74, 0x65, 0x72, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x22, 0x18, 0x2f, 0x61, 0x70, 0x69,
0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x72, 0x65, 0x67, 0x69,
0x73, 0x74, 0x65, 0x72, 0x12, 0x7e, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69,
0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x2a, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f,
0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x5f, 0x69, 0x64, 0x7d, 0x12, 0x85, 0x01, 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68,
0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12,
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b,
0x65, 0x79, 0x12, 0x89, 0x01, 0x0a, 0x12, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61,
0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x27, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72,
0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63,
0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31,
0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x75,
0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x1f, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74,
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x22, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31,
0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31,
0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e,
0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x12, 0x90, 0x01, 0x0a,
0x0d, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x22,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65,
0x6e, 0x61, 0x6d, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x22,
0x2e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65,
0x6e, 0x61, 0x6d, 0x65, 0x2f, 0x7b, 0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12,
0x6e, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x12,
0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f,
0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12,
0x7d, 0x0a, 0x0b, 0x4d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x20,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f,
0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
0x4d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x22, 0x21, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x12, 0x64,
0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x74, 0x0a, 0x07, 0x53, 0x65, 0x74, 0x54, 0x61, 0x67, 0x73,
0x12, 0x1c, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
0x53, 0x65, 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65,
0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76,
0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69,
0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x74, 0x61, 0x67, 0x73, 0x12, 0x80, 0x01, 0x0a, 0x0f,
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12,
0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x63,
0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x1a, 0x22, 0x18, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x7e,
0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12,
0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44,
0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e,
0x2a, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e,
0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x85,
0x01, 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x12, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65,
0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x25, 0x22, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69,
0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f,
0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x12, 0x90, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x6e, 0x61, 0x6d,
0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61,
0x6d, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x22, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x2f,
0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68,
0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2f, 0x7b,
0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x6e, 0x0a, 0x0c, 0x4c, 0x69, 0x73,
0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63,
0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74,
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76,
0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x0b, 0x4d, 0x6f,
0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x63,
0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x65,
0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x4d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e,
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x22, 0x26, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f,
0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x64,
0x0a, 0x09, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x68, 0x65,
0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f,
0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x65,
@@ -229,11 +235,11 @@ var file_headscale_v1_headscale_proto_rawDesc = []byte{
}
var file_headscale_v1_headscale_proto_goTypes = []interface{}{
(*GetUserRequest)(nil), // 0: headscale.v1.GetUserRequest
(*CreateUserRequest)(nil), // 1: headscale.v1.CreateUserRequest
(*RenameUserRequest)(nil), // 2: headscale.v1.RenameUserRequest
(*DeleteUserRequest)(nil), // 3: headscale.v1.DeleteUserRequest
(*ListUsersRequest)(nil), // 4: headscale.v1.ListUsersRequest
(*GetNamespaceRequest)(nil), // 0: headscale.v1.GetNamespaceRequest
(*CreateNamespaceRequest)(nil), // 1: headscale.v1.CreateNamespaceRequest
(*RenameNamespaceRequest)(nil), // 2: headscale.v1.RenameNamespaceRequest
(*DeleteNamespaceRequest)(nil), // 3: headscale.v1.DeleteNamespaceRequest
(*ListNamespacesRequest)(nil), // 4: headscale.v1.ListNamespacesRequest
(*CreatePreAuthKeyRequest)(nil), // 5: headscale.v1.CreatePreAuthKeyRequest
(*ExpirePreAuthKeyRequest)(nil), // 6: headscale.v1.ExpirePreAuthKeyRequest
(*ListPreAuthKeysRequest)(nil), // 7: headscale.v1.ListPreAuthKeysRequest
@@ -253,11 +259,11 @@ var file_headscale_v1_headscale_proto_goTypes = []interface{}{
(*CreateApiKeyRequest)(nil), // 21: headscale.v1.CreateApiKeyRequest
(*ExpireApiKeyRequest)(nil), // 22: headscale.v1.ExpireApiKeyRequest
(*ListApiKeysRequest)(nil), // 23: headscale.v1.ListApiKeysRequest
(*GetUserResponse)(nil), // 24: headscale.v1.GetUserResponse
(*CreateUserResponse)(nil), // 25: headscale.v1.CreateUserResponse
(*RenameUserResponse)(nil), // 26: headscale.v1.RenameUserResponse
(*DeleteUserResponse)(nil), // 27: headscale.v1.DeleteUserResponse
(*ListUsersResponse)(nil), // 28: headscale.v1.ListUsersResponse
(*GetNamespaceResponse)(nil), // 24: headscale.v1.GetNamespaceResponse
(*CreateNamespaceResponse)(nil), // 25: headscale.v1.CreateNamespaceResponse
(*RenameNamespaceResponse)(nil), // 26: headscale.v1.RenameNamespaceResponse
(*DeleteNamespaceResponse)(nil), // 27: headscale.v1.DeleteNamespaceResponse
(*ListNamespacesResponse)(nil), // 28: headscale.v1.ListNamespacesResponse
(*CreatePreAuthKeyResponse)(nil), // 29: headscale.v1.CreatePreAuthKeyResponse
(*ExpirePreAuthKeyResponse)(nil), // 30: headscale.v1.ExpirePreAuthKeyResponse
(*ListPreAuthKeysResponse)(nil), // 31: headscale.v1.ListPreAuthKeysResponse
@@ -278,13 +284,12 @@ var file_headscale_v1_headscale_proto_goTypes = []interface{}{
(*ExpireApiKeyResponse)(nil), // 46: headscale.v1.ExpireApiKeyResponse
(*ListApiKeysResponse)(nil), // 47: headscale.v1.ListApiKeysResponse
}
var file_headscale_v1_headscale_proto_depIdxs = []int32{
0, // 0: headscale.v1.HeadscaleService.GetUser:input_type -> headscale.v1.GetUserRequest
1, // 1: headscale.v1.HeadscaleService.CreateUser:input_type -> headscale.v1.CreateUserRequest
2, // 2: headscale.v1.HeadscaleService.RenameUser:input_type -> headscale.v1.RenameUserRequest
3, // 3: headscale.v1.HeadscaleService.DeleteUser:input_type -> headscale.v1.DeleteUserRequest
4, // 4: headscale.v1.HeadscaleService.ListUsers:input_type -> headscale.v1.ListUsersRequest
0, // 0: headscale.v1.HeadscaleService.GetNamespace:input_type -> headscale.v1.GetNamespaceRequest
1, // 1: headscale.v1.HeadscaleService.CreateNamespace:input_type -> headscale.v1.CreateNamespaceRequest
2, // 2: headscale.v1.HeadscaleService.RenameNamespace:input_type -> headscale.v1.RenameNamespaceRequest
3, // 3: headscale.v1.HeadscaleService.DeleteNamespace:input_type -> headscale.v1.DeleteNamespaceRequest
4, // 4: headscale.v1.HeadscaleService.ListNamespaces:input_type -> headscale.v1.ListNamespacesRequest
5, // 5: headscale.v1.HeadscaleService.CreatePreAuthKey:input_type -> headscale.v1.CreatePreAuthKeyRequest
6, // 6: headscale.v1.HeadscaleService.ExpirePreAuthKey:input_type -> headscale.v1.ExpirePreAuthKeyRequest
7, // 7: headscale.v1.HeadscaleService.ListPreAuthKeys:input_type -> headscale.v1.ListPreAuthKeysRequest
@@ -304,11 +309,11 @@ var file_headscale_v1_headscale_proto_depIdxs = []int32{
21, // 21: headscale.v1.HeadscaleService.CreateApiKey:input_type -> headscale.v1.CreateApiKeyRequest
22, // 22: headscale.v1.HeadscaleService.ExpireApiKey:input_type -> headscale.v1.ExpireApiKeyRequest
23, // 23: headscale.v1.HeadscaleService.ListApiKeys:input_type -> headscale.v1.ListApiKeysRequest
24, // 24: headscale.v1.HeadscaleService.GetUser:output_type -> headscale.v1.GetUserResponse
25, // 25: headscale.v1.HeadscaleService.CreateUser:output_type -> headscale.v1.CreateUserResponse
26, // 26: headscale.v1.HeadscaleService.RenameUser:output_type -> headscale.v1.RenameUserResponse
27, // 27: headscale.v1.HeadscaleService.DeleteUser:output_type -> headscale.v1.DeleteUserResponse
28, // 28: headscale.v1.HeadscaleService.ListUsers:output_type -> headscale.v1.ListUsersResponse
24, // 24: headscale.v1.HeadscaleService.GetNamespace:output_type -> headscale.v1.GetNamespaceResponse
25, // 25: headscale.v1.HeadscaleService.CreateNamespace:output_type -> headscale.v1.CreateNamespaceResponse
26, // 26: headscale.v1.HeadscaleService.RenameNamespace:output_type -> headscale.v1.RenameNamespaceResponse
27, // 27: headscale.v1.HeadscaleService.DeleteNamespace:output_type -> headscale.v1.DeleteNamespaceResponse
28, // 28: headscale.v1.HeadscaleService.ListNamespaces:output_type -> headscale.v1.ListNamespacesResponse
29, // 29: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse
30, // 30: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse
31, // 31: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse
@@ -340,7 +345,7 @@ func file_headscale_v1_headscale_proto_init() {
if File_headscale_v1_headscale_proto != nil {
return
}
file_headscale_v1_user_proto_init()
file_headscale_v1_namespace_proto_init()
file_headscale_v1_preauthkey_proto_init()
file_headscale_v1_machine_proto_init()
file_headscale_v1_routes_proto_init()

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,6 @@ package v1
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
@@ -23,12 +22,12 @@ const _ = grpc.SupportPackageIsVersion7
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type HeadscaleServiceClient interface {
// --- User start ---
GetUser(ctx context.Context, in *GetUserRequest, opts ...grpc.CallOption) (*GetUserResponse, error)
CreateUser(ctx context.Context, in *CreateUserRequest, opts ...grpc.CallOption) (*CreateUserResponse, error)
RenameUser(ctx context.Context, in *RenameUserRequest, opts ...grpc.CallOption) (*RenameUserResponse, error)
DeleteUser(ctx context.Context, in *DeleteUserRequest, opts ...grpc.CallOption) (*DeleteUserResponse, error)
ListUsers(ctx context.Context, in *ListUsersRequest, opts ...grpc.CallOption) (*ListUsersResponse, error)
// --- Namespace start ---
GetNamespace(ctx context.Context, in *GetNamespaceRequest, opts ...grpc.CallOption) (*GetNamespaceResponse, error)
CreateNamespace(ctx context.Context, in *CreateNamespaceRequest, opts ...grpc.CallOption) (*CreateNamespaceResponse, error)
RenameNamespace(ctx context.Context, in *RenameNamespaceRequest, opts ...grpc.CallOption) (*RenameNamespaceResponse, error)
DeleteNamespace(ctx context.Context, in *DeleteNamespaceRequest, opts ...grpc.CallOption) (*DeleteNamespaceResponse, error)
ListNamespaces(ctx context.Context, in *ListNamespacesRequest, opts ...grpc.CallOption) (*ListNamespacesResponse, error)
// --- PreAuthKeys start ---
CreatePreAuthKey(ctx context.Context, in *CreatePreAuthKeyRequest, opts ...grpc.CallOption) (*CreatePreAuthKeyResponse, error)
ExpirePreAuthKey(ctx context.Context, in *ExpirePreAuthKeyRequest, opts ...grpc.CallOption) (*ExpirePreAuthKeyResponse, error)
@@ -62,45 +61,45 @@ func NewHeadscaleServiceClient(cc grpc.ClientConnInterface) HeadscaleServiceClie
return &headscaleServiceClient{cc}
}
func (c *headscaleServiceClient) GetUser(ctx context.Context, in *GetUserRequest, opts ...grpc.CallOption) (*GetUserResponse, error) {
out := new(GetUserResponse)
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/GetUser", in, out, opts...)
func (c *headscaleServiceClient) GetNamespace(ctx context.Context, in *GetNamespaceRequest, opts ...grpc.CallOption) (*GetNamespaceResponse, error) {
out := new(GetNamespaceResponse)
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/GetNamespace", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *headscaleServiceClient) CreateUser(ctx context.Context, in *CreateUserRequest, opts ...grpc.CallOption) (*CreateUserResponse, error) {
out := new(CreateUserResponse)
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/CreateUser", in, out, opts...)
func (c *headscaleServiceClient) CreateNamespace(ctx context.Context, in *CreateNamespaceRequest, opts ...grpc.CallOption) (*CreateNamespaceResponse, error) {
out := new(CreateNamespaceResponse)
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/CreateNamespace", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *headscaleServiceClient) RenameUser(ctx context.Context, in *RenameUserRequest, opts ...grpc.CallOption) (*RenameUserResponse, error) {
out := new(RenameUserResponse)
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/RenameUser", in, out, opts...)
func (c *headscaleServiceClient) RenameNamespace(ctx context.Context, in *RenameNamespaceRequest, opts ...grpc.CallOption) (*RenameNamespaceResponse, error) {
out := new(RenameNamespaceResponse)
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/RenameNamespace", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *headscaleServiceClient) DeleteUser(ctx context.Context, in *DeleteUserRequest, opts ...grpc.CallOption) (*DeleteUserResponse, error) {
out := new(DeleteUserResponse)
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/DeleteUser", in, out, opts...)
func (c *headscaleServiceClient) DeleteNamespace(ctx context.Context, in *DeleteNamespaceRequest, opts ...grpc.CallOption) (*DeleteNamespaceResponse, error) {
out := new(DeleteNamespaceResponse)
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/DeleteNamespace", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *headscaleServiceClient) ListUsers(ctx context.Context, in *ListUsersRequest, opts ...grpc.CallOption) (*ListUsersResponse, error) {
out := new(ListUsersResponse)
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ListUsers", in, out, opts...)
func (c *headscaleServiceClient) ListNamespaces(ctx context.Context, in *ListNamespacesRequest, opts ...grpc.CallOption) (*ListNamespacesResponse, error) {
out := new(ListNamespacesResponse)
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ListNamespaces", in, out, opts...)
if err != nil {
return nil, err
}
@@ -282,12 +281,12 @@ func (c *headscaleServiceClient) ListApiKeys(ctx context.Context, in *ListApiKey
// All implementations must embed UnimplementedHeadscaleServiceServer
// for forward compatibility
type HeadscaleServiceServer interface {
// --- User start ---
GetUser(context.Context, *GetUserRequest) (*GetUserResponse, error)
CreateUser(context.Context, *CreateUserRequest) (*CreateUserResponse, error)
RenameUser(context.Context, *RenameUserRequest) (*RenameUserResponse, error)
DeleteUser(context.Context, *DeleteUserRequest) (*DeleteUserResponse, error)
ListUsers(context.Context, *ListUsersRequest) (*ListUsersResponse, error)
// --- Namespace start ---
GetNamespace(context.Context, *GetNamespaceRequest) (*GetNamespaceResponse, error)
CreateNamespace(context.Context, *CreateNamespaceRequest) (*CreateNamespaceResponse, error)
RenameNamespace(context.Context, *RenameNamespaceRequest) (*RenameNamespaceResponse, error)
DeleteNamespace(context.Context, *DeleteNamespaceRequest) (*DeleteNamespaceResponse, error)
ListNamespaces(context.Context, *ListNamespacesRequest) (*ListNamespacesResponse, error)
// --- PreAuthKeys start ---
CreatePreAuthKey(context.Context, *CreatePreAuthKeyRequest) (*CreatePreAuthKeyResponse, error)
ExpirePreAuthKey(context.Context, *ExpirePreAuthKeyRequest) (*ExpirePreAuthKeyResponse, error)
@@ -315,100 +314,78 @@ type HeadscaleServiceServer interface {
}
// UnimplementedHeadscaleServiceServer must be embedded to have forward compatible implementations.
type UnimplementedHeadscaleServiceServer struct{}
func (UnimplementedHeadscaleServiceServer) GetUser(context.Context, *GetUserRequest) (*GetUserResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetUser not implemented")
type UnimplementedHeadscaleServiceServer struct {
}
func (UnimplementedHeadscaleServiceServer) CreateUser(context.Context, *CreateUserRequest) (*CreateUserResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateUser not implemented")
func (UnimplementedHeadscaleServiceServer) GetNamespace(context.Context, *GetNamespaceRequest) (*GetNamespaceResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetNamespace not implemented")
}
func (UnimplementedHeadscaleServiceServer) RenameUser(context.Context, *RenameUserRequest) (*RenameUserResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RenameUser not implemented")
func (UnimplementedHeadscaleServiceServer) CreateNamespace(context.Context, *CreateNamespaceRequest) (*CreateNamespaceResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateNamespace not implemented")
}
func (UnimplementedHeadscaleServiceServer) DeleteUser(context.Context, *DeleteUserRequest) (*DeleteUserResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteUser not implemented")
func (UnimplementedHeadscaleServiceServer) RenameNamespace(context.Context, *RenameNamespaceRequest) (*RenameNamespaceResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RenameNamespace not implemented")
}
func (UnimplementedHeadscaleServiceServer) ListUsers(context.Context, *ListUsersRequest) (*ListUsersResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListUsers not implemented")
func (UnimplementedHeadscaleServiceServer) DeleteNamespace(context.Context, *DeleteNamespaceRequest) (*DeleteNamespaceResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteNamespace not implemented")
}
func (UnimplementedHeadscaleServiceServer) ListNamespaces(context.Context, *ListNamespacesRequest) (*ListNamespacesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListNamespaces not implemented")
}
func (UnimplementedHeadscaleServiceServer) CreatePreAuthKey(context.Context, *CreatePreAuthKeyRequest) (*CreatePreAuthKeyResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreatePreAuthKey not implemented")
}
func (UnimplementedHeadscaleServiceServer) ExpirePreAuthKey(context.Context, *ExpirePreAuthKeyRequest) (*ExpirePreAuthKeyResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ExpirePreAuthKey not implemented")
}
func (UnimplementedHeadscaleServiceServer) ListPreAuthKeys(context.Context, *ListPreAuthKeysRequest) (*ListPreAuthKeysResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListPreAuthKeys not implemented")
}
func (UnimplementedHeadscaleServiceServer) DebugCreateMachine(context.Context, *DebugCreateMachineRequest) (*DebugCreateMachineResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DebugCreateMachine not implemented")
}
func (UnimplementedHeadscaleServiceServer) GetMachine(context.Context, *GetMachineRequest) (*GetMachineResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetMachine not implemented")
}
func (UnimplementedHeadscaleServiceServer) SetTags(context.Context, *SetTagsRequest) (*SetTagsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SetTags not implemented")
}
func (UnimplementedHeadscaleServiceServer) RegisterMachine(context.Context, *RegisterMachineRequest) (*RegisterMachineResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RegisterMachine not implemented")
}
func (UnimplementedHeadscaleServiceServer) DeleteMachine(context.Context, *DeleteMachineRequest) (*DeleteMachineResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteMachine not implemented")
}
func (UnimplementedHeadscaleServiceServer) ExpireMachine(context.Context, *ExpireMachineRequest) (*ExpireMachineResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ExpireMachine not implemented")
}
func (UnimplementedHeadscaleServiceServer) RenameMachine(context.Context, *RenameMachineRequest) (*RenameMachineResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RenameMachine not implemented")
}
func (UnimplementedHeadscaleServiceServer) ListMachines(context.Context, *ListMachinesRequest) (*ListMachinesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListMachines not implemented")
}
func (UnimplementedHeadscaleServiceServer) MoveMachine(context.Context, *MoveMachineRequest) (*MoveMachineResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method MoveMachine not implemented")
}
func (UnimplementedHeadscaleServiceServer) GetRoutes(context.Context, *GetRoutesRequest) (*GetRoutesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetRoutes not implemented")
}
func (UnimplementedHeadscaleServiceServer) EnableRoute(context.Context, *EnableRouteRequest) (*EnableRouteResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method EnableRoute not implemented")
}
func (UnimplementedHeadscaleServiceServer) DisableRoute(context.Context, *DisableRouteRequest) (*DisableRouteResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DisableRoute not implemented")
}
func (UnimplementedHeadscaleServiceServer) GetMachineRoutes(context.Context, *GetMachineRoutesRequest) (*GetMachineRoutesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetMachineRoutes not implemented")
}
func (UnimplementedHeadscaleServiceServer) CreateApiKey(context.Context, *CreateApiKeyRequest) (*CreateApiKeyResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateApiKey not implemented")
}
func (UnimplementedHeadscaleServiceServer) ExpireApiKey(context.Context, *ExpireApiKeyRequest) (*ExpireApiKeyResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ExpireApiKey not implemented")
}
func (UnimplementedHeadscaleServiceServer) ListApiKeys(context.Context, *ListApiKeysRequest) (*ListApiKeysResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListApiKeys not implemented")
}
@@ -425,92 +402,92 @@ func RegisterHeadscaleServiceServer(s grpc.ServiceRegistrar, srv HeadscaleServic
s.RegisterService(&HeadscaleService_ServiceDesc, srv)
}
func _HeadscaleService_GetUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetUserRequest)
func _HeadscaleService_GetNamespace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetNamespaceRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HeadscaleServiceServer).GetUser(ctx, in)
return srv.(HeadscaleServiceServer).GetNamespace(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/headscale.v1.HeadscaleService/GetUser",
FullMethod: "/headscale.v1.HeadscaleService/GetNamespace",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HeadscaleServiceServer).GetUser(ctx, req.(*GetUserRequest))
return srv.(HeadscaleServiceServer).GetNamespace(ctx, req.(*GetNamespaceRequest))
}
return interceptor(ctx, in, info, handler)
}
func _HeadscaleService_CreateUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateUserRequest)
func _HeadscaleService_CreateNamespace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateNamespaceRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HeadscaleServiceServer).CreateUser(ctx, in)
return srv.(HeadscaleServiceServer).CreateNamespace(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/headscale.v1.HeadscaleService/CreateUser",
FullMethod: "/headscale.v1.HeadscaleService/CreateNamespace",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HeadscaleServiceServer).CreateUser(ctx, req.(*CreateUserRequest))
return srv.(HeadscaleServiceServer).CreateNamespace(ctx, req.(*CreateNamespaceRequest))
}
return interceptor(ctx, in, info, handler)
}
func _HeadscaleService_RenameUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RenameUserRequest)
func _HeadscaleService_RenameNamespace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RenameNamespaceRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HeadscaleServiceServer).RenameUser(ctx, in)
return srv.(HeadscaleServiceServer).RenameNamespace(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/headscale.v1.HeadscaleService/RenameUser",
FullMethod: "/headscale.v1.HeadscaleService/RenameNamespace",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HeadscaleServiceServer).RenameUser(ctx, req.(*RenameUserRequest))
return srv.(HeadscaleServiceServer).RenameNamespace(ctx, req.(*RenameNamespaceRequest))
}
return interceptor(ctx, in, info, handler)
}
func _HeadscaleService_DeleteUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteUserRequest)
func _HeadscaleService_DeleteNamespace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteNamespaceRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HeadscaleServiceServer).DeleteUser(ctx, in)
return srv.(HeadscaleServiceServer).DeleteNamespace(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/headscale.v1.HeadscaleService/DeleteUser",
FullMethod: "/headscale.v1.HeadscaleService/DeleteNamespace",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HeadscaleServiceServer).DeleteUser(ctx, req.(*DeleteUserRequest))
return srv.(HeadscaleServiceServer).DeleteNamespace(ctx, req.(*DeleteNamespaceRequest))
}
return interceptor(ctx, in, info, handler)
}
func _HeadscaleService_ListUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListUsersRequest)
func _HeadscaleService_ListNamespaces_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListNamespacesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HeadscaleServiceServer).ListUsers(ctx, in)
return srv.(HeadscaleServiceServer).ListNamespaces(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/headscale.v1.HeadscaleService/ListUsers",
FullMethod: "/headscale.v1.HeadscaleService/ListNamespaces",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HeadscaleServiceServer).ListUsers(ctx, req.(*ListUsersRequest))
return srv.(HeadscaleServiceServer).ListNamespaces(ctx, req.(*ListNamespacesRequest))
}
return interceptor(ctx, in, info, handler)
}
@@ -865,24 +842,24 @@ var HeadscaleService_ServiceDesc = grpc.ServiceDesc{
HandlerType: (*HeadscaleServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetUser",
Handler: _HeadscaleService_GetUser_Handler,
MethodName: "GetNamespace",
Handler: _HeadscaleService_GetNamespace_Handler,
},
{
MethodName: "CreateUser",
Handler: _HeadscaleService_CreateUser_Handler,
MethodName: "CreateNamespace",
Handler: _HeadscaleService_CreateNamespace_Handler,
},
{
MethodName: "RenameUser",
Handler: _HeadscaleService_RenameUser_Handler,
MethodName: "RenameNamespace",
Handler: _HeadscaleService_RenameNamespace_Handler,
},
{
MethodName: "DeleteUser",
Handler: _HeadscaleService_DeleteUser_Handler,
MethodName: "DeleteNamespace",
Handler: _HeadscaleService_DeleteNamespace_Handler,
},
{
MethodName: "ListUsers",
Handler: _HeadscaleService_ListUsers_Handler,
MethodName: "ListNamespaces",
Handler: _HeadscaleService_ListNamespaces_Handler,
},
{
MethodName: "CreatePreAuthKey",

View File

@@ -7,12 +7,11 @@
package v1
import (
reflect "reflect"
sync "sync"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (
@@ -85,7 +84,7 @@ type Machine struct {
DiscoKey string `protobuf:"bytes,4,opt,name=disco_key,json=discoKey,proto3" json:"disco_key,omitempty"`
IpAddresses []string `protobuf:"bytes,5,rep,name=ip_addresses,json=ipAddresses,proto3" json:"ip_addresses,omitempty"`
Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"`
User *User `protobuf:"bytes,7,opt,name=user,proto3" json:"user,omitempty"`
Namespace *Namespace `protobuf:"bytes,7,opt,name=namespace,proto3" json:"namespace,omitempty"`
LastSeen *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=last_seen,json=lastSeen,proto3" json:"last_seen,omitempty"`
LastSuccessfulUpdate *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=last_successful_update,json=lastSuccessfulUpdate,proto3" json:"last_successful_update,omitempty"`
Expiry *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=expiry,proto3" json:"expiry,omitempty"`
@@ -173,9 +172,9 @@ func (x *Machine) GetName() string {
return ""
}
func (x *Machine) GetUser() *User {
func (x *Machine) GetNamespace() *Namespace {
if x != nil {
return x.User
return x.Namespace
}
return nil
}
@@ -262,8 +261,8 @@ type RegisterMachineRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
}
func (x *RegisterMachineRequest) Reset() {
@@ -298,9 +297,9 @@ func (*RegisterMachineRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_machine_proto_rawDescGZIP(), []int{1}
}
func (x *RegisterMachineRequest) GetUser() string {
func (x *RegisterMachineRequest) GetNamespace() string {
if x != nil {
return x.User
return x.Namespace
}
return ""
}
@@ -841,7 +840,7 @@ type ListMachinesRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
}
func (x *ListMachinesRequest) Reset() {
@@ -876,9 +875,9 @@ func (*ListMachinesRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_machine_proto_rawDescGZIP(), []int{13}
}
func (x *ListMachinesRequest) GetUser() string {
func (x *ListMachinesRequest) GetNamespace() string {
if x != nil {
return x.User
return x.Namespace
}
return ""
}
@@ -936,7 +935,7 @@ type MoveMachineRequest struct {
unknownFields protoimpl.UnknownFields
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
User string `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"`
Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"`
}
func (x *MoveMachineRequest) Reset() {
@@ -978,9 +977,9 @@ func (x *MoveMachineRequest) GetMachineId() uint64 {
return 0
}
func (x *MoveMachineRequest) GetUser() string {
func (x *MoveMachineRequest) GetNamespace() string {
if x != nil {
return x.User
return x.Namespace
}
return ""
}
@@ -1037,10 +1036,10 @@ type DebugCreateMachineRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
Routes []string `protobuf:"bytes,4,rep,name=routes,proto3" json:"routes,omitempty"`
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
Routes []string `protobuf:"bytes,4,rep,name=routes,proto3" json:"routes,omitempty"`
}
func (x *DebugCreateMachineRequest) Reset() {
@@ -1075,9 +1074,9 @@ func (*DebugCreateMachineRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_machine_proto_rawDescGZIP(), []int{17}
}
func (x *DebugCreateMachineRequest) GetUser() string {
func (x *DebugCreateMachineRequest) GetNamespace() string {
if x != nil {
return x.User
return x.Namespace
}
return ""
}
@@ -1157,145 +1156,149 @@ var file_headscale_v1_machine_proto_rawDesc = []byte{
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x68, 0x65,
0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x68, 0x65, 0x61,
0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f,
0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0xee, 0x05, 0x0a, 0x07, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12,
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x12,
0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x4b, 0x65, 0x79,
0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01,
0x28, 0x09, 0x52, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x64,
0x69, 0x73, 0x63, 0x6f, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x64, 0x69, 0x73, 0x63, 0x6f, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x70, 0x5f, 0x61,
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b,
0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
0x26, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65,
0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f,
0x73, 0x65, 0x65, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x65, 0x65, 0x6e,
0x12, 0x50, 0x0a, 0x16, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73,
0x66, 0x75, 0x6c, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x14, 0x6c, 0x61,
0x73, 0x74, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x55, 0x70, 0x64, 0x61,
0x74, 0x65, 0x12, 0x32, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x18, 0x0a, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x06,
0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x12, 0x3a, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x5f, 0x61, 0x75,
0x74, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x41,
0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b,
0x65, 0x79, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74,
0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x68, 0x65, 0x61,
0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
0x61, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x68, 0x65, 0x61, 0x64, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b,
0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xfd, 0x05, 0x0a, 0x07, 0x4d, 0x61, 0x63,
0x68, 0x69, 0x6e, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f,
0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69,
0x6e, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6b, 0x65,
0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x4b, 0x65, 0x79,
0x12, 0x1b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20,
0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x0a,
0x0c, 0x69, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x05, 0x20,
0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73,
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63,
0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x09, 0x6c,
0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74,
0x53, 0x65, 0x65, 0x6e, 0x12, 0x50, 0x0a, 0x16, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x75, 0x63,
0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x09,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
0x52, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x32, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79,
0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x45, 0x0a,
0x0f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,
0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x65,
0x74, 0x68, 0x6f, 0x64, 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x65,
0x74, 0x68, 0x6f, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x5f, 0x74,
0x61, 0x67, 0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x6f, 0x72, 0x63, 0x65,
0x64, 0x54, 0x61, 0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64,
0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x13, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x76,
0x61, 0x6c, 0x69, 0x64, 0x54, 0x61, 0x67, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69,
0x64, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x76, 0x61,
0x6c, 0x69, 0x64, 0x54, 0x61, 0x67, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x76, 0x65, 0x6e,
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x69, 0x76,
0x65, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65,
0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x4a, 0x04,
0x08, 0x0e, 0x10, 0x12, 0x22, 0x3e, 0x0a, 0x16, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12,
0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73,
0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x03, 0x6b, 0x65, 0x79, 0x22, 0x4a, 0x0a, 0x17, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x22, 0x32, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65,
0x6d, 0x70, 0x52, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x12, 0x3a, 0x0a, 0x0c, 0x70, 0x72,
0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x18, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x41,
0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
0x64, 0x5f, 0x61, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41,
0x74, 0x12, 0x45, 0x0a, 0x0f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x65,
0x74, 0x68, 0x6f, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
0x65, 0x72, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74,
0x65, 0x72, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x6f, 0x72, 0x63,
0x65, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x66,
0x6f, 0x72, 0x63, 0x65, 0x64, 0x54, 0x61, 0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x76,
0x61, 0x6c, 0x69, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x13, 0x20, 0x03, 0x28, 0x09, 0x52,
0x0b, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x54, 0x61, 0x67, 0x73, 0x12, 0x1d, 0x0a, 0x0a,
0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x09,
0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x54, 0x61, 0x67, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x67,
0x69, 0x76, 0x65, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52,
0x09, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x6e,
0x6c, 0x69, 0x6e, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6f, 0x6e, 0x6c, 0x69,
0x6e, 0x65, 0x4a, 0x04, 0x08, 0x0e, 0x10, 0x12, 0x22, 0x48, 0x0a, 0x16, 0x52, 0x65, 0x67, 0x69,
0x73, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
0x65, 0x79, 0x22, 0x4a, 0x0a, 0x17, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a,
0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x32,
0x0a, 0x11, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x49, 0x64, 0x22, 0x45, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68,
0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x43, 0x0a, 0x0e, 0x53, 0x65, 0x74,
0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61,
0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x22, 0x42,
0x0a, 0x0f, 0x53, 0x65, 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69,
0x6e, 0x65, 0x22, 0x35, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68,
0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09,
0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c,
0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x35, 0x0a, 0x14, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68,
0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09,
0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x22, 0x48, 0x0a, 0x15, 0x45, 0x78, 0x70,
0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e,
0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68,
0x69, 0x6e, 0x65, 0x22, 0x50, 0x0a, 0x14, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4d, 0x61, 0x63,
0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65,
0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65,
0x77, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x48, 0x0a, 0x15, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f,
0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22,
0x33, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73,
0x70, 0x61, 0x63, 0x65, 0x22, 0x49, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68,
0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x08,
0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x22,
0x51, 0x0a, 0x12, 0x4d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69,
0x6e, 0x65, 0x49, 0x64, 0x22, 0x45, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69,
0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65,
0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69,
0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x43, 0x0a, 0x0e, 0x53,
0x65, 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a,
0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04,
0x74, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73,
0x22, 0x42, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65,
0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63,
0x68, 0x69, 0x6e, 0x65, 0x22, 0x35, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a,
0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x44,
0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x0a, 0x14, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a,
0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x22, 0x48, 0x0a, 0x15, 0x45,
0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x50, 0x0a, 0x14, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a,
0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08,
0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
0x6e, 0x65, 0x77, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x48, 0x0a, 0x15, 0x52, 0x65, 0x6e, 0x61, 0x6d,
0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e,
0x65, 0x22, 0x29, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x49, 0x0a, 0x14,
0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73,
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x08, 0x6d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x47, 0x0a, 0x12, 0x4d, 0x6f, 0x76, 0x65, 0x4d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a,
0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04,
0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72,
0x22, 0x46, 0x0a, 0x13, 0x4d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69,
0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52,
0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x6d, 0x0a, 0x19, 0x44, 0x65, 0x62, 0x75,
0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
0x16, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52,
0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0x4d, 0x0a, 0x1a, 0x44, 0x65, 0x62, 0x75, 0x67,
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2a, 0x82, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73,
0x74, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x45, 0x47,
0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x55, 0x4e, 0x53,
0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45,
0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x41, 0x55,
0x54, 0x48, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x47, 0x49,
0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x43, 0x4c, 0x49, 0x10,
0x02, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45,
0x54, 0x48, 0x4f, 0x44, 0x5f, 0x4f, 0x49, 0x44, 0x43, 0x10, 0x03, 0x42, 0x29, 0x5a, 0x27, 0x67,
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x75, 0x61, 0x6e, 0x66, 0x6f,
0x6e, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x67, 0x65, 0x6e,
0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x6e, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
0x63, 0x65, 0x22, 0x46, 0x0a, 0x13, 0x4d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63,
0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x77, 0x0a, 0x19, 0x44, 0x65,
0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73,
0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65,
0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72,
0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x75,
0x74, 0x65, 0x73, 0x22, 0x4d, 0x0a, 0x1a, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61,
0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69,
0x6e, 0x65, 0x2a, 0x82, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d,
0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45,
0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49,
0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54,
0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x4b,
0x45, 0x59, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52,
0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x43, 0x4c, 0x49, 0x10, 0x02, 0x12, 0x18, 0x0a,
0x14, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44,
0x5f, 0x4f, 0x49, 0x44, 0x43, 0x10, 0x03, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x75, 0x61, 0x6e, 0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68,
0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f,
0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -1310,37 +1313,35 @@ func file_headscale_v1_machine_proto_rawDescGZIP() []byte {
return file_headscale_v1_machine_proto_rawDescData
}
var (
file_headscale_v1_machine_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
file_headscale_v1_machine_proto_msgTypes = make([]protoimpl.MessageInfo, 19)
file_headscale_v1_machine_proto_goTypes = []interface{}{
(RegisterMethod)(0), // 0: headscale.v1.RegisterMethod
(*Machine)(nil), // 1: headscale.v1.Machine
(*RegisterMachineRequest)(nil), // 2: headscale.v1.RegisterMachineRequest
(*RegisterMachineResponse)(nil), // 3: headscale.v1.RegisterMachineResponse
(*GetMachineRequest)(nil), // 4: headscale.v1.GetMachineRequest
(*GetMachineResponse)(nil), // 5: headscale.v1.GetMachineResponse
(*SetTagsRequest)(nil), // 6: headscale.v1.SetTagsRequest
(*SetTagsResponse)(nil), // 7: headscale.v1.SetTagsResponse
(*DeleteMachineRequest)(nil), // 8: headscale.v1.DeleteMachineRequest
(*DeleteMachineResponse)(nil), // 9: headscale.v1.DeleteMachineResponse
(*ExpireMachineRequest)(nil), // 10: headscale.v1.ExpireMachineRequest
(*ExpireMachineResponse)(nil), // 11: headscale.v1.ExpireMachineResponse
(*RenameMachineRequest)(nil), // 12: headscale.v1.RenameMachineRequest
(*RenameMachineResponse)(nil), // 13: headscale.v1.RenameMachineResponse
(*ListMachinesRequest)(nil), // 14: headscale.v1.ListMachinesRequest
(*ListMachinesResponse)(nil), // 15: headscale.v1.ListMachinesResponse
(*MoveMachineRequest)(nil), // 16: headscale.v1.MoveMachineRequest
(*MoveMachineResponse)(nil), // 17: headscale.v1.MoveMachineResponse
(*DebugCreateMachineRequest)(nil), // 18: headscale.v1.DebugCreateMachineRequest
(*DebugCreateMachineResponse)(nil), // 19: headscale.v1.DebugCreateMachineResponse
(*User)(nil), // 20: headscale.v1.User
(*timestamppb.Timestamp)(nil), // 21: google.protobuf.Timestamp
(*PreAuthKey)(nil), // 22: headscale.v1.PreAuthKey
}
)
var file_headscale_v1_machine_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_headscale_v1_machine_proto_msgTypes = make([]protoimpl.MessageInfo, 19)
var file_headscale_v1_machine_proto_goTypes = []interface{}{
(RegisterMethod)(0), // 0: headscale.v1.RegisterMethod
(*Machine)(nil), // 1: headscale.v1.Machine
(*RegisterMachineRequest)(nil), // 2: headscale.v1.RegisterMachineRequest
(*RegisterMachineResponse)(nil), // 3: headscale.v1.RegisterMachineResponse
(*GetMachineRequest)(nil), // 4: headscale.v1.GetMachineRequest
(*GetMachineResponse)(nil), // 5: headscale.v1.GetMachineResponse
(*SetTagsRequest)(nil), // 6: headscale.v1.SetTagsRequest
(*SetTagsResponse)(nil), // 7: headscale.v1.SetTagsResponse
(*DeleteMachineRequest)(nil), // 8: headscale.v1.DeleteMachineRequest
(*DeleteMachineResponse)(nil), // 9: headscale.v1.DeleteMachineResponse
(*ExpireMachineRequest)(nil), // 10: headscale.v1.ExpireMachineRequest
(*ExpireMachineResponse)(nil), // 11: headscale.v1.ExpireMachineResponse
(*RenameMachineRequest)(nil), // 12: headscale.v1.RenameMachineRequest
(*RenameMachineResponse)(nil), // 13: headscale.v1.RenameMachineResponse
(*ListMachinesRequest)(nil), // 14: headscale.v1.ListMachinesRequest
(*ListMachinesResponse)(nil), // 15: headscale.v1.ListMachinesResponse
(*MoveMachineRequest)(nil), // 16: headscale.v1.MoveMachineRequest
(*MoveMachineResponse)(nil), // 17: headscale.v1.MoveMachineResponse
(*DebugCreateMachineRequest)(nil), // 18: headscale.v1.DebugCreateMachineRequest
(*DebugCreateMachineResponse)(nil), // 19: headscale.v1.DebugCreateMachineResponse
(*Namespace)(nil), // 20: headscale.v1.Namespace
(*timestamppb.Timestamp)(nil), // 21: google.protobuf.Timestamp
(*PreAuthKey)(nil), // 22: headscale.v1.PreAuthKey
}
var file_headscale_v1_machine_proto_depIdxs = []int32{
20, // 0: headscale.v1.Machine.user:type_name -> headscale.v1.User
20, // 0: headscale.v1.Machine.namespace:type_name -> headscale.v1.Namespace
21, // 1: headscale.v1.Machine.last_seen:type_name -> google.protobuf.Timestamp
21, // 2: headscale.v1.Machine.last_successful_update:type_name -> google.protobuf.Timestamp
21, // 3: headscale.v1.Machine.expiry:type_name -> google.protobuf.Timestamp
@@ -1367,7 +1368,7 @@ func file_headscale_v1_machine_proto_init() {
if File_headscale_v1_machine_proto != nil {
return
}
file_headscale_v1_user_proto_init()
file_headscale_v1_namespace_proto_init()
file_headscale_v1_preauthkey_proto_init()
if !protoimpl.UnsafeEnabled {
file_headscale_v1_machine_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {

View File

@@ -0,0 +1,801 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc (unknown)
// source: headscale/v1/namespace.proto
package v1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Namespace struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
}
func (x *Namespace) Reset() {
*x = Namespace{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_namespace_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Namespace) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Namespace) ProtoMessage() {}
func (x *Namespace) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_namespace_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Namespace.ProtoReflect.Descriptor instead.
func (*Namespace) Descriptor() ([]byte, []int) {
return file_headscale_v1_namespace_proto_rawDescGZIP(), []int{0}
}
func (x *Namespace) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *Namespace) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *Namespace) GetCreatedAt() *timestamppb.Timestamp {
if x != nil {
return x.CreatedAt
}
return nil
}
type GetNamespaceRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
}
func (x *GetNamespaceRequest) Reset() {
*x = GetNamespaceRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_namespace_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetNamespaceRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetNamespaceRequest) ProtoMessage() {}
func (x *GetNamespaceRequest) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_namespace_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetNamespaceRequest.ProtoReflect.Descriptor instead.
func (*GetNamespaceRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_namespace_proto_rawDescGZIP(), []int{1}
}
func (x *GetNamespaceRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type GetNamespaceResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Namespace *Namespace `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
}
func (x *GetNamespaceResponse) Reset() {
*x = GetNamespaceResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_namespace_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetNamespaceResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetNamespaceResponse) ProtoMessage() {}
func (x *GetNamespaceResponse) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_namespace_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetNamespaceResponse.ProtoReflect.Descriptor instead.
func (*GetNamespaceResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_namespace_proto_rawDescGZIP(), []int{2}
}
func (x *GetNamespaceResponse) GetNamespace() *Namespace {
if x != nil {
return x.Namespace
}
return nil
}
type CreateNamespaceRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
}
func (x *CreateNamespaceRequest) Reset() {
*x = CreateNamespaceRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_namespace_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CreateNamespaceRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateNamespaceRequest) ProtoMessage() {}
func (x *CreateNamespaceRequest) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_namespace_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreateNamespaceRequest.ProtoReflect.Descriptor instead.
func (*CreateNamespaceRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_namespace_proto_rawDescGZIP(), []int{3}
}
func (x *CreateNamespaceRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type CreateNamespaceResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Namespace *Namespace `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
}
func (x *CreateNamespaceResponse) Reset() {
*x = CreateNamespaceResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_namespace_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CreateNamespaceResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateNamespaceResponse) ProtoMessage() {}
func (x *CreateNamespaceResponse) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_namespace_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreateNamespaceResponse.ProtoReflect.Descriptor instead.
func (*CreateNamespaceResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_namespace_proto_rawDescGZIP(), []int{4}
}
func (x *CreateNamespaceResponse) GetNamespace() *Namespace {
if x != nil {
return x.Namespace
}
return nil
}
type RenameNamespaceRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
OldName string `protobuf:"bytes,1,opt,name=old_name,json=oldName,proto3" json:"old_name,omitempty"`
NewName string `protobuf:"bytes,2,opt,name=new_name,json=newName,proto3" json:"new_name,omitempty"`
}
func (x *RenameNamespaceRequest) Reset() {
*x = RenameNamespaceRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_namespace_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RenameNamespaceRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RenameNamespaceRequest) ProtoMessage() {}
func (x *RenameNamespaceRequest) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_namespace_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RenameNamespaceRequest.ProtoReflect.Descriptor instead.
func (*RenameNamespaceRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_namespace_proto_rawDescGZIP(), []int{5}
}
func (x *RenameNamespaceRequest) GetOldName() string {
if x != nil {
return x.OldName
}
return ""
}
func (x *RenameNamespaceRequest) GetNewName() string {
if x != nil {
return x.NewName
}
return ""
}
type RenameNamespaceResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Namespace *Namespace `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
}
func (x *RenameNamespaceResponse) Reset() {
*x = RenameNamespaceResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_namespace_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RenameNamespaceResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RenameNamespaceResponse) ProtoMessage() {}
func (x *RenameNamespaceResponse) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_namespace_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RenameNamespaceResponse.ProtoReflect.Descriptor instead.
func (*RenameNamespaceResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_namespace_proto_rawDescGZIP(), []int{6}
}
func (x *RenameNamespaceResponse) GetNamespace() *Namespace {
if x != nil {
return x.Namespace
}
return nil
}
type DeleteNamespaceRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
}
func (x *DeleteNamespaceRequest) Reset() {
*x = DeleteNamespaceRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_namespace_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteNamespaceRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteNamespaceRequest) ProtoMessage() {}
func (x *DeleteNamespaceRequest) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_namespace_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeleteNamespaceRequest.ProtoReflect.Descriptor instead.
func (*DeleteNamespaceRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_namespace_proto_rawDescGZIP(), []int{7}
}
func (x *DeleteNamespaceRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type DeleteNamespaceResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *DeleteNamespaceResponse) Reset() {
*x = DeleteNamespaceResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_namespace_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteNamespaceResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteNamespaceResponse) ProtoMessage() {}
func (x *DeleteNamespaceResponse) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_namespace_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeleteNamespaceResponse.ProtoReflect.Descriptor instead.
func (*DeleteNamespaceResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_namespace_proto_rawDescGZIP(), []int{8}
}
type ListNamespacesRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *ListNamespacesRequest) Reset() {
*x = ListNamespacesRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_namespace_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ListNamespacesRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListNamespacesRequest) ProtoMessage() {}
func (x *ListNamespacesRequest) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_namespace_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListNamespacesRequest.ProtoReflect.Descriptor instead.
func (*ListNamespacesRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_namespace_proto_rawDescGZIP(), []int{9}
}
type ListNamespacesResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Namespaces []*Namespace `protobuf:"bytes,1,rep,name=namespaces,proto3" json:"namespaces,omitempty"`
}
func (x *ListNamespacesResponse) Reset() {
*x = ListNamespacesResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_namespace_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ListNamespacesResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListNamespacesResponse) ProtoMessage() {}
func (x *ListNamespacesResponse) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_namespace_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListNamespacesResponse.ProtoReflect.Descriptor instead.
func (*ListNamespacesResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_namespace_proto_rawDescGZIP(), []int{10}
}
func (x *ListNamespacesResponse) GetNamespaces() []*Namespace {
if x != nil {
return x.Namespaces
}
return nil
}
var File_headscale_v1_namespace_proto protoreflect.FileDescriptor
var file_headscale_v1_namespace_proto_rawDesc = []byte{
0x0a, 0x1c, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x6e,
0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c,
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6a, 0x0a,
0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39,
0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09,
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x29, 0x0a, 0x13, 0x47, 0x65, 0x74,
0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x22, 0x4d, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73,
0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x09,
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x17, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e,
0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
0x61, 0x63, 0x65, 0x22, 0x2c, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d,
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
0x65, 0x22, 0x50, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73,
0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x09,
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x17, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e,
0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
0x61, 0x63, 0x65, 0x22, 0x4e, 0x0a, 0x16, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4e, 0x61, 0x6d,
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a,
0x08, 0x6f, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x07, 0x6f, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x4e,
0x61, 0x6d, 0x65, 0x22, 0x50, 0x0a, 0x17, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4e, 0x61, 0x6d,
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35,
0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x17, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65,
0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e,
0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x22, 0x19, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x61, 0x6d,
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17,
0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x51, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x4e,
0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x37, 0x0a, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x0a,
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69,
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x75, 0x61, 0x6e, 0x66, 0x6f, 0x6e,
0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f,
0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_headscale_v1_namespace_proto_rawDescOnce sync.Once
file_headscale_v1_namespace_proto_rawDescData = file_headscale_v1_namespace_proto_rawDesc
)
func file_headscale_v1_namespace_proto_rawDescGZIP() []byte {
file_headscale_v1_namespace_proto_rawDescOnce.Do(func() {
file_headscale_v1_namespace_proto_rawDescData = protoimpl.X.CompressGZIP(file_headscale_v1_namespace_proto_rawDescData)
})
return file_headscale_v1_namespace_proto_rawDescData
}
var file_headscale_v1_namespace_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_headscale_v1_namespace_proto_goTypes = []interface{}{
(*Namespace)(nil), // 0: headscale.v1.Namespace
(*GetNamespaceRequest)(nil), // 1: headscale.v1.GetNamespaceRequest
(*GetNamespaceResponse)(nil), // 2: headscale.v1.GetNamespaceResponse
(*CreateNamespaceRequest)(nil), // 3: headscale.v1.CreateNamespaceRequest
(*CreateNamespaceResponse)(nil), // 4: headscale.v1.CreateNamespaceResponse
(*RenameNamespaceRequest)(nil), // 5: headscale.v1.RenameNamespaceRequest
(*RenameNamespaceResponse)(nil), // 6: headscale.v1.RenameNamespaceResponse
(*DeleteNamespaceRequest)(nil), // 7: headscale.v1.DeleteNamespaceRequest
(*DeleteNamespaceResponse)(nil), // 8: headscale.v1.DeleteNamespaceResponse
(*ListNamespacesRequest)(nil), // 9: headscale.v1.ListNamespacesRequest
(*ListNamespacesResponse)(nil), // 10: headscale.v1.ListNamespacesResponse
(*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp
}
var file_headscale_v1_namespace_proto_depIdxs = []int32{
11, // 0: headscale.v1.Namespace.created_at:type_name -> google.protobuf.Timestamp
0, // 1: headscale.v1.GetNamespaceResponse.namespace:type_name -> headscale.v1.Namespace
0, // 2: headscale.v1.CreateNamespaceResponse.namespace:type_name -> headscale.v1.Namespace
0, // 3: headscale.v1.RenameNamespaceResponse.namespace:type_name -> headscale.v1.Namespace
0, // 4: headscale.v1.ListNamespacesResponse.namespaces:type_name -> headscale.v1.Namespace
5, // [5:5] is the sub-list for method output_type
5, // [5:5] is the sub-list for method input_type
5, // [5:5] is the sub-list for extension type_name
5, // [5:5] is the sub-list for extension extendee
0, // [0:5] is the sub-list for field type_name
}
func init() { file_headscale_v1_namespace_proto_init() }
func file_headscale_v1_namespace_proto_init() {
if File_headscale_v1_namespace_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_headscale_v1_namespace_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Namespace); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_namespace_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetNamespaceRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_namespace_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetNamespaceResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_namespace_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateNamespaceRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_namespace_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateNamespaceResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_namespace_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RenameNamespaceRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_namespace_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RenameNamespaceResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_namespace_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteNamespaceRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_namespace_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteNamespaceResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_namespace_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListNamespacesRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_namespace_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListNamespacesResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_headscale_v1_namespace_proto_rawDesc,
NumEnums: 0,
NumMessages: 11,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_headscale_v1_namespace_proto_goTypes,
DependencyIndexes: file_headscale_v1_namespace_proto_depIdxs,
MessageInfos: file_headscale_v1_namespace_proto_msgTypes,
}.Build()
File_headscale_v1_namespace_proto = out.File
file_headscale_v1_namespace_proto_rawDesc = nil
file_headscale_v1_namespace_proto_goTypes = nil
file_headscale_v1_namespace_proto_depIdxs = nil
}

View File

@@ -7,12 +7,11 @@
package v1
import (
reflect "reflect"
sync "sync"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (
@@ -27,7 +26,7 @@ type PreAuthKey struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
Key string `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"`
Reusable bool `protobuf:"varint,4,opt,name=reusable,proto3" json:"reusable,omitempty"`
@@ -70,9 +69,9 @@ func (*PreAuthKey) Descriptor() ([]byte, []int) {
return file_headscale_v1_preauthkey_proto_rawDescGZIP(), []int{0}
}
func (x *PreAuthKey) GetUser() string {
func (x *PreAuthKey) GetNamespace() string {
if x != nil {
return x.User
return x.Namespace
}
return ""
}
@@ -138,7 +137,7 @@ type CreatePreAuthKeyRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
Reusable bool `protobuf:"varint,2,opt,name=reusable,proto3" json:"reusable,omitempty"`
Ephemeral bool `protobuf:"varint,3,opt,name=ephemeral,proto3" json:"ephemeral,omitempty"`
Expiration *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=expiration,proto3" json:"expiration,omitempty"`
@@ -177,9 +176,9 @@ func (*CreatePreAuthKeyRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_preauthkey_proto_rawDescGZIP(), []int{1}
}
func (x *CreatePreAuthKeyRequest) GetUser() string {
func (x *CreatePreAuthKeyRequest) GetNamespace() string {
if x != nil {
return x.User
return x.Namespace
}
return ""
}
@@ -264,8 +263,8 @@ type ExpirePreAuthKeyRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
}
func (x *ExpirePreAuthKeyRequest) Reset() {
@@ -300,9 +299,9 @@ func (*ExpirePreAuthKeyRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_preauthkey_proto_rawDescGZIP(), []int{3}
}
func (x *ExpirePreAuthKeyRequest) GetUser() string {
func (x *ExpirePreAuthKeyRequest) GetNamespace() string {
if x != nil {
return x.User
return x.Namespace
}
return ""
}
@@ -357,7 +356,7 @@ type ListPreAuthKeysRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
}
func (x *ListPreAuthKeysRequest) Reset() {
@@ -392,9 +391,9 @@ func (*ListPreAuthKeysRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_preauthkey_proto_rawDescGZIP(), []int{5}
}
func (x *ListPreAuthKeysRequest) GetUser() string {
func (x *ListPreAuthKeysRequest) GetNamespace() string {
if x != nil {
return x.User
return x.Namespace
}
return ""
}
@@ -453,61 +452,63 @@ var file_headscale_v1_preauthkey_proto_rawDesc = []byte{
0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x0c, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74,
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa2,
0x02, 0x0a, 0x0a, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a,
0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, 0x65,
0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x75, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x18,
0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x75, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x12,
0x1c, 0x0a, 0x09, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01,
0x28, 0x08, 0x52, 0x09, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x12, 0x0a,
0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x75, 0x73, 0x65,
0x64, 0x12, 0x3a, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xac,
0x02, 0x0a, 0x0a, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a,
0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69,
0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b,
0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a,
0x08, 0x72, 0x65, 0x75, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52,
0x08, 0x72, 0x65, 0x75, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x70, 0x68,
0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x70,
0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18,
0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x75, 0x73, 0x65, 0x64, 0x12, 0x3a, 0x0a, 0x0a, 0x65,
0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70,
0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74,
0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x41, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x63, 0x6c, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x09,
0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x6c, 0x54, 0x61, 0x67, 0x73, 0x22, 0xc8, 0x01,
0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b,
0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d,
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61,
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x75, 0x73, 0x61,
0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x75, 0x73, 0x61,
0x62, 0x6c, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c,
0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61,
0x6c, 0x12, 0x3a, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a,
0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63,
0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x63, 0x6c, 0x5f,
0x74, 0x61, 0x67, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x6c, 0x54,
0x61, 0x67, 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72,
0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75,
0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x75, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x75, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x12,
0x1c, 0x0a, 0x09, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01,
0x28, 0x08, 0x52, 0x09, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x3a, 0x0a,
0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65,
0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x63, 0x6c,
0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x6c,
0x54, 0x61, 0x67, 0x73, 0x22, 0x56, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72,
0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x3a, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6b, 0x65, 0x79,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79,
0x52, 0x0a, 0x70, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x22, 0x3f, 0x0a, 0x17,
0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b,
0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x1a, 0x0a,
0x18, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65,
0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x0a, 0x16, 0x4c, 0x69, 0x73,
0x74, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x57, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x50,
0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x3c, 0x0a, 0x0d, 0x70, 0x72, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6b,
0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68,
0x4b, 0x65, 0x79, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73,
0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a,
0x75, 0x61, 0x6e, 0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a,
0x08, 0x61, 0x63, 0x6c, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52,
0x07, 0x61, 0x63, 0x6c, 0x54, 0x61, 0x67, 0x73, 0x22, 0x56, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61,
0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68,
0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74,
0x68, 0x4b, 0x65, 0x79, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79,
0x22, 0x49, 0x0a, 0x17, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74,
0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e,
0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x1a, 0x0a, 0x18, 0x45,
0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x50,
0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22,
0x57, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65,
0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x0d, 0x70, 0x72,
0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x18, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
0x2e, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x0b, 0x70, 0x72, 0x65,
0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68,
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x75, 0x61, 0x6e, 0x66, 0x6f, 0x6e, 0x74, 0x2f,
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f,
0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -522,19 +523,17 @@ func file_headscale_v1_preauthkey_proto_rawDescGZIP() []byte {
return file_headscale_v1_preauthkey_proto_rawDescData
}
var (
file_headscale_v1_preauthkey_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
file_headscale_v1_preauthkey_proto_goTypes = []interface{}{
(*PreAuthKey)(nil), // 0: headscale.v1.PreAuthKey
(*CreatePreAuthKeyRequest)(nil), // 1: headscale.v1.CreatePreAuthKeyRequest
(*CreatePreAuthKeyResponse)(nil), // 2: headscale.v1.CreatePreAuthKeyResponse
(*ExpirePreAuthKeyRequest)(nil), // 3: headscale.v1.ExpirePreAuthKeyRequest
(*ExpirePreAuthKeyResponse)(nil), // 4: headscale.v1.ExpirePreAuthKeyResponse
(*ListPreAuthKeysRequest)(nil), // 5: headscale.v1.ListPreAuthKeysRequest
(*ListPreAuthKeysResponse)(nil), // 6: headscale.v1.ListPreAuthKeysResponse
(*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp
}
)
var file_headscale_v1_preauthkey_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_headscale_v1_preauthkey_proto_goTypes = []interface{}{
(*PreAuthKey)(nil), // 0: headscale.v1.PreAuthKey
(*CreatePreAuthKeyRequest)(nil), // 1: headscale.v1.CreatePreAuthKeyRequest
(*CreatePreAuthKeyResponse)(nil), // 2: headscale.v1.CreatePreAuthKeyResponse
(*ExpirePreAuthKeyRequest)(nil), // 3: headscale.v1.ExpirePreAuthKeyRequest
(*ExpirePreAuthKeyResponse)(nil), // 4: headscale.v1.ExpirePreAuthKeyResponse
(*ListPreAuthKeysRequest)(nil), // 5: headscale.v1.ListPreAuthKeysRequest
(*ListPreAuthKeysResponse)(nil), // 6: headscale.v1.ListPreAuthKeysResponse
(*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp
}
var file_headscale_v1_preauthkey_proto_depIdxs = []int32{
7, // 0: headscale.v1.PreAuthKey.expiration:type_name -> google.protobuf.Timestamp
7, // 1: headscale.v1.PreAuthKey.created_at:type_name -> google.protobuf.Timestamp

View File

@@ -7,12 +7,11 @@
package v1
import (
reflect "reflect"
sync "sync"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (
@@ -555,22 +554,20 @@ func file_headscale_v1_routes_proto_rawDescGZIP() []byte {
return file_headscale_v1_routes_proto_rawDescData
}
var (
file_headscale_v1_routes_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
file_headscale_v1_routes_proto_goTypes = []interface{}{
(*Route)(nil), // 0: headscale.v1.Route
(*GetRoutesRequest)(nil), // 1: headscale.v1.GetRoutesRequest
(*GetRoutesResponse)(nil), // 2: headscale.v1.GetRoutesResponse
(*EnableRouteRequest)(nil), // 3: headscale.v1.EnableRouteRequest
(*EnableRouteResponse)(nil), // 4: headscale.v1.EnableRouteResponse
(*DisableRouteRequest)(nil), // 5: headscale.v1.DisableRouteRequest
(*DisableRouteResponse)(nil), // 6: headscale.v1.DisableRouteResponse
(*GetMachineRoutesRequest)(nil), // 7: headscale.v1.GetMachineRoutesRequest
(*GetMachineRoutesResponse)(nil), // 8: headscale.v1.GetMachineRoutesResponse
(*Machine)(nil), // 9: headscale.v1.Machine
(*timestamppb.Timestamp)(nil), // 10: google.protobuf.Timestamp
}
)
var file_headscale_v1_routes_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
var file_headscale_v1_routes_proto_goTypes = []interface{}{
(*Route)(nil), // 0: headscale.v1.Route
(*GetRoutesRequest)(nil), // 1: headscale.v1.GetRoutesRequest
(*GetRoutesResponse)(nil), // 2: headscale.v1.GetRoutesResponse
(*EnableRouteRequest)(nil), // 3: headscale.v1.EnableRouteRequest
(*EnableRouteResponse)(nil), // 4: headscale.v1.EnableRouteResponse
(*DisableRouteRequest)(nil), // 5: headscale.v1.DisableRouteRequest
(*DisableRouteResponse)(nil), // 6: headscale.v1.DisableRouteResponse
(*GetMachineRoutesRequest)(nil), // 7: headscale.v1.GetMachineRoutesRequest
(*GetMachineRoutesResponse)(nil), // 8: headscale.v1.GetMachineRoutesResponse
(*Machine)(nil), // 9: headscale.v1.Machine
(*timestamppb.Timestamp)(nil), // 10: google.protobuf.Timestamp
}
var file_headscale_v1_routes_proto_depIdxs = []int32{
9, // 0: headscale.v1.Route.machine:type_name -> headscale.v1.Machine
10, // 1: headscale.v1.Route.created_at:type_name -> google.protobuf.Timestamp

View File

@@ -1,797 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc (unknown)
// source: headscale/v1/user.proto
package v1
import (
reflect "reflect"
sync "sync"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type User struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
}
func (x *User) Reset() {
*x = User{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_user_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *User) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*User) ProtoMessage() {}
func (x *User) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_user_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use User.ProtoReflect.Descriptor instead.
func (*User) Descriptor() ([]byte, []int) {
return file_headscale_v1_user_proto_rawDescGZIP(), []int{0}
}
func (x *User) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *User) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *User) GetCreatedAt() *timestamppb.Timestamp {
if x != nil {
return x.CreatedAt
}
return nil
}
type GetUserRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
}
func (x *GetUserRequest) Reset() {
*x = GetUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_user_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetUserRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetUserRequest) ProtoMessage() {}
func (x *GetUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_user_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetUserRequest.ProtoReflect.Descriptor instead.
func (*GetUserRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_user_proto_rawDescGZIP(), []int{1}
}
func (x *GetUserRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type GetUserResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
}
func (x *GetUserResponse) Reset() {
*x = GetUserResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_user_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetUserResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetUserResponse) ProtoMessage() {}
func (x *GetUserResponse) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_user_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetUserResponse.ProtoReflect.Descriptor instead.
func (*GetUserResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_user_proto_rawDescGZIP(), []int{2}
}
func (x *GetUserResponse) GetUser() *User {
if x != nil {
return x.User
}
return nil
}
type CreateUserRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
}
func (x *CreateUserRequest) Reset() {
*x = CreateUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_user_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CreateUserRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateUserRequest) ProtoMessage() {}
func (x *CreateUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_user_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreateUserRequest.ProtoReflect.Descriptor instead.
func (*CreateUserRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_user_proto_rawDescGZIP(), []int{3}
}
func (x *CreateUserRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type CreateUserResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
}
func (x *CreateUserResponse) Reset() {
*x = CreateUserResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_user_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CreateUserResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateUserResponse) ProtoMessage() {}
func (x *CreateUserResponse) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_user_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreateUserResponse.ProtoReflect.Descriptor instead.
func (*CreateUserResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_user_proto_rawDescGZIP(), []int{4}
}
func (x *CreateUserResponse) GetUser() *User {
if x != nil {
return x.User
}
return nil
}
type RenameUserRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
OldName string `protobuf:"bytes,1,opt,name=old_name,json=oldName,proto3" json:"old_name,omitempty"`
NewName string `protobuf:"bytes,2,opt,name=new_name,json=newName,proto3" json:"new_name,omitempty"`
}
func (x *RenameUserRequest) Reset() {
*x = RenameUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_user_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RenameUserRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RenameUserRequest) ProtoMessage() {}
func (x *RenameUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_user_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RenameUserRequest.ProtoReflect.Descriptor instead.
func (*RenameUserRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_user_proto_rawDescGZIP(), []int{5}
}
func (x *RenameUserRequest) GetOldName() string {
if x != nil {
return x.OldName
}
return ""
}
func (x *RenameUserRequest) GetNewName() string {
if x != nil {
return x.NewName
}
return ""
}
type RenameUserResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
}
func (x *RenameUserResponse) Reset() {
*x = RenameUserResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_user_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RenameUserResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RenameUserResponse) ProtoMessage() {}
func (x *RenameUserResponse) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_user_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RenameUserResponse.ProtoReflect.Descriptor instead.
func (*RenameUserResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_user_proto_rawDescGZIP(), []int{6}
}
func (x *RenameUserResponse) GetUser() *User {
if x != nil {
return x.User
}
return nil
}
type DeleteUserRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
}
func (x *DeleteUserRequest) Reset() {
*x = DeleteUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_user_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteUserRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteUserRequest) ProtoMessage() {}
func (x *DeleteUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_user_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeleteUserRequest.ProtoReflect.Descriptor instead.
func (*DeleteUserRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_user_proto_rawDescGZIP(), []int{7}
}
func (x *DeleteUserRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type DeleteUserResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *DeleteUserResponse) Reset() {
*x = DeleteUserResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_user_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteUserResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteUserResponse) ProtoMessage() {}
func (x *DeleteUserResponse) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_user_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeleteUserResponse.ProtoReflect.Descriptor instead.
func (*DeleteUserResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_user_proto_rawDescGZIP(), []int{8}
}
type ListUsersRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *ListUsersRequest) Reset() {
*x = ListUsersRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_user_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ListUsersRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListUsersRequest) ProtoMessage() {}
func (x *ListUsersRequest) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_user_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListUsersRequest.ProtoReflect.Descriptor instead.
func (*ListUsersRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_user_proto_rawDescGZIP(), []int{9}
}
type ListUsersResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Users []*User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"`
}
func (x *ListUsersResponse) Reset() {
*x = ListUsersResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_user_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ListUsersResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListUsersResponse) ProtoMessage() {}
func (x *ListUsersResponse) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_user_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListUsersResponse.ProtoReflect.Descriptor instead.
func (*ListUsersResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_user_proto_rawDescGZIP(), []int{10}
}
func (x *ListUsersResponse) GetUsers() []*User {
if x != nil {
return x.Users
}
return nil
}
var File_headscale_v1_user_proto protoreflect.FileDescriptor
var file_headscale_v1_user_proto_rawDesc = []byte{
0x0a, 0x17, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x75,
0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x65, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f,
0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22,
0x24, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x39, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72,
0x22, 0x27, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3c, 0x0a, 0x12, 0x43, 0x72, 0x65,
0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x26, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65,
0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x49, 0x0a, 0x11, 0x52, 0x65, 0x6e, 0x61, 0x6d,
0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08,
0x6f, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
0x6f, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x4e, 0x61,
0x6d, 0x65, 0x22, 0x3c, 0x0a, 0x12, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x72,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72,
0x22, 0x27, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x14, 0x0a, 0x12, 0x44, 0x65, 0x6c,
0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x12, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x22, 0x3d, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72,
0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63,
0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65,
0x72, 0x73, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x6a, 0x75, 0x61, 0x6e, 0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63,
0x61, 0x6c, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_headscale_v1_user_proto_rawDescOnce sync.Once
file_headscale_v1_user_proto_rawDescData = file_headscale_v1_user_proto_rawDesc
)
func file_headscale_v1_user_proto_rawDescGZIP() []byte {
file_headscale_v1_user_proto_rawDescOnce.Do(func() {
file_headscale_v1_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_headscale_v1_user_proto_rawDescData)
})
return file_headscale_v1_user_proto_rawDescData
}
var (
file_headscale_v1_user_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
file_headscale_v1_user_proto_goTypes = []interface{}{
(*User)(nil), // 0: headscale.v1.User
(*GetUserRequest)(nil), // 1: headscale.v1.GetUserRequest
(*GetUserResponse)(nil), // 2: headscale.v1.GetUserResponse
(*CreateUserRequest)(nil), // 3: headscale.v1.CreateUserRequest
(*CreateUserResponse)(nil), // 4: headscale.v1.CreateUserResponse
(*RenameUserRequest)(nil), // 5: headscale.v1.RenameUserRequest
(*RenameUserResponse)(nil), // 6: headscale.v1.RenameUserResponse
(*DeleteUserRequest)(nil), // 7: headscale.v1.DeleteUserRequest
(*DeleteUserResponse)(nil), // 8: headscale.v1.DeleteUserResponse
(*ListUsersRequest)(nil), // 9: headscale.v1.ListUsersRequest
(*ListUsersResponse)(nil), // 10: headscale.v1.ListUsersResponse
(*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp
}
)
var file_headscale_v1_user_proto_depIdxs = []int32{
11, // 0: headscale.v1.User.created_at:type_name -> google.protobuf.Timestamp
0, // 1: headscale.v1.GetUserResponse.user:type_name -> headscale.v1.User
0, // 2: headscale.v1.CreateUserResponse.user:type_name -> headscale.v1.User
0, // 3: headscale.v1.RenameUserResponse.user:type_name -> headscale.v1.User
0, // 4: headscale.v1.ListUsersResponse.users:type_name -> headscale.v1.User
5, // [5:5] is the sub-list for method output_type
5, // [5:5] is the sub-list for method input_type
5, // [5:5] is the sub-list for extension type_name
5, // [5:5] is the sub-list for extension extendee
0, // [0:5] is the sub-list for field type_name
}
func init() { file_headscale_v1_user_proto_init() }
func file_headscale_v1_user_proto_init() {
if File_headscale_v1_user_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_headscale_v1_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*User); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetUserRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_user_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetUserResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_user_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateUserRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_user_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateUserResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_user_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RenameUserRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_user_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RenameUserResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_user_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteUserRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_user_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteUserResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_user_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListUsersRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_user_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListUsersResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_headscale_v1_user_proto_rawDesc,
NumEnums: 0,
NumMessages: 11,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_headscale_v1_user_proto_goTypes,
DependencyIndexes: file_headscale_v1_user_proto_depIdxs,
MessageInfos: file_headscale_v1_user_proto_msgTypes,
}.Build()
File_headscale_v1_user_proto = out.File
file_headscale_v1_user_proto_rawDesc = nil
file_headscale_v1_user_proto_goTypes = nil
file_headscale_v1_user_proto_depIdxs = nil
}

View File

@@ -153,7 +153,7 @@
},
"parameters": [
{
"name": "user",
"name": "namespace",
"in": "query",
"required": false,
"type": "string"
@@ -183,7 +183,7 @@
},
"parameters": [
{
"name": "user",
"name": "namespace",
"in": "query",
"required": false,
"type": "string"
@@ -291,6 +291,43 @@
]
}
},
"/api/v1/machine/{machineId}/namespace": {
"post": {
"operationId": "HeadscaleService_MoveMachine",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1MoveMachineResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "machineId",
"in": "path",
"required": true,
"type": "string",
"format": "uint64"
},
{
"name": "namespace",
"in": "query",
"required": false,
"type": "string"
}
],
"tags": [
"HeadscaleService"
]
}
},
"/api/v1/machine/{machineId}/rename/{newName}": {
"post": {
"operationId": "HeadscaleService_RenameMachine",
@@ -406,14 +443,34 @@
]
}
},
"/api/v1/machine/{machineId}/user": {
"post": {
"operationId": "HeadscaleService_MoveMachine",
"/api/v1/namespace": {
"get": {
"operationId": "HeadscaleService_ListNamespaces",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1MoveMachineResponse"
"$ref": "#/definitions/v1ListNamespacesResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"tags": [
"HeadscaleService"
]
},
"post": {
"operationId": "HeadscaleService_CreateNamespace",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1CreateNamespaceResponse"
}
},
"default": {
@@ -425,16 +482,106 @@
},
"parameters": [
{
"name": "machineId",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/v1CreateNamespaceRequest"
}
}
],
"tags": [
"HeadscaleService"
]
}
},
"/api/v1/namespace/{name}": {
"get": {
"summary": "--- Namespace start ---",
"operationId": "HeadscaleService_GetNamespace",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1GetNamespaceResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "name",
"in": "path",
"required": true,
"type": "string",
"format": "uint64"
"type": "string"
}
],
"tags": [
"HeadscaleService"
]
},
"delete": {
"operationId": "HeadscaleService_DeleteNamespace",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1DeleteNamespaceResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "name",
"in": "path",
"required": true,
"type": "string"
}
],
"tags": [
"HeadscaleService"
]
}
},
"/api/v1/namespace/{oldName}/rename/{newName}": {
"post": {
"operationId": "HeadscaleService_RenameNamespace",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1RenameNamespaceResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "oldName",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "user",
"in": "query",
"required": false,
"name": "newName",
"in": "path",
"required": true,
"type": "string"
}
],
@@ -462,7 +609,7 @@
},
"parameters": [
{
"name": "user",
"name": "namespace",
"in": "query",
"required": false,
"type": "string"
@@ -620,153 +767,6 @@
"HeadscaleService"
]
}
},
"/api/v1/user": {
"get": {
"operationId": "HeadscaleService_ListUsers",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1ListUsersResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"tags": [
"HeadscaleService"
]
},
"post": {
"operationId": "HeadscaleService_CreateUser",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1CreateUserResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/v1CreateUserRequest"
}
}
],
"tags": [
"HeadscaleService"
]
}
},
"/api/v1/user/{name}": {
"get": {
"summary": "--- User start ---",
"operationId": "HeadscaleService_GetUser",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1GetUserResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "name",
"in": "path",
"required": true,
"type": "string"
}
],
"tags": [
"HeadscaleService"
]
},
"delete": {
"operationId": "HeadscaleService_DeleteUser",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1DeleteUserResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "name",
"in": "path",
"required": true,
"type": "string"
}
],
"tags": [
"HeadscaleService"
]
}
},
"/api/v1/user/{oldName}/rename/{newName}": {
"post": {
"operationId": "HeadscaleService_RenameUser",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1RenameUserResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "oldName",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "newName",
"in": "path",
"required": true,
"type": "string"
}
],
"tags": [
"HeadscaleService"
]
}
}
},
"definitions": {
@@ -838,10 +838,26 @@
}
}
},
"v1CreateNamespaceRequest": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
},
"v1CreateNamespaceResponse": {
"type": "object",
"properties": {
"namespace": {
"$ref": "#/definitions/v1Namespace"
}
}
},
"v1CreatePreAuthKeyRequest": {
"type": "object",
"properties": {
"user": {
"namespace": {
"type": "string"
},
"reusable": {
@@ -870,26 +886,10 @@
}
}
},
"v1CreateUserRequest": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
},
"v1CreateUserResponse": {
"type": "object",
"properties": {
"user": {
"$ref": "#/definitions/v1User"
}
}
},
"v1DebugCreateMachineRequest": {
"type": "object",
"properties": {
"user": {
"namespace": {
"type": "string"
},
"key": {
@@ -917,7 +917,7 @@
"v1DeleteMachineResponse": {
"type": "object"
},
"v1DeleteUserResponse": {
"v1DeleteNamespaceResponse": {
"type": "object"
},
"v1DisableRouteResponse": {
@@ -948,7 +948,7 @@
"v1ExpirePreAuthKeyRequest": {
"type": "object",
"properties": {
"user": {
"namespace": {
"type": "string"
},
"key": {
@@ -978,6 +978,14 @@
}
}
},
"v1GetNamespaceResponse": {
"type": "object",
"properties": {
"namespace": {
"$ref": "#/definitions/v1Namespace"
}
}
},
"v1GetRoutesResponse": {
"type": "object",
"properties": {
@@ -989,14 +997,6 @@
}
}
},
"v1GetUserResponse": {
"type": "object",
"properties": {
"user": {
"$ref": "#/definitions/v1User"
}
}
},
"v1ListApiKeysResponse": {
"type": "object",
"properties": {
@@ -1019,6 +1019,17 @@
}
}
},
"v1ListNamespacesResponse": {
"type": "object",
"properties": {
"namespaces": {
"type": "array",
"items": {
"$ref": "#/definitions/v1Namespace"
}
}
}
},
"v1ListPreAuthKeysResponse": {
"type": "object",
"properties": {
@@ -1030,17 +1041,6 @@
}
}
},
"v1ListUsersResponse": {
"type": "object",
"properties": {
"users": {
"type": "array",
"items": {
"$ref": "#/definitions/v1User"
}
}
}
},
"v1Machine": {
"type": "object",
"properties": {
@@ -1066,8 +1066,8 @@
"name": {
"type": "string"
},
"user": {
"$ref": "#/definitions/v1User"
"namespace": {
"$ref": "#/definitions/v1Namespace"
},
"lastSeen": {
"type": "string",
@@ -1125,10 +1125,25 @@
}
}
},
"v1Namespace": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"createdAt": {
"type": "string",
"format": "date-time"
}
}
},
"v1PreAuthKey": {
"type": "object",
"properties": {
"user": {
"namespace": {
"type": "string"
},
"id": {
@@ -1188,11 +1203,11 @@
}
}
},
"v1RenameUserResponse": {
"v1RenameNamespaceResponse": {
"type": "object",
"properties": {
"user": {
"$ref": "#/definitions/v1User"
"namespace": {
"$ref": "#/definitions/v1Namespace"
}
}
},
@@ -1239,21 +1254,6 @@
"$ref": "#/definitions/v1Machine"
}
}
},
"v1User": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"createdAt": {
"type": "string",
"format": "date-time"
}
}
}
}
}

View File

@@ -1,7 +1,7 @@
{
"swagger": "2.0",
"info": {
"title": "headscale/v1/user.proto",
"title": "headscale/v1/namespace.proto",
"version": "version not set"
},
"consumes": [

2
go.mod
View File

@@ -7,7 +7,6 @@ require (
github.com/ccding/go-stun/stun v0.0.0-20200514191101-4dc67bcdb029
github.com/cenkalti/backoff/v4 v4.2.0
github.com/coreos/go-oidc/v3 v3.4.0
github.com/davecgh/go-spew v1.1.1
github.com/deckarep/golang-set/v2 v2.1.0
github.com/efekarakus/termcolor v1.0.1
github.com/glebarez/sqlite v1.5.0
@@ -59,6 +58,7 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/containerd/console v1.0.3 // indirect
github.com/containerd/continuity v0.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/cli v20.10.21+incompatible // indirect
github.com/docker/docker v20.10.21+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect

View File

@@ -26,76 +26,76 @@ func newHeadscaleV1APIServer(h *Headscale) v1.HeadscaleServiceServer {
}
}
func (api headscaleV1APIServer) GetUser(
func (api headscaleV1APIServer) GetNamespace(
ctx context.Context,
request *v1.GetUserRequest,
) (*v1.GetUserResponse, error) {
user, err := api.h.GetUser(request.GetName())
request *v1.GetNamespaceRequest,
) (*v1.GetNamespaceResponse, error) {
namespace, err := api.h.GetNamespace(request.GetName())
if err != nil {
return nil, err
}
return &v1.GetUserResponse{User: user.toProto()}, nil
return &v1.GetNamespaceResponse{Namespace: namespace.toProto()}, nil
}
func (api headscaleV1APIServer) CreateUser(
func (api headscaleV1APIServer) CreateNamespace(
ctx context.Context,
request *v1.CreateUserRequest,
) (*v1.CreateUserResponse, error) {
user, err := api.h.CreateUser(request.GetName())
request *v1.CreateNamespaceRequest,
) (*v1.CreateNamespaceResponse, error) {
namespace, err := api.h.CreateNamespace(request.GetName())
if err != nil {
return nil, err
}
return &v1.CreateUserResponse{User: user.toProto()}, nil
return &v1.CreateNamespaceResponse{Namespace: namespace.toProto()}, nil
}
func (api headscaleV1APIServer) RenameUser(
func (api headscaleV1APIServer) RenameNamespace(
ctx context.Context,
request *v1.RenameUserRequest,
) (*v1.RenameUserResponse, error) {
err := api.h.RenameUser(request.GetOldName(), request.GetNewName())
request *v1.RenameNamespaceRequest,
) (*v1.RenameNamespaceResponse, error) {
err := api.h.RenameNamespace(request.GetOldName(), request.GetNewName())
if err != nil {
return nil, err
}
user, err := api.h.GetUser(request.GetNewName())
namespace, err := api.h.GetNamespace(request.GetNewName())
if err != nil {
return nil, err
}
return &v1.RenameUserResponse{User: user.toProto()}, nil
return &v1.RenameNamespaceResponse{Namespace: namespace.toProto()}, nil
}
func (api headscaleV1APIServer) DeleteUser(
func (api headscaleV1APIServer) DeleteNamespace(
ctx context.Context,
request *v1.DeleteUserRequest,
) (*v1.DeleteUserResponse, error) {
err := api.h.DestroyUser(request.GetName())
request *v1.DeleteNamespaceRequest,
) (*v1.DeleteNamespaceResponse, error) {
err := api.h.DestroyNamespace(request.GetName())
if err != nil {
return nil, err
}
return &v1.DeleteUserResponse{}, nil
return &v1.DeleteNamespaceResponse{}, nil
}
func (api headscaleV1APIServer) ListUsers(
func (api headscaleV1APIServer) ListNamespaces(
ctx context.Context,
request *v1.ListUsersRequest,
) (*v1.ListUsersResponse, error) {
users, err := api.h.ListUsers()
request *v1.ListNamespacesRequest,
) (*v1.ListNamespacesResponse, error) {
namespaces, err := api.h.ListNamespaces()
if err != nil {
return nil, err
}
response := make([]*v1.User, len(users))
for index, user := range users {
response[index] = user.toProto()
response := make([]*v1.Namespace, len(namespaces))
for index, namespace := range namespaces {
response[index] = namespace.toProto()
}
log.Trace().Caller().Interface("users", response).Msg("")
log.Trace().Caller().Interface("namespaces", response).Msg("")
return &v1.ListUsersResponse{Users: response}, nil
return &v1.ListNamespacesResponse{Namespaces: response}, nil
}
func (api headscaleV1APIServer) CreatePreAuthKey(
@@ -117,7 +117,7 @@ func (api headscaleV1APIServer) CreatePreAuthKey(
}
preAuthKey, err := api.h.CreatePreAuthKey(
request.GetUser(),
request.GetNamespace(),
request.GetReusable(),
request.GetEphemeral(),
&expiration,
@@ -134,7 +134,7 @@ func (api headscaleV1APIServer) ExpirePreAuthKey(
ctx context.Context,
request *v1.ExpirePreAuthKeyRequest,
) (*v1.ExpirePreAuthKeyResponse, error) {
preAuthKey, err := api.h.GetPreAuthKey(request.GetUser(), request.Key)
preAuthKey, err := api.h.GetPreAuthKey(request.GetNamespace(), request.Key)
if err != nil {
return nil, err
}
@@ -151,7 +151,7 @@ func (api headscaleV1APIServer) ListPreAuthKeys(
ctx context.Context,
request *v1.ListPreAuthKeysRequest,
) (*v1.ListPreAuthKeysResponse, error) {
preAuthKeys, err := api.h.ListPreAuthKeys(request.GetUser())
preAuthKeys, err := api.h.ListPreAuthKeys(request.GetNamespace())
if err != nil {
return nil, err
}
@@ -169,14 +169,13 @@ func (api headscaleV1APIServer) RegisterMachine(
request *v1.RegisterMachineRequest,
) (*v1.RegisterMachineResponse, error) {
log.Trace().
Str("user", request.GetUser()).
Str("namespace", request.GetNamespace()).
Str("node_key", request.GetKey()).
Msg("Registering machine")
machine, err := api.h.RegisterMachineFromAuthCallback(
request.GetKey(),
request.GetUser(),
nil,
request.GetNamespace(),
RegisterMethodCLI,
)
if err != nil {
@@ -313,8 +312,8 @@ func (api headscaleV1APIServer) ListMachines(
ctx context.Context,
request *v1.ListMachinesRequest,
) (*v1.ListMachinesResponse, error) {
if request.GetUser() != "" {
machines, err := api.h.ListMachinesByUser(request.GetUser())
if request.GetNamespace() != "" {
machines, err := api.h.ListMachinesInNamespace(request.GetNamespace())
if err != nil {
return nil, err
}
@@ -357,7 +356,7 @@ func (api headscaleV1APIServer) MoveMachine(
return nil, err
}
err = api.h.SetMachineUser(machine, request.GetUser())
err = api.h.SetMachineNamespace(machine, request.GetNamespace())
if err != nil {
return nil, err
}
@@ -483,7 +482,7 @@ func (api headscaleV1APIServer) DebugCreateMachine(
ctx context.Context,
request *v1.DebugCreateMachineRequest,
) (*v1.DebugCreateMachineResponse, error) {
user, err := api.h.GetUser(request.GetUser())
namespace, err := api.h.GetNamespace(request.GetNamespace())
if err != nil {
return nil, err
}
@@ -514,7 +513,7 @@ func (api headscaleV1APIServer) DebugCreateMachine(
MachineKey: request.GetKey(),
Hostname: request.GetName(),
GivenName: givenName,
User: *user,
Namespace: *namespace,
Expiry: &time.Time{},
LastSeen: &time.Time{},

View File

@@ -1,16 +0,0 @@
# Integration testing
Headscale relies on integration testing to ensure we remain compatible with Tailscale.
This is typically performed by starting a Headscale server and running a test "scenario"
with an array of Tailscale clients and versions.
Headscale's test framework and the current set of scenarios are defined in this directory.
Tests are located in files ending with `_test.go` and the framework are located in the rest.
## Running integration tests on GitHub Actions
Each test currently runs as a separate workflows in GitHub actions, to add new test, add
the new test to the list in `../cmd/gh-action-integration-generator/main.go` and run
`go generate` inside `../cmd/gh-action-integration-generator/` and commit the result.

View File

@@ -9,10 +9,8 @@ import (
"log"
"net"
"net/http"
"net/netip"
"strconv"
"testing"
"time"
"github.com/juanfont/headscale"
"github.com/juanfont/headscale/integration/dockertestutil"
@@ -24,7 +22,7 @@ import (
const (
dockerContextPath = "../."
hsicOIDCMockHashLength = 6
defaultAccessTTL = 10 * time.Minute
oidcServerPort = 10000
)
var errStatusCodeNotOK = errors.New("status code not OK")
@@ -49,81 +47,14 @@ func TestOIDCAuthenticationPingAll(t *testing.T) {
}
spec := map[string]int{
"user1": len(TailscaleVersions),
"namespace1": len(TailscaleVersions),
}
oidcConfig, err := scenario.runMockOIDC(defaultAccessTTL)
oidcConfig, err := scenario.runMockOIDC()
if err != nil {
t.Errorf("failed to run mock OIDC server: %s", err)
}
oidcMap := map[string]string{
"HEADSCALE_OIDC_ISSUER": oidcConfig.Issuer,
"HEADSCALE_OIDC_CLIENT_ID": oidcConfig.ClientID,
"CREDENTIALS_DIRECTORY_TEST": "/tmp",
"HEADSCALE_OIDC_CLIENT_SECRET_PATH": "${CREDENTIALS_DIRECTORY_TEST}/hs_client_oidc_secret",
"HEADSCALE_OIDC_STRIP_EMAIL_DOMAIN": fmt.Sprintf("%t", oidcConfig.StripEmaildomain),
}
err = scenario.CreateHeadscaleEnv(
spec,
hsic.WithTestName("oidcauthping"),
hsic.WithConfigEnv(oidcMap),
hsic.WithHostnameAsServerURL(),
hsic.WithFileInContainer("/tmp/hs_client_oidc_secret", []byte(oidcConfig.ClientSecret)),
)
if err != nil {
t.Errorf("failed to create headscale environment: %s", err)
}
allClients, err := scenario.ListTailscaleClients()
if err != nil {
t.Errorf("failed to get clients: %s", err)
}
allIps, err := scenario.ListTailscaleClientsIPs()
if err != nil {
t.Errorf("failed to get clients: %s", err)
}
err = scenario.WaitForTailscaleSync()
if err != nil {
t.Errorf("failed wait for tailscale clients to be in sync: %s", err)
}
success := pingAll(t, allClients, allIps)
t.Logf("%d successful pings out of %d", success, len(allClients)*len(allIps))
err = scenario.Shutdown()
if err != nil {
t.Errorf("failed to tear down scenario: %s", err)
}
}
func TestOIDCExpireNodes(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
shortAccessTTL := 5 * time.Minute
baseScenario, err := NewScenario()
if err != nil {
t.Errorf("failed to create scenario: %s", err)
}
scenario := AuthOIDCScenario{
Scenario: baseScenario,
}
spec := map[string]int{
"user1": len(TailscaleVersions),
}
oidcConfig, err := scenario.runMockOIDC(shortAccessTTL)
if err != nil {
t.Fatalf("failed to run mock OIDC server: %s", err)
}
oidcMap := map[string]string{
"HEADSCALE_OIDC_ISSUER": oidcConfig.Issuer,
"HEADSCALE_OIDC_CLIENT_ID": oidcConfig.ClientID,
@@ -133,7 +64,7 @@ func TestOIDCExpireNodes(t *testing.T) {
err = scenario.CreateHeadscaleEnv(
spec,
hsic.WithTestName("oidcexpirenodes"),
hsic.WithTestName("oidcauthping"),
hsic.WithConfigEnv(oidcMap),
hsic.WithHostnameAsServerURL(),
)
@@ -156,11 +87,20 @@ func TestOIDCExpireNodes(t *testing.T) {
t.Errorf("failed wait for tailscale clients to be in sync: %s", err)
}
success := pingAll(t, allClients, allIps)
t.Logf("%d successful pings out of %d (before expiry)", success, len(allClients)*len(allIps))
success := 0
// await all nodes being logged out after OIDC token expiry
scenario.WaitForTailscaleLogout()
for _, client := range allClients {
for _, ip := range allIps {
err := client.Ping(ip.String())
if err != nil {
t.Errorf("failed to ping %s from %s: %s", ip, client.Hostname(), err)
} else {
success++
}
}
}
t.Logf("%d successful pings out of %d", success, len(allClients)*len(allIps))
err = scenario.Shutdown()
if err != nil {
@@ -169,7 +109,7 @@ func TestOIDCExpireNodes(t *testing.T) {
}
func (s *AuthOIDCScenario) CreateHeadscaleEnv(
users map[string]int,
namespaces map[string]int,
opts ...hsic.Option,
) error {
headscale, err := s.Headscale(opts...)
@@ -182,19 +122,19 @@ func (s *AuthOIDCScenario) CreateHeadscaleEnv(
return err
}
for userName, clientCount := range users {
log.Printf("creating user %s with %d clients", userName, clientCount)
err = s.CreateUser(userName)
for namespaceName, clientCount := range namespaces {
log.Printf("creating namespace %s with %d clients", namespaceName, clientCount)
err = s.CreateNamespace(namespaceName)
if err != nil {
return err
}
err = s.CreateTailscaleNodesInUser(userName, "all", clientCount)
err = s.CreateTailscaleNodesInNamespace(namespaceName, "all", clientCount)
if err != nil {
return err
}
err = s.runTailscaleUp(userName, headscale.GetEndpoint())
err = s.runTailscaleUp(namespaceName, headscale.GetEndpoint())
if err != nil {
return err
}
@@ -203,13 +143,7 @@ func (s *AuthOIDCScenario) CreateHeadscaleEnv(
return nil
}
func (s *AuthOIDCScenario) runMockOIDC(accessTTL time.Duration) (*headscale.OIDCConfig, error) {
port, err := dockertestutil.RandomFreeHostPort()
if err != nil {
log.Fatalf("could not find an open port: %s", err)
}
portNotation := fmt.Sprintf("%d/tcp", port)
func (s *AuthOIDCScenario) runMockOIDC() (*headscale.OIDCConfig, error) {
hash, _ := headscale.GenerateRandomStringDNSSafe(hsicOIDCMockHashLength)
hostname := fmt.Sprintf("hs-oidcmock-%s", hash)
@@ -217,17 +151,16 @@ func (s *AuthOIDCScenario) runMockOIDC(accessTTL time.Duration) (*headscale.OIDC
mockOidcOptions := &dockertest.RunOptions{
Name: hostname,
Cmd: []string{"headscale", "mockoidc"},
ExposedPorts: []string{portNotation},
ExposedPorts: []string{"10000/tcp"},
PortBindings: map[docker.Port][]docker.PortBinding{
docker.Port(portNotation): {{HostPort: strconv.Itoa(port)}},
"10000/tcp": {{HostPort: "10000"}},
},
Networks: []*dockertest.Network{s.Scenario.network},
Env: []string{
fmt.Sprintf("MOCKOIDC_ADDR=%s", hostname),
fmt.Sprintf("MOCKOIDC_PORT=%d", port),
"MOCKOIDC_PORT=10000",
"MOCKOIDC_CLIENT_ID=superclient",
"MOCKOIDC_CLIENT_SECRET=supersecret",
fmt.Sprintf("MOCKOIDC_ACCESS_TTL=%s", accessTTL.String()),
},
}
@@ -236,7 +169,7 @@ func (s *AuthOIDCScenario) runMockOIDC(accessTTL time.Duration) (*headscale.OIDC
ContextDir: dockerContextPath,
}
err = s.pool.RemoveContainerByName(hostname)
err := s.pool.RemoveContainerByName(hostname)
if err != nil {
return nil, err
}
@@ -251,7 +184,11 @@ func (s *AuthOIDCScenario) runMockOIDC(accessTTL time.Duration) (*headscale.OIDC
}
log.Println("Waiting for headscale mock oidc to be ready for tests")
hostEndpoint := fmt.Sprintf("%s:%d", s.mockOIDC.GetIPInNetwork(s.network), port)
hostEndpoint := fmt.Sprintf(
"%s:%s",
s.mockOIDC.GetIPInNetwork(s.network),
s.mockOIDC.GetPort(fmt.Sprintf("%d/tcp", oidcServerPort)),
)
if err := s.pool.Retry(func() error {
oidcConfigURL := fmt.Sprintf("http://%s/oidc/.well-known/openid-configuration", hostEndpoint)
@@ -278,29 +215,29 @@ func (s *AuthOIDCScenario) runMockOIDC(accessTTL time.Duration) (*headscale.OIDC
log.Printf("headscale mock oidc is ready for tests at %s", hostEndpoint)
return &headscale.OIDCConfig{
Issuer: fmt.Sprintf("http://%s/oidc", net.JoinHostPort(s.mockOIDC.GetIPInNetwork(s.network), strconv.Itoa(port))),
ClientID: "superclient",
ClientSecret: "supersecret",
StripEmaildomain: true,
OnlyStartIfOIDCIsAvailable: true,
Issuer: fmt.Sprintf("http://%s/oidc",
net.JoinHostPort(s.mockOIDC.GetIPInNetwork(s.network), strconv.Itoa(oidcServerPort))),
ClientID: "superclient",
ClientSecret: "supersecret",
StripEmaildomain: true,
}, nil
}
func (s *AuthOIDCScenario) runTailscaleUp(
userStr, loginServer string,
namespaceStr, loginServer string,
) error {
headscale, err := s.Headscale()
if err != nil {
return err
}
log.Printf("running tailscale up for user %s", userStr)
if user, ok := s.users[userStr]; ok {
for _, client := range user.Clients {
user.joinWaitGroup.Add(1)
log.Printf("running tailscale up for namespace %s", namespaceStr)
if namespace, ok := s.namespaces[namespaceStr]; ok {
for _, client := range namespace.Clients {
namespace.joinWaitGroup.Add(1)
go func(c TailscaleClient) {
defer user.joinWaitGroup.Done()
defer namespace.joinWaitGroup.Done()
// TODO(juanfont): error handle this
loginURL, err := c.UpWithLoginURL(loginServer)
@@ -347,30 +284,12 @@ func (s *AuthOIDCScenario) runTailscaleUp(
log.Printf("client %s is ready", client.Hostname())
}
user.joinWaitGroup.Wait()
namespace.joinWaitGroup.Wait()
return nil
}
return fmt.Errorf("failed to up tailscale node: %w", errNoUserAvailable)
}
func pingAll(t *testing.T, clients []TailscaleClient, ips []netip.Addr) int {
t.Helper()
success := 0
for _, client := range clients {
for _, ip := range ips {
err := client.Ping(ip.String())
if err != nil {
t.Errorf("failed to ping %s from %s: %s", ip, client.Hostname(), err)
} else {
success++
}
}
}
return success
return fmt.Errorf("failed to up tailscale node: %w", errNoNamespaceAvailable)
}
func (s *AuthOIDCScenario) Shutdown() error {

View File

@@ -35,8 +35,8 @@ func TestAuthWebFlowAuthenticationPingAll(t *testing.T) {
}
spec := map[string]int{
"user1": len(TailscaleVersions),
"user2": len(TailscaleVersions),
"namespace1": len(TailscaleVersions),
"namespace2": len(TailscaleVersions),
}
err = scenario.CreateHeadscaleEnv(spec, hsic.WithTestName("webauthping"))
@@ -93,8 +93,8 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
}
spec := map[string]int{
"user1": len(TailscaleVersions),
"user2": len(TailscaleVersions),
"namespace1": len(TailscaleVersions),
"namespace2": len(TailscaleVersions),
}
err = scenario.CreateHeadscaleEnv(spec, hsic.WithTestName("weblogout"))
@@ -147,7 +147,7 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
}
}
scenario.WaitForTailscaleLogout()
scenario.waitForTailscaleLogout()
t.Logf("all clients logged out")
@@ -156,8 +156,8 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
t.Errorf("failed to get headscale server: %s", err)
}
for userName := range spec {
err = scenario.runTailscaleUp(userName, headscale.GetEndpoint())
for namespaceName := range spec {
err = scenario.runTailscaleUp(namespaceName, headscale.GetEndpoint())
if err != nil {
t.Errorf("failed to run tailscale up: %s", err)
}
@@ -225,7 +225,7 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
}
func (s *AuthWebFlowScenario) CreateHeadscaleEnv(
users map[string]int,
namespaces map[string]int,
opts ...hsic.Option,
) error {
headscale, err := s.Headscale(opts...)
@@ -238,19 +238,19 @@ func (s *AuthWebFlowScenario) CreateHeadscaleEnv(
return err
}
for userName, clientCount := range users {
log.Printf("creating user %s with %d clients", userName, clientCount)
err = s.CreateUser(userName)
for namespaceName, clientCount := range namespaces {
log.Printf("creating namespace %s with %d clients", namespaceName, clientCount)
err = s.CreateNamespace(namespaceName)
if err != nil {
return err
}
err = s.CreateTailscaleNodesInUser(userName, "all", clientCount)
err = s.CreateTailscaleNodesInNamespace(namespaceName, "all", clientCount)
if err != nil {
return err
}
err = s.runTailscaleUp(userName, headscale.GetEndpoint())
err = s.runTailscaleUp(namespaceName, headscale.GetEndpoint())
if err != nil {
return err
}
@@ -259,16 +259,32 @@ func (s *AuthWebFlowScenario) CreateHeadscaleEnv(
return nil
}
func (s *AuthWebFlowScenario) runTailscaleUp(
userStr, loginServer string,
) error {
log.Printf("running tailscale up for user %s", userStr)
if user, ok := s.users[userStr]; ok {
for _, client := range user.Clients {
user.joinWaitGroup.Add(1)
func (s *AuthWebFlowScenario) waitForTailscaleLogout() {
for _, namespace := range s.namespaces {
for _, client := range namespace.Clients {
namespace.syncWaitGroup.Add(1)
go func(c TailscaleClient) {
defer user.joinWaitGroup.Done()
defer namespace.syncWaitGroup.Done()
// TODO(kradalby): error handle this
_ = c.WaitForLogout()
}(client)
}
namespace.syncWaitGroup.Wait()
}
}
func (s *AuthWebFlowScenario) runTailscaleUp(
namespaceStr, loginServer string,
) error {
log.Printf("running tailscale up for namespace %s", namespaceStr)
if namespace, ok := s.namespaces[namespaceStr]; ok {
for _, client := range namespace.Clients {
namespace.joinWaitGroup.Add(1)
go func(c TailscaleClient) {
defer namespace.joinWaitGroup.Done()
// TODO(juanfont): error handle this
loginURL, err := c.UpWithLoginURL(loginServer)
@@ -276,7 +292,7 @@ func (s *AuthWebFlowScenario) runTailscaleUp(
log.Printf("failed to run tailscale up: %s", err)
}
err = s.runHeadscaleRegister(userStr, loginURL)
err = s.runHeadscaleRegister(namespaceStr, loginURL)
if err != nil {
log.Printf("failed to register client: %s", err)
}
@@ -287,15 +303,15 @@ func (s *AuthWebFlowScenario) runTailscaleUp(
log.Printf("error waiting for client %s to be ready: %s", client.Hostname(), err)
}
}
user.joinWaitGroup.Wait()
namespace.joinWaitGroup.Wait()
return nil
}
return fmt.Errorf("failed to up tailscale node: %w", errNoUserAvailable)
return fmt.Errorf("failed to up tailscale node: %w", errNoNamespaceAvailable)
}
func (s *AuthWebFlowScenario) runHeadscaleRegister(userStr string, loginURL *url.URL) error {
func (s *AuthWebFlowScenario) runHeadscaleRegister(namespaceStr string, loginURL *url.URL) error {
headscale, err := s.Headscale()
if err != nil {
return err
@@ -335,7 +351,7 @@ func (s *AuthWebFlowScenario) runHeadscaleRegister(userStr string, loginURL *url
if headscale, err := s.Headscale(); err == nil {
_, err = headscale.Execute(
[]string{"headscale", "nodes", "register", "--user", userStr, "--key", key},
[]string{"headscale", "-n", namespaceStr, "nodes", "register", "--key", key},
)
if err != nil {
log.Printf("failed to register node: %s", err)

View File

@@ -28,7 +28,7 @@ func executeAndUnmarshal[T any](headscale ControlServer, command []string, resul
return nil
}
func TestUserCommand(t *testing.T) {
func TestNamespaceCommand(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
@@ -36,8 +36,8 @@ func TestUserCommand(t *testing.T) {
assert.NoError(t, err)
spec := map[string]int{
"user1": 0,
"user2": 0,
"namespace1": 0,
"namespace2": 0,
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
@@ -46,60 +46,60 @@ func TestUserCommand(t *testing.T) {
headscale, err := scenario.Headscale()
assert.NoError(t, err)
var listUsers []v1.User
var listNamespaces []v1.Namespace
err = executeAndUnmarshal(headscale,
[]string{
"headscale",
"users",
"namespaces",
"list",
"--output",
"json",
},
&listUsers,
&listNamespaces,
)
assert.NoError(t, err)
result := []string{listUsers[0].Name, listUsers[1].Name}
result := []string{listNamespaces[0].Name, listNamespaces[1].Name}
sort.Strings(result)
assert.Equal(
t,
[]string{"user1", "user2"},
[]string{"namespace1", "namespace2"},
result,
)
_, err = headscale.Execute(
[]string{
"headscale",
"users",
"namespaces",
"rename",
"--output",
"json",
"user2",
"namespace2",
"newname",
},
)
assert.NoError(t, err)
var listAfterRenameUsers []v1.User
var listAfterRenameNamespaces []v1.Namespace
err = executeAndUnmarshal(headscale,
[]string{
"headscale",
"users",
"namespaces",
"list",
"--output",
"json",
},
&listAfterRenameUsers,
&listAfterRenameNamespaces,
)
assert.NoError(t, err)
result = []string{listAfterRenameUsers[0].Name, listAfterRenameUsers[1].Name}
result = []string{listAfterRenameNamespaces[0].Name, listAfterRenameNamespaces[1].Name}
sort.Strings(result)
assert.Equal(
t,
[]string{"user1", "newname"},
[]string{"namespace1", "newname"},
result,
)
@@ -111,14 +111,14 @@ func TestPreAuthKeyCommand(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
user := "preauthkeyspace"
namespace := "preauthkeyspace"
count := 3
scenario, err := NewScenario()
assert.NoError(t, err)
spec := map[string]int{
user: 0,
namespace: 0,
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipak"))
@@ -137,8 +137,8 @@ func TestPreAuthKeyCommand(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--user",
user,
"--namespace",
namespace,
"create",
"--reusable",
"--expiration",
@@ -163,8 +163,8 @@ func TestPreAuthKeyCommand(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--user",
user,
"--namespace",
namespace,
"list",
"--output",
"json",
@@ -216,8 +216,8 @@ func TestPreAuthKeyCommand(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--user",
user,
"--namespace",
namespace,
"expire",
listedPreAuthKeys[1].Key,
},
@@ -230,8 +230,8 @@ func TestPreAuthKeyCommand(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--user",
user,
"--namespace",
namespace,
"list",
"--output",
"json",
@@ -252,13 +252,13 @@ func TestPreAuthKeyCommandWithoutExpiry(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
user := "pre-auth-key-without-exp-user"
namespace := "pre-auth-key-without-exp-namespace"
scenario, err := NewScenario()
assert.NoError(t, err)
spec := map[string]int{
user: 0,
namespace: 0,
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipaknaexp"))
@@ -273,8 +273,8 @@ func TestPreAuthKeyCommandWithoutExpiry(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--user",
user,
"--namespace",
namespace,
"create",
"--reusable",
"--output",
@@ -290,8 +290,8 @@ func TestPreAuthKeyCommandWithoutExpiry(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--user",
user,
"--namespace",
namespace,
"list",
"--output",
"json",
@@ -317,13 +317,13 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
user := "pre-auth-key-reus-ephm-user"
namespace := "pre-auth-key-reus-ephm-namespace"
scenario, err := NewScenario()
assert.NoError(t, err)
spec := map[string]int{
user: 0,
namespace: 0,
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipakresueeph"))
@@ -338,8 +338,8 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--user",
user,
"--namespace",
namespace,
"create",
"--reusable=true",
"--output",
@@ -355,8 +355,8 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--user",
user,
"--namespace",
namespace,
"create",
"--ephemeral=true",
"--output",
@@ -375,8 +375,8 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--user",
user,
"--namespace",
namespace,
"list",
"--output",
"json",
@@ -396,13 +396,13 @@ func TestEnablingRoutes(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
user := "enable-routing"
namespace := "enable-routing"
scenario, err := NewScenario()
assert.NoError(t, err)
spec := map[string]int{
user: 3,
namespace: 3,
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clienableroute"))

View File

@@ -10,9 +10,9 @@ type ControlServer interface {
GetHealthEndpoint() string
GetEndpoint() string
WaitForReady() error
CreateUser(user string) error
CreateAuthKey(user string, reusable bool, ephemeral bool) (*v1.PreAuthKey, error)
ListMachinesInUser(user string) ([]*v1.Machine, error)
CreateNamespace(namespace string) error
CreateAuthKey(namespace string) (*v1.PreAuthKey, error)
ListMachinesInNamespace(namespace string) ([]*v1.Machine, error)
GetCert() []byte
GetHostname() string
GetIP() string

View File

@@ -2,7 +2,6 @@ package dockertestutil
import (
"errors"
"net"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
@@ -61,20 +60,3 @@ func AddContainerToNetwork(
return nil
}
// RandomFreeHostPort asks the kernel for a free open port that is ready to use.
// (from https://github.com/phayes/freeport)
func RandomFreeHostPort() (int, error) {
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
if err != nil {
return 0, err
}
listener, err := net.ListenTCP("tcp", addr)
if err != nil {
return 0, err
}
defer listener.Close()
//nolint:forcetypeassert
return listener.Addr().(*net.TCPAddr).Port, nil
}

View File

@@ -2,7 +2,6 @@ package integration
import (
"fmt"
"net/netip"
"strings"
"testing"
"time"
@@ -22,8 +21,8 @@ func TestPingAllByIP(t *testing.T) {
}
spec := map[string]int{
"user1": len(TailscaleVersions),
"user2": len(TailscaleVersions),
"namespace1": len(TailscaleVersions),
"namespace2": len(TailscaleVersions),
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("pingallbyip"))
@@ -67,239 +66,6 @@ func TestPingAllByIP(t *testing.T) {
}
}
func TestAuthKeyLogoutAndRelogin(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario()
if err != nil {
t.Errorf("failed to create scenario: %s", err)
}
spec := map[string]int{
"user1": len(TailscaleVersions),
"user2": len(TailscaleVersions),
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("pingallbyip"))
if err != nil {
t.Errorf("failed to create headscale environment: %s", err)
}
allClients, err := scenario.ListTailscaleClients()
if err != nil {
t.Errorf("failed to get clients: %s", err)
}
err = scenario.WaitForTailscaleSync()
if err != nil {
t.Errorf("failed wait for tailscale clients to be in sync: %s", err)
}
clientIPs := make(map[TailscaleClient][]netip.Addr)
for _, client := range allClients {
ips, err := client.IPs()
if err != nil {
t.Errorf("failed to get IPs for client %s: %s", client.Hostname(), err)
}
clientIPs[client] = ips
}
for _, client := range allClients {
err := client.Logout()
if err != nil {
t.Errorf("failed to logout client %s: %s", client.Hostname(), err)
}
}
scenario.WaitForTailscaleLogout()
t.Logf("all clients logged out")
headscale, err := scenario.Headscale()
if err != nil {
t.Errorf("failed to get headscale server: %s", err)
}
for userName := range spec {
key, err := scenario.CreatePreAuthKey(userName, true, false)
if err != nil {
t.Errorf("failed to create pre-auth key for user %s: %s", userName, err)
}
err = scenario.RunTailscaleUp(userName, headscale.GetEndpoint(), key.GetKey())
if err != nil {
t.Errorf("failed to run tailscale up for user %s: %s", userName, err)
}
}
err = scenario.WaitForTailscaleSync()
if err != nil {
t.Errorf("failed wait for tailscale clients to be in sync: %s", err)
}
allClients, err = scenario.ListTailscaleClients()
if err != nil {
t.Errorf("failed to get clients: %s", err)
}
allIps, err := scenario.ListTailscaleClientsIPs()
if err != nil {
t.Errorf("failed to get clients: %s", err)
}
success := 0
for _, client := range allClients {
for _, ip := range allIps {
err := client.Ping(ip.String())
if err != nil {
t.Errorf("failed to ping %s from %s: %s", ip, client.Hostname(), err)
} else {
success++
}
}
}
t.Logf("%d successful pings out of %d", success, len(allClients)*len(allIps))
for _, client := range allClients {
ips, err := client.IPs()
if err != nil {
t.Errorf("failed to get IPs for client %s: %s", client.Hostname(), err)
}
// lets check if the IPs are the same
if len(ips) != len(clientIPs[client]) {
t.Errorf("IPs changed for client %s", client.Hostname())
}
for _, ip := range ips {
found := false
for _, oldIP := range clientIPs[client] {
if ip == oldIP {
found = true
break
}
}
if !found {
t.Errorf("IPs changed for client %s. Used to be %v now %v", client.Hostname(), clientIPs[client], ips)
}
}
}
t.Logf("all clients IPs are the same")
err = scenario.Shutdown()
if err != nil {
t.Errorf("failed to tear down scenario: %s", err)
}
}
func TestEphemeral(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
scenario, err := NewScenario()
if err != nil {
t.Errorf("failed to create scenario: %s", err)
}
spec := map[string]int{
"user1": len(TailscaleVersions),
"user2": len(TailscaleVersions),
}
headscale, err := scenario.Headscale(hsic.WithTestName("ephemeral"))
if err != nil {
t.Errorf("failed to create headscale environment: %s", err)
}
for userName, clientCount := range spec {
err = scenario.CreateUser(userName)
if err != nil {
t.Errorf("failed to create user %s: %s", userName, err)
}
err = scenario.CreateTailscaleNodesInUser(userName, "all", clientCount, []tsic.Option{}...)
if err != nil {
t.Errorf("failed to create tailscale nodes in user %s: %s", userName, err)
}
key, err := scenario.CreatePreAuthKey(userName, true, true)
if err != nil {
t.Errorf("failed to create pre-auth key for user %s: %s", userName, err)
}
err = scenario.RunTailscaleUp(userName, headscale.GetEndpoint(), key.GetKey())
if err != nil {
t.Errorf("failed to run tailscale up for user %s: %s", userName, err)
}
}
err = scenario.WaitForTailscaleSync()
if err != nil {
t.Errorf("failed wait for tailscale clients to be in sync: %s", err)
}
allClients, err := scenario.ListTailscaleClients()
if err != nil {
t.Errorf("failed to get clients: %s", err)
}
allIps, err := scenario.ListTailscaleClientsIPs()
if err != nil {
t.Errorf("failed to get clients: %s", err)
}
success := 0
for _, client := range allClients {
for _, ip := range allIps {
err := client.Ping(ip.String())
if err != nil {
t.Errorf("failed to ping %s from %s: %s", ip, client.Hostname(), err)
} else {
success++
}
}
}
t.Logf("%d successful pings out of %d", success, len(allClients)*len(allIps))
for _, client := range allClients {
err := client.Logout()
if err != nil {
t.Errorf("failed to logout client %s: %s", client.Hostname(), err)
}
}
scenario.WaitForTailscaleLogout()
t.Logf("all clients logged out")
for userName := range spec {
machines, err := headscale.ListMachinesInUser(userName)
if err != nil {
log.Error().
Err(err).
Str("user", userName).
Msg("Error listing machines in user")
return
}
if len(machines) != 0 {
t.Errorf("expected no machines, got %d in user %s", len(machines), userName)
}
}
err = scenario.Shutdown()
if err != nil {
t.Errorf("failed to tear down scenario: %s", err)
}
}
func TestPingAllByHostname(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
@@ -311,8 +77,8 @@ func TestPingAllByHostname(t *testing.T) {
spec := map[string]int{
// Omit 1.16.2 (-1) because it does not have the FQDN field
"user3": len(TailscaleVersions) - 1,
"user4": len(TailscaleVersions) - 1,
"namespace3": len(TailscaleVersions) - 1,
"namespace4": len(TailscaleVersions) - 1,
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("pingallbyname"))

View File

@@ -60,8 +60,6 @@ package hsic
// }
// TODO: Reuse the actual configuration object above.
// Deprecated: use env function instead as it is easier to
// override.
func DefaultConfigYAML() string {
yaml := `
log:
@@ -97,35 +95,3 @@ derp:
return yaml
}
func MinimumConfigYAML() string {
return `
private_key_path: /tmp/private.key
noise:
private_key_path: /tmp/noise_private.key
`
}
func DefaultConfigEnv() map[string]string {
return map[string]string{
"HEADSCALE_LOG_LEVEL": "trace",
"HEADSCALE_ACL_POLICY_PATH": "",
"HEADSCALE_DB_TYPE": "sqlite3",
"HEADSCALE_DB_PATH": "/tmp/integration_test_db.sqlite3",
"HEADSCALE_EPHEMERAL_NODE_INACTIVITY_TIMEOUT": "30m",
"HEADSCALE_NODE_UPDATE_CHECK_INTERVAL": "10s",
"HEADSCALE_IP_PREFIXES": "fd7a:115c:a1e0::/48 100.64.0.0/10",
"HEADSCALE_DNS_CONFIG_BASE_DOMAIN": "headscale.net",
"HEADSCALE_DNS_CONFIG_MAGIC_DNS": "true",
"HEADSCALE_DNS_CONFIG_DOMAINS": "",
"HEADSCALE_DNS_CONFIG_NAMESERVERS": "127.0.0.11 1.1.1.1",
"HEADSCALE_PRIVATE_KEY_PATH": "/tmp/private.key",
"HEADSCALE_NOISE_PRIVATE_KEY_PATH": "/tmp/noise_private.key",
"HEADSCALE_LISTEN_ADDR": "0.0.0.0:8080",
"HEADSCALE_METRICS_LISTEN_ADDR": "127.0.0.1:9090",
"HEADSCALE_SERVER_URL": "http://headscale:8080",
"HEADSCALE_DERP_URLS": "https://controlplane.tailscale.com/derpmap/default",
"HEADSCALE_DERP_AUTO_UPDATE_ENABLED": "false",
"HEADSCALE_DERP_UPDATE_FREQUENCY": "1m",
}
}

View File

@@ -17,7 +17,6 @@ import (
"net/http"
"time"
"github.com/davecgh/go-spew/spew"
"github.com/juanfont/headscale"
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
"github.com/juanfont/headscale/integration/dockertestutil"
@@ -36,11 +35,6 @@ const (
var errHeadscaleStatusCodeNotOk = errors.New("headscale status code not ok")
type fileInContainer struct {
path string
contents []byte
}
type HeadscaleInContainer struct {
hostname string
@@ -49,12 +43,11 @@ type HeadscaleInContainer struct {
network *dockertest.Network
// optional config
port int
aclPolicy *headscale.ACLPolicy
env map[string]string
tlsCert []byte
tlsKey []byte
filesInContainer []fileInContainer
port int
aclPolicy *headscale.ACLPolicy
env []string
tlsCert []byte
tlsKey []byte
}
type Option = func(c *HeadscaleInContainer)
@@ -62,7 +55,7 @@ type Option = func(c *HeadscaleInContainer)
func WithACLPolicy(acl *headscale.ACLPolicy) Option {
return func(hsic *HeadscaleInContainer) {
// TODO(kradalby): Move somewhere appropriate
hsic.env["HEADSCALE_ACL_POLICY_PATH"] = aclPolicyPath
hsic.env = append(hsic.env, fmt.Sprintf("HEADSCALE_ACL_POLICY_PATH=%s", aclPolicyPath))
hsic.aclPolicy = acl
}
@@ -76,8 +69,8 @@ func WithTLS() Option {
}
// TODO(kradalby): Move somewhere appropriate
hsic.env["HEADSCALE_TLS_CERT_PATH"] = tlsCertPath
hsic.env["HEADSCALE_TLS_KEY_PATH"] = tlsKeyPath
hsic.env = append(hsic.env, fmt.Sprintf("HEADSCALE_TLS_CERT_PATH=%s", tlsCertPath))
hsic.env = append(hsic.env, fmt.Sprintf("HEADSCALE_TLS_KEY_PATH=%s", tlsKeyPath))
hsic.tlsCert = cert
hsic.tlsKey = key
@@ -87,7 +80,7 @@ func WithTLS() Option {
func WithConfigEnv(configEnv map[string]string) Option {
return func(hsic *HeadscaleInContainer) {
for key, value := range configEnv {
hsic.env[key] = value
hsic.env = append(hsic.env, fmt.Sprintf("%s=%s", key, value))
}
}
}
@@ -109,20 +102,12 @@ func WithTestName(testName string) Option {
func WithHostnameAsServerURL() Option {
return func(hsic *HeadscaleInContainer) {
hsic.env["HEADSCALE_SERVER_URL"] = fmt.Sprintf("http://%s",
net.JoinHostPort(hsic.GetHostname(),
fmt.Sprintf("%d", hsic.port)),
)
}
}
func WithFileInContainer(path string, contents []byte) Option {
return func(hsic *HeadscaleInContainer) {
hsic.filesInContainer = append(hsic.filesInContainer,
fileInContainer{
path: path,
contents: contents,
})
hsic.env = append(
hsic.env,
fmt.Sprintf("HEADSCALE_SERVER_URL=http://%s:%d",
hsic.GetHostname(),
hsic.port,
))
}
}
@@ -144,9 +129,6 @@ func New(
pool: pool,
network: network,
env: DefaultConfigEnv(),
filesInContainer: []fileInContainer{},
}
for _, opt := range opts {
@@ -162,13 +144,6 @@ func New(
ContextDir: dockerContextPath,
}
env := []string{}
for key, value := range hsic.env {
env = append(env, fmt.Sprintf("%s=%s", key, value))
}
log.Printf("ENV: \n%s", spew.Sdump(hsic.env))
runOptions := &dockertest.RunOptions{
Name: hsic.hostname,
ExposedPorts: []string{portProto},
@@ -177,7 +152,7 @@ func New(
// TODO(kradalby): Get rid of this hack, we currently need to give us some
// to inject the headscale configuration further down.
Entrypoint: []string{"/bin/bash", "-c", "/bin/sleep 3 ; headscale serve"},
Env: env,
Env: hsic.env,
}
// dockertest isnt very good at handling containers that has already
@@ -202,7 +177,7 @@ func New(
hsic.container = container
err = hsic.WriteFile("/etc/headscale/config.yaml", []byte(MinimumConfigYAML()))
err = hsic.WriteFile("/etc/headscale/config.yaml", []byte(DefaultConfigYAML()))
if err != nil {
return nil, fmt.Errorf("failed to write headscale config to container: %w", err)
}
@@ -231,12 +206,6 @@ func New(
}
}
for _, f := range hsic.filesInContainer {
if err := hsic.WriteFile(f.path, f.contents); err != nil {
return nil, fmt.Errorf("failed to write %q: %w", f.path, err)
}
}
return hsic, nil
}
@@ -328,10 +297,10 @@ func (t *HeadscaleInContainer) WaitForReady() error {
})
}
func (t *HeadscaleInContainer) CreateUser(
user string,
func (t *HeadscaleInContainer) CreateNamespace(
namespace string,
) error {
command := []string{"headscale", "users", "create", user}
command := []string{"headscale", "namespaces", "create", namespace}
_, _, err := dockertestutil.ExecuteCommand(
t.container,
@@ -346,30 +315,21 @@ func (t *HeadscaleInContainer) CreateUser(
}
func (t *HeadscaleInContainer) CreateAuthKey(
user string,
reusable bool,
ephemeral bool,
namespace string,
) (*v1.PreAuthKey, error) {
command := []string{
"headscale",
"--user",
user,
"--namespace",
namespace,
"preauthkeys",
"create",
"--reusable",
"--expiration",
"24h",
"--output",
"json",
}
if reusable {
command = append(command, "--reusable")
}
if ephemeral {
command = append(command, "--ephemeral")
}
result, _, err := dockertestutil.ExecuteCommand(
t.container,
command,
@@ -388,10 +348,10 @@ func (t *HeadscaleInContainer) CreateAuthKey(
return &preAuthKey, nil
}
func (t *HeadscaleInContainer) ListMachinesInUser(
user string,
func (t *HeadscaleInContainer) ListMachinesInNamespace(
namespace string,
) ([]*v1.Machine, error) {
command := []string{"headscale", "--user", user, "nodes", "list", "--output", "json"}
command := []string{"headscale", "--namespace", namespace, "nodes", "list", "--output", "json"}
result, _, err := dockertestutil.ExecuteCommand(
t.container,

View File

@@ -25,15 +25,14 @@ const (
var (
errNoHeadscaleAvailable = errors.New("no headscale available")
errNoUserAvailable = errors.New("no user available")
errNoNamespaceAvailable = errors.New("no namespace available")
// Tailscale started adding TS2021 support in CapabilityVersion>=28 (v1.24.0), but
// proper support in Headscale was only added for CapabilityVersion>=39 clients (v1.30.0).
tailscaleVersions2021 = []string{
"head",
"unstable",
"1.36.0",
"1.34.2",
"1.34.0",
"1.32.3",
"1.30.2",
}
@@ -44,11 +43,11 @@ var (
"1.24.2",
"1.22.2",
"1.20.4",
"1.18.2",
}
// tailscaleVersionsUnavailable = []string{
// // These versions seem to fail when fetching from apt.
// "1.18.2",
// "1.16.2",
// "1.14.6",
// "1.12.4",
@@ -62,7 +61,7 @@ var (
)
)
type User struct {
type Namespace struct {
Clients map[string]TailscaleClient
createWaitGroup sync.WaitGroup
@@ -76,7 +75,7 @@ type Scenario struct {
// use one.
controlServers *xsync.MapOf[string, ControlServer]
users map[string]*User
namespaces map[string]*Namespace
pool *dockertest.Pool
network *dockertest.Network
@@ -117,7 +116,7 @@ func NewScenario() (*Scenario, error) {
return &Scenario{
controlServers: xsync.NewMapOf[ControlServer](),
users: make(map[string]*User),
namespaces: make(map[string]*Namespace),
pool: pool,
network: network,
@@ -137,9 +136,9 @@ func (s *Scenario) Shutdown() error {
return true
})
for userName, user := range s.users {
for _, client := range user.Clients {
log.Printf("removing client %s in user %s", client.Hostname(), userName)
for namespaceName, namespace := range s.namespaces {
for _, client := range namespace.Clients {
log.Printf("removing client %s in namespace %s", client.Hostname(), namespaceName)
err := client.Shutdown()
if err != nil {
return fmt.Errorf("failed to tear down client: %w", err)
@@ -159,13 +158,13 @@ func (s *Scenario) Shutdown() error {
return nil
}
func (s *Scenario) Users() []string {
users := make([]string, 0)
for user := range s.users {
users = append(users, user)
func (s *Scenario) Namespaces() []string {
namespaces := make([]string, 0)
for namespace := range s.namespaces {
namespaces = append(namespaces, namespace)
}
return users
return namespaces
}
/// Headscale related stuff
@@ -195,45 +194,45 @@ func (s *Scenario) Headscale(opts ...hsic.Option) (ControlServer, error) {
return headscale, nil
}
func (s *Scenario) CreatePreAuthKey(user string, reusable bool, ephemeral bool) (*v1.PreAuthKey, error) {
func (s *Scenario) CreatePreAuthKey(namespace string) (*v1.PreAuthKey, error) {
if headscale, err := s.Headscale(); err == nil {
key, err := headscale.CreateAuthKey(user, reusable, ephemeral)
key, err := headscale.CreateAuthKey(namespace)
if err != nil {
return nil, fmt.Errorf("failed to create user: %w", err)
return nil, fmt.Errorf("failed to create namespace: %w", err)
}
return key, nil
}
return nil, fmt.Errorf("failed to create user: %w", errNoHeadscaleAvailable)
return nil, fmt.Errorf("failed to create namespace: %w", errNoHeadscaleAvailable)
}
func (s *Scenario) CreateUser(user string) error {
func (s *Scenario) CreateNamespace(namespace string) error {
if headscale, err := s.Headscale(); err == nil {
err := headscale.CreateUser(user)
err := headscale.CreateNamespace(namespace)
if err != nil {
return fmt.Errorf("failed to create user: %w", err)
return fmt.Errorf("failed to create namespace: %w", err)
}
s.users[user] = &User{
s.namespaces[namespace] = &Namespace{
Clients: make(map[string]TailscaleClient),
}
return nil
}
return fmt.Errorf("failed to create user: %w", errNoHeadscaleAvailable)
return fmt.Errorf("failed to create namespace: %w", errNoHeadscaleAvailable)
}
/// Client related stuff
func (s *Scenario) CreateTailscaleNodesInUser(
userStr string,
func (s *Scenario) CreateTailscaleNodesInNamespace(
namespaceStr string,
requestedVersion string,
count int,
opts ...tsic.Option,
) error {
if user, ok := s.users[userStr]; ok {
if namespace, ok := s.namespaces[namespaceStr]; ok {
for i := 0; i < count; i++ {
version := requestedVersion
if requestedVersion == "all" {
@@ -248,7 +247,7 @@ func (s *Scenario) CreateTailscaleNodesInUser(
cert := headscale.GetCert()
hostname := headscale.GetHostname()
user.createWaitGroup.Add(1)
namespace.createWaitGroup.Add(1)
opts = append(opts,
tsic.WithHeadscaleTLS(cert),
@@ -256,7 +255,7 @@ func (s *Scenario) CreateTailscaleNodesInUser(
)
go func() {
defer user.createWaitGroup.Done()
defer namespace.createWaitGroup.Done()
// TODO(kradalby): error handle this
tsClient, err := tsic.New(
@@ -276,26 +275,26 @@ func (s *Scenario) CreateTailscaleNodesInUser(
log.Printf("failed to wait for tailscaled: %s", err)
}
user.Clients[tsClient.Hostname()] = tsClient
namespace.Clients[tsClient.Hostname()] = tsClient
}()
}
user.createWaitGroup.Wait()
namespace.createWaitGroup.Wait()
return nil
}
return fmt.Errorf("failed to add tailscale node: %w", errNoUserAvailable)
return fmt.Errorf("failed to add tailscale node: %w", errNoNamespaceAvailable)
}
func (s *Scenario) RunTailscaleUp(
userStr, loginServer, authKey string,
namespaceStr, loginServer, authKey string,
) error {
if user, ok := s.users[userStr]; ok {
for _, client := range user.Clients {
user.joinWaitGroup.Add(1)
if namespace, ok := s.namespaces[namespaceStr]; ok {
for _, client := range namespace.Clients {
namespace.joinWaitGroup.Add(1)
go func(c TailscaleClient) {
defer user.joinWaitGroup.Done()
defer namespace.joinWaitGroup.Done()
// TODO(kradalby): error handle this
_ = c.Up(loginServer, authKey)
@@ -307,19 +306,19 @@ func (s *Scenario) RunTailscaleUp(
}
}
user.joinWaitGroup.Wait()
namespace.joinWaitGroup.Wait()
return nil
}
return fmt.Errorf("failed to up tailscale node: %w", errNoUserAvailable)
return fmt.Errorf("failed to up tailscale node: %w", errNoNamespaceAvailable)
}
func (s *Scenario) CountTailscale() int {
count := 0
for _, user := range s.users {
count += len(user.Clients)
for _, namespace := range s.namespaces {
count += len(namespace.Clients)
}
return count
@@ -328,18 +327,18 @@ func (s *Scenario) CountTailscale() int {
func (s *Scenario) WaitForTailscaleSync() error {
tsCount := s.CountTailscale()
for _, user := range s.users {
for _, client := range user.Clients {
user.syncWaitGroup.Add(1)
for _, namespace := range s.namespaces {
for _, client := range namespace.Clients {
namespace.syncWaitGroup.Add(1)
go func(c TailscaleClient) {
defer user.syncWaitGroup.Done()
defer namespace.syncWaitGroup.Done()
// TODO(kradalby): error handle this
_ = c.WaitForPeers(tsCount)
}(client)
}
user.syncWaitGroup.Wait()
namespace.syncWaitGroup.Wait()
}
return nil
@@ -347,9 +346,9 @@ func (s *Scenario) WaitForTailscaleSync() error {
// CreateHeadscaleEnv is a conventient method returning a set up Headcale
// test environment with nodes of all versions, joined to the server with X
// users.
// namespaces.
func (s *Scenario) CreateHeadscaleEnv(
users map[string]int,
namespaces map[string]int,
tsOpts []tsic.Option,
opts ...hsic.Option,
) error {
@@ -358,23 +357,23 @@ func (s *Scenario) CreateHeadscaleEnv(
return err
}
for userName, clientCount := range users {
err = s.CreateUser(userName)
for namespaceName, clientCount := range namespaces {
err = s.CreateNamespace(namespaceName)
if err != nil {
return err
}
err = s.CreateTailscaleNodesInUser(userName, "all", clientCount, tsOpts...)
err = s.CreateTailscaleNodesInNamespace(namespaceName, "all", clientCount, tsOpts...)
if err != nil {
return err
}
key, err := s.CreatePreAuthKey(userName, true, false)
key, err := s.CreatePreAuthKey(namespaceName)
if err != nil {
return err
}
err = s.RunTailscaleUp(userName, headscale.GetEndpoint(), key.GetKey())
err = s.RunTailscaleUp(namespaceName, headscale.GetEndpoint(), key.GetKey())
if err != nil {
return err
}
@@ -383,9 +382,9 @@ func (s *Scenario) CreateHeadscaleEnv(
return nil
}
func (s *Scenario) GetIPs(user string) ([]netip.Addr, error) {
func (s *Scenario) GetIPs(namespace string) ([]netip.Addr, error) {
var ips []netip.Addr
if ns, ok := s.users[user]; ok {
if ns, ok := s.namespaces[namespace]; ok {
for _, client := range ns.Clients {
clientIps, err := client.IPs()
if err != nil {
@@ -397,12 +396,12 @@ func (s *Scenario) GetIPs(user string) ([]netip.Addr, error) {
return ips, nil
}
return ips, fmt.Errorf("failed to get ips: %w", errNoUserAvailable)
return ips, fmt.Errorf("failed to get ips: %w", errNoNamespaceAvailable)
}
func (s *Scenario) GetClients(user string) ([]TailscaleClient, error) {
func (s *Scenario) GetClients(namespace string) ([]TailscaleClient, error) {
var clients []TailscaleClient
if ns, ok := s.users[user]; ok {
if ns, ok := s.namespaces[namespace]; ok {
for _, client := range ns.Clients {
clients = append(clients, client)
}
@@ -410,18 +409,18 @@ func (s *Scenario) GetClients(user string) ([]TailscaleClient, error) {
return clients, nil
}
return clients, fmt.Errorf("failed to get clients: %w", errNoUserAvailable)
return clients, fmt.Errorf("failed to get clients: %w", errNoNamespaceAvailable)
}
func (s *Scenario) ListTailscaleClients(users ...string) ([]TailscaleClient, error) {
func (s *Scenario) ListTailscaleClients(namespaces ...string) ([]TailscaleClient, error) {
var allClients []TailscaleClient
if len(users) == 0 {
users = s.Users()
if len(namespaces) == 0 {
namespaces = s.Namespaces()
}
for _, user := range users {
clients, err := s.GetClients(user)
for _, namespace := range namespaces {
clients, err := s.GetClients(namespace)
if err != nil {
return nil, err
}
@@ -432,15 +431,15 @@ func (s *Scenario) ListTailscaleClients(users ...string) ([]TailscaleClient, err
return allClients, nil
}
func (s *Scenario) ListTailscaleClientsIPs(users ...string) ([]netip.Addr, error) {
func (s *Scenario) ListTailscaleClientsIPs(namespaces ...string) ([]netip.Addr, error) {
var allIps []netip.Addr
if len(users) == 0 {
users = s.Users()
if len(namespaces) == 0 {
namespaces = s.Namespaces()
}
for _, user := range users {
ips, err := s.GetIPs(user)
for _, namespace := range namespaces {
ips, err := s.GetIPs(namespace)
if err != nil {
return nil, err
}
@@ -451,10 +450,10 @@ func (s *Scenario) ListTailscaleClientsIPs(users ...string) ([]netip.Addr, error
return allIps, nil
}
func (s *Scenario) ListTailscaleClientsFQDNs(users ...string) ([]string, error) {
func (s *Scenario) ListTailscaleClientsFQDNs(namespaces ...string) ([]string, error) {
allFQDNs := make([]string, 0)
clients, err := s.ListTailscaleClients(users...)
clients, err := s.ListTailscaleClients(namespaces...)
if err != nil {
return nil, err
}
@@ -470,19 +469,3 @@ func (s *Scenario) ListTailscaleClientsFQDNs(users ...string) ([]string, error)
return allFQDNs, nil
}
func (s *Scenario) WaitForTailscaleLogout() {
for _, user := range s.users {
for _, client := range user.Clients {
user.syncWaitGroup.Add(1)
go func(c TailscaleClient) {
defer user.syncWaitGroup.Done()
// TODO(kradalby): error handle this
_ = c.WaitForLogout()
}(client)
}
user.syncWaitGroup.Wait()
}
}

View File

@@ -31,7 +31,7 @@ func TestHeadscale(t *testing.T) {
var err error
user := "test-space"
namespace := "test-space"
scenario, err := NewScenario()
if err != nil {
@@ -50,19 +50,19 @@ func TestHeadscale(t *testing.T) {
}
})
t.Run("create-user", func(t *testing.T) {
err := scenario.CreateUser(user)
t.Run("create-namespace", func(t *testing.T) {
err := scenario.CreateNamespace(namespace)
if err != nil {
t.Errorf("failed to create user: %s", err)
t.Errorf("failed to create namespace: %s", err)
}
if _, ok := scenario.users[user]; !ok {
t.Errorf("user is not in scenario")
if _, ok := scenario.namespaces[namespace]; !ok {
t.Errorf("namespace is not in scenario")
}
})
t.Run("create-auth-key", func(t *testing.T) {
_, err := scenario.CreatePreAuthKey(user, true, false)
_, err := scenario.CreatePreAuthKey(namespace)
if err != nil {
t.Errorf("failed to create preauthkey: %s", err)
}
@@ -82,24 +82,24 @@ func TestCreateTailscale(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
user := "only-create-containers"
namespace := "only-create-containers"
scenario, err := NewScenario()
if err != nil {
t.Errorf("failed to create scenario: %s", err)
}
scenario.users[user] = &User{
scenario.namespaces[namespace] = &Namespace{
Clients: make(map[string]TailscaleClient),
}
t.Run("create-tailscale", func(t *testing.T) {
err := scenario.CreateTailscaleNodesInUser(user, "all", 3)
err := scenario.CreateTailscaleNodesInNamespace(namespace, "all", 3)
if err != nil {
t.Errorf("failed to add tailscale nodes: %s", err)
}
if clients := len(scenario.users[user].Clients); clients != 3 {
if clients := len(scenario.namespaces[namespace].Clients); clients != 3 {
t.Errorf("wrong number of tailscale clients: %d != %d", clients, 3)
}
@@ -122,7 +122,7 @@ func TestTailscaleNodesJoiningHeadcale(t *testing.T) {
var err error
user := "join-node-test"
namespace := "join-node-test"
count := 1
@@ -143,30 +143,30 @@ func TestTailscaleNodesJoiningHeadcale(t *testing.T) {
}
})
t.Run("create-user", func(t *testing.T) {
err := scenario.CreateUser(user)
t.Run("create-namespace", func(t *testing.T) {
err := scenario.CreateNamespace(namespace)
if err != nil {
t.Errorf("failed to create user: %s", err)
t.Errorf("failed to create namespace: %s", err)
}
if _, ok := scenario.users[user]; !ok {
t.Errorf("user is not in scenario")
if _, ok := scenario.namespaces[namespace]; !ok {
t.Errorf("namespace is not in scenario")
}
})
t.Run("create-tailscale", func(t *testing.T) {
err := scenario.CreateTailscaleNodesInUser(user, "1.30.2", count)
err := scenario.CreateTailscaleNodesInNamespace(namespace, "1.30.2", count)
if err != nil {
t.Errorf("failed to add tailscale nodes: %s", err)
}
if clients := len(scenario.users[user].Clients); clients != count {
if clients := len(scenario.namespaces[namespace].Clients); clients != count {
t.Errorf("wrong number of tailscale clients: %d != %d", clients, count)
}
})
t.Run("join-headscale", func(t *testing.T) {
key, err := scenario.CreatePreAuthKey(user, true, false)
key, err := scenario.CreatePreAuthKey(namespace)
if err != nil {
t.Errorf("failed to create preauthkey: %s", err)
}
@@ -177,7 +177,7 @@ func TestTailscaleNodesJoiningHeadcale(t *testing.T) {
}
err = scenario.RunTailscaleUp(
user,
namespace,
headscale.GetEndpoint(),
key.GetKey(),
)
@@ -187,7 +187,7 @@ func TestTailscaleNodesJoiningHeadcale(t *testing.T) {
})
t.Run("get-ips", func(t *testing.T) {
ips, err := scenario.GetIPs(user)
ips, err := scenario.GetIPs(namespace)
if err != nil {
t.Errorf("failed to get tailscale ips: %s", err)
}

View File

@@ -41,7 +41,7 @@ var retry = func(times int, sleepInterval time.Duration,
return result, stderr, err
}
func TestSSHOneUserAllToAll(t *testing.T) {
func TestSSHOneNamespaceAllToAll(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
@@ -51,7 +51,7 @@ func TestSSHOneUserAllToAll(t *testing.T) {
}
spec := map[string]int{
"user1": len(TailscaleVersions) - 5,
"namespace1": len(TailscaleVersions) - 5,
}
err = scenario.CreateHeadscaleEnv(spec,
@@ -59,7 +59,7 @@ func TestSSHOneUserAllToAll(t *testing.T) {
hsic.WithACLPolicy(
&headscale.ACLPolicy{
Groups: map[string][]string{
"group:integration-test": {"user1"},
"group:integration-test": {"namespace1"},
},
ACLs: []headscale.ACL{
{
@@ -117,7 +117,7 @@ func TestSSHOneUserAllToAll(t *testing.T) {
}
}
func TestSSHMultipleUsersAllToAll(t *testing.T) {
func TestSSHMultipleNamespacesAllToAll(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
@@ -127,8 +127,8 @@ func TestSSHMultipleUsersAllToAll(t *testing.T) {
}
spec := map[string]int{
"user1": len(TailscaleVersions) - 5,
"user2": len(TailscaleVersions) - 5,
"namespace1": len(TailscaleVersions) - 5,
"namespace2": len(TailscaleVersions) - 5,
}
err = scenario.CreateHeadscaleEnv(spec,
@@ -136,7 +136,7 @@ func TestSSHMultipleUsersAllToAll(t *testing.T) {
hsic.WithACLPolicy(
&headscale.ACLPolicy{
Groups: map[string][]string{
"group:integration-test": {"user1", "user2"},
"group:integration-test": {"namespace1", "namespace2"},
},
ACLs: []headscale.ACL{
{
@@ -163,12 +163,12 @@ func TestSSHMultipleUsersAllToAll(t *testing.T) {
t.Errorf("failed to create headscale environment: %s", err)
}
nsOneClients, err := scenario.ListTailscaleClients("user1")
nsOneClients, err := scenario.ListTailscaleClients("namespace1")
if err != nil {
t.Errorf("failed to get clients: %s", err)
}
nsTwoClients, err := scenario.ListTailscaleClients("user2")
nsTwoClients, err := scenario.ListTailscaleClients("namespace2")
if err != nil {
t.Errorf("failed to get clients: %s", err)
}
@@ -183,7 +183,7 @@ func TestSSHMultipleUsersAllToAll(t *testing.T) {
t.Errorf("failed to get FQDNs: %s", err)
}
testInterUserSSH := func(sourceClients []TailscaleClient, targetClients []TailscaleClient) {
testInterNamespaceSSH := func(sourceClients []TailscaleClient, targetClients []TailscaleClient) {
for _, client := range sourceClients {
for _, peer := range targetClients {
assertSSHHostname(t, client, peer)
@@ -191,8 +191,8 @@ func TestSSHMultipleUsersAllToAll(t *testing.T) {
}
}
testInterUserSSH(nsOneClients, nsTwoClients)
testInterUserSSH(nsTwoClients, nsOneClients)
testInterNamespaceSSH(nsOneClients, nsTwoClients)
testInterNamespaceSSH(nsTwoClients, nsOneClients)
err = scenario.Shutdown()
if err != nil {
@@ -210,7 +210,7 @@ func TestSSHNoSSHConfigured(t *testing.T) {
}
spec := map[string]int{
"user1": len(TailscaleVersions) - 5,
"namespace1": len(TailscaleVersions) - 5,
}
err = scenario.CreateHeadscaleEnv(spec,
@@ -218,7 +218,7 @@ func TestSSHNoSSHConfigured(t *testing.T) {
hsic.WithACLPolicy(
&headscale.ACLPolicy{
Groups: map[string][]string{
"group:integration-test": {"user1"},
"group:integration-test": {"namespace1"},
},
ACLs: []headscale.ACL{
{
@@ -280,7 +280,7 @@ func TestSSHIsBlockedInACL(t *testing.T) {
}
spec := map[string]int{
"user1": len(TailscaleVersions) - 5,
"namespace1": len(TailscaleVersions) - 5,
}
err = scenario.CreateHeadscaleEnv(spec,
@@ -288,7 +288,7 @@ func TestSSHIsBlockedInACL(t *testing.T) {
hsic.WithACLPolicy(
&headscale.ACLPolicy{
Groups: map[string][]string{
"group:integration-test": {"user1"},
"group:integration-test": {"namespace1"},
},
ACLs: []headscale.ACL{
{
@@ -347,7 +347,7 @@ func TestSSHIsBlockedInACL(t *testing.T) {
}
}
func TestSSUserOnlyIsolation(t *testing.T) {
func TestSSNamespaceOnlyIsolation(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
@@ -357,8 +357,8 @@ func TestSSUserOnlyIsolation(t *testing.T) {
}
spec := map[string]int{
"useracl1": len(TailscaleVersions) - 5,
"useracl2": len(TailscaleVersions) - 5,
"namespaceacl1": len(TailscaleVersions) - 5,
"namespaceacl2": len(TailscaleVersions) - 5,
}
err = scenario.CreateHeadscaleEnv(spec,
@@ -366,8 +366,8 @@ func TestSSUserOnlyIsolation(t *testing.T) {
hsic.WithACLPolicy(
&headscale.ACLPolicy{
Groups: map[string][]string{
"group:ssh1": {"useracl1"},
"group:ssh2": {"useracl2"},
"group:ssh1": {"namespaceacl1"},
"group:ssh2": {"namespaceacl2"},
},
ACLs: []headscale.ACL{
{
@@ -392,7 +392,7 @@ func TestSSUserOnlyIsolation(t *testing.T) {
},
},
),
hsic.WithTestName("sshtwouseraclblock"),
hsic.WithTestName("sshtwonamespaceaclblock"),
hsic.WithConfigEnv(map[string]string{
"HEADSCALE_EXPERIMENTAL_FEATURE_SSH": "1",
}),
@@ -401,12 +401,12 @@ func TestSSUserOnlyIsolation(t *testing.T) {
t.Errorf("failed to create headscale environment: %s", err)
}
ssh1Clients, err := scenario.ListTailscaleClients("useracl1")
ssh1Clients, err := scenario.ListTailscaleClients("namespaceacl1")
if err != nil {
t.Errorf("failed to get clients: %s", err)
}
ssh2Clients, err := scenario.ListTailscaleClients("useracl2")
ssh2Clients, err := scenario.ListTailscaleClients("namespaceacl2")
if err != nil {
t.Errorf("failed to get clients: %s", err)
}

View File

@@ -138,12 +138,12 @@ func (s *IntegrationCLITestSuite) HandleStats(
s.stats = stats
}
func (s *IntegrationCLITestSuite) createUser(name string) (*v1.User, error) {
func (s *IntegrationCLITestSuite) createNamespace(name string) (*v1.Namespace, error) {
result, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
"users",
"namespaces",
"create",
name,
"--output",
@@ -155,38 +155,38 @@ func (s *IntegrationCLITestSuite) createUser(name string) (*v1.User, error) {
return nil, err
}
var user v1.User
err = json.Unmarshal([]byte(result), &user)
var namespace v1.Namespace
err = json.Unmarshal([]byte(result), &namespace)
if err != nil {
return nil, err
}
return &user, nil
return &namespace, nil
}
func (s *IntegrationCLITestSuite) TestUserCommand() {
names := []string{"user1", "otherspace", "tasty"}
users := make([]*v1.User, len(names))
func (s *IntegrationCLITestSuite) TestNamespaceCommand() {
names := []string{"namespace1", "otherspace", "tasty"}
namespaces := make([]*v1.Namespace, len(names))
for index, userName := range names {
user, err := s.createUser(userName)
for index, namespaceName := range names {
namespace, err := s.createNamespace(namespaceName)
assert.Nil(s.T(), err)
users[index] = user
namespaces[index] = namespace
}
assert.Len(s.T(), users, len(names))
assert.Len(s.T(), namespaces, len(names))
assert.Equal(s.T(), names[0], users[0].Name)
assert.Equal(s.T(), names[1], users[1].Name)
assert.Equal(s.T(), names[2], users[2].Name)
assert.Equal(s.T(), names[0], namespaces[0].Name)
assert.Equal(s.T(), names[1], namespaces[1].Name)
assert.Equal(s.T(), names[2], namespaces[2].Name)
// Test list users
// Test list namespaces
listResult, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
"users",
"namespaces",
"list",
"--output",
"json",
@@ -195,20 +195,20 @@ func (s *IntegrationCLITestSuite) TestUserCommand() {
)
assert.Nil(s.T(), err)
var listedUsers []v1.User
err = json.Unmarshal([]byte(listResult), &listedUsers)
var listedNamespaces []v1.Namespace
err = json.Unmarshal([]byte(listResult), &listedNamespaces)
assert.Nil(s.T(), err)
assert.Equal(s.T(), names[0], listedUsers[0].Name)
assert.Equal(s.T(), names[1], listedUsers[1].Name)
assert.Equal(s.T(), names[2], listedUsers[2].Name)
assert.Equal(s.T(), names[0], listedNamespaces[0].Name)
assert.Equal(s.T(), names[1], listedNamespaces[1].Name)
assert.Equal(s.T(), names[2], listedNamespaces[2].Name)
// Test rename user
// Test rename namespace
renameResult, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
"users",
"namespaces",
"rename",
"--output",
"json",
@@ -219,18 +219,18 @@ func (s *IntegrationCLITestSuite) TestUserCommand() {
)
assert.Nil(s.T(), err)
var renamedUser v1.User
err = json.Unmarshal([]byte(renameResult), &renamedUser)
var renamedNamespace v1.Namespace
err = json.Unmarshal([]byte(renameResult), &renamedNamespace)
assert.Nil(s.T(), err)
assert.Equal(s.T(), renamedUser.Name, "newname")
assert.Equal(s.T(), renamedNamespace.Name, "newname")
// Test list after rename users
// Test list after rename namespaces
listAfterRenameResult, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
"users",
"namespaces",
"list",
"--output",
"json",
@@ -239,19 +239,19 @@ func (s *IntegrationCLITestSuite) TestUserCommand() {
)
assert.Nil(s.T(), err)
var listedAfterRenameUsers []v1.User
err = json.Unmarshal([]byte(listAfterRenameResult), &listedAfterRenameUsers)
var listedAfterRenameNamespaces []v1.Namespace
err = json.Unmarshal([]byte(listAfterRenameResult), &listedAfterRenameNamespaces)
assert.Nil(s.T(), err)
assert.Equal(s.T(), names[0], listedAfterRenameUsers[0].Name)
assert.Equal(s.T(), names[1], listedAfterRenameUsers[1].Name)
assert.Equal(s.T(), "newname", listedAfterRenameUsers[2].Name)
assert.Equal(s.T(), names[0], listedAfterRenameNamespaces[0].Name)
assert.Equal(s.T(), names[1], listedAfterRenameNamespaces[1].Name)
assert.Equal(s.T(), "newname", listedAfterRenameNamespaces[2].Name)
}
func (s *IntegrationCLITestSuite) TestPreAuthKeyCommand() {
count := 5
user, err := s.createUser("pre-auth-key-user")
namespace, err := s.createNamespace("pre-auth-key-namespace")
keys := make([]*v1.PreAuthKey, count)
assert.Nil(s.T(), err)
@@ -262,8 +262,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommand() {
[]string{
"headscale",
"preauthkeys",
"--user",
user.Name,
"--namespace",
namespace.Name,
"create",
"--reusable",
"--expiration",
@@ -292,8 +292,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommand() {
[]string{
"headscale",
"preauthkeys",
"--user",
user.Name,
"--namespace",
namespace.Name,
"list",
"--output",
"json",
@@ -357,8 +357,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommand() {
[]string{
"headscale",
"preauthkeys",
"--user",
user.Name,
"--namespace",
namespace.Name,
"expire",
listedPreAuthKeys[i].Key,
},
@@ -373,8 +373,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommand() {
[]string{
"headscale",
"preauthkeys",
"--user",
user.Name,
"--namespace",
namespace.Name,
"list",
"--output",
"json",
@@ -410,7 +410,7 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommand() {
}
func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandWithoutExpiry() {
user, err := s.createUser("pre-auth-key-without-exp-user")
namespace, err := s.createNamespace("pre-auth-key-without-exp-namespace")
assert.Nil(s.T(), err)
preAuthResult, _, err := ExecuteCommand(
@@ -418,8 +418,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandWithoutExpiry() {
[]string{
"headscale",
"preauthkeys",
"--user",
user.Name,
"--namespace",
namespace.Name,
"create",
"--reusable",
"--output",
@@ -439,8 +439,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandWithoutExpiry() {
[]string{
"headscale",
"preauthkeys",
"--user",
user.Name,
"--namespace",
namespace.Name,
"list",
"--output",
"json",
@@ -463,7 +463,7 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandWithoutExpiry() {
}
func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandReusableEphemeral() {
user, err := s.createUser("pre-auth-key-reus-ephm-user")
namespace, err := s.createNamespace("pre-auth-key-reus-ephm-namespace")
assert.Nil(s.T(), err)
preAuthReusableResult, _, err := ExecuteCommand(
@@ -471,8 +471,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandReusableEphemeral() {
[]string{
"headscale",
"preauthkeys",
"--user",
user.Name,
"--namespace",
namespace.Name,
"create",
"--reusable=true",
"--output",
@@ -494,8 +494,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandReusableEphemeral() {
[]string{
"headscale",
"preauthkeys",
"--user",
user.Name,
"--namespace",
namespace.Name,
"create",
"--ephemeral=true",
"--output",
@@ -518,8 +518,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandReusableEphemeral() {
// []string{
// "headscale",
// "preauthkeys",
// "--user",
// user.Name,
// "--namespace",
// namespace.Name,
// "create",
// "--ephemeral",
// "--reusable",
@@ -536,8 +536,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandReusableEphemeral() {
[]string{
"headscale",
"preauthkeys",
"--user",
user.Name,
"--namespace",
namespace.Name,
"list",
"--output",
"json",
@@ -554,7 +554,7 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandReusableEphemeral() {
}
func (s *IntegrationCLITestSuite) TestNodeTagCommand() {
user, err := s.createUser("machine-user")
namespace, err := s.createNamespace("machine-namespace")
assert.Nil(s.T(), err)
machineKeys := []string{
@@ -573,8 +573,8 @@ func (s *IntegrationCLITestSuite) TestNodeTagCommand() {
"create-node",
"--name",
fmt.Sprintf("machine-%d", index+1),
"--user",
user.Name,
"--namespace",
namespace.Name,
"--key",
machineKey,
"--output",
@@ -589,8 +589,8 @@ func (s *IntegrationCLITestSuite) TestNodeTagCommand() {
[]string{
"headscale",
"nodes",
"--user",
user.Name,
"--namespace",
namespace.Name,
"register",
"--key",
machineKey,
@@ -683,10 +683,10 @@ func (s *IntegrationCLITestSuite) TestNodeTagCommand() {
}
func (s *IntegrationCLITestSuite) TestNodeCommand() {
user, err := s.createUser("machine-user")
namespace, err := s.createNamespace("machine-namespace")
assert.Nil(s.T(), err)
secondUser, err := s.createUser("other-user")
secondNamespace, err := s.createNamespace("other-namespace")
assert.Nil(s.T(), err)
// Randomly generated machine keys
@@ -709,8 +709,8 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
"create-node",
"--name",
fmt.Sprintf("machine-%d", index+1),
"--user",
user.Name,
"--namespace",
namespace.Name,
"--key",
machineKey,
"--output",
@@ -725,8 +725,8 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
[]string{
"headscale",
"nodes",
"--user",
user.Name,
"--namespace",
namespace.Name,
"register",
"--key",
machineKey,
@@ -778,14 +778,14 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
assert.Equal(s.T(), "machine-4", listAll[3].Name)
assert.Equal(s.T(), "machine-5", listAll[4].Name)
otherUserMachineKeys := []string{
otherNamespaceMachineKeys := []string{
"nodekey:b5b444774186d4217adcec407563a1223929465ee2c68a4da13af0d0185b4f8e",
"nodekey:dc721977ac7415aafa87f7d4574cbe07c6b171834a6d37375782bdc1fb6b3584",
}
otherUserMachines := make([]*v1.Machine, len(otherUserMachineKeys))
otherNamespaceMachines := make([]*v1.Machine, len(otherNamespaceMachineKeys))
assert.Nil(s.T(), err)
for index, machineKey := range otherUserMachineKeys {
for index, machineKey := range otherNamespaceMachineKeys {
_, _, err := ExecuteCommand(
&s.headscale,
[]string{
@@ -793,9 +793,9 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
"debug",
"create-node",
"--name",
fmt.Sprintf("otherUser-machine-%d", index+1),
"--user",
secondUser.Name,
fmt.Sprintf("otherNamespace-machine-%d", index+1),
"--namespace",
secondNamespace.Name,
"--key",
machineKey,
"--output",
@@ -810,8 +810,8 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
[]string{
"headscale",
"nodes",
"--user",
secondUser.Name,
"--namespace",
secondNamespace.Name,
"register",
"--key",
machineKey,
@@ -826,13 +826,13 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
err = json.Unmarshal([]byte(machineResult), &machine)
assert.Nil(s.T(), err)
otherUserMachines[index] = &machine
otherNamespaceMachines[index] = &machine
}
assert.Len(s.T(), otherUserMachines, len(otherUserMachineKeys))
assert.Len(s.T(), otherNamespaceMachines, len(otherNamespaceMachineKeys))
// Test list all nodes after added otherUser
listAllWithotherUserResult, _, err := ExecuteCommand(
// Test list all nodes after added otherNamespace
listAllWithotherNamespaceResult, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
@@ -845,31 +845,31 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
)
assert.Nil(s.T(), err)
var listAllWithotherUser []v1.Machine
var listAllWithotherNamespace []v1.Machine
err = json.Unmarshal(
[]byte(listAllWithotherUserResult),
&listAllWithotherUser,
[]byte(listAllWithotherNamespaceResult),
&listAllWithotherNamespace,
)
assert.Nil(s.T(), err)
// All nodes, machines + otherUser
assert.Len(s.T(), listAllWithotherUser, 7)
// All nodes, machines + otherNamespace
assert.Len(s.T(), listAllWithotherNamespace, 7)
assert.Equal(s.T(), uint64(6), listAllWithotherUser[5].Id)
assert.Equal(s.T(), uint64(7), listAllWithotherUser[6].Id)
assert.Equal(s.T(), uint64(6), listAllWithotherNamespace[5].Id)
assert.Equal(s.T(), uint64(7), listAllWithotherNamespace[6].Id)
assert.Equal(s.T(), "otherUser-machine-1", listAllWithotherUser[5].Name)
assert.Equal(s.T(), "otherUser-machine-2", listAllWithotherUser[6].Name)
assert.Equal(s.T(), "otherNamespace-machine-1", listAllWithotherNamespace[5].Name)
assert.Equal(s.T(), "otherNamespace-machine-2", listAllWithotherNamespace[6].Name)
// Test list all nodes after added otherUser
listOnlyotherUserMachineUserResult, _, err := ExecuteCommand(
// Test list all nodes after added otherNamespace
listOnlyotherNamespaceMachineNamespaceResult, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
"nodes",
"list",
"--user",
secondUser.Name,
"--namespace",
secondNamespace.Name,
"--output",
"json",
},
@@ -877,27 +877,27 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
)
assert.Nil(s.T(), err)
var listOnlyotherUserMachineUser []v1.Machine
var listOnlyotherNamespaceMachineNamespace []v1.Machine
err = json.Unmarshal(
[]byte(listOnlyotherUserMachineUserResult),
&listOnlyotherUserMachineUser,
[]byte(listOnlyotherNamespaceMachineNamespaceResult),
&listOnlyotherNamespaceMachineNamespace,
)
assert.Nil(s.T(), err)
assert.Len(s.T(), listOnlyotherUserMachineUser, 2)
assert.Len(s.T(), listOnlyotherNamespaceMachineNamespace, 2)
assert.Equal(s.T(), uint64(6), listOnlyotherUserMachineUser[0].Id)
assert.Equal(s.T(), uint64(7), listOnlyotherUserMachineUser[1].Id)
assert.Equal(s.T(), uint64(6), listOnlyotherNamespaceMachineNamespace[0].Id)
assert.Equal(s.T(), uint64(7), listOnlyotherNamespaceMachineNamespace[1].Id)
assert.Equal(
s.T(),
"otherUser-machine-1",
listOnlyotherUserMachineUser[0].Name,
"otherNamespace-machine-1",
listOnlyotherNamespaceMachineNamespace[0].Name,
)
assert.Equal(
s.T(),
"otherUser-machine-2",
listOnlyotherUserMachineUser[1].Name,
"otherNamespace-machine-2",
listOnlyotherNamespaceMachineNamespace[1].Name,
)
// Delete a machines
@@ -918,15 +918,15 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
)
assert.Nil(s.T(), err)
// Test: list main user after machine is deleted
listOnlyMachineUserAfterDeleteResult, _, err := ExecuteCommand(
// Test: list main namespace after machine is deleted
listOnlyMachineNamespaceAfterDeleteResult, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
"nodes",
"list",
"--user",
user.Name,
"--namespace",
namespace.Name,
"--output",
"json",
},
@@ -934,18 +934,18 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
)
assert.Nil(s.T(), err)
var listOnlyMachineUserAfterDelete []v1.Machine
var listOnlyMachineNamespaceAfterDelete []v1.Machine
err = json.Unmarshal(
[]byte(listOnlyMachineUserAfterDeleteResult),
&listOnlyMachineUserAfterDelete,
[]byte(listOnlyMachineNamespaceAfterDeleteResult),
&listOnlyMachineNamespaceAfterDelete,
)
assert.Nil(s.T(), err)
assert.Len(s.T(), listOnlyMachineUserAfterDelete, 4)
assert.Len(s.T(), listOnlyMachineNamespaceAfterDelete, 4)
}
func (s *IntegrationCLITestSuite) TestNodeExpireCommand() {
user, err := s.createUser("machine-expire-user")
namespace, err := s.createNamespace("machine-expire-namespace")
assert.Nil(s.T(), err)
// Randomly generated machine keys
@@ -968,8 +968,8 @@ func (s *IntegrationCLITestSuite) TestNodeExpireCommand() {
"create-node",
"--name",
fmt.Sprintf("machine-%d", index+1),
"--user",
user.Name,
"--namespace",
namespace.Name,
"--key",
machineKey,
"--output",
@@ -984,8 +984,8 @@ func (s *IntegrationCLITestSuite) TestNodeExpireCommand() {
[]string{
"headscale",
"nodes",
"--user",
user.Name,
"--namespace",
namespace.Name,
"register",
"--key",
machineKey,
@@ -1072,7 +1072,7 @@ func (s *IntegrationCLITestSuite) TestNodeExpireCommand() {
}
func (s *IntegrationCLITestSuite) TestNodeRenameCommand() {
user, err := s.createUser("machine-rename-command")
namespace, err := s.createNamespace("machine-rename-command")
assert.Nil(s.T(), err)
// Randomly generated machine keys
@@ -1095,8 +1095,8 @@ func (s *IntegrationCLITestSuite) TestNodeRenameCommand() {
"create-node",
"--name",
fmt.Sprintf("machine-%d", index+1),
"--user",
user.Name,
"--namespace",
namespace.Name,
"--key",
machineKey,
"--output",
@@ -1111,8 +1111,8 @@ func (s *IntegrationCLITestSuite) TestNodeRenameCommand() {
[]string{
"headscale",
"nodes",
"--user",
user.Name,
"--namespace",
namespace.Name,
"register",
"--key",
machineKey,
@@ -1389,9 +1389,9 @@ func (s *IntegrationCLITestSuite) TestApiKeyCommand() {
}
func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
oldUser, err := s.createUser("old-user")
oldNamespace, err := s.createNamespace("old-namespace")
assert.Nil(s.T(), err)
newUser, err := s.createUser("new-user")
newNamespace, err := s.createNamespace("new-namespace")
assert.Nil(s.T(), err)
// Randomly generated machine key
@@ -1405,8 +1405,8 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
"create-node",
"--name",
"nomad-machine",
"--user",
oldUser.Name,
"--namespace",
oldNamespace.Name,
"--key",
machineKey,
"--output",
@@ -1421,8 +1421,8 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
[]string{
"headscale",
"nodes",
"--user",
oldUser.Name,
"--namespace",
oldNamespace.Name,
"register",
"--key",
machineKey,
@@ -1439,7 +1439,7 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
assert.Equal(s.T(), uint64(1), machine.Id)
assert.Equal(s.T(), "nomad-machine", machine.Name)
assert.Equal(s.T(), machine.User.Name, oldUser.Name)
assert.Equal(s.T(), machine.Namespace.Name, oldNamespace.Name)
machineId := fmt.Sprintf("%d", machine.Id)
@@ -1451,8 +1451,8 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
"move",
"--identifier",
machineId,
"--user",
newUser.Name,
"--namespace",
newNamespace.Name,
"--output",
"json",
},
@@ -1463,7 +1463,7 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
err = json.Unmarshal([]byte(moveToNewNSResult), &machine)
assert.Nil(s.T(), err)
assert.Equal(s.T(), machine.User, newUser)
assert.Equal(s.T(), machine.Namespace, newNamespace)
listAllNodesResult, _, err := ExecuteCommand(
&s.headscale,
@@ -1485,8 +1485,8 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
assert.Len(s.T(), allNodes, 1)
assert.Equal(s.T(), allNodes[0].Id, machine.Id)
assert.Equal(s.T(), allNodes[0].User, machine.User)
assert.Equal(s.T(), allNodes[0].User, newUser)
assert.Equal(s.T(), allNodes[0].Namespace, machine.Namespace)
assert.Equal(s.T(), allNodes[0].Namespace, newNamespace)
moveToNonExistingNSResult, _, err := ExecuteCommand(
&s.headscale,
@@ -1496,8 +1496,8 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
"move",
"--identifier",
machineId,
"--user",
"non-existing-user",
"--namespace",
"non-existing-namespace",
"--output",
"json",
},
@@ -1508,9 +1508,9 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
assert.Contains(
s.T(),
string(moveToNonExistingNSResult),
"User not found",
"Namespace not found",
)
assert.Equal(s.T(), machine.User, newUser)
assert.Equal(s.T(), machine.Namespace, newNamespace)
moveToOldNSResult, _, err := ExecuteCommand(
&s.headscale,
@@ -1520,8 +1520,8 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
"move",
"--identifier",
machineId,
"--user",
oldUser.Name,
"--namespace",
oldNamespace.Name,
"--output",
"json",
},
@@ -1532,7 +1532,7 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
err = json.Unmarshal([]byte(moveToOldNSResult), &machine)
assert.Nil(s.T(), err)
assert.Equal(s.T(), machine.User, oldUser)
assert.Equal(s.T(), machine.Namespace, oldNamespace)
moveToSameNSResult, _, err := ExecuteCommand(
&s.headscale,
@@ -1542,8 +1542,8 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
"move",
"--identifier",
machineId,
"--user",
oldUser.Name,
"--namespace",
oldNamespace.Name,
"--output",
"json",
},
@@ -1554,7 +1554,7 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
err = json.Unmarshal([]byte(moveToSameNSResult), &machine)
assert.Nil(s.T(), err)
assert.Equal(s.T(), machine.User, oldUser)
assert.Equal(s.T(), machine.Namespace, oldNamespace)
}
func (s *IntegrationCLITestSuite) TestLoadConfigFromCommand() {

View File

@@ -1,4 +1,4 @@
// nolint
//nolint
package headscale
import (
@@ -47,7 +47,7 @@ var (
}
)
type TestUser struct {
type TestNamespace struct {
count int
tailscales map[string]dockertest.Resource
}
@@ -296,7 +296,7 @@ func getMagicFQDN(
hostnames[index] = fmt.Sprintf(
"%s.%s.headscale.net",
listAll[index].GetGivenName(),
listAll[index].GetUser().GetName(),
listAll[index].GetNamespace().GetName(),
)
}

View File

@@ -1,4 +1,4 @@
// nolint
//nolint
package headscale
import (
@@ -26,7 +26,7 @@ import (
const (
headscaleDerpHostname = "headscale-derp"
userName = "derpuser"
namespaceName = "derpnamespace"
totalContainers = 3
)
@@ -199,22 +199,22 @@ func (s *IntegrationDERPTestSuite) SetupSuite() {
}
log.Println("headscale container is ready for embedded DERP tests")
log.Printf("Creating headscale user: %s\n", userName)
log.Printf("Creating headscale namespace: %s\n", namespaceName)
result, _, err := ExecuteCommand(
&s.headscale,
[]string{"headscale", "users", "create", userName},
[]string{"headscale", "namespaces", "create", namespaceName},
[]string{},
)
log.Println("headscale create user result: ", result)
log.Println("headscale create namespace result: ", result)
assert.Nil(s.T(), err)
log.Printf("Creating pre auth key for %s\n", userName)
log.Printf("Creating pre auth key for %s\n", namespaceName)
preAuthResult, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
"--user",
userName,
"--namespace",
namespaceName,
"preauthkeys",
"create",
"--reusable",

View File

@@ -27,8 +27,8 @@ const (
)
ErrCouldNotConvertMachineInterface = Error("failed to convert machine interface")
ErrHostnameTooLong = Error("Hostname too long")
ErrDifferentRegisteredUser = Error(
"machine was previously registered with a different user",
ErrDifferentRegisteredNamespace = Error(
"machine was previously registered with a different namespace",
)
MachineGivenNameHashLength = 8
MachineGivenNameTrimSize = 2
@@ -56,9 +56,9 @@ type Machine struct {
//
// GivenName is the name used in all DNS related
// parts of headscale.
GivenName string `gorm:"type:varchar(63);unique_index"`
UserID uint
User User `gorm:"foreignKey:UserID"`
GivenName string `gorm:"type:varchar(63);unique_index"`
NamespaceID uint
Namespace Namespace `gorm:"foreignKey:NamespaceID"`
RegisterMethod string
@@ -153,15 +153,9 @@ func (machine *Machine) isOnline() bool {
return machine.LastSeen.After(time.Now().Add(-keepAliveInterval))
}
// isEphemeral returns if the machine is registered as an Ephemeral node.
// https://tailscale.com/kb/1111/ephemeral-nodes/
func (machine *Machine) isEphemeral() bool {
return machine.AuthKey != nil && machine.AuthKey.Ephemeral
}
func containsAddresses(inputs []string, addrs []string) bool {
for _, addr := range addrs {
if containsStr(inputs, addr) {
if contains(inputs, addr) {
return true
}
}
@@ -192,9 +186,8 @@ func getFilteredByACLPeers(
Msg("Finding peers filtered by ACLs")
peers := make(map[uint64]Machine)
// Aclfilter peers here. We are itering through machines in all users and search through the computed aclRules
// Aclfilter peers here. We are itering through machines in all namespaces and search through the computed aclRules
// for match between rule SrcIPs and DstPorts. If the rule is a match we allow the machine to be viewable.
machineIPs := machine.IPAddresses.ToStringSlice()
for _, peer := range machines {
if peer.ID == machine.ID {
continue
@@ -204,23 +197,22 @@ func getFilteredByACLPeers(
for _, d := range rule.DstPorts {
dst = append(dst, d.IP)
}
peerIPs := peer.IPAddresses.ToStringSlice()
if matchSourceAndDestinationWithRule(
rule.SrcIPs,
dst,
machineIPs,
peerIPs,
machine.IPAddresses.ToStringSlice(),
peer.IPAddresses.ToStringSlice(),
) || // match source and destination
matchSourceAndDestinationWithRule(
rule.SrcIPs,
dst,
peerIPs,
machineIPs,
peer.IPAddresses.ToStringSlice(),
machine.IPAddresses.ToStringSlice(),
) || // match return path
matchSourceAndDestinationWithRule(
rule.SrcIPs,
dst,
machineIPs,
machine.IPAddresses.ToStringSlice(),
[]string{"*"},
) || // match source and all destination
matchSourceAndDestinationWithRule(
@@ -233,13 +225,13 @@ func getFilteredByACLPeers(
rule.SrcIPs,
dst,
[]string{"*"},
peerIPs,
peer.IPAddresses.ToStringSlice(),
) || // match source and all destination
matchSourceAndDestinationWithRule(
rule.SrcIPs,
dst,
[]string{"*"},
machineIPs,
machine.IPAddresses.ToStringSlice(),
) { // match all sources and source
peers[peer.ID] = peer
}
@@ -270,7 +262,7 @@ func (h *Headscale) ListPeers(machine *Machine) (Machines, error) {
Msg("Finding direct peers")
machines := Machines{}
if err := h.db.Preload("AuthKey").Preload("AuthKey.User").Preload("User").Where("node_key <> ?",
if err := h.db.Preload("AuthKey").Preload("AuthKey.Namespace").Preload("Namespace").Where("node_key <> ?",
machine.NodeKey).Find(&machines).Error; err != nil {
log.Error().Err(err).Msg("Error accessing db")
@@ -292,7 +284,7 @@ func (h *Headscale) getPeers(machine *Machine) (Machines, error) {
var err error
// If ACLs rules are defined, filter visible host list with the ACLs
// else use the classic user scope
// else use the classic namespace scope
if h.aclPolicy != nil {
var machines []Machine
machines, err = h.ListMachines()
@@ -343,7 +335,7 @@ func (h *Headscale) getValidPeers(machine *Machine) (Machines, error) {
func (h *Headscale) ListMachines() ([]Machine, error) {
machines := []Machine{}
if err := h.db.Preload("AuthKey").Preload("AuthKey.User").Preload("User").Find(&machines).Error; err != nil {
if err := h.db.Preload("AuthKey").Preload("AuthKey.Namespace").Preload("Namespace").Find(&machines).Error; err != nil {
return nil, err
}
@@ -352,16 +344,16 @@ func (h *Headscale) ListMachines() ([]Machine, error) {
func (h *Headscale) ListMachinesByGivenName(givenName string) ([]Machine, error) {
machines := []Machine{}
if err := h.db.Preload("AuthKey").Preload("AuthKey.User").Preload("User").Where("given_name = ?", givenName).Find(&machines).Error; err != nil {
if err := h.db.Preload("AuthKey").Preload("AuthKey.Namespace").Preload("Namespace").Find(&machines).Where("given_name = ?", givenName).Error; err != nil {
return nil, err
}
return machines, nil
}
// GetMachine finds a Machine by name and user and returns the Machine struct.
func (h *Headscale) GetMachine(user string, name string) (*Machine, error) {
machines, err := h.ListMachinesByUser(user)
// GetMachine finds a Machine by name and namespace and returns the Machine struct.
func (h *Headscale) GetMachine(namespace string, name string) (*Machine, error) {
machines, err := h.ListMachinesInNamespace(namespace)
if err != nil {
return nil, err
}
@@ -375,9 +367,9 @@ func (h *Headscale) GetMachine(user string, name string) (*Machine, error) {
return nil, ErrMachineNotFound
}
// GetMachineByGivenName finds a Machine by given name and user and returns the Machine struct.
func (h *Headscale) GetMachineByGivenName(user string, givenName string) (*Machine, error) {
machines, err := h.ListMachinesByUser(user)
// GetMachineByGivenName finds a Machine by given name and namespace and returns the Machine struct.
func (h *Headscale) GetMachineByGivenName(namespace string, givenName string) (*Machine, error) {
machines, err := h.ListMachinesInNamespace(namespace)
if err != nil {
return nil, err
}
@@ -394,7 +386,7 @@ func (h *Headscale) GetMachineByGivenName(user string, givenName string) (*Machi
// GetMachineByID finds a Machine by ID and returns the Machine struct.
func (h *Headscale) GetMachineByID(id uint64) (*Machine, error) {
m := Machine{}
if result := h.db.Preload("AuthKey").Preload("User").Find(&Machine{ID: id}).First(&m); result.Error != nil {
if result := h.db.Preload("Namespace").Find(&Machine{ID: id}).First(&m); result.Error != nil {
return nil, result.Error
}
@@ -406,7 +398,7 @@ func (h *Headscale) GetMachineByMachineKey(
machineKey key.MachinePublic,
) (*Machine, error) {
m := Machine{}
if result := h.db.Preload("AuthKey").Preload("User").First(&m, "machine_key = ?", MachinePublicKeyStripPrefix(machineKey)); result.Error != nil {
if result := h.db.Preload("Namespace").First(&m, "machine_key = ?", MachinePublicKeyStripPrefix(machineKey)); result.Error != nil {
return nil, result.Error
}
@@ -418,7 +410,7 @@ func (h *Headscale) GetMachineByNodeKey(
nodeKey key.NodePublic,
) (*Machine, error) {
machine := Machine{}
if result := h.db.Preload("AuthKey").Preload("User").First(&machine, "node_key = ?",
if result := h.db.Preload("Namespace").First(&machine, "node_key = ?",
NodePublicKeyStripPrefix(nodeKey)); result.Error != nil {
return nil, result.Error
}
@@ -431,7 +423,7 @@ func (h *Headscale) GetMachineByAnyKey(
machineKey key.MachinePublic, nodeKey key.NodePublic, oldNodeKey key.NodePublic,
) (*Machine, error) {
machine := Machine{}
if result := h.db.Preload("AuthKey").Preload("User").First(&machine, "machine_key = ? OR node_key = ? OR node_key = ?",
if result := h.db.Preload("Namespace").First(&machine, "machine_key = ? OR node_key = ? OR node_key = ?",
MachinePublicKeyStripPrefix(machineKey),
NodePublicKeyStripPrefix(nodeKey),
NodePublicKeyStripPrefix(oldNodeKey)); result.Error != nil {
@@ -570,9 +562,9 @@ func (h *Headscale) isOutdated(machine *Machine) bool {
return true
}
// Get the last update from all headscale users to compare with our nodes
// Get the last update from all headscale namespaces to compare with our nodes
// last update.
// TODO(kradalby): Only request updates from users where we can talk to nodes
// TODO(kradalby): Only request updates from namespaces where we can talk to nodes
// This would mostly be for a bit of performance, and can be calculated based on
// ACLs.
lastChange := h.getLastStateChange()
@@ -691,15 +683,7 @@ func (h *Headscale) toNode(
}
primaryPrefixes := Routes(primaryRoutes).toPrefixes()
machineRoutes, err := h.GetMachineRoutes(&machine)
if err != nil {
return nil, err
}
for _, route := range machineRoutes {
if route.Enabled && (route.IsPrimary || route.isExitRoute()) {
allowedIPs = append(allowedIPs, netip.Prefix(route.Prefix))
}
}
allowedIPs = append(allowedIPs, primaryPrefixes...)
var derp string
if machine.HostInfo.NetInfo != nil {
@@ -720,7 +704,7 @@ func (h *Headscale) toNode(
hostname = fmt.Sprintf(
"%s.%s.%s",
machine.GivenName,
machine.User.Name,
machine.Namespace.Name,
baseDomain,
)
if len(hostname) > maxHostnameLength {
@@ -744,7 +728,7 @@ func (h *Headscale) toNode(
strconv.FormatUint(machine.ID, Base10),
), // in headscale, unlike tailcontrol server, IDs are permanent
Name: hostname,
User: tailcfg.UserID(machine.UserID),
User: tailcfg.UserID(machine.NamespaceID),
Key: nodeKey,
KeyExpiry: keyExpiry,
Machine: machineKey,
@@ -782,7 +766,7 @@ func (machine *Machine) toProto() *v1.Machine {
IpAddresses: machine.IPAddresses.ToStringSlice(),
Name: machine.Hostname,
GivenName: machine.GivenName,
User: machine.User.toProto(),
Namespace: machine.Namespace.toProto(),
ForcedTags: machine.ForcedTags,
Online: machine.isOnline(),
@@ -837,7 +821,7 @@ func getTags(
}
var found bool
for _, owner := range owners {
if machine.User.Name == owner {
if machine.Namespace.Name == owner {
found = true
}
}
@@ -859,8 +843,7 @@ func getTags(
func (h *Headscale) RegisterMachineFromAuthCallback(
nodeKeyStr string,
userName string,
machineExpiry *time.Time,
namespaceName string,
registrationMethod string,
) (*Machine, error) {
nodeKey := key.NodePublic{}
@@ -871,34 +854,29 @@ func (h *Headscale) RegisterMachineFromAuthCallback(
log.Debug().
Str("nodeKey", nodeKey.ShortString()).
Str("userName", userName).
Str("namespaceName", namespaceName).
Str("registrationMethod", registrationMethod).
Str("expiresAt", fmt.Sprintf("%v", machineExpiry)).
Msg("Registering machine from API/CLI or auth callback")
if machineInterface, ok := h.registrationCache.Get(NodePublicKeyStripPrefix(nodeKey)); ok {
if registrationMachine, ok := machineInterface.(Machine); ok {
user, err := h.GetUser(userName)
namespace, err := h.GetNamespace(namespaceName)
if err != nil {
return nil, fmt.Errorf(
"failed to find user in register machine from auth callback, %w",
"failed to find namespace in register machine from auth callback, %w",
err,
)
}
// Registration of expired machine with different user
// Registration of expired machine with different namespace
if registrationMachine.ID != 0 &&
registrationMachine.UserID != user.ID {
return nil, ErrDifferentRegisteredUser
registrationMachine.NamespaceID != namespace.ID {
return nil, ErrDifferentRegisteredNamespace
}
registrationMachine.UserID = user.ID
registrationMachine.NamespaceID = namespace.ID
registrationMachine.RegisterMethod = registrationMethod
if machineExpiry != nil {
registrationMachine.Expiry = machineExpiry
}
machine, err := h.RegisterMachine(
registrationMachine,
)
@@ -923,7 +901,7 @@ func (h *Headscale) RegisterMachine(machine Machine,
Str("machine", machine.Hostname).
Str("machine_key", machine.MachineKey).
Str("node_key", machine.NodeKey).
Str("user", machine.User.Name).
Str("namespace", machine.Namespace.Name).
Msg("Registering machine")
// If the machine exists and we had already IPs for it, we just save it
@@ -939,7 +917,7 @@ func (h *Headscale) RegisterMachine(machine Machine,
Str("machine", machine.Hostname).
Str("machine_key", machine.MachineKey).
Str("node_key", machine.NodeKey).
Str("user", machine.User.Name).
Str("namespace", machine.Namespace.Name).
Msg("Machine authorized again")
return &machine, nil
@@ -1137,7 +1115,7 @@ func (h *Headscale) EnableAutoApprovedRoutes(machine *Machine) error {
}
for _, approvedAlias := range routeApprovers {
if approvedAlias == machine.User.Name {
if approvedAlias == machine.Namespace.Name {
approvedRoutes = append(approvedRoutes, advertisedRoute)
} else {
approvedIps, err := expandAlias([]Machine{*machine}, *h.aclPolicy, approvedAlias, h.cfg.OIDC.StripEmaildomain)

View File

@@ -15,10 +15,10 @@ import (
)
func (s *Suite) TestGetMachine(c *check.C) {
user, err := app.CreateUser("test")
namespace, err := app.CreateNamespace("test")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("test", "testmachine")
@@ -30,7 +30,7 @@ func (s *Suite) TestGetMachine(c *check.C) {
NodeKey: "bar",
DiscoKey: "faa",
Hostname: "testmachine",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
}
@@ -41,10 +41,10 @@ func (s *Suite) TestGetMachine(c *check.C) {
}
func (s *Suite) TestGetMachineByID(c *check.C) {
user, err := app.CreateUser("test")
namespace, err := app.CreateNamespace("test")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachineByID(0)
@@ -56,7 +56,7 @@ func (s *Suite) TestGetMachineByID(c *check.C) {
NodeKey: "bar",
DiscoKey: "faa",
Hostname: "testmachine",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
}
@@ -67,10 +67,10 @@ func (s *Suite) TestGetMachineByID(c *check.C) {
}
func (s *Suite) TestGetMachineByNodeKey(c *check.C) {
user, err := app.CreateUser("test")
namespace, err := app.CreateNamespace("test")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachineByID(0)
@@ -85,7 +85,7 @@ func (s *Suite) TestGetMachineByNodeKey(c *check.C) {
NodeKey: NodePublicKeyStripPrefix(nodeKey.Public()),
DiscoKey: "faa",
Hostname: "testmachine",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
}
@@ -96,10 +96,10 @@ func (s *Suite) TestGetMachineByNodeKey(c *check.C) {
}
func (s *Suite) TestGetMachineByAnyNodeKey(c *check.C) {
user, err := app.CreateUser("test")
namespace, err := app.CreateNamespace("test")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachineByID(0)
@@ -116,7 +116,7 @@ func (s *Suite) TestGetMachineByAnyNodeKey(c *check.C) {
NodeKey: NodePublicKeyStripPrefix(nodeKey.Public()),
DiscoKey: "faa",
Hostname: "testmachine",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
}
@@ -127,7 +127,7 @@ func (s *Suite) TestGetMachineByAnyNodeKey(c *check.C) {
}
func (s *Suite) TestDeleteMachine(c *check.C) {
user, err := app.CreateUser("test")
namespace, err := app.CreateNamespace("test")
c.Assert(err, check.IsNil)
machine := Machine{
ID: 0,
@@ -135,7 +135,7 @@ func (s *Suite) TestDeleteMachine(c *check.C) {
NodeKey: "bar",
DiscoKey: "faa",
Hostname: "testmachine",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(1),
}
@@ -144,12 +144,12 @@ func (s *Suite) TestDeleteMachine(c *check.C) {
err = app.DeleteMachine(&machine)
c.Assert(err, check.IsNil)
_, err = app.GetMachine(user.Name, "testmachine")
_, err = app.GetMachine(namespace.Name, "testmachine")
c.Assert(err, check.NotNil)
}
func (s *Suite) TestHardDeleteMachine(c *check.C) {
user, err := app.CreateUser("test")
namespace, err := app.CreateNamespace("test")
c.Assert(err, check.IsNil)
machine := Machine{
ID: 0,
@@ -157,7 +157,7 @@ func (s *Suite) TestHardDeleteMachine(c *check.C) {
NodeKey: "bar",
DiscoKey: "faa",
Hostname: "testmachine3",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(1),
}
@@ -166,15 +166,15 @@ func (s *Suite) TestHardDeleteMachine(c *check.C) {
err = app.HardDeleteMachine(&machine)
c.Assert(err, check.IsNil)
_, err = app.GetMachine(user.Name, "testmachine3")
_, err = app.GetMachine(namespace.Name, "testmachine3")
c.Assert(err, check.NotNil)
}
func (s *Suite) TestListPeers(c *check.C) {
user, err := app.CreateUser("test")
namespace, err := app.CreateNamespace("test")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachineByID(0)
@@ -187,7 +187,7 @@ func (s *Suite) TestListPeers(c *check.C) {
NodeKey: "bar" + strconv.Itoa(index),
DiscoKey: "faa" + strconv.Itoa(index),
Hostname: "testmachine" + strconv.Itoa(index),
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
}
@@ -208,18 +208,18 @@ func (s *Suite) TestListPeers(c *check.C) {
func (s *Suite) TestGetACLFilteredPeers(c *check.C) {
type base struct {
user *User
key *PreAuthKey
namespace *Namespace
key *PreAuthKey
}
stor := make([]base, 0)
for _, name := range []string{"test", "admin"} {
user, err := app.CreateUser(name)
namespace, err := app.CreateNamespace(name)
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
stor = append(stor, base{user, pak})
stor = append(stor, base{namespace, pak})
}
_, err := app.GetMachineByID(0)
@@ -235,7 +235,7 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) {
netip.MustParseAddr(fmt.Sprintf("100.64.0.%v", strconv.Itoa(index+1))),
},
Hostname: "testmachine" + strconv.Itoa(index),
UserID: stor[index%2].user.ID,
NamespaceID: stor[index%2].namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(stor[index%2].key.ID),
}
@@ -267,11 +267,11 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) {
c.Assert(err, check.IsNil)
adminMachine, err := app.GetMachineByID(1)
c.Logf("Machine(%v), user: %v", adminMachine.Hostname, adminMachine.User)
c.Logf("Machine(%v), namespace: %v", adminMachine.Hostname, adminMachine.Namespace)
c.Assert(err, check.IsNil)
testMachine, err := app.GetMachineByID(2)
c.Logf("Machine(%v), user: %v", testMachine.Hostname, testMachine.User)
c.Logf("Machine(%v), namespace: %v", testMachine.Hostname, testMachine.Namespace)
c.Assert(err, check.IsNil)
machines, err := app.ListMachines()
@@ -294,10 +294,10 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) {
}
func (s *Suite) TestExpireMachine(c *check.C) {
user, err := app.CreateUser("test")
namespace, err := app.CreateNamespace("test")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("test", "testmachine")
@@ -309,7 +309,7 @@ func (s *Suite) TestExpireMachine(c *check.C) {
NodeKey: "bar",
DiscoKey: "faa",
Hostname: "testmachine",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
Expiry: &time.Time{},
@@ -350,13 +350,13 @@ func (s *Suite) TestSerdeAddressStrignSlice(c *check.C) {
}
func (s *Suite) TestGenerateGivenName(c *check.C) {
user1, err := app.CreateUser("user-1")
namespace1, err := app.CreateNamespace("namespace-1")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user1.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace1.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("user-1", "testmachine")
_, err = app.GetMachine("namespace-1", "testmachine")
c.Assert(err, check.NotNil)
machine := &Machine{
@@ -366,38 +366,38 @@ func (s *Suite) TestGenerateGivenName(c *check.C) {
DiscoKey: "disco-key-1",
Hostname: "hostname-1",
GivenName: "hostname-1",
UserID: user1.ID,
NamespaceID: namespace1.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
}
app.db.Save(machine)
givenName, err := app.GenerateGivenName("machine-key-2", "hostname-2")
comment := check.Commentf("Same user, unique machines, unique hostnames, no conflict")
comment := check.Commentf("Same namespace, unique machines, unique hostnames, no conflict")
c.Assert(err, check.IsNil, comment)
c.Assert(givenName, check.Equals, "hostname-2", comment)
givenName, err = app.GenerateGivenName("machine-key-1", "hostname-1")
comment = check.Commentf("Same user, same machine, same hostname, no conflict")
comment = check.Commentf("Same namespace, same machine, same hostname, no conflict")
c.Assert(err, check.IsNil, comment)
c.Assert(givenName, check.Equals, "hostname-1", comment)
givenName, err = app.GenerateGivenName("machine-key-2", "hostname-1")
comment = check.Commentf("Same user, unique machines, same hostname, conflict")
comment = check.Commentf("Same namespace, unique machines, same hostname, conflict")
c.Assert(err, check.IsNil, comment)
c.Assert(givenName, check.Matches, fmt.Sprintf("^hostname-1-[a-z0-9]{%d}$", MachineGivenNameHashLength), comment)
givenName, err = app.GenerateGivenName("machine-key-2", "hostname-1")
comment = check.Commentf("Unique users, unique machines, same hostname, conflict")
comment = check.Commentf("Unique namespaces, unique machines, same hostname, conflict")
c.Assert(err, check.IsNil, comment)
c.Assert(givenName, check.Matches, fmt.Sprintf("^hostname-1-[a-z0-9]{%d}$", MachineGivenNameHashLength), comment)
}
func (s *Suite) TestSetTags(c *check.C) {
user, err := app.CreateUser("test")
namespace, err := app.CreateNamespace("test")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("test", "testmachine")
@@ -409,7 +409,7 @@ func (s *Suite) TestSetTags(c *check.C) {
NodeKey: "bar",
DiscoKey: "faa",
Hostname: "testmachine",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
}
@@ -457,7 +457,7 @@ func Test_getTags(t *testing.T) {
},
},
machine: Machine{
User: User{
Namespace: Namespace{
Name: "joe",
},
HostInfo: HostInfo{
@@ -478,7 +478,7 @@ func Test_getTags(t *testing.T) {
},
},
machine: Machine{
User: User{
Namespace: Namespace{
Name: "joe",
},
HostInfo: HostInfo{
@@ -499,7 +499,7 @@ func Test_getTags(t *testing.T) {
},
},
machine: Machine{
User: User{
Namespace: Namespace{
Name: "joe",
},
HostInfo: HostInfo{
@@ -524,7 +524,7 @@ func Test_getTags(t *testing.T) {
},
},
machine: Machine{
User: User{
Namespace: Namespace{
Name: "joe",
},
HostInfo: HostInfo{
@@ -541,7 +541,7 @@ func Test_getTags(t *testing.T) {
args: args{
aclPolicy: nil,
machine: Machine{
User: User{
Namespace: Namespace{
Name: "joe",
},
HostInfo: HostInfo{
@@ -607,21 +607,21 @@ func Test_getFilteredByACLPeers(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
ID: 2,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
ID: 3,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
rules: []tailcfg.FilterRule{ // list of all ACLRules registered
@@ -635,19 +635,19 @@ func Test_getFilteredByACLPeers(t *testing.T) {
machine: &Machine{ // current machine
ID: 1,
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.1")},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
},
want: Machines{
{
ID: 2,
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.2")},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
ID: 3,
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.3")},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
},
@@ -660,21 +660,21 @@ func Test_getFilteredByACLPeers(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
ID: 2,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
ID: 3,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
rules: []tailcfg.FilterRule{ // list of all ACLRules registered
@@ -688,14 +688,14 @@ func Test_getFilteredByACLPeers(t *testing.T) {
machine: &Machine{ // current machine
ID: 1,
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.1")},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
},
want: Machines{
{
ID: 2,
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.2")},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
},
},
@@ -708,21 +708,21 @@ func Test_getFilteredByACLPeers(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
ID: 2,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
ID: 3,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
rules: []tailcfg.FilterRule{ // list of all ACLRules registered
@@ -736,14 +736,14 @@ func Test_getFilteredByACLPeers(t *testing.T) {
machine: &Machine{ // current machine
ID: 2,
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.2")},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
},
want: Machines{
{
ID: 3,
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.3")},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
},
@@ -756,21 +756,21 @@ func Test_getFilteredByACLPeers(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
ID: 2,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
ID: 3,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
rules: []tailcfg.FilterRule{ // list of all ACLRules registered
@@ -786,7 +786,7 @@ func Test_getFilteredByACLPeers(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
},
want: Machines{
@@ -795,7 +795,7 @@ func Test_getFilteredByACLPeers(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
},
},
@@ -808,21 +808,21 @@ func Test_getFilteredByACLPeers(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
ID: 2,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
ID: 3,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
rules: []tailcfg.FilterRule{ // list of all ACLRules registered
@@ -838,7 +838,7 @@ func Test_getFilteredByACLPeers(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
},
want: Machines{
@@ -847,14 +847,14 @@ func Test_getFilteredByACLPeers(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
ID: 3,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
},
@@ -867,21 +867,21 @@ func Test_getFilteredByACLPeers(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
ID: 2,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
ID: 3,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
rules: []tailcfg.FilterRule{ // list of all ACLRules registered
@@ -895,7 +895,7 @@ func Test_getFilteredByACLPeers(t *testing.T) {
machine: &Machine{ // current machine
ID: 2,
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.2")},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
},
want: Machines{
@@ -904,12 +904,12 @@ func Test_getFilteredByACLPeers(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
ID: 3,
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.3")},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
},
@@ -922,21 +922,21 @@ func Test_getFilteredByACLPeers(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
User: User{Name: "joe"},
Namespace: Namespace{Name: "joe"},
},
{
ID: 2,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
{
ID: 3,
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
User: User{Name: "mickael"},
Namespace: Namespace{Name: "mickael"},
},
},
rules: []tailcfg.FilterRule{ // list of all ACLRules registered
@@ -944,7 +944,7 @@ func Test_getFilteredByACLPeers(t *testing.T) {
machine: &Machine{ // current machine
ID: 2,
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.2")},
User: User{Name: "marc"},
Namespace: Namespace{Name: "marc"},
},
},
want: Machines{},
@@ -1125,10 +1125,10 @@ func (s *Suite) TestAutoApproveRoutes(c *check.C) {
err := app.LoadACLPolicy("./tests/acls/acl_policy_autoapprovers.hujson")
c.Assert(err, check.IsNil)
user, err := app.CreateUser("test")
namespace, err := app.CreateNamespace("test")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
nodeKey := key.NewNode()
@@ -1144,7 +1144,7 @@ func (s *Suite) TestAutoApproveRoutes(c *check.C) {
NodeKey: NodePublicKeyStripPrefix(nodeKey.Public()),
DiscoKey: "faa",
Hostname: "test",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
HostInfo: HostInfo{

View File

@@ -8,34 +8,34 @@ import (
const prometheusNamespace = "headscale"
var (
// This is a high cardinality metric (user x machines), we might want to make this
// This is a high cardinality metric (namespace x machines), we might want to make this
// configurable/opt-in in the future.
lastStateUpdate = promauto.NewGaugeVec(prometheus.GaugeOpts{
Namespace: prometheusNamespace,
Name: "last_update_seconds",
Help: "Time stamp in unix time when a machine or headscale was updated",
}, []string{"user", "machine"})
}, []string{"namespace", "machine"})
machineRegistrations = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: prometheusNamespace,
Name: "machine_registrations_total",
Help: "The total amount of registered machine attempts",
}, []string{"action", "auth", "status", "user"})
}, []string{"action", "auth", "status", "namespace"})
updateRequestsFromNode = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: prometheusNamespace,
Name: "update_request_from_node_total",
Help: "The number of updates requested by a node/update function",
}, []string{"user", "machine", "state"})
}, []string{"namespace", "machine", "state"})
updateRequestsSentToNode = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: prometheusNamespace,
Name: "update_request_sent_to_node_total",
Help: "The number of calls/messages issued on a specific nodes update channel",
}, []string{"user", "machine", "status"})
}, []string{"namespace", "machine", "status"})
// TODO(kradalby): This is very debugging, we might want to remove it.
updateRequestsReceivedOnChannel = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: prometheusNamespace,
Name: "update_request_received_on_channel_total",
Help: "The number of update requests received on an update channel",
}, []string{"user", "machine"})
}, []string{"namespace", "machine"})
)

301
namespaces.go Normal file
View File

@@ -0,0 +1,301 @@
package headscale
import (
"errors"
"fmt"
"regexp"
"strconv"
"strings"
"time"
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
"github.com/rs/zerolog/log"
"google.golang.org/protobuf/types/known/timestamppb"
"gorm.io/gorm"
"tailscale.com/tailcfg"
)
const (
ErrNamespaceExists = Error("Namespace already exists")
ErrNamespaceNotFound = Error("Namespace not found")
ErrNamespaceNotEmptyOfNodes = Error("Namespace not empty: node(s) found")
ErrInvalidNamespaceName = Error("Invalid namespace name")
)
const (
// value related to RFC 1123 and 952.
labelHostnameLength = 63
)
var invalidCharsInNamespaceRegex = regexp.MustCompile("[^a-z0-9-.]+")
// Namespace is the way Headscale implements the concept of users in Tailscale
//
// At the end of the day, users in Tailscale are some kind of 'bubbles' or namespaces
// that contain our machines.
type Namespace struct {
gorm.Model
Name string `gorm:"unique"`
}
// CreateNamespace creates a new Namespace. Returns error if could not be created
// or another namespace already exists.
func (h *Headscale) CreateNamespace(name string) (*Namespace, error) {
err := CheckForFQDNRules(name)
if err != nil {
return nil, err
}
namespace := Namespace{}
if err := h.db.Where("name = ?", name).First(&namespace).Error; err == nil {
return nil, ErrNamespaceExists
}
namespace.Name = name
if err := h.db.Create(&namespace).Error; err != nil {
log.Error().
Str("func", "CreateNamespace").
Err(err).
Msg("Could not create row")
return nil, err
}
return &namespace, nil
}
// DestroyNamespace destroys a Namespace. Returns error if the Namespace does
// not exist or if there are machines associated with it.
func (h *Headscale) DestroyNamespace(name string) error {
namespace, err := h.GetNamespace(name)
if err != nil {
return ErrNamespaceNotFound
}
machines, err := h.ListMachinesInNamespace(name)
if err != nil {
return err
}
if len(machines) > 0 {
return ErrNamespaceNotEmptyOfNodes
}
keys, err := h.ListPreAuthKeys(name)
if err != nil {
return err
}
for _, key := range keys {
err = h.DestroyPreAuthKey(key)
if err != nil {
return err
}
}
if result := h.db.Unscoped().Delete(&namespace); result.Error != nil {
return result.Error
}
return nil
}
// RenameNamespace renames a Namespace. Returns error if the Namespace does
// not exist or if another Namespace exists with the new name.
func (h *Headscale) RenameNamespace(oldName, newName string) error {
var err error
oldNamespace, err := h.GetNamespace(oldName)
if err != nil {
return err
}
err = CheckForFQDNRules(newName)
if err != nil {
return err
}
_, err = h.GetNamespace(newName)
if err == nil {
return ErrNamespaceExists
}
if !errors.Is(err, ErrNamespaceNotFound) {
return err
}
oldNamespace.Name = newName
if result := h.db.Save(&oldNamespace); result.Error != nil {
return result.Error
}
return nil
}
// GetNamespace fetches a namespace by name.
func (h *Headscale) GetNamespace(name string) (*Namespace, error) {
namespace := Namespace{}
if result := h.db.First(&namespace, "name = ?", name); errors.Is(
result.Error,
gorm.ErrRecordNotFound,
) {
return nil, ErrNamespaceNotFound
}
return &namespace, nil
}
// ListNamespaces gets all the existing namespaces.
func (h *Headscale) ListNamespaces() ([]Namespace, error) {
namespaces := []Namespace{}
if err := h.db.Find(&namespaces).Error; err != nil {
return nil, err
}
return namespaces, nil
}
// ListMachinesInNamespace gets all the nodes in a given namespace.
func (h *Headscale) ListMachinesInNamespace(name string) ([]Machine, error) {
err := CheckForFQDNRules(name)
if err != nil {
return nil, err
}
namespace, err := h.GetNamespace(name)
if err != nil {
return nil, err
}
machines := []Machine{}
if err := h.db.Preload("AuthKey").Preload("AuthKey.Namespace").Preload("Namespace").Where(&Machine{NamespaceID: namespace.ID}).Find(&machines).Error; err != nil {
return nil, err
}
return machines, nil
}
// SetMachineNamespace assigns a Machine to a namespace.
func (h *Headscale) SetMachineNamespace(machine *Machine, namespaceName string) error {
err := CheckForFQDNRules(namespaceName)
if err != nil {
return err
}
namespace, err := h.GetNamespace(namespaceName)
if err != nil {
return err
}
machine.Namespace = *namespace
if result := h.db.Save(&machine); result.Error != nil {
return result.Error
}
return nil
}
func (n *Namespace) toUser() *tailcfg.User {
user := tailcfg.User{
ID: tailcfg.UserID(n.ID),
LoginName: n.Name,
DisplayName: n.Name,
ProfilePicURL: "",
Domain: "headscale.net",
Logins: []tailcfg.LoginID{},
Created: time.Time{},
}
return &user
}
func (n *Namespace) toLogin() *tailcfg.Login {
login := tailcfg.Login{
ID: tailcfg.LoginID(n.ID),
LoginName: n.Name,
DisplayName: n.Name,
ProfilePicURL: "",
Domain: "headscale.net",
}
return &login
}
func (h *Headscale) getMapResponseUserProfiles(
machine Machine,
peers Machines,
) []tailcfg.UserProfile {
namespaceMap := make(map[string]Namespace)
namespaceMap[machine.Namespace.Name] = machine.Namespace
for _, peer := range peers {
namespaceMap[peer.Namespace.Name] = peer.Namespace // not worth checking if already is there
}
profiles := []tailcfg.UserProfile{}
for _, namespace := range namespaceMap {
displayName := namespace.Name
if h.cfg.BaseDomain != "" {
displayName = fmt.Sprintf("%s@%s", namespace.Name, h.cfg.BaseDomain)
}
profiles = append(profiles,
tailcfg.UserProfile{
ID: tailcfg.UserID(namespace.ID),
LoginName: namespace.Name,
DisplayName: displayName,
})
}
return profiles
}
func (n *Namespace) toProto() *v1.Namespace {
return &v1.Namespace{
Id: strconv.FormatUint(uint64(n.ID), Base10),
Name: n.Name,
CreatedAt: timestamppb.New(n.CreatedAt),
}
}
// NormalizeToFQDNRules will replace forbidden chars in namespace
// it can also return an error if the namespace doesn't respect RFC 952 and 1123.
func NormalizeToFQDNRules(name string, stripEmailDomain bool) (string, error) {
name = strings.ToLower(name)
name = strings.ReplaceAll(name, "'", "")
atIdx := strings.Index(name, "@")
if stripEmailDomain && atIdx > 0 {
name = name[:atIdx]
} else {
name = strings.ReplaceAll(name, "@", ".")
}
name = invalidCharsInNamespaceRegex.ReplaceAllString(name, "-")
for _, elt := range strings.Split(name, ".") {
if len(elt) > labelHostnameLength {
return "", fmt.Errorf(
"label %v is more than 63 chars: %w",
elt,
ErrInvalidNamespaceName,
)
}
}
return name, nil
}
func CheckForFQDNRules(name string) error {
if len(name) > labelHostnameLength {
return fmt.Errorf(
"DNS segment must not be over 63 chars. %v doesn't comply with this rule: %w",
name,
ErrInvalidNamespaceName,
)
}
if strings.ToLower(name) != name {
return fmt.Errorf(
"DNS segment should be lowercase. %v doesn't comply with this rule: %w",
name,
ErrInvalidNamespaceName,
)
}
if invalidCharsInNamespaceRegex.MatchString(name) {
return fmt.Errorf(
"DNS segment should only be composed of lowercase ASCII letters numbers, hyphen and dots. %v doesn't comply with theses rules: %w",
name,
ErrInvalidNamespaceName,
)
}
return nil
}

View File

@@ -8,43 +8,43 @@ import (
"gorm.io/gorm"
)
func (s *Suite) TestCreateAndDestroyUser(c *check.C) {
user, err := app.CreateUser("test")
func (s *Suite) TestCreateAndDestroyNamespace(c *check.C) {
namespace, err := app.CreateNamespace("test")
c.Assert(err, check.IsNil)
c.Assert(user.Name, check.Equals, "test")
c.Assert(namespace.Name, check.Equals, "test")
users, err := app.ListUsers()
namespaces, err := app.ListNamespaces()
c.Assert(err, check.IsNil)
c.Assert(len(users), check.Equals, 1)
c.Assert(len(namespaces), check.Equals, 1)
err = app.DestroyUser("test")
err = app.DestroyNamespace("test")
c.Assert(err, check.IsNil)
_, err = app.GetUser("test")
_, err = app.GetNamespace("test")
c.Assert(err, check.NotNil)
}
func (s *Suite) TestDestroyUserErrors(c *check.C) {
err := app.DestroyUser("test")
c.Assert(err, check.Equals, ErrUserNotFound)
func (s *Suite) TestDestroyNamespaceErrors(c *check.C) {
err := app.DestroyNamespace("test")
c.Assert(err, check.Equals, ErrNamespaceNotFound)
user, err := app.CreateUser("test")
namespace, err := app.CreateNamespace("test")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
err = app.DestroyUser("test")
err = app.DestroyNamespace("test")
c.Assert(err, check.IsNil)
result := app.db.Preload("User").First(&pak, "key = ?", pak.Key)
// destroying a user also deletes all associated preauthkeys
result := app.db.Preload("Namespace").First(&pak, "key = ?", pak.Key)
// destroying a namespace also deletes all associated preauthkeys
c.Assert(result.Error, check.Equals, gorm.ErrRecordNotFound)
user, err = app.CreateUser("test")
namespace, err = app.CreateNamespace("test")
c.Assert(err, check.IsNil)
pak, err = app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err = app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
machine := Machine{
@@ -53,57 +53,57 @@ func (s *Suite) TestDestroyUserErrors(c *check.C) {
NodeKey: "bar",
DiscoKey: "faa",
Hostname: "testmachine",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
}
app.db.Save(&machine)
err = app.DestroyUser("test")
c.Assert(err, check.Equals, ErrUserStillHasNodes)
err = app.DestroyNamespace("test")
c.Assert(err, check.Equals, ErrNamespaceNotEmptyOfNodes)
}
func (s *Suite) TestRenameUser(c *check.C) {
userTest, err := app.CreateUser("test")
func (s *Suite) TestRenameNamespace(c *check.C) {
namespaceTest, err := app.CreateNamespace("test")
c.Assert(err, check.IsNil)
c.Assert(userTest.Name, check.Equals, "test")
c.Assert(namespaceTest.Name, check.Equals, "test")
users, err := app.ListUsers()
namespaces, err := app.ListNamespaces()
c.Assert(err, check.IsNil)
c.Assert(len(users), check.Equals, 1)
c.Assert(len(namespaces), check.Equals, 1)
err = app.RenameUser("test", "test-renamed")
err = app.RenameNamespace("test", "test-renamed")
c.Assert(err, check.IsNil)
_, err = app.GetUser("test")
c.Assert(err, check.Equals, ErrUserNotFound)
_, err = app.GetNamespace("test")
c.Assert(err, check.Equals, ErrNamespaceNotFound)
_, err = app.GetUser("test-renamed")
_, err = app.GetNamespace("test-renamed")
c.Assert(err, check.IsNil)
err = app.RenameUser("test-does-not-exit", "test")
c.Assert(err, check.Equals, ErrUserNotFound)
err = app.RenameNamespace("test-does-not-exit", "test")
c.Assert(err, check.Equals, ErrNamespaceNotFound)
userTest2, err := app.CreateUser("test2")
namespaceTest2, err := app.CreateNamespace("test2")
c.Assert(err, check.IsNil)
c.Assert(userTest2.Name, check.Equals, "test2")
c.Assert(namespaceTest2.Name, check.Equals, "test2")
err = app.RenameUser("test2", "test-renamed")
c.Assert(err, check.Equals, ErrUserExists)
err = app.RenameNamespace("test2", "test-renamed")
c.Assert(err, check.Equals, ErrNamespaceExists)
}
func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
userShared1, err := app.CreateUser("shared1")
namespaceShared1, err := app.CreateNamespace("shared1")
c.Assert(err, check.IsNil)
userShared2, err := app.CreateUser("shared2")
namespaceShared2, err := app.CreateNamespace("shared2")
c.Assert(err, check.IsNil)
userShared3, err := app.CreateUser("shared3")
namespaceShared3, err := app.CreateNamespace("shared3")
c.Assert(err, check.IsNil)
preAuthKeyShared1, err := app.CreatePreAuthKey(
userShared1.Name,
namespaceShared1.Name,
false,
false,
nil,
@@ -112,7 +112,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
c.Assert(err, check.IsNil)
preAuthKeyShared2, err := app.CreatePreAuthKey(
userShared2.Name,
namespaceShared2.Name,
false,
false,
nil,
@@ -121,7 +121,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
c.Assert(err, check.IsNil)
preAuthKeyShared3, err := app.CreatePreAuthKey(
userShared3.Name,
namespaceShared3.Name,
false,
false,
nil,
@@ -130,7 +130,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
c.Assert(err, check.IsNil)
preAuthKey2Shared1, err := app.CreatePreAuthKey(
userShared1.Name,
namespaceShared1.Name,
false,
false,
nil,
@@ -138,7 +138,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
)
c.Assert(err, check.IsNil)
_, err = app.GetMachine(userShared1.Name, "test_get_shared_nodes_1")
_, err = app.GetMachine(namespaceShared1.Name, "test_get_shared_nodes_1")
c.Assert(err, check.NotNil)
machineInShared1 := &Machine{
@@ -147,15 +147,15 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
NodeKey: "686824e749f3b7f2a5927ee6c1e422aee5292592d9179a271ed7b3e659b44a66",
DiscoKey: "686824e749f3b7f2a5927ee6c1e422aee5292592d9179a271ed7b3e659b44a66",
Hostname: "test_get_shared_nodes_1",
UserID: userShared1.ID,
User: *userShared1,
NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.1")},
AuthKeyID: uint(preAuthKeyShared1.ID),
}
app.db.Save(machineInShared1)
_, err = app.GetMachine(userShared1.Name, machineInShared1.Hostname)
_, err = app.GetMachine(namespaceShared1.Name, machineInShared1.Hostname)
c.Assert(err, check.IsNil)
machineInShared2 := &Machine{
@@ -164,15 +164,15 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
NodeKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
DiscoKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
Hostname: "test_get_shared_nodes_2",
UserID: userShared2.ID,
User: *userShared2,
NamespaceID: namespaceShared2.ID,
Namespace: *namespaceShared2,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.2")},
AuthKeyID: uint(preAuthKeyShared2.ID),
}
app.db.Save(machineInShared2)
_, err = app.GetMachine(userShared2.Name, machineInShared2.Hostname)
_, err = app.GetMachine(namespaceShared2.Name, machineInShared2.Hostname)
c.Assert(err, check.IsNil)
machineInShared3 := &Machine{
@@ -181,15 +181,15 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
NodeKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
DiscoKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
Hostname: "test_get_shared_nodes_3",
UserID: userShared3.ID,
User: *userShared3,
NamespaceID: namespaceShared3.ID,
Namespace: *namespaceShared3,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.3")},
AuthKeyID: uint(preAuthKeyShared3.ID),
}
app.db.Save(machineInShared3)
_, err = app.GetMachine(userShared3.Name, machineInShared3.Hostname)
_, err = app.GetMachine(namespaceShared3.Name, machineInShared3.Hostname)
c.Assert(err, check.IsNil)
machine2InShared1 := &Machine{
@@ -198,8 +198,8 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
NodeKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
DiscoKey: "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863",
Hostname: "test_get_shared_nodes_4",
UserID: userShared1.ID,
User: *userShared1,
NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.4")},
AuthKeyID: uint(preAuthKey2Shared1.ID),
@@ -218,7 +218,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
found := false
for _, userProfiles := range userProfiles {
if userProfiles.DisplayName == userShared1.Name {
if userProfiles.DisplayName == namespaceShared1.Name {
found = true
break
@@ -228,7 +228,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
found = false
for _, userProfile := range userProfiles {
if userProfile.DisplayName == userShared2.Name {
if userProfile.DisplayName == namespaceShared2.Name {
found = true
break
@@ -294,7 +294,7 @@ func TestNormalizeToFQDNRules(t *testing.T) {
wantErr: false,
},
{
name: "user name with space",
name: "namespace name with space",
args: args{
name: "name space",
stripEmailDomain: false,
@@ -303,7 +303,7 @@ func TestNormalizeToFQDNRules(t *testing.T) {
wantErr: false,
},
{
name: "user with quote",
name: "namespace with quote",
args: args{
name: "Jamie's iPhone 5",
stripEmailDomain: false,
@@ -341,29 +341,29 @@ func TestCheckForFQDNRules(t *testing.T) {
wantErr bool
}{
{
name: "valid: user",
args: args{name: "valid-user"},
name: "valid: namespace",
args: args{name: "valid-namespace"},
wantErr: false,
},
{
name: "invalid: capitalized user",
args: args{name: "Invalid-CapItaLIzed-user"},
name: "invalid: capitalized namespace",
args: args{name: "Invalid-CapItaLIzed-namespace"},
wantErr: true,
},
{
name: "invalid: email as user",
name: "invalid: email as namespace",
args: args{name: "foo.bar@example.com"},
wantErr: true,
},
{
name: "invalid: chars in user name",
args: args{name: "super-user+name"},
name: "invalid: chars in namespace name",
args: args{name: "super-namespace+name"},
wantErr: true,
},
{
name: "invalid: too long name for user",
name: "invalid: too long name for namespace",
args: args{
name: "super-long-useruseruser-name-that-should-be-a-little-more-than-63-chars",
name: "super-long-namespace-name-that-should-be-a-little-more-than-63-chars",
},
wantErr: true,
},
@@ -377,14 +377,14 @@ func TestCheckForFQDNRules(t *testing.T) {
}
}
func (s *Suite) TestSetMachineUser(c *check.C) {
oldUser, err := app.CreateUser("old")
func (s *Suite) TestSetMachineNamespace(c *check.C) {
oldNamespace, err := app.CreateNamespace("old")
c.Assert(err, check.IsNil)
newUser, err := app.CreateUser("new")
newNamespace, err := app.CreateNamespace("new")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(oldUser.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(oldNamespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
machine := Machine{
@@ -393,23 +393,23 @@ func (s *Suite) TestSetMachineUser(c *check.C) {
NodeKey: "bar",
DiscoKey: "faa",
Hostname: "testmachine",
UserID: oldUser.ID,
NamespaceID: oldNamespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
}
app.db.Save(&machine)
c.Assert(machine.UserID, check.Equals, oldUser.ID)
c.Assert(machine.NamespaceID, check.Equals, oldNamespace.ID)
err = app.SetMachineUser(&machine, newUser.Name)
err = app.SetMachineNamespace(&machine, newNamespace.Name)
c.Assert(err, check.IsNil)
c.Assert(machine.UserID, check.Equals, newUser.ID)
c.Assert(machine.User.Name, check.Equals, newUser.Name)
c.Assert(machine.NamespaceID, check.Equals, newNamespace.ID)
c.Assert(machine.Namespace.Name, check.Equals, newNamespace.Name)
err = app.SetMachineUser(&machine, "non-existing-user")
c.Assert(err, check.Equals, ErrUserNotFound)
err = app.SetMachineNamespace(&machine, "non-existing-namespace")
c.Assert(err, check.Equals, ErrNamespaceNotFound)
err = app.SetMachineUser(&machine, newUser.Name)
err = app.SetMachineNamespace(&machine, newNamespace.Name)
c.Assert(err, check.IsNil)
c.Assert(machine.UserID, check.Equals, newUser.ID)
c.Assert(machine.User.Name, check.Equals, newUser.Name)
c.Assert(machine.NamespaceID, check.Equals, newNamespace.ID)
c.Assert(machine.Namespace.Name, check.Equals, newNamespace.Name)
}

53
oidc.go
View File

@@ -171,7 +171,7 @@ var oidcCallbackTemplate = template.Must(
)
// OIDCCallback handles the callback from the OIDC endpoint
// Retrieves the nkey from the state cache and adds the machine to the users email user
// Retrieves the nkey from the state cache and adds the machine to the users email namespace
// TODO: A confirmation page for new machines should be added to avoid phishing vulnerabilities
// TODO: Add groups information from OIDC tokens into machine HostInfo
// Listens in /oidc/callback.
@@ -218,12 +218,12 @@ func (h *Headscale) OIDCCallback(
return
}
nodeKey, machineExists, err := h.validateMachineForOIDCCallback(writer, state, claims, idToken.Expiry)
nodeKey, machineExists, err := h.validateMachineForOIDCCallback(writer, state, claims)
if err != nil || machineExists {
return
}
userName, err := getUserName(writer, claims, h.cfg.OIDC.StripEmaildomain)
namespaceName, err := getNamespaceName(writer, claims, h.cfg.OIDC.StripEmaildomain)
if err != nil {
return
}
@@ -231,12 +231,12 @@ func (h *Headscale) OIDCCallback(
// register the machine if it's new
log.Debug().Msg("Registering new machine after successful callback")
user, err := h.findOrCreateNewUserForOIDCCallback(writer, userName)
namespace, err := h.findOrCreateNewNamespaceForOIDCCallback(writer, namespaceName)
if err != nil {
return
}
if err := h.registerMachineForOIDCCallback(writer, user, nodeKey, idToken.Expiry); err != nil {
if err := h.registerMachineForOIDCCallback(writer, namespace, nodeKey); err != nil {
return
}
@@ -476,7 +476,6 @@ func (h *Headscale) validateMachineForOIDCCallback(
writer http.ResponseWriter,
state string,
claims *IDTokenClaims,
expiry time.Time,
) (*key.NodePublic, bool, error) {
// retrieve machinekey from state cache
nodeKeyIf, nodeKeyFound := h.registrationCache.Get(state)
@@ -547,7 +546,7 @@ func (h *Headscale) validateMachineForOIDCCallback(
Str("machine", machine.Hostname).
Msg("machine already registered, reauthenticating")
err := h.RefreshMachine(machine, expiry)
err := h.RefreshMachine(machine, time.Time{})
if err != nil {
log.Error().
Caller().
@@ -561,10 +560,6 @@ func (h *Headscale) validateMachineForOIDCCallback(
return nil, true, err
}
log.Debug().
Str("machine", machine.Hostname).
Str("expiresAt", fmt.Sprintf("%v", expiry)).
Msg("successfully refreshed machine")
var content bytes.Buffer
if err := oidcCallbackTemplate.Execute(&content, oidcCallbackTemplateConfig{
@@ -606,12 +601,12 @@ func (h *Headscale) validateMachineForOIDCCallback(
return &nodeKey, false, nil
}
func getUserName(
func getNamespaceName(
writer http.ResponseWriter,
claims *IDTokenClaims,
stripEmaildomain bool,
) (string, error) {
userName, err := NormalizeToFQDNRules(
namespaceName, err := NormalizeToFQDNRules(
claims.Email,
stripEmaildomain,
)
@@ -630,25 +625,25 @@ func getUserName(
return "", err
}
return userName, nil
return namespaceName, nil
}
func (h *Headscale) findOrCreateNewUserForOIDCCallback(
func (h *Headscale) findOrCreateNewNamespaceForOIDCCallback(
writer http.ResponseWriter,
userName string,
) (*User, error) {
user, err := h.GetUser(userName)
if errors.Is(err, ErrUserNotFound) {
user, err = h.CreateUser(userName)
namespaceName string,
) (*Namespace, error) {
namespace, err := h.GetNamespace(namespaceName)
if errors.Is(err, ErrNamespaceNotFound) {
namespace, err = h.CreateNamespace(namespaceName)
if err != nil {
log.Error().
Err(err).
Caller().
Msgf("could not create new user '%s'", userName)
Msgf("could not create new namespace '%s'", namespaceName)
writer.Header().Set("Content-Type", "text/plain; charset=utf-8")
writer.WriteHeader(http.StatusInternalServerError)
_, werr := writer.Write([]byte("could not create user"))
_, werr := writer.Write([]byte("could not create namespace"))
if werr != nil {
log.Error().
Caller().
@@ -662,11 +657,11 @@ func (h *Headscale) findOrCreateNewUserForOIDCCallback(
log.Error().
Caller().
Err(err).
Str("user", userName).
Msg("could not find or create user")
Str("namespace", namespaceName).
Msg("could not find or create namespace")
writer.Header().Set("Content-Type", "text/plain; charset=utf-8")
writer.WriteHeader(http.StatusInternalServerError)
_, werr := writer.Write([]byte("could not find or create user"))
_, werr := writer.Write([]byte("could not find or create namespace"))
if werr != nil {
log.Error().
Caller().
@@ -677,19 +672,17 @@ func (h *Headscale) findOrCreateNewUserForOIDCCallback(
return nil, err
}
return user, nil
return namespace, nil
}
func (h *Headscale) registerMachineForOIDCCallback(
writer http.ResponseWriter,
user *User,
namespace *Namespace,
nodeKey *key.NodePublic,
expiry time.Time,
) error {
if _, err := h.RegisterMachineFromAuthCallback(
nodeKey.String(),
user.Name,
&expiry,
namespace.Name,
RegisterMethodOIDC,
); err != nil {
log.Error().

View File

@@ -255,7 +255,7 @@ func (h *Headscale) ApplePlatformConfig(
writer.Header().Set("Content-Type", "text/plain; charset=utf-8")
writer.WriteHeader(http.StatusBadRequest)
_, err := writer.Write(
[]byte("Invalid platform. Only ios, macos-app-store and macos-standalone are supported"),
[]byte("Invalid platform, only ios and macos is supported"),
)
if err != nil {
log.Error().

View File

@@ -18,20 +18,20 @@ const (
ErrPreAuthKeyNotFound = Error("AuthKey not found")
ErrPreAuthKeyExpired = Error("AuthKey expired")
ErrSingleUseAuthKeyHasBeenUsed = Error("AuthKey has already been used")
ErrUserMismatch = Error("user mismatch")
ErrNamespaceMismatch = Error("namespace mismatch")
ErrPreAuthKeyACLTagInvalid = Error("AuthKey tag is invalid")
)
// PreAuthKey describes a pre-authorization key usable in a particular user.
// PreAuthKey describes a pre-authorization key usable in a particular namespace.
type PreAuthKey struct {
ID uint64 `gorm:"primary_key"`
Key string
UserID uint
User User
Reusable bool
Ephemeral bool `gorm:"default:false"`
Used bool `gorm:"default:false"`
ACLTags []PreAuthKeyACLTag
ID uint64 `gorm:"primary_key"`
Key string
NamespaceID uint
Namespace Namespace
Reusable bool
Ephemeral bool `gorm:"default:false"`
Used bool `gorm:"default:false"`
ACLTags []PreAuthKeyACLTag
CreatedAt *time.Time
Expiration *time.Time
@@ -44,15 +44,15 @@ type PreAuthKeyACLTag struct {
Tag string
}
// CreatePreAuthKey creates a new PreAuthKey in a user, and returns it.
// CreatePreAuthKey creates a new PreAuthKey in a namespace, and returns it.
func (h *Headscale) CreatePreAuthKey(
userName string,
namespaceName string,
reusable bool,
ephemeral bool,
expiration *time.Time,
aclTags []string,
) (*PreAuthKey, error) {
user, err := h.GetUser(userName)
namespace, err := h.GetNamespace(namespaceName)
if err != nil {
return nil, err
}
@@ -70,13 +70,13 @@ func (h *Headscale) CreatePreAuthKey(
}
key := PreAuthKey{
Key: kstr,
UserID: user.ID,
User: *user,
Reusable: reusable,
Ephemeral: ephemeral,
CreatedAt: &now,
Expiration: expiration,
Key: kstr,
NamespaceID: namespace.ID,
Namespace: *namespace,
Reusable: reusable,
Ephemeral: ephemeral,
CreatedAt: &now,
Expiration: expiration,
}
err = h.db.Transaction(func(db *gorm.DB) error {
@@ -110,15 +110,15 @@ func (h *Headscale) CreatePreAuthKey(
return &key, nil
}
// ListPreAuthKeys returns the list of PreAuthKeys for a user.
func (h *Headscale) ListPreAuthKeys(userName string) ([]PreAuthKey, error) {
user, err := h.GetUser(userName)
// ListPreAuthKeys returns the list of PreAuthKeys for a namespace.
func (h *Headscale) ListPreAuthKeys(namespaceName string) ([]PreAuthKey, error) {
namespace, err := h.GetNamespace(namespaceName)
if err != nil {
return nil, err
}
keys := []PreAuthKey{}
if err := h.db.Preload("User").Preload("ACLTags").Where(&PreAuthKey{UserID: user.ID}).Find(&keys).Error; err != nil {
if err := h.db.Preload("Namespace").Preload("ACLTags").Where(&PreAuthKey{NamespaceID: namespace.ID}).Find(&keys).Error; err != nil {
return nil, err
}
@@ -126,14 +126,14 @@ func (h *Headscale) ListPreAuthKeys(userName string) ([]PreAuthKey, error) {
}
// GetPreAuthKey returns a PreAuthKey for a given key.
func (h *Headscale) GetPreAuthKey(user string, key string) (*PreAuthKey, error) {
func (h *Headscale) GetPreAuthKey(namespace string, key string) (*PreAuthKey, error) {
pak, err := h.checkKeyValidity(key)
if err != nil {
return nil, err
}
if pak.User.Name != user {
return nil, ErrUserMismatch
if pak.Namespace.Name != namespace {
return nil, ErrNamespaceMismatch
}
return pak, nil
@@ -178,7 +178,7 @@ func (h *Headscale) UsePreAuthKey(k *PreAuthKey) error {
// If returns no error and a PreAuthKey, it can be used.
func (h *Headscale) checkKeyValidity(k string) (*PreAuthKey, error) {
pak := PreAuthKey{}
if result := h.db.Preload("User").Preload("ACLTags").First(&pak, "key = ?", k); errors.Is(
if result := h.db.Preload("Namespace").Preload("ACLTags").First(&pak, "key = ?", k); errors.Is(
result.Error,
gorm.ErrRecordNotFound,
) {
@@ -217,7 +217,7 @@ func (h *Headscale) generateKey() (string, error) {
func (key *PreAuthKey) toProto() *v1.PreAuthKey {
protoKey := v1.PreAuthKey{
User: key.User.Name,
Namespace: key.Namespace.Name,
Id: strconv.FormatUint(key.ID, Base10),
Key: key.Key,
Ephemeral: key.Ephemeral,

View File

@@ -11,36 +11,36 @@ func (*Suite) TestCreatePreAuthKey(c *check.C) {
c.Assert(err, check.NotNil)
user, err := app.CreateUser("test")
namespace, err := app.CreateNamespace("test")
c.Assert(err, check.IsNil)
key, err := app.CreatePreAuthKey(user.Name, true, false, nil, nil)
key, err := app.CreatePreAuthKey(namespace.Name, true, false, nil, nil)
c.Assert(err, check.IsNil)
// Did we get a valid key?
c.Assert(key.Key, check.NotNil)
c.Assert(len(key.Key), check.Equals, 48)
// Make sure the User association is populated
c.Assert(key.User.Name, check.Equals, user.Name)
// Make sure the Namespace association is populated
c.Assert(key.Namespace.Name, check.Equals, namespace.Name)
_, err = app.ListPreAuthKeys("bogus")
c.Assert(err, check.NotNil)
keys, err := app.ListPreAuthKeys(user.Name)
keys, err := app.ListPreAuthKeys(namespace.Name)
c.Assert(err, check.IsNil)
c.Assert(len(keys), check.Equals, 1)
// Make sure the User association is populated
c.Assert((keys)[0].User.Name, check.Equals, user.Name)
// Make sure the Namespace association is populated
c.Assert((keys)[0].Namespace.Name, check.Equals, namespace.Name)
}
func (*Suite) TestExpiredPreAuthKey(c *check.C) {
user, err := app.CreateUser("test2")
namespace, err := app.CreateNamespace("test2")
c.Assert(err, check.IsNil)
now := time.Now()
pak, err := app.CreatePreAuthKey(user.Name, true, false, &now, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, true, false, &now, nil)
c.Assert(err, check.IsNil)
key, err := app.checkKeyValidity(pak.Key)
@@ -55,10 +55,10 @@ func (*Suite) TestPreAuthKeyDoesNotExist(c *check.C) {
}
func (*Suite) TestValidateKeyOk(c *check.C) {
user, err := app.CreateUser("test3")
namespace, err := app.CreateNamespace("test3")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, true, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, true, false, nil, nil)
c.Assert(err, check.IsNil)
key, err := app.checkKeyValidity(pak.Key)
@@ -67,10 +67,10 @@ func (*Suite) TestValidateKeyOk(c *check.C) {
}
func (*Suite) TestAlreadyUsedKey(c *check.C) {
user, err := app.CreateUser("test4")
namespace, err := app.CreateNamespace("test4")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
machine := Machine{
@@ -79,7 +79,7 @@ func (*Suite) TestAlreadyUsedKey(c *check.C) {
NodeKey: "bar",
DiscoKey: "faa",
Hostname: "testest",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
}
@@ -91,10 +91,10 @@ func (*Suite) TestAlreadyUsedKey(c *check.C) {
}
func (*Suite) TestReusableBeingUsedKey(c *check.C) {
user, err := app.CreateUser("test5")
namespace, err := app.CreateNamespace("test5")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, true, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, true, false, nil, nil)
c.Assert(err, check.IsNil)
machine := Machine{
@@ -103,7 +103,7 @@ func (*Suite) TestReusableBeingUsedKey(c *check.C) {
NodeKey: "bar",
DiscoKey: "faa",
Hostname: "testest",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
}
@@ -115,10 +115,10 @@ func (*Suite) TestReusableBeingUsedKey(c *check.C) {
}
func (*Suite) TestNotReusableNotBeingUsedKey(c *check.C) {
user, err := app.CreateUser("test6")
namespace, err := app.CreateNamespace("test6")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
key, err := app.checkKeyValidity(pak.Key)
@@ -127,10 +127,10 @@ func (*Suite) TestNotReusableNotBeingUsedKey(c *check.C) {
}
func (*Suite) TestEphemeralKey(c *check.C) {
user, err := app.CreateUser("test7")
namespace, err := app.CreateNamespace("test7")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, true, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, true, nil, nil)
c.Assert(err, check.IsNil)
now := time.Now()
@@ -140,7 +140,7 @@ func (*Suite) TestEphemeralKey(c *check.C) {
NodeKey: "bar",
DiscoKey: "faa",
Hostname: "testest",
UserID: user.ID,
NamespaceID: namespace.ID,
RegisterMethod: RegisterMethodAuthKey,
LastSeen: &now,
AuthKeyID: uint(pak.ID),
@@ -162,10 +162,10 @@ func (*Suite) TestEphemeralKey(c *check.C) {
}
func (*Suite) TestExpirePreauthKey(c *check.C) {
user, err := app.CreateUser("test3")
namespace, err := app.CreateNamespace("test3")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, true, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, true, false, nil, nil)
c.Assert(err, check.IsNil)
c.Assert(pak.Expiration, check.IsNil)
@@ -179,10 +179,10 @@ func (*Suite) TestExpirePreauthKey(c *check.C) {
}
func (*Suite) TestNotReusableMarkedAsUsed(c *check.C) {
user, err := app.CreateUser("test6")
namespace, err := app.CreateNamespace("test6")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
pak.Used = true
app.db.Save(&pak)
@@ -192,15 +192,15 @@ func (*Suite) TestNotReusableMarkedAsUsed(c *check.C) {
}
func (*Suite) TestPreAuthKeyACLTags(c *check.C) {
user, err := app.CreateUser("test8")
namespace, err := app.CreateNamespace("test8")
c.Assert(err, check.IsNil)
_, err = app.CreatePreAuthKey(user.Name, false, false, nil, []string{"badtag"})
_, err = app.CreatePreAuthKey(namespace.Name, false, false, nil, []string{"badtag"})
c.Assert(err, check.NotNil) // Confirm that malformed tags are rejected
tags := []string{"tag:test1", "tag:test2"}
tagsWithDuplicate := []string{"tag:test1", "tag:test2", "tag:test2"}
_, err = app.CreatePreAuthKey(user.Name, false, false, nil, tagsWithDuplicate)
_, err = app.CreatePreAuthKey(namespace.Name, false, false, nil, tagsWithDuplicate)
c.Assert(err, check.IsNil)
listedPaks, err := app.ListPreAuthKeys("test8")

View File

@@ -4,7 +4,7 @@ option go_package = "github.com/juanfont/headscale/gen/go/v1";
import "google/api/annotations.proto";
import "headscale/v1/user.proto";
import "headscale/v1/namespace.proto";
import "headscale/v1/preauthkey.proto";
import "headscale/v1/machine.proto";
import "headscale/v1/routes.proto";
@@ -12,164 +12,165 @@ import "headscale/v1/apikey.proto";
// import "headscale/v1/device.proto";
service HeadscaleService {
// --- User start ---
rpc GetUser(GetUserRequest) returns(GetUserResponse) {
option(google.api.http) = {
get : "/api/v1/user/{name}"
// --- Namespace start ---
rpc GetNamespace(GetNamespaceRequest) returns (GetNamespaceResponse) {
option (google.api.http) = {
get: "/api/v1/namespace/{name}"
};
}
rpc CreateUser(CreateUserRequest) returns(CreateUserResponse) {
option(google.api.http) = {
post : "/api/v1/user"
body : "*"
rpc CreateNamespace(CreateNamespaceRequest) returns (CreateNamespaceResponse) {
option (google.api.http) = {
post: "/api/v1/namespace"
body: "*"
};
}
rpc RenameUser(RenameUserRequest) returns(RenameUserResponse) {
option(google.api.http) = {
post : "/api/v1/user/{old_name}/rename/{new_name}"
rpc RenameNamespace(RenameNamespaceRequest) returns (RenameNamespaceResponse) {
option (google.api.http) = {
post: "/api/v1/namespace/{old_name}/rename/{new_name}"
};
}
rpc DeleteUser(DeleteUserRequest) returns(DeleteUserResponse) {
option(google.api.http) = {
delete : "/api/v1/user/{name}"
rpc DeleteNamespace(DeleteNamespaceRequest) returns (DeleteNamespaceResponse) {
option (google.api.http) = {
delete: "/api/v1/namespace/{name}"
};
}
rpc ListUsers(ListUsersRequest) returns(ListUsersResponse) {
option(google.api.http) = {
get : "/api/v1/user"
rpc ListNamespaces(ListNamespacesRequest) returns (ListNamespacesResponse) {
option (google.api.http) = {
get: "/api/v1/namespace"
};
}
// --- User end ---
// --- Namespace end ---
// --- PreAuthKeys start ---
rpc CreatePreAuthKey(CreatePreAuthKeyRequest) returns(CreatePreAuthKeyResponse) {
option(google.api.http) = {
post : "/api/v1/preauthkey"
body : "*"
rpc CreatePreAuthKey(CreatePreAuthKeyRequest) returns (CreatePreAuthKeyResponse) {
option (google.api.http) = {
post: "/api/v1/preauthkey"
body: "*"
};
}
rpc ExpirePreAuthKey(ExpirePreAuthKeyRequest) returns(ExpirePreAuthKeyResponse) {
option(google.api.http) = {
post : "/api/v1/preauthkey/expire"
body : "*"
rpc ExpirePreAuthKey(ExpirePreAuthKeyRequest) returns (ExpirePreAuthKeyResponse) {
option (google.api.http) = {
post: "/api/v1/preauthkey/expire"
body: "*"
};
}
rpc ListPreAuthKeys(ListPreAuthKeysRequest) returns(ListPreAuthKeysResponse) {
option(google.api.http) = {
get : "/api/v1/preauthkey"
rpc ListPreAuthKeys(ListPreAuthKeysRequest) returns (ListPreAuthKeysResponse) {
option (google.api.http) = {
get: "/api/v1/preauthkey"
};
}
// --- PreAuthKeys end ---
// --- Machine start ---
rpc DebugCreateMachine(DebugCreateMachineRequest) returns(DebugCreateMachineResponse) {
option(google.api.http) = {
post : "/api/v1/debug/machine"
body : "*"
rpc DebugCreateMachine(DebugCreateMachineRequest) returns (DebugCreateMachineResponse) {
option (google.api.http) = {
post: "/api/v1/debug/machine"
body: "*"
};
}
rpc GetMachine(GetMachineRequest) returns(GetMachineResponse) {
option(google.api.http) = {
get : "/api/v1/machine/{machine_id}"
rpc GetMachine(GetMachineRequest) returns (GetMachineResponse) {
option (google.api.http) = {
get: "/api/v1/machine/{machine_id}"
};
}
rpc SetTags(SetTagsRequest) returns(SetTagsResponse) {
option(google.api.http) = {
post : "/api/v1/machine/{machine_id}/tags"
body : "*"
rpc SetTags(SetTagsRequest) returns (SetTagsResponse) {
option (google.api.http) = {
post: "/api/v1/machine/{machine_id}/tags"
body: "*"
};
}
rpc RegisterMachine(RegisterMachineRequest) returns(RegisterMachineResponse) {
option(google.api.http) = {
post : "/api/v1/machine/register"
rpc RegisterMachine(RegisterMachineRequest) returns (RegisterMachineResponse) {
option (google.api.http) = {
post: "/api/v1/machine/register"
};
}
rpc DeleteMachine(DeleteMachineRequest) returns(DeleteMachineResponse) {
option(google.api.http) = {
delete : "/api/v1/machine/{machine_id}"
rpc DeleteMachine(DeleteMachineRequest) returns (DeleteMachineResponse) {
option (google.api.http) = {
delete: "/api/v1/machine/{machine_id}"
};
}
rpc ExpireMachine(ExpireMachineRequest) returns(ExpireMachineResponse) {
option(google.api.http) = {
post : "/api/v1/machine/{machine_id}/expire"
rpc ExpireMachine(ExpireMachineRequest) returns (ExpireMachineResponse) {
option (google.api.http) = {
post: "/api/v1/machine/{machine_id}/expire"
};
}
rpc RenameMachine(RenameMachineRequest) returns(RenameMachineResponse) {
option(google.api.http) = {
post : "/api/v1/machine/{machine_id}/rename/{new_name}"
rpc RenameMachine(RenameMachineRequest) returns (RenameMachineResponse) {
option (google.api.http) = {
post: "/api/v1/machine/{machine_id}/rename/{new_name}"
};
}
rpc ListMachines(ListMachinesRequest) returns(ListMachinesResponse) {
option(google.api.http) = {
get : "/api/v1/machine"
rpc ListMachines(ListMachinesRequest) returns (ListMachinesResponse) {
option (google.api.http) = {
get: "/api/v1/machine"
};
}
rpc MoveMachine(MoveMachineRequest) returns(MoveMachineResponse) {
option(google.api.http) = {
post : "/api/v1/machine/{machine_id}/user"
rpc MoveMachine(MoveMachineRequest) returns (MoveMachineResponse) {
option (google.api.http) = {
post: "/api/v1/machine/{machine_id}/namespace"
};
}
// --- Machine end ---
// --- Route start ---
rpc GetRoutes(GetRoutesRequest) returns(GetRoutesResponse) {
option(google.api.http) = {
get : "/api/v1/routes"
rpc GetRoutes(GetRoutesRequest) returns (GetRoutesResponse) {
option (google.api.http) = {
get: "/api/v1/routes"
};
}
rpc EnableRoute(EnableRouteRequest) returns(EnableRouteResponse) {
option(google.api.http) = {
post : "/api/v1/routes/{route_id}/enable"
rpc EnableRoute(EnableRouteRequest) returns (EnableRouteResponse) {
option (google.api.http) = {
post: "/api/v1/routes/{route_id}/enable"
};
}
rpc DisableRoute(DisableRouteRequest) returns(DisableRouteResponse) {
option(google.api.http) = {
post : "/api/v1/routes/{route_id}/disable"
rpc DisableRoute(DisableRouteRequest) returns (DisableRouteResponse) {
option (google.api.http) = {
post: "/api/v1/routes/{route_id}/disable"
};
}
rpc GetMachineRoutes(GetMachineRoutesRequest) returns(GetMachineRoutesResponse) {
option(google.api.http) = {
get : "/api/v1/machine/{machine_id}/routes"
rpc GetMachineRoutes(GetMachineRoutesRequest) returns (GetMachineRoutesResponse) {
option (google.api.http) = {
get: "/api/v1/machine/{machine_id}/routes"
};
}
// --- Route end ---
// --- ApiKeys start ---
rpc CreateApiKey(CreateApiKeyRequest) returns(CreateApiKeyResponse) {
option(google.api.http) = {
post : "/api/v1/apikey"
body : "*"
rpc CreateApiKey(CreateApiKeyRequest) returns (CreateApiKeyResponse) {
option (google.api.http) = {
post: "/api/v1/apikey"
body: "*"
};
}
rpc ExpireApiKey(ExpireApiKeyRequest) returns(ExpireApiKeyResponse) {
option(google.api.http) = {
post : "/api/v1/apikey/expire"
body : "*"
rpc ExpireApiKey(ExpireApiKeyRequest) returns (ExpireApiKeyResponse) {
option (google.api.http) = {
post: "/api/v1/apikey/expire"
body: "*"
};
}
rpc ListApiKeys(ListApiKeysRequest) returns(ListApiKeysResponse) {
option(google.api.http) = {
get : "/api/v1/apikey"
rpc ListApiKeys(ListApiKeysRequest) returns (ListApiKeysResponse) {
option (google.api.http) = {
get: "/api/v1/apikey"
};
}
// --- ApiKeys end ---

View File

@@ -3,7 +3,7 @@ package headscale.v1;
option go_package = "github.com/juanfont/headscale/gen/go/v1";
import "google/protobuf/timestamp.proto";
import "headscale/v1/user.proto";
import "headscale/v1/namespace.proto";
import "headscale/v1/preauthkey.proto";
enum RegisterMethod {
@@ -20,7 +20,7 @@ message Machine {
string disco_key = 4;
repeated string ip_addresses = 5;
string name = 6;
User user = 7;
Namespace namespace = 7;
google.protobuf.Timestamp last_seen = 8;
google.protobuf.Timestamp last_successful_update = 9;
@@ -48,7 +48,7 @@ message Machine {
}
message RegisterMachineRequest {
string user = 1;
string namespace = 1;
string key = 2;
}
@@ -98,7 +98,7 @@ message RenameMachineResponse {
}
message ListMachinesRequest {
string user = 1;
string namespace = 1;
}
message ListMachinesResponse {
@@ -107,7 +107,7 @@ message ListMachinesResponse {
message MoveMachineRequest {
uint64 machine_id = 1;
string user = 2;
string namespace = 2;
}
message MoveMachineResponse {
@@ -115,7 +115,7 @@ message MoveMachineResponse {
}
message DebugCreateMachineRequest {
string user = 1;
string namespace = 1;
string key = 2;
string name = 3;
repeated string routes = 4;

View File

@@ -0,0 +1,50 @@
syntax = "proto3";
package headscale.v1;
option go_package = "github.com/juanfont/headscale/gen/go/v1";
import "google/protobuf/timestamp.proto";
message Namespace {
string id = 1;
string name = 2;
google.protobuf.Timestamp created_at = 3;
}
message GetNamespaceRequest {
string name = 1;
}
message GetNamespaceResponse {
Namespace namespace = 1;
}
message CreateNamespaceRequest {
string name = 1;
}
message CreateNamespaceResponse {
Namespace namespace = 1;
}
message RenameNamespaceRequest {
string old_name = 1;
string new_name = 2;
}
message RenameNamespaceResponse {
Namespace namespace = 1;
}
message DeleteNamespaceRequest {
string name = 1;
}
message DeleteNamespaceResponse {
}
message ListNamespacesRequest {
}
message ListNamespacesResponse {
repeated Namespace namespaces = 1;
}

View File

@@ -5,7 +5,7 @@ option go_package = "github.com/juanfont/headscale/gen/go/v1";
import "google/protobuf/timestamp.proto";
message PreAuthKey {
string user = 1;
string namespace = 1;
string id = 2;
string key = 3;
bool reusable = 4;
@@ -17,7 +17,7 @@ message PreAuthKey {
}
message CreatePreAuthKeyRequest {
string user = 1;
string namespace = 1;
bool reusable = 2;
bool ephemeral = 3;
google.protobuf.Timestamp expiration = 4;
@@ -29,7 +29,7 @@ message CreatePreAuthKeyResponse {
}
message ExpirePreAuthKeyRequest {
string user = 1;
string namespace = 1;
string key = 2;
}
@@ -37,7 +37,7 @@ message ExpirePreAuthKeyResponse {
}
message ListPreAuthKeysRequest {
string user = 1;
string namespace = 1;
}
message ListPreAuthKeysResponse {

View File

@@ -1,50 +0,0 @@
syntax = "proto3";
package headscale.v1;
option go_package = "github.com/juanfont/headscale/gen/go/v1";
import "google/protobuf/timestamp.proto";
message User {
string id = 1;
string name = 2;
google.protobuf.Timestamp created_at = 3;
}
message GetUserRequest {
string name = 1;
}
message GetUserResponse {
User user = 1;
}
message CreateUserRequest {
string name = 1;
}
message CreateUserResponse {
User user = 1;
}
message RenameUserRequest {
string old_name = 1;
string new_name = 2;
}
message RenameUserResponse {
User user = 1;
}
message DeleteUserRequest {
string name = 1;
}
message DeleteUserResponse {
}
message ListUsersRequest {
}
message ListUsersResponse {
repeated User users = 1;
}

View File

@@ -325,7 +325,7 @@ func (h *Headscale) handleAuthKeyCommon(
Err(err).
Msg("Cannot encode message")
http.Error(writer, "Internal server error", http.StatusInternalServerError)
machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name).
machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.Namespace.Name).
Inc()
return
@@ -350,7 +350,7 @@ func (h *Headscale) handleAuthKeyCommon(
Msg("Failed authentication via AuthKey")
if pak != nil {
machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name).
machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.Namespace.Name).
Inc()
} else {
machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", "unknown").Inc()
@@ -428,7 +428,7 @@ func (h *Headscale) handleAuthKeyCommon(
machineToRegister := Machine{
Hostname: registerRequest.Hostinfo.Hostname,
GivenName: givenName,
UserID: pak.User.ID,
NamespaceID: pak.Namespace.ID,
MachineKey: MachinePublicKeyStripPrefix(machineKey),
RegisterMethod: RegisterMethodAuthKey,
Expiry: &registerRequest.Expiry,
@@ -447,7 +447,7 @@ func (h *Headscale) handleAuthKeyCommon(
Bool("noise", isNoise).
Err(err).
Msg("could not register machine")
machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name).
machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.Namespace.Name).
Inc()
http.Error(writer, "Internal server error", http.StatusInternalServerError)
@@ -462,7 +462,7 @@ func (h *Headscale) handleAuthKeyCommon(
Bool("noise", isNoise).
Err(err).
Msg("Failed to use pre-auth key")
machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name).
machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.Namespace.Name).
Inc()
http.Error(writer, "Internal server error", http.StatusInternalServerError)
@@ -470,10 +470,10 @@ func (h *Headscale) handleAuthKeyCommon(
}
resp.MachineAuthorized = true
resp.User = *pak.User.toTailscaleUser()
resp.User = *pak.Namespace.toUser()
// Provide LoginName when registering with pre-auth key
// Otherwise it will need to exec `tailscale up` twice to fetch the *LoginName*
resp.Login = *pak.User.toTailscaleLogin()
resp.Login = *pak.Namespace.toLogin()
respBody, err := h.marshalResponse(resp, machineKey, isNoise)
if err != nil {
@@ -484,13 +484,13 @@ func (h *Headscale) handleAuthKeyCommon(
Str("machine", registerRequest.Hostinfo.Hostname).
Err(err).
Msg("Cannot encode message")
machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.User.Name).
machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.Namespace.Name).
Inc()
http.Error(writer, "Internal server error", http.StatusInternalServerError)
return
}
machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "success", pak.User.Name).
machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "success", pak.Namespace.Name).
Inc()
writer.Header().Set("Content-Type", "application/json; charset=utf-8")
writer.WriteHeader(http.StatusOK)
@@ -600,7 +600,7 @@ func (h *Headscale) handleMachineLogOutCommon(
resp.AuthURL = ""
resp.MachineAuthorized = false
resp.NodeKeyExpired = true
resp.User = *machine.User.toTailscaleUser()
resp.User = *machine.Namespace.toUser()
respBody, err := h.marshalResponse(resp, machineKey, isNoise)
if err != nil {
log.Error().
@@ -622,20 +622,6 @@ func (h *Headscale) handleMachineLogOutCommon(
Caller().
Err(err).
Msg("Failed to write response")
return
}
if machine.isEphemeral() {
err = h.HardDeleteMachine(&machine)
if err != nil {
log.Error().
Err(err).
Str("machine", machine.Hostname).
Msg("Cannot delete ephemeral machine from the database")
}
return
}
log.Info().
@@ -662,8 +648,8 @@ func (h *Headscale) handleMachineValidRegistrationCommon(
resp.AuthURL = ""
resp.MachineAuthorized = true
resp.User = *machine.User.toTailscaleUser()
resp.Login = *machine.User.toTailscaleLogin()
resp.User = *machine.Namespace.toUser()
resp.Login = *machine.Namespace.toLogin()
respBody, err := h.marshalResponse(resp, machineKey, isNoise)
if err != nil {
@@ -672,13 +658,13 @@ func (h *Headscale) handleMachineValidRegistrationCommon(
Bool("noise", isNoise).
Err(err).
Msg("Cannot encode message")
machineRegistrations.WithLabelValues("update", "web", "error", machine.User.Name).
machineRegistrations.WithLabelValues("update", "web", "error", machine.Namespace.Name).
Inc()
http.Error(writer, "Internal server error", http.StatusInternalServerError)
return
}
machineRegistrations.WithLabelValues("update", "web", "success", machine.User.Name).
machineRegistrations.WithLabelValues("update", "web", "success", machine.Namespace.Name).
Inc()
writer.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -726,7 +712,7 @@ func (h *Headscale) handleMachineRefreshKeyCommon(
}
resp.AuthURL = ""
resp.User = *machine.User.toTailscaleUser()
resp.User = *machine.Namespace.toUser()
respBody, err := h.marshalResponse(resp, machineKey, isNoise)
if err != nil {
log.Error().
@@ -801,13 +787,13 @@ func (h *Headscale) handleMachineExpiredOrLoggedOutCommon(
Bool("noise", isNoise).
Err(err).
Msg("Cannot encode message")
machineRegistrations.WithLabelValues("reauth", "web", "error", machine.User.Name).
machineRegistrations.WithLabelValues("reauth", "web", "error", machine.Namespace.Name).
Inc()
http.Error(writer, "Internal server error", http.StatusInternalServerError)
return
}
machineRegistrations.WithLabelValues("reauth", "web", "success", machine.User.Name).
machineRegistrations.WithLabelValues("reauth", "web", "success", machine.Namespace.Name).
Inc()
writer.Header().Set("Content-Type", "application/json; charset=utf-8")

View File

@@ -183,7 +183,7 @@ func (h *Headscale) handlePollCommon(
}
// It sounds like we should update the nodes when we have received a endpoint update
// even tho the comments in the tailscale code dont explicitly say so.
updateRequestsFromNode.WithLabelValues(machine.User.Name, machine.Hostname, "endpoint-update").
updateRequestsFromNode.WithLabelValues(machine.Namespace.Name, machine.Hostname, "endpoint-update").
Inc()
updateChan <- struct{}{}
@@ -216,7 +216,7 @@ func (h *Headscale) handlePollCommon(
Bool("noise", isNoise).
Str("machine", machine.Hostname).
Msg("Notifying peers")
updateRequestsFromNode.WithLabelValues(machine.User.Name, machine.Hostname, "full-update").
updateRequestsFromNode.WithLabelValues(machine.Namespace.Name, machine.Hostname, "full-update").
Inc()
updateChan <- struct{}{}
@@ -342,7 +342,7 @@ func (h *Headscale) pollNetMapStream(
now := time.Now().UTC()
machine.LastSeen = &now
lastStateUpdate.WithLabelValues(machine.User.Name, machine.Hostname).
lastStateUpdate.WithLabelValues(machine.Namespace.Name, machine.Hostname).
Set(float64(now.Unix()))
machine.LastSuccessfulUpdate = &now
@@ -453,7 +453,7 @@ func (h *Headscale) pollNetMapStream(
Str("machine", machine.Hostname).
Str("channel", "update").
Msg("Received a request for update")
updateRequestsReceivedOnChannel.WithLabelValues(machine.User.Name, machine.Hostname).
updateRequestsReceivedOnChannel.WithLabelValues(machine.Namespace.Name, machine.Hostname).
Inc()
if h.isOutdated(machine) {
@@ -466,7 +466,7 @@ func (h *Headscale) pollNetMapStream(
Bool("noise", isNoise).
Str("machine", machine.Hostname).
Time("last_successful_update", lastUpdate).
Time("last_state_change", h.getLastStateChange(machine.User)).
Time("last_state_change", h.getLastStateChange(machine.Namespace)).
Msgf("There has been updates since the last successful update to %s", machine.Hostname)
data, err := h.getMapResponseData(mapRequest, machine, isNoise)
if err != nil {
@@ -489,7 +489,7 @@ func (h *Headscale) pollNetMapStream(
Str("channel", "update").
Err(err).
Msg("Could not write the map response")
updateRequestsSentToNode.WithLabelValues(machine.User.Name, machine.Hostname, "failed").
updateRequestsSentToNode.WithLabelValues(machine.Namespace.Name, machine.Hostname, "failed").
Inc()
return
@@ -514,7 +514,7 @@ func (h *Headscale) pollNetMapStream(
Str("machine", machine.Hostname).
Str("channel", "update").
Msg("Updated Map has been sent")
updateRequestsSentToNode.WithLabelValues(machine.User.Name, machine.Hostname, "success").
updateRequestsSentToNode.WithLabelValues(machine.Namespace.Name, machine.Hostname, "success").
Inc()
// Keep track of the last successful update,
@@ -540,7 +540,7 @@ func (h *Headscale) pollNetMapStream(
}
now := time.Now().UTC()
lastStateUpdate.WithLabelValues(machine.User.Name, machine.Hostname).
lastStateUpdate.WithLabelValues(machine.Namespace.Name, machine.Hostname).
Set(float64(now.Unix()))
machine.LastSuccessfulUpdate = &now
@@ -566,7 +566,7 @@ func (h *Headscale) pollNetMapStream(
Bool("noise", isNoise).
Str("machine", machine.Hostname).
Time("last_successful_update", lastUpdate).
Time("last_state_change", h.getLastStateChange(machine.User)).
Time("last_state_change", h.getLastStateChange(machine.Namespace)).
Msgf("%s is up to date", machine.Hostname)
}
@@ -664,11 +664,7 @@ func (h *Headscale) scheduledPollWorker(
Str("machine", machine.Hostname).
Bool("noise", isNoise).
Msg("Sending keepalive")
select {
case keepAliveChan <- data:
case <-ctx.Done():
return
}
keepAliveChan <- data
case <-updateCheckerTicker.C:
log.Debug().
@@ -676,13 +672,9 @@ func (h *Headscale) scheduledPollWorker(
Str("machine", machine.Hostname).
Bool("noise", isNoise).
Msg("Sending update request")
updateRequestsFromNode.WithLabelValues(machine.User.Name, machine.Hostname, "scheduled-update").
updateRequestsFromNode.WithLabelValues(machine.Namespace.Name, machine.Hostname, "scheduled-update").
Inc()
select {
case updateChan <- struct{}{}:
case <-ctx.Done():
return
}
updateChan <- struct{}{}
}
}
}

View File

@@ -3,11 +3,9 @@ package headscale
import (
"encoding/binary"
"encoding/json"
"sync"
"github.com/klauspost/compress/zstd"
"github.com/rs/zerolog/log"
"tailscale.com/smallzstd"
"tailscale.com/tailcfg"
"tailscale.com/types/key"
)
@@ -105,7 +103,8 @@ func (h *Headscale) marshalMapResponse(
var respBody []byte
if compression == ZstdCompression {
respBody = zstdEncode(jsonBody)
encoder, _ := zstd.NewWriter(nil)
respBody = encoder.EncodeAll(jsonBody, nil)
if !isNoise { // if legacy protocol
respBody = h.privateKey.SealTo(machineKey, respBody)
}
@@ -123,28 +122,3 @@ func (h *Headscale) marshalMapResponse(
return data, nil
}
func zstdEncode(in []byte) []byte {
encoder, ok := zstdEncoderPool.Get().(*zstd.Encoder)
if !ok {
panic("invalid type in sync pool")
}
out := encoder.EncodeAll(in, nil)
_ = encoder.Close()
zstdEncoderPool.Put(encoder)
return out
}
var zstdEncoderPool = &sync.Pool{
New: func() any {
encoder, err := smallzstd.NewEncoder(
nil,
zstd.WithEncoderLevel(zstd.SpeedFastest))
if err != nil {
panic(err)
}
return encoder
},
}

Some files were not shown because too many files have changed in this diff Show More