Compare commits

...

74 Commits

Author SHA1 Message Date
Juan Font 248abcf353 Add missing entry to changelog and prepare for 0.22
Add missing entry to changelog
2023-03-20 13:48:56 +01:00
Kurnia D Win 2560c32378 adding some sleep on re-registration after machine expired (#1256) 2023-03-20 11:14:34 +01:00
Kristoffer Dalby e38efd3cfa Add ACL test for limiting a single port. (#1258) 2023-03-20 08:52:52 +01:00
Moritz Poldrack d12f247490 document running exit nodes
Currently the only kind-of documentation is #210 which is outdated. To remedy
this, add a document describing the process.
2023-03-19 11:02:01 +01:00
nicholas-yap 003036a779 Update iOS compatibility and added iOS docs (#1264) 2023-03-17 15:56:15 +01:00
github-actions[bot] ed79f977a7 docs(README): update contributors (#1262) 2023-03-17 10:07:39 +01:00
Kristoffer Dalby 8012e1cbd2 Add instructions on how to login to iOS (#1261) 2023-03-15 11:31:38 +00:00
Kristoffer Dalby a5562850a7 MapResponse optimalisations, peer list integration tests (#1254)
Co-authored-by: Allen <979347228@qq.com>
2023-03-06 17:50:26 +01:00
Stefan Majer bb786ac8e4 github.com/gofrs/uuid/v5 is now go modules compatible, use it (#1224) 2023-03-06 09:54:24 +01:00
Juan Font ea82035222 Allow to delete routes (#1244) 2023-03-06 09:05:40 +01:00
Albert Copeland c9ecdd6ef1 Add Graphical Control Panels section to README (#1226) 2023-03-03 19:05:12 +01:00
Juan Font 54f5c249f1 Fix various linting issues + golang-lint upgrade (#1245) 2023-03-03 18:22:47 +01:00
dnaq a82a603db6 Return 404 on unmatched routes (#1201) 2023-03-03 17:14:30 +01:00
Sean Reifschneider f49930c514 Add "configtest" CLI command. (#1230)
Co-authored-by: Kristoffer Dalby <kristoffer@dalby.cc>
Fixes https://github.com/juanfont/headscale/issues/1229
2023-03-03 14:55:29 +01:00
Kristoffer Dalby 2baeb79aa0 changelog: prep for 0.21 (#1246) 2023-03-03 13:42:45 +01:00
Kristoffer Dalby b3f78a209a Post PR comment when nix vendor sum breaks
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-03-02 18:17:59 +01:00
Josh Taylor 5e6868a858 Run prettier 2023-02-27 10:28:49 +01:00
Josh Taylor 5caf848f94 Add steps for Google OAuth for OIDC 2023-02-27 10:28:49 +01:00
Juan Font 3e097123bf Target ts 1.36 in integration tests 2023-02-26 15:35:27 +01:00
Juan Font 74447b02e8 Target Tailscale 1.36 when building 2023-02-26 15:35:27 +01:00
Juan Font 20e96de963 Update dependencies 20230226 2023-02-26 14:39:37 +01:00
Juan Font 7c765fb3dc Update prettier action
Update prettier action
2023-02-26 13:54:30 +01:00
Michael Savage dcc246c869 Fix OpenBSD build docs
- OpenBSD 7.2 installs go 1.19 by default
- Doubt you can run nix so skip the makefile/nix build and just go build directly
2023-02-26 12:54:47 +01:00
Àlex Torregrosa cf7767d8f9 Add css to the /windows and /apple templates (#1211)
Co-authored-by: Kristoffer Dalby <kristoffer@dalby.cc>
2023-02-09 08:49:05 -05:00
Maxim Gajdaj 61c578f82b Update running-headscale-linux.md
Option WorkingDirectory for headscale.service added
2023-02-09 08:17:28 -05:00
Kristoffer Dalby 6950ff7841 Add list of talks to the readme
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-07 17:04:14 +01:00
Kristoffer Dalby e65ce17f7b Add documentation to integration test framework
so tsic, hsic and scenario

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-03 16:25:58 +01:00
Kristoffer Dalby b190ec8edc Add section about running locally
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-03 16:25:58 +01:00
Kristoffer Dalby c39085911f Add node expiry test
This commits adds a test to verify that nodes get updated if a node in
their network expires.

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-03 09:26:22 +01:00
Kristoffer Dalby 3c20d2a178 Update changelog
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-03 09:26:22 +01:00
Kristoffer Dalby 9187e4287c Remove unused components from old integration tests
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-03 09:26:22 +01:00
Kristoffer Dalby 2b7bcb77a5 Stop using deprecated string function
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-03 09:26:22 +01:00
Kristoffer Dalby 97a909866d Use pingAll helper for all integration pinging
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-03 09:26:22 +01:00
Kristoffer Dalby feeb5d334b Populate the tags field on node
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-03 09:26:22 +01:00
Kristoffer Dalby a840a2e6ee Sort tailcfg.Node creation as upstream
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-03 09:26:22 +01:00
Kristoffer Dalby 4183345020 Do not collect services, we dont support it
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-03 09:26:22 +01:00
Kristoffer Dalby 50fb7ad6ce Add TODOs for only sending patch updates
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-03 09:26:22 +01:00
Kristoffer Dalby 88a9f4b44c Send control time in map response
This gives all the nodes the same constant time to work from

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-03 09:26:22 +01:00
Kristoffer Dalby 00fbd8dd93 Remove all tests before generating new ones
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-02 17:55:19 +01:00
Kristoffer Dalby ce587d2421 Update test workflows
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-01 10:58:37 +01:00
Kristoffer Dalby e1eb30084d Remove new line at start of test template
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-01 10:58:37 +01:00
Kristoffer Dalby 673638afe7 Use ripgrep to find list of tests
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-02-01 10:58:37 +01:00
Kristoffer Dalby da48cf64b3 Set OpenID Connect Expiry
This commit adds a default OpenID Connect expiry to 180d to align with
Tailscale SaaS (previously infinite or based on token expiry).

In addition, it adds an option use the expiry time from the Token sent
by the OpenID provider. This will typically cause really short expiry
and you should only turn on this option if you know what you are
desiring.

This fixes #1176.

Co-authored-by: Even Holthe <even.holthe@bekk.no>
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-31 18:55:16 +01:00
Dominic Bevacqua 385fd93e73 Update changelog 2023-01-31 00:15:48 +01:00
Dominic Bevacqua 26edf24477 Allow split DNS configuration without requiring global nameservers
Align behaviour of dns_config.restricted_nameservers to tailscale.

Tailscale allows split DNS configuration without requiring global nameservers.

In addition, as per [the docs](https://tailscale.com/kb/1054/dns/#using-dns-settings-in-the-admin-console):

> These nameservers also configure search domains for your devices

This commit aligns headscale to tailscale by:

 * honouring dns_config.restricted_nameservers regardless of whether any global resolvers are configured
 * adding a search domain for each restricted_nameserver
2023-01-31 00:15:48 +01:00
Kristoffer Dalby 83a538cc95 Rename IP specific function, add missing test case
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-30 15:56:38 +01:00
Kristoffer Dalby cffa040474 Cancel old builds if new commits appear
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-30 14:57:10 +01:00
Kristoffer Dalby 727d95b477 Improve generated integration tests
- Save logs from control(headscale) on every run to tmp
- Upgrade nix-actions
- Cancel builds if new commit is pushed
- Fix a sorting bug in user command test

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-30 14:43:03 +01:00
Juan Font 640bb94119 Do not show IsPrimary field as false in exit nodes 2023-01-29 14:54:09 +01:00
Juan Font 0f65918a25 Update tests
Fixed linting
2023-01-29 12:25:37 +01:00
Juan Font 3ac2e0b253 Enable both exit node routes (IPv4 and IPv6) at the same time.
As indicated by bradfitz in https://github.com/juanfont/headscale/issues/804#issuecomment-1399314002,
both routes for the exit node must be enabled at the same time. If a user tries to enable one of the exit node routes,
the other gets activated too.

This commit also reduces the API surface, making private a method that didnt need to be exposed.
2023-01-29 12:25:37 +01:00
Juan Font b322cdf251 Updated changelog for v0.20.0 2023-01-29 11:46:37 +01:00
Johan Siebens e128796b59 use smallzstd and sync pool 2023-01-27 12:03:24 +01:00
Kristoffer Dalby 6d669c6b9c Migrate namespace_id to user_id column in machine and pak
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-26 11:07:26 +01:00
Kristoffer Dalby 8dadb045cf Mark -n and --namespace as deprecated
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-26 10:22:38 +01:00
Christian Heusel 9f6e546522 modify the test to reflect the changes on the webinterface
related to 2d44a1c99c17

Signed-off-by: Christian Heusel <christian@heusel.eu>
2023-01-26 08:33:44 +01:00
Juan Font 9714900db9 Target Tailscale 1.36.0 2023-01-26 07:50:03 +01:00
Jan Hartkopf cb25f0d650 Add hint for reverse proxying with Apache 2023-01-23 15:51:20 +01:00
caelansar 9c2e580ab5 put Where before Find 2023-01-20 10:50:29 +01:00
Christian Heusel 0ffff2c994 Update the node join instruction to reference "username"
related to https://github.com/juanfont/headscale/pull/1144

Signed-off-by: Christian Heusel <christian@heusel.eu>
2023-01-20 09:50:49 +01:00
Christian Heusel c720af66d6 permalink in the limitations section to tailscale
The relative link was broken after one commit to the file

Signed-off-by: Christian Heusel <christian@heusel.eu>
2023-01-20 09:19:26 +01:00
Kristoffer Dalby 86a7129027 Update changelog, more explicit backup note
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-19 12:54:34 +01:00
Kristoffer Dalby 9eaa8dd049 Migrate DB: rename table is plural, order matters
The calls to AutoMigrate to other classes that refer to users will
create the table and it will break, it needs to be done before
everything else.

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-19 12:54:34 +01:00
Kristoffer Dalby 81441afe70 update changelog
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-18 15:40:04 +01:00
Kristoffer Dalby f19e8aa7f0 Fix failing tests
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-18 15:40:04 +01:00
Kristoffer Dalby 90287a6735 gofumpt
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-18 15:40:04 +01:00
Kristoffer Dalby fb3e2dcf10 Rename namespace to user in docs
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-18 15:40:04 +01:00
Kristoffer Dalby bf0b85f382 Rename acl test file
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-18 15:40:04 +01:00
Kristoffer Dalby 5da0963aac Migrate DB: rename namespace, automigrate user
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-18 15:40:04 +01:00
Kristoffer Dalby da5c051d73 Lint fix
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-18 15:40:04 +01:00
Kristoffer Dalby b98bf199dd Regenerate go from proto
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-18 15:40:04 +01:00
Kristoffer Dalby 428d7c86ce Rename namespace in protobuf files
While this truly breaks the point of the backwards compatible stuff with
protobuf, it does not seem worth it to attempt to glue together a
compatible API.

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-18 15:40:04 +01:00
Kristoffer Dalby af1ec5a593 Rename .go namespace files
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-18 15:40:04 +01:00
Kristoffer Dalby e3a2593344 Rename [Nn]amespace -> [Uu]ser in go code
Use gopls, ag and perl to rename all occurances of Namespace

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2023-01-18 15:40:04 +01:00
127 changed files with 6527 additions and 4536 deletions
+31 -2
View File
@@ -8,9 +8,14 @@ on:
branches:
- main
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
permissions: write-all
steps:
- uses: actions/checkout@v3
@@ -32,10 +37,34 @@ jobs:
if: steps.changed-files.outputs.any_changed == 'true'
- name: Run build
id: build
if: steps.changed-files.outputs.any_changed == 'true'
run: nix build
run: |
nix build |& tee build-result
BUILD_STATUS="${PIPESTATUS[0]}"
- uses: actions/upload-artifact@v2
OLD_HASH=$(cat build-result | grep specified: | awk -F ':' '{print $2}' | sed 's/ //g')
NEW_HASH=$(cat build-result | grep got: | awk -F ':' '{print $2}' | sed 's/ //g')
echo "OLD_HASH=$OLD_HASH" >> $GITHUB_OUTPUT
echo "NEW_HASH=$NEW_HASH" >> $GITHUB_OUTPUT
exit $BUILD_STATUS
- name: Nix gosum diverging
uses: actions/github-script@v6
if: failure() && steps.build.outcome == 'failure'
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.rest.pulls.createReviewComment({
pull_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Nix build failed with wrong gosum, please update "vendorSha256" (${{ steps.build.outputs.OLD_HASH }}) for the "headscale" package in flake.nix with the new SHA: ${{ steps.build.outputs.NEW_HASH }}'
})
- uses: actions/upload-artifact@v3
if: steps.changed-files.outputs.any_changed == 'true'
with:
name: headscale-linux
+6 -2
View File
@@ -3,6 +3,10 @@ name: Lint
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
golangci-lint:
runs-on: ubuntu-latest
@@ -26,7 +30,7 @@ jobs:
if: steps.changed-files.outputs.any_changed == 'true'
uses: golangci/golangci-lint-action@v2
with:
version: v1.49.0
version: v1.51.2
# Only block PRs on new problems.
# If this is not enabled, we will end up having PRs
@@ -59,7 +63,7 @@ jobs:
- name: Prettify code
if: steps.changed-files.outputs.any_changed == 'true'
uses: creyD/prettier_action@v4.0
uses: creyD/prettier_action@v4.3
with:
prettier_options: >-
--check **/*.{ts,js,md,yaml,yml,sass,css,scss,html}
@@ -1,11 +1,14 @@
# 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
name: Integration Test v2 - TestACLAllowUser80Dst
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,10 +41,17 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestSSHOneNamespaceAllToAll$"
-run "^TestACLAllowUser80Dst$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -0,0 +1,57 @@
# 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 - TestACLHostsInNetMapTable
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
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@v18
if: ${{ env.ACT }} || 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 \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestACLHostsInNetMapTable$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestAuthKeyLogoutAndRelogin
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestAuthKeyLogoutAndRelogin$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestAuthWebFlowAuthenticationPingAll
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestAuthWebFlowAuthenticationPingAll$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestAuthWebFlowLogoutAndRelogin
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestAuthWebFlowLogoutAndRelogin$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestCreateTailscale
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestCreateTailscale$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestEnablingRoutes
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestEnablingRoutes$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,11 +1,14 @@
# 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
name: Integration Test v2 - TestEphemeral
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,10 +41,17 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestNamespaceCommand$"
-run "^TestEphemeral$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,11 +1,14 @@
# 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
name: Integration Test v2 - TestExpireNode
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,10 +41,17 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestOIDCExpireNodes$"
-run "^TestExpireNode$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestHeadscale
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestHeadscale$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestOIDCAuthenticationPingAll
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestOIDCAuthenticationPingAll$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -0,0 +1,57 @@
# 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 - TestOIDCExpireNodesBasedOnTokenExpiry
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
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@v18
if: ${{ env.ACT }} || 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 \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestOIDCExpireNodesBasedOnTokenExpiry$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestPingAllByHostname
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestPingAllByHostname$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestPingAllByIP
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestPingAllByIP$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestPreAuthKeyCommand
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestPreAuthKeyCommand$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestPreAuthKeyCommandReusableEphemeral
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestPreAuthKeyCommandReusableEphemeral$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestPreAuthKeyCommandWithoutExpiry
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestPreAuthKeyCommandWithoutExpiry$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestResolveMagicDNS
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestResolveMagicDNS$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestSSHIsBlockedInACL
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestSSHIsBlockedInACL$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -0,0 +1,57 @@
# 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 - TestSSHMultipleUsersAllToAll
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
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@v18
if: ${{ env.ACT }} || 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 \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestSSHMultipleUsersAllToAll$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestSSHNoSSHConfigured
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestSSHNoSSHConfigured$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -0,0 +1,57 @@
# 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 - TestSSHOneUserAllToAll
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
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@v18
if: ${{ env.ACT }} || 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 \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestSSHOneUserAllToAll$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -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$"
@@ -0,0 +1,57 @@
# 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 - TestSSUserOnlyIsolation
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
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@v18
if: ${{ env.ACT }} || 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 \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestSSUserOnlyIsolation$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestTaildrop
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestTaildrop$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,4 +1,3 @@
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/
@@ -6,6 +5,10 @@ name: Integration Test v2 - TestTailscaleNodesJoiningHeadcale
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,6 +41,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -45,3 +49,9 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^TestTailscaleNodesJoiningHeadcale$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
@@ -1,11 +1,14 @@
# 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
name: Integration Test v2 - TestUserCommand
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -26,8 +29,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: ${{ env.ACT }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -38,10 +41,17 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
-failfast \
-timeout 120m \
-parallel 1 \
-run "^TestSSHMultipleNamespacesAllToAll$"
-run "^TestUserCommand$"
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
+4
View File
@@ -2,6 +2,10 @@ name: Tests
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
+2 -1
View File
@@ -26,7 +26,8 @@ derp.yaml
# Exclude Jetbrains Editors
.idea
test_output/
test_output/
control_logs/
# Nix build output
result
+34 -1
View File
@@ -1,6 +1,39 @@
# CHANGELOG
## 0.18.x (2022-xx-xx)
## 0.22.0 (2023-XX-XX)
### Changes
## 0.21.0 (2023-03-20)
### Changes
- Adding "configtest" CLI command. [#1230](https://github.com/juanfont/headscale/pull/1230)
- Add documentation on connecting with iOS to `/apple` [#1261](https://github.com/juanfont/headscale/pull/1261)
- Update iOS compatibility and added documentation for iOS [#1264](https://github.com/juanfont/headscale/pull/1264)
- Allow to delete routes [#1244](https://github.com/juanfont/headscale/pull/1244)
## 0.20.0 (2023-02-03)
### Changes
- Fix wrong behaviour in exit nodes [#1159](https://github.com/juanfont/headscale/pull/1159)
- Align behaviour of `dns_config.restricted_nameservers` to tailscale [#1162](https://github.com/juanfont/headscale/pull/1162)
- Make OpenID Connect authenticated client expiry time configurable [#1191](https://github.com/juanfont/headscale/pull/1191)
- defaults to 180 days like Tailscale SaaS
- adds option to use the expiry time from the OpenID token for the node (see config-example.yaml)
- Set ControlTime in Map info sent to nodes [#1195](https://github.com/juanfont/headscale/pull/1195)
- Populate Tags field on Node updates sent [#1195](https://github.com/juanfont/headscale/pull/1195)
## 0.19.0 (2023-01-29)
### 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 (2023-01-14)
### Changes
+212 -43
View File
@@ -75,12 +75,26 @@ one of the maintainers.
| macOS | Yes (see `/apple` on your headscale for more information) |
| Windows | Yes [docs](./docs/windows-client.md) |
| Android | Yes [docs](./docs/android-client.md) |
| iOS | Not yet |
| iOS | Yes [docs](./docs/iOS-client.md) |
## Running headscale
Please have a look at the documentation under [`docs/`](docs/).
## Graphical Control Panels
Headscale provides an API for complete management of your Tailnet.
These are community projects not directly affiliated with the Headscale project.
| Name | Repository Link | Description | Status |
| --------------- | ---------------------------------------------------- | ------------------------------------------------------ | ------ |
| headscale-webui | [Github](https://github.com/ifargle/headscale-webui) | A simple Headscale web UI for small-scale deployments. | Alpha |
## Talks
- Fosdem 2023 (video): [Headscale: How we are using integration testing to reimplement Tailscale](https://fosdem.org/2023/schedule/event/goheadscale/)
- presented by Juan Font Alonso and Kristoffer Dalby
## Disclaimer
1. We have nothing to do with Tailscale, or Tailscale Inc.
@@ -211,6 +225,13 @@ make build
<sub style="font-size:14px"><b>Nico</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/evenh>
<img src=https://avatars.githubusercontent.com/u/2701536?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Even Holthe/>
<br />
<sub style="font-size:14px"><b>Even Holthe</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/e-zk>
<img src=https://avatars.githubusercontent.com/u/58356365?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=e-zk/>
@@ -239,6 +260,8 @@ make build
<sub style="font-size:14px"><b>unreality</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/ohdearaugustin>
<img src=https://avatars.githubusercontent.com/u/14001491?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=ohdearaugustin/>
@@ -246,8 +269,6 @@ make build
<sub style="font-size:14px"><b>ohdearaugustin</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/mpldr>
<img src=https://avatars.githubusercontent.com/u/33086936?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Moritz Poldrack/>
@@ -262,6 +283,13 @@ make build
<sub style="font-size:14px"><b>GrigoriyMikhalkin</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/christian-heusel>
<img src=https://avatars.githubusercontent.com/u/26827864?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Christian Heusel/>
<br />
<sub style="font-size:14px"><b>Christian Heusel</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/mike-lloyd03>
<img src=https://avatars.githubusercontent.com/u/49411532?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Mike Lloyd/>
@@ -276,6 +304,8 @@ make build
<sub style="font-size:14px"><b>Anton Schubert</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/Niek>
<img src=https://avatars.githubusercontent.com/u/213140?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Niek van der Maas/>
@@ -290,8 +320,6 @@ make build
<sub style="font-size:14px"><b>Eugen Biegler</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/617a7a>
<img src=https://avatars.githubusercontent.com/u/67651251?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Azz/>
@@ -299,13 +327,6 @@ make build
<sub style="font-size:14px"><b>Azz</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/evenh>
<img src=https://avatars.githubusercontent.com/u/2701536?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Even Holthe/>
<br />
<sub style="font-size:14px"><b>Even Holthe</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/qbit>
<img src=https://avatars.githubusercontent.com/u/68368?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Aaron Bieber/>
@@ -327,6 +348,8 @@ make build
<sub style="font-size:14px"><b>Laurent Marchaud</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/fdelucchijr>
<img src=https://avatars.githubusercontent.com/u/69133647?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Fernando De Lucchi/>
@@ -334,8 +357,6 @@ make build
<sub style="font-size:14px"><b>Fernando De Lucchi</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/OrvilleQ>
<img src=https://avatars.githubusercontent.com/u/21377465?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Orville Q. Song/>
@@ -343,6 +364,13 @@ make build
<sub style="font-size:14px"><b>Orville Q. Song</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/majst01>
<img src=https://avatars.githubusercontent.com/u/410110?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Stefan Majer/>
<br />
<sub style="font-size:14px"><b>Stefan Majer</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/hdhoang>
<img src=https://avatars.githubusercontent.com/u/12537?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=hdhoang/>
@@ -364,6 +392,8 @@ make build
<sub style="font-size:14px"><b>Deon Thomas</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/madjam002>
<img src=https://avatars.githubusercontent.com/u/679137?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Jamie Greeff/>
@@ -378,8 +408,6 @@ make build
<sub style="font-size:14px"><b>ChibangLW</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/mevansam>
<img src=https://avatars.githubusercontent.com/u/403630?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Mevan Samaratunga/>
@@ -408,13 +436,8 @@ make build
<sub style="font-size:14px"><b>Samuel Lock</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/majst01>
<img src=https://avatars.githubusercontent.com/u/410110?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Stefan Majer/>
<br />
<sub style="font-size:14px"><b>Stefan Majer</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/kevin1sMe>
<img src=https://avatars.githubusercontent.com/u/6886076?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=kevinlin/>
@@ -422,8 +445,13 @@ make build
<sub style="font-size:14px"><b>kevinlin</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/QZAiXH>
<img src=https://avatars.githubusercontent.com/u/23068780?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Snack/>
<br />
<sub style="font-size:14px"><b>Snack</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/artemklevtsov>
<img src=https://avatars.githubusercontent.com/u/603798?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Artem Klevtsov/>
@@ -438,6 +466,22 @@ make build
<sub style="font-size:14px"><b>Casey Marshall</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/dbevacqua>
<img src=https://avatars.githubusercontent.com/u/6534306?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=dbevacqua/>
<br />
<sub style="font-size:14px"><b>dbevacqua</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/joshuataylor>
<img src=https://avatars.githubusercontent.com/u/225131?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Josh Taylor/>
<br />
<sub style="font-size:14px"><b>Josh Taylor</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/CNLHC>
<img src=https://avatars.githubusercontent.com/u/21005146?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=LiuHanCheng/>
@@ -445,6 +489,13 @@ make build
<sub style="font-size:14px"><b>LiuHanCheng</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/motiejus>
<img src=https://avatars.githubusercontent.com/u/107720?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Motiejus Jakštys/>
<br />
<sub style="font-size:14px"><b>Motiejus Jakštys</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/pvinis>
<img src=https://avatars.githubusercontent.com/u/100233?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Pavlos Vinieratos/>
@@ -466,8 +517,6 @@ make build
<sub style="font-size:14px"><b>Steven Honson</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/ratsclub>
<img src=https://avatars.githubusercontent.com/u/25647735?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Victor Freire/>
@@ -475,6 +524,8 @@ make build
<sub style="font-size:14px"><b>Victor Freire</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/lachy2849>
<img src=https://avatars.githubusercontent.com/u/98844035?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=lachy2849/>
@@ -496,6 +547,13 @@ make build
<sub style="font-size:14px"><b>Abraham Ingersoll</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/iFargle>
<img src=https://avatars.githubusercontent.com/u/124551390?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Albert Copeland/>
<br />
<sub style="font-size:14px"><b>Albert Copeland</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/puzpuzpuz>
<img src=https://avatars.githubusercontent.com/u/37772591?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Andrei Pechkurov/>
@@ -503,6 +561,15 @@ make build
<sub style="font-size:14px"><b>Andrei Pechkurov</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/theryecatcher>
<img src=https://avatars.githubusercontent.com/u/16442416?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Anoop Sundaresh/>
<br />
<sub style="font-size:14px"><b>Anoop Sundaresh</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/apognu>
<img src=https://avatars.githubusercontent.com/u/3017182?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Antoine POPINEAU/>
@@ -510,8 +577,6 @@ make build
<sub style="font-size:14px"><b>Antoine POPINEAU</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/aofei>
<img src=https://avatars.githubusercontent.com/u/5037285?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Aofei Sheng/>
@@ -533,6 +598,13 @@ make build
<sub style="font-size:14px"><b>Arthur Woimbée</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/avirut>
<img src=https://avatars.githubusercontent.com/u/27095602?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Avirut Mehta/>
<br />
<sub style="font-size:14px"><b>Avirut Mehta</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/stensonb>
<img src=https://avatars.githubusercontent.com/u/933389?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Bryan Stenson/>
@@ -540,6 +612,8 @@ make build
<sub style="font-size:14px"><b>Bryan Stenson</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/yangchuansheng>
<img src=https://avatars.githubusercontent.com/u/15308462?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt= Carson Yang/>
@@ -554,8 +628,13 @@ make build
<sub style="font-size:14px"><b>kundel</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/fatih-acar>
<img src=https://avatars.githubusercontent.com/u/15028881?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=fatih-acar/>
<br />
<sub style="font-size:14px"><b>fatih-acar</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/fkr>
<img src=https://avatars.githubusercontent.com/u/51063?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Felix Kronlage-Dammers/>
@@ -577,6 +656,15 @@ make build
<sub style="font-size:14px"><b>JJGadgets</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/hrtkpf>
<img src=https://avatars.githubusercontent.com/u/42646788?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=hrtkpf/>
<br />
<sub style="font-size:14px"><b>hrtkpf</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/jimt>
<img src=https://avatars.githubusercontent.com/u/180326?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Jim Tittsler/>
@@ -584,6 +672,20 @@ make build
<sub style="font-size:14px"><b>Jim Tittsler</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/jsiebens>
<img src=https://avatars.githubusercontent.com/u/499769?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Johan Siebens/>
<br />
<sub style="font-size:14px"><b>Johan Siebens</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/johnae>
<img src=https://avatars.githubusercontent.com/u/28332?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=John Axel Eriksson/>
<br />
<sub style="font-size:14px"><b>John Axel Eriksson</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/ShadowJonathan>
<img src=https://avatars.githubusercontent.com/u/22740616?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Jonathan de Jong/>
@@ -591,6 +693,29 @@ make build
<sub style="font-size:14px"><b>Jonathan de Jong</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/foxtrot>
<img src=https://avatars.githubusercontent.com/u/4153572?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Marc/>
<br />
<sub style="font-size:14px"><b>Marc</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/magf>
<img src=https://avatars.githubusercontent.com/u/11992737?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Maxim Gajdaj/>
<br />
<sub style="font-size:14px"><b>Maxim Gajdaj</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/mikejsavage>
<img src=https://avatars.githubusercontent.com/u/579299?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Michael Savage/>
<br />
<sub style="font-size:14px"><b>Michael Savage</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/piec>
<img src=https://avatars.githubusercontent.com/u/781471?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Pierre Carru/>
@@ -598,8 +723,6 @@ make build
<sub style="font-size:14px"><b>Pierre Carru</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/Donran>
<img src=https://avatars.githubusercontent.com/u/4838348?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Pontus N/>
@@ -621,6 +744,8 @@ make build
<sub style="font-size:14px"><b>rcursaru</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/renovate-bot>
<img src=https://avatars.githubusercontent.com/u/25180681?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Mend Renovate/>
@@ -635,6 +760,13 @@ make build
<sub style="font-size:14px"><b>Ryan Fowler</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/linsomniac>
<img src=https://avatars.githubusercontent.com/u/466380?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Sean Reifschneider/>
<br />
<sub style="font-size:14px"><b>Sean Reifschneider</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/shaananc>
<img src=https://avatars.githubusercontent.com/u/2287839?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Shaanan Cohney/>
@@ -642,8 +774,6 @@ make build
<sub style="font-size:14px"><b>Shaanan Cohney</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/stefanvanburen>
<img src=https://avatars.githubusercontent.com/u/622527?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Stefan VanBuren/>
@@ -658,6 +788,8 @@ make build
<sub style="font-size:14px"><b>sophware</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/m-tanner-dev0>
<img src=https://avatars.githubusercontent.com/u/97977342?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Tanner/>
@@ -686,8 +818,6 @@ make build
<sub style="font-size:14px"><b>Tianon Gravi</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/thetillhoff>
<img src=https://avatars.githubusercontent.com/u/25052289?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Till Hoffmann/>
@@ -702,6 +832,8 @@ make build
<sub style="font-size:14px"><b>Tjerk Woudsma</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/y0ngb1n>
<img src=https://avatars.githubusercontent.com/u/25719408?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Yang Bin/>
@@ -718,9 +850,9 @@ make build
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/newellz2>
<img src=https://avatars.githubusercontent.com/u/52436542?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Zachary N./>
<img src=https://avatars.githubusercontent.com/u/52436542?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Zachary Newell/>
<br />
<sub style="font-size:14px"><b>Zachary N.</b></sub>
<sub style="font-size:14px"><b>Zachary Newell</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
@@ -730,8 +862,6 @@ make build
<sub style="font-size:14px"><b>Zakhar Bessarab</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/zhzy0077>
<img src=https://avatars.githubusercontent.com/u/8717471?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Zhiyuan Zheng/>
@@ -746,6 +876,15 @@ make build
<sub style="font-size:14px"><b>Ziyuan Han</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/caelansar>
<img src=https://avatars.githubusercontent.com/u/31852257?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=caelansar/>
<br />
<sub style="font-size:14px"><b>caelansar</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/derelm>
<img src=https://avatars.githubusercontent.com/u/465155?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=derelm/>
@@ -753,6 +892,13 @@ make build
<sub style="font-size:14px"><b>derelm</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/dnaq>
<img src=https://avatars.githubusercontent.com/u/1299717?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=dnaq/>
<br />
<sub style="font-size:14px"><b>dnaq</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/nning>
<img src=https://avatars.githubusercontent.com/u/557430?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=henning mueller/>
@@ -767,6 +913,15 @@ make build
<sub style="font-size:14px"><b>ignoramous</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/jimyag>
<img src=https://avatars.githubusercontent.com/u/69233189?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=jimyag/>
<br />
<sub style="font-size:14px"><b>jimyag</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/magichuihui>
<img src=https://avatars.githubusercontent.com/u/10866198?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=suhelen/>
@@ -774,8 +929,6 @@ make build
<sub style="font-size:14px"><b>suhelen</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/lion24>
<img src=https://avatars.githubusercontent.com/u/1382102?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=sharkonet/>
@@ -783,6 +936,13 @@ make build
<sub style="font-size:14px"><b>sharkonet</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/ma6174>
<img src=https://avatars.githubusercontent.com/u/1449133?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=ma6174/>
<br />
<sub style="font-size:14px"><b>ma6174</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/manju-rn>
<img src=https://avatars.githubusercontent.com/u/26291847?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=manju-rn/>
@@ -804,6 +964,8 @@ make build
<sub style="font-size:14px"><b>phpmalik</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/Wakeful-Cloud>
<img src=https://avatars.githubusercontent.com/u/38930607?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Wakeful-Cloud/>
@@ -818,5 +980,12 @@ make build
<sub style="font-size:14px"><b>zy</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0">
<a href=https://github.com/atorregrosa-smd>
<img src=https://avatars.githubusercontent.com/u/78434679?v=4 width="100;" style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Àlex Torregrosa/>
<br />
<sub style="font-size:14px"><b>Àlex Torregrosa</b></sub>
</a>
</td>
</tr>
</table>
+58 -21
View File
@@ -133,6 +133,14 @@ func (h *Headscale) UpdateACLRules() error {
log.Trace().Interface("ACL", rules).Msg("ACL rules generated")
h.aclRules = rules
// Precompute a map of which sources can reach each destination, this is
// to provide quicker lookup when we calculate the peerlist for the map
// response to nodes.
aclPeerCacheMap := generateACLPeerCacheMap(rules)
h.aclPeerCacheMapRW.Lock()
h.aclPeerCacheMap = aclPeerCacheMap
h.aclPeerCacheMapRW.Unlock()
if featureEnableSSH() {
sshRules, err := h.generateSSHRules()
if err != nil {
@@ -150,7 +158,35 @@ func (h *Headscale) UpdateACLRules() error {
return nil
}
func generateACLRules(machines []Machine, aclPolicy ACLPolicy, stripEmaildomain bool) ([]tailcfg.FilterRule, error) {
// generateACLPeerCacheMap takes a list of Tailscale filter rules and generates a map
// of which Sources ("*" and IPs) can access destinations. This is to speed up the
// process of generating MapResponses when deciding which Peers to inform nodes about.
func generateACLPeerCacheMap(rules []tailcfg.FilterRule) map[string]map[string]struct{} {
aclCachePeerMap := make(map[string]map[string]struct{})
for _, rule := range rules {
for _, srcIP := range rule.SrcIPs {
if data, ok := aclCachePeerMap[srcIP]; ok {
for _, dstPort := range rule.DstPorts {
data[dstPort.IP] = struct{}{}
}
} else {
dstPortsMap := make(map[string]struct{}, len(rule.DstPorts))
for _, dstPort := range rule.DstPorts {
dstPortsMap[dstPort.IP] = struct{}{}
}
aclCachePeerMap[srcIP] = dstPortsMap
}
}
}
return aclCachePeerMap
}
func generateACLRules(
machines []Machine,
aclPolicy ACLPolicy,
stripEmaildomain bool,
) ([]tailcfg.FilterRule, error) {
rules := []tailcfg.FilterRule{}
for index, acl := range aclPolicy.ACLs {
@@ -160,7 +196,7 @@ func generateACLRules(machines []Machine, aclPolicy ACLPolicy, stripEmaildomain
srcIPs := []string{}
for innerIndex, src := range acl.Sources {
srcs, err := generateACLPolicySrcIP(machines, aclPolicy, src, stripEmaildomain)
srcs, err := generateACLPolicySrc(machines, aclPolicy, src, stripEmaildomain)
if err != nil {
log.Error().
Msgf("Error parsing ACL %d, Source %d", index, innerIndex)
@@ -311,7 +347,7 @@ func sshCheckAction(duration string) (*tailcfg.SSHAction, error) {
}, nil
}
func generateACLPolicySrcIP(
func generateACLPolicySrc(
machines []Machine,
aclPolicy ACLPolicy,
src string,
@@ -424,9 +460,10 @@ func parseProtocol(protocol string) ([]int, bool, error) {
}
// expandalias has an input of either
// - a namespace
// - a user
// - a group
// - a tag
// - a host
// and transform these in IPAddresses.
func expandAlias(
machines []Machine,
@@ -444,12 +481,12 @@ func expandAlias(
Msg("Expanding")
if strings.HasPrefix(alias, "group:") {
namespaces, err := expandGroup(aclPolicy, alias, stripEmailDomain)
users, err := expandGroup(aclPolicy, alias, stripEmailDomain)
if err != nil {
return ips, err
}
for _, n := range namespaces {
nodes := filterMachinesByNamespace(machines, n)
for _, n := range users {
nodes := filterMachinesByUser(machines, n)
for _, node := range nodes {
ips = append(ips, node.IPAddresses.ToStringSlice()...)
}
@@ -485,8 +522,8 @@ func expandAlias(
}
// filter out machines per tag owner
for _, namespace := range owners {
machines := filterMachinesByNamespace(machines, namespace)
for _, user := range owners {
machines := filterMachinesByUser(machines, user)
for _, machine := range machines {
hi := machine.GetHostInfo()
if contains(hi.RequestTags, alias) {
@@ -498,8 +535,8 @@ func expandAlias(
return ips, nil
}
// if alias is a namespace
nodes := filterMachinesByNamespace(machines, alias)
// if alias is a user
nodes := filterMachinesByUser(machines, alias)
nodes = excludeCorrectlyTaggedNodes(aclPolicy, nodes, alias, stripEmailDomain)
for _, n := range nodes {
@@ -532,20 +569,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 namespace
// we assume in this function that we only have nodes from 1 namespace.
// 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.
func excludeCorrectlyTaggedNodes(
aclPolicy ACLPolicy,
nodes []Machine,
namespace string,
user string,
stripEmailDomain bool,
) []Machine {
out := []Machine{}
tags := []string{}
for tag := range aclPolicy.TagOwners {
owners, _ := expandTagOwners(aclPolicy, namespace, stripEmailDomain)
ns := append(owners, namespace)
if contains(ns, namespace) {
owners, _ := expandTagOwners(aclPolicy, user, stripEmailDomain)
ns := append(owners, user)
if contains(ns, user) {
tags = append(tags, tag)
}
}
@@ -619,10 +656,10 @@ func expandPorts(portsStr string, needsWildcard bool) (*[]tailcfg.PortRange, err
return &ports, nil
}
func filterMachinesByNamespace(machines []Machine, namespace string) []Machine {
func filterMachinesByUser(machines []Machine, user string) []Machine {
out := []Machine{}
for _, machine := range machines {
if machine.Namespace.Name == namespace {
if machine.User.Name == user {
out = append(out, machine)
}
}
@@ -630,7 +667,7 @@ func filterMachinesByNamespace(machines []Machine, namespace string) []Machine {
return out
}
// expandTagOwners will return a list of namespace. An owner can be either a namespace or a group
// expandTagOwners will return a list of user. An owner can be either a user or a group
// a group cannot be composed of groups.
func expandTagOwners(
aclPolicy ACLPolicy,
@@ -661,7 +698,7 @@ func expandTagOwners(
return owners, nil
}
// expandGroup will return the list of namespace inside the group
// expandGroup will return the list of user inside the group
// after some validation.
func expandGroup(
aclPolicy ACLPolicy,
+123 -108
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")
namespace, err := app.CreateNamespace("user1")
user, err := app.CreateUser("user1")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(user.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")},
NamespaceID: namespace.ID,
UserID: user.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) {
namespace, err := app.CreateNamespace("user1")
user, err := app.CreateUser("user1")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(user.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")},
NamespaceID: namespace.ID,
UserID: user.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) {
namespace, err := app.CreateNamespace("user1")
user, err := app.CreateUser("user1")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(user.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")},
NamespaceID: namespace.ID,
UserID: user.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 namespace
// tag on a host that isn't owned by a tag owners. So the user
// of the host should be valid.
func (s *Suite) TestInvalidTagValidNamespace(c *check.C) {
namespace, err := app.CreateNamespace("user1")
func (s *Suite) TestInvalidTagValidUser(c *check.C) {
user, err := app.CreateUser("user1")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("user1", "testmachine")
@@ -308,7 +308,7 @@ func (s *Suite) TestInvalidTagValidNamespace(c *check.C) {
DiscoKey: "faa",
Hostname: "testmachine",
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.1")},
NamespaceID: namespace.ID,
UserID: user.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
HostInfo: HostInfo(hostInfo),
@@ -333,13 +333,13 @@ func (s *Suite) TestInvalidTagValidNamespace(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 namespace. It should not be valid since the
// an ACL rule is matching the tag to a user. It should not be valid since the
// host should be tied to the tag now.
func (s *Suite) TestValidTagInvalidNamespace(c *check.C) {
namespace, err := app.CreateNamespace("user1")
func (s *Suite) TestValidTagInvalidUser(c *check.C) {
user, err := app.CreateUser("user1")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("user1", "webserver")
@@ -357,7 +357,7 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) {
DiscoKey: "faa",
Hostname: "webserver",
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.1")},
NamespaceID: namespace.ID,
UserID: user.ID,
RegisterMethod: RegisterMethodAuthKey,
AuthKeyID: uint(pak.ID),
HostInfo: HostInfo(hostInfo),
@@ -376,7 +376,7 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) {
DiscoKey: "faab",
Hostname: "user",
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.2")},
NamespaceID: namespace.ID,
UserID: user.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) TestPortNamespace(c *check.C) {
namespace, err := app.CreateNamespace("testnamespace")
func (s *Suite) TestPortUser(c *check.C) {
user, err := app.CreateUser("testuser")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("testnamespace", "testmachine")
_, err = app.GetMachine("testuser", "testmachine")
c.Assert(err, check.NotNil)
ips, _ := app.getAvailableIPs()
machine := Machine{
@@ -483,7 +483,7 @@ func (s *Suite) TestPortNamespace(c *check.C) {
NodeKey: "bar",
DiscoKey: "faa",
Hostname: "testmachine",
NamespaceID: namespace.ID,
UserID: user.ID,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: ips,
AuthKeyID: uint(pak.ID),
@@ -491,7 +491,7 @@ func (s *Suite) TestPortNamespace(c *check.C) {
app.db.Save(&machine)
err = app.LoadACLPolicy(
"./tests/acls/acl_policy_basic_namespace_as_user.hujson",
"./tests/acls/acl_policy_basic_user_as_user.hujson",
)
c.Assert(err, check.IsNil)
@@ -513,13 +513,13 @@ func (s *Suite) TestPortNamespace(c *check.C) {
}
func (s *Suite) TestPortGroup(c *check.C) {
namespace, err := app.CreateNamespace("testnamespace")
user, err := app.CreateUser("testuser")
c.Assert(err, check.IsNil)
pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil, nil)
pak, err := app.CreatePreAuthKey(user.Name, false, false, nil, nil)
c.Assert(err, check.IsNil)
_, err = app.GetMachine("testnamespace", "testmachine")
_, err = app.GetMachine("testuser", "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",
NamespaceID: namespace.ID,
UserID: user.ID,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: ips,
AuthKeyID: uint(pak.ID),
@@ -689,7 +689,7 @@ func Test_expandTagOwners(t *testing.T) {
wantErr: false,
},
{
name: "expand with namespace and group",
name: "expand with user 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_listMachinesInNamespace(t *testing.T) {
func Test_listMachinesInUser(t *testing.T) {
type args struct {
machines []Machine
namespace string
machines []Machine
user string
}
tests := []struct {
name string
@@ -854,54 +854,54 @@ func Test_listMachinesInNamespace(t *testing.T) {
want []Machine
}{
{
name: "1 machine in namespace",
name: "1 machine in user",
args: args{
machines: []Machine{
{Namespace: Namespace{Name: "joe"}},
{User: User{Name: "joe"}},
},
namespace: "joe",
user: "joe",
},
want: []Machine{
{Namespace: Namespace{Name: "joe"}},
{User: User{Name: "joe"}},
},
},
{
name: "3 machines, 2 in namespace",
name: "3 machines, 2 in user",
args: args{
machines: []Machine{
{ID: 1, Namespace: Namespace{Name: "joe"}},
{ID: 2, Namespace: Namespace{Name: "marc"}},
{ID: 3, Namespace: Namespace{Name: "marc"}},
{ID: 1, User: User{Name: "joe"}},
{ID: 2, User: User{Name: "marc"}},
{ID: 3, User: User{Name: "marc"}},
},
namespace: "marc",
user: "marc",
},
want: []Machine{
{ID: 2, Namespace: Namespace{Name: "marc"}},
{ID: 3, Namespace: Namespace{Name: "marc"}},
{ID: 2, User: User{Name: "marc"}},
{ID: 3, User: User{Name: "marc"}},
},
},
{
name: "5 machines, 0 in namespace",
name: "5 machines, 0 in user",
args: args{
machines: []Machine{
{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"}},
{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"}},
},
namespace: "mickael",
user: "mickael",
},
want: []Machine{},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if got := filterMachinesByNamespace(test.args.machines, test.args.namespace); !reflect.DeepEqual(
if got := filterMachinesByUser(test.args.machines, test.args.user); !reflect.DeepEqual(
got,
test.want,
) {
t.Errorf("listMachinesInNamespace() = %v, want %v", got, test.want)
t.Errorf("listMachinesInUser() = %v, want %v", got, test.want)
}
})
}
@@ -947,25 +947,25 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
Namespace: Namespace{Name: "marc"},
User: User{Name: "marc"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
Namespace: Namespace{Name: "mickael"},
User: User{Name: "mickael"},
},
},
aclPolicy: ACLPolicy{
@@ -985,25 +985,25 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
Namespace: Namespace{Name: "marc"},
User: User{Name: "marc"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
Namespace: Namespace{Name: "mickael"},
User: User{Name: "mickael"},
},
},
aclPolicy: ACLPolicy{
@@ -1041,7 +1041,7 @@ func Test_expandAlias(t *testing.T) {
wantErr: false,
},
{
name: "simple host",
name: "simple host by ip",
args: args{
alias: "10.0.0.1",
machines: []Machine{},
@@ -1051,6 +1051,21 @@ func Test_expandAlias(t *testing.T) {
want: []string{"10.0.0.1"},
wantErr: false,
},
{
name: "simple host by hostname alias",
args: args{
alias: "testy",
machines: []Machine{},
aclPolicy: ACLPolicy{
Hosts: Hosts{
"testy": netip.MustParsePrefix("10.0.0.132/32"),
},
},
stripEmailDomain: true,
},
want: []string{"10.0.0.132/32"},
wantErr: false,
},
{
name: "simple CIDR",
args: args{
@@ -1071,7 +1086,7 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1082,7 +1097,7 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1093,13 +1108,13 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
Namespace: Namespace{Name: "marc"},
User: User{Name: "marc"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
},
aclPolicy: ACLPolicy{
@@ -1119,25 +1134,25 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
Namespace: Namespace{Name: "marc"},
User: User{Name: "marc"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
Namespace: Namespace{Name: "mickael"},
User: User{Name: "mickael"},
},
},
aclPolicy: ACLPolicy{
@@ -1160,27 +1175,27 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
ForcedTags: []string{"tag:hr-webserver"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
ForcedTags: []string{"tag:hr-webserver"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
Namespace: Namespace{Name: "marc"},
User: User{Name: "marc"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
Namespace: Namespace{Name: "mickael"},
User: User{Name: "mickael"},
},
},
aclPolicy: ACLPolicy{},
@@ -1198,14 +1213,14 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
ForcedTags: []string{"tag:hr-webserver"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1216,13 +1231,13 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
Namespace: Namespace{Name: "marc"},
User: User{Name: "marc"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
Namespace: Namespace{Name: "mickael"},
User: User{Name: "mickael"},
},
},
aclPolicy: ACLPolicy{
@@ -1236,7 +1251,7 @@ func Test_expandAlias(t *testing.T) {
wantErr: false,
},
{
name: "list host in namespace without correctly tagged servers",
name: "list host in user without correctly tagged servers",
args: args{
alias: "joe",
machines: []Machine{
@@ -1244,7 +1259,7 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1255,7 +1270,7 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1266,13 +1281,13 @@ func Test_expandAlias(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.3"),
},
Namespace: Namespace{Name: "marc"},
User: User{Name: "marc"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
},
aclPolicy: ACLPolicy{
@@ -1308,7 +1323,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
type args struct {
aclPolicy ACLPolicy
nodes []Machine
namespace string
user string
stripEmailDomain bool
}
tests := []struct {
@@ -1328,7 +1343,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1339,7 +1354,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1350,16 +1365,16 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
},
namespace: "joe",
user: "joe",
stripEmailDomain: true,
},
want: []Machine{
{
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.4")},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
},
},
@@ -1379,7 +1394,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1390,7 +1405,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1401,16 +1416,16 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
},
namespace: "joe",
user: "joe",
stripEmailDomain: true,
},
want: []Machine{
{
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.4")},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
},
},
@@ -1425,7 +1440,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "foo",
@@ -1436,23 +1451,23 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
ForcedTags: []string{"tag:accountant-webserver"},
},
{
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
},
namespace: "joe",
user: "joe",
stripEmailDomain: true,
},
want: []Machine{
{
IPAddresses: MachineAddresses{netip.MustParseAddr("100.64.0.4")},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
},
},
@@ -1467,7 +1482,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "hr-web1",
@@ -1478,7 +1493,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "hr-web2",
@@ -1489,10 +1504,10 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
},
namespace: "joe",
user: "joe",
stripEmailDomain: true,
},
want: []Machine{
@@ -1500,7 +1515,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.1"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "hr-web1",
@@ -1511,7 +1526,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.2"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
HostInfo: HostInfo{
OS: "centos",
Hostname: "hr-web2",
@@ -1522,7 +1537,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
IPAddresses: MachineAddresses{
netip.MustParseAddr("100.64.0.4"),
},
Namespace: Namespace{Name: "joe"},
User: User{Name: "joe"},
},
},
},
@@ -1532,7 +1547,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) {
got := excludeCorrectlyTaggedNodes(
test.args.aclPolicy,
test.args.nodes,
test.args.namespace,
test.args.user,
test.args.stripEmailDomain,
)
if !reflect.DeepEqual(got, test.want) {
+3 -3
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 (namespaces?) are allow to use certain tags.
// TagOwners specify what users (users?) 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 (namespaces?), groups or tags have their advertised routes
// AutoApprovers specify which users (users?), 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 namespaces, groups or tags for a given IPPrefix.
// Returns the list of autoApproving users, groups or tags for a given IPPrefix.
func (autoApprovers *AutoApprovers) GetRouteApprovers(
prefix netip.Prefix,
) ([]string, error) {
+1 -1
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 -n NAMESPACE nodes register --key {{.Key}}</code></pre>
<pre><code>headscale nodes register --user USERNAME --key {{.Key}}</code></pre>
</body>
</html>
`))
+39 -7
View File
@@ -1,6 +1,8 @@
package headscale
import (
"time"
"github.com/rs/zerolog/log"
"tailscale.com/tailcfg"
)
@@ -55,16 +57,46 @@ func (h *Headscale) generateMapResponse(
peers,
)
now := time.Now()
resp := tailcfg.MapResponse{
KeepAlive: false,
Node: node,
Peers: nodePeers,
DNSConfig: dnsConfig,
Domain: h.cfg.BaseDomain,
KeepAlive: false,
Node: node,
// TODO: Only send if updated
DERPMap: h.DERPMap,
// TODO: Only send if updated
Peers: nodePeers,
// TODO(kradalby): Implement:
// https://github.com/tailscale/tailscale/blob/main/tailcfg/tailcfg.go#L1351-L1374
// PeersChanged
// PeersRemoved
// PeersChangedPatch
// PeerSeenChange
// OnlineChange
// TODO: Only send if updated
DNSConfig: dnsConfig,
// TODO: Only send if updated
Domain: h.cfg.BaseDomain,
// Do not instruct clients to collect services, we do not
// support or do anything with them
CollectServices: "false",
// TODO: Only send if updated
PacketFilter: h.aclRules,
SSHPolicy: h.sshPolicy,
DERPMap: h.DERPMap,
UserProfiles: profiles,
// TODO: Only send if updated
SSHPolicy: h.sshPolicy,
ControlTime: &now,
Debug: &tailcfg.Debug{
DisableLogTail: !h.cfg.LogTail.Enabled,
RandomizeClientPort: h.cfg.RandomizeClientPort,
+2 -2
View File
@@ -29,7 +29,7 @@ type APIKey struct {
LastSeen *time.Time
}
// CreateAPIKey creates a new ApiKey in a namespace, and returns it.
// CreateAPIKey creates a new ApiKey in a user, 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 namespace.
// ListAPIKeys returns the list of ApiKeys for a user.
func (h *Headscale) ListAPIKeys() ([]APIKey, error) {
keys := []APIKey{}
if err := h.db.Find(&keys).Error; err != nil {
+32 -29
View File
@@ -84,9 +84,11 @@ type Headscale struct {
DERPMap *tailcfg.DERPMap
DERPServer *DERPServer
aclPolicy *ACLPolicy
aclRules []tailcfg.FilterRule
sshPolicy *tailcfg.SSHPolicy
aclPolicy *ACLPolicy
aclRules []tailcfg.FilterRule
aclPeerCacheMapRW sync.RWMutex
aclPeerCacheMap map[string]map[string]struct{}
sshPolicy *tailcfg.SSHPolicy
lastStateChange *xsync.MapOf[string, time.Time]
@@ -238,20 +240,20 @@ func (h *Headscale) failoverSubnetRoutes(milliSeconds int64) {
}
func (h *Headscale) expireEphemeralNodesWorker() {
namespaces, err := h.ListNamespaces()
users, err := h.ListUsers()
if err != nil {
log.Error().Err(err).Msg("Error listing namespaces")
log.Error().Err(err).Msg("Error listing users")
return
}
for _, namespace := range namespaces {
machines, err := h.ListMachinesInNamespace(namespace.Name)
for _, user := range users {
machines, err := h.ListMachinesByUser(user.Name)
if err != nil {
log.Error().
Err(err).
Str("namespace", namespace.Name).
Msg("Error listing machines in namespace")
Str("user", user.Name).
Msg("Error listing machines in user")
return
}
@@ -283,20 +285,20 @@ func (h *Headscale) expireEphemeralNodesWorker() {
}
func (h *Headscale) expireExpiredMachinesWorker() {
namespaces, err := h.ListNamespaces()
users, err := h.ListUsers()
if err != nil {
log.Error().Err(err).Msg("Error listing namespaces")
log.Error().Err(err).Msg("Error listing users")
return
}
for _, namespace := range namespaces {
machines, err := h.ListMachinesInNamespace(namespace.Name)
for _, user := range users {
machines, err := h.ListMachinesByUser(user.Name)
if err != nil {
log.Error().
Err(err).
Str("namespace", namespace.Name).
Msg("Error listing machines in namespace")
Str("user", user.Name).
Msg("Error listing machines in user")
return
}
@@ -304,7 +306,7 @@ func (h *Headscale) expireExpiredMachinesWorker() {
expiredFound := false
for index, machine := range machines {
if machine.isExpired() &&
machine.Expiry.After(h.getLastStateChange(namespace)) {
machine.Expiry.After(h.getLastStateChange(user)) {
expiredFound = true
err := h.ExpireMachine(&machines[index])
@@ -521,7 +523,7 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *mux.Router {
apiRouter.Use(h.httpAuthenticationMiddleware)
apiRouter.PathPrefix("/v1/").HandlerFunc(grpcMux.ServeHTTP)
router.PathPrefix("/").HandlerFunc(stdoutHandler)
router.PathPrefix("/").HandlerFunc(notFoundHandler)
return router
}
@@ -908,31 +910,31 @@ func (h *Headscale) setLastStateChangeToNow() {
now := time.Now().UTC()
namespaces, err := h.ListNamespaces()
users, err := h.ListUsers()
if err != nil {
log.Error().
Caller().
Err(err).
Msg("failed to fetch all namespaces, failing to update last changed state.")
Msg("failed to fetch all users, failing to update last changed state.")
}
for _, namespace := range namespaces {
lastStateUpdate.WithLabelValues(namespace.Name, "headscale").Set(float64(now.Unix()))
for _, user := range users {
lastStateUpdate.WithLabelValues(user.Name, "headscale").Set(float64(now.Unix()))
if h.lastStateChange == nil {
h.lastStateChange = xsync.NewMapOf[time.Time]()
}
h.lastStateChange.Store(namespace.Name, now)
h.lastStateChange.Store(user.Name, now)
}
}
func (h *Headscale) getLastStateChange(namespaces ...Namespace) time.Time {
func (h *Headscale) getLastStateChange(users ...User) time.Time {
times := []time.Time{}
// 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 {
// 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 {
times = append(times, lastChange)
}
}
@@ -957,7 +959,7 @@ func (h *Headscale) getLastStateChange(namespaces ...Namespace) time.Time {
}
}
func stdoutHandler(
func notFoundHandler(
writer http.ResponseWriter,
req *http.Request,
) {
@@ -969,6 +971,7 @@ func stdoutHandler(
Interface("url", req.URL).
Bytes("body", body).
Msg("Request did not match")
writer.WriteHeader(http.StatusNotFound)
}
func readOrCreatePrivateKey(path string) (*key.MachinePrivate, error) {
+81 -32
View File
@@ -7,19 +7,29 @@ import (
"fmt"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
"text/template"
)
var (
githubWorkflowPath = "../../.github/workflows/"
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
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]
concurrency:
group: {{ "${{ github.workflow }}-$${{ github.head_ref || github.run_id }}" }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -40,8 +50,8 @@ jobs:
integration_test/
config-example.yaml
- uses: cachix/install-nix-action@v16
if: steps.changed-files.outputs.any_changed == 'true'
- uses: cachix/install-nix-action@v18
if: {{ "${{ env.ACT }}" }} || steps.changed-files.outputs.any_changed == 'true'
- name: Run general integration tests
if: steps.changed-files.outputs.any_changed == 'true'
@@ -52,6 +62,7 @@ jobs:
--name headscale-test-suite \
--volume $PWD:$PWD -w $PWD/integration \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume $PWD/control_logs:/tmp/control \
golang:1 \
go test ./... \
-tags ts2019 \
@@ -59,43 +70,81 @@ jobs:
-timeout 120m \
-parallel 1 \
-run "^{{.Name}}$"
`))
- uses: actions/upload-artifact@v3
if: always() && steps.changed-files.outputs.any_changed == 'true'
with:
name: logs
path: "control_logs/*.log"
`),
)
)
const workflowFilePerm = 0o600
func removeTests() {
glob := fmt.Sprintf(jobFileNameTemplate, "*")
files, err := filepath.Glob(filepath.Join(githubWorkflowPath, glob))
if err != nil {
log.Fatalf("failed to find test files")
}
for _, file := range files {
err := os.Remove(file)
if err != nil {
log.Printf("failed to remove: %s", err)
}
}
}
func findTests() []string {
rgBin, err := exec.LookPath("rg")
if err != nil {
log.Fatalf("failed to find rg (ripgrep) binary")
}
args := []string{
"--regexp", "func (Test.+)\\(.*",
"../../integration/",
"--replace", "$1",
"--sort", "path",
"--no-line-number",
"--no-filename",
"--no-heading",
}
log.Printf("executing: %s %s", rgBin, strings.Join(args, " "))
ripgrep := exec.Command(
rgBin,
args...,
)
result, err := ripgrep.CombinedOutput()
if err != nil {
log.Printf("out: %s", result)
log.Fatalf("failed to run ripgrep: %s", err)
}
tests := strings.Split(string(result), "\n")
tests = tests[:len(tests)-1]
return tests
}
func main() {
type testConfig struct {
Name string
}
// TODO(kradalby): automatic fetch tests at runtime
tests := []string{
"TestAuthKeyLogoutAndRelogin",
"TestAuthWebFlowAuthenticationPingAll",
"TestAuthWebFlowLogoutAndRelogin",
"TestCreateTailscale",
"TestEnablingRoutes",
"TestHeadscale",
"TestNamespaceCommand",
"TestOIDCAuthenticationPingAll",
"TestOIDCExpireNodes",
"TestPingAllByHostname",
"TestPingAllByIP",
"TestPreAuthKeyCommand",
"TestPreAuthKeyCommandReusableEphemeral",
"TestPreAuthKeyCommandWithoutExpiry",
"TestResolveMagicDNS",
"TestSSHIsBlockedInACL",
"TestSSHMultipleNamespacesAllToAll",
"TestSSHNoSSHConfigured",
"TestSSHOneNamespaceAllToAll",
"TestSSNamespaceOnlyIsolation",
"TestTaildrop",
"TestTailscaleNodesJoiningHeadcale",
}
tests := findTests()
removeTests()
for _, test := range tests {
log.Printf("generating workflow for %s", test)
var content bytes.Buffer
if err := jobTemplate.Execute(&content, testConfig{
@@ -104,9 +153,9 @@ func main() {
log.Fatalf("failed to render template: %s", err)
}
path := "../../.github/workflows/" + fmt.Sprintf(jobFileNameTemplate, test)
testPath := path.Join(githubWorkflowPath, fmt.Sprintf(jobFileNameTemplate, test))
err := os.WriteFile(path, content.Bytes(), workflowFilePerm)
err := os.WriteFile(testPath, content.Bytes(), workflowFilePerm)
if err != nil {
log.Fatalf("failed to write github job: %s", err)
}
+22
View File
@@ -0,0 +1,22 @@
package cli
import (
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(configTestCmd)
}
var configTestCmd = &cobra.Command{
Use: "configtest",
Short: "Test the configuration.",
Long: "Run a test of the configuration and exit.",
Run: func(cmd *cobra.Command, args []string) {
_, err := getHeadscaleApp()
if err != nil {
log.Fatal().Caller().Err(err).Msg("Error initializing")
}
},
}
+14 -8
View File
@@ -27,8 +27,14 @@ func init() {
if err != nil {
log.Fatal().Err(err).Msg("")
}
createNodeCmd.Flags().StringP("namespace", "n", "", "Namespace")
err = createNodeCmd.MarkFlagRequired("namespace")
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")
if err != nil {
log.Fatal().Err(err).Msg("")
}
@@ -55,9 +61,9 @@ var createNodeCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
namespace, err := cmd.Flags().GetString("namespace")
user, err := cmd.Flags().GetString("user")
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error getting namespace: %s", err), output)
ErrorOutput(err, fmt.Sprintf("Error getting user: %s", err), output)
return
}
@@ -110,10 +116,10 @@ var createNodeCmd = &cobra.Command{
}
request := &v1.DebugCreateMachineRequest{
Key: machineKey,
Name: name,
Namespace: namespace,
Routes: routes,
Key: machineKey,
Name: name,
User: user,
Routes: routes,
}
response, err := client.DebugCreateMachine(ctx, request)
+43 -26
View File
@@ -19,12 +19,24 @@ import (
func init() {
rootCmd.AddCommand(nodeCmd)
listNodesCmd.Flags().StringP("namespace", "n", "", "Filter by namespace")
listNodesCmd.Flags().StringP("user", "u", "", "Filter by user")
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("namespace", "n", "", "Namespace")
err := registerNodeCmd.MarkFlagRequired("namespace")
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")
if err != nil {
log.Fatalf(err.Error())
}
@@ -63,9 +75,14 @@ func init() {
log.Fatalf(err.Error())
}
moveNodeCmd.Flags().StringP("namespace", "n", "", "New namespace")
moveNodeCmd.Flags().StringP("user", "u", "", "New user")
err = moveNodeCmd.MarkFlagRequired("namespace")
moveNodeCmd.Flags().StringP("namespace", "n", "", "User")
moveNodeNamespaceFlag := moveNodeCmd.Flags().Lookup("namespace")
moveNodeNamespaceFlag.Deprecated = deprecateNamespaceMessage
moveNodeNamespaceFlag.Hidden = true
err = moveNodeCmd.MarkFlagRequired("user")
if err != nil {
log.Fatalf(err.Error())
}
@@ -93,9 +110,9 @@ var registerNodeCmd = &cobra.Command{
Short: "Registers a machine to your network",
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
namespace, err := cmd.Flags().GetString("namespace")
user, err := cmd.Flags().GetString("user")
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error getting namespace: %s", err), output)
ErrorOutput(err, fmt.Sprintf("Error getting user: %s", err), output)
return
}
@@ -116,8 +133,8 @@ var registerNodeCmd = &cobra.Command{
}
request := &v1.RegisterMachineRequest{
Key: machineKey,
Namespace: namespace,
Key: machineKey,
User: user,
}
response, err := client.RegisterMachine(ctx, request)
@@ -146,9 +163,9 @@ var listNodesCmd = &cobra.Command{
Aliases: []string{"ls", "show"},
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
namespace, err := cmd.Flags().GetString("namespace")
user, err := cmd.Flags().GetString("user")
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error getting namespace: %s", err), output)
ErrorOutput(err, fmt.Sprintf("Error getting user: %s", err), output)
return
}
@@ -164,7 +181,7 @@ var listNodesCmd = &cobra.Command{
defer conn.Close()
request := &v1.ListMachinesRequest{
Namespace: namespace,
User: user,
}
response, err := client.ListMachines(ctx, request)
@@ -184,7 +201,7 @@ var listNodesCmd = &cobra.Command{
return
}
tableData, err := nodesToPtables(namespace, showTags, response.Machines)
tableData, err := nodesToPtables(user, showTags, response.Machines)
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error converting to table: %s", err), output)
@@ -388,7 +405,7 @@ var deleteNodeCmd = &cobra.Command{
var moveNodeCmd = &cobra.Command{
Use: "move",
Short: "Move node to another namespace",
Short: "Move node to another user",
Aliases: []string{"mv"},
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
@@ -404,11 +421,11 @@ var moveNodeCmd = &cobra.Command{
return
}
namespace, err := cmd.Flags().GetString("namespace")
user, err := cmd.Flags().GetString("user")
if err != nil {
ErrorOutput(
err,
fmt.Sprintf("Error getting namespace: %s", err),
fmt.Sprintf("Error getting user: %s", err),
output,
)
@@ -439,7 +456,7 @@ var moveNodeCmd = &cobra.Command{
moveRequest := &v1.MoveMachineRequest{
MachineId: identifier,
Namespace: namespace,
User: user,
}
moveResponse, err := client.MoveMachine(ctx, moveRequest)
@@ -456,12 +473,12 @@ var moveNodeCmd = &cobra.Command{
return
}
SuccessOutput(moveResponse.Machine, "Node moved to another namespace", output)
SuccessOutput(moveResponse.Machine, "Node moved to another user", output)
},
}
func nodesToPtables(
currentNamespace string,
currentUser string,
showTags bool,
machines []*v1.Machine,
) (pterm.TableData, error) {
@@ -471,7 +488,7 @@ func nodesToPtables(
"Name",
"MachineKey",
"NodeKey",
"Namespace",
"User",
"IP addresses",
"Ephemeral",
"Last seen",
@@ -560,12 +577,12 @@ func nodesToPtables(
}
validTags = strings.TrimLeft(validTags, ",")
var namespace string
if currentNamespace == "" || (currentNamespace == machine.Namespace.Name) {
namespace = pterm.LightMagenta(machine.Namespace.Name)
var user string
if currentUser == "" || (currentUser == machine.User.Name) {
user = pterm.LightMagenta(machine.User.Name)
} else {
// Shared into this namespace
namespace = pterm.LightYellow(machine.Namespace.Name)
// Shared into this user
user = pterm.LightYellow(machine.User.Name)
}
var IPV4Address string
@@ -584,7 +601,7 @@ func nodesToPtables(
machine.GetGivenName(),
machineKey.ShortString(),
nodeKey.ShortString(),
namespace,
user,
strings.Join([]string{IPV4Address, IPV6Address}, ", "),
strconv.FormatBool(ephemeral),
lastSeenTime,
+21 -15
View File
@@ -20,8 +20,14 @@ const (
func init() {
rootCmd.AddCommand(preauthkeysCmd)
preauthkeysCmd.PersistentFlags().StringP("namespace", "n", "", "Namespace")
err := preauthkeysCmd.MarkPersistentFlagRequired("namespace")
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")
if err != nil {
log.Fatal().Err(err).Msg("")
}
@@ -46,14 +52,14 @@ var preauthkeysCmd = &cobra.Command{
var listPreAuthKeys = &cobra.Command{
Use: "list",
Short: "List the preauthkeys for this namespace",
Short: "List the preauthkeys for this user",
Aliases: []string{"ls", "show"},
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
namespace, err := cmd.Flags().GetString("namespace")
user, err := cmd.Flags().GetString("user")
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error getting namespace: %s", err), output)
ErrorOutput(err, fmt.Sprintf("Error getting user: %s", err), output)
return
}
@@ -63,7 +69,7 @@ var listPreAuthKeys = &cobra.Command{
defer conn.Close()
request := &v1.ListPreAuthKeysRequest{
Namespace: namespace,
User: user,
}
response, err := client.ListPreAuthKeys(ctx, request)
@@ -143,14 +149,14 @@ var listPreAuthKeys = &cobra.Command{
var createPreAuthKeyCmd = &cobra.Command{
Use: "create",
Short: "Creates a new preauthkey in the specified namespace",
Short: "Creates a new preauthkey in the specified user",
Aliases: []string{"c", "new"},
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
namespace, err := cmd.Flags().GetString("namespace")
user, err := cmd.Flags().GetString("user")
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error getting namespace: %s", err), output)
ErrorOutput(err, fmt.Sprintf("Error getting user: %s", err), output)
return
}
@@ -162,11 +168,11 @@ var createPreAuthKeyCmd = &cobra.Command{
log.Trace().
Bool("reusable", reusable).
Bool("ephemeral", ephemeral).
Str("namespace", namespace).
Str("user", user).
Msg("Preparing to create preauthkey")
request := &v1.CreatePreAuthKeyRequest{
Namespace: namespace,
User: user,
Reusable: reusable,
Ephemeral: ephemeral,
AclTags: tags,
@@ -225,9 +231,9 @@ var expirePreAuthKeyCmd = &cobra.Command{
},
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
namespace, err := cmd.Flags().GetString("namespace")
user, err := cmd.Flags().GetString("user")
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error getting namespace: %s", err), output)
ErrorOutput(err, fmt.Sprintf("Error getting user: %s", err), output)
return
}
@@ -237,8 +243,8 @@ var expirePreAuthKeyCmd = &cobra.Command{
defer conn.Close()
request := &v1.ExpirePreAuthKeyRequest{
Namespace: namespace,
Key: args[0],
User: user,
Key: args[0],
}
response, err := client.ExpirePreAuthKey(ctx, request)
+6 -1
View File
@@ -12,10 +12,15 @@ 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
}
+67 -2
View File
@@ -3,8 +3,10 @@ package cli
import (
"fmt"
"log"
"net/netip"
"strconv"
"github.com/juanfont/headscale"
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
"github.com/pterm/pterm"
"github.com/spf13/cobra"
@@ -33,6 +35,13 @@ func init() {
log.Fatalf(err.Error())
}
routesCmd.AddCommand(disableRouteCmd)
deleteRouteCmd.Flags().Uint64P("route", "r", 0, "Route identifier (ID)")
err = deleteRouteCmd.MarkFlagRequired("route")
if err != nil {
log.Fatalf(err.Error())
}
routesCmd.AddCommand(deleteRouteCmd)
}
var routesCmd = &cobra.Command{
@@ -198,7 +207,50 @@ var disableRouteCmd = &cobra.Command{
if err != nil {
ErrorOutput(
err,
fmt.Sprintf("Cannot enable route %d: %s", routeID, status.Convert(err).Message()),
fmt.Sprintf("Cannot disable route %d: %s", routeID, status.Convert(err).Message()),
output,
)
return
}
if output != "" {
SuccessOutput(response, "", output)
return
}
},
}
var deleteRouteCmd = &cobra.Command{
Use: "delete",
Short: "Delete a given route",
Long: `This command will delete a given route.`,
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
routeID, err := cmd.Flags().GetUint64("route")
if err != nil {
ErrorOutput(
err,
fmt.Sprintf("Error getting machine id from flag: %s", err),
output,
)
return
}
ctx, client, conn, cancel := getHeadscaleCLIClient()
defer cancel()
defer conn.Close()
response, err := client.DeleteRoute(ctx, &v1.DeleteRouteRequest{
RouteId: routeID,
})
if err != nil {
ErrorOutput(
err,
fmt.Sprintf("Cannot delete route %d: %s", routeID, status.Convert(err).Message()),
output,
)
@@ -218,6 +270,19 @@ func routesToPtables(routes []*v1.Route) pterm.TableData {
tableData := pterm.TableData{{"ID", "Machine", "Prefix", "Advertised", "Enabled", "Primary"}}
for _, route := range routes {
var isPrimaryStr string
prefix, err := netip.ParsePrefix(route.Prefix)
if err != nil {
log.Printf("Error parsing prefix %s: %s", route.Prefix, err)
continue
}
if prefix == headscale.ExitRouteV4 || prefix == headscale.ExitRouteV6 {
isPrimaryStr = "-"
} else {
isPrimaryStr = strconv.FormatBool(route.IsPrimary)
}
tableData = append(tableData,
[]string{
strconv.FormatUint(route.Id, Base10),
@@ -225,7 +290,7 @@ func routesToPtables(routes []*v1.Route) pterm.TableData {
route.Prefix,
strconv.FormatBool(route.Advertised),
strconv.FormatBool(route.Enabled),
strconv.FormatBool(route.IsPrimary),
isPrimaryStr,
})
}
@@ -13,26 +13,26 @@ import (
)
func init() {
rootCmd.AddCommand(namespaceCmd)
namespaceCmd.AddCommand(createNamespaceCmd)
namespaceCmd.AddCommand(listNamespacesCmd)
namespaceCmd.AddCommand(destroyNamespaceCmd)
namespaceCmd.AddCommand(renameNamespaceCmd)
rootCmd.AddCommand(userCmd)
userCmd.AddCommand(createUserCmd)
userCmd.AddCommand(listUsersCmd)
userCmd.AddCommand(destroyUserCmd)
userCmd.AddCommand(renameUserCmd)
}
const (
errMissingParameter = headscale.Error("missing parameters")
)
var namespaceCmd = &cobra.Command{
Use: "namespaces",
Short: "Manage the namespaces of Headscale",
Aliases: []string{"namespace", "ns", "user", "users"},
var userCmd = &cobra.Command{
Use: "users",
Short: "Manage the users of Headscale",
Aliases: []string{"user", "namespace", "namespaces", "ns"},
}
var createNamespaceCmd = &cobra.Command{
var createUserCmd = &cobra.Command{
Use: "create NAME",
Short: "Creates a new namespace",
Short: "Creates a new user",
Aliases: []string{"c", "new"},
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
@@ -44,7 +44,7 @@ var createNamespaceCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
namespaceName := args[0]
userName := args[0]
ctx, client, conn, cancel := getHeadscaleCLIClient()
defer cancel()
@@ -52,15 +52,15 @@ var createNamespaceCmd = &cobra.Command{
log.Trace().Interface("client", client).Msg("Obtained gRPC client")
request := &v1.CreateNamespaceRequest{Name: namespaceName}
request := &v1.CreateUserRequest{Name: userName}
log.Trace().Interface("request", request).Msg("Sending CreateNamespace request")
response, err := client.CreateNamespace(ctx, request)
log.Trace().Interface("request", request).Msg("Sending CreateUser request")
response, err := client.CreateUser(ctx, request)
if err != nil {
ErrorOutput(
err,
fmt.Sprintf(
"Cannot create namespace: %s",
"Cannot create user: %s",
status.Convert(err).Message(),
),
output,
@@ -69,13 +69,13 @@ var createNamespaceCmd = &cobra.Command{
return
}
SuccessOutput(response.Namespace, "Namespace created", output)
SuccessOutput(response.User, "User created", output)
},
}
var destroyNamespaceCmd = &cobra.Command{
var destroyUserCmd = &cobra.Command{
Use: "destroy NAME",
Short: "Destroys a namespace",
Short: "Destroys a user",
Aliases: []string{"delete"},
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
@@ -87,17 +87,17 @@ var destroyNamespaceCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
namespaceName := args[0]
userName := args[0]
request := &v1.GetNamespaceRequest{
Name: namespaceName,
request := &v1.GetUserRequest{
Name: userName,
}
ctx, client, conn, cancel := getHeadscaleCLIClient()
defer cancel()
defer conn.Close()
_, err := client.GetNamespace(ctx, request)
_, err := client.GetUser(ctx, request)
if err != nil {
ErrorOutput(
err,
@@ -113,8 +113,8 @@ var destroyNamespaceCmd = &cobra.Command{
if !force {
prompt := &survey.Confirm{
Message: fmt.Sprintf(
"Do you want to remove the namespace '%s' and any associated preauthkeys?",
namespaceName,
"Do you want to remove the user '%s' and any associated preauthkeys?",
userName,
),
}
err := survey.AskOne(prompt, &confirm)
@@ -124,14 +124,14 @@ var destroyNamespaceCmd = &cobra.Command{
}
if confirm || force {
request := &v1.DeleteNamespaceRequest{Name: namespaceName}
request := &v1.DeleteUserRequest{Name: userName}
response, err := client.DeleteNamespace(ctx, request)
response, err := client.DeleteUser(ctx, request)
if err != nil {
ErrorOutput(
err,
fmt.Sprintf(
"Cannot destroy namespace: %s",
"Cannot destroy user: %s",
status.Convert(err).Message(),
),
output,
@@ -139,16 +139,16 @@ var destroyNamespaceCmd = &cobra.Command{
return
}
SuccessOutput(response, "Namespace destroyed", output)
SuccessOutput(response, "User destroyed", output)
} else {
SuccessOutput(map[string]string{"Result": "Namespace not destroyed"}, "Namespace not destroyed", output)
SuccessOutput(map[string]string{"Result": "User not destroyed"}, "User not destroyed", output)
}
},
}
var listNamespacesCmd = &cobra.Command{
var listUsersCmd = &cobra.Command{
Use: "list",
Short: "List all the namespaces",
Short: "List all the users",
Aliases: []string{"ls", "show"},
Run: func(cmd *cobra.Command, args []string) {
output, _ := cmd.Flags().GetString("output")
@@ -157,13 +157,13 @@ var listNamespacesCmd = &cobra.Command{
defer cancel()
defer conn.Close()
request := &v1.ListNamespacesRequest{}
request := &v1.ListUsersRequest{}
response, err := client.ListNamespaces(ctx, request)
response, err := client.ListUsers(ctx, request)
if err != nil {
ErrorOutput(
err,
fmt.Sprintf("Cannot get namespaces: %s", status.Convert(err).Message()),
fmt.Sprintf("Cannot get users: %s", status.Convert(err).Message()),
output,
)
@@ -171,19 +171,19 @@ var listNamespacesCmd = &cobra.Command{
}
if output != "" {
SuccessOutput(response.Namespaces, "", output)
SuccessOutput(response.Users, "", output)
return
}
tableData := pterm.TableData{{"ID", "Name", "Created"}}
for _, namespace := range response.GetNamespaces() {
for _, user := range response.GetUsers() {
tableData = append(
tableData,
[]string{
namespace.GetId(),
namespace.GetName(),
namespace.GetCreatedAt().AsTime().Format("2006-01-02 15:04:05"),
user.GetId(),
user.GetName(),
user.GetCreatedAt().AsTime().Format("2006-01-02 15:04:05"),
},
)
}
@@ -200,9 +200,9 @@ var listNamespacesCmd = &cobra.Command{
},
}
var renameNamespaceCmd = &cobra.Command{
var renameUserCmd = &cobra.Command{
Use: "rename OLD_NAME NEW_NAME",
Short: "Renames a namespace",
Short: "Renames a user",
Aliases: []string{"mv"},
Args: func(cmd *cobra.Command, args []string) error {
expectedArguments := 2
@@ -219,17 +219,17 @@ var renameNamespaceCmd = &cobra.Command{
defer cancel()
defer conn.Close()
request := &v1.RenameNamespaceRequest{
request := &v1.RenameUserRequest{
OldName: args[0],
NewName: args[1],
}
response, err := client.RenameNamespace(ctx, request)
response, err := client.RenameUser(ctx, request)
if err != nil {
ErrorOutput(
err,
fmt.Sprintf(
"Cannot rename namespace: %s",
"Cannot rename user: %s",
status.Convert(err).Message(),
),
output,
@@ -238,6 +238,6 @@ var renameNamespaceCmd = &cobra.Command{
return
}
SuccessOutput(response.Namespace, "Namespace renamed", output)
SuccessOutput(response.User, "User renamed", output)
},
}
+21 -10
View File
@@ -258,7 +258,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.namespace.base_domain` (e.g., _myhost.mynamespace.example.com_).
# `hostname.user.base_domain` (e.g., _myhost.myuser.example.com_).
base_domain: example.com
# Unix socket used for the CLI to connect without authentication
@@ -282,28 +282,39 @@ unix_socket_permission: "0770"
# 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".
# # The amount of time from a node is authenticated with OpenID until it
# # expires and needs to reauthenticate.
# # Setting the value to "0" will mean no expiry.
# expiry: 180d
#
# # Use the expiry from the token received from OpenID when the user logged
# # in, this will typically lead to frequent need to reauthenticate and should
# # only been enabled if you know what you are doing.
# # Note: enabling this will cause `oidc.expiry` to be ignored.
# use_expiry_from_token: false
#
# # 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"]
# extra_params:
# domain_hint: example.com
#
# List allowed principal domains and/or users. If an authenticated user's domain is not in this list, the
# authentication request will be rejected.
# # 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
# Groups from keycloak have a leading '/'
# # Note: Groups from keycloak have a leading '/'
# allowed_groups:
# - /headscale
# 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 namespace `first-name.last-name`
# If `strip_email_domain` is set to `false` the domain part will NOT be removed resulting to the following
# namespace: `first-name.last-name.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
+49 -25
View File
@@ -11,6 +11,7 @@ import (
"time"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/prometheus/common/model"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/viper"
@@ -25,9 +26,14 @@ const (
JSONLogFormat = "json"
TextLogFormat = "text"
defaultOIDCExpiryTime = 180 * 24 * time.Hour // 180 Days
maxDuration time.Duration = 1<<63 - 1
)
var errOidcMutuallyExclusive = errors.New("oidc_client_secret and oidc_client_secret_path are mutually exclusive")
var errOidcMutuallyExclusive = errors.New(
"oidc_client_secret and oidc_client_secret_path are mutually exclusive",
)
// Config contains the initial Headscale configuration.
type Config struct {
@@ -101,6 +107,8 @@ type OIDCConfig struct {
AllowedUsers []string
AllowedGroups []string
StripEmaildomain bool
Expiry time.Duration
UseExpiryFromToken bool
}
type DERPConfig struct {
@@ -180,6 +188,8 @@ func LoadConfig(path string, isFile bool) error {
viper.SetDefault("oidc.scope", []string{oidc.ScopeOpenID, "profile", "email"})
viper.SetDefault("oidc.strip_email_domain", true)
viper.SetDefault("oidc.only_start_if_oidc_is_available", true)
viper.SetDefault("oidc.expiry", "180d")
viper.SetDefault("oidc.use_expiry_from_token", false)
viper.SetDefault("logtail.enabled", false)
viper.SetDefault("randomize_client_port", false)
@@ -411,34 +421,32 @@ func GetDNSConfig() (*tailcfg.DNSConfig, string) {
}
if viper.IsSet("dns_config.restricted_nameservers") {
if len(dnsConfig.Resolvers) > 0 {
dnsConfig.Routes = make(map[string][]*dnstype.Resolver)
restrictedDNS := viper.GetStringMapStringSlice(
"dns_config.restricted_nameservers",
dnsConfig.Routes = make(map[string][]*dnstype.Resolver)
domains := []string{}
restrictedDNS := viper.GetStringMapStringSlice(
"dns_config.restricted_nameservers",
)
for domain, restrictedNameservers := range restrictedDNS {
restrictedResolvers := make(
[]*dnstype.Resolver,
len(restrictedNameservers),
)
for domain, restrictedNameservers := range restrictedDNS {
restrictedResolvers := make(
[]*dnstype.Resolver,
len(restrictedNameservers),
)
for index, nameserverStr := range restrictedNameservers {
nameserver, err := netip.ParseAddr(nameserverStr)
if err != nil {
log.Error().
Str("func", "getDNSConfig").
Err(err).
Msgf("Could not parse restricted nameserver IP: %s", nameserverStr)
}
restrictedResolvers[index] = &dnstype.Resolver{
Addr: nameserver.String(),
}
for index, nameserverStr := range restrictedNameservers {
nameserver, err := netip.ParseAddr(nameserverStr)
if err != nil {
log.Error().
Str("func", "getDNSConfig").
Err(err).
Msgf("Could not parse restricted nameserver IP: %s", nameserverStr)
}
restrictedResolvers[index] = &dnstype.Resolver{
Addr: nameserver.String(),
}
dnsConfig.Routes[domain] = restrictedResolvers
}
} else {
log.Warn().
Msg("Warning: dns_config.restricted_nameservers is set, but no nameservers are configured. Ignoring restricted_nameservers.")
dnsConfig.Routes[domain] = restrictedResolvers
domains = append(domains, domain)
}
dnsConfig.Domains = domains
}
if viper.IsSet("dns_config.domains") {
@@ -603,6 +611,22 @@ func GetHeadscaleConfig() (*Config, error) {
AllowedUsers: viper.GetStringSlice("oidc.allowed_users"),
AllowedGroups: viper.GetStringSlice("oidc.allowed_groups"),
StripEmaildomain: viper.GetBool("oidc.strip_email_domain"),
Expiry: func() time.Duration {
// if set to 0, we assume no expiry
if value := viper.GetString("oidc.expiry"); value == "0" {
return maxDuration
} else {
expiry, err := model.ParseDuration(value)
if err != nil {
log.Warn().Msg("failed to parse oidc.expiry, defaulting back to 180 days")
return defaultOIDCExpiryTime
}
return time.Duration(expiry)
}
}(),
UseExpiryFromToken: viper.GetBool("oidc.use_expiry_from_token"),
},
LogTail: logConfig,
+14 -6
View File
@@ -41,6 +41,16 @@ 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")
@@ -110,7 +120,10 @@ 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()).
@@ -184,11 +197,6 @@ 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
+2 -2
View File
@@ -157,14 +157,14 @@ func (h *Headscale) DERPHandler(
if !fastStart {
pubKey := h.privateKey.Public()
pubKeyStr := pubKey.UntypedHexString() //nolint
pubKeyStr, _ := pubKey.MarshalText() //nolint
fmt.Fprintf(conn, "HTTP/1.1 101 Switching Protocols\r\n"+
"Upgrade: DERP\r\n"+
"Connection: Upgrade\r\n"+
"Derp-Version: %v\r\n"+
"Derp-Public-Key: %s\r\n\r\n",
derp.ProtocolVersion,
pubKeyStr)
string(pubKeyStr))
}
h.DERPServer.tailscaleDERP.Accept(req.Context(), netConn, conn, netConn.RemoteAddr().String())
+7 -7
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 namespace - shared nodes should use their full FQDN
// Only inject the Search Domain of the current user - shared nodes should use their full FQDN
dnsConfig.Domains = append(
dnsConfig.Domains,
fmt.Sprintf(
"%s.%s",
machine.Namespace.Name,
machine.User.Name,
baseDomain,
),
)
namespaceSet := mapset.NewSet[Namespace]()
namespaceSet.Add(machine.Namespace)
userSet := mapset.NewSet[User]()
userSet.Add(machine.User)
for _, p := range peers {
namespaceSet.Add(p.Namespace)
userSet.Add(p.User)
}
for _, namespace := range namespaceSet.ToSlice() {
dnsRoute := fmt.Sprintf("%v.%v", namespace.Name, baseDomain)
for _, user := range userSet.ToSlice() {
dnsRoute := fmt.Sprintf("%v.%v", user.Name, baseDomain)
dnsConfig.Routes[dnsRoute] = nil
}
} else {
+41 -41
View File
@@ -112,17 +112,17 @@ func (s *Suite) TestMagicDNSRootDomainsIPv6SingleMultiple(c *check.C) {
}
func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
namespaceShared1, err := app.CreateNamespace("shared1")
userShared1, err := app.CreateUser("shared1")
c.Assert(err, check.IsNil)
namespaceShared2, err := app.CreateNamespace("shared2")
userShared2, err := app.CreateUser("shared2")
c.Assert(err, check.IsNil)
namespaceShared3, err := app.CreateNamespace("shared3")
userShared3, err := app.CreateUser("shared3")
c.Assert(err, check.IsNil)
preAuthKeyInShared1, err := app.CreatePreAuthKey(
namespaceShared1.Name,
userShared1.Name,
false,
false,
nil,
@@ -131,7 +131,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
c.Assert(err, check.IsNil)
preAuthKeyInShared2, err := app.CreatePreAuthKey(
namespaceShared2.Name,
userShared2.Name,
false,
false,
nil,
@@ -140,7 +140,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
c.Assert(err, check.IsNil)
preAuthKeyInShared3, err := app.CreatePreAuthKey(
namespaceShared3.Name,
userShared3.Name,
false,
false,
nil,
@@ -149,7 +149,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
c.Assert(err, check.IsNil)
PreAuthKey2InShared1, err := app.CreatePreAuthKey(
namespaceShared1.Name,
userShared1.Name,
false,
false,
nil,
@@ -157,7 +157,7 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) {
)
c.Assert(err, check.IsNil)
_, err = app.GetMachine(namespaceShared1.Name, "test_get_shared_nodes_1")
_, err = app.GetMachine(userShared1.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",
NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1,
UserID: userShared1.ID,
User: *userShared1,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.1")},
AuthKeyID: uint(preAuthKeyInShared1.ID),
}
app.db.Save(machineInShared1)
_, err = app.GetMachine(namespaceShared1.Name, machineInShared1.Hostname)
_, err = app.GetMachine(userShared1.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",
NamespaceID: namespaceShared2.ID,
Namespace: *namespaceShared2,
UserID: userShared2.ID,
User: *userShared2,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.2")},
AuthKeyID: uint(preAuthKeyInShared2.ID),
}
app.db.Save(machineInShared2)
_, err = app.GetMachine(namespaceShared2.Name, machineInShared2.Hostname)
_, err = app.GetMachine(userShared2.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",
NamespaceID: namespaceShared3.ID,
Namespace: *namespaceShared3,
UserID: userShared3.ID,
User: *userShared3,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.3")},
AuthKeyID: uint(preAuthKeyInShared3.ID),
}
app.db.Save(machineInShared3)
_, err = app.GetMachine(namespaceShared3.Name, machineInShared3.Hostname)
_, err = app.GetMachine(userShared3.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",
NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1,
UserID: userShared1.ID,
User: *userShared1,
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", namespaceShared1.Name, baseDomain)
domainRouteShared1 := fmt.Sprintf("%s.%s", userShared1.Name, baseDomain)
_, ok := dnsConfig.Routes[domainRouteShared1]
c.Assert(ok, check.Equals, true)
domainRouteShared2 := fmt.Sprintf("%s.%s", namespaceShared2.Name, baseDomain)
domainRouteShared2 := fmt.Sprintf("%s.%s", userShared2.Name, baseDomain)
_, ok = dnsConfig.Routes[domainRouteShared2]
c.Assert(ok, check.Equals, true)
domainRouteShared3 := fmt.Sprintf("%s.%s", namespaceShared3.Name, baseDomain)
domainRouteShared3 := fmt.Sprintf("%s.%s", userShared3.Name, baseDomain)
_, ok = dnsConfig.Routes[domainRouteShared3]
c.Assert(ok, check.Equals, true)
}
func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
namespaceShared1, err := app.CreateNamespace("shared1")
userShared1, err := app.CreateUser("shared1")
c.Assert(err, check.IsNil)
namespaceShared2, err := app.CreateNamespace("shared2")
userShared2, err := app.CreateUser("shared2")
c.Assert(err, check.IsNil)
namespaceShared3, err := app.CreateNamespace("shared3")
userShared3, err := app.CreateUser("shared3")
c.Assert(err, check.IsNil)
preAuthKeyInShared1, err := app.CreatePreAuthKey(
namespaceShared1.Name,
userShared1.Name,
false,
false,
nil,
@@ -278,7 +278,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
c.Assert(err, check.IsNil)
preAuthKeyInShared2, err := app.CreatePreAuthKey(
namespaceShared2.Name,
userShared2.Name,
false,
false,
nil,
@@ -287,7 +287,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
c.Assert(err, check.IsNil)
preAuthKeyInShared3, err := app.CreatePreAuthKey(
namespaceShared3.Name,
userShared3.Name,
false,
false,
nil,
@@ -296,7 +296,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
c.Assert(err, check.IsNil)
preAuthKey2InShared1, err := app.CreatePreAuthKey(
namespaceShared1.Name,
userShared1.Name,
false,
false,
nil,
@@ -304,7 +304,7 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) {
)
c.Assert(err, check.IsNil)
_, err = app.GetMachine(namespaceShared1.Name, "test_get_shared_nodes_1")
_, err = app.GetMachine(userShared1.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",
NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1,
UserID: userShared1.ID,
User: *userShared1,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.1")},
AuthKeyID: uint(preAuthKeyInShared1.ID),
}
app.db.Save(machineInShared1)
_, err = app.GetMachine(namespaceShared1.Name, machineInShared1.Hostname)
_, err = app.GetMachine(userShared1.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",
NamespaceID: namespaceShared2.ID,
Namespace: *namespaceShared2,
UserID: userShared2.ID,
User: *userShared2,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.2")},
AuthKeyID: uint(preAuthKeyInShared2.ID),
}
app.db.Save(machineInShared2)
_, err = app.GetMachine(namespaceShared2.Name, machineInShared2.Hostname)
_, err = app.GetMachine(userShared2.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",
NamespaceID: namespaceShared3.ID,
Namespace: *namespaceShared3,
UserID: userShared3.ID,
User: *userShared3,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.3")},
AuthKeyID: uint(preAuthKeyInShared3.ID),
}
app.db.Save(machineInShared3)
_, err = app.GetMachine(namespaceShared3.Name, machineInShared3.Hostname)
_, err = app.GetMachine(userShared3.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",
NamespaceID: namespaceShared1.ID,
Namespace: *namespaceShared1,
UserID: userShared1.ID,
User: *userShared1,
RegisterMethod: RegisterMethodAuthKey,
IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.4")},
AuthKeyID: uint(preAuthKey2InShared1.ID),
+3 -3
View File
@@ -39,12 +39,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 namespaces (which are the equivalent to user/logins in Tailscale.com).
use users (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 Namespace borders are no longer applied. All machines
whichever the Namespace have the ability to communicate with other hosts as
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
long as the ACL's permits this exchange.
The [ACLs](acls.md) document should help understand a fictional case of setting
+5 -5
View File
@@ -29,17 +29,17 @@ servers.
## ACL setup
Note: Namespaces will be created automatically when users authenticate with the
Note: Users 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 (namespace) that is
`--advertise-tags=tag:<tag1>,tag:<tag2>`, and the user 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 namespace that is
and only valid tags are applied. A tag is valid if the user 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 namespaces communications since nothing guarantees that each user have
// their own namespaces.
// We still have to allow internal users communications since nothing guarantees that each user have
// their own users.
{ "action": "accept", "src": ["boss"], "dst": ["boss:*"] },
{ "action": "accept", "src": ["dev1"], "dst": ["dev1:*"] },
{ "action": "accept", "src": ["dev2"], "dst": ["dev2:*"] },
+1 -1
View File
@@ -80,4 +80,4 @@ server {
## Limitations
[Not all types of records are supported](https://github.com/tailscale/tailscale/blob/main/ipn/ipnlocal/local.go#L2891-L2909), especially no CNAME records.
[Not all types of records are supported](https://github.com/tailscale/tailscale/blob/6edf357b96b28ee1be659a70232c0135b2ffedfd/ipn/ipnlocal/local.go#L2989-L3007), especially no CNAME records.
+47
View File
@@ -0,0 +1,47 @@
# Exit Nodes
## On the node
Register the node and make it advertise itself as an exit node:
```console
$ sudo tailscale up --login-server https://my-server.com --advertise-exit-node
```
If the node is already registered, it can advertise exit capabilities like this:
```console
$ sudo tailscale set --advertise-exit-node
```
## On the control server
```console
$ # list nodes
$ headscale routes list
ID | Machine | Prefix | Advertised | Enabled | Primary
1 | | 0.0.0.0/0 | false | false | -
2 | | ::/0 | false | false | -
3 | phobos | 0.0.0.0/0 | true | false | -
4 | phobos | ::/0 | true | false | -
$ # enable routes for phobos
$ headscale routes enable -r 3
$ headscale routes enable -r 4
$ # Check node list again. The routes are now enabled.
$ headscale routes list
ID | Machine | Prefix | Advertised | Enabled | Primary
1 | | 0.0.0.0/0 | false | false | -
2 | | ::/0 | false | false | -
3 | phobos | 0.0.0.0/0 | true | true | -
4 | phobos | ::/0 | true | true | -
```
## On the client
The exit node can now be used with:
```console
$ sudo tailscale set --exit-node phobos
```
Check the official [Tailscale documentation](https://tailscale.com/kb/1103/exit-nodes/?q=exit#step-3-use-the-exit-node) for how to do it on your device.
+4 -4
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 is a logical grouping of machines "owned" by the same entity, in Tailscale, this is typically a 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 was a logical grouping of machines "owned" by the same entity, in Tailscale, this is typically a User (This is now called user) |
+25
View File
@@ -0,0 +1,25 @@
# Connecting an iOS client
## Goal
This documentation has the goal of showing how a user can use the official iOS [Tailscale](https://tailscale.com) client with `headscale`.
## Installation
Install the official Tailscale iOS client from the [App Store](https://apps.apple.com/app/tailscale/id1470499037).
Ensure that the installed version is at least 1.38.1, as that is the first release to support alternate control servers.
## Configuring the headscale URL
Ensure that the tailscale app is logged out before proceeding.
Go to iOS settings, scroll down past game center and tv provider to the tailscale app and select it. The headscale URL can be entered into the _"ALTERNATE COORDINATION SERVER URL"_ box.
> **Note**
>
> If the app was previously logged into tailscale, toggle on the _Reset Keychain_ switch.
Restart the app by closing it from the iOS app switcher, open the app and select the regular _Sign in_ option (non-SSO), and it should open up to the headscale authentication page.
Enter your credentials and log in. Headscale should now be working on your iOS device.
+33 -2
View File
@@ -44,9 +44,9 @@ oidc:
- 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 namespace `first-name.last-name`
# 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
# namespace: `first-name.last-name.example.com`
# user: `first-name.last-name.example.com`
strip_email_domain: true
```
@@ -139,3 +139,34 @@ oidc:
# Optional: Force the Azure AD account picker
prompt: select_account
```
## Google OAuth Example
In order to integrate Headscale with Google, you'll need to have a [Google Cloud Console](https://console.cloud.google.com) account.
Google OAuth has a [verification process](https://support.google.com/cloud/answer/9110914?hl=en) if you need to have users authenticate who are outside of your domain. If you only need to authenticate users from your domain name (ie `@example.com`), you don't need to go through the verification process.
However if you don't have a domain, or need to add users outside of your domain, you can manually add emails via Google Console.
### Steps
1. Go to [Google Console](https://console.cloud.google.com) and login or create an account if you don't have one.
2. Create a project (if you don't already have one).
3. On the left hand menu, go to `APIs and services` -> `Credentials`
4. Click `Create Credentials` -> `OAuth client ID`
5. Under `Application Type`, choose `Web Application`
6. For `Name`, enter whatever you like
7. Under `Authorised redirect URIs`, use `https://example.com/oidc/callback`, replacing example.com with your Headscale URL.
8. Click `Save` at the bottom of the form
9. Take note of the `Client ID` and `Client secret`, you can also download it for reference if you need it.
10. Edit your headscale config, under `oidc`, filling in your `client_id` and `client_secret`:
```yaml
oidc:
issuer: "https://accounts.google.com"
client_id: ""
client_secret: ""
scope: ["openid", "profile", "email"]
```
You can also use `allowed_domains` and `allowed_users` to restrict the users who can authenticate.
+17
View File
@@ -112,3 +112,20 @@ The following Caddyfile is all that is necessary to use Caddy as a reverse proxy
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>
```
+4 -4
View File
@@ -101,11 +101,11 @@ Verify `headscale` is available:
curl http://127.0.0.1:9090/metrics
```
6. Create a namespace ([tailnet](https://tailscale.com/kb/1136/tailnet/)):
6. Create a user ([tailnet](https://tailscale.com/kb/1136/tailnet/)):
```shell
docker exec headscale \
headscale namespaces create myfirstnamespace
headscale users create myfirstuser
```
### 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 --namespace myfirstnamespace nodes register --key <YOU_+MACHINE_KEY>
headscale --user myfirstuser 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 --namespace myfirstnamespace preauthkeys create --reusable --expiration 24h
headscale --user myfirstuser 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:
+5 -4
View File
@@ -78,10 +78,10 @@ Verify `headscale` is available:
curl http://127.0.0.1:9090/metrics
```
8. Create a namespace ([tailnet](https://tailscale.com/kb/1136/tailnet/)):
8. Create a user ([tailnet](https://tailscale.com/kb/1136/tailnet/)):
```shell
headscale namespaces create myfirstnamespace
headscale users create myfirstuser
```
### Register a machine (normal login)
@@ -95,7 +95,7 @@ tailscale up --login-server YOUR_HEADSCALE_URL
Register the machine:
```shell
headscale --namespace myfirstnamespace nodes register --key <YOU_+MACHINE_KEY>
headscale --user myfirstuser nodes register --key <YOU_+MACHINE_KEY>
```
### Register machine using a pre authenticated key
@@ -103,7 +103,7 @@ headscale --namespace myfirstnamespace nodes register --key <YOU_+MACHINE_KEY>
Generate a key using the command line:
```shell
headscale --namespace myfirstnamespace preauthkeys create --reusable --expiration 24h
headscale --user myfirstuser 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:
@@ -138,6 +138,7 @@ NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
WorkingDirectory=/var/lib/headscale
ReadWritePaths=/var/lib/headscale /var/run/headscale
AmbientCapabilities=CAP_NET_BIND_SERVICE
RuntimeDirectory=headscale
+8 -11
View File
@@ -10,17 +10,14 @@ describing how to make `headscale` run properly in a server environment.
1. Install from ports (Not Recommend)
As of OpenBSD 7.1, there's a headscale in ports collection, however, it's severely outdated(v0.12.4).
As of OpenBSD 7.2, there's a headscale in ports collection, however, it's severely outdated(v0.12.4).
You can install it via `pkg_add headscale`.
2. Install from source on OpenBSD 7.1
2. Install from source on OpenBSD 7.2
```shell
# Install prerequistes
# 1. go v1.19+: headscale newer than 0.17 needs go 1.19+ to compile
# 2. gmake: Makefile in the headscale repo is written in GNU make syntax
pkg_add -D snap go
pkg_add gmake
pkg_add go
git clone https://github.com/juanfont/headscale.git
@@ -33,7 +30,7 @@ latestTag=$(git describe --tags `git rev-list --tags --max-count=1`)
git checkout $latestTag
gmake build
go build -ldflags="-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$latestTag" github.com/juanfont/headscale
# make it executable
chmod a+x headscale
@@ -116,10 +113,10 @@ Verify `headscale` is available:
curl http://127.0.0.1:9090/metrics
```
6. Create a namespace ([tailnet](https://tailscale.com/kb/1136/tailnet/)):
6. Create a user ([tailnet](https://tailscale.com/kb/1136/tailnet/)):
```shell
headscale namespaces create myfirstnamespace
headscale users create myfirstuser
```
### Register a machine (normal login)
@@ -133,7 +130,7 @@ tailscale up --login-server YOUR_HEADSCALE_URL
Register the machine:
```shell
headscale --namespace myfirstnamespace nodes register --key <YOU_+MACHINE_KEY>
headscale --user myfirstuser nodes register --key <YOU_+MACHINE_KEY>
```
### Register machine using a pre authenticated key
@@ -141,7 +138,7 @@ headscale --namespace myfirstnamespace nodes register --key <YOU_+MACHINE_KEY>
Generate a key using the command line:
```shell
headscale --namespace myfirstnamespace preauthkeys create --reusable --expiration 24h
headscale --user myfirstuser 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:
+138 -132
View File
@@ -6,157 +6,163 @@
flake-utils.url = "github:numtide/flake-utils";
};
outputs = {
self,
nixpkgs,
flake-utils,
...
}: let
headscaleVersion =
if (self ? shortRev)
then self.shortRev
else "dev";
in
outputs =
{ self
, nixpkgs
, flake-utils
, ...
}:
let
headscaleVersion =
if (self ? shortRev)
then self.shortRev
else "dev";
in
{
overlay = _: prev: let
pkgs = nixpkgs.legacyPackages.${prev.system};
in rec {
headscale = pkgs.buildGo119Module rec {
pname = "headscale";
version = headscaleVersion;
src = pkgs.lib.cleanSource self;
overlay = _: prev:
let
pkgs = nixpkgs.legacyPackages.${prev.system};
in
rec {
headscale = pkgs.buildGo119Module rec {
pname = "headscale";
version = headscaleVersion;
src = pkgs.lib.cleanSource self;
tags = ["ts2019"];
tags = [ "ts2019" ];
# Only run unit tests when testing a build
checkFlags = ["-short"];
# Only run unit tests when testing a build
checkFlags = [ "-short" ];
# 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-SuKT+b8g6xEK15ry2IAmpS/vwDG+zJqK9nfsWpHNXuU=";
# 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-R183PDeAUnNwNV8iE3b22S5hGPJG8aZQGdENGqcPCw8=";
ldflags = ["-s" "-w" "-X github.com/juanfont/headscale/cmd/headscale/cli.Version=v${version}"];
};
golines = pkgs.buildGoModule rec {
pname = "golines";
version = "0.11.0";
src = pkgs.fetchFromGitHub {
owner = "segmentio";
repo = "golines";
rev = "v${version}";
sha256 = "sha256-2K9KAg8iSubiTbujyFGN3yggrL+EDyeUCs9OOta/19A=";
ldflags = [ "-s" "-w" "-X github.com/juanfont/headscale/cmd/headscale/cli.Version=v${version}" ];
};
vendorSha256 = "sha256-rxYuzn4ezAxaeDhxd8qdOzt+CKYIh03A9zKNdzILq18=";
golines = pkgs.buildGoModule rec {
pname = "golines";
version = "0.11.0";
nativeBuildInputs = [pkgs.installShellFiles];
};
src = pkgs.fetchFromGitHub {
owner = "segmentio";
repo = "golines";
rev = "v${version}";
sha256 = "sha256-2K9KAg8iSubiTbujyFGN3yggrL+EDyeUCs9OOta/19A=";
};
golangci-lint = prev.golangci-lint.override {
# Override https://github.com/NixOS/nixpkgs/pull/166801 which changed this
# to buildGo118Module because it does not build on Darwin.
inherit (prev) buildGoModule;
};
vendorSha256 = "sha256-rxYuzn4ezAxaeDhxd8qdOzt+CKYIh03A9zKNdzILq18=";
protoc-gen-grpc-gateway = pkgs.buildGoModule rec {
pname = "grpc-gateway";
version = "2.14.0";
src = pkgs.fetchFromGitHub {
owner = "grpc-ecosystem";
repo = "grpc-gateway";
rev = "v${version}";
sha256 = "sha256-lnNdsDCpeSHtl2lC1IhUw11t3cnGF+37qSM7HDvKLls=";
nativeBuildInputs = [ pkgs.installShellFiles ];
};
vendorSha256 = "sha256-dGdnDuRbwg8fU7uB5GaHEWa/zI3w06onqjturvooJQA=";
golangci-lint = prev.golangci-lint.override {
# Override https://github.com/NixOS/nixpkgs/pull/166801 which changed this
# to buildGo118Module because it does not build on Darwin.
inherit (prev) buildGoModule;
};
nativeBuildInputs = [pkgs.installShellFiles];
protoc-gen-grpc-gateway = pkgs.buildGoModule rec {
pname = "grpc-gateway";
version = "2.14.0";
subPackages = ["protoc-gen-grpc-gateway" "protoc-gen-openapiv2"];
src = pkgs.fetchFromGitHub {
owner = "grpc-ecosystem";
repo = "grpc-gateway";
rev = "v${version}";
sha256 = "sha256-lnNdsDCpeSHtl2lC1IhUw11t3cnGF+37qSM7HDvKLls=";
};
vendorSha256 = "sha256-dGdnDuRbwg8fU7uB5GaHEWa/zI3w06onqjturvooJQA=";
nativeBuildInputs = [ pkgs.installShellFiles ];
subPackages = [ "protoc-gen-grpc-gateway" "protoc-gen-openapiv2" ];
};
};
};
}
// flake-utils.lib.eachDefaultSystem
(system: let
pkgs = import nixpkgs {
overlays = [self.overlay];
inherit system;
};
buildDeps = with pkgs; [git go_1_19 gnumake];
devDeps = with pkgs;
buildDeps
++ [
golangci-lint
golines
nodePackages.prettier
goreleaser
(system:
let
pkgs = import nixpkgs {
overlays = [ self.overlay ];
inherit system;
};
buildDeps = with pkgs; [ git go_1_19 gnumake ];
devDeps = with pkgs;
buildDeps
++ [
golangci-lint
golines
nodePackages.prettier
goreleaser
gotestsum
# Protobuf dependencies
protobuf
protoc-gen-go
protoc-gen-go-grpc
protoc-gen-grpc-gateway
buf
clang-tools # clang-format
];
# Protobuf dependencies
protobuf
protoc-gen-go
protoc-gen-go-grpc
protoc-gen-grpc-gateway
buf
clang-tools # clang-format
];
# Add entry to build a docker image with headscale
# caveat: only works on Linux
#
# Usage:
# nix build .#headscale-docker
# docker load < result
headscale-docker = pkgs.dockerTools.buildLayeredImage {
name = "headscale";
tag = headscaleVersion;
contents = [pkgs.headscale];
config.Entrypoint = [(pkgs.headscale + "/bin/headscale")];
};
in rec {
# `nix develop`
devShell = pkgs.mkShell {
buildInputs = devDeps;
# Add entry to build a docker image with headscale
# caveat: only works on Linux
#
# Usage:
# nix build .#headscale-docker
# docker load < result
headscale-docker = pkgs.dockerTools.buildLayeredImage {
name = "headscale";
tag = headscaleVersion;
contents = [ pkgs.headscale ];
config.Entrypoint = [ (pkgs.headscale + "/bin/headscale") ];
};
in
rec {
# `nix develop`
devShell = pkgs.mkShell {
buildInputs = devDeps;
shellHook = ''
export GOFLAGS=-tags="ts2019"
'';
};
# `nix build`
packages = with pkgs; {
inherit headscale;
inherit headscale-docker;
};
defaultPackage = pkgs.headscale;
# `nix run`
apps.headscale = flake-utils.lib.mkApp {
drv = packages.headscale;
};
apps.default = apps.headscale;
checks = {
format =
pkgs.runCommand "check-format"
{
buildInputs = with pkgs; [
gnumake
nixpkgs-fmt
golangci-lint
nodePackages.prettier
golines
clang-tools
];
} ''
${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt ${./.}
${pkgs.golangci-lint}/bin/golangci-lint run --fix --timeout 10m
${pkgs.nodePackages.prettier}/bin/prettier --write '**/**.{ts,js,md,yaml,yml,sass,css,scss,html}'
${pkgs.golines}/bin/golines --max-len=88 --base-formatter=gofumpt -w ${./.}
${pkgs.clang-tools}/bin/clang-format -style="{BasedOnStyle: Google, IndentWidth: 4, AlignConsecutiveDeclarations: true, AlignConsecutiveAssignments: true, ColumnLimit: 0}" -i ${./.}
shellHook = ''
export GOFLAGS=-tags="ts2019"
'';
};
});
};
# `nix build`
packages = with pkgs; {
inherit headscale;
inherit headscale-docker;
};
defaultPackage = pkgs.headscale;
# `nix run`
apps.headscale = flake-utils.lib.mkApp {
drv = packages.headscale;
};
apps.default = apps.headscale;
checks = {
format =
pkgs.runCommand "check-format"
{
buildInputs = with pkgs; [
gnumake
nixpkgs-fmt
golangci-lint
nodePackages.prettier
golines
clang-tools
];
} ''
${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt ${./.}
${pkgs.golangci-lint}/bin/golangci-lint run --fix --timeout 10m
${pkgs.nodePackages.prettier}/bin/prettier --write '**/**.{ts,js,md,yaml,yml,sass,css,scss,html}'
${pkgs.golines}/bin/golines --max-len=88 --base-formatter=gofumpt -w ${./.}
${pkgs.clang-tools}/bin/clang-format -style="{BasedOnStyle: Google, IndentWidth: 4, AlignConsecutiveDeclarations: true, AlignConsecutiveAssignments: true, ColumnLimit: 0}" -i ${./.}
'';
};
});
}
+242 -237
View File
@@ -27,155 +27,148 @@ 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, 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,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12,
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, 0x8d, 0x18, 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, 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,
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, 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, 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,
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, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x64,
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,
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,
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,
@@ -207,39 +200,47 @@ var file_headscale_v1_headscale_proto_rawDesc = []byte{
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x25, 0x12, 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,
0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x70, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b,
0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41,
0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82,
0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76,
0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x12, 0x77, 0x0a, 0x0c, 0x45, 0x78, 0x70, 0x69,
0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70,
0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65,
0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72,
0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 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, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72,
0x65, 0x12, 0x6a, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73,
0x12, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f,
0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 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,
0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x75, 0x0a, 0x0b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63,
0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x75,
0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x1b, 0x2a, 0x19, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74,
0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x70, 0x0a,
0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65,
0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22,
0x0e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x12,
0x77, 0x0a, 0x0c, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x12,
0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45,
0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 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, 0x61, 0x70, 0x69, 0x6b, 0x65,
0x79, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x12, 0x6a, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74,
0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63,
0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65,
0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69,
0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70,
0x69, 0x6b, 0x65, 0x79, 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_headscale_proto_goTypes = []interface{}{
(*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
(*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
(*CreatePreAuthKeyRequest)(nil), // 5: headscale.v1.CreatePreAuthKeyRequest
(*ExpirePreAuthKeyRequest)(nil), // 6: headscale.v1.ExpirePreAuthKeyRequest
(*ListPreAuthKeysRequest)(nil), // 7: headscale.v1.ListPreAuthKeysRequest
@@ -256,40 +257,42 @@ var file_headscale_v1_headscale_proto_goTypes = []interface{}{
(*EnableRouteRequest)(nil), // 18: headscale.v1.EnableRouteRequest
(*DisableRouteRequest)(nil), // 19: headscale.v1.DisableRouteRequest
(*GetMachineRoutesRequest)(nil), // 20: headscale.v1.GetMachineRoutesRequest
(*CreateApiKeyRequest)(nil), // 21: headscale.v1.CreateApiKeyRequest
(*ExpireApiKeyRequest)(nil), // 22: headscale.v1.ExpireApiKeyRequest
(*ListApiKeysRequest)(nil), // 23: headscale.v1.ListApiKeysRequest
(*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
(*DebugCreateMachineResponse)(nil), // 32: headscale.v1.DebugCreateMachineResponse
(*GetMachineResponse)(nil), // 33: headscale.v1.GetMachineResponse
(*SetTagsResponse)(nil), // 34: headscale.v1.SetTagsResponse
(*RegisterMachineResponse)(nil), // 35: headscale.v1.RegisterMachineResponse
(*DeleteMachineResponse)(nil), // 36: headscale.v1.DeleteMachineResponse
(*ExpireMachineResponse)(nil), // 37: headscale.v1.ExpireMachineResponse
(*RenameMachineResponse)(nil), // 38: headscale.v1.RenameMachineResponse
(*ListMachinesResponse)(nil), // 39: headscale.v1.ListMachinesResponse
(*MoveMachineResponse)(nil), // 40: headscale.v1.MoveMachineResponse
(*GetRoutesResponse)(nil), // 41: headscale.v1.GetRoutesResponse
(*EnableRouteResponse)(nil), // 42: headscale.v1.EnableRouteResponse
(*DisableRouteResponse)(nil), // 43: headscale.v1.DisableRouteResponse
(*GetMachineRoutesResponse)(nil), // 44: headscale.v1.GetMachineRoutesResponse
(*CreateApiKeyResponse)(nil), // 45: headscale.v1.CreateApiKeyResponse
(*ExpireApiKeyResponse)(nil), // 46: headscale.v1.ExpireApiKeyResponse
(*ListApiKeysResponse)(nil), // 47: headscale.v1.ListApiKeysResponse
(*DeleteRouteRequest)(nil), // 21: headscale.v1.DeleteRouteRequest
(*CreateApiKeyRequest)(nil), // 22: headscale.v1.CreateApiKeyRequest
(*ExpireApiKeyRequest)(nil), // 23: headscale.v1.ExpireApiKeyRequest
(*ListApiKeysRequest)(nil), // 24: headscale.v1.ListApiKeysRequest
(*GetUserResponse)(nil), // 25: headscale.v1.GetUserResponse
(*CreateUserResponse)(nil), // 26: headscale.v1.CreateUserResponse
(*RenameUserResponse)(nil), // 27: headscale.v1.RenameUserResponse
(*DeleteUserResponse)(nil), // 28: headscale.v1.DeleteUserResponse
(*ListUsersResponse)(nil), // 29: headscale.v1.ListUsersResponse
(*CreatePreAuthKeyResponse)(nil), // 30: headscale.v1.CreatePreAuthKeyResponse
(*ExpirePreAuthKeyResponse)(nil), // 31: headscale.v1.ExpirePreAuthKeyResponse
(*ListPreAuthKeysResponse)(nil), // 32: headscale.v1.ListPreAuthKeysResponse
(*DebugCreateMachineResponse)(nil), // 33: headscale.v1.DebugCreateMachineResponse
(*GetMachineResponse)(nil), // 34: headscale.v1.GetMachineResponse
(*SetTagsResponse)(nil), // 35: headscale.v1.SetTagsResponse
(*RegisterMachineResponse)(nil), // 36: headscale.v1.RegisterMachineResponse
(*DeleteMachineResponse)(nil), // 37: headscale.v1.DeleteMachineResponse
(*ExpireMachineResponse)(nil), // 38: headscale.v1.ExpireMachineResponse
(*RenameMachineResponse)(nil), // 39: headscale.v1.RenameMachineResponse
(*ListMachinesResponse)(nil), // 40: headscale.v1.ListMachinesResponse
(*MoveMachineResponse)(nil), // 41: headscale.v1.MoveMachineResponse
(*GetRoutesResponse)(nil), // 42: headscale.v1.GetRoutesResponse
(*EnableRouteResponse)(nil), // 43: headscale.v1.EnableRouteResponse
(*DisableRouteResponse)(nil), // 44: headscale.v1.DisableRouteResponse
(*GetMachineRoutesResponse)(nil), // 45: headscale.v1.GetMachineRoutesResponse
(*DeleteRouteResponse)(nil), // 46: headscale.v1.DeleteRouteResponse
(*CreateApiKeyResponse)(nil), // 47: headscale.v1.CreateApiKeyResponse
(*ExpireApiKeyResponse)(nil), // 48: headscale.v1.ExpireApiKeyResponse
(*ListApiKeysResponse)(nil), // 49: headscale.v1.ListApiKeysResponse
}
var file_headscale_v1_headscale_proto_depIdxs = []int32{
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
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
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
@@ -306,35 +309,37 @@ var file_headscale_v1_headscale_proto_depIdxs = []int32{
18, // 18: headscale.v1.HeadscaleService.EnableRoute:input_type -> headscale.v1.EnableRouteRequest
19, // 19: headscale.v1.HeadscaleService.DisableRoute:input_type -> headscale.v1.DisableRouteRequest
20, // 20: headscale.v1.HeadscaleService.GetMachineRoutes:input_type -> headscale.v1.GetMachineRoutesRequest
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.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
32, // 32: headscale.v1.HeadscaleService.DebugCreateMachine:output_type -> headscale.v1.DebugCreateMachineResponse
33, // 33: headscale.v1.HeadscaleService.GetMachine:output_type -> headscale.v1.GetMachineResponse
34, // 34: headscale.v1.HeadscaleService.SetTags:output_type -> headscale.v1.SetTagsResponse
35, // 35: headscale.v1.HeadscaleService.RegisterMachine:output_type -> headscale.v1.RegisterMachineResponse
36, // 36: headscale.v1.HeadscaleService.DeleteMachine:output_type -> headscale.v1.DeleteMachineResponse
37, // 37: headscale.v1.HeadscaleService.ExpireMachine:output_type -> headscale.v1.ExpireMachineResponse
38, // 38: headscale.v1.HeadscaleService.RenameMachine:output_type -> headscale.v1.RenameMachineResponse
39, // 39: headscale.v1.HeadscaleService.ListMachines:output_type -> headscale.v1.ListMachinesResponse
40, // 40: headscale.v1.HeadscaleService.MoveMachine:output_type -> headscale.v1.MoveMachineResponse
41, // 41: headscale.v1.HeadscaleService.GetRoutes:output_type -> headscale.v1.GetRoutesResponse
42, // 42: headscale.v1.HeadscaleService.EnableRoute:output_type -> headscale.v1.EnableRouteResponse
43, // 43: headscale.v1.HeadscaleService.DisableRoute:output_type -> headscale.v1.DisableRouteResponse
44, // 44: headscale.v1.HeadscaleService.GetMachineRoutes:output_type -> headscale.v1.GetMachineRoutesResponse
45, // 45: headscale.v1.HeadscaleService.CreateApiKey:output_type -> headscale.v1.CreateApiKeyResponse
46, // 46: headscale.v1.HeadscaleService.ExpireApiKey:output_type -> headscale.v1.ExpireApiKeyResponse
47, // 47: headscale.v1.HeadscaleService.ListApiKeys:output_type -> headscale.v1.ListApiKeysResponse
24, // [24:48] is the sub-list for method output_type
0, // [0:24] is the sub-list for method input_type
21, // 21: headscale.v1.HeadscaleService.DeleteRoute:input_type -> headscale.v1.DeleteRouteRequest
22, // 22: headscale.v1.HeadscaleService.CreateApiKey:input_type -> headscale.v1.CreateApiKeyRequest
23, // 23: headscale.v1.HeadscaleService.ExpireApiKey:input_type -> headscale.v1.ExpireApiKeyRequest
24, // 24: headscale.v1.HeadscaleService.ListApiKeys:input_type -> headscale.v1.ListApiKeysRequest
25, // 25: headscale.v1.HeadscaleService.GetUser:output_type -> headscale.v1.GetUserResponse
26, // 26: headscale.v1.HeadscaleService.CreateUser:output_type -> headscale.v1.CreateUserResponse
27, // 27: headscale.v1.HeadscaleService.RenameUser:output_type -> headscale.v1.RenameUserResponse
28, // 28: headscale.v1.HeadscaleService.DeleteUser:output_type -> headscale.v1.DeleteUserResponse
29, // 29: headscale.v1.HeadscaleService.ListUsers:output_type -> headscale.v1.ListUsersResponse
30, // 30: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse
31, // 31: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse
32, // 32: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse
33, // 33: headscale.v1.HeadscaleService.DebugCreateMachine:output_type -> headscale.v1.DebugCreateMachineResponse
34, // 34: headscale.v1.HeadscaleService.GetMachine:output_type -> headscale.v1.GetMachineResponse
35, // 35: headscale.v1.HeadscaleService.SetTags:output_type -> headscale.v1.SetTagsResponse
36, // 36: headscale.v1.HeadscaleService.RegisterMachine:output_type -> headscale.v1.RegisterMachineResponse
37, // 37: headscale.v1.HeadscaleService.DeleteMachine:output_type -> headscale.v1.DeleteMachineResponse
38, // 38: headscale.v1.HeadscaleService.ExpireMachine:output_type -> headscale.v1.ExpireMachineResponse
39, // 39: headscale.v1.HeadscaleService.RenameMachine:output_type -> headscale.v1.RenameMachineResponse
40, // 40: headscale.v1.HeadscaleService.ListMachines:output_type -> headscale.v1.ListMachinesResponse
41, // 41: headscale.v1.HeadscaleService.MoveMachine:output_type -> headscale.v1.MoveMachineResponse
42, // 42: headscale.v1.HeadscaleService.GetRoutes:output_type -> headscale.v1.GetRoutesResponse
43, // 43: headscale.v1.HeadscaleService.EnableRoute:output_type -> headscale.v1.EnableRouteResponse
44, // 44: headscale.v1.HeadscaleService.DisableRoute:output_type -> headscale.v1.DisableRouteResponse
45, // 45: headscale.v1.HeadscaleService.GetMachineRoutes:output_type -> headscale.v1.GetMachineRoutesResponse
46, // 46: headscale.v1.HeadscaleService.DeleteRoute:output_type -> headscale.v1.DeleteRouteResponse
47, // 47: headscale.v1.HeadscaleService.CreateApiKey:output_type -> headscale.v1.CreateApiKeyResponse
48, // 48: headscale.v1.HeadscaleService.ExpireApiKey:output_type -> headscale.v1.ExpireApiKeyResponse
49, // 49: headscale.v1.HeadscaleService.ListApiKeys:output_type -> headscale.v1.ListApiKeysResponse
25, // [25:50] is the sub-list for method output_type
0, // [0:25] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
@@ -345,7 +350,7 @@ func file_headscale_v1_headscale_proto_init() {
if File_headscale_v1_headscale_proto != nil {
return
}
file_headscale_v1_namespace_proto_init()
file_headscale_v1_user_proto_init()
file_headscale_v1_preauthkey_proto_init()
file_headscale_v1_machine_proto_init()
file_headscale_v1_routes_proto_init()
+186 -83
View File
@@ -31,8 +31,8 @@ var _ = runtime.String
var _ = utilities.NewDoubleArray
var _ = metadata.Join
func request_HeadscaleService_GetNamespace_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq GetNamespaceRequest
func request_HeadscaleService_GetUser_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq GetUserRequest
var metadata runtime.ServerMetadata
var (
@@ -52,13 +52,13 @@ func request_HeadscaleService_GetNamespace_0(ctx context.Context, marshaler runt
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
}
msg, err := client.GetNamespace(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
msg, err := client.GetUser(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_HeadscaleService_GetNamespace_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq GetNamespaceRequest
func local_request_HeadscaleService_GetUser_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq GetUserRequest
var metadata runtime.ServerMetadata
var (
@@ -78,13 +78,13 @@ func local_request_HeadscaleService_GetNamespace_0(ctx context.Context, marshale
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
}
msg, err := server.GetNamespace(ctx, &protoReq)
msg, err := server.GetUser(ctx, &protoReq)
return msg, metadata, err
}
func request_HeadscaleService_CreateNamespace_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq CreateNamespaceRequest
func request_HeadscaleService_CreateUser_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq CreateUserRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
@@ -95,13 +95,13 @@ func request_HeadscaleService_CreateNamespace_0(ctx context.Context, marshaler r
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.CreateNamespace(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
msg, err := client.CreateUser(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_HeadscaleService_CreateNamespace_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq CreateNamespaceRequest
func local_request_HeadscaleService_CreateUser_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq CreateUserRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
@@ -112,13 +112,13 @@ func local_request_HeadscaleService_CreateNamespace_0(ctx context.Context, marsh
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.CreateNamespace(ctx, &protoReq)
msg, err := server.CreateUser(ctx, &protoReq)
return msg, metadata, err
}
func request_HeadscaleService_RenameNamespace_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq RenameNamespaceRequest
func request_HeadscaleService_RenameUser_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq RenameUserRequest
var metadata runtime.ServerMetadata
var (
@@ -148,13 +148,13 @@ func request_HeadscaleService_RenameNamespace_0(ctx context.Context, marshaler r
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "new_name", err)
}
msg, err := client.RenameNamespace(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
msg, err := client.RenameUser(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_HeadscaleService_RenameNamespace_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq RenameNamespaceRequest
func local_request_HeadscaleService_RenameUser_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq RenameUserRequest
var metadata runtime.ServerMetadata
var (
@@ -184,13 +184,13 @@ func local_request_HeadscaleService_RenameNamespace_0(ctx context.Context, marsh
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "new_name", err)
}
msg, err := server.RenameNamespace(ctx, &protoReq)
msg, err := server.RenameUser(ctx, &protoReq)
return msg, metadata, err
}
func request_HeadscaleService_DeleteNamespace_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeleteNamespaceRequest
func request_HeadscaleService_DeleteUser_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeleteUserRequest
var metadata runtime.ServerMetadata
var (
@@ -210,13 +210,13 @@ func request_HeadscaleService_DeleteNamespace_0(ctx context.Context, marshaler r
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
}
msg, err := client.DeleteNamespace(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
msg, err := client.DeleteUser(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_HeadscaleService_DeleteNamespace_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeleteNamespaceRequest
func local_request_HeadscaleService_DeleteUser_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeleteUserRequest
var metadata runtime.ServerMetadata
var (
@@ -236,25 +236,25 @@ func local_request_HeadscaleService_DeleteNamespace_0(ctx context.Context, marsh
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
}
msg, err := server.DeleteNamespace(ctx, &protoReq)
msg, err := server.DeleteUser(ctx, &protoReq)
return msg, metadata, err
}
func request_HeadscaleService_ListNamespaces_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ListNamespacesRequest
func request_HeadscaleService_ListUsers_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ListUsersRequest
var metadata runtime.ServerMetadata
msg, err := client.ListNamespaces(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
msg, err := client.ListUsers(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_HeadscaleService_ListNamespaces_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ListNamespacesRequest
func local_request_HeadscaleService_ListUsers_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ListUsersRequest
var metadata runtime.ServerMetadata
msg, err := server.ListNamespaces(ctx, &protoReq)
msg, err := server.ListUsers(ctx, &protoReq)
return msg, metadata, err
}
@@ -1009,6 +1009,58 @@ func local_request_HeadscaleService_GetMachineRoutes_0(ctx context.Context, mars
}
func request_HeadscaleService_DeleteRoute_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeleteRouteRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["route_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "route_id")
}
protoReq.RouteId, err = runtime.Uint64(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "route_id", err)
}
msg, err := client.DeleteRoute(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_HeadscaleService_DeleteRoute_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeleteRouteRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["route_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "route_id")
}
protoReq.RouteId, err = runtime.Uint64(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "route_id", err)
}
msg, err := server.DeleteRoute(ctx, &protoReq)
return msg, metadata, err
}
func request_HeadscaleService_CreateApiKey_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq CreateApiKeyRequest
var metadata runtime.ServerMetadata
@@ -1101,7 +1153,7 @@ func local_request_HeadscaleService_ListApiKeys_0(ctx context.Context, marshaler
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterHeadscaleServiceHandlerFromEndpoint instead.
func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server HeadscaleServiceServer) error {
mux.Handle("GET", pattern_HeadscaleService_GetNamespace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("GET", pattern_HeadscaleService_GetUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
@@ -1109,12 +1161,12 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/GetNamespace", runtime.WithHTTPPathPattern("/api/v1/namespace/{name}"))
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/GetUser", runtime.WithHTTPPathPattern("/api/v1/user/{name}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_HeadscaleService_GetNamespace_0(annotatedContext, inboundMarshaler, server, req, pathParams)
resp, md, err := local_request_HeadscaleService_GetUser_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
@@ -1122,11 +1174,11 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser
return
}
forward_HeadscaleService_GetNamespace_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_HeadscaleService_GetUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_HeadscaleService_CreateNamespace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("POST", pattern_HeadscaleService_CreateUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
@@ -1134,12 +1186,12 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/CreateNamespace", runtime.WithHTTPPathPattern("/api/v1/namespace"))
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/CreateUser", runtime.WithHTTPPathPattern("/api/v1/user"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_HeadscaleService_CreateNamespace_0(annotatedContext, inboundMarshaler, server, req, pathParams)
resp, md, err := local_request_HeadscaleService_CreateUser_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
@@ -1147,11 +1199,11 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser
return
}
forward_HeadscaleService_CreateNamespace_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_HeadscaleService_CreateUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_HeadscaleService_RenameNamespace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("POST", pattern_HeadscaleService_RenameUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
@@ -1159,12 +1211,12 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/RenameNamespace", runtime.WithHTTPPathPattern("/api/v1/namespace/{old_name}/rename/{new_name}"))
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/RenameUser", runtime.WithHTTPPathPattern("/api/v1/user/{old_name}/rename/{new_name}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_HeadscaleService_RenameNamespace_0(annotatedContext, inboundMarshaler, server, req, pathParams)
resp, md, err := local_request_HeadscaleService_RenameUser_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
@@ -1172,11 +1224,11 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser
return
}
forward_HeadscaleService_RenameNamespace_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_HeadscaleService_RenameUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("DELETE", pattern_HeadscaleService_DeleteNamespace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("DELETE", pattern_HeadscaleService_DeleteUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
@@ -1184,12 +1236,12 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/DeleteNamespace", runtime.WithHTTPPathPattern("/api/v1/namespace/{name}"))
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/DeleteUser", runtime.WithHTTPPathPattern("/api/v1/user/{name}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_HeadscaleService_DeleteNamespace_0(annotatedContext, inboundMarshaler, server, req, pathParams)
resp, md, err := local_request_HeadscaleService_DeleteUser_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
@@ -1197,11 +1249,11 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser
return
}
forward_HeadscaleService_DeleteNamespace_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_HeadscaleService_DeleteUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_HeadscaleService_ListNamespaces_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("GET", pattern_HeadscaleService_ListUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
@@ -1209,12 +1261,12 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/ListNamespaces", runtime.WithHTTPPathPattern("/api/v1/namespace"))
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/ListUsers", runtime.WithHTTPPathPattern("/api/v1/user"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_HeadscaleService_ListNamespaces_0(annotatedContext, inboundMarshaler, server, req, pathParams)
resp, md, err := local_request_HeadscaleService_ListUsers_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
@@ -1222,7 +1274,7 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser
return
}
forward_HeadscaleService_ListNamespaces_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_HeadscaleService_ListUsers_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
@@ -1509,7 +1561,7 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/MoveMachine", runtime.WithHTTPPathPattern("/api/v1/machine/{machine_id}/namespace"))
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/MoveMachine", runtime.WithHTTPPathPattern("/api/v1/machine/{machine_id}/user"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
@@ -1626,6 +1678,31 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser
})
mux.Handle("DELETE", pattern_HeadscaleService_DeleteRoute_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/DeleteRoute", runtime.WithHTTPPathPattern("/api/v1/routes/{route_id}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_HeadscaleService_DeleteRoute_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_HeadscaleService_DeleteRoute_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_HeadscaleService_CreateApiKey_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -1742,113 +1819,113 @@ func RegisterHeadscaleServiceHandler(ctx context.Context, mux *runtime.ServeMux,
// "HeadscaleServiceClient" to call the correct interceptors.
func RegisterHeadscaleServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client HeadscaleServiceClient) error {
mux.Handle("GET", pattern_HeadscaleService_GetNamespace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("GET", pattern_HeadscaleService_GetUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/GetNamespace", runtime.WithHTTPPathPattern("/api/v1/namespace/{name}"))
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/GetUser", runtime.WithHTTPPathPattern("/api/v1/user/{name}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_HeadscaleService_GetNamespace_0(annotatedContext, inboundMarshaler, client, req, pathParams)
resp, md, err := request_HeadscaleService_GetUser_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_HeadscaleService_GetNamespace_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_HeadscaleService_GetUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_HeadscaleService_CreateNamespace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("POST", pattern_HeadscaleService_CreateUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/CreateNamespace", runtime.WithHTTPPathPattern("/api/v1/namespace"))
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/CreateUser", runtime.WithHTTPPathPattern("/api/v1/user"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_HeadscaleService_CreateNamespace_0(annotatedContext, inboundMarshaler, client, req, pathParams)
resp, md, err := request_HeadscaleService_CreateUser_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_HeadscaleService_CreateNamespace_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_HeadscaleService_CreateUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_HeadscaleService_RenameNamespace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("POST", pattern_HeadscaleService_RenameUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/RenameNamespace", runtime.WithHTTPPathPattern("/api/v1/namespace/{old_name}/rename/{new_name}"))
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/RenameUser", runtime.WithHTTPPathPattern("/api/v1/user/{old_name}/rename/{new_name}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_HeadscaleService_RenameNamespace_0(annotatedContext, inboundMarshaler, client, req, pathParams)
resp, md, err := request_HeadscaleService_RenameUser_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_HeadscaleService_RenameNamespace_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_HeadscaleService_RenameUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("DELETE", pattern_HeadscaleService_DeleteNamespace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("DELETE", pattern_HeadscaleService_DeleteUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/DeleteNamespace", runtime.WithHTTPPathPattern("/api/v1/namespace/{name}"))
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/DeleteUser", runtime.WithHTTPPathPattern("/api/v1/user/{name}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_HeadscaleService_DeleteNamespace_0(annotatedContext, inboundMarshaler, client, req, pathParams)
resp, md, err := request_HeadscaleService_DeleteUser_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_HeadscaleService_DeleteNamespace_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_HeadscaleService_DeleteUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_HeadscaleService_ListNamespaces_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("GET", pattern_HeadscaleService_ListUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/ListNamespaces", runtime.WithHTTPPathPattern("/api/v1/namespace"))
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/ListUsers", runtime.WithHTTPPathPattern("/api/v1/user"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_HeadscaleService_ListNamespaces_0(annotatedContext, inboundMarshaler, client, req, pathParams)
resp, md, err := request_HeadscaleService_ListUsers_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_HeadscaleService_ListNamespaces_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_HeadscaleService_ListUsers_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
@@ -2100,7 +2177,7 @@ func RegisterHeadscaleServiceHandlerClient(ctx context.Context, mux *runtime.Ser
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/MoveMachine", runtime.WithHTTPPathPattern("/api/v1/machine/{machine_id}/namespace"))
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/MoveMachine", runtime.WithHTTPPathPattern("/api/v1/machine/{machine_id}/user"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
@@ -2204,6 +2281,28 @@ func RegisterHeadscaleServiceHandlerClient(ctx context.Context, mux *runtime.Ser
})
mux.Handle("DELETE", pattern_HeadscaleService_DeleteRoute_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/DeleteRoute", runtime.WithHTTPPathPattern("/api/v1/routes/{route_id}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_HeadscaleService_DeleteRoute_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_HeadscaleService_DeleteRoute_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_HeadscaleService_CreateApiKey_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -2274,15 +2373,15 @@ func RegisterHeadscaleServiceHandlerClient(ctx context.Context, mux *runtime.Ser
}
var (
pattern_HeadscaleService_GetNamespace_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "namespace", "name"}, ""))
pattern_HeadscaleService_GetUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "user", "name"}, ""))
pattern_HeadscaleService_CreateNamespace_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "namespace"}, ""))
pattern_HeadscaleService_CreateUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "user"}, ""))
pattern_HeadscaleService_RenameNamespace_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"api", "v1", "namespace", "old_name", "rename", "new_name"}, ""))
pattern_HeadscaleService_RenameUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"api", "v1", "user", "old_name", "rename", "new_name"}, ""))
pattern_HeadscaleService_DeleteNamespace_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "namespace", "name"}, ""))
pattern_HeadscaleService_DeleteUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "user", "name"}, ""))
pattern_HeadscaleService_ListNamespaces_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "namespace"}, ""))
pattern_HeadscaleService_ListUsers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "user"}, ""))
pattern_HeadscaleService_CreatePreAuthKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "preauthkey"}, ""))
@@ -2306,7 +2405,7 @@ var (
pattern_HeadscaleService_ListMachines_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "machine"}, ""))
pattern_HeadscaleService_MoveMachine_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "machine", "machine_id", "namespace"}, ""))
pattern_HeadscaleService_MoveMachine_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "machine", "machine_id", "user"}, ""))
pattern_HeadscaleService_GetRoutes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "routes"}, ""))
@@ -2316,6 +2415,8 @@ var (
pattern_HeadscaleService_GetMachineRoutes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "machine", "machine_id", "routes"}, ""))
pattern_HeadscaleService_DeleteRoute_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "routes", "route_id"}, ""))
pattern_HeadscaleService_CreateApiKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "apikey"}, ""))
pattern_HeadscaleService_ExpireApiKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "apikey", "expire"}, ""))
@@ -2324,15 +2425,15 @@ var (
)
var (
forward_HeadscaleService_GetNamespace_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_GetUser_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_CreateNamespace_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_CreateUser_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_RenameNamespace_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_RenameUser_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_DeleteNamespace_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_DeleteUser_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_ListNamespaces_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_ListUsers_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_CreatePreAuthKey_0 = runtime.ForwardResponseMessage
@@ -2366,6 +2467,8 @@ var (
forward_HeadscaleService_GetMachineRoutes_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_DeleteRoute_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_CreateApiKey_0 = runtime.ForwardResponseMessage
forward_HeadscaleService_ExpireApiKey_0 = runtime.ForwardResponseMessage
+108 -72
View File
@@ -22,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 {
// --- 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)
// --- 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)
// --- PreAuthKeys start ---
CreatePreAuthKey(ctx context.Context, in *CreatePreAuthKeyRequest, opts ...grpc.CallOption) (*CreatePreAuthKeyResponse, error)
ExpirePreAuthKey(ctx context.Context, in *ExpirePreAuthKeyRequest, opts ...grpc.CallOption) (*ExpirePreAuthKeyResponse, error)
@@ -47,6 +47,7 @@ type HeadscaleServiceClient interface {
EnableRoute(ctx context.Context, in *EnableRouteRequest, opts ...grpc.CallOption) (*EnableRouteResponse, error)
DisableRoute(ctx context.Context, in *DisableRouteRequest, opts ...grpc.CallOption) (*DisableRouteResponse, error)
GetMachineRoutes(ctx context.Context, in *GetMachineRoutesRequest, opts ...grpc.CallOption) (*GetMachineRoutesResponse, error)
DeleteRoute(ctx context.Context, in *DeleteRouteRequest, opts ...grpc.CallOption) (*DeleteRouteResponse, error)
// --- ApiKeys start ---
CreateApiKey(ctx context.Context, in *CreateApiKeyRequest, opts ...grpc.CallOption) (*CreateApiKeyResponse, error)
ExpireApiKey(ctx context.Context, in *ExpireApiKeyRequest, opts ...grpc.CallOption) (*ExpireApiKeyResponse, error)
@@ -61,45 +62,45 @@ func NewHeadscaleServiceClient(cc grpc.ClientConnInterface) HeadscaleServiceClie
return &headscaleServiceClient{cc}
}
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...)
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...)
if err != nil {
return nil, err
}
return out, nil
}
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...)
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...)
if err != nil {
return nil, err
}
return out, nil
}
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...)
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...)
if err != nil {
return nil, err
}
return out, nil
}
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...)
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...)
if err != nil {
return nil, err
}
return out, nil
}
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...)
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...)
if err != nil {
return nil, err
}
@@ -250,6 +251,15 @@ func (c *headscaleServiceClient) GetMachineRoutes(ctx context.Context, in *GetMa
return out, nil
}
func (c *headscaleServiceClient) DeleteRoute(ctx context.Context, in *DeleteRouteRequest, opts ...grpc.CallOption) (*DeleteRouteResponse, error) {
out := new(DeleteRouteResponse)
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/DeleteRoute", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *headscaleServiceClient) CreateApiKey(ctx context.Context, in *CreateApiKeyRequest, opts ...grpc.CallOption) (*CreateApiKeyResponse, error) {
out := new(CreateApiKeyResponse)
err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/CreateApiKey", in, out, opts...)
@@ -281,12 +291,12 @@ func (c *headscaleServiceClient) ListApiKeys(ctx context.Context, in *ListApiKey
// All implementations must embed UnimplementedHeadscaleServiceServer
// for forward compatibility
type HeadscaleServiceServer interface {
// --- 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)
// --- 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)
// --- PreAuthKeys start ---
CreatePreAuthKey(context.Context, *CreatePreAuthKeyRequest) (*CreatePreAuthKeyResponse, error)
ExpirePreAuthKey(context.Context, *ExpirePreAuthKeyRequest) (*ExpirePreAuthKeyResponse, error)
@@ -306,6 +316,7 @@ type HeadscaleServiceServer interface {
EnableRoute(context.Context, *EnableRouteRequest) (*EnableRouteResponse, error)
DisableRoute(context.Context, *DisableRouteRequest) (*DisableRouteResponse, error)
GetMachineRoutes(context.Context, *GetMachineRoutesRequest) (*GetMachineRoutesResponse, error)
DeleteRoute(context.Context, *DeleteRouteRequest) (*DeleteRouteResponse, error)
// --- ApiKeys start ---
CreateApiKey(context.Context, *CreateApiKeyRequest) (*CreateApiKeyResponse, error)
ExpireApiKey(context.Context, *ExpireApiKeyRequest) (*ExpireApiKeyResponse, error)
@@ -317,20 +328,20 @@ type HeadscaleServiceServer interface {
type UnimplementedHeadscaleServiceServer struct {
}
func (UnimplementedHeadscaleServiceServer) GetNamespace(context.Context, *GetNamespaceRequest) (*GetNamespaceResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetNamespace not implemented")
func (UnimplementedHeadscaleServiceServer) GetUser(context.Context, *GetUserRequest) (*GetUserResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetUser not implemented")
}
func (UnimplementedHeadscaleServiceServer) CreateNamespace(context.Context, *CreateNamespaceRequest) (*CreateNamespaceResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateNamespace not implemented")
func (UnimplementedHeadscaleServiceServer) CreateUser(context.Context, *CreateUserRequest) (*CreateUserResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateUser not implemented")
}
func (UnimplementedHeadscaleServiceServer) RenameNamespace(context.Context, *RenameNamespaceRequest) (*RenameNamespaceResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RenameNamespace not implemented")
func (UnimplementedHeadscaleServiceServer) RenameUser(context.Context, *RenameUserRequest) (*RenameUserResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RenameUser not implemented")
}
func (UnimplementedHeadscaleServiceServer) DeleteNamespace(context.Context, *DeleteNamespaceRequest) (*DeleteNamespaceResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteNamespace not implemented")
func (UnimplementedHeadscaleServiceServer) DeleteUser(context.Context, *DeleteUserRequest) (*DeleteUserResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteUser not implemented")
}
func (UnimplementedHeadscaleServiceServer) ListNamespaces(context.Context, *ListNamespacesRequest) (*ListNamespacesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListNamespaces not implemented")
func (UnimplementedHeadscaleServiceServer) ListUsers(context.Context, *ListUsersRequest) (*ListUsersResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListUsers not implemented")
}
func (UnimplementedHeadscaleServiceServer) CreatePreAuthKey(context.Context, *CreatePreAuthKeyRequest) (*CreatePreAuthKeyResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreatePreAuthKey not implemented")
@@ -380,6 +391,9 @@ func (UnimplementedHeadscaleServiceServer) DisableRoute(context.Context, *Disabl
func (UnimplementedHeadscaleServiceServer) GetMachineRoutes(context.Context, *GetMachineRoutesRequest) (*GetMachineRoutesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetMachineRoutes not implemented")
}
func (UnimplementedHeadscaleServiceServer) DeleteRoute(context.Context, *DeleteRouteRequest) (*DeleteRouteResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteRoute not implemented")
}
func (UnimplementedHeadscaleServiceServer) CreateApiKey(context.Context, *CreateApiKeyRequest) (*CreateApiKeyResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateApiKey not implemented")
}
@@ -402,92 +416,92 @@ func RegisterHeadscaleServiceServer(s grpc.ServiceRegistrar, srv HeadscaleServic
s.RegisterService(&HeadscaleService_ServiceDesc, srv)
}
func _HeadscaleService_GetNamespace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetNamespaceRequest)
func _HeadscaleService_GetUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetUserRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HeadscaleServiceServer).GetNamespace(ctx, in)
return srv.(HeadscaleServiceServer).GetUser(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/headscale.v1.HeadscaleService/GetNamespace",
FullMethod: "/headscale.v1.HeadscaleService/GetUser",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HeadscaleServiceServer).GetNamespace(ctx, req.(*GetNamespaceRequest))
return srv.(HeadscaleServiceServer).GetUser(ctx, req.(*GetUserRequest))
}
return interceptor(ctx, in, info, handler)
}
func _HeadscaleService_CreateNamespace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateNamespaceRequest)
func _HeadscaleService_CreateUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateUserRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HeadscaleServiceServer).CreateNamespace(ctx, in)
return srv.(HeadscaleServiceServer).CreateUser(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/headscale.v1.HeadscaleService/CreateNamespace",
FullMethod: "/headscale.v1.HeadscaleService/CreateUser",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HeadscaleServiceServer).CreateNamespace(ctx, req.(*CreateNamespaceRequest))
return srv.(HeadscaleServiceServer).CreateUser(ctx, req.(*CreateUserRequest))
}
return interceptor(ctx, in, info, handler)
}
func _HeadscaleService_RenameNamespace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RenameNamespaceRequest)
func _HeadscaleService_RenameUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RenameUserRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HeadscaleServiceServer).RenameNamespace(ctx, in)
return srv.(HeadscaleServiceServer).RenameUser(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/headscale.v1.HeadscaleService/RenameNamespace",
FullMethod: "/headscale.v1.HeadscaleService/RenameUser",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HeadscaleServiceServer).RenameNamespace(ctx, req.(*RenameNamespaceRequest))
return srv.(HeadscaleServiceServer).RenameUser(ctx, req.(*RenameUserRequest))
}
return interceptor(ctx, in, info, handler)
}
func _HeadscaleService_DeleteNamespace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteNamespaceRequest)
func _HeadscaleService_DeleteUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteUserRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HeadscaleServiceServer).DeleteNamespace(ctx, in)
return srv.(HeadscaleServiceServer).DeleteUser(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/headscale.v1.HeadscaleService/DeleteNamespace",
FullMethod: "/headscale.v1.HeadscaleService/DeleteUser",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HeadscaleServiceServer).DeleteNamespace(ctx, req.(*DeleteNamespaceRequest))
return srv.(HeadscaleServiceServer).DeleteUser(ctx, req.(*DeleteUserRequest))
}
return interceptor(ctx, in, info, handler)
}
func _HeadscaleService_ListNamespaces_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListNamespacesRequest)
func _HeadscaleService_ListUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListUsersRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HeadscaleServiceServer).ListNamespaces(ctx, in)
return srv.(HeadscaleServiceServer).ListUsers(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/headscale.v1.HeadscaleService/ListNamespaces",
FullMethod: "/headscale.v1.HeadscaleService/ListUsers",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HeadscaleServiceServer).ListNamespaces(ctx, req.(*ListNamespacesRequest))
return srv.(HeadscaleServiceServer).ListUsers(ctx, req.(*ListUsersRequest))
}
return interceptor(ctx, in, info, handler)
}
@@ -780,6 +794,24 @@ func _HeadscaleService_GetMachineRoutes_Handler(srv interface{}, ctx context.Con
return interceptor(ctx, in, info, handler)
}
func _HeadscaleService_DeleteRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteRouteRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HeadscaleServiceServer).DeleteRoute(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/headscale.v1.HeadscaleService/DeleteRoute",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HeadscaleServiceServer).DeleteRoute(ctx, req.(*DeleteRouteRequest))
}
return interceptor(ctx, in, info, handler)
}
func _HeadscaleService_CreateApiKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateApiKeyRequest)
if err := dec(in); err != nil {
@@ -842,24 +874,24 @@ var HeadscaleService_ServiceDesc = grpc.ServiceDesc{
HandlerType: (*HeadscaleServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetNamespace",
Handler: _HeadscaleService_GetNamespace_Handler,
MethodName: "GetUser",
Handler: _HeadscaleService_GetUser_Handler,
},
{
MethodName: "CreateNamespace",
Handler: _HeadscaleService_CreateNamespace_Handler,
MethodName: "CreateUser",
Handler: _HeadscaleService_CreateUser_Handler,
},
{
MethodName: "RenameNamespace",
Handler: _HeadscaleService_RenameNamespace_Handler,
MethodName: "RenameUser",
Handler: _HeadscaleService_RenameUser_Handler,
},
{
MethodName: "DeleteNamespace",
Handler: _HeadscaleService_DeleteNamespace_Handler,
MethodName: "DeleteUser",
Handler: _HeadscaleService_DeleteUser_Handler,
},
{
MethodName: "ListNamespaces",
Handler: _HeadscaleService_ListNamespaces_Handler,
MethodName: "ListUsers",
Handler: _HeadscaleService_ListUsers_Handler,
},
{
MethodName: "CreatePreAuthKey",
@@ -925,6 +957,10 @@ var HeadscaleService_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetMachineRoutes",
Handler: _HeadscaleService_GetMachineRoutes_Handler,
},
{
MethodName: "DeleteRoute",
Handler: _HeadscaleService_DeleteRoute_Handler,
},
{
MethodName: "CreateApiKey",
Handler: _HeadscaleService_CreateApiKey_Handler,
+158 -162
View File
@@ -84,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"`
Namespace *Namespace `protobuf:"bytes,7,opt,name=namespace,proto3" json:"namespace,omitempty"`
User *User `protobuf:"bytes,7,opt,name=user,proto3" json:"user,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"`
@@ -172,9 +172,9 @@ func (x *Machine) GetName() string {
return ""
}
func (x *Machine) GetNamespace() *Namespace {
func (x *Machine) GetUser() *User {
if x != nil {
return x.Namespace
return x.User
}
return nil
}
@@ -261,8 +261,8 @@ type RegisterMachineRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
}
func (x *RegisterMachineRequest) Reset() {
@@ -297,9 +297,9 @@ func (*RegisterMachineRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_machine_proto_rawDescGZIP(), []int{1}
}
func (x *RegisterMachineRequest) GetNamespace() string {
func (x *RegisterMachineRequest) GetUser() string {
if x != nil {
return x.Namespace
return x.User
}
return ""
}
@@ -840,7 +840,7 @@ type ListMachinesRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
}
func (x *ListMachinesRequest) Reset() {
@@ -875,9 +875,9 @@ func (*ListMachinesRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_machine_proto_rawDescGZIP(), []int{13}
}
func (x *ListMachinesRequest) GetNamespace() string {
func (x *ListMachinesRequest) GetUser() string {
if x != nil {
return x.Namespace
return x.User
}
return ""
}
@@ -935,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"`
Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"`
User string `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"`
}
func (x *MoveMachineRequest) Reset() {
@@ -977,9 +977,9 @@ func (x *MoveMachineRequest) GetMachineId() uint64 {
return 0
}
func (x *MoveMachineRequest) GetNamespace() string {
func (x *MoveMachineRequest) GetUser() string {
if x != nil {
return x.Namespace
return x.User
}
return ""
}
@@ -1036,10 +1036,10 @@ type DebugCreateMachineRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
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"`
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"`
}
func (x *DebugCreateMachineRequest) Reset() {
@@ -1074,9 +1074,9 @@ func (*DebugCreateMachineRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_machine_proto_rawDescGZIP(), []int{17}
}
func (x *DebugCreateMachineRequest) GetNamespace() string {
func (x *DebugCreateMachineRequest) GetUser() string {
if x != nil {
return x.Namespace
return x.User
}
return ""
}
@@ -1156,149 +1156,145 @@ 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, 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, 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,
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, 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,
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,
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,
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, 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,
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,
}
var (
@@ -1336,12 +1332,12 @@ var file_headscale_v1_machine_proto_goTypes = []interface{}{
(*MoveMachineResponse)(nil), // 17: headscale.v1.MoveMachineResponse
(*DebugCreateMachineRequest)(nil), // 18: headscale.v1.DebugCreateMachineRequest
(*DebugCreateMachineResponse)(nil), // 19: headscale.v1.DebugCreateMachineResponse
(*Namespace)(nil), // 20: headscale.v1.Namespace
(*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_depIdxs = []int32{
20, // 0: headscale.v1.Machine.namespace:type_name -> headscale.v1.Namespace
20, // 0: headscale.v1.Machine.user:type_name -> headscale.v1.User
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
@@ -1368,7 +1364,7 @@ func file_headscale_v1_machine_proto_init() {
if File_headscale_v1_machine_proto != nil {
return
}
file_headscale_v1_namespace_proto_init()
file_headscale_v1_user_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{} {
-801
View File
@@ -1,801 +0,0 @@
// 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
}
+67 -69
View File
@@ -26,7 +26,7 @@ type PreAuthKey struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,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"`
@@ -69,9 +69,9 @@ func (*PreAuthKey) Descriptor() ([]byte, []int) {
return file_headscale_v1_preauthkey_proto_rawDescGZIP(), []int{0}
}
func (x *PreAuthKey) GetNamespace() string {
func (x *PreAuthKey) GetUser() string {
if x != nil {
return x.Namespace
return x.User
}
return ""
}
@@ -137,7 +137,7 @@ type CreatePreAuthKeyRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,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"`
@@ -176,9 +176,9 @@ func (*CreatePreAuthKeyRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_preauthkey_proto_rawDescGZIP(), []int{1}
}
func (x *CreatePreAuthKeyRequest) GetNamespace() string {
func (x *CreatePreAuthKeyRequest) GetUser() string {
if x != nil {
return x.Namespace
return x.User
}
return ""
}
@@ -263,8 +263,8 @@ type ExpirePreAuthKeyRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
}
func (x *ExpirePreAuthKeyRequest) Reset() {
@@ -299,9 +299,9 @@ func (*ExpirePreAuthKeyRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_preauthkey_proto_rawDescGZIP(), []int{3}
}
func (x *ExpirePreAuthKeyRequest) GetNamespace() string {
func (x *ExpirePreAuthKeyRequest) GetUser() string {
if x != nil {
return x.Namespace
return x.User
}
return ""
}
@@ -356,7 +356,7 @@ type ListPreAuthKeysRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
}
func (x *ListPreAuthKeysRequest) Reset() {
@@ -391,9 +391,9 @@ func (*ListPreAuthKeysRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_preauthkey_proto_rawDescGZIP(), []int{5}
}
func (x *ListPreAuthKeysRequest) GetNamespace() string {
func (x *ListPreAuthKeysRequest) GetUser() string {
if x != nil {
return x.Namespace
return x.User
}
return ""
}
@@ -452,63 +452,61 @@ 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, 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,
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,
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, 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,
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,
}
var (
+128 -13
View File
@@ -481,6 +481,91 @@ func (x *GetMachineRoutesResponse) GetRoutes() []*Route {
return nil
}
type DeleteRouteRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
RouteId uint64 `protobuf:"varint,1,opt,name=route_id,json=routeId,proto3" json:"route_id,omitempty"`
}
func (x *DeleteRouteRequest) Reset() {
*x = DeleteRouteRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_routes_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteRouteRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteRouteRequest) ProtoMessage() {}
func (x *DeleteRouteRequest) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_routes_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 DeleteRouteRequest.ProtoReflect.Descriptor instead.
func (*DeleteRouteRequest) Descriptor() ([]byte, []int) {
return file_headscale_v1_routes_proto_rawDescGZIP(), []int{9}
}
func (x *DeleteRouteRequest) GetRouteId() uint64 {
if x != nil {
return x.RouteId
}
return 0
}
type DeleteRouteResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *DeleteRouteResponse) Reset() {
*x = DeleteRouteResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_headscale_v1_routes_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteRouteResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteRouteResponse) ProtoMessage() {}
func (x *DeleteRouteResponse) ProtoReflect() protoreflect.Message {
mi := &file_headscale_v1_routes_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 DeleteRouteResponse.ProtoReflect.Descriptor instead.
func (*DeleteRouteResponse) Descriptor() ([]byte, []int) {
return file_headscale_v1_routes_proto_rawDescGZIP(), []int{10}
}
var File_headscale_v1_routes_proto protoreflect.FileDescriptor
var file_headscale_v1_routes_proto_rawDesc = []byte{
@@ -535,11 +620,15 @@ var file_headscale_v1_routes_proto_rawDesc = []byte{
0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x2b, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x13, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 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,
0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0x2f,
0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x22,
0x15, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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 (
@@ -554,7 +643,7 @@ 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)
var file_headscale_v1_routes_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_headscale_v1_routes_proto_goTypes = []interface{}{
(*Route)(nil), // 0: headscale.v1.Route
(*GetRoutesRequest)(nil), // 1: headscale.v1.GetRoutesRequest
@@ -565,14 +654,16 @@ var file_headscale_v1_routes_proto_goTypes = []interface{}{
(*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
(*DeleteRouteRequest)(nil), // 9: headscale.v1.DeleteRouteRequest
(*DeleteRouteResponse)(nil), // 10: headscale.v1.DeleteRouteResponse
(*Machine)(nil), // 11: headscale.v1.Machine
(*timestamppb.Timestamp)(nil), // 12: 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
10, // 2: headscale.v1.Route.updated_at:type_name -> google.protobuf.Timestamp
10, // 3: headscale.v1.Route.deleted_at:type_name -> google.protobuf.Timestamp
11, // 0: headscale.v1.Route.machine:type_name -> headscale.v1.Machine
12, // 1: headscale.v1.Route.created_at:type_name -> google.protobuf.Timestamp
12, // 2: headscale.v1.Route.updated_at:type_name -> google.protobuf.Timestamp
12, // 3: headscale.v1.Route.deleted_at:type_name -> google.protobuf.Timestamp
0, // 4: headscale.v1.GetRoutesResponse.routes:type_name -> headscale.v1.Route
0, // 5: headscale.v1.GetMachineRoutesResponse.routes:type_name -> headscale.v1.Route
6, // [6:6] is the sub-list for method output_type
@@ -697,6 +788,30 @@ func file_headscale_v1_routes_proto_init() {
return nil
}
}
file_headscale_v1_routes_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteRouteRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_headscale_v1_routes_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteRouteResponse); 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{
@@ -704,7 +819,7 @@ func file_headscale_v1_routes_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_headscale_v1_routes_proto_rawDesc,
NumEnums: 0,
NumMessages: 9,
NumMessages: 11,
NumExtensions: 0,
NumServices: 0,
},
+794
View File
@@ -0,0 +1,794 @@
// 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 (
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 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)
var 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
}
+253 -219
View File
@@ -153,7 +153,7 @@
},
"parameters": [
{
"name": "namespace",
"name": "user",
"in": "query",
"required": false,
"type": "string"
@@ -183,7 +183,7 @@
},
"parameters": [
{
"name": "namespace",
"name": "user",
"in": "query",
"required": false,
"type": "string"
@@ -291,43 +291,6 @@
]
}
},
"/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",
@@ -443,34 +406,14 @@
]
}
},
"/api/v1/namespace": {
"get": {
"operationId": "HeadscaleService_ListNamespaces",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1ListNamespacesResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"tags": [
"HeadscaleService"
]
},
"/api/v1/machine/{machineId}/user": {
"post": {
"operationId": "HeadscaleService_CreateNamespace",
"operationId": "HeadscaleService_MoveMachine",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1CreateNamespaceResponse"
"$ref": "#/definitions/v1MoveMachineResponse"
}
},
"default": {
@@ -482,106 +425,16 @@
},
"parameters": [
{
"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",
"name": "machineId",
"in": "path",
"required": true,
"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"
"type": "string",
"format": "uint64"
},
{
"name": "newName",
"in": "path",
"required": true,
"name": "user",
"in": "query",
"required": false,
"type": "string"
}
],
@@ -609,7 +462,7 @@
},
"parameters": [
{
"name": "namespace",
"name": "user",
"in": "query",
"required": false,
"type": "string"
@@ -706,6 +559,37 @@
]
}
},
"/api/v1/routes/{routeId}": {
"delete": {
"operationId": "HeadscaleService_DeleteRoute",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v1DeleteRouteResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "routeId",
"in": "path",
"required": true,
"type": "string",
"format": "uint64"
}
],
"tags": [
"HeadscaleService"
]
}
},
"/api/v1/routes/{routeId}/disable": {
"post": {
"operationId": "HeadscaleService_DisableRoute",
@@ -767,6 +651,153 @@
"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,26 +869,10 @@
}
}
},
"v1CreateNamespaceRequest": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
},
"v1CreateNamespaceResponse": {
"type": "object",
"properties": {
"namespace": {
"$ref": "#/definitions/v1Namespace"
}
}
},
"v1CreatePreAuthKeyRequest": {
"type": "object",
"properties": {
"namespace": {
"user": {
"type": "string"
},
"reusable": {
@@ -886,10 +901,26 @@
}
}
},
"v1CreateUserRequest": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
},
"v1CreateUserResponse": {
"type": "object",
"properties": {
"user": {
"$ref": "#/definitions/v1User"
}
}
},
"v1DebugCreateMachineRequest": {
"type": "object",
"properties": {
"namespace": {
"user": {
"type": "string"
},
"key": {
@@ -917,7 +948,10 @@
"v1DeleteMachineResponse": {
"type": "object"
},
"v1DeleteNamespaceResponse": {
"v1DeleteRouteResponse": {
"type": "object"
},
"v1DeleteUserResponse": {
"type": "object"
},
"v1DisableRouteResponse": {
@@ -948,7 +982,7 @@
"v1ExpirePreAuthKeyRequest": {
"type": "object",
"properties": {
"namespace": {
"user": {
"type": "string"
},
"key": {
@@ -978,14 +1012,6 @@
}
}
},
"v1GetNamespaceResponse": {
"type": "object",
"properties": {
"namespace": {
"$ref": "#/definitions/v1Namespace"
}
}
},
"v1GetRoutesResponse": {
"type": "object",
"properties": {
@@ -997,6 +1023,14 @@
}
}
},
"v1GetUserResponse": {
"type": "object",
"properties": {
"user": {
"$ref": "#/definitions/v1User"
}
}
},
"v1ListApiKeysResponse": {
"type": "object",
"properties": {
@@ -1019,17 +1053,6 @@
}
}
},
"v1ListNamespacesResponse": {
"type": "object",
"properties": {
"namespaces": {
"type": "array",
"items": {
"$ref": "#/definitions/v1Namespace"
}
}
}
},
"v1ListPreAuthKeysResponse": {
"type": "object",
"properties": {
@@ -1041,6 +1064,17 @@
}
}
},
"v1ListUsersResponse": {
"type": "object",
"properties": {
"users": {
"type": "array",
"items": {
"$ref": "#/definitions/v1User"
}
}
}
},
"v1Machine": {
"type": "object",
"properties": {
@@ -1066,8 +1100,8 @@
"name": {
"type": "string"
},
"namespace": {
"$ref": "#/definitions/v1Namespace"
"user": {
"$ref": "#/definitions/v1User"
},
"lastSeen": {
"type": "string",
@@ -1125,25 +1159,10 @@
}
}
},
"v1Namespace": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"createdAt": {
"type": "string",
"format": "date-time"
}
}
},
"v1PreAuthKey": {
"type": "object",
"properties": {
"namespace": {
"user": {
"type": "string"
},
"id": {
@@ -1203,11 +1222,11 @@
}
}
},
"v1RenameNamespaceResponse": {
"v1RenameUserResponse": {
"type": "object",
"properties": {
"namespace": {
"$ref": "#/definitions/v1Namespace"
"user": {
"$ref": "#/definitions/v1User"
}
}
},
@@ -1254,6 +1273,21 @@
"$ref": "#/definitions/v1Machine"
}
}
},
"v1User": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"createdAt": {
"type": "string",
"format": "date-time"
}
}
}
}
}
@@ -1,7 +1,7 @@
{
"swagger": "2.0",
"info": {
"title": "headscale/v1/namespace.proto",
"title": "headscale/v1/user.proto",
"version": "version not set"
},
"consumes": [
+57 -55
View File
@@ -6,50 +6,52 @@ require (
github.com/AlecAivazis/survey/v2 v2.3.6
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/coreos/go-oidc/v3 v3.5.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
github.com/gofrs/uuid v4.3.1+incompatible
github.com/glebarez/sqlite v1.7.0
github.com/gofrs/uuid/v5 v5.0.0
github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.14.0
github.com/klauspost/compress v1.15.12
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.1
github.com/klauspost/compress v1.15.15
github.com/oauth2-proxy/mockoidc v0.0.0-20220308204021-b9169deeb282
github.com/ory/dockertest/v3 v3.9.1
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/philip-bui/grpc-zerolog v1.0.1
github.com/prometheus/client_golang v1.14.0
github.com/prometheus/common v0.37.0
github.com/pterm/pterm v0.12.50
github.com/prometheus/common v0.40.0
github.com/pterm/pterm v0.12.54
github.com/puzpuzpuz/xsync/v2 v2.4.0
github.com/rs/zerolog v1.28.0
github.com/rs/zerolog v1.29.0
github.com/samber/lo v1.37.0
github.com/spf13/cobra v1.6.1
github.com/spf13/viper v1.14.0
github.com/stretchr/testify v1.8.1
github.com/tailscale/hujson v0.0.0-20220630195928-54599719472f
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.2
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a
github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e
go4.org/netipx v0.0.0-20220925034521-797b0c90d8ab
golang.org/x/crypto v0.3.0
golang.org/x/net v0.2.0
golang.org/x/oauth2 v0.2.0
go4.org/netipx v0.0.0-20230125063823-8449b0a6169f
golang.org/x/crypto v0.6.0
golang.org/x/net v0.7.0
golang.org/x/oauth2 v0.5.0
golang.org/x/sync v0.1.0
google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd
google.golang.org/grpc v1.51.0
google.golang.org/genproto v0.0.0-20230223222841-637eb2293923
google.golang.org/grpc v1.53.0
google.golang.org/protobuf v1.28.1
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/postgres v1.4.5
gorm.io/gorm v1.24.2
tailscale.com v1.34.0
gorm.io/driver/postgres v1.4.8
gorm.io/gorm v1.24.5
tailscale.com v1.36.2
)
require (
atomicgo.dev/cursor v0.1.1 // indirect
atomicgo.dev/keyboard v0.2.8 // indirect
atomicgo.dev/keyboard v0.2.9 // indirect
filippo.io/edwards25519 v1.0.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/akutz/memconn v0.1.0 // indirect
@@ -58,16 +60,18 @@ 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/cli v23.0.1+incompatible // indirect
github.com/docker/docker v23.0.1+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/glebarez/go-sqlite v1.19.5 // indirect
github.com/glebarez/go-sqlite v1.20.3 // indirect
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang/glog v1.0.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.9 // indirect
@@ -81,71 +85,69 @@ require (
github.com/hdevalence/ed25519consensus v0.1.0 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.13.0 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.1 // indirect
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jackc/pgtype v1.13.0 // indirect
github.com/jackc/pgx/v4 v4.17.2 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.3.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/josharian/native v1.0.0 // indirect
github.com/jsimonetti/rtnetlink v1.3.0 // indirect
github.com/josharian/native v1.1.0 // indirect
github.com/jsimonetti/rtnetlink v1.3.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/lib/pq v1.10.7 // indirect
github.com/lithammer/fuzzysearch v1.1.5 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mdlayher/netlink v1.7.0 // indirect
github.com/mdlayher/netlink v1.7.1 // indirect
github.com/mdlayher/socket v0.4.0 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/mitchellh/go-ps v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/term v0.0.0-20221128092401-c43b287e0e0f // indirect
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc2 // indirect
github.com/opencontainers/runc v1.1.4 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20220927061507-ef77025ab5aa // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/afero v1.9.4 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.4.1 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go4.org/mem v0.0.0-20220726221520-4f986261bf13 // indirect
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/term v0.2.0 // indirect
golang.org/x/text v0.5.0 // indirect
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/term v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.3.0 // indirect
golang.org/x/tools v0.6.0 // indirect
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
google.golang.org/appengine v1.6.7 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
modernc.org/libc v1.21.5 // indirect
modernc.org/libc v1.22.2 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.5.0 // indirect
modernc.org/sqlite v1.20.0 // indirect
modernc.org/sqlite v1.20.3 // indirect
nhooyr.io/websocket v1.8.7 // indirect
)
+124 -506
View File
File diff suppressed because it is too large Load Diff
+52 -40
View File
@@ -26,76 +26,76 @@ func newHeadscaleV1APIServer(h *Headscale) v1.HeadscaleServiceServer {
}
}
func (api headscaleV1APIServer) GetNamespace(
func (api headscaleV1APIServer) GetUser(
ctx context.Context,
request *v1.GetNamespaceRequest,
) (*v1.GetNamespaceResponse, error) {
namespace, err := api.h.GetNamespace(request.GetName())
request *v1.GetUserRequest,
) (*v1.GetUserResponse, error) {
user, err := api.h.GetUser(request.GetName())
if err != nil {
return nil, err
}
return &v1.GetNamespaceResponse{Namespace: namespace.toProto()}, nil
return &v1.GetUserResponse{User: user.toProto()}, nil
}
func (api headscaleV1APIServer) CreateNamespace(
func (api headscaleV1APIServer) CreateUser(
ctx context.Context,
request *v1.CreateNamespaceRequest,
) (*v1.CreateNamespaceResponse, error) {
namespace, err := api.h.CreateNamespace(request.GetName())
request *v1.CreateUserRequest,
) (*v1.CreateUserResponse, error) {
user, err := api.h.CreateUser(request.GetName())
if err != nil {
return nil, err
}
return &v1.CreateNamespaceResponse{Namespace: namespace.toProto()}, nil
return &v1.CreateUserResponse{User: user.toProto()}, nil
}
func (api headscaleV1APIServer) RenameNamespace(
func (api headscaleV1APIServer) RenameUser(
ctx context.Context,
request *v1.RenameNamespaceRequest,
) (*v1.RenameNamespaceResponse, error) {
err := api.h.RenameNamespace(request.GetOldName(), request.GetNewName())
request *v1.RenameUserRequest,
) (*v1.RenameUserResponse, error) {
err := api.h.RenameUser(request.GetOldName(), request.GetNewName())
if err != nil {
return nil, err
}
namespace, err := api.h.GetNamespace(request.GetNewName())
user, err := api.h.GetUser(request.GetNewName())
if err != nil {
return nil, err
}
return &v1.RenameNamespaceResponse{Namespace: namespace.toProto()}, nil
return &v1.RenameUserResponse{User: user.toProto()}, nil
}
func (api headscaleV1APIServer) DeleteNamespace(
func (api headscaleV1APIServer) DeleteUser(
ctx context.Context,
request *v1.DeleteNamespaceRequest,
) (*v1.DeleteNamespaceResponse, error) {
err := api.h.DestroyNamespace(request.GetName())
request *v1.DeleteUserRequest,
) (*v1.DeleteUserResponse, error) {
err := api.h.DestroyUser(request.GetName())
if err != nil {
return nil, err
}
return &v1.DeleteNamespaceResponse{}, nil
return &v1.DeleteUserResponse{}, nil
}
func (api headscaleV1APIServer) ListNamespaces(
func (api headscaleV1APIServer) ListUsers(
ctx context.Context,
request *v1.ListNamespacesRequest,
) (*v1.ListNamespacesResponse, error) {
namespaces, err := api.h.ListNamespaces()
request *v1.ListUsersRequest,
) (*v1.ListUsersResponse, error) {
users, err := api.h.ListUsers()
if err != nil {
return nil, err
}
response := make([]*v1.Namespace, len(namespaces))
for index, namespace := range namespaces {
response[index] = namespace.toProto()
response := make([]*v1.User, len(users))
for index, user := range users {
response[index] = user.toProto()
}
log.Trace().Caller().Interface("namespaces", response).Msg("")
log.Trace().Caller().Interface("users", response).Msg("")
return &v1.ListNamespacesResponse{Namespaces: response}, nil
return &v1.ListUsersResponse{Users: response}, nil
}
func (api headscaleV1APIServer) CreatePreAuthKey(
@@ -117,7 +117,7 @@ func (api headscaleV1APIServer) CreatePreAuthKey(
}
preAuthKey, err := api.h.CreatePreAuthKey(
request.GetNamespace(),
request.GetUser(),
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.GetNamespace(), request.Key)
preAuthKey, err := api.h.GetPreAuthKey(request.GetUser(), 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.GetNamespace())
preAuthKeys, err := api.h.ListPreAuthKeys(request.GetUser())
if err != nil {
return nil, err
}
@@ -169,13 +169,13 @@ func (api headscaleV1APIServer) RegisterMachine(
request *v1.RegisterMachineRequest,
) (*v1.RegisterMachineResponse, error) {
log.Trace().
Str("namespace", request.GetNamespace()).
Str("user", request.GetUser()).
Str("node_key", request.GetKey()).
Msg("Registering machine")
machine, err := api.h.RegisterMachineFromAuthCallback(
request.GetKey(),
request.GetNamespace(),
request.GetUser(),
nil,
RegisterMethodCLI,
)
@@ -313,8 +313,8 @@ func (api headscaleV1APIServer) ListMachines(
ctx context.Context,
request *v1.ListMachinesRequest,
) (*v1.ListMachinesResponse, error) {
if request.GetNamespace() != "" {
machines, err := api.h.ListMachinesInNamespace(request.GetNamespace())
if request.GetUser() != "" {
machines, err := api.h.ListMachinesByUser(request.GetUser())
if err != nil {
return nil, err
}
@@ -357,7 +357,7 @@ func (api headscaleV1APIServer) MoveMachine(
return nil, err
}
err = api.h.SetMachineNamespace(machine, request.GetNamespace())
err = api.h.SetMachineUser(machine, request.GetUser())
if err != nil {
return nil, err
}
@@ -422,6 +422,18 @@ func (api headscaleV1APIServer) GetMachineRoutes(
}, nil
}
func (api headscaleV1APIServer) DeleteRoute(
ctx context.Context,
request *v1.DeleteRouteRequest,
) (*v1.DeleteRouteResponse, error) {
err := api.h.DeleteRoute(request.GetRouteId())
if err != nil {
return nil, err
}
return &v1.DeleteRouteResponse{}, nil
}
func (api headscaleV1APIServer) CreateApiKey(
ctx context.Context,
request *v1.CreateApiKeyRequest,
@@ -483,7 +495,7 @@ func (api headscaleV1APIServer) DebugCreateMachine(
ctx context.Context,
request *v1.DebugCreateMachineRequest,
) (*v1.DebugCreateMachineResponse, error) {
namespace, err := api.h.GetNamespace(request.GetNamespace())
user, err := api.h.GetUser(request.GetUser())
if err != nil {
return nil, err
}
@@ -514,7 +526,7 @@ func (api headscaleV1APIServer) DebugCreateMachine(
MachineKey: request.GetKey(),
Hostname: request.GetName(),
GivenName: givenName,
Namespace: *namespace,
User: *user,
Expiry: &time.Time{},
LastSeen: &time.Time{},
+11 -2
View File
@@ -9,8 +9,17 @@ Headscale's test framework and the current set of scenarios are defined in this
Tests are located in files ending with `_test.go` and the framework are located in the rest.
## Running integration tests locally
The easiest way to run tests locally is to use `[act](INSERT LINK)`, a local GitHub Actions runner:
```
act pull_request -W .github/workflows/test-integration-v2-TestPingAllByIP.yaml
```
Alternatively, the `docker run` command in each GitHub workflow file can be used.
## 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
Each test currently runs as a separate workflows in GitHub actions, to add new test, run
`go generate` inside `../cmd/gh-action-integration-generator/` and commit the result.
+280
View File
@@ -0,0 +1,280 @@
package integration
import (
"fmt"
"testing"
"github.com/juanfont/headscale"
"github.com/juanfont/headscale/integration/hsic"
"github.com/juanfont/headscale/integration/tsic"
"github.com/stretchr/testify/assert"
)
const numberOfTestClients = 2
func aclScenario(t *testing.T, policy headscale.ACLPolicy) *Scenario {
t.Helper()
scenario, err := NewScenario()
assert.NoError(t, err)
spec := map[string]int{
"user1": numberOfTestClients,
"user2": numberOfTestClients,
}
err = scenario.CreateHeadscaleEnv(spec,
[]tsic.Option{
tsic.WithDockerEntrypoint([]string{
"/bin/bash",
"-c",
"/bin/sleep 3 ; update-ca-certificates ; python3 -m http.server 80 & tailscaled --tun=tsdev",
}),
tsic.WithDockerWorkdir("/"),
},
hsic.WithACLPolicy(&policy),
hsic.WithTestName("acldenyallping"),
)
assert.NoError(t, err)
// allClients, err := scenario.ListTailscaleClients()
// assert.NoError(t, err)
err = scenario.WaitForTailscaleSync()
assert.NoError(t, err)
_, err = scenario.ListTailscaleClientsFQDNs()
assert.NoError(t, err)
return scenario
}
// This tests a different ACL mechanism, if a host _cannot_ connect
// to another node at all based on ACL, it should just not be part
// of the NetMap sent to the host. This is slightly different than
// the other tests as we can just check if the hosts are present
// or not.
func TestACLHostsInNetMapTable(t *testing.T) {
IntegrationSkip(t)
// NOTE: All want cases currently checks the
// total count of expected peers, this would
// typically be the client count of the users
// they can access minus one (them self).
tests := map[string]struct {
users map[string]int
policy headscale.ACLPolicy
want map[string]int
}{
// Test that when we have no ACL, each client netmap has
// the amount of peers of the total amount of clients
"base-acls": {
users: map[string]int{
"user1": 2,
"user2": 2,
},
policy: headscale.ACLPolicy{
ACLs: []headscale.ACL{
{
Action: "accept",
Sources: []string{"*"},
Destinations: []string{"*:*"},
},
},
}, want: map[string]int{
"user1": 3, // ns1 + ns2
"user2": 3, // ns2 + ns1
},
},
// Test that when we have two users, which cannot see
// eachother, each node has only the number of pairs from
// their own user.
"two-isolated-users": {
users: map[string]int{
"user1": 2,
"user2": 2,
},
policy: headscale.ACLPolicy{
ACLs: []headscale.ACL{
{
Action: "accept",
Sources: []string{"user1"},
Destinations: []string{"user1:*"},
},
{
Action: "accept",
Sources: []string{"user2"},
Destinations: []string{"user2:*"},
},
},
}, want: map[string]int{
"user1": 1,
"user2": 1,
},
},
// Test that when we have two users, with ACLs and they
// are restricted to a single port, nodes are still present
// in the netmap.
"two-restricted-present-in-netmap": {
users: map[string]int{
"user1": 2,
"user2": 2,
},
policy: headscale.ACLPolicy{
ACLs: []headscale.ACL{
{
Action: "accept",
Sources: []string{"user1"},
Destinations: []string{"user1:22"},
},
{
Action: "accept",
Sources: []string{"user2"},
Destinations: []string{"user2:22"},
},
{
Action: "accept",
Sources: []string{"user1"},
Destinations: []string{"user2:22"},
},
{
Action: "accept",
Sources: []string{"user2"},
Destinations: []string{"user1:22"},
},
},
}, want: map[string]int{
"user1": 3,
"user2": 3,
},
},
// Test that when we have two users, that are isolated,
// but one can see the others, we have the appropriate number
// of peers. This will still result in all the peers as we
// need them present on the other side for the "return path".
"two-ns-one-isolated": {
users: map[string]int{
"user1": 2,
"user2": 2,
},
policy: headscale.ACLPolicy{
ACLs: []headscale.ACL{
{
Action: "accept",
Sources: []string{"user1"},
Destinations: []string{"user1:*"},
},
{
Action: "accept",
Sources: []string{"user2"},
Destinations: []string{"user2:*"},
},
{
Action: "accept",
Sources: []string{"user1"},
Destinations: []string{"user2:*"},
},
},
}, want: map[string]int{
"user1": 3, // ns1 + ns2
"user2": 3, // ns1 + ns2 (return path)
},
},
}
for name, testCase := range tests {
t.Run(name, func(t *testing.T) {
scenario, err := NewScenario()
assert.NoError(t, err)
spec := testCase.users
err = scenario.CreateHeadscaleEnv(spec,
[]tsic.Option{},
hsic.WithACLPolicy(&testCase.policy),
// hsic.WithTestName(fmt.Sprintf("aclinnetmap%s", name)),
)
assert.NoError(t, err)
allClients, err := scenario.ListTailscaleClients()
assert.NoError(t, err)
err = scenario.WaitForTailscaleSync()
assert.NoError(t, err)
// allHostnames, err := scenario.ListTailscaleClientsFQDNs()
// assert.NoError(t, err)
for _, client := range allClients {
status, err := client.Status()
assert.NoError(t, err)
user := status.User[status.Self.UserID].LoginName
assert.Equal(t, (testCase.want[user]), len(status.Peer))
}
err = scenario.Shutdown()
assert.NoError(t, err)
})
}
}
// Test to confirm that we can use user:80 from one user
// This should make the node appear in the peer list, but
// disallow ping.
// This ACL will not allow user1 access its own machines.
// Reported: https://github.com/juanfont/headscale/issues/699
func TestACLAllowUser80Dst(t *testing.T) {
IntegrationSkip(t)
scenario := aclScenario(t,
headscale.ACLPolicy{
ACLs: []headscale.ACL{
{
Action: "accept",
Sources: []string{"user1"},
Destinations: []string{"user2:80"},
},
},
},
)
user1Clients, err := scenario.ListTailscaleClients("user1")
assert.NoError(t, err)
user2Clients, err := scenario.ListTailscaleClients("user2")
assert.NoError(t, err)
// Test that user1 can visit all user2
for _, client := range user1Clients {
for _, peer := range user2Clients {
fqdn, err := peer.FQDN()
assert.NoError(t, err)
url := fmt.Sprintf("http://%s/etc/hostname", fqdn)
t.Logf("url from %s to %s", client.Hostname(), url)
result, err := client.Curl(url)
assert.Len(t, result, 13)
assert.NoError(t, err)
}
}
// Test that user2 _cannot_ visit user1
for _, client := range user2Clients {
for _, peer := range user1Clients {
fqdn, err := peer.FQDN()
assert.NoError(t, err)
url := fmt.Sprintf("http://%s/etc/hostname", fqdn)
t.Logf("url from %s to %s", client.Hostname(), url)
result, err := client.Curl(url)
assert.Empty(t, result)
assert.Error(t, err)
}
}
err = scenario.Shutdown()
assert.NoError(t, err)
}
+37 -42
View File
@@ -19,6 +19,7 @@ import (
"github.com/juanfont/headscale/integration/hsic"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
"github.com/samber/lo"
)
const (
@@ -49,7 +50,7 @@ func TestOIDCAuthenticationPingAll(t *testing.T) {
}
spec := map[string]int{
"namespace1": len(TailscaleVersions),
"user1": len(TailscaleVersions),
}
oidcConfig, err := scenario.runMockOIDC(defaultAccessTTL)
@@ -91,7 +92,11 @@ func TestOIDCAuthenticationPingAll(t *testing.T) {
t.Errorf("failed wait for tailscale clients to be in sync: %s", err)
}
success := pingAll(t, allClients, allIps)
allAddrs := lo.Map(allIps, func(x netip.Addr, index int) string {
return x.String()
})
success := pingAllHelper(t, allClients, allAddrs)
t.Logf("%d successful pings out of %d", success, len(allClients)*len(allIps))
err = scenario.Shutdown()
@@ -100,7 +105,7 @@ func TestOIDCAuthenticationPingAll(t *testing.T) {
}
}
func TestOIDCExpireNodes(t *testing.T) {
func TestOIDCExpireNodesBasedOnTokenExpiry(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
@@ -116,7 +121,7 @@ func TestOIDCExpireNodes(t *testing.T) {
}
spec := map[string]int{
"namespace1": len(TailscaleVersions),
"user1": len(TailscaleVersions),
}
oidcConfig, err := scenario.runMockOIDC(shortAccessTTL)
@@ -125,10 +130,11 @@ func TestOIDCExpireNodes(t *testing.T) {
}
oidcMap := map[string]string{
"HEADSCALE_OIDC_ISSUER": oidcConfig.Issuer,
"HEADSCALE_OIDC_CLIENT_ID": oidcConfig.ClientID,
"HEADSCALE_OIDC_CLIENT_SECRET": oidcConfig.ClientSecret,
"HEADSCALE_OIDC_STRIP_EMAIL_DOMAIN": fmt.Sprintf("%t", oidcConfig.StripEmaildomain),
"HEADSCALE_OIDC_ISSUER": oidcConfig.Issuer,
"HEADSCALE_OIDC_CLIENT_ID": oidcConfig.ClientID,
"HEADSCALE_OIDC_CLIENT_SECRET": oidcConfig.ClientSecret,
"HEADSCALE_OIDC_STRIP_EMAIL_DOMAIN": fmt.Sprintf("%t", oidcConfig.StripEmaildomain),
"HEADSCALE_OIDC_USE_EXPIRY_FROM_TOKEN": "1",
}
err = scenario.CreateHeadscaleEnv(
@@ -156,7 +162,11 @@ func TestOIDCExpireNodes(t *testing.T) {
t.Errorf("failed wait for tailscale clients to be in sync: %s", err)
}
success := pingAll(t, allClients, allIps)
allAddrs := lo.Map(allIps, func(x netip.Addr, index int) string {
return x.String()
})
success := pingAllHelper(t, allClients, allAddrs)
t.Logf("%d successful pings out of %d (before expiry)", success, len(allClients)*len(allIps))
// await all nodes being logged out after OIDC token expiry
@@ -169,7 +179,7 @@ func TestOIDCExpireNodes(t *testing.T) {
}
func (s *AuthOIDCScenario) CreateHeadscaleEnv(
namespaces map[string]int,
users map[string]int,
opts ...hsic.Option,
) error {
headscale, err := s.Headscale(opts...)
@@ -182,19 +192,19 @@ func (s *AuthOIDCScenario) CreateHeadscaleEnv(
return err
}
for namespaceName, clientCount := range namespaces {
log.Printf("creating namespace %s with %d clients", namespaceName, clientCount)
err = s.CreateNamespace(namespaceName)
for userName, clientCount := range users {
log.Printf("creating user %s with %d clients", userName, clientCount)
err = s.CreateUser(userName)
if err != nil {
return err
}
err = s.CreateTailscaleNodesInNamespace(namespaceName, "all", clientCount)
err = s.CreateTailscaleNodesInUser(userName, "all", clientCount)
if err != nil {
return err
}
err = s.runTailscaleUp(namespaceName, headscale.GetEndpoint())
err = s.runTailscaleUp(userName, headscale.GetEndpoint())
if err != nil {
return err
}
@@ -278,7 +288,10 @@ 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))),
Issuer: fmt.Sprintf(
"http://%s/oidc",
net.JoinHostPort(s.mockOIDC.GetIPInNetwork(s.network), strconv.Itoa(port)),
),
ClientID: "superclient",
ClientSecret: "supersecret",
StripEmaildomain: true,
@@ -287,20 +300,20 @@ func (s *AuthOIDCScenario) runMockOIDC(accessTTL time.Duration) (*headscale.OIDC
}
func (s *AuthOIDCScenario) runTailscaleUp(
namespaceStr, loginServer string,
userStr, loginServer string,
) error {
headscale, err := s.Headscale()
if err != nil {
return err
}
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)
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)
go func(c TailscaleClient) {
defer namespace.joinWaitGroup.Done()
defer user.joinWaitGroup.Done()
// TODO(juanfont): error handle this
loginURL, err := c.UpWithLoginURL(loginServer)
@@ -347,30 +360,12 @@ func (s *AuthOIDCScenario) runTailscaleUp(
log.Printf("client %s is ready", client.Hostname())
}
namespace.joinWaitGroup.Wait()
user.joinWaitGroup.Wait()
return nil
}
return fmt.Errorf("failed to up tailscale node: %w", errNoNamespaceAvailable)
}
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", errNoUserAvailable)
}
func (s *AuthOIDCScenario) Shutdown() error {
+42 -57
View File
@@ -13,6 +13,7 @@ import (
"testing"
"github.com/juanfont/headscale/integration/hsic"
"github.com/samber/lo"
)
var errParseAuthPage = errors.New("failed to parse auth page")
@@ -35,8 +36,8 @@ func TestAuthWebFlowAuthenticationPingAll(t *testing.T) {
}
spec := map[string]int{
"namespace1": len(TailscaleVersions),
"namespace2": len(TailscaleVersions),
"user1": len(TailscaleVersions),
"user2": len(TailscaleVersions),
}
err = scenario.CreateHeadscaleEnv(spec, hsic.WithTestName("webauthping"))
@@ -59,18 +60,11 @@ func TestAuthWebFlowAuthenticationPingAll(t *testing.T) {
t.Errorf("failed wait for tailscale clients to be in sync: %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++
}
}
}
allAddrs := lo.Map(allIps, func(x netip.Addr, index int) string {
return x.String()
})
success := pingAllHelper(t, allClients, allAddrs)
t.Logf("%d successful pings out of %d", success, len(allClients)*len(allIps))
err = scenario.Shutdown()
@@ -93,8 +87,8 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
}
spec := map[string]int{
"namespace1": len(TailscaleVersions),
"namespace2": len(TailscaleVersions),
"user1": len(TailscaleVersions),
"user2": len(TailscaleVersions),
}
err = scenario.CreateHeadscaleEnv(spec, hsic.WithTestName("weblogout"))
@@ -117,18 +111,11 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
t.Errorf("failed wait for tailscale clients to be in sync: %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++
}
}
}
allAddrs := lo.Map(allIps, func(x netip.Addr, index int) string {
return x.String()
})
success := pingAllHelper(t, allClients, allAddrs)
t.Logf("%d successful pings out of %d", success, len(allClients)*len(allIps))
clientIPs := make(map[TailscaleClient][]netip.Addr)
@@ -156,8 +143,8 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
t.Errorf("failed to get headscale server: %s", err)
}
for namespaceName := range spec {
err = scenario.runTailscaleUp(namespaceName, headscale.GetEndpoint())
for userName := range spec {
err = scenario.runTailscaleUp(userName, headscale.GetEndpoint())
if err != nil {
t.Errorf("failed to run tailscale up: %s", err)
}
@@ -175,18 +162,11 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
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++
}
}
}
allAddrs = lo.Map(allIps, func(x netip.Addr, index int) string {
return x.String()
})
success = pingAllHelper(t, allClients, allAddrs)
t.Logf("%d successful pings out of %d", success, len(allClients)*len(allIps))
for _, client := range allClients {
@@ -211,7 +191,12 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
}
if !found {
t.Errorf("IPs changed for client %s. Used to be %v now %v", client.Hostname(), clientIPs[client], ips)
t.Errorf(
"IPs changed for client %s. Used to be %v now %v",
client.Hostname(),
clientIPs[client],
ips,
)
}
}
}
@@ -225,7 +210,7 @@ func TestAuthWebFlowLogoutAndRelogin(t *testing.T) {
}
func (s *AuthWebFlowScenario) CreateHeadscaleEnv(
namespaces map[string]int,
users map[string]int,
opts ...hsic.Option,
) error {
headscale, err := s.Headscale(opts...)
@@ -238,19 +223,19 @@ func (s *AuthWebFlowScenario) CreateHeadscaleEnv(
return err
}
for namespaceName, clientCount := range namespaces {
log.Printf("creating namespace %s with %d clients", namespaceName, clientCount)
err = s.CreateNamespace(namespaceName)
for userName, clientCount := range users {
log.Printf("creating user %s with %d clients", userName, clientCount)
err = s.CreateUser(userName)
if err != nil {
return err
}
err = s.CreateTailscaleNodesInNamespace(namespaceName, "all", clientCount)
err = s.CreateTailscaleNodesInUser(userName, "all", clientCount)
if err != nil {
return err
}
err = s.runTailscaleUp(namespaceName, headscale.GetEndpoint())
err = s.runTailscaleUp(userName, headscale.GetEndpoint())
if err != nil {
return err
}
@@ -260,15 +245,15 @@ func (s *AuthWebFlowScenario) CreateHeadscaleEnv(
}
func (s *AuthWebFlowScenario) runTailscaleUp(
namespaceStr, loginServer string,
userStr, 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)
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)
go func(c TailscaleClient) {
defer namespace.joinWaitGroup.Done()
defer user.joinWaitGroup.Done()
// TODO(juanfont): error handle this
loginURL, err := c.UpWithLoginURL(loginServer)
@@ -276,7 +261,7 @@ func (s *AuthWebFlowScenario) runTailscaleUp(
log.Printf("failed to run tailscale up: %s", err)
}
err = s.runHeadscaleRegister(namespaceStr, loginURL)
err = s.runHeadscaleRegister(userStr, loginURL)
if err != nil {
log.Printf("failed to register client: %s", err)
}
@@ -287,15 +272,15 @@ func (s *AuthWebFlowScenario) runTailscaleUp(
log.Printf("error waiting for client %s to be ready: %s", client.Hostname(), err)
}
}
namespace.joinWaitGroup.Wait()
user.joinWaitGroup.Wait()
return nil
}
return fmt.Errorf("failed to up tailscale node: %w", errNoNamespaceAvailable)
return fmt.Errorf("failed to up tailscale node: %w", errNoUserAvailable)
}
func (s *AuthWebFlowScenario) runHeadscaleRegister(namespaceStr string, loginURL *url.URL) error {
func (s *AuthWebFlowScenario) runHeadscaleRegister(userStr string, loginURL *url.URL) error {
headscale, err := s.Headscale()
if err != nil {
return err
@@ -335,7 +320,7 @@ func (s *AuthWebFlowScenario) runHeadscaleRegister(namespaceStr string, loginURL
if headscale, err := s.Headscale(); err == nil {
_, err = headscale.Execute(
[]string{"headscale", "-n", namespaceStr, "nodes", "register", "--key", key},
[]string{"headscale", "nodes", "register", "--user", userStr, "--key", key},
)
if err != nil {
log.Printf("failed to register node: %s", err)
+41 -41
View File
@@ -28,7 +28,7 @@ func executeAndUnmarshal[T any](headscale ControlServer, command []string, resul
return nil
}
func TestNamespaceCommand(t *testing.T) {
func TestUserCommand(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
@@ -36,8 +36,8 @@ func TestNamespaceCommand(t *testing.T) {
assert.NoError(t, err)
spec := map[string]int{
"namespace1": 0,
"namespace2": 0,
"user1": 0,
"user2": 0,
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clins"))
@@ -46,60 +46,60 @@ func TestNamespaceCommand(t *testing.T) {
headscale, err := scenario.Headscale()
assert.NoError(t, err)
var listNamespaces []v1.Namespace
var listUsers []v1.User
err = executeAndUnmarshal(headscale,
[]string{
"headscale",
"namespaces",
"users",
"list",
"--output",
"json",
},
&listNamespaces,
&listUsers,
)
assert.NoError(t, err)
result := []string{listNamespaces[0].Name, listNamespaces[1].Name}
result := []string{listUsers[0].Name, listUsers[1].Name}
sort.Strings(result)
assert.Equal(
t,
[]string{"namespace1", "namespace2"},
[]string{"user1", "user2"},
result,
)
_, err = headscale.Execute(
[]string{
"headscale",
"namespaces",
"users",
"rename",
"--output",
"json",
"namespace2",
"user2",
"newname",
},
)
assert.NoError(t, err)
var listAfterRenameNamespaces []v1.Namespace
var listAfterRenameUsers []v1.User
err = executeAndUnmarshal(headscale,
[]string{
"headscale",
"namespaces",
"users",
"list",
"--output",
"json",
},
&listAfterRenameNamespaces,
&listAfterRenameUsers,
)
assert.NoError(t, err)
result = []string{listAfterRenameNamespaces[0].Name, listAfterRenameNamespaces[1].Name}
result = []string{listAfterRenameUsers[0].Name, listAfterRenameUsers[1].Name}
sort.Strings(result)
assert.Equal(
t,
[]string{"namespace1", "newname"},
[]string{"newname", "user1"},
result,
)
@@ -111,14 +111,14 @@ func TestPreAuthKeyCommand(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
namespace := "preauthkeyspace"
user := "preauthkeyspace"
count := 3
scenario, err := NewScenario()
assert.NoError(t, err)
spec := map[string]int{
namespace: 0,
user: 0,
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipak"))
@@ -137,8 +137,8 @@ func TestPreAuthKeyCommand(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace,
"--user",
user,
"create",
"--reusable",
"--expiration",
@@ -163,8 +163,8 @@ func TestPreAuthKeyCommand(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace,
"--user",
user,
"list",
"--output",
"json",
@@ -216,8 +216,8 @@ func TestPreAuthKeyCommand(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace,
"--user",
user,
"expire",
listedPreAuthKeys[1].Key,
},
@@ -230,8 +230,8 @@ func TestPreAuthKeyCommand(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace,
"--user",
user,
"list",
"--output",
"json",
@@ -252,13 +252,13 @@ func TestPreAuthKeyCommandWithoutExpiry(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
namespace := "pre-auth-key-without-exp-namespace"
user := "pre-auth-key-without-exp-user"
scenario, err := NewScenario()
assert.NoError(t, err)
spec := map[string]int{
namespace: 0,
user: 0,
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipaknaexp"))
@@ -273,8 +273,8 @@ func TestPreAuthKeyCommandWithoutExpiry(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace,
"--user",
user,
"create",
"--reusable",
"--output",
@@ -290,8 +290,8 @@ func TestPreAuthKeyCommandWithoutExpiry(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace,
"--user",
user,
"list",
"--output",
"json",
@@ -317,13 +317,13 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
namespace := "pre-auth-key-reus-ephm-namespace"
user := "pre-auth-key-reus-ephm-user"
scenario, err := NewScenario()
assert.NoError(t, err)
spec := map[string]int{
namespace: 0,
user: 0,
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipakresueeph"))
@@ -338,8 +338,8 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace,
"--user",
user,
"create",
"--reusable=true",
"--output",
@@ -355,8 +355,8 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace,
"--user",
user,
"create",
"--ephemeral=true",
"--output",
@@ -375,8 +375,8 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace,
"--user",
user,
"list",
"--output",
"json",
@@ -396,13 +396,13 @@ func TestEnablingRoutes(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
namespace := "enable-routing"
user := "enable-routing"
scenario, err := NewScenario()
assert.NoError(t, err)
spec := map[string]int{
namespace: 3,
user: 3,
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clienableroute"))
+4 -3
View File
@@ -6,13 +6,14 @@ import (
type ControlServer interface {
Shutdown() error
SaveLog(string) error
Execute(command []string) (string, error)
GetHealthEndpoint() string
GetEndpoint() string
WaitForReady() error
CreateNamespace(namespace string) error
CreateAuthKey(namespace string, reusable bool, ephemeral bool) (*v1.PreAuthKey, error)
ListMachinesInNamespace(namespace string) ([]*v1.Machine, error)
CreateUser(user string) error
CreateAuthKey(user string, reusable bool, ephemeral bool) (*v1.PreAuthKey, error)
ListMachinesInUser(user string) ([]*v1.Machine, error)
GetCert() []byte
GetHostname() string
GetIP() string
+68
View File
@@ -0,0 +1,68 @@
package dockertestutil
import (
"bytes"
"context"
"log"
"os"
"path"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
)
const filePerm = 0o644
func SaveLog(
pool *dockertest.Pool,
resource *dockertest.Resource,
basePath string,
) error {
err := os.MkdirAll(basePath, os.ModePerm)
if err != nil {
return err
}
var stdout bytes.Buffer
var stderr bytes.Buffer
err = pool.Client.Logs(
docker.LogsOptions{
Context: context.TODO(),
Container: resource.Container.ID,
OutputStream: &stdout,
ErrorStream: &stderr,
Tail: "all",
RawTerminal: false,
Stdout: true,
Stderr: true,
Follow: false,
Timestamps: false,
},
)
if err != nil {
return err
}
log.Printf("Saving logs for %s to %s\n", resource.Container.Name, basePath)
err = os.WriteFile(
path.Join(basePath, resource.Container.Name+".stdout.log"),
stdout.Bytes(),
filePerm,
)
if err != nil {
return err
}
err = os.WriteFile(
path.Join(basePath, resource.Container.Name+".stderr.log"),
stderr.Bytes(),
filePerm,
)
if err != nil {
return err
}
return nil
}
+140 -74
View File
@@ -1,15 +1,19 @@
package integration
import (
"encoding/json"
"fmt"
"net/netip"
"strings"
"testing"
"time"
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
"github.com/juanfont/headscale/integration/hsic"
"github.com/juanfont/headscale/integration/tsic"
"github.com/rs/zerolog/log"
"github.com/samber/lo"
"github.com/stretchr/testify/assert"
)
func TestPingAllByIP(t *testing.T) {
@@ -22,8 +26,8 @@ func TestPingAllByIP(t *testing.T) {
}
spec := map[string]int{
"namespace1": len(TailscaleVersions),
"namespace2": len(TailscaleVersions),
"user1": len(TailscaleVersions),
"user2": len(TailscaleVersions),
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("pingallbyip"))
@@ -46,19 +50,11 @@ func TestPingAllByIP(t *testing.T) {
t.Errorf("failed wait for tailscale clients to be in sync: %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++
}
}
}
allAddrs := lo.Map(allIps, func(x netip.Addr, index int) string {
return x.String()
})
success := pingAllHelper(t, allClients, allAddrs)
t.Logf("%d successful pings out of %d", success, len(allClients)*len(allIps))
err = scenario.Shutdown()
@@ -77,8 +73,8 @@ func TestAuthKeyLogoutAndRelogin(t *testing.T) {
}
spec := map[string]int{
"namespace1": len(TailscaleVersions),
"namespace2": len(TailscaleVersions),
"user1": len(TailscaleVersions),
"user2": len(TailscaleVersions),
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("pingallbyip"))
@@ -121,15 +117,15 @@ func TestAuthKeyLogoutAndRelogin(t *testing.T) {
t.Errorf("failed to get headscale server: %s", err)
}
for namespaceName := range spec {
key, err := scenario.CreatePreAuthKey(namespaceName, true, false)
for userName := range spec {
key, err := scenario.CreatePreAuthKey(userName, true, false)
if err != nil {
t.Errorf("failed to create pre-auth key for namespace %s: %s", namespaceName, err)
t.Errorf("failed to create pre-auth key for user %s: %s", userName, err)
}
err = scenario.RunTailscaleUp(namespaceName, headscale.GetEndpoint(), key.GetKey())
err = scenario.RunTailscaleUp(userName, headscale.GetEndpoint(), key.GetKey())
if err != nil {
t.Errorf("failed to run tailscale up for namespace %s: %s", namespaceName, err)
t.Errorf("failed to run tailscale up for user %s: %s", userName, err)
}
}
@@ -148,18 +144,11 @@ func TestAuthKeyLogoutAndRelogin(t *testing.T) {
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++
}
}
}
allAddrs := lo.Map(allIps, func(x netip.Addr, index int) string {
return x.String()
})
success := pingAllHelper(t, allClients, allAddrs)
t.Logf("%d successful pings out of %d", success, len(allClients)*len(allIps))
for _, client := range allClients {
@@ -184,7 +173,12 @@ func TestAuthKeyLogoutAndRelogin(t *testing.T) {
}
if !found {
t.Errorf("IPs changed for client %s. Used to be %v now %v", client.Hostname(), clientIPs[client], ips)
t.Errorf(
"IPs changed for client %s. Used to be %v now %v",
client.Hostname(),
clientIPs[client],
ips,
)
}
}
}
@@ -207,8 +201,8 @@ func TestEphemeral(t *testing.T) {
}
spec := map[string]int{
"namespace1": len(TailscaleVersions),
"namespace2": len(TailscaleVersions),
"user1": len(TailscaleVersions),
"user2": len(TailscaleVersions),
}
headscale, err := scenario.Headscale(hsic.WithTestName("ephemeral"))
@@ -216,25 +210,25 @@ func TestEphemeral(t *testing.T) {
t.Errorf("failed to create headscale environment: %s", err)
}
for namespaceName, clientCount := range spec {
err = scenario.CreateNamespace(namespaceName)
for userName, clientCount := range spec {
err = scenario.CreateUser(userName)
if err != nil {
t.Errorf("failed to create namespace %s: %s", namespaceName, err)
t.Errorf("failed to create user %s: %s", userName, err)
}
err = scenario.CreateTailscaleNodesInNamespace(namespaceName, "all", clientCount, []tsic.Option{}...)
err = scenario.CreateTailscaleNodesInUser(userName, "all", clientCount, []tsic.Option{}...)
if err != nil {
t.Errorf("failed to create tailscale nodes in namespace %s: %s", namespaceName, err)
t.Errorf("failed to create tailscale nodes in user %s: %s", userName, err)
}
key, err := scenario.CreatePreAuthKey(namespaceName, true, true)
key, err := scenario.CreatePreAuthKey(userName, true, true)
if err != nil {
t.Errorf("failed to create pre-auth key for namespace %s: %s", namespaceName, err)
t.Errorf("failed to create pre-auth key for user %s: %s", userName, err)
}
err = scenario.RunTailscaleUp(namespaceName, headscale.GetEndpoint(), key.GetKey())
err = scenario.RunTailscaleUp(userName, headscale.GetEndpoint(), key.GetKey())
if err != nil {
t.Errorf("failed to run tailscale up for namespace %s: %s", namespaceName, err)
t.Errorf("failed to run tailscale up for user %s: %s", userName, err)
}
}
@@ -253,18 +247,11 @@ func TestEphemeral(t *testing.T) {
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++
}
}
}
allAddrs := lo.Map(allIps, func(x netip.Addr, index int) string {
return x.String()
})
success := pingAllHelper(t, allClients, allAddrs)
t.Logf("%d successful pings out of %d", success, len(allClients)*len(allIps))
for _, client := range allClients {
@@ -278,19 +265,19 @@ func TestEphemeral(t *testing.T) {
t.Logf("all clients logged out")
for namespaceName := range spec {
machines, err := headscale.ListMachinesInNamespace(namespaceName)
for userName := range spec {
machines, err := headscale.ListMachinesInUser(userName)
if err != nil {
log.Error().
Err(err).
Str("namespace", namespaceName).
Msg("Error listing machines in namespace")
Str("user", userName).
Msg("Error listing machines in user")
return
}
if len(machines) != 0 {
t.Errorf("expected no machines, got %d in namespace %s", len(machines), namespaceName)
t.Errorf("expected no machines, got %d in user %s", len(machines), userName)
}
}
@@ -311,8 +298,8 @@ func TestPingAllByHostname(t *testing.T) {
spec := map[string]int{
// Omit 1.16.2 (-1) because it does not have the FQDN field
"namespace3": len(TailscaleVersions) - 1,
"namespace4": len(TailscaleVersions) - 1,
"user3": len(TailscaleVersions) - 1,
"user4": len(TailscaleVersions) - 1,
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("pingallbyname"))
@@ -335,18 +322,7 @@ func TestPingAllByHostname(t *testing.T) {
t.Errorf("failed to get FQDNs: %s", err)
}
success := 0
for _, client := range allClients {
for _, hostname := range allHostnames {
err := client.Ping(hostname)
if err != nil {
t.Errorf("failed to ping %s from %s: %s", hostname, client.Hostname(), err)
} else {
success++
}
}
}
success := pingAllHelper(t, allClients, allHostnames)
t.Logf("%d successful pings out of %d", success, len(allClients)*len(allClients))
@@ -582,3 +558,93 @@ func TestResolveMagicDNS(t *testing.T) {
t.Errorf("failed to tear down scenario: %s", err)
}
}
func TestExpireNode(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),
}
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("expirenode"))
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)
}
allAddrs := lo.Map(allIps, func(x netip.Addr, index int) string {
return x.String()
})
success := pingAllHelper(t, allClients, allAddrs)
t.Logf("before expire: %d successful pings out of %d", success, len(allClients)*len(allIps))
for _, client := range allClients {
status, err := client.Status()
assert.NoError(t, err)
// Assert that we have the original count - self
assert.Len(t, status.Peers(), len(TailscaleVersions)-1)
}
headscale, err := scenario.Headscale()
assert.NoError(t, err)
// TODO(kradalby): This is Headscale specific and would not play nicely
// with other implementations of the ControlServer interface
result, err := headscale.Execute([]string{
"headscale", "nodes", "expire", "--identifier", "0", "--output", "json",
})
assert.NoError(t, err)
var machine v1.Machine
err = json.Unmarshal([]byte(result), &machine)
assert.NoError(t, err)
time.Sleep(30 * time.Second)
// Verify that the expired not is no longer present in the Peer list
// of connected nodes.
for _, client := range allClients {
status, err := client.Status()
assert.NoError(t, err)
for _, peerKey := range status.Peers() {
peerStatus := status.Peer[peerKey]
peerPublicKey := strings.TrimPrefix(peerStatus.PublicKey.String(), "nodekey:")
assert.NotEqual(t, machine.NodeKey, peerPublicKey)
}
if client.Hostname() != machine.Name {
// Assert that we have the original count - self - expired node
assert.Len(t, status.Peers(), len(TailscaleVersions)-2)
}
}
err = scenario.Shutdown()
if err != nil {
t.Errorf("failed to tear down scenario: %s", err)
}
}
+49 -9
View File
@@ -41,6 +41,8 @@ type fileInContainer struct {
contents []byte
}
// HeadscaleInContainer is an implementation of ControlServer which
// sets up a Headscale instance inside a container.
type HeadscaleInContainer struct {
hostname string
@@ -57,8 +59,12 @@ type HeadscaleInContainer struct {
filesInContainer []fileInContainer
}
// Option represent optional settings that can be given to a
// Headscale instance.
type Option = func(c *HeadscaleInContainer)
// WithACLPolicy adds a headscale.ACLPolicy policy to the
// HeadscaleInContainer instance.
func WithACLPolicy(acl *headscale.ACLPolicy) Option {
return func(hsic *HeadscaleInContainer) {
// TODO(kradalby): Move somewhere appropriate
@@ -68,6 +74,7 @@ func WithACLPolicy(acl *headscale.ACLPolicy) Option {
}
}
// WithTLS creates certificates and enables HTTPS.
func WithTLS() Option {
return func(hsic *HeadscaleInContainer) {
cert, key, err := createCertificate()
@@ -84,6 +91,8 @@ func WithTLS() Option {
}
}
// WithConfigEnv takes a map of environment variables that
// can be used to override Headscale configuration.
func WithConfigEnv(configEnv map[string]string) Option {
return func(hsic *HeadscaleInContainer) {
for key, value := range configEnv {
@@ -92,12 +101,15 @@ func WithConfigEnv(configEnv map[string]string) Option {
}
}
// WithPort sets the port on where to run Headscale.
func WithPort(port int) Option {
return func(hsic *HeadscaleInContainer) {
hsic.port = port
}
}
// WithTestName sets a name for the test, this will be reflected
// in the Docker container name.
func WithTestName(testName string) Option {
return func(hsic *HeadscaleInContainer) {
hash, _ := headscale.GenerateRandomStringDNSSafe(hsicHashLength)
@@ -107,6 +119,8 @@ func WithTestName(testName string) Option {
}
}
// WithHostnameAsServerURL sets the Headscale ServerURL based on
// the Hostname.
func WithHostnameAsServerURL() Option {
return func(hsic *HeadscaleInContainer) {
hsic.env["HEADSCALE_SERVER_URL"] = fmt.Sprintf("http://%s",
@@ -116,6 +130,7 @@ func WithHostnameAsServerURL() Option {
}
}
// WithFileInContainer adds a file to the container at the given path.
func WithFileInContainer(path string, contents []byte) Option {
return func(hsic *HeadscaleInContainer) {
hsic.filesInContainer = append(hsic.filesInContainer,
@@ -126,6 +141,7 @@ func WithFileInContainer(path string, contents []byte) Option {
}
}
// New returns a new HeadscaleInContainer instance.
func New(
pool *dockertest.Pool,
network *dockertest.Network,
@@ -244,10 +260,19 @@ func (t *HeadscaleInContainer) hasTLS() bool {
return len(t.tlsCert) != 0 && len(t.tlsKey) != 0
}
// Shutdown stops and cleans up the Headscale container.
func (t *HeadscaleInContainer) Shutdown() error {
return t.pool.Purge(t.container)
}
// SaveLog saves the current stdout log of the container to a path
// on the host system.
func (t *HeadscaleInContainer) SaveLog(path string) error {
return dockertestutil.SaveLog(t.pool, t.container, path)
}
// Execute runs a command inside the Headscale container and returns the
// result of stdout as a string.
func (t *HeadscaleInContainer) Execute(
command []string,
) (string, error) {
@@ -269,18 +294,23 @@ func (t *HeadscaleInContainer) Execute(
return stdout, nil
}
// GetIP returns the docker container IP as a string.
func (t *HeadscaleInContainer) GetIP() string {
return t.container.GetIPInNetwork(t.network)
}
// GetPort returns the docker container port as a string.
func (t *HeadscaleInContainer) GetPort() string {
return fmt.Sprintf("%d", t.port)
}
// GetHealthEndpoint returns a health endpoint for the HeadscaleInContainer
// instance.
func (t *HeadscaleInContainer) GetHealthEndpoint() string {
return fmt.Sprintf("%s/health", t.GetEndpoint())
}
// GetEndpoint returns the Headscale endpoint for the HeadscaleInContainer.
func (t *HeadscaleInContainer) GetEndpoint() string {
hostEndpoint := fmt.Sprintf("%s:%d",
t.GetIP(),
@@ -293,14 +323,18 @@ func (t *HeadscaleInContainer) GetEndpoint() string {
return fmt.Sprintf("http://%s", hostEndpoint)
}
// GetCert returns the public certificate of the HeadscaleInContainer.
func (t *HeadscaleInContainer) GetCert() []byte {
return t.tlsCert
}
// GetHostname returns the hostname of the HeadscaleInContainer.
func (t *HeadscaleInContainer) GetHostname() string {
return t.hostname
}
// WaitForReady blocks until the Headscale instance is ready to
// serve clients.
func (t *HeadscaleInContainer) WaitForReady() error {
url := t.GetHealthEndpoint()
@@ -328,10 +362,11 @@ func (t *HeadscaleInContainer) WaitForReady() error {
})
}
func (t *HeadscaleInContainer) CreateNamespace(
namespace string,
// CreateUser adds a new user to the Headscale instance.
func (t *HeadscaleInContainer) CreateUser(
user string,
) error {
command := []string{"headscale", "namespaces", "create", namespace}
command := []string{"headscale", "users", "create", user}
_, _, err := dockertestutil.ExecuteCommand(
t.container,
@@ -345,15 +380,17 @@ func (t *HeadscaleInContainer) CreateNamespace(
return nil
}
// CreateAuthKey creates a new "authorisation key" for a User that can be used
// to authorise a TailscaleClient with the Headscale instance.
func (t *HeadscaleInContainer) CreateAuthKey(
namespace string,
user string,
reusable bool,
ephemeral bool,
) (*v1.PreAuthKey, error) {
command := []string{
"headscale",
"--namespace",
namespace,
"--user",
user,
"preauthkeys",
"create",
"--expiration",
@@ -388,10 +425,12 @@ func (t *HeadscaleInContainer) CreateAuthKey(
return &preAuthKey, nil
}
func (t *HeadscaleInContainer) ListMachinesInNamespace(
namespace string,
// ListMachinesInUser list the TailscaleClients (Machine, Headscale internal representation)
// associated with a user.
func (t *HeadscaleInContainer) ListMachinesInUser(
user string,
) ([]*v1.Machine, error) {
command := []string{"headscale", "--namespace", namespace, "nodes", "list", "--output", "json"}
command := []string{"headscale", "--user", user, "nodes", "list", "--output", "json"}
result, _, err := dockertestutil.ExecuteCommand(
t.container,
@@ -411,6 +450,7 @@ func (t *HeadscaleInContainer) ListMachinesInNamespace(
return nodes, nil
}
// WriteFile save file inside the Headscale container.
func (t *HeadscaleInContainer) WriteFile(path string, data []byte) error {
return integrationutil.WriteFileToContainer(t.pool, t.container, path, data)
}
+160 -78
View File
@@ -25,14 +25,16 @@ const (
var (
errNoHeadscaleAvailable = errors.New("no headscale available")
errNoNamespaceAvailable = errors.New("no namespace available")
errNoUserAvailable = errors.New("no user available")
errNoClientFound = errors.New("client not found")
// 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.34.0",
"1.36.0",
"1.34.2",
"1.32.3",
"1.30.2",
}
@@ -55,13 +57,24 @@ var (
// "1.8.7",
// }.
// TailscaleVersions represents a list of Tailscale versions the suite
// uses to test compatibility with the ControlServer.
//
// The list contains two special cases, "head" and "unstable" which
// points to the current tip of Tailscale's main branch and the latest
// released unstable version.
//
// The rest of the version represents Tailscale versions that can be
// found in Tailscale's apt repository.
TailscaleVersions = append(
tailscaleVersions2021,
tailscaleVersions2019...,
)
)
type Namespace struct {
// User represents a User in the ControlServer and a map of TailscaleClient's
// associated with the User.
type User struct {
Clients map[string]TailscaleClient
createWaitGroup sync.WaitGroup
@@ -69,13 +82,17 @@ type Namespace struct {
syncWaitGroup sync.WaitGroup
}
// Scenario is a representation of an environment with one ControlServer and
// one or more User's and its associated TailscaleClients.
// A Scenario is intended to simplify setting up a new testcase for testing
// a ControlServer with TailscaleClients.
// TODO(kradalby): make control server configurable, test correctness with Tailscale SaaS.
type Scenario struct {
// TODO(kradalby): support multiple headcales for later, currently only
// use one.
controlServers *xsync.MapOf[string, ControlServer]
namespaces map[string]*Namespace
users map[string]*User
pool *dockertest.Pool
network *dockertest.Network
@@ -83,6 +100,8 @@ type Scenario struct {
headscaleLock sync.Mutex
}
// NewScenario creates a test Scenario which can be used to bootstraps a ControlServer with
// a set of Users and TailscaleClients.
func NewScenario() (*Scenario, error) {
hash, err := headscale.GenerateRandomStringDNSSafe(scenarioHashLength)
if err != nil {
@@ -116,16 +135,28 @@ func NewScenario() (*Scenario, error) {
return &Scenario{
controlServers: xsync.NewMapOf[ControlServer](),
namespaces: make(map[string]*Namespace),
users: make(map[string]*User),
pool: pool,
network: network,
}, nil
}
// Shutdown shuts down and cleans up all the containers (ControlServer, TailscaleClient)
// and networks associated with it.
// In addition, it will save the logs of the ControlServer to `/tmp/control` in the
// environment running the tests.
func (s *Scenario) Shutdown() error {
s.controlServers.Range(func(_ string, control ControlServer) bool {
err := control.Shutdown()
err := control.SaveLog("/tmp/control")
if err != nil {
log.Printf(
"Failed to save log from control: %s",
fmt.Errorf("failed to save log from control: %w", err),
)
}
err = control.Shutdown()
if err != nil {
log.Printf(
"Failed to shut down control: %s",
@@ -136,9 +167,9 @@ func (s *Scenario) Shutdown() error {
return true
})
for namespaceName, namespace := range s.namespaces {
for _, client := range namespace.Clients {
log.Printf("removing client %s in namespace %s", client.Hostname(), namespaceName)
for userName, user := range s.users {
for _, client := range user.Clients {
log.Printf("removing client %s in user %s", client.Hostname(), userName)
err := client.Shutdown()
if err != nil {
return fmt.Errorf("failed to tear down client: %w", err)
@@ -158,18 +189,22 @@ func (s *Scenario) Shutdown() error {
return nil
}
func (s *Scenario) Namespaces() []string {
namespaces := make([]string, 0)
for namespace := range s.namespaces {
namespaces = append(namespaces, namespace)
// Users returns the name of all users associated with the Scenario.
func (s *Scenario) Users() []string {
users := make([]string, 0)
for user := range s.users {
users = append(users, user)
}
return namespaces
return users
}
/// Headscale related stuff
// Note: These functions assume that there is a _single_ headscale instance for now
// Headscale returns a ControlServer instance based on hsic (HeadscaleInContainer)
// If the Scenario already has an instance, the pointer to the running container
// will be return, otherwise a new instance will be created.
// TODO(kradalby): make port and headscale configurable, multiple instances support?
func (s *Scenario) Headscale(opts ...hsic.Option) (ControlServer, error) {
s.headscaleLock.Lock()
@@ -194,45 +229,55 @@ func (s *Scenario) Headscale(opts ...hsic.Option) (ControlServer, error) {
return headscale, nil
}
func (s *Scenario) CreatePreAuthKey(namespace string, reusable bool, ephemeral bool) (*v1.PreAuthKey, error) {
// CreatePreAuthKey creates a "pre authentorised key" to be created in the
// Headscale instance on behalf of the Scenario.
func (s *Scenario) CreatePreAuthKey(
user string,
reusable bool,
ephemeral bool,
) (*v1.PreAuthKey, error) {
if headscale, err := s.Headscale(); err == nil {
key, err := headscale.CreateAuthKey(namespace, reusable, ephemeral)
key, err := headscale.CreateAuthKey(user, reusable, ephemeral)
if err != nil {
return nil, fmt.Errorf("failed to create namespace: %w", err)
return nil, fmt.Errorf("failed to create user: %w", err)
}
return key, nil
}
return nil, fmt.Errorf("failed to create namespace: %w", errNoHeadscaleAvailable)
return nil, fmt.Errorf("failed to create user: %w", errNoHeadscaleAvailable)
}
func (s *Scenario) CreateNamespace(namespace string) error {
// CreateUser creates a User to be created in the
// Headscale instance on behalf of the Scenario.
func (s *Scenario) CreateUser(user string) error {
if headscale, err := s.Headscale(); err == nil {
err := headscale.CreateNamespace(namespace)
err := headscale.CreateUser(user)
if err != nil {
return fmt.Errorf("failed to create namespace: %w", err)
return fmt.Errorf("failed to create user: %w", err)
}
s.namespaces[namespace] = &Namespace{
s.users[user] = &User{
Clients: make(map[string]TailscaleClient),
}
return nil
}
return fmt.Errorf("failed to create namespace: %w", errNoHeadscaleAvailable)
return fmt.Errorf("failed to create user: %w", errNoHeadscaleAvailable)
}
/// Client related stuff
func (s *Scenario) CreateTailscaleNodesInNamespace(
namespaceStr string,
// CreateTailscaleNodesInUser creates and adds a new TailscaleClient to a
// User in the Scenario.
func (s *Scenario) CreateTailscaleNodesInUser(
userStr string,
requestedVersion string,
count int,
opts ...tsic.Option,
) error {
if namespace, ok := s.namespaces[namespaceStr]; ok {
if user, ok := s.users[userStr]; ok {
for i := 0; i < count; i++ {
version := requestedVersion
if requestedVersion == "all" {
@@ -247,7 +292,7 @@ func (s *Scenario) CreateTailscaleNodesInNamespace(
cert := headscale.GetCert()
hostname := headscale.GetHostname()
namespace.createWaitGroup.Add(1)
user.createWaitGroup.Add(1)
opts = append(opts,
tsic.WithHeadscaleTLS(cert),
@@ -255,7 +300,7 @@ func (s *Scenario) CreateTailscaleNodesInNamespace(
)
go func() {
defer namespace.createWaitGroup.Done()
defer user.createWaitGroup.Done()
// TODO(kradalby): error handle this
tsClient, err := tsic.New(
@@ -275,26 +320,28 @@ func (s *Scenario) CreateTailscaleNodesInNamespace(
log.Printf("failed to wait for tailscaled: %s", err)
}
namespace.Clients[tsClient.Hostname()] = tsClient
user.Clients[tsClient.Hostname()] = tsClient
}()
}
namespace.createWaitGroup.Wait()
user.createWaitGroup.Wait()
return nil
}
return fmt.Errorf("failed to add tailscale node: %w", errNoNamespaceAvailable)
return fmt.Errorf("failed to add tailscale node: %w", errNoUserAvailable)
}
// RunTailscaleUp will log in all of the TailscaleClients associated with a
// User to the given ControlServer (by URL).
func (s *Scenario) RunTailscaleUp(
namespaceStr, loginServer, authKey string,
userStr, loginServer, authKey string,
) error {
if namespace, ok := s.namespaces[namespaceStr]; ok {
for _, client := range namespace.Clients {
namespace.joinWaitGroup.Add(1)
if user, ok := s.users[userStr]; ok {
for _, client := range user.Clients {
user.joinWaitGroup.Add(1)
go func(c TailscaleClient) {
defer namespace.joinWaitGroup.Done()
defer user.joinWaitGroup.Done()
// TODO(kradalby): error handle this
_ = c.Up(loginServer, authKey)
@@ -306,49 +353,53 @@ func (s *Scenario) RunTailscaleUp(
}
}
namespace.joinWaitGroup.Wait()
user.joinWaitGroup.Wait()
return nil
}
return fmt.Errorf("failed to up tailscale node: %w", errNoNamespaceAvailable)
return fmt.Errorf("failed to up tailscale node: %w", errNoUserAvailable)
}
// CountTailscale returns the total number of TailscaleClients in a Scenario.
// This is the sum of Users x TailscaleClients.
func (s *Scenario) CountTailscale() int {
count := 0
for _, namespace := range s.namespaces {
count += len(namespace.Clients)
for _, user := range s.users {
count += len(user.Clients)
}
return count
}
// WaitForTailscaleSync blocks execution until all the TailscaleClient reports
// to have all other TailscaleClients present in their netmap.NetworkMap.
func (s *Scenario) WaitForTailscaleSync() error {
tsCount := s.CountTailscale()
for _, namespace := range s.namespaces {
for _, client := range namespace.Clients {
namespace.syncWaitGroup.Add(1)
for _, user := range s.users {
for _, client := range user.Clients {
user.syncWaitGroup.Add(1)
go func(c TailscaleClient) {
defer namespace.syncWaitGroup.Done()
defer user.syncWaitGroup.Done()
// TODO(kradalby): error handle this
_ = c.WaitForPeers(tsCount)
}(client)
}
namespace.syncWaitGroup.Wait()
user.syncWaitGroup.Wait()
}
return nil
}
// CreateHeadscaleEnv is a conventient method returning a set up Headcale
// CreateHeadscaleEnv is a conventient method returning a complete Headcale
// test environment with nodes of all versions, joined to the server with X
// namespaces.
// users.
func (s *Scenario) CreateHeadscaleEnv(
namespaces map[string]int,
users map[string]int,
tsOpts []tsic.Option,
opts ...hsic.Option,
) error {
@@ -357,23 +408,23 @@ func (s *Scenario) CreateHeadscaleEnv(
return err
}
for namespaceName, clientCount := range namespaces {
err = s.CreateNamespace(namespaceName)
for userName, clientCount := range users {
err = s.CreateUser(userName)
if err != nil {
return err
}
err = s.CreateTailscaleNodesInNamespace(namespaceName, "all", clientCount, tsOpts...)
err = s.CreateTailscaleNodesInUser(userName, "all", clientCount, tsOpts...)
if err != nil {
return err
}
key, err := s.CreatePreAuthKey(namespaceName, true, false)
key, err := s.CreatePreAuthKey(userName, true, false)
if err != nil {
return err
}
err = s.RunTailscaleUp(namespaceName, headscale.GetEndpoint(), key.GetKey())
err = s.RunTailscaleUp(userName, headscale.GetEndpoint(), key.GetKey())
if err != nil {
return err
}
@@ -382,9 +433,11 @@ func (s *Scenario) CreateHeadscaleEnv(
return nil
}
func (s *Scenario) GetIPs(namespace string) ([]netip.Addr, error) {
// GetIPs returns all netip.Addr of TailscaleClients associated with a User
// in a Scenario.
func (s *Scenario) GetIPs(user string) ([]netip.Addr, error) {
var ips []netip.Addr
if ns, ok := s.namespaces[namespace]; ok {
if ns, ok := s.users[user]; ok {
for _, client := range ns.Clients {
clientIps, err := client.IPs()
if err != nil {
@@ -396,12 +449,13 @@ func (s *Scenario) GetIPs(namespace string) ([]netip.Addr, error) {
return ips, nil
}
return ips, fmt.Errorf("failed to get ips: %w", errNoNamespaceAvailable)
return ips, fmt.Errorf("failed to get ips: %w", errNoUserAvailable)
}
func (s *Scenario) GetClients(namespace string) ([]TailscaleClient, error) {
// GetIPs returns all TailscaleClients associated with a User in a Scenario.
func (s *Scenario) GetClients(user string) ([]TailscaleClient, error) {
var clients []TailscaleClient
if ns, ok := s.namespaces[namespace]; ok {
if ns, ok := s.users[user]; ok {
for _, client := range ns.Clients {
clients = append(clients, client)
}
@@ -409,18 +463,20 @@ func (s *Scenario) GetClients(namespace string) ([]TailscaleClient, error) {
return clients, nil
}
return clients, fmt.Errorf("failed to get clients: %w", errNoNamespaceAvailable)
return clients, fmt.Errorf("failed to get clients: %w", errNoUserAvailable)
}
func (s *Scenario) ListTailscaleClients(namespaces ...string) ([]TailscaleClient, error) {
// ListTailscaleClients returns a list of TailscaleClients given the Users
// passed as parameters.
func (s *Scenario) ListTailscaleClients(users ...string) ([]TailscaleClient, error) {
var allClients []TailscaleClient
if len(namespaces) == 0 {
namespaces = s.Namespaces()
if len(users) == 0 {
users = s.Users()
}
for _, namespace := range namespaces {
clients, err := s.GetClients(namespace)
for _, user := range users {
clients, err := s.GetClients(user)
if err != nil {
return nil, err
}
@@ -431,15 +487,37 @@ func (s *Scenario) ListTailscaleClients(namespaces ...string) ([]TailscaleClient
return allClients, nil
}
func (s *Scenario) ListTailscaleClientsIPs(namespaces ...string) ([]netip.Addr, error) {
var allIps []netip.Addr
if len(namespaces) == 0 {
namespaces = s.Namespaces()
// FindTailscaleClientByIP returns a TailscaleClient associated with an IP address
// if it exists.
func (s *Scenario) FindTailscaleClientByIP(ip netip.Addr) (TailscaleClient, error) {
clients, err := s.ListTailscaleClients()
if err != nil {
return nil, err
}
for _, namespace := range namespaces {
ips, err := s.GetIPs(namespace)
for _, client := range clients {
ips, _ := client.IPs()
for _, ip2 := range ips {
if ip == ip2 {
return client, nil
}
}
}
return nil, errNoClientFound
}
// ListTailscaleClientsIPs returns a list of netip.Addr based on Users
// passed as parameters.
func (s *Scenario) ListTailscaleClientsIPs(users ...string) ([]netip.Addr, error) {
var allIps []netip.Addr
if len(users) == 0 {
users = s.Users()
}
for _, user := range users {
ips, err := s.GetIPs(user)
if err != nil {
return nil, err
}
@@ -450,10 +528,12 @@ func (s *Scenario) ListTailscaleClientsIPs(namespaces ...string) ([]netip.Addr,
return allIps, nil
}
func (s *Scenario) ListTailscaleClientsFQDNs(namespaces ...string) ([]string, error) {
// ListTailscaleClientsIPs returns a list of FQDN based on Users
// passed as parameters.
func (s *Scenario) ListTailscaleClientsFQDNs(users ...string) ([]string, error) {
allFQDNs := make([]string, 0)
clients, err := s.ListTailscaleClients(namespaces...)
clients, err := s.ListTailscaleClients(users...)
if err != nil {
return nil, err
}
@@ -470,18 +550,20 @@ func (s *Scenario) ListTailscaleClientsFQDNs(namespaces ...string) ([]string, er
return allFQDNs, nil
}
// WaitForTailscaleLogout blocks execution until all TailscaleClients have
// logged out of the ControlServer.
func (s *Scenario) WaitForTailscaleLogout() {
for _, namespace := range s.namespaces {
for _, client := range namespace.Clients {
namespace.syncWaitGroup.Add(1)
for _, user := range s.users {
for _, client := range user.Clients {
user.syncWaitGroup.Add(1)
go func(c TailscaleClient) {
defer namespace.syncWaitGroup.Done()
defer user.syncWaitGroup.Done()
// TODO(kradalby): error handle this
_ = c.WaitForLogout()
}(client)
}
namespace.syncWaitGroup.Wait()
user.syncWaitGroup.Wait()
}
}
+22 -22
View File
@@ -31,7 +31,7 @@ func TestHeadscale(t *testing.T) {
var err error
namespace := "test-space"
user := "test-space"
scenario, err := NewScenario()
if err != nil {
@@ -50,19 +50,19 @@ func TestHeadscale(t *testing.T) {
}
})
t.Run("create-namespace", func(t *testing.T) {
err := scenario.CreateNamespace(namespace)
t.Run("create-user", func(t *testing.T) {
err := scenario.CreateUser(user)
if err != nil {
t.Errorf("failed to create namespace: %s", err)
t.Errorf("failed to create user: %s", err)
}
if _, ok := scenario.namespaces[namespace]; !ok {
t.Errorf("namespace is not in scenario")
if _, ok := scenario.users[user]; !ok {
t.Errorf("user is not in scenario")
}
})
t.Run("create-auth-key", func(t *testing.T) {
_, err := scenario.CreatePreAuthKey(namespace, true, false)
_, err := scenario.CreatePreAuthKey(user, true, false)
if err != nil {
t.Errorf("failed to create preauthkey: %s", err)
}
@@ -82,24 +82,24 @@ func TestCreateTailscale(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
namespace := "only-create-containers"
user := "only-create-containers"
scenario, err := NewScenario()
if err != nil {
t.Errorf("failed to create scenario: %s", err)
}
scenario.namespaces[namespace] = &Namespace{
scenario.users[user] = &User{
Clients: make(map[string]TailscaleClient),
}
t.Run("create-tailscale", func(t *testing.T) {
err := scenario.CreateTailscaleNodesInNamespace(namespace, "all", 3)
err := scenario.CreateTailscaleNodesInUser(user, "all", 3)
if err != nil {
t.Errorf("failed to add tailscale nodes: %s", err)
}
if clients := len(scenario.namespaces[namespace].Clients); clients != 3 {
if clients := len(scenario.users[user].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
namespace := "join-node-test"
user := "join-node-test"
count := 1
@@ -143,30 +143,30 @@ func TestTailscaleNodesJoiningHeadcale(t *testing.T) {
}
})
t.Run("create-namespace", func(t *testing.T) {
err := scenario.CreateNamespace(namespace)
t.Run("create-user", func(t *testing.T) {
err := scenario.CreateUser(user)
if err != nil {
t.Errorf("failed to create namespace: %s", err)
t.Errorf("failed to create user: %s", err)
}
if _, ok := scenario.namespaces[namespace]; !ok {
t.Errorf("namespace is not in scenario")
if _, ok := scenario.users[user]; !ok {
t.Errorf("user is not in scenario")
}
})
t.Run("create-tailscale", func(t *testing.T) {
err := scenario.CreateTailscaleNodesInNamespace(namespace, "1.30.2", count)
err := scenario.CreateTailscaleNodesInUser(user, "1.30.2", count)
if err != nil {
t.Errorf("failed to add tailscale nodes: %s", err)
}
if clients := len(scenario.namespaces[namespace].Clients); clients != count {
if clients := len(scenario.users[user].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(namespace, true, false)
key, err := scenario.CreatePreAuthKey(user, true, false)
if err != nil {
t.Errorf("failed to create preauthkey: %s", err)
}
@@ -177,7 +177,7 @@ func TestTailscaleNodesJoiningHeadcale(t *testing.T) {
}
err = scenario.RunTailscaleUp(
namespace,
user,
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(namespace)
ips, err := scenario.GetIPs(user)
if err != nil {
t.Errorf("failed to get tailscale ips: %s", err)
}
+24 -24
View File
@@ -41,7 +41,7 @@ var retry = func(times int, sleepInterval time.Duration,
return result, stderr, err
}
func TestSSHOneNamespaceAllToAll(t *testing.T) {
func TestSSHOneUserAllToAll(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
@@ -51,7 +51,7 @@ func TestSSHOneNamespaceAllToAll(t *testing.T) {
}
spec := map[string]int{
"namespace1": len(TailscaleVersions) - 5,
"user1": len(TailscaleVersions) - 5,
}
err = scenario.CreateHeadscaleEnv(spec,
@@ -59,7 +59,7 @@ func TestSSHOneNamespaceAllToAll(t *testing.T) {
hsic.WithACLPolicy(
&headscale.ACLPolicy{
Groups: map[string][]string{
"group:integration-test": {"namespace1"},
"group:integration-test": {"user1"},
},
ACLs: []headscale.ACL{
{
@@ -117,7 +117,7 @@ func TestSSHOneNamespaceAllToAll(t *testing.T) {
}
}
func TestSSHMultipleNamespacesAllToAll(t *testing.T) {
func TestSSHMultipleUsersAllToAll(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
@@ -127,8 +127,8 @@ func TestSSHMultipleNamespacesAllToAll(t *testing.T) {
}
spec := map[string]int{
"namespace1": len(TailscaleVersions) - 5,
"namespace2": len(TailscaleVersions) - 5,
"user1": len(TailscaleVersions) - 5,
"user2": len(TailscaleVersions) - 5,
}
err = scenario.CreateHeadscaleEnv(spec,
@@ -136,7 +136,7 @@ func TestSSHMultipleNamespacesAllToAll(t *testing.T) {
hsic.WithACLPolicy(
&headscale.ACLPolicy{
Groups: map[string][]string{
"group:integration-test": {"namespace1", "namespace2"},
"group:integration-test": {"user1", "user2"},
},
ACLs: []headscale.ACL{
{
@@ -163,12 +163,12 @@ func TestSSHMultipleNamespacesAllToAll(t *testing.T) {
t.Errorf("failed to create headscale environment: %s", err)
}
nsOneClients, err := scenario.ListTailscaleClients("namespace1")
nsOneClients, err := scenario.ListTailscaleClients("user1")
if err != nil {
t.Errorf("failed to get clients: %s", err)
}
nsTwoClients, err := scenario.ListTailscaleClients("namespace2")
nsTwoClients, err := scenario.ListTailscaleClients("user2")
if err != nil {
t.Errorf("failed to get clients: %s", err)
}
@@ -183,7 +183,7 @@ func TestSSHMultipleNamespacesAllToAll(t *testing.T) {
t.Errorf("failed to get FQDNs: %s", err)
}
testInterNamespaceSSH := func(sourceClients []TailscaleClient, targetClients []TailscaleClient) {
testInterUserSSH := func(sourceClients []TailscaleClient, targetClients []TailscaleClient) {
for _, client := range sourceClients {
for _, peer := range targetClients {
assertSSHHostname(t, client, peer)
@@ -191,8 +191,8 @@ func TestSSHMultipleNamespacesAllToAll(t *testing.T) {
}
}
testInterNamespaceSSH(nsOneClients, nsTwoClients)
testInterNamespaceSSH(nsTwoClients, nsOneClients)
testInterUserSSH(nsOneClients, nsTwoClients)
testInterUserSSH(nsTwoClients, nsOneClients)
err = scenario.Shutdown()
if err != nil {
@@ -210,7 +210,7 @@ func TestSSHNoSSHConfigured(t *testing.T) {
}
spec := map[string]int{
"namespace1": len(TailscaleVersions) - 5,
"user1": 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": {"namespace1"},
"group:integration-test": {"user1"},
},
ACLs: []headscale.ACL{
{
@@ -280,7 +280,7 @@ func TestSSHIsBlockedInACL(t *testing.T) {
}
spec := map[string]int{
"namespace1": len(TailscaleVersions) - 5,
"user1": 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": {"namespace1"},
"group:integration-test": {"user1"},
},
ACLs: []headscale.ACL{
{
@@ -347,7 +347,7 @@ func TestSSHIsBlockedInACL(t *testing.T) {
}
}
func TestSSNamespaceOnlyIsolation(t *testing.T) {
func TestSSUserOnlyIsolation(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
@@ -357,8 +357,8 @@ func TestSSNamespaceOnlyIsolation(t *testing.T) {
}
spec := map[string]int{
"namespaceacl1": len(TailscaleVersions) - 5,
"namespaceacl2": len(TailscaleVersions) - 5,
"useracl1": len(TailscaleVersions) - 5,
"useracl2": len(TailscaleVersions) - 5,
}
err = scenario.CreateHeadscaleEnv(spec,
@@ -366,8 +366,8 @@ func TestSSNamespaceOnlyIsolation(t *testing.T) {
hsic.WithACLPolicy(
&headscale.ACLPolicy{
Groups: map[string][]string{
"group:ssh1": {"namespaceacl1"},
"group:ssh2": {"namespaceacl2"},
"group:ssh1": {"useracl1"},
"group:ssh2": {"useracl2"},
},
ACLs: []headscale.ACL{
{
@@ -392,7 +392,7 @@ func TestSSNamespaceOnlyIsolation(t *testing.T) {
},
},
),
hsic.WithTestName("sshtwonamespaceaclblock"),
hsic.WithTestName("sshtwouseraclblock"),
hsic.WithConfigEnv(map[string]string{
"HEADSCALE_EXPERIMENTAL_FEATURE_SSH": "1",
}),
@@ -401,12 +401,12 @@ func TestSSNamespaceOnlyIsolation(t *testing.T) {
t.Errorf("failed to create headscale environment: %s", err)
}
ssh1Clients, err := scenario.ListTailscaleClients("namespaceacl1")
ssh1Clients, err := scenario.ListTailscaleClients("useracl1")
if err != nil {
t.Errorf("failed to get clients: %s", err)
}
ssh2Clients, err := scenario.ListTailscaleClients("namespaceacl2")
ssh2Clients, err := scenario.ListTailscaleClients("useracl2")
if err != nil {
t.Errorf("failed to get clients: %s", err)
}
+3 -1
View File
@@ -4,6 +4,7 @@ import (
"net/netip"
"net/url"
"github.com/juanfont/headscale/integration/tsic"
"tailscale.com/ipn/ipnstate"
)
@@ -22,6 +23,7 @@ type TailscaleClient interface {
WaitForReady() error
WaitForLogout() error
WaitForPeers(expected int) error
Ping(hostnameOrIP string) error
Ping(hostnameOrIP string, opts ...tsic.PingOption) error
Curl(url string, opts ...tsic.CurlOption) (string, error)
ID() string
}
+233 -15
View File
@@ -7,7 +7,9 @@ import (
"log"
"net/netip"
"net/url"
"strconv"
"strings"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/juanfont/headscale"
@@ -20,6 +22,7 @@ import (
const (
tsicHashLength = 6
defaultPingCount = 10
dockerContextPath = "../."
headscaleCertPath = "/usr/local/share/ca-certificates/headscale.crt"
)
@@ -33,6 +36,8 @@ var (
errTailscaleNotLoggedOut = errors.New("tailscale not logged out")
)
// TailscaleInContainer is an implementation of TailscaleClient which
// sets up a Tailscale instance inside a container.
type TailscaleInContainer struct {
version string
hostname string
@@ -49,16 +54,27 @@ type TailscaleInContainer struct {
headscaleCert []byte
headscaleHostname string
withSSH bool
withTags []string
withEntrypoint []string
workdir string
}
// Option represent optional settings that can be given to a
// Tailscale instance.
type Option = func(c *TailscaleInContainer)
// WithHeadscaleTLS takes the certificate of the Headscale instance
// and adds it to the trusted surtificate of the Tailscale container.
func WithHeadscaleTLS(cert []byte) Option {
return func(tsic *TailscaleInContainer) {
tsic.headscaleCert = cert
}
}
// WithOrCreateNetwork sets the Docker container network to use with
// the Tailscale instance, if the parameter is nil, a new network,
// isolating the TailscaleClient, will be created. If a network is
// passed, the Tailscale instance will join the given network.
func WithOrCreateNetwork(network *dockertest.Network) Option {
return func(tsic *TailscaleInContainer) {
if network != nil {
@@ -79,18 +95,47 @@ func WithOrCreateNetwork(network *dockertest.Network) Option {
}
}
// WithHeadscaleName set the name of the headscale instance,
// mostly useful in combination with TLS and WithHeadscaleTLS.
func WithHeadscaleName(hsName string) Option {
return func(tsic *TailscaleInContainer) {
tsic.headscaleHostname = hsName
}
}
// WithTags associates the given tags to the Tailscale instance.
func WithTags(tags []string) Option {
return func(tsic *TailscaleInContainer) {
tsic.withTags = tags
}
}
// WithSSH enables SSH for the Tailscale instance.
func WithSSH() Option {
return func(tsic *TailscaleInContainer) {
tsic.withSSH = true
}
}
// WithDockerWorkdir allows the docker working directory to be set.
func WithDockerWorkdir(dir string) Option {
return func(tsic *TailscaleInContainer) {
tsic.workdir = dir
}
}
// WithDockerEntrypoint allows the docker entrypoint of the container
// to be overridden. This is a dangerous option which can make
// the container not work as intended as a typo might prevent
// tailscaled and other processes from starting.
// Use with caution.
func WithDockerEntrypoint(args []string) Option {
return func(tsic *TailscaleInContainer) {
tsic.withEntrypoint = args
}
}
// New returns a new TailscaleInContainer instance.
func New(
pool *dockertest.Pool,
version string,
@@ -110,6 +155,12 @@ func New(
pool: pool,
network: network,
withEntrypoint: []string{
"/bin/bash",
"-c",
"/bin/sleep 3 ; update-ca-certificates ; tailscaled --tun=tsdev",
},
}
for _, opt := range opts {
@@ -122,11 +173,7 @@ func New(
// Cmd: []string{
// "tailscaled", "--tun=tsdev",
// },
Entrypoint: []string{
"/bin/bash",
"-c",
"/bin/sleep 3 ; update-ca-certificates ; tailscaled --tun=tsdev",
},
Entrypoint: tsic.withEntrypoint,
}
if tsic.headscaleHostname != "" {
@@ -136,6 +183,10 @@ func New(
}
}
if tsic.workdir != "" {
tailscaleOptions.WorkingDir = tsic.workdir
}
// dockertest isnt very good at handling containers that has already
// been created, this is an attempt to make sure this container isnt
// present.
@@ -172,22 +223,29 @@ func (t *TailscaleInContainer) hasTLS() bool {
return len(t.headscaleCert) != 0
}
// Shutdown stops and cleans up the Tailscale container.
func (t *TailscaleInContainer) Shutdown() error {
return t.pool.Purge(t.container)
}
// Hostname returns the hostname of the Tailscale instance.
func (t *TailscaleInContainer) Hostname() string {
return t.hostname
}
// Version returns the running Tailscale version of the instance.
func (t *TailscaleInContainer) Version() string {
return t.version
}
// ID returns the Docker container ID of the TailscaleInContainer
// instance.
func (t *TailscaleInContainer) ID() string {
return t.container.Container.ID
}
// Execute runs a command inside the Tailscale container and returns the
// result of stdout as a string.
func (t *TailscaleInContainer) Execute(
command []string,
) (string, string, error) {
@@ -213,6 +271,8 @@ func (t *TailscaleInContainer) Execute(
return stdout, stderr, nil
}
// Up runs the login routine on the given Tailscale instance.
// This login mechanism uses the authorised key for authentication.
func (t *TailscaleInContainer) Up(
loginServer, authKey string,
) error {
@@ -231,6 +291,12 @@ func (t *TailscaleInContainer) Up(
command = append(command, "--ssh")
}
if len(t.withTags) > 0 {
command = append(command,
fmt.Sprintf(`--advertise-tags=%s`, strings.Join(t.withTags, ",")),
)
}
if _, _, err := t.Execute(command); err != nil {
return fmt.Errorf("failed to join tailscale client: %w", err)
}
@@ -238,6 +304,8 @@ func (t *TailscaleInContainer) Up(
return nil
}
// Up runs the login routine on the given Tailscale instance.
// This login mechanism uses web + command line flow for authentication.
func (t *TailscaleInContainer) UpWithLoginURL(
loginServer string,
) (*url.URL, error) {
@@ -270,6 +338,7 @@ func (t *TailscaleInContainer) UpWithLoginURL(
return loginURL, nil
}
// Logout runs the logout routine on the given Tailscale instance.
func (t *TailscaleInContainer) Logout() error {
_, _, err := t.Execute([]string{"tailscale", "logout"})
if err != nil {
@@ -279,6 +348,7 @@ func (t *TailscaleInContainer) Logout() error {
return nil
}
// IPs returns the netip.Addr of the Tailscale instance.
func (t *TailscaleInContainer) IPs() ([]netip.Addr, error) {
if t.ips != nil && len(t.ips) != 0 {
return t.ips, nil
@@ -311,6 +381,7 @@ func (t *TailscaleInContainer) IPs() ([]netip.Addr, error) {
return ips, nil
}
// Status returns the ipnstate.Status of the Tailscale instance.
func (t *TailscaleInContainer) Status() (*ipnstate.Status, error) {
command := []string{
"tailscale",
@@ -332,6 +403,7 @@ func (t *TailscaleInContainer) Status() (*ipnstate.Status, error) {
return &status, err
}
// FQDN returns the FQDN as a string of the Tailscale instance.
func (t *TailscaleInContainer) FQDN() (string, error) {
if t.fqdn != "" {
return t.fqdn, nil
@@ -345,6 +417,8 @@ func (t *TailscaleInContainer) FQDN() (string, error) {
return status.Self.DNSName, nil
}
// WaitForReady blocks until the Tailscale (tailscaled) instance is ready
// to login or be used.
func (t *TailscaleInContainer) WaitForReady() error {
return t.pool.Retry(func() error {
status, err := t.Status()
@@ -360,6 +434,7 @@ func (t *TailscaleInContainer) WaitForReady() error {
})
}
// WaitForLogout blocks until the Tailscale instance has logged out.
func (t *TailscaleInContainer) WaitForLogout() error {
return t.pool.Retry(func() error {
status, err := t.Status()
@@ -375,6 +450,8 @@ func (t *TailscaleInContainer) WaitForLogout() error {
})
}
// WaitForPeers blocks until N number of peers is present in the
// Peer list of the Tailscale instance.
func (t *TailscaleInContainer) WaitForPeers(expected int) error {
return t.pool.Retry(func() error {
status, err := t.Status()
@@ -390,17 +467,65 @@ func (t *TailscaleInContainer) WaitForPeers(expected int) error {
})
}
// TODO(kradalby): Make multiping, go routine magic.
func (t *TailscaleInContainer) Ping(hostnameOrIP string) error {
return t.pool.Retry(func() error {
command := []string{
"tailscale", "ping",
"--timeout=1s",
"--c=10",
"--until-direct=true",
hostnameOrIP,
}
type (
// PingOption repreent optional settings that can be given
// to ping another host.
PingOption = func(args *pingArgs)
pingArgs struct {
timeout time.Duration
count int
direct bool
}
)
// WithPingTimeout sets the timeout for the ping command.
func WithPingTimeout(timeout time.Duration) PingOption {
return func(args *pingArgs) {
args.timeout = timeout
}
}
// WithPingCount sets the count of pings to attempt.
func WithPingCount(count int) PingOption {
return func(args *pingArgs) {
args.count = count
}
}
// WithPingUntilDirect decides if the ping should only succeed
// if a direct connection is established or if successful
// DERP ping is sufficient.
func WithPingUntilDirect(direct bool) PingOption {
return func(args *pingArgs) {
args.direct = direct
}
}
// Ping executes the Tailscale ping command and pings a hostname
// or IP. It accepts a series of PingOption.
// TODO(kradalby): Make multiping, go routine magic.
func (t *TailscaleInContainer) Ping(hostnameOrIP string, opts ...PingOption) error {
args := pingArgs{
timeout: time.Second,
count: defaultPingCount,
direct: true,
}
for _, opt := range opts {
opt(&args)
}
command := []string{
"tailscale", "ping",
fmt.Sprintf("--timeout=%s", args.timeout),
fmt.Sprintf("--c=%d", args.count),
fmt.Sprintf("--until-direct=%s", strconv.FormatBool(args.direct)),
}
command = append(command, hostnameOrIP)
return t.pool.Retry(func() error {
result, _, err := t.Execute(command)
if err != nil {
log.Printf(
@@ -421,6 +546,99 @@ func (t *TailscaleInContainer) Ping(hostnameOrIP string) error {
})
}
type (
// CurlOption repreent optional settings that can be given
// to curl another host.
CurlOption = func(args *curlArgs)
curlArgs struct {
connectionTimeout time.Duration
maxTime time.Duration
retry int
retryDelay time.Duration
retryMaxTime time.Duration
}
)
// WithCurlConnectionTimeout sets the timeout for each connection started
// by curl.
func WithCurlConnectionTimeout(timeout time.Duration) CurlOption {
return func(args *curlArgs) {
args.connectionTimeout = timeout
}
}
// WithCurlMaxTime sets the max time for a transfer for each connection started
// by curl.
func WithCurlMaxTime(t time.Duration) CurlOption {
return func(args *curlArgs) {
args.maxTime = t
}
}
// WithCurlRetry sets the number of retries a connection is attempted by curl.
func WithCurlRetry(ret int) CurlOption {
return func(args *curlArgs) {
args.retry = ret
}
}
const (
defaultConnectionTimeout = 3 * time.Second
defaultMaxTime = 10 * time.Second
defaultRetry = 5
defaultRetryDelay = 0 * time.Second
defaultRetryMaxTime = 50 * time.Second
)
// Curl executes the Tailscale curl command and curls a hostname
// or IP. It accepts a series of CurlOption.
func (t *TailscaleInContainer) Curl(url string, opts ...CurlOption) (string, error) {
args := curlArgs{
connectionTimeout: defaultConnectionTimeout,
maxTime: defaultMaxTime,
retry: defaultRetry,
retryDelay: defaultRetryDelay,
retryMaxTime: defaultRetryMaxTime,
}
for _, opt := range opts {
opt(&args)
}
command := []string{
"curl",
"--silent",
"--connect-timeout", fmt.Sprintf("%d", int(args.connectionTimeout.Seconds())),
"--max-time", fmt.Sprintf("%d", int(args.maxTime.Seconds())),
"--retry", fmt.Sprintf("%d", args.retry),
"--retry-delay", fmt.Sprintf("%d", int(args.retryDelay.Seconds())),
"--retry-max-time", fmt.Sprintf("%d", int(args.retryMaxTime.Seconds())),
url,
}
var result string
err := t.pool.Retry(func() error {
var err error
result, _, err = t.Execute(command)
if err != nil {
log.Printf(
"failed to run curl command from %s to %s, err: %s",
t.Hostname(),
url,
err,
)
return err
}
return nil
})
return result, err
}
// WriteFile save file inside the Tailscale container.
func (t *TailscaleInContainer) WriteFile(path string, data []byte) error {
return integrationutil.WriteFileToContainer(t.pool, t.container, path, data)
}
+48
View File
@@ -0,0 +1,48 @@
package integration
import (
"testing"
)
func pingAllHelper(t *testing.T, clients []TailscaleClient, addrs []string) int {
t.Helper()
success := 0
for _, client := range clients {
for _, addr := range addrs {
err := client.Ping(addr)
if err != nil {
t.Errorf("failed to ping %s from %s: %s", addr, client.Hostname(), err)
} else {
success++
}
}
}
return success
}
// pingAllNegativeHelper is intended to have 1 or more nodes timeing out from the ping,
// it counts failures instead of successes.
// func pingAllNegativeHelper(t *testing.T, clients []TailscaleClient, addrs []string) int {
// t.Helper()
// failures := 0
//
// timeout := 100
// count := 3
//
// for _, client := range clients {
// for _, addr := range addrs {
// err := client.Ping(
// addr,
// tsic.WithPingTimeout(time.Duration(timeout)*time.Millisecond),
// tsic.WithPingCount(count),
// )
// if err != nil {
// failures++
// }
// }
// }
//
// return failures
// }
+143 -144
View File
@@ -24,7 +24,6 @@ type IntegrationCLITestSuite struct {
pool dockertest.Pool
network dockertest.Network
headscale dockertest.Resource
env []string
}
func TestIntegrationCLITestSuite(t *testing.T) {
@@ -138,12 +137,12 @@ func (s *IntegrationCLITestSuite) HandleStats(
s.stats = stats
}
func (s *IntegrationCLITestSuite) createNamespace(name string) (*v1.Namespace, error) {
func (s *IntegrationCLITestSuite) createUser(name string) (*v1.User, error) {
result, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
"namespaces",
"users",
"create",
name,
"--output",
@@ -155,38 +154,38 @@ func (s *IntegrationCLITestSuite) createNamespace(name string) (*v1.Namespace, e
return nil, err
}
var namespace v1.Namespace
err = json.Unmarshal([]byte(result), &namespace)
var user v1.User
err = json.Unmarshal([]byte(result), &user)
if err != nil {
return nil, err
}
return &namespace, nil
return &user, nil
}
func (s *IntegrationCLITestSuite) TestNamespaceCommand() {
names := []string{"namespace1", "otherspace", "tasty"}
namespaces := make([]*v1.Namespace, len(names))
func (s *IntegrationCLITestSuite) TestUserCommand() {
names := []string{"user1", "otherspace", "tasty"}
users := make([]*v1.User, len(names))
for index, namespaceName := range names {
namespace, err := s.createNamespace(namespaceName)
for index, userName := range names {
user, err := s.createUser(userName)
assert.Nil(s.T(), err)
namespaces[index] = namespace
users[index] = user
}
assert.Len(s.T(), namespaces, len(names))
assert.Len(s.T(), users, len(names))
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)
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)
// Test list namespaces
// Test list users
listResult, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
"namespaces",
"users",
"list",
"--output",
"json",
@@ -195,20 +194,20 @@ func (s *IntegrationCLITestSuite) TestNamespaceCommand() {
)
assert.Nil(s.T(), err)
var listedNamespaces []v1.Namespace
err = json.Unmarshal([]byte(listResult), &listedNamespaces)
var listedUsers []v1.User
err = json.Unmarshal([]byte(listResult), &listedUsers)
assert.Nil(s.T(), err)
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)
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)
// Test rename namespace
// Test rename user
renameResult, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
"namespaces",
"users",
"rename",
"--output",
"json",
@@ -219,18 +218,18 @@ func (s *IntegrationCLITestSuite) TestNamespaceCommand() {
)
assert.Nil(s.T(), err)
var renamedNamespace v1.Namespace
err = json.Unmarshal([]byte(renameResult), &renamedNamespace)
var renamedUser v1.User
err = json.Unmarshal([]byte(renameResult), &renamedUser)
assert.Nil(s.T(), err)
assert.Equal(s.T(), renamedNamespace.Name, "newname")
assert.Equal(s.T(), renamedUser.Name, "newname")
// Test list after rename namespaces
// Test list after rename users
listAfterRenameResult, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
"namespaces",
"users",
"list",
"--output",
"json",
@@ -239,19 +238,19 @@ func (s *IntegrationCLITestSuite) TestNamespaceCommand() {
)
assert.Nil(s.T(), err)
var listedAfterRenameNamespaces []v1.Namespace
err = json.Unmarshal([]byte(listAfterRenameResult), &listedAfterRenameNamespaces)
var listedAfterRenameUsers []v1.User
err = json.Unmarshal([]byte(listAfterRenameResult), &listedAfterRenameUsers)
assert.Nil(s.T(), err)
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)
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)
}
func (s *IntegrationCLITestSuite) TestPreAuthKeyCommand() {
count := 5
namespace, err := s.createNamespace("pre-auth-key-namespace")
user, err := s.createUser("pre-auth-key-user")
keys := make([]*v1.PreAuthKey, count)
assert.Nil(s.T(), err)
@@ -262,8 +261,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommand() {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace.Name,
"--user",
user.Name,
"create",
"--reusable",
"--expiration",
@@ -292,8 +291,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommand() {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace.Name,
"--user",
user.Name,
"list",
"--output",
"json",
@@ -357,8 +356,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommand() {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace.Name,
"--user",
user.Name,
"expire",
listedPreAuthKeys[i].Key,
},
@@ -373,8 +372,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommand() {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace.Name,
"--user",
user.Name,
"list",
"--output",
"json",
@@ -410,7 +409,7 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommand() {
}
func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandWithoutExpiry() {
namespace, err := s.createNamespace("pre-auth-key-without-exp-namespace")
user, err := s.createUser("pre-auth-key-without-exp-user")
assert.Nil(s.T(), err)
preAuthResult, _, err := ExecuteCommand(
@@ -418,8 +417,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandWithoutExpiry() {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace.Name,
"--user",
user.Name,
"create",
"--reusable",
"--output",
@@ -439,8 +438,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandWithoutExpiry() {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace.Name,
"--user",
user.Name,
"list",
"--output",
"json",
@@ -463,7 +462,7 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandWithoutExpiry() {
}
func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandReusableEphemeral() {
namespace, err := s.createNamespace("pre-auth-key-reus-ephm-namespace")
user, err := s.createUser("pre-auth-key-reus-ephm-user")
assert.Nil(s.T(), err)
preAuthReusableResult, _, err := ExecuteCommand(
@@ -471,8 +470,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandReusableEphemeral() {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace.Name,
"--user",
user.Name,
"create",
"--reusable=true",
"--output",
@@ -494,8 +493,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandReusableEphemeral() {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace.Name,
"--user",
user.Name,
"create",
"--ephemeral=true",
"--output",
@@ -518,8 +517,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandReusableEphemeral() {
// []string{
// "headscale",
// "preauthkeys",
// "--namespace",
// namespace.Name,
// "--user",
// user.Name,
// "create",
// "--ephemeral",
// "--reusable",
@@ -536,8 +535,8 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandReusableEphemeral() {
[]string{
"headscale",
"preauthkeys",
"--namespace",
namespace.Name,
"--user",
user.Name,
"list",
"--output",
"json",
@@ -554,7 +553,7 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandReusableEphemeral() {
}
func (s *IntegrationCLITestSuite) TestNodeTagCommand() {
namespace, err := s.createNamespace("machine-namespace")
user, err := s.createUser("machine-user")
assert.Nil(s.T(), err)
machineKeys := []string{
@@ -573,8 +572,8 @@ func (s *IntegrationCLITestSuite) TestNodeTagCommand() {
"create-node",
"--name",
fmt.Sprintf("machine-%d", index+1),
"--namespace",
namespace.Name,
"--user",
user.Name,
"--key",
machineKey,
"--output",
@@ -589,8 +588,8 @@ func (s *IntegrationCLITestSuite) TestNodeTagCommand() {
[]string{
"headscale",
"nodes",
"--namespace",
namespace.Name,
"--user",
user.Name,
"register",
"--key",
machineKey,
@@ -683,10 +682,10 @@ func (s *IntegrationCLITestSuite) TestNodeTagCommand() {
}
func (s *IntegrationCLITestSuite) TestNodeCommand() {
namespace, err := s.createNamespace("machine-namespace")
user, err := s.createUser("machine-user")
assert.Nil(s.T(), err)
secondNamespace, err := s.createNamespace("other-namespace")
secondUser, err := s.createUser("other-user")
assert.Nil(s.T(), err)
// Randomly generated machine keys
@@ -709,8 +708,8 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
"create-node",
"--name",
fmt.Sprintf("machine-%d", index+1),
"--namespace",
namespace.Name,
"--user",
user.Name,
"--key",
machineKey,
"--output",
@@ -725,8 +724,8 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
[]string{
"headscale",
"nodes",
"--namespace",
namespace.Name,
"--user",
user.Name,
"register",
"--key",
machineKey,
@@ -778,14 +777,14 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
assert.Equal(s.T(), "machine-4", listAll[3].Name)
assert.Equal(s.T(), "machine-5", listAll[4].Name)
otherNamespaceMachineKeys := []string{
otherUserMachineKeys := []string{
"nodekey:b5b444774186d4217adcec407563a1223929465ee2c68a4da13af0d0185b4f8e",
"nodekey:dc721977ac7415aafa87f7d4574cbe07c6b171834a6d37375782bdc1fb6b3584",
}
otherNamespaceMachines := make([]*v1.Machine, len(otherNamespaceMachineKeys))
otherUserMachines := make([]*v1.Machine, len(otherUserMachineKeys))
assert.Nil(s.T(), err)
for index, machineKey := range otherNamespaceMachineKeys {
for index, machineKey := range otherUserMachineKeys {
_, _, err := ExecuteCommand(
&s.headscale,
[]string{
@@ -793,9 +792,9 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
"debug",
"create-node",
"--name",
fmt.Sprintf("otherNamespace-machine-%d", index+1),
"--namespace",
secondNamespace.Name,
fmt.Sprintf("otherUser-machine-%d", index+1),
"--user",
secondUser.Name,
"--key",
machineKey,
"--output",
@@ -810,8 +809,8 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
[]string{
"headscale",
"nodes",
"--namespace",
secondNamespace.Name,
"--user",
secondUser.Name,
"register",
"--key",
machineKey,
@@ -826,13 +825,13 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
err = json.Unmarshal([]byte(machineResult), &machine)
assert.Nil(s.T(), err)
otherNamespaceMachines[index] = &machine
otherUserMachines[index] = &machine
}
assert.Len(s.T(), otherNamespaceMachines, len(otherNamespaceMachineKeys))
assert.Len(s.T(), otherUserMachines, len(otherUserMachineKeys))
// Test list all nodes after added otherNamespace
listAllWithotherNamespaceResult, _, err := ExecuteCommand(
// Test list all nodes after added otherUser
listAllWithotherUserResult, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
@@ -845,31 +844,31 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
)
assert.Nil(s.T(), err)
var listAllWithotherNamespace []v1.Machine
var listAllWithotherUser []v1.Machine
err = json.Unmarshal(
[]byte(listAllWithotherNamespaceResult),
&listAllWithotherNamespace,
[]byte(listAllWithotherUserResult),
&listAllWithotherUser,
)
assert.Nil(s.T(), err)
// All nodes, machines + otherNamespace
assert.Len(s.T(), listAllWithotherNamespace, 7)
// All nodes, machines + otherUser
assert.Len(s.T(), listAllWithotherUser, 7)
assert.Equal(s.T(), uint64(6), listAllWithotherNamespace[5].Id)
assert.Equal(s.T(), uint64(7), listAllWithotherNamespace[6].Id)
assert.Equal(s.T(), uint64(6), listAllWithotherUser[5].Id)
assert.Equal(s.T(), uint64(7), listAllWithotherUser[6].Id)
assert.Equal(s.T(), "otherNamespace-machine-1", listAllWithotherNamespace[5].Name)
assert.Equal(s.T(), "otherNamespace-machine-2", listAllWithotherNamespace[6].Name)
assert.Equal(s.T(), "otherUser-machine-1", listAllWithotherUser[5].Name)
assert.Equal(s.T(), "otherUser-machine-2", listAllWithotherUser[6].Name)
// Test list all nodes after added otherNamespace
listOnlyotherNamespaceMachineNamespaceResult, _, err := ExecuteCommand(
// Test list all nodes after added otherUser
listOnlyotherUserMachineUserResult, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
"nodes",
"list",
"--namespace",
secondNamespace.Name,
"--user",
secondUser.Name,
"--output",
"json",
},
@@ -877,27 +876,27 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
)
assert.Nil(s.T(), err)
var listOnlyotherNamespaceMachineNamespace []v1.Machine
var listOnlyotherUserMachineUser []v1.Machine
err = json.Unmarshal(
[]byte(listOnlyotherNamespaceMachineNamespaceResult),
&listOnlyotherNamespaceMachineNamespace,
[]byte(listOnlyotherUserMachineUserResult),
&listOnlyotherUserMachineUser,
)
assert.Nil(s.T(), err)
assert.Len(s.T(), listOnlyotherNamespaceMachineNamespace, 2)
assert.Len(s.T(), listOnlyotherUserMachineUser, 2)
assert.Equal(s.T(), uint64(6), listOnlyotherNamespaceMachineNamespace[0].Id)
assert.Equal(s.T(), uint64(7), listOnlyotherNamespaceMachineNamespace[1].Id)
assert.Equal(s.T(), uint64(6), listOnlyotherUserMachineUser[0].Id)
assert.Equal(s.T(), uint64(7), listOnlyotherUserMachineUser[1].Id)
assert.Equal(
s.T(),
"otherNamespace-machine-1",
listOnlyotherNamespaceMachineNamespace[0].Name,
"otherUser-machine-1",
listOnlyotherUserMachineUser[0].Name,
)
assert.Equal(
s.T(),
"otherNamespace-machine-2",
listOnlyotherNamespaceMachineNamespace[1].Name,
"otherUser-machine-2",
listOnlyotherUserMachineUser[1].Name,
)
// Delete a machines
@@ -918,15 +917,15 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
)
assert.Nil(s.T(), err)
// Test: list main namespace after machine is deleted
listOnlyMachineNamespaceAfterDeleteResult, _, err := ExecuteCommand(
// Test: list main user after machine is deleted
listOnlyMachineUserAfterDeleteResult, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
"nodes",
"list",
"--namespace",
namespace.Name,
"--user",
user.Name,
"--output",
"json",
},
@@ -934,18 +933,18 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() {
)
assert.Nil(s.T(), err)
var listOnlyMachineNamespaceAfterDelete []v1.Machine
var listOnlyMachineUserAfterDelete []v1.Machine
err = json.Unmarshal(
[]byte(listOnlyMachineNamespaceAfterDeleteResult),
&listOnlyMachineNamespaceAfterDelete,
[]byte(listOnlyMachineUserAfterDeleteResult),
&listOnlyMachineUserAfterDelete,
)
assert.Nil(s.T(), err)
assert.Len(s.T(), listOnlyMachineNamespaceAfterDelete, 4)
assert.Len(s.T(), listOnlyMachineUserAfterDelete, 4)
}
func (s *IntegrationCLITestSuite) TestNodeExpireCommand() {
namespace, err := s.createNamespace("machine-expire-namespace")
user, err := s.createUser("machine-expire-user")
assert.Nil(s.T(), err)
// Randomly generated machine keys
@@ -968,8 +967,8 @@ func (s *IntegrationCLITestSuite) TestNodeExpireCommand() {
"create-node",
"--name",
fmt.Sprintf("machine-%d", index+1),
"--namespace",
namespace.Name,
"--user",
user.Name,
"--key",
machineKey,
"--output",
@@ -984,8 +983,8 @@ func (s *IntegrationCLITestSuite) TestNodeExpireCommand() {
[]string{
"headscale",
"nodes",
"--namespace",
namespace.Name,
"--user",
user.Name,
"register",
"--key",
machineKey,
@@ -1072,7 +1071,7 @@ func (s *IntegrationCLITestSuite) TestNodeExpireCommand() {
}
func (s *IntegrationCLITestSuite) TestNodeRenameCommand() {
namespace, err := s.createNamespace("machine-rename-command")
user, err := s.createUser("machine-rename-command")
assert.Nil(s.T(), err)
// Randomly generated machine keys
@@ -1095,8 +1094,8 @@ func (s *IntegrationCLITestSuite) TestNodeRenameCommand() {
"create-node",
"--name",
fmt.Sprintf("machine-%d", index+1),
"--namespace",
namespace.Name,
"--user",
user.Name,
"--key",
machineKey,
"--output",
@@ -1111,8 +1110,8 @@ func (s *IntegrationCLITestSuite) TestNodeRenameCommand() {
[]string{
"headscale",
"nodes",
"--namespace",
namespace.Name,
"--user",
user.Name,
"register",
"--key",
machineKey,
@@ -1389,9 +1388,9 @@ func (s *IntegrationCLITestSuite) TestApiKeyCommand() {
}
func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
oldNamespace, err := s.createNamespace("old-namespace")
oldUser, err := s.createUser("old-user")
assert.Nil(s.T(), err)
newNamespace, err := s.createNamespace("new-namespace")
newUser, err := s.createUser("new-user")
assert.Nil(s.T(), err)
// Randomly generated machine key
@@ -1405,8 +1404,8 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
"create-node",
"--name",
"nomad-machine",
"--namespace",
oldNamespace.Name,
"--user",
oldUser.Name,
"--key",
machineKey,
"--output",
@@ -1421,8 +1420,8 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
[]string{
"headscale",
"nodes",
"--namespace",
oldNamespace.Name,
"--user",
oldUser.Name,
"register",
"--key",
machineKey,
@@ -1439,7 +1438,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.Namespace.Name, oldNamespace.Name)
assert.Equal(s.T(), machine.User.Name, oldUser.Name)
machineId := fmt.Sprintf("%d", machine.Id)
@@ -1451,8 +1450,8 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
"move",
"--identifier",
machineId,
"--namespace",
newNamespace.Name,
"--user",
newUser.Name,
"--output",
"json",
},
@@ -1463,7 +1462,7 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
err = json.Unmarshal([]byte(moveToNewNSResult), &machine)
assert.Nil(s.T(), err)
assert.Equal(s.T(), machine.Namespace, newNamespace)
assert.Equal(s.T(), machine.User, newUser)
listAllNodesResult, _, err := ExecuteCommand(
&s.headscale,
@@ -1485,8 +1484,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].Namespace, machine.Namespace)
assert.Equal(s.T(), allNodes[0].Namespace, newNamespace)
assert.Equal(s.T(), allNodes[0].User, machine.User)
assert.Equal(s.T(), allNodes[0].User, newUser)
moveToNonExistingNSResult, _, err := ExecuteCommand(
&s.headscale,
@@ -1496,8 +1495,8 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
"move",
"--identifier",
machineId,
"--namespace",
"non-existing-namespace",
"--user",
"non-existing-user",
"--output",
"json",
},
@@ -1508,9 +1507,9 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
assert.Contains(
s.T(),
string(moveToNonExistingNSResult),
"Namespace not found",
"User not found",
)
assert.Equal(s.T(), machine.Namespace, newNamespace)
assert.Equal(s.T(), machine.User, newUser)
moveToOldNSResult, _, err := ExecuteCommand(
&s.headscale,
@@ -1520,8 +1519,8 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
"move",
"--identifier",
machineId,
"--namespace",
oldNamespace.Name,
"--user",
oldUser.Name,
"--output",
"json",
},
@@ -1532,7 +1531,7 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
err = json.Unmarshal([]byte(moveToOldNSResult), &machine)
assert.Nil(s.T(), err)
assert.Equal(s.T(), machine.Namespace, oldNamespace)
assert.Equal(s.T(), machine.User, oldUser)
moveToSameNSResult, _, err := ExecuteCommand(
&s.headscale,
@@ -1542,8 +1541,8 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
"move",
"--identifier",
machineId,
"--namespace",
oldNamespace.Name,
"--user",
oldUser.Name,
"--output",
"json",
},
@@ -1554,7 +1553,7 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
err = json.Unmarshal([]byte(moveToSameNSResult), &machine)
assert.Nil(s.T(), err)
assert.Equal(s.T(), machine.Namespace, oldNamespace)
assert.Equal(s.T(), machine.User, oldUser)
}
func (s *IntegrationCLITestSuite) TestLoadConfigFromCommand() {
+3 -77
View File
@@ -1,4 +1,4 @@
//nolint
// nolint
package headscale
import (
@@ -9,7 +9,6 @@ import (
"net/netip"
"os"
"strconv"
"strings"
"time"
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
@@ -32,7 +31,8 @@ var (
tailscaleVersions = []string{
"head",
"unstable",
"1.34.0",
"1.36.2",
"1.34.2",
"1.32.3",
"1.30.2",
"1.28.0",
@@ -47,11 +47,6 @@ var (
}
)
type TestNamespace struct {
count int
tailscales map[string]dockertest.Resource
}
type ExecuteCommandConfig struct {
timeout time.Duration
}
@@ -201,38 +196,6 @@ func getDockerBuildOptions(version string) *dockertest.BuildOptions {
return tailscaleBuildOptions
}
func getIPs(
tailscales map[string]dockertest.Resource,
) (map[string][]netip.Addr, error) {
ips := make(map[string][]netip.Addr)
for hostname, tailscale := range tailscales {
command := []string{"tailscale", "ip"}
result, _, err := ExecuteCommand(
&tailscale,
command,
[]string{},
)
if err != nil {
return nil, err
}
for _, address := range strings.Split(result, "\n") {
address = strings.TrimSuffix(address, "\n")
if len(address) < 1 {
continue
}
ip, err := netip.ParseAddr(address)
if err != nil {
return nil, err
}
ips[hostname] = append(ips[hostname], ip)
}
}
return ips, nil
}
func getDNSNames(
headscale *dockertest.Resource,
) ([]string, error) {
@@ -266,43 +229,6 @@ func getDNSNames(
return hostnames, nil
}
func getMagicFQDN(
headscale *dockertest.Resource,
) ([]string, error) {
listAllResult, _, err := ExecuteCommand(
headscale,
[]string{
"headscale",
"nodes",
"list",
"--output",
"json",
},
[]string{},
)
if err != nil {
return nil, err
}
var listAll []v1.Machine
err = json.Unmarshal([]byte(listAllResult), &listAll)
if err != nil {
return nil, err
}
hostnames := make([]string, len(listAll))
for index := range listAll {
hostnames[index] = fmt.Sprintf(
"%s.%s.headscale.net",
listAll[index].GetGivenName(),
listAll[index].GetNamespace().GetName(),
)
}
return hostnames, nil
}
func GetEnvStr(key string) (string, error) {
v := os.Getenv(key)
if v == "" {
+10 -10
View File
@@ -1,4 +1,4 @@
//nolint
// nolint
package headscale
import (
@@ -26,7 +26,7 @@ import (
const (
headscaleDerpHostname = "headscale-derp"
namespaceName = "derpnamespace"
userName = "derpuser"
totalContainers = 3
)
@@ -199,22 +199,22 @@ func (s *IntegrationDERPTestSuite) SetupSuite() {
}
log.Println("headscale container is ready for embedded DERP tests")
log.Printf("Creating headscale namespace: %s\n", namespaceName)
log.Printf("Creating headscale user: %s\n", userName)
result, _, err := ExecuteCommand(
&s.headscale,
[]string{"headscale", "namespaces", "create", namespaceName},
[]string{"headscale", "users", "create", userName},
[]string{},
)
log.Println("headscale create namespace result: ", result)
log.Println("headscale create user result: ", result)
assert.Nil(s.T(), err)
log.Printf("Creating pre auth key for %s\n", namespaceName)
log.Printf("Creating pre auth key for %s\n", userName)
preAuthResult, _, err := ExecuteCommand(
&s.headscale,
[]string{
"headscale",
"--namespace",
namespaceName,
"--user",
userName,
"preauthkeys",
"create",
"--reusable",
@@ -382,7 +382,7 @@ func (s *IntegrationDERPTestSuite) saveLog(
err = os.WriteFile(
path.Join(basePath, resource.Container.Name+".stdout.log"),
[]byte(stdout.String()),
stderr.Bytes(),
0o644,
)
if err != nil {
@@ -391,7 +391,7 @@ func (s *IntegrationDERPTestSuite) saveLog(
err = os.WriteFile(
path.Join(basePath, resource.Container.Name+".stderr.log"),
[]byte(stdout.String()),
stderr.Bytes(),
0o644,
)
if err != nil {
@@ -37,12 +37,14 @@ logtail:
enabled: false
metrics_listen_addr: 127.0.0.1:19090
oidc:
expiry: 180d
only_start_if_oidc_is_available: true
scope:
- openid
- profile
- email
strip_email_domain: true
use_expiry_from_token: false
private_key_path: private.key
noise:
private_key_path: noise_private.key
@@ -36,12 +36,14 @@ logtail:
enabled: false
metrics_listen_addr: 127.0.0.1:19090
oidc:
expiry: 180d
only_start_if_oidc_is_available: true
scope:
- openid
- profile
- email
strip_email_domain: true
use_expiry_from_token: false
private_key_path: private.key
noise:
private_key_path: noise_private.key
@@ -37,12 +37,14 @@ logtail:
enabled: false
metrics_listen_addr: 127.0.0.1:9090
oidc:
expiry: 180d
only_start_if_oidc_is_available: true
scope:
- openid
- profile
- email
strip_email_domain: true
use_expiry_from_token: false
private_key_path: private.key
noise:
private_key_path: noise_private.key

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