mirror of
				https://github.com/juanfont/headscale.git
				synced 2025-11-01 05:27:44 +09:00 
			
		
		
		
	Merge master
This commit is contained in:
		
							
								
								
									
										17
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -22,30 +22,21 @@ jobs: | ||||
|         uses: tj-actions/changed-files@v14.1 | ||||
|         with: | ||||
|           files: | | ||||
|             *.nix | ||||
|             go.* | ||||
|             **/*.go | ||||
|             integration_test/ | ||||
|             config-example.yaml | ||||
|  | ||||
|       - name: Setup Go | ||||
|       - uses: cachix/install-nix-action@v16 | ||||
|         if: steps.changed-files.outputs.any_changed == 'true' | ||||
|         uses: actions/setup-go@v2 | ||||
|         with: | ||||
|           go-version: "1.18.0" | ||||
|  | ||||
|       - name: Install dependencies | ||||
|         if: steps.changed-files.outputs.any_changed == 'true' | ||||
|         run: | | ||||
|           go version | ||||
|           sudo apt update | ||||
|           sudo apt install -y make | ||||
|  | ||||
|       - name: Run build | ||||
|         if: steps.changed-files.outputs.any_changed == 'true' | ||||
|         run: make build | ||||
|         run: nix build | ||||
|  | ||||
|       - uses: actions/upload-artifact@v2 | ||||
|         if: steps.changed-files.outputs.any_changed == 'true' | ||||
|         with: | ||||
|           name: headscale-linux | ||||
|           path: headscale | ||||
|           path: result/bin/headscale | ||||
|   | ||||
							
								
								
									
										4
									
								
								.github/workflows/lint.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/lint.yml
									
									
									
									
										vendored
									
									
								
							| @@ -16,6 +16,7 @@ jobs: | ||||
|         uses: tj-actions/changed-files@v14.1 | ||||
|         with: | ||||
|           files: | | ||||
|             *.nix | ||||
|             go.* | ||||
|             **/*.go | ||||
|             integration_test/ | ||||
| @@ -25,7 +26,7 @@ jobs: | ||||
|         if: steps.changed-files.outputs.any_changed == 'true' | ||||
|         uses: golangci/golangci-lint-action@v2 | ||||
|         with: | ||||
|           version: latest | ||||
|           version: v1.46.1 | ||||
|  | ||||
|           # Only block PRs on new problems. | ||||
|           # If this is not enabled, we will end up having PRs | ||||
| @@ -45,6 +46,7 @@ jobs: | ||||
|         uses: tj-actions/changed-files@v14.1 | ||||
|         with: | ||||
|           files: | | ||||
|             *.nix | ||||
|             **/*.md | ||||
|             **/*.yml | ||||
|             **/*.yaml | ||||
|   | ||||
							
								
								
									
										8
									
								
								.github/workflows/test-integration.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/test-integration.yml
									
									
									
									
										vendored
									
									
								
							| @@ -16,17 +16,15 @@ jobs: | ||||
|         uses: tj-actions/changed-files@v14.1 | ||||
|         with: | ||||
|           files: | | ||||
|             *.nix | ||||
|             go.* | ||||
|             **/*.go | ||||
|             integration_test/ | ||||
|             config-example.yaml | ||||
|  | ||||
|       - name: Setup Go | ||||
|       - uses: cachix/install-nix-action@v16 | ||||
|         if: steps.changed-files.outputs.any_changed == 'true' | ||||
|         uses: actions/setup-go@v2 | ||||
|         with: | ||||
|           go-version: "1.18.0" | ||||
|  | ||||
|       - name: Run Integration tests | ||||
|         if: steps.changed-files.outputs.any_changed == 'true' | ||||
|         run: make test_integration | ||||
|         run: nix develop --command -- make test_integration | ||||
|   | ||||
							
								
								
									
										19
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							| @@ -16,28 +16,15 @@ jobs: | ||||
|         uses: tj-actions/changed-files@v14.1 | ||||
|         with: | ||||
|           files: | | ||||
|             *.nix | ||||
|             go.* | ||||
|             **/*.go | ||||
|             integration_test/ | ||||
|             config-example.yaml | ||||
|  | ||||
|       - name: Setup Go | ||||
|       - uses: cachix/install-nix-action@v16 | ||||
|         if: steps.changed-files.outputs.any_changed == 'true' | ||||
|         uses: actions/setup-go@v2 | ||||
|         with: | ||||
|           go-version: "1.18.0" | ||||
|  | ||||
|       - name: Install dependencies | ||||
|         if: steps.changed-files.outputs.any_changed == 'true' | ||||
|         run: | | ||||
|           go version | ||||
|           sudo apt update | ||||
|           sudo apt install -y make | ||||
|  | ||||
|       - name: Run tests | ||||
|         if: steps.changed-files.outputs.any_changed == 'true' | ||||
|         run: make test | ||||
|  | ||||
|       - name: Run build | ||||
|         if: steps.changed-files.outputs.any_changed == 'true' | ||||
|         run: make | ||||
|         run: nix develop --check | ||||
|   | ||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -28,6 +28,6 @@ derp.yaml | ||||
|  | ||||
| test_output/  | ||||
|  | ||||
| # Nix and direnv | ||||
| .direnv/ | ||||
| # Nix build output | ||||
| result | ||||
| .direnv/ | ||||
|   | ||||
| @@ -24,6 +24,8 @@ linters: | ||||
|     - tagliatelle | ||||
|     - godox | ||||
|     - ireturn | ||||
|     - execinquery | ||||
|     - exhaustruct | ||||
|  | ||||
|     # We should strive to enable these: | ||||
|     - wrapcheck | ||||
|   | ||||
| @@ -7,6 +7,12 @@ | ||||
| - Headscale fails to serve if the ACL policy file cannot be parsed [#537](https://github.com/juanfont/headscale/pull/537) | ||||
| - Fix labels cardinality error when registering unknown pre-auth key [#519](https://github.com/juanfont/headscale/pull/519) | ||||
| - Fix send on closed channel crash in polling [#542](https://github.com/juanfont/headscale/pull/542) | ||||
| - Fixed spurious calls to setLastStateChangeToNow from ephemeral nodes [#566](https://github.com/juanfont/headscale/pull/566) | ||||
| - Add command for moving nodes between namespaces [#362](https://github.com/juanfont/headscale/issues/362) | ||||
| - Added more configuration parameters for OpenID Connect (scopes, free-form paramters, domain and user allowlist) | ||||
| - Add command to set tags on a node [#525](https://github.com/juanfont/headscale/issues/525) | ||||
| - Add command to view tags of nodes [#356](https://github.com/juanfont/headscale/issues/356) | ||||
| - Add --all (-a) flag to enable routes command [#360](https://github.com/juanfont/headscale/issues/360) | ||||
|  | ||||
| ## 0.15.0 (2022-03-20) | ||||
|  | ||||
|   | ||||
							
								
								
									
										58
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								README.md
									
									
									
									
									
								
							| @@ -91,6 +91,10 @@ Please have a look at the documentation under [`docs/`](docs/). | ||||
| To contribute to headscale you would need the lastest version of [Go](https://golang.org) | ||||
| and [Buf](https://buf.build)(Protobuf generator). | ||||
|  | ||||
| We recommend using [Nix](https://nixos.org/) to setup a development environment. This can | ||||
| be done with `nix develop`, which will install the tools and give you a shell. | ||||
| This guarantees that you will have the same dev env as `headscale` maintainers. | ||||
|  | ||||
| PRs and suggestions are welcome. | ||||
|  | ||||
| ### Code style | ||||
| @@ -115,10 +119,12 @@ Check out the `.golangci.yaml` and `Makefile` to see the specific configuration. | ||||
|  | ||||
| - Go | ||||
| - Buf | ||||
| - Protobuf tools: | ||||
| - Protobuf tools | ||||
|  | ||||
| Install and activate: | ||||
|  | ||||
| ```shell | ||||
| make install-protobuf-plugins | ||||
| nix develop | ||||
| ``` | ||||
|  | ||||
| ### Testing and building | ||||
| @@ -140,6 +146,12 @@ make test | ||||
|  | ||||
| To build the program: | ||||
|  | ||||
| ```shell | ||||
| nix build | ||||
| ``` | ||||
|  | ||||
| or | ||||
|  | ||||
| ```shell | ||||
| make build | ||||
| ``` | ||||
| @@ -264,6 +276,13 @@ make build | ||||
|             <sub style="font-size:14px"><b>Hoàng Đức Hiếu</b></sub> | ||||
|         </a> | ||||
|     </td> | ||||
|     <td align="center" style="word-wrap: break-word; width: 150.0; height: 150.0"> | ||||
|         <a href=https://github.com/deonthomasgy> | ||||
|             <img src=https://avatars.githubusercontent.com/u/150036?v=4 width="100;"  style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Deon Thomas/> | ||||
|             <br /> | ||||
|             <sub style="font-size:14px"><b>Deon Thomas</b></sub> | ||||
|         </a> | ||||
|     </td> | ||||
|     <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/> | ||||
| @@ -271,6 +290,8 @@ make build | ||||
|             <sub style="font-size:14px"><b>Mevan Samaratunga</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/dragetd> | ||||
|             <img src=https://avatars.githubusercontent.com/u/3639577?v=4 width="100;"  style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Michael G./> | ||||
| @@ -278,8 +299,6 @@ make build | ||||
|             <sub style="font-size:14px"><b>Michael G.</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/ptman> | ||||
|             <img src=https://avatars.githubusercontent.com/u/24669?v=4 width="100;"  style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Paul Tötterman/> | ||||
| @@ -315,6 +334,8 @@ make build | ||||
|             <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/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/> | ||||
| @@ -322,8 +343,6 @@ make build | ||||
|             <sub style="font-size:14px"><b>lachy2849</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/t56k> | ||||
|             <img src=https://avatars.githubusercontent.com/u/12165422?v=4 width="100;"  style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=thomas/> | ||||
| @@ -338,6 +357,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/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/> | ||||
|             <br /> | ||||
|             <sub style="font-size:14px"><b>Antoine POPINEAU</b></sub> | ||||
|         </a> | ||||
|     </td> | ||||
|     <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/> | ||||
| @@ -352,6 +378,8 @@ make build | ||||
|             <sub style="font-size:14px"><b>Arthur Woimbée</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/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/> | ||||
| @@ -366,8 +394,6 @@ make build | ||||
|             <sub style="font-size:14px"><b> Carson Yang</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/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/> | ||||
| @@ -396,6 +422,8 @@ make build | ||||
|             <sub style="font-size:14px"><b>Jamie Greeff</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/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/> | ||||
| @@ -410,8 +438,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/rcursaru> | ||||
|             <img src=https://avatars.githubusercontent.com/u/16259641?v=4 width="100;"  style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=rcursaru/> | ||||
| @@ -440,6 +466,8 @@ 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/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/> | ||||
| @@ -454,8 +482,6 @@ make build | ||||
|             <sub style="font-size:14px"><b>Teteros</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/gitter-badger> | ||||
|             <img src=https://avatars.githubusercontent.com/u/8518239?v=4 width="100;"  style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=The Gitter Badger/> | ||||
| @@ -484,6 +510,8 @@ make build | ||||
|             <sub style="font-size:14px"><b>Yang Bin</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/zekker6> | ||||
|             <img src=https://avatars.githubusercontent.com/u/1367798?v=4 width="100;"  style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=Zakhar Bessarab/> | ||||
| @@ -498,8 +526,6 @@ make build | ||||
|             <sub style="font-size:14px"><b>ZiYuan</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/bravechamp> | ||||
|             <img src=https://avatars.githubusercontent.com/u/48980452?v=4 width="100;"  style="border-radius:50%;align-items:center;justify-content:center;overflow:hidden;padding-top:10px" alt=bravechamp/> | ||||
| @@ -528,6 +554,8 @@ make build | ||||
|             <sub style="font-size:14px"><b>ignoramous</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=lion24/> | ||||
| @@ -542,8 +570,6 @@ make build | ||||
|             <sub style="font-size:14px"><b>pernila</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/> | ||||
|   | ||||
							
								
								
									
										27
									
								
								acls.go
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								acls.go
									
									
									
									
									
								
							| @@ -2,6 +2,7 @@ package headscale | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"os" | ||||
| @@ -251,8 +252,27 @@ func expandAlias( | ||||
| 	if strings.HasPrefix(alias, "tag:") { | ||||
| 		owners, err := expandTagOwners(aclPolicy, alias, stripEmailDomain) | ||||
| 		if err != nil { | ||||
| 			if errors.Is(err, errInvalidTag) { | ||||
| 				for _, machine := range machines { | ||||
| 					for _, t := range machine.ForcedTags { | ||||
| 						if alias == t { | ||||
| 							ips = append(ips, machine.IPAddresses.ToStringSlice()...) | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				if len(ips) == 0 { | ||||
| 					return ips, fmt.Errorf( | ||||
| 						"%w. %v isn't owned by a TagOwner and no forced tags are defined", | ||||
| 						errInvalidTag, | ||||
| 						alias, | ||||
| 					) | ||||
| 				} | ||||
|  | ||||
| 				return ips, nil | ||||
| 			} else { | ||||
| 				return ips, err | ||||
| 			} | ||||
| 		} | ||||
| 		for _, namespace := range owners { | ||||
| 			machines := filterMachinesByNamespace(machines, namespace) | ||||
| 			for _, machine := range machines { | ||||
| @@ -312,7 +332,7 @@ func excludeCorrectlyTaggedNodes( | ||||
| 	out := []Machine{} | ||||
| 	tags := []string{} | ||||
| 	for tag, ns := range aclPolicy.TagOwners { | ||||
| 		if containsString(ns, namespace) { | ||||
| 		if contains(ns, namespace) { | ||||
| 			tags = append(tags, tag) | ||||
| 		} | ||||
| 	} | ||||
| @@ -322,12 +342,15 @@ func excludeCorrectlyTaggedNodes( | ||||
|  | ||||
| 		found := false | ||||
| 		for _, t := range hi.RequestTags { | ||||
| 			if containsString(tags, t) { | ||||
| 			if contains(tags, t) { | ||||
| 				found = true | ||||
|  | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 		if len(machine.ForcedTags) > 0 { | ||||
| 			found = true | ||||
| 		} | ||||
| 		if !found { | ||||
| 			out = append(out, machine) | ||||
| 		} | ||||
|   | ||||
							
								
								
									
										79
									
								
								acls_test.go
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								acls_test.go
									
									
									
									
									
								
							| @@ -1017,6 +1017,44 @@ func Test_expandAlias(t *testing.T) { | ||||
| 			want:    []string{}, | ||||
| 			wantErr: true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "Forced tag defined", | ||||
| 			args: args{ | ||||
| 				alias: "tag:hr-webserver", | ||||
| 				machines: []Machine{ | ||||
| 					{ | ||||
| 						IPAddresses: MachineAddresses{ | ||||
| 							netaddr.MustParseIP("100.64.0.1"), | ||||
| 						}, | ||||
| 						Namespace:  Namespace{Name: "joe"}, | ||||
| 						ForcedTags: []string{"tag:hr-webserver"}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						IPAddresses: MachineAddresses{ | ||||
| 							netaddr.MustParseIP("100.64.0.2"), | ||||
| 						}, | ||||
| 						Namespace:  Namespace{Name: "joe"}, | ||||
| 						ForcedTags: []string{"tag:hr-webserver"}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						IPAddresses: MachineAddresses{ | ||||
| 							netaddr.MustParseIP("100.64.0.3"), | ||||
| 						}, | ||||
| 						Namespace: Namespace{Name: "marc"}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						IPAddresses: MachineAddresses{ | ||||
| 							netaddr.MustParseIP("100.64.0.4"), | ||||
| 						}, | ||||
| 						Namespace: Namespace{Name: "mickael"}, | ||||
| 					}, | ||||
| 				}, | ||||
| 				aclPolicy:        ACLPolicy{}, | ||||
| 				stripEmailDomain: true, | ||||
| 			}, | ||||
| 			want:    []string{"100.64.0.1", "100.64.0.2"}, | ||||
| 			wantErr: false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "list host in namespace without correctly tagged servers", | ||||
| 			args: args{ | ||||
| @@ -1143,6 +1181,47 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "exclude nodes with valid tags and with forced tags", | ||||
| 			args: args{ | ||||
| 				aclPolicy: ACLPolicy{ | ||||
| 					TagOwners: TagOwners{"tag:accountant-webserver": []string{"joe"}}, | ||||
| 				}, | ||||
| 				nodes: []Machine{ | ||||
| 					{ | ||||
| 						IPAddresses: MachineAddresses{ | ||||
| 							netaddr.MustParseIP("100.64.0.1"), | ||||
| 						}, | ||||
| 						Namespace: Namespace{Name: "joe"}, | ||||
| 						HostInfo: HostInfo{ | ||||
| 							OS:          "centos", | ||||
| 							Hostname:    "foo", | ||||
| 							RequestTags: []string{"tag:accountant-webserver"}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						IPAddresses: MachineAddresses{ | ||||
| 							netaddr.MustParseIP("100.64.0.2"), | ||||
| 						}, | ||||
| 						Namespace:  Namespace{Name: "joe"}, | ||||
| 						ForcedTags: []string{"tag:accountant-webserver"}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						IPAddresses: MachineAddresses{ | ||||
| 							netaddr.MustParseIP("100.64.0.4"), | ||||
| 						}, | ||||
| 						Namespace: Namespace{Name: "joe"}, | ||||
| 					}, | ||||
| 				}, | ||||
| 				namespace: "joe", | ||||
| 			}, | ||||
| 			want: []Machine{ | ||||
| 				{ | ||||
| 					IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, | ||||
| 					Namespace:   Namespace{Name: "joe"}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "all nodes have invalid tags, don't exclude them", | ||||
| 			args: args{ | ||||
|   | ||||
							
								
								
									
										11
									
								
								app.go
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								app.go
									
									
									
									
									
								
							| @@ -119,6 +119,10 @@ type OIDCConfig struct { | ||||
| 	Issuer           string | ||||
| 	ClientID         string | ||||
| 	ClientSecret     string | ||||
| 	Scope            []string | ||||
| 	ExtraParams      map[string]string | ||||
| 	AllowedDomains   []string | ||||
| 	AllowedUsers     []string | ||||
| 	StripEmaildomain bool | ||||
| } | ||||
|  | ||||
| @@ -292,11 +296,13 @@ func (h *Headscale) expireEphemeralNodesWorker() { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		expiredFound := false | ||||
| 		for _, machine := range machines { | ||||
| 			if machine.AuthKey != nil && machine.LastSeen != nil && | ||||
| 				machine.AuthKey.Ephemeral && | ||||
| 				time.Now(). | ||||
| 					After(machine.LastSeen.Add(h.cfg.EphemeralNodeInactivityTimeout)) { | ||||
| 				expiredFound = true | ||||
| 				log.Info(). | ||||
| 					Str("machine", machine.Hostname). | ||||
| 					Msg("Ephemeral client removed from database") | ||||
| @@ -311,14 +317,17 @@ func (h *Headscale) expireEphemeralNodesWorker() { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if expiredFound { | ||||
| 			h.setLastStateChangeToNow(namespace.Name) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (h *Headscale) grpcAuthenticationInterceptor(ctx context.Context, | ||||
| 	req interface{}, | ||||
| 	info *grpc.UnaryServerInfo, | ||||
| 	handler grpc.UnaryHandler) (interface{}, error) { | ||||
| 	handler grpc.UnaryHandler, | ||||
| ) (interface{}, error) { | ||||
| 	// Check if the request is coming from the on-server client. | ||||
| 	// This is not secure, but it is to maintain maintainability | ||||
| 	// with the "legacy" database-based client | ||||
|   | ||||
| @@ -13,12 +13,14 @@ import ( | ||||
| 	"github.com/pterm/pterm" | ||||
| 	"github.com/spf13/cobra" | ||||
| 	"google.golang.org/grpc/status" | ||||
| 	"inet.af/netaddr" | ||||
| 	"tailscale.com/types/key" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	rootCmd.AddCommand(nodeCmd) | ||||
| 	listNodesCmd.Flags().StringP("namespace", "n", "", "Filter by namespace") | ||||
| 	listNodesCmd.Flags().BoolP("tags", "t", false, "Show tags") | ||||
| 	nodeCmd.AddCommand(listNodesCmd) | ||||
|  | ||||
| 	registerNodeCmd.Flags().StringP("namespace", "n", "", "Namespace") | ||||
| @@ -53,6 +55,31 @@ func init() { | ||||
| 		log.Fatalf(err.Error()) | ||||
| 	} | ||||
| 	nodeCmd.AddCommand(deleteNodeCmd) | ||||
|  | ||||
| 	moveNodeCmd.Flags().Uint64P("identifier", "i", 0, "Node identifier (ID)") | ||||
|  | ||||
| 	err = moveNodeCmd.MarkFlagRequired("identifier") | ||||
| 	if err != nil { | ||||
| 		log.Fatalf(err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	moveNodeCmd.Flags().StringP("namespace", "n", "", "New namespace") | ||||
|  | ||||
| 	err = moveNodeCmd.MarkFlagRequired("namespace") | ||||
| 	if err != nil { | ||||
| 		log.Fatalf(err.Error()) | ||||
| 	} | ||||
| 	nodeCmd.AddCommand(moveNodeCmd) | ||||
|  | ||||
| 	tagCmd.Flags().Uint64P("identifier", "i", 0, "Node identifier (ID)") | ||||
|  | ||||
| 	err = tagCmd.MarkFlagRequired("identifier") | ||||
| 	if err != nil { | ||||
| 		log.Fatalf(err.Error()) | ||||
| 	} | ||||
| 	tagCmd.Flags(). | ||||
| 		StringSliceP("tags", "t", []string{}, "List of tags to add to the node") | ||||
| 	nodeCmd.AddCommand(tagCmd) | ||||
| } | ||||
|  | ||||
| var nodeCmd = &cobra.Command{ | ||||
| @@ -123,6 +150,12 @@ var listNodesCmd = &cobra.Command{ | ||||
|  | ||||
| 			return | ||||
| 		} | ||||
| 		showTags, err := cmd.Flags().GetBool("tags") | ||||
| 		if err != nil { | ||||
| 			ErrorOutput(err, fmt.Sprintf("Error getting tags flag: %s", err), output) | ||||
|  | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		ctx, client, conn, cancel := getHeadscaleCLIClient() | ||||
| 		defer cancel() | ||||
| @@ -149,7 +182,7 @@ var listNodesCmd = &cobra.Command{ | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		tableData, err := nodesToPtables(namespace, response.Machines) | ||||
| 		tableData, err := nodesToPtables(namespace, showTags, response.Machines) | ||||
| 		if err != nil { | ||||
| 			ErrorOutput(err, fmt.Sprintf("Error converting to table: %s", err), output) | ||||
|  | ||||
| @@ -351,15 +384,88 @@ var deleteNodeCmd = &cobra.Command{ | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var moveNodeCmd = &cobra.Command{ | ||||
| 	Use:     "move", | ||||
| 	Short:   "Move node to another namespace", | ||||
| 	Aliases: []string{"mv"}, | ||||
| 	Run: func(cmd *cobra.Command, args []string) { | ||||
| 		output, _ := cmd.Flags().GetString("output") | ||||
|  | ||||
| 		identifier, err := cmd.Flags().GetUint64("identifier") | ||||
| 		if err != nil { | ||||
| 			ErrorOutput( | ||||
| 				err, | ||||
| 				fmt.Sprintf("Error converting ID to integer: %s", err), | ||||
| 				output, | ||||
| 			) | ||||
|  | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		namespace, err := cmd.Flags().GetString("namespace") | ||||
| 		if err != nil { | ||||
| 			ErrorOutput( | ||||
| 				err, | ||||
| 				fmt.Sprintf("Error getting namespace: %s", err), | ||||
| 				output, | ||||
| 			) | ||||
|  | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		ctx, client, conn, cancel := getHeadscaleCLIClient() | ||||
| 		defer cancel() | ||||
| 		defer conn.Close() | ||||
|  | ||||
| 		getRequest := &v1.GetMachineRequest{ | ||||
| 			MachineId: identifier, | ||||
| 		} | ||||
|  | ||||
| 		_, err = client.GetMachine(ctx, getRequest) | ||||
| 		if err != nil { | ||||
| 			ErrorOutput( | ||||
| 				err, | ||||
| 				fmt.Sprintf( | ||||
| 					"Error getting node: %s", | ||||
| 					status.Convert(err).Message(), | ||||
| 				), | ||||
| 				output, | ||||
| 			) | ||||
|  | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		moveRequest := &v1.MoveMachineRequest{ | ||||
| 			MachineId: identifier, | ||||
| 			Namespace: namespace, | ||||
| 		} | ||||
|  | ||||
| 		moveResponse, err := client.MoveMachine(ctx, moveRequest) | ||||
| 		if err != nil { | ||||
| 			ErrorOutput( | ||||
| 				err, | ||||
| 				fmt.Sprintf( | ||||
| 					"Error moving node: %s", | ||||
| 					status.Convert(err).Message(), | ||||
| 				), | ||||
| 				output, | ||||
| 			) | ||||
|  | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		SuccessOutput(moveResponse.Machine, "Node moved to another namespace", output) | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| func nodesToPtables( | ||||
| 	currentNamespace string, | ||||
| 	showTags bool, | ||||
| 	machines []*v1.Machine, | ||||
| ) (pterm.TableData, error) { | ||||
| 	tableData := pterm.TableData{ | ||||
| 		{ | ||||
| 	tableHeader := []string{ | ||||
| 		"ID", | ||||
| 			"Hostname", | ||||
| 			"Friendly name", | ||||
| 		"Name", | ||||
| 		"NodeKey", | ||||
| 		"Namespace", | ||||
| 		"IP addresses", | ||||
| @@ -367,8 +473,15 @@ func nodesToPtables( | ||||
| 		"Last seen", | ||||
| 		"Online", | ||||
| 		"Expired", | ||||
| 		}, | ||||
| 	} | ||||
| 	if showTags { | ||||
| 		tableHeader = append(tableHeader, []string{ | ||||
| 			"ForcedTags", | ||||
| 			"InvalidTags", | ||||
| 			"ValidTags", | ||||
| 		}...) | ||||
| 	} | ||||
| 	tableData := pterm.TableData{tableHeader} | ||||
|  | ||||
| 	for _, machine := range machines { | ||||
| 		var ephemeral bool | ||||
| @@ -412,6 +525,26 @@ func nodesToPtables( | ||||
| 			expired = pterm.LightRed("yes") | ||||
| 		} | ||||
|  | ||||
| 		var forcedTags string | ||||
| 		for _, tag := range machine.ForcedTags { | ||||
| 			forcedTags += "," + tag | ||||
| 		} | ||||
| 		forcedTags = strings.TrimLeft(forcedTags, ",") | ||||
| 		var invalidTags string | ||||
| 		for _, tag := range machine.InvalidTags { | ||||
| 			if !contains(machine.ForcedTags, tag) { | ||||
| 				invalidTags += "," + pterm.LightRed(tag) | ||||
| 			} | ||||
| 		} | ||||
| 		invalidTags = strings.TrimLeft(invalidTags, ",") | ||||
| 		var validTags string | ||||
| 		for _, tag := range machine.ValidTags { | ||||
| 			if !contains(machine.ForcedTags, tag) { | ||||
| 				validTags += "," + pterm.LightGreen(tag) | ||||
| 			} | ||||
| 		} | ||||
| 		validTags = strings.TrimLeft(validTags, ",") | ||||
|  | ||||
| 		var namespace string | ||||
| 		if currentNamespace == "" || (currentNamespace == machine.Namespace.Name) { | ||||
| 			namespace = pterm.LightMagenta(machine.Namespace.Name) | ||||
| @@ -419,22 +552,94 @@ func nodesToPtables( | ||||
| 			// Shared into this namespace | ||||
| 			namespace = pterm.LightYellow(machine.Namespace.Name) | ||||
| 		} | ||||
| 		tableData = append( | ||||
| 			tableData, | ||||
| 			[]string{ | ||||
|  | ||||
| 		var IPV4Address string | ||||
| 		var IPV6Address string | ||||
| 		for _, addr := range machine.IpAddresses { | ||||
| 			if netaddr.MustParseIP(addr).Is4() { | ||||
| 				IPV4Address = addr | ||||
| 			} else { | ||||
| 				IPV6Address = addr | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		nodeData := []string{ | ||||
| 			strconv.FormatUint(machine.Id, headscale.Base10), | ||||
| 			machine.Name, | ||||
| 				machine.GivenName, | ||||
| 			nodeKey.ShortString(), | ||||
| 			namespace, | ||||
| 				strings.Join(machine.IpAddresses, ", "), | ||||
| 			strings.Join([]string{IPV4Address, IPV6Address}, ", "), | ||||
| 			strconv.FormatBool(ephemeral), | ||||
| 			lastSeenTime, | ||||
| 			online, | ||||
| 			expired, | ||||
| 			}, | ||||
| 		} | ||||
| 		if showTags { | ||||
| 			nodeData = append(nodeData, []string{forcedTags, invalidTags, validTags}...) | ||||
| 		} | ||||
| 		tableData = append( | ||||
| 			tableData, | ||||
| 			nodeData, | ||||
| 		) | ||||
| 	} | ||||
|  | ||||
| 	return tableData, nil | ||||
| } | ||||
|  | ||||
| var tagCmd = &cobra.Command{ | ||||
| 	Use:     "tag", | ||||
| 	Short:   "Manage the tags of a node", | ||||
| 	Aliases: []string{"tags", "t"}, | ||||
| 	Run: func(cmd *cobra.Command, args []string) { | ||||
| 		output, _ := cmd.Flags().GetString("output") | ||||
| 		ctx, client, conn, cancel := getHeadscaleCLIClient() | ||||
| 		defer cancel() | ||||
| 		defer conn.Close() | ||||
|  | ||||
| 		// retrieve flags from CLI | ||||
| 		identifier, err := cmd.Flags().GetUint64("identifier") | ||||
| 		if err != nil { | ||||
| 			ErrorOutput( | ||||
| 				err, | ||||
| 				fmt.Sprintf("Error converting ID to integer: %s", err), | ||||
| 				output, | ||||
| 			) | ||||
|  | ||||
| 			return | ||||
| 		} | ||||
| 		tagsToSet, err := cmd.Flags().GetStringSlice("tags") | ||||
| 		if err != nil { | ||||
| 			ErrorOutput( | ||||
| 				err, | ||||
| 				fmt.Sprintf("Error retrieving list of tags to add to machine, %v", err), | ||||
| 				output, | ||||
| 			) | ||||
|  | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		// Sending tags to machine | ||||
| 		request := &v1.SetTagsRequest{ | ||||
| 			MachineId: identifier, | ||||
| 			Tags:      tagsToSet, | ||||
| 		} | ||||
| 		resp, err := client.SetTags(ctx, request) | ||||
| 		if err != nil { | ||||
| 			ErrorOutput( | ||||
| 				err, | ||||
| 				fmt.Sprintf("Error while sending tags to headscale: %s", err), | ||||
| 				output, | ||||
| 			) | ||||
|  | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		if resp != nil { | ||||
| 			SuccessOutput( | ||||
| 				resp.GetMachine(), | ||||
| 				"Machine updated", | ||||
| 				output, | ||||
| 			) | ||||
| 		} | ||||
| 	}, | ||||
| } | ||||
|   | ||||
| @@ -24,6 +24,8 @@ func init() { | ||||
| 	enableRouteCmd.Flags(). | ||||
| 		StringSliceP("route", "r", []string{}, "List (or repeated flags) of routes to enable") | ||||
| 	enableRouteCmd.Flags().Uint64P("identifier", "i", 0, "Node identifier (ID)") | ||||
| 	enableRouteCmd.Flags().BoolP("all", "a", false, "All routes from host") | ||||
|  | ||||
| 	err = enableRouteCmd.MarkFlagRequired("identifier") | ||||
| 	if err != nil { | ||||
| 		log.Fatalf(err.Error()) | ||||
| @@ -125,7 +127,32 @@ omit the route you do not want to enable. | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		routes, err := cmd.Flags().GetStringSlice("route") | ||||
| 		ctx, client, conn, cancel := getHeadscaleCLIClient() | ||||
| 		defer cancel() | ||||
| 		defer conn.Close() | ||||
|  | ||||
| 		var routes []string | ||||
|  | ||||
| 		isAll, _ := cmd.Flags().GetBool("all") | ||||
| 		if isAll { | ||||
| 			response, err := client.GetMachineRoute(ctx, &v1.GetMachineRouteRequest{ | ||||
| 				MachineId: machineID, | ||||
| 			}) | ||||
| 			if err != nil { | ||||
| 				ErrorOutput( | ||||
| 					err, | ||||
| 					fmt.Sprintf( | ||||
| 						"Cannot get machine routes: %s\n", | ||||
| 						status.Convert(err).Message(), | ||||
| 					), | ||||
| 					output, | ||||
| 				) | ||||
|  | ||||
| 				return | ||||
| 			} | ||||
| 			routes = response.GetRoutes().GetAdvertisedRoutes() | ||||
| 		} else { | ||||
| 			routes, err = cmd.Flags().GetStringSlice("route") | ||||
| 			if err != nil { | ||||
| 				ErrorOutput( | ||||
| 					err, | ||||
| @@ -135,10 +162,7 @@ omit the route you do not want to enable. | ||||
|  | ||||
| 				return | ||||
| 			} | ||||
|  | ||||
| 		ctx, client, conn, cancel := getHeadscaleCLIClient() | ||||
| 		defer cancel() | ||||
| 		defer conn.Close() | ||||
| 		} | ||||
|  | ||||
| 		request := &v1.EnableMachineRoutesRequest{ | ||||
| 			MachineId: machineID, | ||||
|   | ||||
| @@ -10,10 +10,12 @@ import ( | ||||
| 	"net/url" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/coreos/go-oidc/v3/oidc" | ||||
| 	"github.com/juanfont/headscale" | ||||
| 	v1 "github.com/juanfont/headscale/gen/go/headscale/v1" | ||||
| 	"github.com/rs/zerolog/log" | ||||
| @@ -67,6 +69,7 @@ func LoadConfig(path string) error { | ||||
| 	viper.SetDefault("cli.timeout", "5s") | ||||
| 	viper.SetDefault("cli.insecure", false) | ||||
|  | ||||
| 	viper.SetDefault("oidc.scope", []string{oidc.ScopeOpenID, "profile", "email"}) | ||||
| 	viper.SetDefault("oidc.strip_email_domain", true) | ||||
|  | ||||
| 	if err := viper.ReadInConfig(); err != nil { | ||||
| @@ -127,7 +130,8 @@ func GetDERPConfig() headscale.DERPConfig { | ||||
| 	stunAddr := viper.GetString("derp.server.stun_listen_addr") | ||||
|  | ||||
| 	if serverEnabled && stunAddr == "" { | ||||
| 		log.Fatal().Msg("derp.server.stun_listen_addr must be set if derp.server.enabled is true") | ||||
| 		log.Fatal(). | ||||
| 			Msg("derp.server.stun_listen_addr must be set if derp.server.enabled is true") | ||||
| 	} | ||||
|  | ||||
| 	urlStrs := viper.GetStringSlice("derp.urls") | ||||
| @@ -367,6 +371,10 @@ func getHeadscaleConfig() headscale.Config { | ||||
| 			Issuer:           viper.GetString("oidc.issuer"), | ||||
| 			ClientID:         viper.GetString("oidc.client_id"), | ||||
| 			ClientSecret:     viper.GetString("oidc.client_secret"), | ||||
| 			Scope:            viper.GetStringSlice("oidc.scope"), | ||||
| 			ExtraParams:      viper.GetStringMapString("oidc.extra_params"), | ||||
| 			AllowedDomains:   viper.GetStringSlice("oidc.allowed_domains"), | ||||
| 			AllowedUsers:     viper.GetStringSlice("oidc.allowed_users"), | ||||
| 			StripEmaildomain: viper.GetBool("oidc.strip_email_domain"), | ||||
| 		}, | ||||
|  | ||||
| @@ -563,3 +571,13 @@ func GetFileMode(key string) fs.FileMode { | ||||
|  | ||||
| 	return fs.FileMode(mode) | ||||
| } | ||||
|  | ||||
| func contains[T string](ts []T, t T) bool { | ||||
| 	for _, v := range ts { | ||||
| 		if reflect.DeepEqual(v, t) { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| } | ||||
|   | ||||
| @@ -214,6 +214,21 @@ unix_socket_permission: "0770" | ||||
| #   client_id: "your-oidc-client-id" | ||||
| #   client_secret: "your-oidc-client-secret" | ||||
| # | ||||
| #   Customize the scopes used in the OIDC flow, defaults to "openid", "profile" and "email" and add custom query | ||||
| #   parameters to the Authorize Endpoint request. Scopes default to "openid", "profile" and "email". | ||||
| # | ||||
| #   scope: ["openid", "profile", "email", "custom"] | ||||
| #   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. | ||||
| # | ||||
| #   allowed_domains: | ||||
| #     - example.com | ||||
| #   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 | ||||
|   | ||||
| @@ -107,7 +107,10 @@ func (h *Headscale) DERPHandler(ctx *gin.Context) { | ||||
| 	hijacker, ok := ctx.Writer.(http.Hijacker) | ||||
| 	if !ok { | ||||
| 		log.Error().Caller().Msg("DERP requires Hijacker interface from Gin") | ||||
| 		ctx.String(http.StatusInternalServerError, "HTTP does not support general TCP support") | ||||
| 		ctx.String( | ||||
| 			http.StatusInternalServerError, | ||||
| 			"HTTP does not support general TCP support", | ||||
| 		) | ||||
|  | ||||
| 		return | ||||
| 	} | ||||
| @@ -115,7 +118,10 @@ func (h *Headscale) DERPHandler(ctx *gin.Context) { | ||||
| 	netConn, conn, err := hijacker.Hijack() | ||||
| 	if err != nil { | ||||
| 		log.Error().Caller().Err(err).Msgf("Hijack failed") | ||||
| 		ctx.String(http.StatusInternalServerError, "HTTP does not support general TCP support") | ||||
| 		ctx.String( | ||||
| 			http.StatusInternalServerError, | ||||
| 			"HTTP does not support general TCP support", | ||||
| 		) | ||||
|  | ||||
| 		return | ||||
| 	} | ||||
| @@ -163,7 +169,10 @@ func (h *Headscale) DERPBootstrapDNSHandler(ctx *gin.Context) { | ||||
| 		for _, node := range region.Nodes { // we don't care if we override some nodes | ||||
| 			addrs, err := r.LookupIP(resolvCtx, "ip", node.HostName) | ||||
| 			if err != nil { | ||||
| 				log.Trace().Caller().Err(err).Msgf("bootstrap DNS lookup failed %q", node.HostName) | ||||
| 				log.Trace(). | ||||
| 					Caller(). | ||||
| 					Err(err). | ||||
| 					Msgf("bootstrap DNS lookup failed %q", node.HostName) | ||||
|  | ||||
| 				continue | ||||
| 			} | ||||
|   | ||||
							
								
								
									
										47
									
								
								docs/acls.md
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								docs/acls.md
									
									
									
									
									
								
							| @@ -5,12 +5,16 @@ ACL's are the most useful). | ||||
|  | ||||
| We have a small company with a boss, an admin, two developers and an intern. | ||||
|  | ||||
| The boss should have access to all servers but not to the users hosts. Admin | ||||
| The boss should have access to all servers but not to the user's hosts. Admin | ||||
| should also have access to all hosts except that their permissions should be | ||||
| limited to maintaining the hosts (for example purposes). The developers can do | ||||
| anything they want on dev hosts, but only watch on productions hosts. Intern | ||||
| anything they want on dev hosts but only watch on productions hosts. Intern | ||||
| can only interact with the development servers. | ||||
|  | ||||
| There's an additional server that acts as a router, connecting the VPN users | ||||
| to an internal network `10.20.0.0/16`. Developers must have access to those | ||||
| internal resources. | ||||
|  | ||||
| Each user have at least a device connected to the network and we have some | ||||
| servers. | ||||
|  | ||||
| @@ -19,22 +23,19 @@ servers. | ||||
| - app-server1.prod | ||||
| - app-server1.dev | ||||
| - billing.internal | ||||
| - router.internal | ||||
|  | ||||
| ## Setup of the network | ||||
|  | ||||
|  | ||||
| Let's create the namespaces. Each user should have his own namespace. The users | ||||
| here are represented as namespaces. | ||||
| ## ACL setup | ||||
|  | ||||
| ```bash | ||||
| headscale namespaces create boss | ||||
| headscale namespaces create admin1 | ||||
| headscale namespaces create dev1 | ||||
| headscale namespaces create dev2 | ||||
| headscale namespaces create intern1 | ||||
| ``` | ||||
| Note: Namespaces will be created automatically when users authenticate with the | ||||
| Headscale server. | ||||
|  | ||||
| We don't need to create namespaces for the servers because the servers will be | ||||
| tagged. When registering the servers we will need to add the flag | ||||
| 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 | ||||
| `--advertised-tags=tag:<tag1>,tag:<tag2>`, and the user (namespace) that is | ||||
| registering the server should be allowed to do it. Since anyone can add tags to | ||||
| a server they can register, the check of the tags is done on headscale server | ||||
| @@ -70,6 +71,14 @@ Here are the ACL's to implement the same permissions as above: | ||||
|  | ||||
|     // interns cannot add servers | ||||
|   }, | ||||
|   // hosts should be defined using its IP addresses and a subnet mask. | ||||
|   // to define a single host, use a /32 mask. You cannot use DNS entries here, | ||||
|   // as they're prone to be hijacked by replacing their IP addresses. | ||||
|   // see https://github.com/tailscale/tailscale/issues/3800 for more information. | ||||
|   "Hosts": { | ||||
|     "postgresql.internal": "10.20.0.2/32", | ||||
|     "webservers.internal": "10.20.10.1/29" | ||||
|   }, | ||||
|   "acls": [ | ||||
|     // boss have access to all servers | ||||
|     { | ||||
| @@ -108,6 +117,16 @@ Here are the ACL's to implement the same permissions as above: | ||||
|         "tag:prod-app-servers:80,443" | ||||
|       ] | ||||
|     }, | ||||
|     // developers have access to the internal network through the router. | ||||
|     // the internal network is composed of HTTPS endpoints and Postgresql | ||||
|     // database servers. There's an additional rule to allow traffic to be | ||||
|     // forwarded to the internal subnet, 10.20.0.0/16. See this issue | ||||
|     // https://github.com/juanfont/headscale/issues/502 | ||||
|     { | ||||
|       "action": "accept", | ||||
|       "users": ["group:dev"], | ||||
|       "ports": ["10.20.0.0/16:443,5432", "router.internal:0"] | ||||
|     }, | ||||
|  | ||||
|     // servers should be able to talk to database. Database should not be able to initiate connections to | ||||
|     // applications servers | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								docs/images/headscale-acl-network.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/images/headscale-acl-network.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 56 KiB | 
| @@ -24,7 +24,7 @@ To create a API key, log into your `headscale` server and generate a key: | ||||
| headscale apikeys create --expiration 90d | ||||
| ``` | ||||
|  | ||||
| Copy the output of the command and save it for later. Please not that you can not retrieve a key again, | ||||
| Copy the output of the command and save it for later. Please note that you can not retrieve a key again, | ||||
| if the key is lost, expire the old one, and create a new key. | ||||
|  | ||||
| To list the keys currently assosicated with the server: | ||||
|   | ||||
							
								
								
									
										42
									
								
								flake.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								flake.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| { | ||||
|   "nodes": { | ||||
|     "flake-utils": { | ||||
|       "locked": { | ||||
|         "lastModified": 1644229661, | ||||
|         "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", | ||||
|         "owner": "numtide", | ||||
|         "repo": "flake-utils", | ||||
|         "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "owner": "numtide", | ||||
|         "repo": "flake-utils", | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "nixpkgs": { | ||||
|       "locked": { | ||||
|         "lastModified": 1647536224, | ||||
|         "narHash": "sha256-SUIiz4DhMXgM7i+hvFWmLnhywr1WeRGIz+EIbwQQguM=", | ||||
|         "owner": "NixOS", | ||||
|         "repo": "nixpkgs", | ||||
|         "rev": "dd8cebebbf0f9352501f251ac37b851d947f92dc", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "id": "nixpkgs", | ||||
|         "ref": "master", | ||||
|         "type": "indirect" | ||||
|       } | ||||
|     }, | ||||
|     "root": { | ||||
|       "inputs": { | ||||
|         "flake-utils": "flake-utils", | ||||
|         "nixpkgs": "nixpkgs" | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   "root": "root", | ||||
|   "version": 7 | ||||
| } | ||||
							
								
								
									
										148
									
								
								flake.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								flake.nix
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| { | ||||
|   description = "headscale - Open Source Tailscale Control server"; | ||||
|  | ||||
|   inputs = { | ||||
|     # TODO: Use unstable when Go 1.18 has made it in | ||||
|     # https://nixpk.gs/pr-tracker.html?pr=164292 | ||||
|     # nixpkgs.url = "nixpkgs/nixpkgs-unstable"; | ||||
|     nixpkgs.url = "nixpkgs/master"; | ||||
|     flake-utils.url = "github:numtide/flake-utils"; | ||||
|   }; | ||||
|  | ||||
|   outputs = { self, nixpkgs, flake-utils, ... }: | ||||
|     let | ||||
|       headscaleVersion = if (self ? shortRev) then self.shortRev else "dev"; | ||||
|     in | ||||
|     { | ||||
|       overlay = final: prev: | ||||
|         let | ||||
|           pkgs = nixpkgs.legacyPackages.${prev.system}; | ||||
|         in | ||||
|         rec { | ||||
|           golines = | ||||
|             pkgs.buildGoModule rec { | ||||
|               pname = "golines"; | ||||
|               version = "0.9.0"; | ||||
|  | ||||
|               src = pkgs.fetchFromGitHub { | ||||
|                 owner = "segmentio"; | ||||
|                 repo = "golines"; | ||||
|                 rev = "v${version}"; | ||||
|                 sha256 = "sha256-BUXEg+4r9L/gqe4DhTlhN55P3jWt7ZyWFQycO6QePrw="; | ||||
|               }; | ||||
|  | ||||
|               vendorSha256 = "sha256-sEzWUeVk5GB0H41wrp12P8sBWRjg0FHUX6ABDEEBqK8="; | ||||
|  | ||||
|               nativeBuildInputs = [ pkgs.installShellFiles ]; | ||||
|             }; | ||||
|  | ||||
|           protoc-gen-grpc-gateway = | ||||
|             pkgs.buildGoModule rec { | ||||
|               pname = "grpc-gateway"; | ||||
|               version = "2.8.0"; | ||||
|  | ||||
|               src = pkgs.fetchFromGitHub { | ||||
|                 owner = "grpc-ecosystem"; | ||||
|                 repo = "grpc-gateway"; | ||||
|                 rev = "v${version}"; | ||||
|                 sha256 = "sha256-8eBBBYJ+tBjB2fgPMX/ZlbN3eeS75e8TAZYOKXs6hcg="; | ||||
|               }; | ||||
|  | ||||
|               vendorSha256 = "sha256-AW2Gn/mlZyLMwF+NpK59eiOmQrYWW/9HPjbunYc9Ij4="; | ||||
|  | ||||
|               nativeBuildInputs = [ pkgs.installShellFiles ]; | ||||
|  | ||||
|               subPackages = [ "protoc-gen-grpc-gateway" "protoc-gen-openapiv2" ]; | ||||
|             }; | ||||
|  | ||||
|           headscale = | ||||
|             pkgs.buildGo118Module rec { | ||||
|               pname = "headscale"; | ||||
|               version = headscaleVersion; | ||||
|               src = pkgs.lib.cleanSource self; | ||||
|  | ||||
|               # 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-bYEN0Rz7D1oJIIUjAHxdPB0CkVlb91f1lIQbucLnirg="; | ||||
|  | ||||
|               ldflags = [ "-s" "-w" "-X github.com/juanfont/headscale/cmd/headscale/cli.Version=v${version}" ]; | ||||
|             }; | ||||
|         }; | ||||
|     } // flake-utils.lib.eachDefaultSystem | ||||
|       (system: | ||||
|         let | ||||
|           pkgs = import nixpkgs { | ||||
|             overlays = [ self.overlay ]; | ||||
|             inherit system; | ||||
|           }; | ||||
|           buildDeps = with pkgs; [ git go_1_18 gnumake ]; | ||||
|           devDeps = with pkgs; | ||||
|             buildDeps ++ [ | ||||
|               golangci-lint | ||||
|               golines | ||||
|               nodePackages.prettier | ||||
|  | ||||
|               # 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; }; | ||||
|  | ||||
|           # `nix build` | ||||
|           packages = with pkgs; { | ||||
|             inherit headscale; | ||||
|             inherit headscale-docker; | ||||
|           }; | ||||
|  | ||||
|           defaultPackage = pkgs.headscale; | ||||
|  | ||||
|           # `nix run` | ||||
|           apps.headscale = flake-utils.lib.mkApp { | ||||
|             drv = packages.headscale; | ||||
|           }; | ||||
|           defaultApp = 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 ${./.} | ||||
|             ''; | ||||
|           }; | ||||
|  | ||||
|  | ||||
|         }); | ||||
| } | ||||
| @@ -36,7 +36,7 @@ var file_headscale_v1_headscale_proto_rawDesc = []byte{ | ||||
| 	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, 0xb6, 0x14, 0x0a, 0x10, 0x48, 0x65, | ||||
| 	0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xb1, 0x16, 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, | ||||
| @@ -119,91 +119,106 @@ var file_headscale_v1_headscale_proto_rawDesc = []byte{ | ||||
| 	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, 0x80, 0x01, 0x0a, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, | ||||
| 	0x65, 0x72, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, | ||||
| 	0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, | ||||
| 	0x72, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, | ||||
| 	0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, | ||||
| 	0x65, 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, 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, 0x3a, 0x01, 0x2a, 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, 0x8b, 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, | ||||
| 	0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x24, 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, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 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, 0x6f, 0x75, 0x74, 0x65, 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, 0x97, 0x01, 0x0a, 0x13, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, | ||||
| 	0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x68, 0x65, 0x61, 0x64, | ||||
| 	0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, | ||||
| 	0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, | ||||
| 	0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, | ||||
| 	0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, | ||||
| 	0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 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, | ||||
| 	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, | ||||
| 	0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x63, | ||||
| 	0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, | ||||
| 	0xe4, 0x93, 0x02, 0x1a, 0x22, 0x18, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, | ||||
| 	0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x7e, | ||||
| 	0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, | ||||
| 	0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, | ||||
| 	0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, | ||||
| 	0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, | ||||
| 	0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, | ||||
| 	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, | ||||
| 	0x2a, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, | ||||
| 	0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x85, | ||||
| 	0x01, 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, | ||||
| 	0x12, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, | ||||
| 	0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, | ||||
| 	0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, | ||||
| 	0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, | ||||
| 	0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, | ||||
| 	0x25, 0x22, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, | ||||
| 	0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, | ||||
| 	0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x12, 0x90, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x6e, 0x61, 0x6d, | ||||
| 	0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, | ||||
| 	0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4d, 0x61, | ||||
| 	0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, | ||||
| 	0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, | ||||
| 	0x6d, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, | ||||
| 	0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x22, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x2f, | ||||
| 	0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, | ||||
| 	0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2f, 0x7b, | ||||
| 	0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x6e, 0x0a, 0x0c, 0x4c, 0x69, 0x73, | ||||
| 	0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, | ||||
| 	0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, | ||||
| 	0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, | ||||
| 	0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, | ||||
| 	0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, | ||||
| 	0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, | ||||
| 	0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x0b, 0x4d, 0x6f, | ||||
| 	0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, | ||||
| 	0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x63, | ||||
| 	0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x65, | ||||
| 	0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x4d, | ||||
| 	0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, | ||||
| 	0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x22, 0x26, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, | ||||
| 	0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, | ||||
| 	0x5f, 0x69, 0x64, 0x7d, 0x2f, 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, 0x22, 0x0e, 0x2f, 0x61, 0x70, 0x69, | ||||
| 	0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x3a, 0x01, 0x2a, 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, 0x22, 0x15, 0x2f, 0x61, | ||||
| 	0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x2f, 0x65, 0x78, 0x70, | ||||
| 	0x69, 0x72, 0x65, 0x3a, 0x01, 0x2a, 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, | ||||
| 	0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x8b, | ||||
| 	0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, | ||||
| 	0x74, 0x65, 0x12, 0x24, 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, 0x6f, 0x75, 0x74, | ||||
| 	0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 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, 0x6f, 0x75, 0x74, 0x65, 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, 0x97, 0x01, 0x0a, | ||||
| 	0x13, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, | ||||
| 	0x75, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, | ||||
| 	0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, | ||||
| 	0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, | ||||
| 	0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, | ||||
| 	0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, | ||||
| 	0x73, 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, | ||||
| 	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, 0x22, 0x0e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, | ||||
| 	0x70, 0x69, 0x6b, 0x65, 0x79, 0x3a, 0x01, 0x2a, 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, 0x22, 0x15, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, | ||||
| 	0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x3a, 0x01, | ||||
| 	0x2a, 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{}{ | ||||
| @@ -217,36 +232,40 @@ var file_headscale_v1_headscale_proto_goTypes = []interface{}{ | ||||
| 	(*ListPreAuthKeysRequest)(nil),      // 7: headscale.v1.ListPreAuthKeysRequest | ||||
| 	(*DebugCreateMachineRequest)(nil),   // 8: headscale.v1.DebugCreateMachineRequest | ||||
| 	(*GetMachineRequest)(nil),           // 9: headscale.v1.GetMachineRequest | ||||
| 	(*RegisterMachineRequest)(nil),      // 10: headscale.v1.RegisterMachineRequest | ||||
| 	(*DeleteMachineRequest)(nil),        // 11: headscale.v1.DeleteMachineRequest | ||||
| 	(*ExpireMachineRequest)(nil),        // 12: headscale.v1.ExpireMachineRequest | ||||
| 	(*RenameMachineRequest)(nil),        // 13: headscale.v1.RenameMachineRequest | ||||
| 	(*ListMachinesRequest)(nil),         // 14: headscale.v1.ListMachinesRequest | ||||
| 	(*GetMachineRouteRequest)(nil),      // 15: headscale.v1.GetMachineRouteRequest | ||||
| 	(*EnableMachineRoutesRequest)(nil),  // 16: headscale.v1.EnableMachineRoutesRequest | ||||
| 	(*CreateApiKeyRequest)(nil),         // 17: headscale.v1.CreateApiKeyRequest | ||||
| 	(*ExpireApiKeyRequest)(nil),         // 18: headscale.v1.ExpireApiKeyRequest | ||||
| 	(*ListApiKeysRequest)(nil),          // 19: headscale.v1.ListApiKeysRequest | ||||
| 	(*GetNamespaceResponse)(nil),        // 20: headscale.v1.GetNamespaceResponse | ||||
| 	(*CreateNamespaceResponse)(nil),     // 21: headscale.v1.CreateNamespaceResponse | ||||
| 	(*RenameNamespaceResponse)(nil),     // 22: headscale.v1.RenameNamespaceResponse | ||||
| 	(*DeleteNamespaceResponse)(nil),     // 23: headscale.v1.DeleteNamespaceResponse | ||||
| 	(*ListNamespacesResponse)(nil),      // 24: headscale.v1.ListNamespacesResponse | ||||
| 	(*CreatePreAuthKeyResponse)(nil),    // 25: headscale.v1.CreatePreAuthKeyResponse | ||||
| 	(*ExpirePreAuthKeyResponse)(nil),    // 26: headscale.v1.ExpirePreAuthKeyResponse | ||||
| 	(*ListPreAuthKeysResponse)(nil),     // 27: headscale.v1.ListPreAuthKeysResponse | ||||
| 	(*DebugCreateMachineResponse)(nil),  // 28: headscale.v1.DebugCreateMachineResponse | ||||
| 	(*GetMachineResponse)(nil),          // 29: headscale.v1.GetMachineResponse | ||||
| 	(*RegisterMachineResponse)(nil),     // 30: headscale.v1.RegisterMachineResponse | ||||
| 	(*DeleteMachineResponse)(nil),       // 31: headscale.v1.DeleteMachineResponse | ||||
| 	(*ExpireMachineResponse)(nil),       // 32: headscale.v1.ExpireMachineResponse | ||||
| 	(*RenameMachineResponse)(nil),       // 33: headscale.v1.RenameMachineResponse | ||||
| 	(*ListMachinesResponse)(nil),        // 34: headscale.v1.ListMachinesResponse | ||||
| 	(*GetMachineRouteResponse)(nil),     // 35: headscale.v1.GetMachineRouteResponse | ||||
| 	(*EnableMachineRoutesResponse)(nil), // 36: headscale.v1.EnableMachineRoutesResponse | ||||
| 	(*CreateApiKeyResponse)(nil),        // 37: headscale.v1.CreateApiKeyResponse | ||||
| 	(*ExpireApiKeyResponse)(nil),        // 38: headscale.v1.ExpireApiKeyResponse | ||||
| 	(*ListApiKeysResponse)(nil),         // 39: headscale.v1.ListApiKeysResponse | ||||
| 	(*SetTagsRequest)(nil),              // 10: headscale.v1.SetTagsRequest | ||||
| 	(*RegisterMachineRequest)(nil),      // 11: headscale.v1.RegisterMachineRequest | ||||
| 	(*DeleteMachineRequest)(nil),        // 12: headscale.v1.DeleteMachineRequest | ||||
| 	(*ExpireMachineRequest)(nil),        // 13: headscale.v1.ExpireMachineRequest | ||||
| 	(*RenameMachineRequest)(nil),        // 14: headscale.v1.RenameMachineRequest | ||||
| 	(*ListMachinesRequest)(nil),         // 15: headscale.v1.ListMachinesRequest | ||||
| 	(*MoveMachineRequest)(nil),          // 16: headscale.v1.MoveMachineRequest | ||||
| 	(*GetMachineRouteRequest)(nil),      // 17: headscale.v1.GetMachineRouteRequest | ||||
| 	(*EnableMachineRoutesRequest)(nil),  // 18: headscale.v1.EnableMachineRoutesRequest | ||||
| 	(*CreateApiKeyRequest)(nil),         // 19: headscale.v1.CreateApiKeyRequest | ||||
| 	(*ExpireApiKeyRequest)(nil),         // 20: headscale.v1.ExpireApiKeyRequest | ||||
| 	(*ListApiKeysRequest)(nil),          // 21: headscale.v1.ListApiKeysRequest | ||||
| 	(*GetNamespaceResponse)(nil),        // 22: headscale.v1.GetNamespaceResponse | ||||
| 	(*CreateNamespaceResponse)(nil),     // 23: headscale.v1.CreateNamespaceResponse | ||||
| 	(*RenameNamespaceResponse)(nil),     // 24: headscale.v1.RenameNamespaceResponse | ||||
| 	(*DeleteNamespaceResponse)(nil),     // 25: headscale.v1.DeleteNamespaceResponse | ||||
| 	(*ListNamespacesResponse)(nil),      // 26: headscale.v1.ListNamespacesResponse | ||||
| 	(*CreatePreAuthKeyResponse)(nil),    // 27: headscale.v1.CreatePreAuthKeyResponse | ||||
| 	(*ExpirePreAuthKeyResponse)(nil),    // 28: headscale.v1.ExpirePreAuthKeyResponse | ||||
| 	(*ListPreAuthKeysResponse)(nil),     // 29: headscale.v1.ListPreAuthKeysResponse | ||||
| 	(*DebugCreateMachineResponse)(nil),  // 30: headscale.v1.DebugCreateMachineResponse | ||||
| 	(*GetMachineResponse)(nil),          // 31: headscale.v1.GetMachineResponse | ||||
| 	(*SetTagsResponse)(nil),             // 32: headscale.v1.SetTagsResponse | ||||
| 	(*RegisterMachineResponse)(nil),     // 33: headscale.v1.RegisterMachineResponse | ||||
| 	(*DeleteMachineResponse)(nil),       // 34: headscale.v1.DeleteMachineResponse | ||||
| 	(*ExpireMachineResponse)(nil),       // 35: headscale.v1.ExpireMachineResponse | ||||
| 	(*RenameMachineResponse)(nil),       // 36: headscale.v1.RenameMachineResponse | ||||
| 	(*ListMachinesResponse)(nil),        // 37: headscale.v1.ListMachinesResponse | ||||
| 	(*MoveMachineResponse)(nil),         // 38: headscale.v1.MoveMachineResponse | ||||
| 	(*GetMachineRouteResponse)(nil),     // 39: headscale.v1.GetMachineRouteResponse | ||||
| 	(*EnableMachineRoutesResponse)(nil), // 40: headscale.v1.EnableMachineRoutesResponse | ||||
| 	(*CreateApiKeyResponse)(nil),        // 41: headscale.v1.CreateApiKeyResponse | ||||
| 	(*ExpireApiKeyResponse)(nil),        // 42: headscale.v1.ExpireApiKeyResponse | ||||
| 	(*ListApiKeysResponse)(nil),         // 43: headscale.v1.ListApiKeysResponse | ||||
| } | ||||
| var file_headscale_v1_headscale_proto_depIdxs = []int32{ | ||||
| 	0,  // 0: headscale.v1.HeadscaleService.GetNamespace:input_type -> headscale.v1.GetNamespaceRequest | ||||
| @@ -259,38 +278,42 @@ var file_headscale_v1_headscale_proto_depIdxs = []int32{ | ||||
| 	7,  // 7: headscale.v1.HeadscaleService.ListPreAuthKeys:input_type -> headscale.v1.ListPreAuthKeysRequest | ||||
| 	8,  // 8: headscale.v1.HeadscaleService.DebugCreateMachine:input_type -> headscale.v1.DebugCreateMachineRequest | ||||
| 	9,  // 9: headscale.v1.HeadscaleService.GetMachine:input_type -> headscale.v1.GetMachineRequest | ||||
| 	10, // 10: headscale.v1.HeadscaleService.RegisterMachine:input_type -> headscale.v1.RegisterMachineRequest | ||||
| 	11, // 11: headscale.v1.HeadscaleService.DeleteMachine:input_type -> headscale.v1.DeleteMachineRequest | ||||
| 	12, // 12: headscale.v1.HeadscaleService.ExpireMachine:input_type -> headscale.v1.ExpireMachineRequest | ||||
| 	13, // 13: headscale.v1.HeadscaleService.RenameMachine:input_type -> headscale.v1.RenameMachineRequest | ||||
| 	14, // 14: headscale.v1.HeadscaleService.ListMachines:input_type -> headscale.v1.ListMachinesRequest | ||||
| 	15, // 15: headscale.v1.HeadscaleService.GetMachineRoute:input_type -> headscale.v1.GetMachineRouteRequest | ||||
| 	16, // 16: headscale.v1.HeadscaleService.EnableMachineRoutes:input_type -> headscale.v1.EnableMachineRoutesRequest | ||||
| 	17, // 17: headscale.v1.HeadscaleService.CreateApiKey:input_type -> headscale.v1.CreateApiKeyRequest | ||||
| 	18, // 18: headscale.v1.HeadscaleService.ExpireApiKey:input_type -> headscale.v1.ExpireApiKeyRequest | ||||
| 	19, // 19: headscale.v1.HeadscaleService.ListApiKeys:input_type -> headscale.v1.ListApiKeysRequest | ||||
| 	20, // 20: headscale.v1.HeadscaleService.GetNamespace:output_type -> headscale.v1.GetNamespaceResponse | ||||
| 	21, // 21: headscale.v1.HeadscaleService.CreateNamespace:output_type -> headscale.v1.CreateNamespaceResponse | ||||
| 	22, // 22: headscale.v1.HeadscaleService.RenameNamespace:output_type -> headscale.v1.RenameNamespaceResponse | ||||
| 	23, // 23: headscale.v1.HeadscaleService.DeleteNamespace:output_type -> headscale.v1.DeleteNamespaceResponse | ||||
| 	24, // 24: headscale.v1.HeadscaleService.ListNamespaces:output_type -> headscale.v1.ListNamespacesResponse | ||||
| 	25, // 25: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse | ||||
| 	26, // 26: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse | ||||
| 	27, // 27: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse | ||||
| 	28, // 28: headscale.v1.HeadscaleService.DebugCreateMachine:output_type -> headscale.v1.DebugCreateMachineResponse | ||||
| 	29, // 29: headscale.v1.HeadscaleService.GetMachine:output_type -> headscale.v1.GetMachineResponse | ||||
| 	30, // 30: headscale.v1.HeadscaleService.RegisterMachine:output_type -> headscale.v1.RegisterMachineResponse | ||||
| 	31, // 31: headscale.v1.HeadscaleService.DeleteMachine:output_type -> headscale.v1.DeleteMachineResponse | ||||
| 	32, // 32: headscale.v1.HeadscaleService.ExpireMachine:output_type -> headscale.v1.ExpireMachineResponse | ||||
| 	33, // 33: headscale.v1.HeadscaleService.RenameMachine:output_type -> headscale.v1.RenameMachineResponse | ||||
| 	34, // 34: headscale.v1.HeadscaleService.ListMachines:output_type -> headscale.v1.ListMachinesResponse | ||||
| 	35, // 35: headscale.v1.HeadscaleService.GetMachineRoute:output_type -> headscale.v1.GetMachineRouteResponse | ||||
| 	36, // 36: headscale.v1.HeadscaleService.EnableMachineRoutes:output_type -> headscale.v1.EnableMachineRoutesResponse | ||||
| 	37, // 37: headscale.v1.HeadscaleService.CreateApiKey:output_type -> headscale.v1.CreateApiKeyResponse | ||||
| 	38, // 38: headscale.v1.HeadscaleService.ExpireApiKey:output_type -> headscale.v1.ExpireApiKeyResponse | ||||
| 	39, // 39: headscale.v1.HeadscaleService.ListApiKeys:output_type -> headscale.v1.ListApiKeysResponse | ||||
| 	20, // [20:40] is the sub-list for method output_type | ||||
| 	0,  // [0:20] is the sub-list for method input_type | ||||
| 	10, // 10: headscale.v1.HeadscaleService.SetTags:input_type -> headscale.v1.SetTagsRequest | ||||
| 	11, // 11: headscale.v1.HeadscaleService.RegisterMachine:input_type -> headscale.v1.RegisterMachineRequest | ||||
| 	12, // 12: headscale.v1.HeadscaleService.DeleteMachine:input_type -> headscale.v1.DeleteMachineRequest | ||||
| 	13, // 13: headscale.v1.HeadscaleService.ExpireMachine:input_type -> headscale.v1.ExpireMachineRequest | ||||
| 	14, // 14: headscale.v1.HeadscaleService.RenameMachine:input_type -> headscale.v1.RenameMachineRequest | ||||
| 	15, // 15: headscale.v1.HeadscaleService.ListMachines:input_type -> headscale.v1.ListMachinesRequest | ||||
| 	16, // 16: headscale.v1.HeadscaleService.MoveMachine:input_type -> headscale.v1.MoveMachineRequest | ||||
| 	17, // 17: headscale.v1.HeadscaleService.GetMachineRoute:input_type -> headscale.v1.GetMachineRouteRequest | ||||
| 	18, // 18: headscale.v1.HeadscaleService.EnableMachineRoutes:input_type -> headscale.v1.EnableMachineRoutesRequest | ||||
| 	19, // 19: headscale.v1.HeadscaleService.CreateApiKey:input_type -> headscale.v1.CreateApiKeyRequest | ||||
| 	20, // 20: headscale.v1.HeadscaleService.ExpireApiKey:input_type -> headscale.v1.ExpireApiKeyRequest | ||||
| 	21, // 21: headscale.v1.HeadscaleService.ListApiKeys:input_type -> headscale.v1.ListApiKeysRequest | ||||
| 	22, // 22: headscale.v1.HeadscaleService.GetNamespace:output_type -> headscale.v1.GetNamespaceResponse | ||||
| 	23, // 23: headscale.v1.HeadscaleService.CreateNamespace:output_type -> headscale.v1.CreateNamespaceResponse | ||||
| 	24, // 24: headscale.v1.HeadscaleService.RenameNamespace:output_type -> headscale.v1.RenameNamespaceResponse | ||||
| 	25, // 25: headscale.v1.HeadscaleService.DeleteNamespace:output_type -> headscale.v1.DeleteNamespaceResponse | ||||
| 	26, // 26: headscale.v1.HeadscaleService.ListNamespaces:output_type -> headscale.v1.ListNamespacesResponse | ||||
| 	27, // 27: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse | ||||
| 	28, // 28: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse | ||||
| 	29, // 29: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse | ||||
| 	30, // 30: headscale.v1.HeadscaleService.DebugCreateMachine:output_type -> headscale.v1.DebugCreateMachineResponse | ||||
| 	31, // 31: headscale.v1.HeadscaleService.GetMachine:output_type -> headscale.v1.GetMachineResponse | ||||
| 	32, // 32: headscale.v1.HeadscaleService.SetTags:output_type -> headscale.v1.SetTagsResponse | ||||
| 	33, // 33: headscale.v1.HeadscaleService.RegisterMachine:output_type -> headscale.v1.RegisterMachineResponse | ||||
| 	34, // 34: headscale.v1.HeadscaleService.DeleteMachine:output_type -> headscale.v1.DeleteMachineResponse | ||||
| 	35, // 35: headscale.v1.HeadscaleService.ExpireMachine:output_type -> headscale.v1.ExpireMachineResponse | ||||
| 	36, // 36: headscale.v1.HeadscaleService.RenameMachine:output_type -> headscale.v1.RenameMachineResponse | ||||
| 	37, // 37: headscale.v1.HeadscaleService.ListMachines:output_type -> headscale.v1.ListMachinesResponse | ||||
| 	38, // 38: headscale.v1.HeadscaleService.MoveMachine:output_type -> headscale.v1.MoveMachineResponse | ||||
| 	39, // 39: headscale.v1.HeadscaleService.GetMachineRoute:output_type -> headscale.v1.GetMachineRouteResponse | ||||
| 	40, // 40: headscale.v1.HeadscaleService.EnableMachineRoutes:output_type -> headscale.v1.EnableMachineRoutesResponse | ||||
| 	41, // 41: headscale.v1.HeadscaleService.CreateApiKey:output_type -> headscale.v1.CreateApiKeyResponse | ||||
| 	42, // 42: headscale.v1.HeadscaleService.ExpireApiKey:output_type -> headscale.v1.ExpireApiKeyResponse | ||||
| 	43, // 43: headscale.v1.HeadscaleService.ListApiKeys:output_type -> headscale.v1.ListApiKeysResponse | ||||
| 	22, // [22:44] is the sub-list for method output_type | ||||
| 	0,  // [0:22] 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 | ||||
|   | ||||
| @@ -449,6 +449,74 @@ func local_request_HeadscaleService_GetMachine_0(ctx context.Context, marshaler | ||||
|  | ||||
| } | ||||
|  | ||||
| func request_HeadscaleService_SetTags_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { | ||||
| 	var protoReq SetTagsRequest | ||||
| 	var metadata runtime.ServerMetadata | ||||
|  | ||||
| 	newReader, berr := utilities.IOReaderFactory(req.Body) | ||||
| 	if berr != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) | ||||
| 	} | ||||
| 	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		val string | ||||
| 		ok  bool | ||||
| 		err error | ||||
| 		_   = err | ||||
| 	) | ||||
|  | ||||
| 	val, ok = pathParams["machine_id"] | ||||
| 	if !ok { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "machine_id") | ||||
| 	} | ||||
|  | ||||
| 	protoReq.MachineId, err = runtime.Uint64(val) | ||||
| 	if err != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "machine_id", err) | ||||
| 	} | ||||
|  | ||||
| 	msg, err := client.SetTags(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) | ||||
| 	return msg, metadata, err | ||||
|  | ||||
| } | ||||
|  | ||||
| func local_request_HeadscaleService_SetTags_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { | ||||
| 	var protoReq SetTagsRequest | ||||
| 	var metadata runtime.ServerMetadata | ||||
|  | ||||
| 	newReader, berr := utilities.IOReaderFactory(req.Body) | ||||
| 	if berr != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) | ||||
| 	} | ||||
| 	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		val string | ||||
| 		ok  bool | ||||
| 		err error | ||||
| 		_   = err | ||||
| 	) | ||||
|  | ||||
| 	val, ok = pathParams["machine_id"] | ||||
| 	if !ok { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "machine_id") | ||||
| 	} | ||||
|  | ||||
| 	protoReq.MachineId, err = runtime.Uint64(val) | ||||
| 	if err != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "machine_id", err) | ||||
| 	} | ||||
|  | ||||
| 	msg, err := server.SetTags(ctx, &protoReq) | ||||
| 	return msg, metadata, err | ||||
|  | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	filter_HeadscaleService_RegisterMachine_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} | ||||
| ) | ||||
| @@ -697,6 +765,76 @@ func local_request_HeadscaleService_ListMachines_0(ctx context.Context, marshale | ||||
|  | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	filter_HeadscaleService_MoveMachine_0 = &utilities.DoubleArray{Encoding: map[string]int{"machine_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} | ||||
| ) | ||||
|  | ||||
| func request_HeadscaleService_MoveMachine_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { | ||||
| 	var protoReq MoveMachineRequest | ||||
| 	var metadata runtime.ServerMetadata | ||||
|  | ||||
| 	var ( | ||||
| 		val string | ||||
| 		ok  bool | ||||
| 		err error | ||||
| 		_   = err | ||||
| 	) | ||||
|  | ||||
| 	val, ok = pathParams["machine_id"] | ||||
| 	if !ok { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "machine_id") | ||||
| 	} | ||||
|  | ||||
| 	protoReq.MachineId, err = runtime.Uint64(val) | ||||
| 	if err != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "machine_id", err) | ||||
| 	} | ||||
|  | ||||
| 	if err := req.ParseForm(); err != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) | ||||
| 	} | ||||
| 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HeadscaleService_MoveMachine_0); err != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) | ||||
| 	} | ||||
|  | ||||
| 	msg, err := client.MoveMachine(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) | ||||
| 	return msg, metadata, err | ||||
|  | ||||
| } | ||||
|  | ||||
| func local_request_HeadscaleService_MoveMachine_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { | ||||
| 	var protoReq MoveMachineRequest | ||||
| 	var metadata runtime.ServerMetadata | ||||
|  | ||||
| 	var ( | ||||
| 		val string | ||||
| 		ok  bool | ||||
| 		err error | ||||
| 		_   = err | ||||
| 	) | ||||
|  | ||||
| 	val, ok = pathParams["machine_id"] | ||||
| 	if !ok { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "machine_id") | ||||
| 	} | ||||
|  | ||||
| 	protoReq.MachineId, err = runtime.Uint64(val) | ||||
| 	if err != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "machine_id", err) | ||||
| 	} | ||||
|  | ||||
| 	if err := req.ParseForm(); err != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) | ||||
| 	} | ||||
| 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_HeadscaleService_MoveMachine_0); err != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) | ||||
| 	} | ||||
|  | ||||
| 	msg, err := server.MoveMachine(ctx, &protoReq) | ||||
| 	return msg, metadata, err | ||||
|  | ||||
| } | ||||
|  | ||||
| func request_HeadscaleService_GetMachineRoute_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { | ||||
| 	var protoReq GetMachineRouteRequest | ||||
| 	var metadata runtime.ServerMetadata | ||||
| @@ -1141,6 +1279,29 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	mux.Handle("POST", pattern_HeadscaleService_SetTags_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) | ||||
| 		rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/SetTags", runtime.WithHTTPPathPattern("/api/v1/machine/{machine_id}/tags")) | ||||
| 		if err != nil { | ||||
| 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) | ||||
| 			return | ||||
| 		} | ||||
| 		resp, md, err := local_request_HeadscaleService_SetTags_0(rctx, inboundMarshaler, server, req, pathParams) | ||||
| 		md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) | ||||
| 		ctx = runtime.NewServerMetadataContext(ctx, md) | ||||
| 		if err != nil { | ||||
| 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		forward_HeadscaleService_SetTags_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	mux.Handle("POST", pattern_HeadscaleService_RegisterMachine_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { | ||||
| 		ctx, cancel := context.WithCancel(req.Context()) | ||||
| 		defer cancel() | ||||
| @@ -1256,6 +1417,29 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	mux.Handle("POST", pattern_HeadscaleService_MoveMachine_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) | ||||
| 		rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/MoveMachine", runtime.WithHTTPPathPattern("/api/v1/machine/{machine_id}/namespace")) | ||||
| 		if err != nil { | ||||
| 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) | ||||
| 			return | ||||
| 		} | ||||
| 		resp, md, err := local_request_HeadscaleService_MoveMachine_0(rctx, inboundMarshaler, server, req, pathParams) | ||||
| 		md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) | ||||
| 		ctx = runtime.NewServerMetadataContext(ctx, md) | ||||
| 		if err != nil { | ||||
| 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		forward_HeadscaleService_MoveMachine_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	mux.Handle("GET", pattern_HeadscaleService_GetMachineRoute_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { | ||||
| 		ctx, cancel := context.WithCancel(req.Context()) | ||||
| 		defer cancel() | ||||
| @@ -1612,6 +1796,26 @@ func RegisterHeadscaleServiceHandlerClient(ctx context.Context, mux *runtime.Ser | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	mux.Handle("POST", pattern_HeadscaleService_SetTags_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) | ||||
| 		rctx, err := runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/SetTags", runtime.WithHTTPPathPattern("/api/v1/machine/{machine_id}/tags")) | ||||
| 		if err != nil { | ||||
| 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) | ||||
| 			return | ||||
| 		} | ||||
| 		resp, md, err := request_HeadscaleService_SetTags_0(rctx, inboundMarshaler, client, req, pathParams) | ||||
| 		ctx = runtime.NewServerMetadataContext(ctx, md) | ||||
| 		if err != nil { | ||||
| 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		forward_HeadscaleService_SetTags_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	mux.Handle("POST", pattern_HeadscaleService_RegisterMachine_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { | ||||
| 		ctx, cancel := context.WithCancel(req.Context()) | ||||
| 		defer cancel() | ||||
| @@ -1712,6 +1916,26 @@ func RegisterHeadscaleServiceHandlerClient(ctx context.Context, mux *runtime.Ser | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	mux.Handle("POST", pattern_HeadscaleService_MoveMachine_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) | ||||
| 		rctx, err := runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/MoveMachine", runtime.WithHTTPPathPattern("/api/v1/machine/{machine_id}/namespace")) | ||||
| 		if err != nil { | ||||
| 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) | ||||
| 			return | ||||
| 		} | ||||
| 		resp, md, err := request_HeadscaleService_MoveMachine_0(rctx, inboundMarshaler, client, req, pathParams) | ||||
| 		ctx = runtime.NewServerMetadataContext(ctx, md) | ||||
| 		if err != nil { | ||||
| 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		forward_HeadscaleService_MoveMachine_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	mux.Handle("GET", pattern_HeadscaleService_GetMachineRoute_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { | ||||
| 		ctx, cancel := context.WithCancel(req.Context()) | ||||
| 		defer cancel() | ||||
| @@ -1836,6 +2060,8 @@ var ( | ||||
|  | ||||
| 	pattern_HeadscaleService_GetMachine_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "machine", "machine_id"}, "")) | ||||
|  | ||||
| 	pattern_HeadscaleService_SetTags_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", "tags"}, "")) | ||||
|  | ||||
| 	pattern_HeadscaleService_RegisterMachine_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "machine", "register"}, "")) | ||||
|  | ||||
| 	pattern_HeadscaleService_DeleteMachine_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "machine", "machine_id"}, "")) | ||||
| @@ -1846,6 +2072,8 @@ 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_GetMachineRoute_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_EnableMachineRoutes_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"}, "")) | ||||
| @@ -1878,6 +2106,8 @@ var ( | ||||
|  | ||||
| 	forward_HeadscaleService_GetMachine_0 = runtime.ForwardResponseMessage | ||||
|  | ||||
| 	forward_HeadscaleService_SetTags_0 = runtime.ForwardResponseMessage | ||||
|  | ||||
| 	forward_HeadscaleService_RegisterMachine_0 = runtime.ForwardResponseMessage | ||||
|  | ||||
| 	forward_HeadscaleService_DeleteMachine_0 = runtime.ForwardResponseMessage | ||||
| @@ -1888,6 +2118,8 @@ var ( | ||||
|  | ||||
| 	forward_HeadscaleService_ListMachines_0 = runtime.ForwardResponseMessage | ||||
|  | ||||
| 	forward_HeadscaleService_MoveMachine_0 = runtime.ForwardResponseMessage | ||||
|  | ||||
| 	forward_HeadscaleService_GetMachineRoute_0 = runtime.ForwardResponseMessage | ||||
|  | ||||
| 	forward_HeadscaleService_EnableMachineRoutes_0 = runtime.ForwardResponseMessage | ||||
|   | ||||
| @@ -1,8 +1,4 @@ | ||||
| // Code generated by protoc-gen-go-grpc. DO NOT EDIT. | ||||
| // versions: | ||||
| // - protoc-gen-go-grpc v1.2.0 | ||||
| // - protoc             (unknown) | ||||
| // source: headscale/v1/headscale.proto | ||||
|  | ||||
| package v1 | ||||
|  | ||||
| @@ -35,11 +31,13 @@ type HeadscaleServiceClient interface { | ||||
| 	// --- Machine start --- | ||||
| 	DebugCreateMachine(ctx context.Context, in *DebugCreateMachineRequest, opts ...grpc.CallOption) (*DebugCreateMachineResponse, error) | ||||
| 	GetMachine(ctx context.Context, in *GetMachineRequest, opts ...grpc.CallOption) (*GetMachineResponse, error) | ||||
| 	SetTags(ctx context.Context, in *SetTagsRequest, opts ...grpc.CallOption) (*SetTagsResponse, error) | ||||
| 	RegisterMachine(ctx context.Context, in *RegisterMachineRequest, opts ...grpc.CallOption) (*RegisterMachineResponse, error) | ||||
| 	DeleteMachine(ctx context.Context, in *DeleteMachineRequest, opts ...grpc.CallOption) (*DeleteMachineResponse, error) | ||||
| 	ExpireMachine(ctx context.Context, in *ExpireMachineRequest, opts ...grpc.CallOption) (*ExpireMachineResponse, error) | ||||
| 	RenameMachine(ctx context.Context, in *RenameMachineRequest, opts ...grpc.CallOption) (*RenameMachineResponse, error) | ||||
| 	ListMachines(ctx context.Context, in *ListMachinesRequest, opts ...grpc.CallOption) (*ListMachinesResponse, error) | ||||
| 	MoveMachine(ctx context.Context, in *MoveMachineRequest, opts ...grpc.CallOption) (*MoveMachineResponse, error) | ||||
| 	// --- Route start --- | ||||
| 	GetMachineRoute(ctx context.Context, in *GetMachineRouteRequest, opts ...grpc.CallOption) (*GetMachineRouteResponse, error) | ||||
| 	EnableMachineRoutes(ctx context.Context, in *EnableMachineRoutesRequest, opts ...grpc.CallOption) (*EnableMachineRoutesResponse, error) | ||||
| @@ -147,6 +145,15 @@ func (c *headscaleServiceClient) GetMachine(ctx context.Context, in *GetMachineR | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| func (c *headscaleServiceClient) SetTags(ctx context.Context, in *SetTagsRequest, opts ...grpc.CallOption) (*SetTagsResponse, error) { | ||||
| 	out := new(SetTagsResponse) | ||||
| 	err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/SetTags", in, out, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| func (c *headscaleServiceClient) RegisterMachine(ctx context.Context, in *RegisterMachineRequest, opts ...grpc.CallOption) (*RegisterMachineResponse, error) { | ||||
| 	out := new(RegisterMachineResponse) | ||||
| 	err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/RegisterMachine", in, out, opts...) | ||||
| @@ -192,6 +199,15 @@ func (c *headscaleServiceClient) ListMachines(ctx context.Context, in *ListMachi | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| func (c *headscaleServiceClient) MoveMachine(ctx context.Context, in *MoveMachineRequest, opts ...grpc.CallOption) (*MoveMachineResponse, error) { | ||||
| 	out := new(MoveMachineResponse) | ||||
| 	err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/MoveMachine", in, out, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| func (c *headscaleServiceClient) GetMachineRoute(ctx context.Context, in *GetMachineRouteRequest, opts ...grpc.CallOption) (*GetMachineRouteResponse, error) { | ||||
| 	out := new(GetMachineRouteResponse) | ||||
| 	err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/GetMachineRoute", in, out, opts...) | ||||
| @@ -254,11 +270,13 @@ type HeadscaleServiceServer interface { | ||||
| 	// --- Machine start --- | ||||
| 	DebugCreateMachine(context.Context, *DebugCreateMachineRequest) (*DebugCreateMachineResponse, error) | ||||
| 	GetMachine(context.Context, *GetMachineRequest) (*GetMachineResponse, error) | ||||
| 	SetTags(context.Context, *SetTagsRequest) (*SetTagsResponse, error) | ||||
| 	RegisterMachine(context.Context, *RegisterMachineRequest) (*RegisterMachineResponse, error) | ||||
| 	DeleteMachine(context.Context, *DeleteMachineRequest) (*DeleteMachineResponse, error) | ||||
| 	ExpireMachine(context.Context, *ExpireMachineRequest) (*ExpireMachineResponse, error) | ||||
| 	RenameMachine(context.Context, *RenameMachineRequest) (*RenameMachineResponse, error) | ||||
| 	ListMachines(context.Context, *ListMachinesRequest) (*ListMachinesResponse, error) | ||||
| 	MoveMachine(context.Context, *MoveMachineRequest) (*MoveMachineResponse, error) | ||||
| 	// --- Route start --- | ||||
| 	GetMachineRoute(context.Context, *GetMachineRouteRequest) (*GetMachineRouteResponse, error) | ||||
| 	EnableMachineRoutes(context.Context, *EnableMachineRoutesRequest) (*EnableMachineRoutesResponse, error) | ||||
| @@ -303,6 +321,9 @@ func (UnimplementedHeadscaleServiceServer) DebugCreateMachine(context.Context, * | ||||
| func (UnimplementedHeadscaleServiceServer) GetMachine(context.Context, *GetMachineRequest) (*GetMachineResponse, error) { | ||||
| 	return nil, status.Errorf(codes.Unimplemented, "method GetMachine not implemented") | ||||
| } | ||||
| func (UnimplementedHeadscaleServiceServer) SetTags(context.Context, *SetTagsRequest) (*SetTagsResponse, error) { | ||||
| 	return nil, status.Errorf(codes.Unimplemented, "method SetTags not implemented") | ||||
| } | ||||
| func (UnimplementedHeadscaleServiceServer) RegisterMachine(context.Context, *RegisterMachineRequest) (*RegisterMachineResponse, error) { | ||||
| 	return nil, status.Errorf(codes.Unimplemented, "method RegisterMachine not implemented") | ||||
| } | ||||
| @@ -318,6 +339,9 @@ func (UnimplementedHeadscaleServiceServer) RenameMachine(context.Context, *Renam | ||||
| func (UnimplementedHeadscaleServiceServer) ListMachines(context.Context, *ListMachinesRequest) (*ListMachinesResponse, error) { | ||||
| 	return nil, status.Errorf(codes.Unimplemented, "method ListMachines not implemented") | ||||
| } | ||||
| func (UnimplementedHeadscaleServiceServer) MoveMachine(context.Context, *MoveMachineRequest) (*MoveMachineResponse, error) { | ||||
| 	return nil, status.Errorf(codes.Unimplemented, "method MoveMachine not implemented") | ||||
| } | ||||
| func (UnimplementedHeadscaleServiceServer) GetMachineRoute(context.Context, *GetMachineRouteRequest) (*GetMachineRouteResponse, error) { | ||||
| 	return nil, status.Errorf(codes.Unimplemented, "method GetMachineRoute not implemented") | ||||
| } | ||||
| @@ -526,6 +550,24 @@ func _HeadscaleService_GetMachine_Handler(srv interface{}, ctx context.Context, | ||||
| 	return interceptor(ctx, in, info, handler) | ||||
| } | ||||
|  | ||||
| func _HeadscaleService_SetTags_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { | ||||
| 	in := new(SetTagsRequest) | ||||
| 	if err := dec(in); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if interceptor == nil { | ||||
| 		return srv.(HeadscaleServiceServer).SetTags(ctx, in) | ||||
| 	} | ||||
| 	info := &grpc.UnaryServerInfo{ | ||||
| 		Server:     srv, | ||||
| 		FullMethod: "/headscale.v1.HeadscaleService/SetTags", | ||||
| 	} | ||||
| 	handler := func(ctx context.Context, req interface{}) (interface{}, error) { | ||||
| 		return srv.(HeadscaleServiceServer).SetTags(ctx, req.(*SetTagsRequest)) | ||||
| 	} | ||||
| 	return interceptor(ctx, in, info, handler) | ||||
| } | ||||
|  | ||||
| func _HeadscaleService_RegisterMachine_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { | ||||
| 	in := new(RegisterMachineRequest) | ||||
| 	if err := dec(in); err != nil { | ||||
| @@ -616,6 +658,24 @@ func _HeadscaleService_ListMachines_Handler(srv interface{}, ctx context.Context | ||||
| 	return interceptor(ctx, in, info, handler) | ||||
| } | ||||
|  | ||||
| func _HeadscaleService_MoveMachine_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { | ||||
| 	in := new(MoveMachineRequest) | ||||
| 	if err := dec(in); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if interceptor == nil { | ||||
| 		return srv.(HeadscaleServiceServer).MoveMachine(ctx, in) | ||||
| 	} | ||||
| 	info := &grpc.UnaryServerInfo{ | ||||
| 		Server:     srv, | ||||
| 		FullMethod: "/headscale.v1.HeadscaleService/MoveMachine", | ||||
| 	} | ||||
| 	handler := func(ctx context.Context, req interface{}) (interface{}, error) { | ||||
| 		return srv.(HeadscaleServiceServer).MoveMachine(ctx, req.(*MoveMachineRequest)) | ||||
| 	} | ||||
| 	return interceptor(ctx, in, info, handler) | ||||
| } | ||||
|  | ||||
| func _HeadscaleService_GetMachineRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { | ||||
| 	in := new(GetMachineRouteRequest) | ||||
| 	if err := dec(in); err != nil { | ||||
| @@ -753,6 +813,10 @@ var HeadscaleService_ServiceDesc = grpc.ServiceDesc{ | ||||
| 			MethodName: "GetMachine", | ||||
| 			Handler:    _HeadscaleService_GetMachine_Handler, | ||||
| 		}, | ||||
| 		{ | ||||
| 			MethodName: "SetTags", | ||||
| 			Handler:    _HeadscaleService_SetTags_Handler, | ||||
| 		}, | ||||
| 		{ | ||||
| 			MethodName: "RegisterMachine", | ||||
| 			Handler:    _HeadscaleService_RegisterMachine_Handler, | ||||
| @@ -773,6 +837,10 @@ var HeadscaleService_ServiceDesc = grpc.ServiceDesc{ | ||||
| 			MethodName: "ListMachines", | ||||
| 			Handler:    _HeadscaleService_ListMachines_Handler, | ||||
| 		}, | ||||
| 		{ | ||||
| 			MethodName: "MoveMachine", | ||||
| 			Handler:    _HeadscaleService_MoveMachine_Handler, | ||||
| 		}, | ||||
| 		{ | ||||
| 			MethodName: "GetMachineRoute", | ||||
| 			Handler:    _HeadscaleService_GetMachineRoute_Handler, | ||||
|   | ||||
| @@ -91,7 +91,10 @@ type Machine struct { | ||||
| 	PreAuthKey           *PreAuthKey            `protobuf:"bytes,11,opt,name=pre_auth_key,json=preAuthKey,proto3" json:"pre_auth_key,omitempty"` | ||||
| 	CreatedAt            *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` | ||||
| 	RegisterMethod       RegisterMethod         `protobuf:"varint,13,opt,name=register_method,json=registerMethod,proto3,enum=headscale.v1.RegisterMethod" json:"register_method,omitempty"` | ||||
| 	GivenName            string                 `protobuf:"bytes,18,opt,name=given_name,json=givenName,proto3" json:"given_name,omitempty"` | ||||
| 	ForcedTags           []string               `protobuf:"bytes,18,rep,name=forced_tags,json=forcedTags,proto3" json:"forced_tags,omitempty"` | ||||
| 	InvalidTags          []string               `protobuf:"bytes,19,rep,name=invalid_tags,json=invalidTags,proto3" json:"invalid_tags,omitempty"` | ||||
| 	ValidTags            []string               `protobuf:"bytes,20,rep,name=valid_tags,json=validTags,proto3" json:"valid_tags,omitempty"` | ||||
| 	GivenName            string                 `protobuf:"bytes,21,opt,name=given_name,json=givenName,proto3" json:"given_name,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *Machine) Reset() { | ||||
| @@ -217,6 +220,27 @@ func (x *Machine) GetRegisterMethod() RegisterMethod { | ||||
| 	return RegisterMethod_REGISTER_METHOD_UNSPECIFIED | ||||
| } | ||||
|  | ||||
| func (x *Machine) GetForcedTags() []string { | ||||
| 	if x != nil { | ||||
| 		return x.ForcedTags | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (x *Machine) GetInvalidTags() []string { | ||||
| 	if x != nil { | ||||
| 		return x.InvalidTags | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (x *Machine) GetValidTags() []string { | ||||
| 	if x != nil { | ||||
| 		return x.ValidTags | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (x *Machine) GetGivenName() string { | ||||
| 	if x != nil { | ||||
| 		return x.GivenName | ||||
| @@ -420,6 +444,108 @@ func (x *GetMachineResponse) GetMachine() *Machine { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type SetTagsRequest struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	unknownFields protoimpl.UnknownFields | ||||
|  | ||||
| 	MachineId uint64   `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"` | ||||
| 	Tags      []string `protobuf:"bytes,2,rep,name=tags,proto3" json:"tags,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *SetTagsRequest) Reset() { | ||||
| 	*x = SetTagsRequest{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[5] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *SetTagsRequest) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*SetTagsRequest) ProtoMessage() {} | ||||
|  | ||||
| func (x *SetTagsRequest) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_headscale_v1_machine_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 SetTagsRequest.ProtoReflect.Descriptor instead. | ||||
| func (*SetTagsRequest) Descriptor() ([]byte, []int) { | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{5} | ||||
| } | ||||
|  | ||||
| func (x *SetTagsRequest) GetMachineId() uint64 { | ||||
| 	if x != nil { | ||||
| 		return x.MachineId | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (x *SetTagsRequest) GetTags() []string { | ||||
| 	if x != nil { | ||||
| 		return x.Tags | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type SetTagsResponse struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	unknownFields protoimpl.UnknownFields | ||||
|  | ||||
| 	Machine *Machine `protobuf:"bytes,1,opt,name=machine,proto3" json:"machine,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *SetTagsResponse) Reset() { | ||||
| 	*x = SetTagsResponse{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[6] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *SetTagsResponse) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*SetTagsResponse) ProtoMessage() {} | ||||
|  | ||||
| func (x *SetTagsResponse) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_headscale_v1_machine_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 SetTagsResponse.ProtoReflect.Descriptor instead. | ||||
| func (*SetTagsResponse) Descriptor() ([]byte, []int) { | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{6} | ||||
| } | ||||
|  | ||||
| func (x *SetTagsResponse) GetMachine() *Machine { | ||||
| 	if x != nil { | ||||
| 		return x.Machine | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type DeleteMachineRequest struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| @@ -431,7 +557,7 @@ type DeleteMachineRequest struct { | ||||
| func (x *DeleteMachineRequest) Reset() { | ||||
| 	*x = DeleteMachineRequest{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[5] | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[7] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| @@ -444,7 +570,7 @@ func (x *DeleteMachineRequest) String() string { | ||||
| func (*DeleteMachineRequest) ProtoMessage() {} | ||||
|  | ||||
| func (x *DeleteMachineRequest) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[5] | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[7] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| @@ -457,7 +583,7 @@ func (x *DeleteMachineRequest) ProtoReflect() protoreflect.Message { | ||||
|  | ||||
| // Deprecated: Use DeleteMachineRequest.ProtoReflect.Descriptor instead. | ||||
| func (*DeleteMachineRequest) Descriptor() ([]byte, []int) { | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{5} | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{7} | ||||
| } | ||||
|  | ||||
| func (x *DeleteMachineRequest) GetMachineId() uint64 { | ||||
| @@ -476,7 +602,7 @@ type DeleteMachineResponse struct { | ||||
| func (x *DeleteMachineResponse) Reset() { | ||||
| 	*x = DeleteMachineResponse{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[6] | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[8] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| @@ -489,7 +615,7 @@ func (x *DeleteMachineResponse) String() string { | ||||
| func (*DeleteMachineResponse) ProtoMessage() {} | ||||
|  | ||||
| func (x *DeleteMachineResponse) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[6] | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[8] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| @@ -502,7 +628,7 @@ func (x *DeleteMachineResponse) ProtoReflect() protoreflect.Message { | ||||
|  | ||||
| // Deprecated: Use DeleteMachineResponse.ProtoReflect.Descriptor instead. | ||||
| func (*DeleteMachineResponse) Descriptor() ([]byte, []int) { | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{6} | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{8} | ||||
| } | ||||
|  | ||||
| type ExpireMachineRequest struct { | ||||
| @@ -516,7 +642,7 @@ type ExpireMachineRequest struct { | ||||
| func (x *ExpireMachineRequest) Reset() { | ||||
| 	*x = ExpireMachineRequest{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[7] | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[9] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| @@ -529,7 +655,7 @@ func (x *ExpireMachineRequest) String() string { | ||||
| func (*ExpireMachineRequest) ProtoMessage() {} | ||||
|  | ||||
| func (x *ExpireMachineRequest) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[7] | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[9] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| @@ -542,7 +668,7 @@ func (x *ExpireMachineRequest) ProtoReflect() protoreflect.Message { | ||||
|  | ||||
| // Deprecated: Use ExpireMachineRequest.ProtoReflect.Descriptor instead. | ||||
| func (*ExpireMachineRequest) Descriptor() ([]byte, []int) { | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{7} | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{9} | ||||
| } | ||||
|  | ||||
| func (x *ExpireMachineRequest) GetMachineId() uint64 { | ||||
| @@ -563,7 +689,7 @@ type ExpireMachineResponse struct { | ||||
| func (x *ExpireMachineResponse) Reset() { | ||||
| 	*x = ExpireMachineResponse{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[8] | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[10] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| @@ -576,7 +702,7 @@ func (x *ExpireMachineResponse) String() string { | ||||
| func (*ExpireMachineResponse) ProtoMessage() {} | ||||
|  | ||||
| func (x *ExpireMachineResponse) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[8] | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[10] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| @@ -589,7 +715,7 @@ func (x *ExpireMachineResponse) ProtoReflect() protoreflect.Message { | ||||
|  | ||||
| // Deprecated: Use ExpireMachineResponse.ProtoReflect.Descriptor instead. | ||||
| func (*ExpireMachineResponse) Descriptor() ([]byte, []int) { | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{8} | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{10} | ||||
| } | ||||
|  | ||||
| func (x *ExpireMachineResponse) GetMachine() *Machine { | ||||
| @@ -611,7 +737,7 @@ type RenameMachineRequest struct { | ||||
| func (x *RenameMachineRequest) Reset() { | ||||
| 	*x = RenameMachineRequest{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[9] | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[11] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| @@ -624,7 +750,7 @@ func (x *RenameMachineRequest) String() string { | ||||
| func (*RenameMachineRequest) ProtoMessage() {} | ||||
|  | ||||
| func (x *RenameMachineRequest) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[9] | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[11] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| @@ -637,7 +763,7 @@ func (x *RenameMachineRequest) ProtoReflect() protoreflect.Message { | ||||
|  | ||||
| // Deprecated: Use RenameMachineRequest.ProtoReflect.Descriptor instead. | ||||
| func (*RenameMachineRequest) Descriptor() ([]byte, []int) { | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{9} | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{11} | ||||
| } | ||||
|  | ||||
| func (x *RenameMachineRequest) GetMachineId() uint64 { | ||||
| @@ -665,7 +791,7 @@ type RenameMachineResponse struct { | ||||
| func (x *RenameMachineResponse) Reset() { | ||||
| 	*x = RenameMachineResponse{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[10] | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[12] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| @@ -678,7 +804,7 @@ func (x *RenameMachineResponse) String() string { | ||||
| func (*RenameMachineResponse) ProtoMessage() {} | ||||
|  | ||||
| func (x *RenameMachineResponse) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[10] | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[12] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| @@ -691,7 +817,7 @@ func (x *RenameMachineResponse) ProtoReflect() protoreflect.Message { | ||||
|  | ||||
| // Deprecated: Use RenameMachineResponse.ProtoReflect.Descriptor instead. | ||||
| func (*RenameMachineResponse) Descriptor() ([]byte, []int) { | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{10} | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{12} | ||||
| } | ||||
|  | ||||
| func (x *RenameMachineResponse) GetMachine() *Machine { | ||||
| @@ -712,7 +838,7 @@ type ListMachinesRequest struct { | ||||
| func (x *ListMachinesRequest) Reset() { | ||||
| 	*x = ListMachinesRequest{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[11] | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[13] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| @@ -725,7 +851,7 @@ func (x *ListMachinesRequest) String() string { | ||||
| func (*ListMachinesRequest) ProtoMessage() {} | ||||
|  | ||||
| func (x *ListMachinesRequest) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[11] | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[13] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| @@ -738,7 +864,7 @@ func (x *ListMachinesRequest) ProtoReflect() protoreflect.Message { | ||||
|  | ||||
| // Deprecated: Use ListMachinesRequest.ProtoReflect.Descriptor instead. | ||||
| func (*ListMachinesRequest) Descriptor() ([]byte, []int) { | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{11} | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{13} | ||||
| } | ||||
|  | ||||
| func (x *ListMachinesRequest) GetNamespace() string { | ||||
| @@ -759,7 +885,7 @@ type ListMachinesResponse struct { | ||||
| func (x *ListMachinesResponse) Reset() { | ||||
| 	*x = ListMachinesResponse{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[12] | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[14] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| @@ -772,7 +898,7 @@ func (x *ListMachinesResponse) String() string { | ||||
| func (*ListMachinesResponse) ProtoMessage() {} | ||||
|  | ||||
| func (x *ListMachinesResponse) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[12] | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[14] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| @@ -785,7 +911,7 @@ func (x *ListMachinesResponse) ProtoReflect() protoreflect.Message { | ||||
|  | ||||
| // Deprecated: Use ListMachinesResponse.ProtoReflect.Descriptor instead. | ||||
| func (*ListMachinesResponse) Descriptor() ([]byte, []int) { | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{12} | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{14} | ||||
| } | ||||
|  | ||||
| func (x *ListMachinesResponse) GetMachines() []*Machine { | ||||
| @@ -795,6 +921,108 @@ func (x *ListMachinesResponse) GetMachines() []*Machine { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type MoveMachineRequest struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	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"` | ||||
| } | ||||
|  | ||||
| func (x *MoveMachineRequest) Reset() { | ||||
| 	*x = MoveMachineRequest{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[15] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *MoveMachineRequest) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*MoveMachineRequest) ProtoMessage() {} | ||||
|  | ||||
| func (x *MoveMachineRequest) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[15] | ||||
| 	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 MoveMachineRequest.ProtoReflect.Descriptor instead. | ||||
| func (*MoveMachineRequest) Descriptor() ([]byte, []int) { | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{15} | ||||
| } | ||||
|  | ||||
| func (x *MoveMachineRequest) GetMachineId() uint64 { | ||||
| 	if x != nil { | ||||
| 		return x.MachineId | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (x *MoveMachineRequest) GetNamespace() string { | ||||
| 	if x != nil { | ||||
| 		return x.Namespace | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| type MoveMachineResponse struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	unknownFields protoimpl.UnknownFields | ||||
|  | ||||
| 	Machine *Machine `protobuf:"bytes,1,opt,name=machine,proto3" json:"machine,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *MoveMachineResponse) Reset() { | ||||
| 	*x = MoveMachineResponse{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[16] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *MoveMachineResponse) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*MoveMachineResponse) ProtoMessage() {} | ||||
|  | ||||
| func (x *MoveMachineResponse) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[16] | ||||
| 	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 MoveMachineResponse.ProtoReflect.Descriptor instead. | ||||
| func (*MoveMachineResponse) Descriptor() ([]byte, []int) { | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{16} | ||||
| } | ||||
|  | ||||
| func (x *MoveMachineResponse) GetMachine() *Machine { | ||||
| 	if x != nil { | ||||
| 		return x.Machine | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type DebugCreateMachineRequest struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| @@ -809,7 +1037,7 @@ type DebugCreateMachineRequest struct { | ||||
| func (x *DebugCreateMachineRequest) Reset() { | ||||
| 	*x = DebugCreateMachineRequest{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[13] | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[17] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| @@ -822,7 +1050,7 @@ func (x *DebugCreateMachineRequest) String() string { | ||||
| func (*DebugCreateMachineRequest) ProtoMessage() {} | ||||
|  | ||||
| func (x *DebugCreateMachineRequest) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[13] | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[17] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| @@ -835,7 +1063,7 @@ func (x *DebugCreateMachineRequest) ProtoReflect() protoreflect.Message { | ||||
|  | ||||
| // Deprecated: Use DebugCreateMachineRequest.ProtoReflect.Descriptor instead. | ||||
| func (*DebugCreateMachineRequest) Descriptor() ([]byte, []int) { | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{13} | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{17} | ||||
| } | ||||
|  | ||||
| func (x *DebugCreateMachineRequest) GetNamespace() string { | ||||
| @@ -877,7 +1105,7 @@ type DebugCreateMachineResponse struct { | ||||
| func (x *DebugCreateMachineResponse) Reset() { | ||||
| 	*x = DebugCreateMachineResponse{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[14] | ||||
| 		mi := &file_headscale_v1_machine_proto_msgTypes[18] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| @@ -890,7 +1118,7 @@ func (x *DebugCreateMachineResponse) String() string { | ||||
| func (*DebugCreateMachineResponse) ProtoMessage() {} | ||||
|  | ||||
| func (x *DebugCreateMachineResponse) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[14] | ||||
| 	mi := &file_headscale_v1_machine_proto_msgTypes[18] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| @@ -903,7 +1131,7 @@ func (x *DebugCreateMachineResponse) ProtoReflect() protoreflect.Message { | ||||
|  | ||||
| // Deprecated: Use DebugCreateMachineResponse.ProtoReflect.Descriptor instead. | ||||
| func (*DebugCreateMachineResponse) Descriptor() ([]byte, []int) { | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{14} | ||||
| 	return file_headscale_v1_machine_proto_rawDescGZIP(), []int{18} | ||||
| } | ||||
|  | ||||
| func (x *DebugCreateMachineResponse) GetMachine() *Machine { | ||||
| @@ -924,7 +1152,7 @@ var file_headscale_v1_machine_proto_rawDesc = []byte{ | ||||
| 	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, 0xfc, 0x04, 0x0a, 0x07, 0x4d, 0x61, 0x63, | ||||
| 	0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe5, 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, | ||||
| @@ -962,81 +1190,106 @@ var file_headscale_v1_machine_proto_rawDesc = []byte{ | ||||
| 	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, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x76, 0x65, | ||||
| 	0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x69, | ||||
| 	0x76, 0x65, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 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, | ||||
| 	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, 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, 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, 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, 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, | ||||
| 	0x64, 0x22, 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, | ||||
| 	0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x0a, 0x14, 0x45, 0x78, | ||||
| 	0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, | ||||
| 	0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, | ||||
| 	0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, | ||||
| 	0x64, 0x22, 0x48, 0x0a, 0x15, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, | ||||
| 	0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, | ||||
| 	0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, | ||||
| 	0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, | ||||
| 	0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x50, 0x0a, 0x14, 0x52, | ||||
| 	0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, | ||||
| 	0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, | ||||
| 	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, | ||||
| 	0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, | ||||
| 	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x48, 0x0a, | ||||
| 	0x15, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, | ||||
| 	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, | ||||
| 	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, | ||||
| 	0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, | ||||
| 	0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x33, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x4d, | ||||
| 	0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, | ||||
| 	0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, | ||||
| 	0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x49, 0x0a, 0x14, | ||||
| 	0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, | ||||
| 	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, | ||||
| 	0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, | ||||
| 	0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x08, 0x6d, | ||||
| 	0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x51, 0x0a, 0x12, 0x4d, 0x6f, 0x76, 0x65, 0x4d, | ||||
| 	0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, | ||||
| 	0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, | ||||
| 	0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, | ||||
| 	0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, | ||||
| 	0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x46, 0x0a, 0x13, 0x4d, 0x6f, | ||||
| 	0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, | ||||
| 	0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, | ||||
| 	0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, | ||||
| 	0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, | ||||
| 	0x6e, 0x65, 0x22, 0x77, 0x0a, 0x19, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, | ||||
| 	0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, | ||||
| 	0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, | ||||
| 	0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, | ||||
| 	0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, | ||||
| 	0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, | ||||
| 	0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, | ||||
| 	0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0x4d, 0x0a, 0x1a, 0x44, | ||||
| 	0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, | ||||
| 	0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, | ||||
| 	0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, | ||||
| 	0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, | ||||
| 	0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2a, 0x82, 0x01, 0x0a, 0x0e, 0x52, | ||||
| 	0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1f, 0x0a, | ||||
| 	0x1b, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, | ||||
| 	0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, | ||||
| 	0x0a, 0x18, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, | ||||
| 	0x44, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, | ||||
| 	0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, | ||||
| 	0x43, 0x4c, 0x49, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, | ||||
| 	0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x4f, 0x49, 0x44, 0x43, 0x10, 0x03, 0x42, | ||||
| 	0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x75, | ||||
| 	0x61, 0x6e, 0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, | ||||
| 	0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, | ||||
| 	0x6f, 0x33, | ||||
| } | ||||
|  | ||||
| var ( | ||||
| @@ -1052,7 +1305,7 @@ func file_headscale_v1_machine_proto_rawDescGZIP() []byte { | ||||
| } | ||||
|  | ||||
| var file_headscale_v1_machine_proto_enumTypes = make([]protoimpl.EnumInfo, 1) | ||||
| var file_headscale_v1_machine_proto_msgTypes = make([]protoimpl.MessageInfo, 15) | ||||
| var file_headscale_v1_machine_proto_msgTypes = make([]protoimpl.MessageInfo, 19) | ||||
| var file_headscale_v1_machine_proto_goTypes = []interface{}{ | ||||
| 	(RegisterMethod)(0),                // 0: headscale.v1.RegisterMethod | ||||
| 	(*Machine)(nil),                    // 1: headscale.v1.Machine | ||||
| @@ -1060,39 +1313,45 @@ var file_headscale_v1_machine_proto_goTypes = []interface{}{ | ||||
| 	(*RegisterMachineResponse)(nil),    // 3: headscale.v1.RegisterMachineResponse | ||||
| 	(*GetMachineRequest)(nil),          // 4: headscale.v1.GetMachineRequest | ||||
| 	(*GetMachineResponse)(nil),         // 5: headscale.v1.GetMachineResponse | ||||
| 	(*DeleteMachineRequest)(nil),       // 6: headscale.v1.DeleteMachineRequest | ||||
| 	(*DeleteMachineResponse)(nil),      // 7: headscale.v1.DeleteMachineResponse | ||||
| 	(*ExpireMachineRequest)(nil),       // 8: headscale.v1.ExpireMachineRequest | ||||
| 	(*ExpireMachineResponse)(nil),      // 9: headscale.v1.ExpireMachineResponse | ||||
| 	(*RenameMachineRequest)(nil),       // 10: headscale.v1.RenameMachineRequest | ||||
| 	(*RenameMachineResponse)(nil),      // 11: headscale.v1.RenameMachineResponse | ||||
| 	(*ListMachinesRequest)(nil),        // 12: headscale.v1.ListMachinesRequest | ||||
| 	(*ListMachinesResponse)(nil),       // 13: headscale.v1.ListMachinesResponse | ||||
| 	(*DebugCreateMachineRequest)(nil),  // 14: headscale.v1.DebugCreateMachineRequest | ||||
| 	(*DebugCreateMachineResponse)(nil), // 15: headscale.v1.DebugCreateMachineResponse | ||||
| 	(*Namespace)(nil),                  // 16: headscale.v1.Namespace | ||||
| 	(*timestamppb.Timestamp)(nil),      // 17: google.protobuf.Timestamp | ||||
| 	(*PreAuthKey)(nil),                 // 18: headscale.v1.PreAuthKey | ||||
| 	(*SetTagsRequest)(nil),             // 6: headscale.v1.SetTagsRequest | ||||
| 	(*SetTagsResponse)(nil),            // 7: headscale.v1.SetTagsResponse | ||||
| 	(*DeleteMachineRequest)(nil),       // 8: headscale.v1.DeleteMachineRequest | ||||
| 	(*DeleteMachineResponse)(nil),      // 9: headscale.v1.DeleteMachineResponse | ||||
| 	(*ExpireMachineRequest)(nil),       // 10: headscale.v1.ExpireMachineRequest | ||||
| 	(*ExpireMachineResponse)(nil),      // 11: headscale.v1.ExpireMachineResponse | ||||
| 	(*RenameMachineRequest)(nil),       // 12: headscale.v1.RenameMachineRequest | ||||
| 	(*RenameMachineResponse)(nil),      // 13: headscale.v1.RenameMachineResponse | ||||
| 	(*ListMachinesRequest)(nil),        // 14: headscale.v1.ListMachinesRequest | ||||
| 	(*ListMachinesResponse)(nil),       // 15: headscale.v1.ListMachinesResponse | ||||
| 	(*MoveMachineRequest)(nil),         // 16: headscale.v1.MoveMachineRequest | ||||
| 	(*MoveMachineResponse)(nil),        // 17: headscale.v1.MoveMachineResponse | ||||
| 	(*DebugCreateMachineRequest)(nil),  // 18: headscale.v1.DebugCreateMachineRequest | ||||
| 	(*DebugCreateMachineResponse)(nil), // 19: headscale.v1.DebugCreateMachineResponse | ||||
| 	(*Namespace)(nil),                  // 20: headscale.v1.Namespace | ||||
| 	(*timestamppb.Timestamp)(nil),      // 21: google.protobuf.Timestamp | ||||
| 	(*PreAuthKey)(nil),                 // 22: headscale.v1.PreAuthKey | ||||
| } | ||||
| var file_headscale_v1_machine_proto_depIdxs = []int32{ | ||||
| 	16, // 0: headscale.v1.Machine.namespace:type_name -> headscale.v1.Namespace | ||||
| 	17, // 1: headscale.v1.Machine.last_seen:type_name -> google.protobuf.Timestamp | ||||
| 	17, // 2: headscale.v1.Machine.last_successful_update:type_name -> google.protobuf.Timestamp | ||||
| 	17, // 3: headscale.v1.Machine.expiry:type_name -> google.protobuf.Timestamp | ||||
| 	18, // 4: headscale.v1.Machine.pre_auth_key:type_name -> headscale.v1.PreAuthKey | ||||
| 	17, // 5: headscale.v1.Machine.created_at:type_name -> google.protobuf.Timestamp | ||||
| 	20, // 0: headscale.v1.Machine.namespace:type_name -> headscale.v1.Namespace | ||||
| 	21, // 1: headscale.v1.Machine.last_seen:type_name -> google.protobuf.Timestamp | ||||
| 	21, // 2: headscale.v1.Machine.last_successful_update:type_name -> google.protobuf.Timestamp | ||||
| 	21, // 3: headscale.v1.Machine.expiry:type_name -> google.protobuf.Timestamp | ||||
| 	22, // 4: headscale.v1.Machine.pre_auth_key:type_name -> headscale.v1.PreAuthKey | ||||
| 	21, // 5: headscale.v1.Machine.created_at:type_name -> google.protobuf.Timestamp | ||||
| 	0,  // 6: headscale.v1.Machine.register_method:type_name -> headscale.v1.RegisterMethod | ||||
| 	1,  // 7: headscale.v1.RegisterMachineResponse.machine:type_name -> headscale.v1.Machine | ||||
| 	1,  // 8: headscale.v1.GetMachineResponse.machine:type_name -> headscale.v1.Machine | ||||
| 	1,  // 9: headscale.v1.ExpireMachineResponse.machine:type_name -> headscale.v1.Machine | ||||
| 	1,  // 10: headscale.v1.RenameMachineResponse.machine:type_name -> headscale.v1.Machine | ||||
| 	1,  // 11: headscale.v1.ListMachinesResponse.machines:type_name -> headscale.v1.Machine | ||||
| 	1,  // 12: headscale.v1.DebugCreateMachineResponse.machine:type_name -> headscale.v1.Machine | ||||
| 	13, // [13:13] is the sub-list for method output_type | ||||
| 	13, // [13:13] is the sub-list for method input_type | ||||
| 	13, // [13:13] is the sub-list for extension type_name | ||||
| 	13, // [13:13] is the sub-list for extension extendee | ||||
| 	0,  // [0:13] is the sub-list for field type_name | ||||
| 	1,  // 9: headscale.v1.SetTagsResponse.machine:type_name -> headscale.v1.Machine | ||||
| 	1,  // 10: headscale.v1.ExpireMachineResponse.machine:type_name -> headscale.v1.Machine | ||||
| 	1,  // 11: headscale.v1.RenameMachineResponse.machine:type_name -> headscale.v1.Machine | ||||
| 	1,  // 12: headscale.v1.ListMachinesResponse.machines:type_name -> headscale.v1.Machine | ||||
| 	1,  // 13: headscale.v1.MoveMachineResponse.machine:type_name -> headscale.v1.Machine | ||||
| 	1,  // 14: headscale.v1.DebugCreateMachineResponse.machine:type_name -> headscale.v1.Machine | ||||
| 	15, // [15:15] is the sub-list for method output_type | ||||
| 	15, // [15:15] is the sub-list for method input_type | ||||
| 	15, // [15:15] is the sub-list for extension type_name | ||||
| 	15, // [15:15] is the sub-list for extension extendee | ||||
| 	0,  // [0:15] is the sub-list for field type_name | ||||
| } | ||||
|  | ||||
| func init() { file_headscale_v1_machine_proto_init() } | ||||
| @@ -1164,7 +1423,7 @@ func file_headscale_v1_machine_proto_init() { | ||||
| 			} | ||||
| 		} | ||||
| 		file_headscale_v1_machine_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*DeleteMachineRequest); i { | ||||
| 			switch v := v.(*SetTagsRequest); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| @@ -1176,7 +1435,7 @@ func file_headscale_v1_machine_proto_init() { | ||||
| 			} | ||||
| 		} | ||||
| 		file_headscale_v1_machine_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*DeleteMachineResponse); i { | ||||
| 			switch v := v.(*SetTagsResponse); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| @@ -1188,7 +1447,7 @@ func file_headscale_v1_machine_proto_init() { | ||||
| 			} | ||||
| 		} | ||||
| 		file_headscale_v1_machine_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*ExpireMachineRequest); i { | ||||
| 			switch v := v.(*DeleteMachineRequest); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| @@ -1200,7 +1459,7 @@ func file_headscale_v1_machine_proto_init() { | ||||
| 			} | ||||
| 		} | ||||
| 		file_headscale_v1_machine_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*ExpireMachineResponse); i { | ||||
| 			switch v := v.(*DeleteMachineResponse); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| @@ -1212,7 +1471,7 @@ func file_headscale_v1_machine_proto_init() { | ||||
| 			} | ||||
| 		} | ||||
| 		file_headscale_v1_machine_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*RenameMachineRequest); i { | ||||
| 			switch v := v.(*ExpireMachineRequest); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| @@ -1224,7 +1483,7 @@ func file_headscale_v1_machine_proto_init() { | ||||
| 			} | ||||
| 		} | ||||
| 		file_headscale_v1_machine_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*RenameMachineResponse); i { | ||||
| 			switch v := v.(*ExpireMachineResponse); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| @@ -1236,7 +1495,7 @@ func file_headscale_v1_machine_proto_init() { | ||||
| 			} | ||||
| 		} | ||||
| 		file_headscale_v1_machine_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*ListMachinesRequest); i { | ||||
| 			switch v := v.(*RenameMachineRequest); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| @@ -1248,7 +1507,7 @@ func file_headscale_v1_machine_proto_init() { | ||||
| 			} | ||||
| 		} | ||||
| 		file_headscale_v1_machine_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*ListMachinesResponse); i { | ||||
| 			switch v := v.(*RenameMachineResponse); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| @@ -1260,7 +1519,7 @@ func file_headscale_v1_machine_proto_init() { | ||||
| 			} | ||||
| 		} | ||||
| 		file_headscale_v1_machine_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*DebugCreateMachineRequest); i { | ||||
| 			switch v := v.(*ListMachinesRequest); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| @@ -1272,6 +1531,54 @@ func file_headscale_v1_machine_proto_init() { | ||||
| 			} | ||||
| 		} | ||||
| 		file_headscale_v1_machine_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*ListMachinesResponse); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 		file_headscale_v1_machine_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*MoveMachineRequest); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 		file_headscale_v1_machine_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*MoveMachineResponse); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 		file_headscale_v1_machine_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*DebugCreateMachineRequest); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 		file_headscale_v1_machine_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*DebugCreateMachineResponse); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| @@ -1290,7 +1597,7 @@ func file_headscale_v1_machine_proto_init() { | ||||
| 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | ||||
| 			RawDescriptor: file_headscale_v1_machine_proto_rawDesc, | ||||
| 			NumEnums:      1, | ||||
| 			NumMessages:   15, | ||||
| 			NumMessages:   19, | ||||
| 			NumExtensions: 0, | ||||
| 			NumServices:   0, | ||||
| 		}, | ||||
|   | ||||
| @@ -291,6 +291,43 @@ | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     "/api/v1/machine/{machineId}/namespace": { | ||||
|       "post": { | ||||
|         "operationId": "HeadscaleService_MoveMachine", | ||||
|         "responses": { | ||||
|           "200": { | ||||
|             "description": "A successful response.", | ||||
|             "schema": { | ||||
|               "$ref": "#/definitions/v1MoveMachineResponse" | ||||
|             } | ||||
|           }, | ||||
|           "default": { | ||||
|             "description": "An unexpected error response.", | ||||
|             "schema": { | ||||
|               "$ref": "#/definitions/rpcStatus" | ||||
|             } | ||||
|           } | ||||
|         }, | ||||
|         "parameters": [ | ||||
|           { | ||||
|             "name": "machineId", | ||||
|             "in": "path", | ||||
|             "required": true, | ||||
|             "type": "string", | ||||
|             "format": "uint64" | ||||
|           }, | ||||
|           { | ||||
|             "name": "namespace", | ||||
|             "in": "query", | ||||
|             "required": false, | ||||
|             "type": "string" | ||||
|           } | ||||
|         ], | ||||
|         "tags": [ | ||||
|           "HeadscaleService" | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     "/api/v1/machine/{machineId}/rename/{newName}": { | ||||
|       "post": { | ||||
|         "operationId": "HeadscaleService_RenameMachine", | ||||
| @@ -399,6 +436,53 @@ | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     "/api/v1/machine/{machineId}/tags": { | ||||
|       "post": { | ||||
|         "operationId": "HeadscaleService_SetTags", | ||||
|         "responses": { | ||||
|           "200": { | ||||
|             "description": "A successful response.", | ||||
|             "schema": { | ||||
|               "$ref": "#/definitions/v1SetTagsResponse" | ||||
|             } | ||||
|           }, | ||||
|           "default": { | ||||
|             "description": "An unexpected error response.", | ||||
|             "schema": { | ||||
|               "$ref": "#/definitions/rpcStatus" | ||||
|             } | ||||
|           } | ||||
|         }, | ||||
|         "parameters": [ | ||||
|           { | ||||
|             "name": "machineId", | ||||
|             "in": "path", | ||||
|             "required": true, | ||||
|             "type": "string", | ||||
|             "format": "uint64" | ||||
|           }, | ||||
|           { | ||||
|             "name": "body", | ||||
|             "in": "body", | ||||
|             "required": true, | ||||
|             "schema": { | ||||
|               "type": "object", | ||||
|               "properties": { | ||||
|                 "tags": { | ||||
|                   "type": "array", | ||||
|                   "items": { | ||||
|                     "type": "string" | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         ], | ||||
|         "tags": [ | ||||
|           "HeadscaleService" | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     "/api/v1/namespace": { | ||||
|       "get": { | ||||
|         "operationId": "HeadscaleService_ListNamespaces", | ||||
| @@ -944,11 +1028,37 @@ | ||||
|         "registerMethod": { | ||||
|           "$ref": "#/definitions/v1RegisterMethod" | ||||
|         }, | ||||
|         "forcedTags": { | ||||
|           "type": "array", | ||||
|           "items": { | ||||
|             "type": "string" | ||||
|           } | ||||
|         }, | ||||
|         "invalidTags": { | ||||
|           "type": "array", | ||||
|           "items": { | ||||
|             "type": "string" | ||||
|           } | ||||
|         }, | ||||
|         "validTags": { | ||||
|           "type": "array", | ||||
|           "items": { | ||||
|             "type": "string" | ||||
|           } | ||||
|         }, | ||||
|         "givenName": { | ||||
|           "type": "string" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "v1MoveMachineResponse": { | ||||
|       "type": "object", | ||||
|       "properties": { | ||||
|         "machine": { | ||||
|           "$ref": "#/definitions/v1Machine" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "v1Namespace": { | ||||
|       "type": "object", | ||||
|       "properties": { | ||||
| @@ -1045,6 +1155,14 @@ | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "v1SetTagsResponse": { | ||||
|       "type": "object", | ||||
|       "properties": { | ||||
|         "machine": { | ||||
|           "$ref": "#/definitions/v1Machine" | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										97
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										97
									
								
								go.mod
									
									
									
									
									
								
							| @@ -3,76 +3,73 @@ module github.com/juanfont/headscale | ||||
| go 1.18 | ||||
|  | ||||
| require ( | ||||
| 	github.com/AlecAivazis/survey/v2 v2.3.2 | ||||
| 	github.com/bufbuild/buf v1.4.0 | ||||
| 	github.com/AlecAivazis/survey/v2 v2.3.4 | ||||
| 	github.com/ccding/go-stun/stun v0.0.0-20200514191101-4dc67bcdb029 | ||||
| 	github.com/coreos/go-oidc/v3 v3.1.0 | ||||
| 	github.com/efekarakus/termcolor v1.0.1 | ||||
| 	github.com/fatih/set v0.2.1 | ||||
| 	github.com/gin-gonic/gin v1.7.7 | ||||
| 	github.com/glebarez/sqlite v1.3.5 | ||||
| 	github.com/glebarez/sqlite v1.4.3 | ||||
| 	github.com/gofrs/uuid v4.2.0+incompatible | ||||
| 	github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 | ||||
| 	github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3 | ||||
| 	github.com/infobloxopen/protoc-gen-gorm v1.1.0 | ||||
| 	github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.0 | ||||
| 	github.com/klauspost/compress v1.15.1 | ||||
| 	github.com/ory/dockertest/v3 v3.8.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.12.1 | ||||
| 	github.com/pterm/pterm v0.12.37 | ||||
| 	github.com/pterm/pterm v0.12.41 | ||||
| 	github.com/rs/zerolog v1.26.1 | ||||
| 	github.com/spf13/cobra v1.4.0 | ||||
| 	github.com/spf13/viper v1.10.1 | ||||
| 	github.com/spf13/viper v1.11.0 | ||||
| 	github.com/stretchr/testify v1.7.1 | ||||
| 	github.com/tailscale/hujson v0.0.0-20211215203138-ffd971c5f362 | ||||
| 	github.com/tailscale/hujson v0.0.0-20220421170326-6583d0610064 | ||||
| 	github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e | ||||
| 	github.com/zsais/go-gin-prometheus v0.1.0 | ||||
| 	golang.org/x/crypto v0.0.0-20220214200702-86341886e292 | ||||
| 	golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b | ||||
| 	golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 | ||||
| 	golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 | ||||
| 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c | ||||
| 	google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4 | ||||
| 	google.golang.org/grpc v1.45.0 | ||||
| 	google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0 | ||||
| 	google.golang.org/genproto v0.0.0-20220422154200-b37d22cd5731 | ||||
| 	google.golang.org/grpc v1.46.0 | ||||
| 	google.golang.org/protobuf v1.28.0 | ||||
| 	gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c | ||||
| 	gopkg.in/yaml.v2 v2.4.0 | ||||
| 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b | ||||
| 	gorm.io/driver/postgres v1.3.1 | ||||
| 	gorm.io/gorm v1.23.1 | ||||
| 	gorm.io/driver/postgres v1.3.5 | ||||
| 	gorm.io/gorm v1.23.4 | ||||
| 	inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6 | ||||
| 	tailscale.com v1.22.0 | ||||
| 	tailscale.com v1.24.0 | ||||
| ) | ||||
|  | ||||
| require ( | ||||
| 	github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect | ||||
| 	github.com/Microsoft/go-winio v0.5.2 // indirect | ||||
| 	github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect | ||||
| 	github.com/Microsoft/go-winio v0.5.1 // indirect | ||||
| 	github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect | ||||
| 	github.com/akutz/memconn v0.1.0 // indirect | ||||
| 	github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 // indirect | ||||
| 	github.com/atomicgo/cursor v0.0.1 // indirect | ||||
| 	github.com/beorn7/perks v1.0.1 // indirect | ||||
| 	github.com/bufbuild/buf v1.4.0 // indirect | ||||
| 	github.com/cenkalti/backoff/v4 v4.1.2 // indirect | ||||
| 	github.com/cespare/xxhash/v2 v2.1.2 // indirect | ||||
| 	github.com/containerd/continuity v0.2.2 // indirect | ||||
| 	github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6 // indirect | ||||
| 	github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect | ||||
| 	github.com/davecgh/go-spew v1.1.1 // indirect | ||||
| 	github.com/denisenkom/go-mssqldb v0.12.0 // indirect | ||||
| 	github.com/docker/cli v20.10.12+incompatible // indirect | ||||
| 	github.com/docker/docker v20.10.12+incompatible // indirect | ||||
| 	github.com/docker/cli v20.10.11+incompatible // indirect | ||||
| 	github.com/docker/docker v20.10.7+incompatible // indirect | ||||
| 	github.com/docker/go-connections v0.4.0 // indirect | ||||
| 	github.com/docker/go-units v0.4.0 // indirect | ||||
| 	github.com/fsnotify/fsnotify v1.5.1 // indirect | ||||
| 	github.com/gin-contrib/sse v0.1.0 // indirect | ||||
| 	github.com/glebarez/go-sqlite v1.14.8 // indirect | ||||
| 	github.com/go-playground/locales v0.14.0 // indirect | ||||
| 	github.com/go-playground/universal-translator v0.18.0 // indirect | ||||
| 	github.com/go-playground/validator/v10 v10.10.0 // indirect | ||||
| 	github.com/go-sql-driver/mysql v1.6.0 // indirect | ||||
| 	github.com/glebarez/go-sqlite v1.16.0 // indirect | ||||
| 	github.com/go-playground/locales v0.13.0 // indirect | ||||
| 	github.com/go-playground/universal-translator v0.17.0 // indirect | ||||
| 	github.com/go-playground/validator/v10 v10.4.1 // indirect | ||||
| 	github.com/gofrs/flock v0.8.1 // indirect | ||||
| 	github.com/gogo/protobuf v1.3.2 // 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.7 // indirect | ||||
| 	github.com/google/go-github v17.0.0+incompatible // indirect | ||||
| 	github.com/google/go-querystring v1.1.0 // indirect | ||||
| 	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect | ||||
| @@ -83,42 +80,44 @@ require ( | ||||
| 	github.com/imdario/mergo v0.3.12 // indirect | ||||
| 	github.com/inconshreveable/mousetrap v1.0.0 // indirect | ||||
| 	github.com/jackc/chunkreader/v2 v2.0.1 // indirect | ||||
| 	github.com/jackc/pgconn v1.11.0 // indirect | ||||
| 	github.com/jackc/pgconn v1.12.0 // indirect | ||||
| 	github.com/jackc/pgio v1.0.0 // indirect | ||||
| 	github.com/jackc/pgpassfile v1.0.0 // indirect | ||||
| 	github.com/jackc/pgproto3/v2 v2.2.0 // indirect | ||||
| 	github.com/jackc/pgproto3/v2 v2.3.0 // indirect | ||||
| 	github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect | ||||
| 	github.com/jackc/pgtype v1.10.0 // indirect | ||||
| 	github.com/jackc/pgx/v4 v4.15.0 // indirect | ||||
| 	github.com/jackc/pgtype v1.11.0 // indirect | ||||
| 	github.com/jackc/pgx/v4 v4.16.0 // indirect | ||||
| 	github.com/jdxcode/netrc v0.0.0-20210204082910-926c7f70242a // indirect | ||||
| 	github.com/jhump/protocompile v0.0.0-20220216033700-d705409f108f // indirect | ||||
| 	github.com/jhump/protoreflect v1.12.1-0.20220417024638-438db461d753 // indirect | ||||
| 	github.com/jinzhu/gorm v1.9.16 // indirect | ||||
| 	github.com/jinzhu/inflection v1.0.0 // indirect | ||||
| 	github.com/jinzhu/now v1.1.4 // indirect | ||||
| 	github.com/josharian/native v1.0.0 // indirect | ||||
| 	github.com/jsimonetti/rtnetlink v1.1.2-0.20220408201609-d380b505068b // indirect | ||||
| 	github.com/json-iterator/go v1.1.12 // indirect | ||||
| 	github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect | ||||
| 	github.com/klauspost/pgzip v1.2.5 // indirect | ||||
| 	github.com/kr/pretty v0.3.0 // indirect | ||||
| 	github.com/kr/text v0.2.0 // indirect | ||||
| 	github.com/leodido/go-urn v1.2.1 // indirect | ||||
| 	github.com/lib/pq v1.10.3 // indirect | ||||
| 	github.com/leodido/go-urn v1.2.0 // indirect | ||||
| 	github.com/magiconair/properties v1.8.6 // indirect | ||||
| 	github.com/mattn/go-colorable v0.1.12 // indirect | ||||
| 	github.com/mattn/go-isatty v0.0.14 // indirect | ||||
| 	github.com/mattn/go-runewidth v0.0.13 // indirect | ||||
| 	github.com/mattn/go-sqlite3 v1.14.11 // indirect | ||||
| 	github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect | ||||
| 	github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect | ||||
| 	github.com/mdlayher/netlink v1.6.0 // indirect | ||||
| 	github.com/mdlayher/socket v0.2.3 // indirect | ||||
| 	github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect | ||||
| 	github.com/mitchellh/go-ps v1.0.0 // indirect | ||||
| 	github.com/mitchellh/mapstructure v1.4.3 // indirect | ||||
| 	github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect | ||||
| 	github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // 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/go-digest v1.0.0-rc1 // indirect | ||||
| 	github.com/opencontainers/image-spec v1.0.2 // indirect | ||||
| 	github.com/opencontainers/runc v1.1.0 // indirect | ||||
| 	github.com/opencontainers/runc v1.0.2 // indirect | ||||
| 	github.com/pelletier/go-toml v1.9.4 // indirect | ||||
| 	github.com/pelletier/go-toml/v2 v2.0.0-beta.8 // indirect | ||||
| 	github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect | ||||
| 	github.com/pkg/errors v0.9.1 // indirect | ||||
| 	github.com/pkg/profile v1.6.0 // indirect | ||||
| @@ -128,16 +127,16 @@ require ( | ||||
| 	github.com/prometheus/procfs v0.7.3 // indirect | ||||
| 	github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect | ||||
| 	github.com/rivo/uniseg v0.2.0 // indirect | ||||
| 	github.com/rogpeppe/go-internal v1.8.1 // indirect | ||||
| 	github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4 // indirect | ||||
| 	github.com/russross/blackfriday/v2 v2.1.0 // indirect | ||||
| 	github.com/sirupsen/logrus v1.8.1 // indirect | ||||
| 	github.com/spf13/afero v1.8.1 // indirect | ||||
| 	github.com/spf13/afero v1.8.2 // indirect | ||||
| 	github.com/spf13/cast v1.4.1 // indirect | ||||
| 	github.com/spf13/jwalterweatherman v1.1.0 // indirect | ||||
| 	github.com/spf13/pflag v1.0.5 // indirect | ||||
| 	github.com/subosito/gotenv v1.2.0 // indirect | ||||
| 	github.com/ugorji/go/codec v1.2.7 // indirect | ||||
| 	github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect | ||||
| 	github.com/ugorji/go/codec v1.1.7 // indirect | ||||
| 	github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // 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-20210125001918-ca9a967f8778 // indirect | ||||
| @@ -153,12 +152,12 @@ require ( | ||||
| 	golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 // indirect | ||||
| 	golang.org/x/text v0.3.7 // indirect | ||||
| 	golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect | ||||
| 	golang.zx2c4.com/wireguard/windows v0.4.10 // indirect | ||||
| 	google.golang.org/appengine v1.6.7 // indirect | ||||
| 	gopkg.in/ini.v1 v1.66.4 // indirect | ||||
| 	gopkg.in/square/go-jose.v2 v2.6.0 // indirect | ||||
| 	modernc.org/libc v1.14.5 // indirect | ||||
| 	gopkg.in/square/go-jose.v2 v2.5.1 // indirect | ||||
| 	modernc.org/libc v1.14.12 // indirect | ||||
| 	modernc.org/mathutil v1.4.1 // indirect | ||||
| 	modernc.org/memory v1.0.5 // indirect | ||||
| 	modernc.org/sqlite v1.14.7 // indirect | ||||
| 	sigs.k8s.io/yaml v1.3.0 // indirect | ||||
| 	modernc.org/memory v1.0.7 // indirect | ||||
| 	modernc.org/sqlite v1.16.0 // indirect | ||||
| ) | ||||
|   | ||||
							
								
								
									
										67
									
								
								grpcv1.go
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								grpcv1.go
									
									
									
									
									
								
							| @@ -3,10 +3,13 @@ package headscale | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/juanfont/headscale/gen/go/headscale/v1" | ||||
| 	v1 "github.com/juanfont/headscale/gen/go/headscale/v1" | ||||
| 	"github.com/rs/zerolog/log" | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/grpc/status" | ||||
| 	"tailscale.com/tailcfg" | ||||
| ) | ||||
|  | ||||
| @@ -182,6 +185,41 @@ func (api headscaleV1APIServer) GetMachine( | ||||
| 	return &v1.GetMachineResponse{Machine: machine.toProto()}, nil | ||||
| } | ||||
|  | ||||
| func (api headscaleV1APIServer) SetTags( | ||||
| 	ctx context.Context, | ||||
| 	request *v1.SetTagsRequest, | ||||
| ) (*v1.SetTagsResponse, error) { | ||||
| 	machine, err := api.h.GetMachineByID(request.GetMachineId()) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	for _, tag := range request.GetTags() { | ||||
| 		if strings.Index(tag, "tag:") != 0 { | ||||
| 			return &v1.SetTagsResponse{ | ||||
| 					Machine: nil, | ||||
| 				}, status.Error( | ||||
| 					codes.InvalidArgument, | ||||
| 					"Invalid tag detected. Each tag must start with the string 'tag:'", | ||||
| 				) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	err = api.h.SetTags(machine, request.GetTags()) | ||||
| 	if err != nil { | ||||
| 		return &v1.SetTagsResponse{ | ||||
| 			Machine: nil, | ||||
| 		}, status.Error(codes.Internal, err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	log.Trace(). | ||||
| 		Str("machine", machine.Hostname). | ||||
| 		Strs("tags", request.GetTags()). | ||||
| 		Msg("Changing tags of machine") | ||||
|  | ||||
| 	return &v1.SetTagsResponse{Machine: machine.toProto()}, nil | ||||
| } | ||||
|  | ||||
| func (api headscaleV1APIServer) DeleteMachine( | ||||
| 	ctx context.Context, | ||||
| 	request *v1.DeleteMachineRequest, | ||||
| @@ -272,12 +310,37 @@ func (api headscaleV1APIServer) ListMachines( | ||||
|  | ||||
| 	response := make([]*v1.Machine, len(machines)) | ||||
| 	for index, machine := range machines { | ||||
| 		response[index] = machine.toProto() | ||||
| 		m := machine.toProto() | ||||
| 		validTags, invalidTags := getTags( | ||||
| 			api.h.aclPolicy, | ||||
| 			machine, | ||||
| 			api.h.cfg.OIDC.StripEmaildomain, | ||||
| 		) | ||||
| 		m.InvalidTags = invalidTags | ||||
| 		m.ValidTags = validTags | ||||
| 		response[index] = m | ||||
| 	} | ||||
|  | ||||
| 	return &v1.ListMachinesResponse{Machines: response}, nil | ||||
| } | ||||
|  | ||||
| func (api headscaleV1APIServer) MoveMachine( | ||||
| 	ctx context.Context, | ||||
| 	request *v1.MoveMachineRequest, | ||||
| ) (*v1.MoveMachineResponse, error) { | ||||
| 	machine, err := api.h.GetMachineByID(request.GetMachineId()) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	err = api.h.SetMachineNamespace(machine, request.GetNamespace()) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return &v1.MoveMachineResponse{Machine: machine.toProto()}, nil | ||||
| } | ||||
|  | ||||
| func (api headscaleV1APIServer) GetMachineRoute( | ||||
| 	ctx context.Context, | ||||
| 	request *v1.GetMachineRouteRequest, | ||||
|   | ||||
| @@ -525,6 +525,135 @@ func (s *IntegrationCLITestSuite) TestPreAuthKeyCommandReusableEphemeral() { | ||||
| 	assert.Len(s.T(), listedPreAuthKeys, 2) | ||||
| } | ||||
|  | ||||
| func (s *IntegrationCLITestSuite) TestNodeTagCommand() { | ||||
| 	namespace, err := s.createNamespace("machine-namespace") | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	machineKeys := []string{ | ||||
| 		"9b2ffa7e08cc421a3d2cca9012280f6a236fd0de0b4ce005b30a98ad930306fe", | ||||
| 		"6abd00bb5fdda622db51387088c68e97e71ce58e7056aa54f592b6a8219d524c", | ||||
| 	} | ||||
| 	machines := make([]*v1.Machine, len(machineKeys)) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	for index, machineKey := range machineKeys { | ||||
| 		_, err := ExecuteCommand( | ||||
| 			&s.headscale, | ||||
| 			[]string{ | ||||
| 				"headscale", | ||||
| 				"debug", | ||||
| 				"create-node", | ||||
| 				"--name", | ||||
| 				fmt.Sprintf("machine-%d", index+1), | ||||
| 				"--namespace", | ||||
| 				namespace.Name, | ||||
| 				"--key", | ||||
| 				machineKey, | ||||
| 				"--output", | ||||
| 				"json", | ||||
| 			}, | ||||
| 			[]string{}, | ||||
| 		) | ||||
| 		assert.Nil(s.T(), err) | ||||
|  | ||||
| 		machineResult, err := ExecuteCommand( | ||||
| 			&s.headscale, | ||||
| 			[]string{ | ||||
| 				"headscale", | ||||
| 				"nodes", | ||||
| 				"--namespace", | ||||
| 				namespace.Name, | ||||
| 				"register", | ||||
| 				"--key", | ||||
| 				machineKey, | ||||
| 				"--output", | ||||
| 				"json", | ||||
| 			}, | ||||
| 			[]string{}, | ||||
| 		) | ||||
| 		assert.Nil(s.T(), err) | ||||
|  | ||||
| 		var machine v1.Machine | ||||
| 		err = json.Unmarshal([]byte(machineResult), &machine) | ||||
| 		assert.Nil(s.T(), err) | ||||
|  | ||||
| 		machines[index] = &machine | ||||
| 	} | ||||
| 	assert.Len(s.T(), machines, len(machineKeys)) | ||||
|  | ||||
| 	addTagResult, err := ExecuteCommand( | ||||
| 		&s.headscale, | ||||
| 		[]string{ | ||||
| 			"headscale", | ||||
| 			"nodes", | ||||
| 			"tag", | ||||
| 			"-i", "1", | ||||
| 			"-t", "tag:test", | ||||
| 			"--output", "json", | ||||
| 		}, | ||||
| 		[]string{}, | ||||
| 	) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	var machine v1.Machine | ||||
| 	err = json.Unmarshal([]byte(addTagResult), &machine) | ||||
| 	assert.Nil(s.T(), err) | ||||
| 	assert.Equal(s.T(), []string{"tag:test"}, machine.ForcedTags) | ||||
|  | ||||
| 	// try to set a wrong tag and retrieve the error | ||||
| 	wrongTagResult, err := ExecuteCommand( | ||||
| 		&s.headscale, | ||||
| 		[]string{ | ||||
| 			"headscale", | ||||
| 			"nodes", | ||||
| 			"tag", | ||||
| 			"-i", "2", | ||||
| 			"-t", "wrong-tag", | ||||
| 			"--output", "json", | ||||
| 		}, | ||||
| 		[]string{}, | ||||
| 	) | ||||
| 	assert.Nil(s.T(), err) | ||||
| 	type errOutput struct { | ||||
| 		Error string `json:"error"` | ||||
| 	} | ||||
| 	var errorOutput errOutput | ||||
| 	err = json.Unmarshal([]byte(wrongTagResult), &errorOutput) | ||||
| 	assert.Nil(s.T(), err) | ||||
| 	assert.Contains(s.T(), errorOutput.Error, "Invalid tag detected") | ||||
|  | ||||
| 	// Test list all nodes after added seconds | ||||
| 	listAllResult, err := ExecuteCommand( | ||||
| 		&s.headscale, | ||||
| 		[]string{ | ||||
| 			"headscale", | ||||
| 			"nodes", | ||||
| 			"list", | ||||
| 			"--output", "json", | ||||
| 		}, | ||||
| 		[]string{}, | ||||
| 	) | ||||
| 	resultMachines := make([]*v1.Machine, len(machineKeys)) | ||||
| 	assert.Nil(s.T(), err) | ||||
| 	json.Unmarshal([]byte(listAllResult), &resultMachines) | ||||
| 	found := false | ||||
| 	for _, machine := range resultMachines { | ||||
| 		if machine.ForcedTags != nil { | ||||
| 			for _, tag := range machine.ForcedTags { | ||||
| 				if tag == "tag:test" { | ||||
| 					found = true | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	assert.Equal( | ||||
| 		s.T(), | ||||
| 		true, | ||||
| 		found, | ||||
| 		"should find a machine with the tag 'tag:test' in the list of machines", | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func (s *IntegrationCLITestSuite) TestNodeCommand() { | ||||
| 	namespace, err := s.createNamespace("machine-namespace") | ||||
| 	assert.Nil(s.T(), err) | ||||
| @@ -1248,6 +1377,35 @@ func (s *IntegrationCLITestSuite) TestRouteCommand() { | ||||
| 		string(failEnableNonAdvertisedRoute), | ||||
| 		"route (route-machine) is not available on node", | ||||
| 	) | ||||
|  | ||||
| 	// Enable all routes on host | ||||
| 	enableAllRouteResult, err := ExecuteCommand( | ||||
| 		&s.headscale, | ||||
| 		[]string{ | ||||
| 			"headscale", | ||||
| 			"routes", | ||||
| 			"enable", | ||||
| 			"--output", | ||||
| 			"json", | ||||
| 			"--identifier", | ||||
| 			"0", | ||||
| 			"--all", | ||||
| 		}, | ||||
| 		[]string{}, | ||||
| 	) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	var enableAllRoute v1.Routes | ||||
| 	err = json.Unmarshal([]byte(enableAllRouteResult), &enableAllRoute) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	assert.Len(s.T(), enableAllRoute.AdvertisedRoutes, 2) | ||||
| 	assert.Contains(s.T(), enableAllRoute.AdvertisedRoutes, "10.0.0.0/8") | ||||
| 	assert.Contains(s.T(), enableAllRoute.AdvertisedRoutes, "192.168.1.0/24") | ||||
|  | ||||
| 	assert.Len(s.T(), enableAllRoute.EnabledRoutes, 2) | ||||
| 	assert.Contains(s.T(), enableAllRoute.EnabledRoutes, "10.0.0.0/8") | ||||
| 	assert.Contains(s.T(), enableAllRoute.EnabledRoutes, "192.168.1.0/24") | ||||
| } | ||||
|  | ||||
| func (s *IntegrationCLITestSuite) TestApiKeyCommand() { | ||||
| @@ -1394,3 +1552,172 @@ func (s *IntegrationCLITestSuite) TestApiKeyCommand() { | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (s *IntegrationCLITestSuite) TestNodeMoveCommand() { | ||||
| 	oldNamespace, err := s.createNamespace("old-namespace") | ||||
| 	assert.Nil(s.T(), err) | ||||
| 	newNamespace, err := s.createNamespace("new-namespace") | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	// Randomly generated machine key | ||||
| 	machineKey := "688411b767663479632d44140f08a9fde87383adc7cdeb518f62ce28a17ef0aa" | ||||
|  | ||||
| 	_, err = ExecuteCommand( | ||||
| 		&s.headscale, | ||||
| 		[]string{ | ||||
| 			"headscale", | ||||
| 			"debug", | ||||
| 			"create-node", | ||||
| 			"--name", | ||||
| 			"nomad-machine", | ||||
| 			"--namespace", | ||||
| 			oldNamespace.Name, | ||||
| 			"--key", | ||||
| 			machineKey, | ||||
| 			"--output", | ||||
| 			"json", | ||||
| 		}, | ||||
| 		[]string{}, | ||||
| 	) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	machineResult, err := ExecuteCommand( | ||||
| 		&s.headscale, | ||||
| 		[]string{ | ||||
| 			"headscale", | ||||
| 			"nodes", | ||||
| 			"--namespace", | ||||
| 			oldNamespace.Name, | ||||
| 			"register", | ||||
| 			"--key", | ||||
| 			machineKey, | ||||
| 			"--output", | ||||
| 			"json", | ||||
| 		}, | ||||
| 		[]string{}, | ||||
| 	) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	var machine v1.Machine | ||||
| 	err = json.Unmarshal([]byte(machineResult), &machine) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	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) | ||||
|  | ||||
| 	machineId := fmt.Sprintf("%d", machine.Id) | ||||
|  | ||||
| 	moveToNewNSResult, err := ExecuteCommand( | ||||
| 		&s.headscale, | ||||
| 		[]string{ | ||||
| 			"headscale", | ||||
| 			"nodes", | ||||
| 			"move", | ||||
| 			"--identifier", | ||||
| 			machineId, | ||||
| 			"--namespace", | ||||
| 			newNamespace.Name, | ||||
| 			"--output", | ||||
| 			"json", | ||||
| 		}, | ||||
| 		[]string{}, | ||||
| 	) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	err = json.Unmarshal([]byte(moveToNewNSResult), &machine) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	assert.Equal(s.T(), machine.Namespace, newNamespace) | ||||
|  | ||||
| 	listAllNodesResult, err := ExecuteCommand( | ||||
| 		&s.headscale, | ||||
| 		[]string{ | ||||
| 			"headscale", | ||||
| 			"nodes", | ||||
| 			"list", | ||||
| 			"--output", | ||||
| 			"json", | ||||
| 		}, | ||||
| 		[]string{}, | ||||
| 	) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	var allNodes []v1.Machine | ||||
| 	err = json.Unmarshal([]byte(listAllNodesResult), &allNodes) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	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) | ||||
|  | ||||
| 	moveToNonExistingNSResult, err := ExecuteCommand( | ||||
| 		&s.headscale, | ||||
| 		[]string{ | ||||
| 			"headscale", | ||||
| 			"nodes", | ||||
| 			"move", | ||||
| 			"--identifier", | ||||
| 			machineId, | ||||
| 			"--namespace", | ||||
| 			"non-existing-namespace", | ||||
| 			"--output", | ||||
| 			"json", | ||||
| 		}, | ||||
| 		[]string{}, | ||||
| 	) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	assert.Contains( | ||||
| 		s.T(), | ||||
| 		string(moveToNonExistingNSResult), | ||||
| 		"Namespace not found", | ||||
| 	) | ||||
| 	assert.Equal(s.T(), machine.Namespace, newNamespace) | ||||
|  | ||||
| 	moveToOldNSResult, err := ExecuteCommand( | ||||
| 		&s.headscale, | ||||
| 		[]string{ | ||||
| 			"headscale", | ||||
| 			"nodes", | ||||
| 			"move", | ||||
| 			"--identifier", | ||||
| 			machineId, | ||||
| 			"--namespace", | ||||
| 			oldNamespace.Name, | ||||
| 			"--output", | ||||
| 			"json", | ||||
| 		}, | ||||
| 		[]string{}, | ||||
| 	) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	err = json.Unmarshal([]byte(moveToOldNSResult), &machine) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	assert.Equal(s.T(), machine.Namespace, oldNamespace) | ||||
|  | ||||
| 	moveToSameNSResult, err := ExecuteCommand( | ||||
| 		&s.headscale, | ||||
| 		[]string{ | ||||
| 			"headscale", | ||||
| 			"nodes", | ||||
| 			"move", | ||||
| 			"--identifier", | ||||
| 			machineId, | ||||
| 			"--namespace", | ||||
| 			oldNamespace.Name, | ||||
| 			"--output", | ||||
| 			"json", | ||||
| 		}, | ||||
| 		[]string{}, | ||||
| 	) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	err = json.Unmarshal([]byte(moveToSameNSResult), &machine) | ||||
| 	assert.Nil(s.T(), err) | ||||
|  | ||||
| 	assert.Equal(s.T(), machine.Namespace, oldNamespace) | ||||
| } | ||||
|   | ||||
| @@ -20,7 +20,17 @@ var ( | ||||
| 	IpPrefix4 = netaddr.MustParseIPPrefix("100.64.0.0/10") | ||||
| 	IpPrefix6 = netaddr.MustParseIPPrefix("fd7a:115c:a1e0::/48") | ||||
|  | ||||
| 	tailscaleVersions = []string{"head", "unstable", "1.22.2", "1.20.4", "1.18.2", "1.16.2", "1.14.3", "1.12.3"} | ||||
| 	tailscaleVersions = []string{ | ||||
| 		"head", | ||||
| 		"unstable", | ||||
| 		"1.24.0", | ||||
| 		"1.22.2", | ||||
| 		"1.20.4", | ||||
| 		"1.18.2", | ||||
| 		"1.16.2", | ||||
| 		"1.14.3", | ||||
| 		"1.12.3", | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| type TestNamespace struct { | ||||
|   | ||||
| @@ -107,7 +107,10 @@ func (s *IntegrationDERPTestSuite) SetupSuite() { | ||||
| 	headscaleOptions := &dockertest.RunOptions{ | ||||
| 		Name: headscaleHostname, | ||||
| 		Mounts: []string{ | ||||
| 			fmt.Sprintf("%s/integration_test/etc_embedded_derp:/etc/headscale", currentPath), | ||||
| 			fmt.Sprintf( | ||||
| 				"%s/integration_test/etc_embedded_derp:/etc/headscale", | ||||
| 				currentPath, | ||||
| 			), | ||||
| 		}, | ||||
| 		Cmd:          []string{"headscale", "serve"}, | ||||
| 		ExposedPorts: []string{"8443/tcp", "3478/udp"}, | ||||
| @@ -197,7 +200,10 @@ func (s *IntegrationDERPTestSuite) SetupSuite() { | ||||
| 	assert.Nil(s.T(), err) | ||||
| 	assert.True(s.T(), preAuthKey.Reusable) | ||||
|  | ||||
| 	headscaleEndpoint := fmt.Sprintf("https://headscale:%s", s.headscale.GetPort("8443/tcp")) | ||||
| 	headscaleEndpoint := fmt.Sprintf( | ||||
| 		"https://headscale:%s", | ||||
| 		s.headscale.GetPort("8443/tcp"), | ||||
| 	) | ||||
|  | ||||
| 	log.Printf( | ||||
| 		"Joining tailscale containers to headscale at %s\n", | ||||
| @@ -243,7 +249,9 @@ func (s *IntegrationDERPTestSuite) Join( | ||||
| 	log.Printf("%s joined\n", hostname) | ||||
| } | ||||
|  | ||||
| func (s *IntegrationDERPTestSuite) tailscaleContainer(identifier, version string, network dockertest.Network, | ||||
| func (s *IntegrationDERPTestSuite) tailscaleContainer( | ||||
| 	identifier, version string, | ||||
| 	network dockertest.Network, | ||||
| ) (string, *dockertest.Resource) { | ||||
| 	tailscaleBuildOptions := getDockerBuildOptions(version) | ||||
|  | ||||
| @@ -260,7 +268,10 @@ func (s *IntegrationDERPTestSuite) tailscaleContainer(identifier, version string | ||||
| 		}, | ||||
|  | ||||
| 		// expose the host IP address, so we can access it from inside the container | ||||
| 		ExtraHosts: []string{"host.docker.internal:host-gateway", "headscale:host-gateway"}, | ||||
| 		ExtraHosts: []string{ | ||||
| 			"host.docker.internal:host-gateway", | ||||
| 			"headscale:host-gateway", | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	pts, err := s.pool.BuildAndRunWithBuildOptions( | ||||
|   | ||||
| @@ -47,11 +47,11 @@ func TestIntegrationTestSuite(t *testing.T) { | ||||
|  | ||||
| 	s.namespaces = map[string]TestNamespace{ | ||||
| 		"thisspace": { | ||||
| 			count:      15, | ||||
| 			count:      10, | ||||
| 			tailscales: make(map[string]dockertest.Resource), | ||||
| 		}, | ||||
| 		"otherspace": { | ||||
| 			count:      5, | ||||
| 			count:      2, | ||||
| 			tailscales: make(map[string]dockertest.Resource), | ||||
| 		}, | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										64
									
								
								machine.go
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								machine.go
									
									
									
									
									
								
							| @@ -2,6 +2,7 @@ package headscale | ||||
|  | ||||
| import ( | ||||
| 	"database/sql/driver" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"sort" | ||||
| 	"strconv" | ||||
| @@ -57,6 +58,8 @@ type Machine struct { | ||||
|  | ||||
| 	RegisterMethod string | ||||
|  | ||||
| 	ForcedTags StringList | ||||
|  | ||||
| 	// TODO(kradalby): This seems like irrelevant information? | ||||
| 	AuthKeyID uint | ||||
| 	AuthKey   *PreAuthKey | ||||
| @@ -134,7 +137,7 @@ func (machine Machine) isExpired() bool { | ||||
|  | ||||
| func containsAddresses(inputs []string, addrs []string) bool { | ||||
| 	for _, addr := range addrs { | ||||
| 		if containsString(inputs, addr) { | ||||
| 		if contains(inputs, addr) { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| @@ -369,6 +372,18 @@ func (h *Headscale) UpdateMachine(machine *Machine) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // SetTags takes a Machine struct pointer and update the forced tags. | ||||
| func (h *Headscale) SetTags(machine *Machine, tags []string) error { | ||||
| 	machine.ForcedTags = tags | ||||
| 	if err := h.UpdateACLRules(); err != nil && !errors.Is(err, errEmptyPolicy) { | ||||
| 		return err | ||||
| 	} | ||||
| 	h.setLastStateChangeToNow(machine.Namespace.Name) | ||||
| 	h.db.Save(machine) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ExpireMachine takes a Machine struct and sets the expire field to now. | ||||
| func (h *Headscale) ExpireMachine(machine *Machine) { | ||||
| 	now := time.Now() | ||||
| @@ -651,6 +666,7 @@ func (machine *Machine) toProto() *v1.Machine { | ||||
| 		Name:        machine.Hostname, | ||||
| 		GivenName:   machine.GivenName, | ||||
| 		Namespace:   machine.Namespace.toProto(), | ||||
| 		ForcedTags:  machine.ForcedTags, | ||||
|  | ||||
| 		// TODO(kradalby): Implement register method enum converter | ||||
| 		// RegisterMethod: , | ||||
| @@ -679,6 +695,50 @@ func (machine *Machine) toProto() *v1.Machine { | ||||
| 	return machineProto | ||||
| } | ||||
|  | ||||
| // getTags will return the tags of the current machine. | ||||
| // Invalid tags are tags added by a user on a node, and that user doesn't have authority to add this tag. | ||||
| // Valid tags are tags added by a user that is allowed in the ACL policy to add this tag. | ||||
| func getTags( | ||||
| 	aclPolicy *ACLPolicy, | ||||
| 	machine Machine, | ||||
| 	stripEmailDomain bool, | ||||
| ) ([]string, []string) { | ||||
| 	validTags := make([]string, 0) | ||||
| 	invalidTags := make([]string, 0) | ||||
| 	if aclPolicy == nil { | ||||
| 		return validTags, invalidTags | ||||
| 	} | ||||
| 	validTagMap := make(map[string]bool) | ||||
| 	invalidTagMap := make(map[string]bool) | ||||
| 	for _, tag := range machine.HostInfo.RequestTags { | ||||
| 		owners, err := expandTagOwners(*aclPolicy, tag, stripEmailDomain) | ||||
| 		if errors.Is(err, errInvalidTag) { | ||||
| 			invalidTagMap[tag] = true | ||||
|  | ||||
| 			continue | ||||
| 		} | ||||
| 		var found bool | ||||
| 		for _, owner := range owners { | ||||
| 			if machine.Namespace.Name == owner { | ||||
| 				found = true | ||||
| 			} | ||||
| 		} | ||||
| 		if found { | ||||
| 			validTagMap[tag] = true | ||||
| 		} else { | ||||
| 			invalidTagMap[tag] = true | ||||
| 		} | ||||
| 	} | ||||
| 	for tag := range invalidTagMap { | ||||
| 		invalidTags = append(invalidTags, tag) | ||||
| 	} | ||||
| 	for tag := range validTagMap { | ||||
| 		validTags = append(validTags, tag) | ||||
| 	} | ||||
|  | ||||
| 	return validTags, invalidTags | ||||
| } | ||||
|  | ||||
| func (h *Headscale) RegisterMachineFromAuthCallback( | ||||
| 	machineKeyStr string, | ||||
| 	namespaceName string, | ||||
| @@ -789,7 +849,7 @@ func (h *Headscale) EnableRoutes(machine *Machine, routeStrs ...string) error { | ||||
| 	} | ||||
|  | ||||
| 	for _, newRoute := range newRoutes { | ||||
| 		if !containsIPPrefix(machine.GetAdvertisedRoutes(), newRoute) { | ||||
| 		if !contains(machine.GetAdvertisedRoutes(), newRoute) { | ||||
| 			return fmt.Errorf( | ||||
| 				"route (%s) is not available on node %s: %w", | ||||
| 				machine.Hostname, | ||||
|   | ||||
							
								
								
									
										151
									
								
								machine_test.go
									
									
									
									
									
								
							
							
						
						
									
										151
									
								
								machine_test.go
									
									
									
									
									
								
							| @@ -278,6 +278,157 @@ func (s *Suite) TestSerdeAddressStrignSlice(c *check.C) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func Test_getTags(t *testing.T) { | ||||
| 	type args struct { | ||||
| 		aclPolicy        *ACLPolicy | ||||
| 		machine          Machine | ||||
| 		stripEmailDomain bool | ||||
| 	} | ||||
| 	tests := []struct { | ||||
| 		name        string | ||||
| 		args        args | ||||
| 		wantInvalid []string | ||||
| 		wantValid   []string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			name: "valid tag one machine", | ||||
| 			args: args{ | ||||
| 				aclPolicy: &ACLPolicy{ | ||||
| 					TagOwners: TagOwners{ | ||||
| 						"tag:valid": []string{"joe"}, | ||||
| 					}, | ||||
| 				}, | ||||
| 				machine: Machine{ | ||||
| 					Namespace: Namespace{ | ||||
| 						Name: "joe", | ||||
| 					}, | ||||
| 					HostInfo: HostInfo{ | ||||
| 						RequestTags: []string{"tag:valid"}, | ||||
| 					}, | ||||
| 				}, | ||||
| 				stripEmailDomain: false, | ||||
| 			}, | ||||
| 			wantValid:   []string{"tag:valid"}, | ||||
| 			wantInvalid: nil, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "invalid tag and valid tag one machine", | ||||
| 			args: args{ | ||||
| 				aclPolicy: &ACLPolicy{ | ||||
| 					TagOwners: TagOwners{ | ||||
| 						"tag:valid": []string{"joe"}, | ||||
| 					}, | ||||
| 				}, | ||||
| 				machine: Machine{ | ||||
| 					Namespace: Namespace{ | ||||
| 						Name: "joe", | ||||
| 					}, | ||||
| 					HostInfo: HostInfo{ | ||||
| 						RequestTags: []string{"tag:valid", "tag:invalid"}, | ||||
| 					}, | ||||
| 				}, | ||||
| 				stripEmailDomain: false, | ||||
| 			}, | ||||
| 			wantValid:   []string{"tag:valid"}, | ||||
| 			wantInvalid: []string{"tag:invalid"}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "multiple invalid and identical tags, should return only one invalid tag", | ||||
| 			args: args{ | ||||
| 				aclPolicy: &ACLPolicy{ | ||||
| 					TagOwners: TagOwners{ | ||||
| 						"tag:valid": []string{"joe"}, | ||||
| 					}, | ||||
| 				}, | ||||
| 				machine: Machine{ | ||||
| 					Namespace: Namespace{ | ||||
| 						Name: "joe", | ||||
| 					}, | ||||
| 					HostInfo: HostInfo{ | ||||
| 						RequestTags: []string{ | ||||
| 							"tag:invalid", | ||||
| 							"tag:valid", | ||||
| 							"tag:invalid", | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 				stripEmailDomain: false, | ||||
| 			}, | ||||
| 			wantValid:   []string{"tag:valid"}, | ||||
| 			wantInvalid: []string{"tag:invalid"}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "only invalid tags", | ||||
| 			args: args{ | ||||
| 				aclPolicy: &ACLPolicy{ | ||||
| 					TagOwners: TagOwners{ | ||||
| 						"tag:valid": []string{"joe"}, | ||||
| 					}, | ||||
| 				}, | ||||
| 				machine: Machine{ | ||||
| 					Namespace: Namespace{ | ||||
| 						Name: "joe", | ||||
| 					}, | ||||
| 					HostInfo: HostInfo{ | ||||
| 						RequestTags: []string{"tag:invalid", "very-invalid"}, | ||||
| 					}, | ||||
| 				}, | ||||
| 				stripEmailDomain: false, | ||||
| 			}, | ||||
| 			wantValid:   nil, | ||||
| 			wantInvalid: []string{"tag:invalid", "very-invalid"}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "empty ACLPolicy should return empty tags and should not panic", | ||||
| 			args: args{ | ||||
| 				aclPolicy: nil, | ||||
| 				machine: Machine{ | ||||
| 					Namespace: Namespace{ | ||||
| 						Name: "joe", | ||||
| 					}, | ||||
| 					HostInfo: HostInfo{ | ||||
| 						RequestTags: []string{"tag:invalid", "very-invalid"}, | ||||
| 					}, | ||||
| 				}, | ||||
| 				stripEmailDomain: false, | ||||
| 			}, | ||||
| 			wantValid:   nil, | ||||
| 			wantInvalid: nil, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, test := range tests { | ||||
| 		t.Run(test.name, func(t *testing.T) { | ||||
| 			gotValid, gotInvalid := getTags( | ||||
| 				test.args.aclPolicy, | ||||
| 				test.args.machine, | ||||
| 				test.args.stripEmailDomain, | ||||
| 			) | ||||
| 			for _, valid := range gotValid { | ||||
| 				if !contains(test.wantValid, valid) { | ||||
| 					t.Errorf( | ||||
| 						"valids: getTags() = %v, want %v", | ||||
| 						gotValid, | ||||
| 						test.wantValid, | ||||
| 					) | ||||
|  | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 			for _, invalid := range gotInvalid { | ||||
| 				if !contains(test.wantInvalid, invalid) { | ||||
| 					t.Errorf( | ||||
| 						"invalids: getTags() = %v, want %v", | ||||
| 						gotInvalid, | ||||
| 						test.wantInvalid, | ||||
| 					) | ||||
|  | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // nolint | ||||
| func Test_getFilteredByACLPeers(t *testing.T) { | ||||
| 	type args struct { | ||||
|   | ||||
| @@ -177,8 +177,10 @@ func (h *Headscale) SetMachineNamespace(machine *Machine, namespaceName string) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	machine.NamespaceID = namespace.ID | ||||
| 	h.db.Save(&machine) | ||||
| 	machine.Namespace = *namespace | ||||
| 	if result := h.db.Save(&machine); result.Error != nil { | ||||
| 		return result.Error | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -372,3 +372,40 @@ func TestCheckForFQDNRules(t *testing.T) { | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (s *Suite) TestSetMachineNamespace(c *check.C) { | ||||
| 	oldNamespace, err := app.CreateNamespace("old") | ||||
| 	c.Assert(err, check.IsNil) | ||||
|  | ||||
| 	newNamespace, err := app.CreateNamespace("new") | ||||
| 	c.Assert(err, check.IsNil) | ||||
|  | ||||
| 	pak, err := app.CreatePreAuthKey(oldNamespace.Name, false, false, nil) | ||||
| 	c.Assert(err, check.IsNil) | ||||
|  | ||||
| 	machine := Machine{ | ||||
| 		ID:             0, | ||||
| 		MachineKey:     "foo", | ||||
| 		NodeKey:        "bar", | ||||
| 		DiscoKey:       "faa", | ||||
| 		Hostname:       "testmachine", | ||||
| 		NamespaceID:    oldNamespace.ID, | ||||
| 		RegisterMethod: RegisterMethodAuthKey, | ||||
| 		AuthKeyID:      uint(pak.ID), | ||||
| 	} | ||||
| 	app.db.Save(&machine) | ||||
| 	c.Assert(machine.NamespaceID, check.Equals, oldNamespace.ID) | ||||
|  | ||||
| 	err = app.SetMachineNamespace(&machine, newNamespace.Name) | ||||
| 	c.Assert(err, check.IsNil) | ||||
| 	c.Assert(machine.NamespaceID, check.Equals, newNamespace.ID) | ||||
| 	c.Assert(machine.Namespace.Name, check.Equals, newNamespace.Name) | ||||
|  | ||||
| 	err = app.SetMachineNamespace(&machine, "non-existing-namespace") | ||||
| 	c.Assert(err, check.Equals, errNamespaceNotFound) | ||||
|  | ||||
| 	err = app.SetMachineNamespace(&machine, newNamespace.Name) | ||||
| 	c.Assert(err, check.IsNil) | ||||
| 	c.Assert(machine.NamespaceID, check.Equals, newNamespace.ID) | ||||
| 	c.Assert(machine.Namespace.Name, check.Equals, newNamespace.Name) | ||||
| } | ||||
|   | ||||
							
								
								
									
										34
									
								
								oidc.go
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								oidc.go
									
									
									
									
									
								
							| @@ -53,7 +53,7 @@ func (h *Headscale) initOIDC() error { | ||||
| 				"%s/oidc/callback", | ||||
| 				strings.TrimSuffix(h.cfg.ServerURL, "/"), | ||||
| 			), | ||||
| 			Scopes: []string{oidc.ScopeOpenID, "profile", "email"}, | ||||
| 			Scopes: h.cfg.OIDC.Scope, | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -91,7 +91,14 @@ func (h *Headscale) RegisterOIDC(ctx *gin.Context) { | ||||
| 	// place the machine key into the state cache, so it can be retrieved later | ||||
| 	h.registrationCache.Set(stateStr, machineKeyStr, registerCacheExpiration) | ||||
|  | ||||
| 	authURL := h.oauth2Config.AuthCodeURL(stateStr) | ||||
| 	// Add any extra parameter provided in the configuration to the Authorize Endpoint request | ||||
| 	extras := make([]oauth2.AuthCodeOption, 0, len(h.cfg.OIDC.ExtraParams)) | ||||
|  | ||||
| 	for k, v := range h.cfg.OIDC.ExtraParams { | ||||
| 		extras = append(extras, oauth2.SetAuthURLParam(k, v)) | ||||
| 	} | ||||
|  | ||||
| 	authURL := h.oauth2Config.AuthCodeURL(stateStr, extras...) | ||||
| 	log.Debug().Msgf("Redirecting to %s for authentication", authURL) | ||||
|  | ||||
| 	ctx.Redirect(http.StatusFound, authURL) | ||||
| @@ -187,6 +194,29 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// If AllowedDomains is provided, check that the authenticated principal ends with @<alloweddomain>. | ||||
| 	if len(h.cfg.OIDC.AllowedDomains) > 0 { | ||||
| 		if at := strings.LastIndex(claims.Email, "@"); at < 0 || | ||||
| 			!IsStringInSlice(h.cfg.OIDC.AllowedDomains, claims.Email[at+1:]) { | ||||
| 			log.Error().Msg("authenticated principal does not match any allowed domain") | ||||
| 			ctx.String( | ||||
| 				http.StatusBadRequest, | ||||
| 				"unauthorized principal (domain mismatch)", | ||||
| 			) | ||||
|  | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// If AllowedUsers is provided, check that the authenticated princial is part of that list. | ||||
| 	if len(h.cfg.OIDC.AllowedUsers) > 0 && | ||||
| 		!IsStringInSlice(h.cfg.OIDC.AllowedUsers, claims.Email) { | ||||
| 		log.Error().Msg("authenticated principal does not match any allowed user") | ||||
| 		ctx.String(http.StatusBadRequest, "unauthorized principal (user mismatch)") | ||||
|  | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// retrieve machinekey from state cache | ||||
| 	machineKeyIf, machineKeyFound := h.registrationCache.Get(state) | ||||
|  | ||||
|   | ||||
							
								
								
									
										10
									
								
								poll.go
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								poll.go
									
									
									
									
									
								
							| @@ -20,6 +20,10 @@ const ( | ||||
| 	updateCheckInterval = 10 * time.Second | ||||
| ) | ||||
|  | ||||
| type contextKey string | ||||
|  | ||||
| const machineNameContextKey = contextKey("machineName") | ||||
|  | ||||
| // PollNetMapHandler takes care of /machine/:id/map | ||||
| // | ||||
| // This is the busiest endpoint, as it keeps the HTTP long poll that updates | ||||
| @@ -261,7 +265,7 @@ func (h *Headscale) PollNetMapStream( | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		ctx := context.WithValue(ctx.Request.Context(), "machineName", machine.Hostname) | ||||
| 		ctx := context.WithValue(ctx.Request.Context(), machineNameContextKey, machine.Hostname) | ||||
|  | ||||
| 		ctx, cancel := context.WithCancel(ctx) | ||||
| 		defer cancel() | ||||
| @@ -565,12 +569,12 @@ func (h *Headscale) scheduledPollWorker( | ||||
|  | ||||
| 	defer closeChanWithLog( | ||||
| 		updateChan, | ||||
| 		fmt.Sprint(ctx.Value("machineName")), | ||||
| 		fmt.Sprint(ctx.Value(machineNameContextKey)), | ||||
| 		"updateChan", | ||||
| 	) | ||||
| 	defer closeChanWithLog( | ||||
| 		keepAliveChan, | ||||
| 		fmt.Sprint(ctx.Value("machineName")), | ||||
| 		fmt.Sprint(ctx.Value(machineNameContextKey)), | ||||
| 		"updateChan", | ||||
| 	) | ||||
|  | ||||
|   | ||||
| @@ -81,6 +81,13 @@ service HeadscaleService { | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     rpc SetTags(SetTagsRequest) returns (SetTagsResponse) { | ||||
|         option (google.api.http) = { | ||||
|             post: "/api/v1/machine/{machine_id}/tags" | ||||
|             body: "*" | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     rpc RegisterMachine(RegisterMachineRequest) returns (RegisterMachineResponse) { | ||||
|         option (google.api.http) = { | ||||
|             post: "/api/v1/machine/register" | ||||
| @@ -110,6 +117,12 @@ service HeadscaleService { | ||||
|             get: "/api/v1/machine" | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     rpc MoveMachine(MoveMachineRequest) returns (MoveMachineResponse) { | ||||
|         option (google.api.http) = { | ||||
|             post: "/api/v1/machine/{machine_id}/namespace" | ||||
|         }; | ||||
|     } | ||||
|     // --- Machine end --- | ||||
|  | ||||
|     // --- Route start --- | ||||
|   | ||||
| @@ -22,7 +22,6 @@ message Machine { | ||||
|     string          name         = 6; | ||||
|     Namespace namespace          = 7; | ||||
|  | ||||
|  | ||||
|     google.protobuf.Timestamp last_seen              = 8; | ||||
|     google.protobuf.Timestamp last_successful_update = 9; | ||||
|     google.protobuf.Timestamp expiry                 = 10; | ||||
| @@ -32,6 +31,8 @@ message Machine { | ||||
|     google.protobuf.Timestamp created_at = 12; | ||||
|  | ||||
|     RegisterMethod register_method = 13; | ||||
|  | ||||
|     reserved 14 to 17; | ||||
|     // google.protobuf.Timestamp updated_at = 14; | ||||
|     // google.protobuf.Timestamp deleted_at = 15; | ||||
|  | ||||
| @@ -39,7 +40,10 @@ message Machine { | ||||
|     // bytes endpoints      = 16; | ||||
|     // bytes enabled_routes = 17; | ||||
|  | ||||
|     string          given_name     = 18; | ||||
|     repeated string forced_tags  = 18; | ||||
|     repeated string invalid_tags = 19; | ||||
|     repeated string valid_tags   = 20; | ||||
|     string          given_name   = 21; | ||||
| } | ||||
|  | ||||
| message RegisterMachineRequest { | ||||
| @@ -59,6 +63,15 @@ message GetMachineResponse { | ||||
|     Machine machine = 1; | ||||
| } | ||||
|  | ||||
| message SetTagsRequest { | ||||
|     uint64          machine_id = 1; | ||||
|     repeated string tags       = 2; | ||||
| } | ||||
|  | ||||
| message SetTagsResponse { | ||||
|     Machine machine = 1; | ||||
| } | ||||
|  | ||||
| message DeleteMachineRequest { | ||||
|     uint64 machine_id = 1; | ||||
| } | ||||
| @@ -91,6 +104,15 @@ message ListMachinesResponse { | ||||
|     repeated Machine machines = 1; | ||||
| } | ||||
|  | ||||
| message MoveMachineRequest { | ||||
|     uint64 machine_id = 1; | ||||
|     string namespace  = 2; | ||||
| } | ||||
|  | ||||
| message MoveMachineResponse { | ||||
|     Machine machine = 1; | ||||
| } | ||||
|  | ||||
| message DebugCreateMachineRequest { | ||||
|     string namespace       = 1; | ||||
|     string          key    = 2; | ||||
|   | ||||
							
								
								
									
										13
									
								
								tools.go
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								tools.go
									
									
									
									
									
								
							| @@ -1,13 +0,0 @@ | ||||
| //go:build tools | ||||
| // +build tools | ||||
|  | ||||
| package tools | ||||
|  | ||||
| import ( | ||||
| 	_ "github.com/bufbuild/buf/cmd/buf" | ||||
| 	_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway" | ||||
| 	_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2" | ||||
| 	_ "github.com/infobloxopen/protoc-gen-gorm" | ||||
| 	_ "google.golang.org/grpc/cmd/protoc-gen-go-grpc" | ||||
| 	_ "google.golang.org/protobuf/cmd/protoc-gen-go" | ||||
| ) | ||||
							
								
								
									
										40
									
								
								utils.go
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								utils.go
									
									
									
									
									
								
							| @@ -12,6 +12,7 @@ import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/rs/zerolog/log" | ||||
| @@ -135,26 +136,29 @@ func encode( | ||||
| 	return privKey.SealTo(*pubKey, b), nil | ||||
| } | ||||
|  | ||||
| func (h *Headscale) getAvailableIPs() (ips MachineAddresses, err error) { | ||||
| func (h *Headscale) getAvailableIPs() (MachineAddresses, error) { | ||||
| 	var ips MachineAddresses | ||||
| 	var err error | ||||
| 	ipPrefixes := h.cfg.IPPrefixes | ||||
| 	for _, ipPrefix := range ipPrefixes { | ||||
| 		var ip *netaddr.IP | ||||
| 		ip, err = h.getAvailableIP(ipPrefix) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 			return ips, err | ||||
| 		} | ||||
| 		ips = append(ips, *ip) | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| 	return ips, err | ||||
| } | ||||
|  | ||||
| func GetIPPrefixEndpoints(na netaddr.IPPrefix) (network, broadcast netaddr.IP) { | ||||
| func GetIPPrefixEndpoints(na netaddr.IPPrefix) (netaddr.IP, netaddr.IP) { | ||||
| 	var network, broadcast netaddr.IP | ||||
| 	ipRange := na.Range() | ||||
| 	network = ipRange.From() | ||||
| 	broadcast = ipRange.To() | ||||
|  | ||||
| 	return | ||||
| 	return network, broadcast | ||||
| } | ||||
|  | ||||
| func (h *Headscale) getAvailableIP(ipPrefix netaddr.IPPrefix) (*netaddr.IP, error) { | ||||
| @@ -223,16 +227,6 @@ func (h *Headscale) getUsedIPs() (*netaddr.IPSet, error) { | ||||
| 	return ipSet, nil | ||||
| } | ||||
|  | ||||
| func containsString(ss []string, s string) bool { | ||||
| 	for _, v := range ss { | ||||
| 		if v == s { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func tailNodesToString(nodes []*tailcfg.Node) string { | ||||
| 	temp := make([]string, len(nodes)) | ||||
|  | ||||
| @@ -282,9 +276,9 @@ func stringToIPPrefix(prefixes []string) ([]netaddr.IPPrefix, error) { | ||||
| 	return result, nil | ||||
| } | ||||
|  | ||||
| func containsIPPrefix(prefixes []netaddr.IPPrefix, prefix netaddr.IPPrefix) bool { | ||||
| 	for _, p := range prefixes { | ||||
| 		if prefix == p { | ||||
| func contains[T string | netaddr.IPPrefix](ts []T, t T) bool { | ||||
| 	for _, v := range ts { | ||||
| 		if reflect.DeepEqual(v, t) { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| @@ -330,3 +324,13 @@ func GenerateRandomStringDNSSafe(n int) (string, error) { | ||||
|  | ||||
| 	return str[:n], err | ||||
| } | ||||
|  | ||||
| func IsStringInSlice(slice []string, str string) bool { | ||||
| 	for _, s := range slice { | ||||
| 		if s == str { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user