From f79a2f308115d4dd5b09cf6d9173761c4c7a3686 Mon Sep 17 00:00:00 2001 From: Pallab Pain Date: Sun, 2 Jun 2024 12:24:15 +0530 Subject: [PATCH] feat: implements apis for managing headscale policy This commit introduces APIs for managing the headscale policy. Until now, the support was limited to file based policy and users could only update the file and reload headscale in order to apply the changes in the policy. With the new APIs, the users of headscale and now manage the policy programatically and will not require to restart headscale. The commit also implements the CLI commands to get and set the policy. BREAKING CHANGE: headscale no longer supports YAML policy files and the only supported format is HuJSON. --- .github/workflows/test-integration.yaml | 2 + CHANGELOG.md | 3 + cmd/headscale/cli/policy.go | 91 +++ cmd/headscale/cli/utils.go | 31 +- config-example.yaml | 16 +- gen/go/headscale/v1/apikey.pb.go | 2 +- gen/go/headscale/v1/device.pb.go | 2 +- gen/go/headscale/v1/headscale.pb.go | 532 +++++++++--------- gen/go/headscale/v1/headscale.pb.gw.go | 240 +++++++- gen/go/headscale/v1/headscale_grpc.pb.go | 214 ++++--- gen/go/headscale/v1/node.pb.go | 2 +- gen/go/headscale/v1/policy.pb.go | 352 ++++++++++++ gen/go/headscale/v1/preauthkey.pb.go | 2 +- gen/go/headscale/v1/routes.pb.go | 2 +- gen/go/headscale/v1/user.pb.go | 2 +- .../headscale/v1/apikey.swagger.json | 1 - .../headscale/v1/device.swagger.json | 1 - .../headscale/v1/headscale.swagger.json | 113 +++- gen/openapiv2/headscale/v1/node.swagger.json | 1 - .../headscale/v1/policy.swagger.json | 43 ++ .../headscale/v1/preauthkey.swagger.json | 1 - .../headscale/v1/routes.swagger.json | 1 - gen/openapiv2/headscale/v1/user.swagger.json | 1 - hscontrol/app.go | 86 ++- hscontrol/db/db.go | 12 + hscontrol/db/node_test.go | 9 +- hscontrol/db/policy.go | 44 ++ hscontrol/grpcv1.go | 74 +++ hscontrol/policy/acls.go | 44 +- hscontrol/policy/acls_test.go | 64 +-- hscontrol/policy/acls_types.go | 70 +-- hscontrol/types/config.go | 55 +- hscontrol/types/policy.go | 20 + integration/acl_test.go | 155 +++++ integration/cli_test.go | 83 ++- integration/control.go | 4 +- proto/headscale/v1/headscale.proto | 17 + proto/headscale/v1/policy.proto | 21 + 38 files changed, 1850 insertions(+), 563 deletions(-) create mode 100644 cmd/headscale/cli/policy.go create mode 100644 gen/go/headscale/v1/policy.pb.go create mode 100644 gen/openapiv2/headscale/v1/policy.swagger.json create mode 100644 hscontrol/db/policy.go create mode 100644 hscontrol/types/policy.go create mode 100644 proto/headscale/v1/policy.proto diff --git a/.github/workflows/test-integration.yaml b/.github/workflows/test-integration.yaml index 9581badaef..ed1d12219f 100644 --- a/.github/workflows/test-integration.yaml +++ b/.github/workflows/test-integration.yaml @@ -18,6 +18,7 @@ jobs: - TestACLNamedHostsCanReachBySubnet - TestACLNamedHostsCanReach - TestACLDevice1CanAccessDevice2 + - TestPolicyUpdateWhileRunningWithCLIInDatabase - TestOIDCAuthenticationPingAll - TestOIDCExpireNodesBasedOnTokenExpiry - TestAuthWebFlowAuthenticationPingAll @@ -35,6 +36,7 @@ jobs: - TestNodeExpireCommand - TestNodeRenameCommand - TestNodeMoveCommand + - TestPolicyCommand - TestDERPServerScenario - TestPingAllByIP - TestPingAllByIPPublicDERP diff --git a/CHANGELOG.md b/CHANGELOG.md index fced0b6d5e..fd8787adc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,8 @@ after improving the test harness as part of adopting [#1460](https://github.com/ - This is in preperation to fix Headscales implementation of tags which currently does not correctly remove the link between a tagged device and a user. As tagged devices will not have a user, this will require a change to the DNS generation, removing the username, see [#1369](https://github.com/juanfont/headscale/issues/1369) for more information. - `use_username_in_magic_dns` can be used to turn this behaviour on again, but note that this option _will be removed_ when tags are fixed. - This option brings Headscales behaviour in line with Tailscale. +- YAML files are no longer supported for headscale policy. [#1792](https://github.com/juanfont/headscale/pull/1792) + - HuJSON is now the only supported format for policy. ### Changes @@ -64,6 +66,7 @@ after improving the test harness as part of adopting [#1460](https://github.com/ - Restore foreign keys and add constraints [#1562](https://github.com/juanfont/headscale/pull/1562) - Make registration page easier to use on mobile devices - Make write-ahead-log default on and configurable for SQLite [#1985](https://github.com/juanfont/headscale/pull/1985) +- Add APIs for managing headscale policy. [#1792](https://github.com/juanfont/headscale/pull/1792) ## 0.22.3 (2023-05-12) diff --git a/cmd/headscale/cli/policy.go b/cmd/headscale/cli/policy.go new file mode 100644 index 0000000000..5b34a1e1c0 --- /dev/null +++ b/cmd/headscale/cli/policy.go @@ -0,0 +1,91 @@ +package cli + +import ( + "io" + "os" + + "github.com/rs/zerolog/log" + "github.com/spf13/cobra" + + v1 "github.com/juanfont/headscale/gen/go/headscale/v1" +) + +func init() { + rootCmd.AddCommand(policyCmd) + policyCmd.AddCommand(getPolicy) + + setPolicy.Flags().StringP("file", "f", "", "Path to a policy file in HuJSON format") + if err := setPolicy.MarkFlagRequired("file"); err != nil { + log.Fatal().Err(err).Msg("") + } + policyCmd.AddCommand(setPolicy) +} + +var policyCmd = &cobra.Command{ + Use: "policy", + Short: "Manage the Headscale ACL Policy", +} + +var getPolicy = &cobra.Command{ + Use: "get", + Short: "Print the current ACL Policy", + Aliases: []string{"show", "view", "fetch"}, + Run: func(cmd *cobra.Command, args []string) { + ctx, client, conn, cancel := getHeadscaleCLIClient() + defer cancel() + defer conn.Close() + + request := &v1.GetPolicyRequest{} + + response, err := client.GetPolicy(ctx, request) + if err != nil { + log.Fatal().Err(err).Msg("Failed to get the policy") + + return + } + + // TODO(pallabpain): Maybe print this better? + SuccessOutput("", response.GetPolicy(), "hujson") + }, +} + +var setPolicy = &cobra.Command{ + Use: "set", + Short: "Updates the ACL Policy", + Long: ` + Updates the existing ACL Policy with the provided policy. The policy must be a valid HuJSON object. + This command only works when the acl.policy_mode is set to "db", and the policy will be stored in the database.`, + Aliases: []string{"put", "update"}, + Run: func(cmd *cobra.Command, args []string) { + policyPath, _ := cmd.Flags().GetString("file") + + f, err := os.Open(policyPath) + if err != nil { + log.Fatal().Err(err).Msg("Error opening the policy file") + + return + } + defer f.Close() + + policyBytes, err := io.ReadAll(f) + if err != nil { + log.Fatal().Err(err).Msg("Error reading the policy file") + + return + } + + request := &v1.SetPolicyRequest{Policy: string(policyBytes)} + + ctx, client, conn, cancel := getHeadscaleCLIClient() + defer cancel() + defer conn.Close() + + if _, err := client.SetPolicy(ctx, request); err != nil { + log.Fatal().Err(err).Msg("Failed to set ACL Policy") + + return + } + + SuccessOutput(nil, "Policy updated.", "") + }, +} diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index a193d17dfb..8a91c5c614 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -8,16 +8,16 @@ import ( "os" "reflect" - v1 "github.com/juanfont/headscale/gen/go/headscale/v1" - "github.com/juanfont/headscale/hscontrol" - "github.com/juanfont/headscale/hscontrol/policy" - "github.com/juanfont/headscale/hscontrol/types" - "github.com/juanfont/headscale/hscontrol/util" "github.com/rs/zerolog/log" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" "gopkg.in/yaml.v3" + + v1 "github.com/juanfont/headscale/gen/go/headscale/v1" + "github.com/juanfont/headscale/hscontrol" + "github.com/juanfont/headscale/hscontrol/types" + "github.com/juanfont/headscale/hscontrol/util" ) const ( @@ -39,21 +39,6 @@ func getHeadscaleApp() (*hscontrol.Headscale, error) { return nil, err } - // We are doing this here, as in the future could be cool to have it also hot-reload - - if cfg.ACL.PolicyPath != "" { - aclPath := util.AbsolutePathFromConfigPath(cfg.ACL.PolicyPath) - pol, err := policy.LoadACLPolicyFromPath(aclPath) - if err != nil { - log.Fatal(). - Str("path", aclPath). - Err(err). - Msg("Could not load the ACL policy") - } - - app.ACLPolicy = pol - } - return app, nil } @@ -89,7 +74,7 @@ func getHeadscaleCLIClient() (context.Context, v1.HeadscaleServiceClient, *grpc. // Try to give the user better feedback if we cannot write to the headscale // socket. - socket, err := os.OpenFile(cfg.UnixSocket, os.O_WRONLY, SocketWritePermissions) //nolint + socket, err := os.OpenFile(cfg.UnixSocket, os.O_WRONLY, SocketWritePermissions) // nolint if err != nil { if os.IsPermission(err) { log.Fatal(). @@ -167,13 +152,13 @@ func SuccessOutput(result interface{}, override string, outputFormat string) { log.Fatal().Err(err).Msg("failed to unmarshal output") } default: - //nolint + // nolint fmt.Println(override) return } - //nolint + // nolint fmt.Println(string(jsonBytes)) } diff --git a/config-example.yaml b/config-example.yaml index 4608317ac8..f408ff50c9 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -203,10 +203,18 @@ log: format: text level: info -# Path to a file containing ACL policies. -# ACLs can be defined as YAML or HUJSON. -# https://tailscale.com/kb/1018/acls/ -acl_policy_path: "" +## Policy +# headscale supports Tailscale's ACL policies. +# Please have a look to their KB to better +# understand the concepts: https://tailscale.com/kb/1018/acls/ +policy: + # The mode can be "file" or "database" that defines + # where the ACL policies are stored and read from. + mode: file + # If the mode is set to "file", the + # path to a file containing ACL policies. + # The file can be in YAML or HuJSON format. + path: "" ## DNS # diff --git a/gen/go/headscale/v1/apikey.pb.go b/gen/go/headscale/v1/apikey.pb.go index c4377e48d2..d1a5f555fa 100644 --- a/gen/go/headscale/v1/apikey.pb.go +++ b/gen/go/headscale/v1/apikey.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.32.0 // protoc (unknown) // source: headscale/v1/apikey.proto diff --git a/gen/go/headscale/v1/device.pb.go b/gen/go/headscale/v1/device.pb.go index 7a382dd671..40e2e24faf 100644 --- a/gen/go/headscale/v1/device.pb.go +++ b/gen/go/headscale/v1/device.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.32.0 // protoc (unknown) // source: headscale/v1/device.proto diff --git a/gen/go/headscale/v1/headscale.pb.go b/gen/go/headscale/v1/headscale.pb.go index 9de6b0606c..63e7d53684 100644 --- a/gen/go/headscale/v1/headscale.pb.go +++ b/gen/go/headscale/v1/headscale.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.32.0 // protoc (unknown) // source: headscale/v1/headscale.proto @@ -36,210 +36,225 @@ var file_headscale_v1_headscale_proto_rawDesc = []byte{ 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, 0x80, 0x19, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x63, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x12, 0x1c, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1d, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, - 0x75, 0x73, 0x65, 0x72, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x68, 0x0a, 0x0a, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, - 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x65, 0x61, - 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a, 0x22, 0x0c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, - 0x2f, 0x75, 0x73, 0x65, 0x72, 0x12, 0x82, 0x01, 0x0a, 0x0a, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, + 0x6f, 0x1a, 0x19, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xcf, 0x1a, 0x0a, + 0x10, 0x48, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x63, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x68, + 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x68, 0x65, 0x61, + 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x15, 0x12, 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, + 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x68, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x22, - 0x29, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x7b, 0x6f, - 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x2f, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2f, - 0x7b, 0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x6c, 0x0a, 0x0a, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, - 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, - 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, - 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x15, 0x2a, 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, - 0x72, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x62, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, - 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x1e, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x12, 0x0c, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x12, 0x80, 0x01, 0x0a, - 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, - 0x79, 0x12, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, - 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, - 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x3a, + 0x01, 0x2a, 0x22, 0x0c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, + 0x12, 0x82, 0x01, 0x0a, 0x0a, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, + 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x22, 0x29, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x7b, 0x6f, 0x6c, 0x64, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x7d, 0x2f, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2f, 0x7b, 0x6e, 0x65, 0x77, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x6c, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, + 0x73, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x2a, 0x13, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x7b, 0x6e, 0x61, + 0x6d, 0x65, 0x7d, 0x12, 0x62, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, + 0x12, 0x1e, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x12, 0x0c, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x12, 0x80, 0x01, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x2e, 0x68, + 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, + 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x17, 0x3a, 0x01, 0x2a, 0x22, 0x12, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, + 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65, 0x79, 0x12, 0x87, 0x01, 0x0a, 0x10, 0x45, + 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x12, + 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, + 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, + 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, + 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x22, 0x19, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65, 0x79, 0x2f, 0x65, 0x78, + 0x70, 0x69, 0x72, 0x65, 0x12, 0x7a, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x41, + 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, + 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x41, 0x75, + 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, + 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x61, + 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65, 0x79, + 0x12, 0x7d, 0x0a, 0x0f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, + 0x6f, 0x64, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, + 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, + 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, 0x01, 0x2a, 0x22, 0x12, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, 0x65, 0x79, 0x12, - 0x87, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, - 0x68, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, - 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x65, - 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, - 0x65, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x22, 0x19, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, - 0x65, 0x79, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x12, 0x7a, 0x0a, 0x0f, 0x4c, 0x69, 0x73, - 0x74, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x24, 0x2e, 0x68, - 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x14, 0x12, 0x12, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, - 0x74, 0x68, 0x6b, 0x65, 0x79, 0x12, 0x7d, 0x0a, 0x0f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, - 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, - 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, - 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, 0x01, 0x2a, - 0x22, 0x12, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2f, - 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x66, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x12, - 0x1c, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, + 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x12, + 0x66, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x68, 0x65, 0x61, + 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, + 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, + 0x16, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x7b, 0x6e, + 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x6e, 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, + 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x7b, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, + 0x64, 0x7d, 0x2f, 0x74, 0x61, 0x67, 0x73, 0x12, 0x74, 0x0a, 0x0c, 0x52, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, + 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, + 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, + 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x15, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, + 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x6f, 0x0a, + 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x2e, 0x68, 0x65, + 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, + 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, + 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x7b, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x76, + 0x0a, 0x0a, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x2e, 0x68, + 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, + 0x72, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, + 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, + 0x69, 0x72, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x22, 0x1d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, + 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x7b, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, + 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x0a, 0x52, 0x65, 0x6e, 0x61, 0x6d, + 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, + 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, + 0x22, 0x28, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x7b, + 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2f, + 0x7b, 0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x62, 0x0a, 0x09, 0x4c, 0x69, + 0x73, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, + 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, + 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, + 0x12, 0x0c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x6e, + 0x0a, 0x08, 0x4d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1d, 0x2e, 0x68, 0x65, 0x61, + 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, + 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x68, 0x65, 0x61, 0x64, + 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1d, 0x22, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, + 0x7b, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x12, 0x80, + 0x01, 0x0a, 0x0f, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x49, + 0x50, 0x73, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x50, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, + 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, + 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x50, 0x73, 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, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x69, 0x70, + 0x73, 0x12, 0x64, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1e, + 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, + 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 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, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x7c, 0x0a, 0x0b, 0x45, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, + 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, + 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x22, 0x22, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, + 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x65, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x0c, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, + 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, + 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, + 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x22, 0x21, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, + 0x2f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x7f, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4e, + 0x6f, 0x64, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, + 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, - 0x64, 0x65, 0x2f, 0x7b, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x6e, 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, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, - 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x7b, 0x6e, - 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x74, 0x61, 0x67, 0x73, 0x12, 0x74, 0x0a, 0x0c, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x21, 0x2e, 0x68, - 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x15, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x65, 0x72, 0x12, 0x6f, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, - 0x12, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x7b, 0x6e, 0x6f, 0x64, 0x65, 0x5f, - 0x69, 0x64, 0x7d, 0x12, 0x76, 0x0a, 0x0a, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4e, 0x6f, 0x64, - 0x65, 0x12, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x22, 0x1d, 0x2f, 0x61, - 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x7b, 0x6e, 0x6f, 0x64, 0x65, - 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x0a, - 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x2e, 0x68, 0x65, 0x61, - 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, - 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x65, - 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, - 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x22, 0x28, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, - 0x6f, 0x64, 0x65, 0x2f, 0x7b, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, - 0x6e, 0x61, 0x6d, 0x65, 0x2f, 0x7b, 0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, - 0x62, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x68, + 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x7b, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, + 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x75, 0x0a, 0x0b, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, + 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x65, 0x61, + 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x2a, 0x19, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x7d, + 0x12, 0x70, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, + 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, + 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, + 0x65, 0x79, 0x12, 0x77, 0x0a, 0x0c, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, + 0x65, 0x79, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, + 0x69, 0x6b, 0x65, 0x79, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x12, 0x6a, 0x0a, 0x0b, 0x4c, + 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x20, 0x2e, 0x68, 0x65, 0x61, + 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, + 0x69, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, - 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x14, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x12, 0x0c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, - 0x6f, 0x64, 0x65, 0x12, 0x6e, 0x0a, 0x08, 0x4d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, - 0x1d, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, - 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, - 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, - 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x22, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, - 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x7b, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x75, - 0x73, 0x65, 0x72, 0x12, 0x80, 0x01, 0x0a, 0x0f, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, - 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x50, 0x73, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, - 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x4e, - 0x6f, 0x64, 0x65, 0x49, 0x50, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, - 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x63, - 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x50, 0x73, 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, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x66, - 0x69, 0x6c, 0x6c, 0x69, 0x70, 0x73, 0x12, 0x64, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 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, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x7c, 0x0a, 0x0b, - 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x68, 0x65, - 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, - 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x22, 0x20, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, - 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, - 0x69, 0x64, 0x7d, 0x2f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x0c, 0x44, - 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x21, 0x2e, 0x68, 0x65, - 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, - 0x6c, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, - 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, - 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x22, 0x21, 0x2f, 0x61, 0x70, 0x69, - 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x75, 0x74, - 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x7f, 0x0a, - 0x0d, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x22, - 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, - 0x1d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x7b, 0x6e, - 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x75, - 0x0a, 0x0b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x20, 0x2e, - 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x2a, 0x19, 0x2f, 0x61, 0x70, 0x69, - 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x6f, 0x75, 0x74, - 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x70, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, - 0x70, 0x69, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, - 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, - 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, - 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x12, 0x77, 0x0a, 0x0c, 0x45, 0x78, 0x70, 0x69, 0x72, + 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, 0x12, 0x76, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 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, + 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 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, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, - 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x61, 0x70, 0x69, 0x2f, - 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, - 0x12, 0x6a, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x12, - 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x61, - 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x12, 0x76, 0x0a, 0x0c, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x2e, 0x68, - 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 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, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x2a, 0x17, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x2f, 0x7b, 0x70, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x7d, 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, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x2a, 0x17, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, + 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x2f, 0x7b, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x7d, 0x12, + 0x64, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1e, 0x2e, 0x68, + 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, + 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 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, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x67, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x12, 0x1e, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x1a, 0x0e, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 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{}{ @@ -270,33 +285,37 @@ var file_headscale_v1_headscale_proto_goTypes = []interface{}{ (*ExpireApiKeyRequest)(nil), // 24: headscale.v1.ExpireApiKeyRequest (*ListApiKeysRequest)(nil), // 25: headscale.v1.ListApiKeysRequest (*DeleteApiKeyRequest)(nil), // 26: headscale.v1.DeleteApiKeyRequest - (*GetUserResponse)(nil), // 27: headscale.v1.GetUserResponse - (*CreateUserResponse)(nil), // 28: headscale.v1.CreateUserResponse - (*RenameUserResponse)(nil), // 29: headscale.v1.RenameUserResponse - (*DeleteUserResponse)(nil), // 30: headscale.v1.DeleteUserResponse - (*ListUsersResponse)(nil), // 31: headscale.v1.ListUsersResponse - (*CreatePreAuthKeyResponse)(nil), // 32: headscale.v1.CreatePreAuthKeyResponse - (*ExpirePreAuthKeyResponse)(nil), // 33: headscale.v1.ExpirePreAuthKeyResponse - (*ListPreAuthKeysResponse)(nil), // 34: headscale.v1.ListPreAuthKeysResponse - (*DebugCreateNodeResponse)(nil), // 35: headscale.v1.DebugCreateNodeResponse - (*GetNodeResponse)(nil), // 36: headscale.v1.GetNodeResponse - (*SetTagsResponse)(nil), // 37: headscale.v1.SetTagsResponse - (*RegisterNodeResponse)(nil), // 38: headscale.v1.RegisterNodeResponse - (*DeleteNodeResponse)(nil), // 39: headscale.v1.DeleteNodeResponse - (*ExpireNodeResponse)(nil), // 40: headscale.v1.ExpireNodeResponse - (*RenameNodeResponse)(nil), // 41: headscale.v1.RenameNodeResponse - (*ListNodesResponse)(nil), // 42: headscale.v1.ListNodesResponse - (*MoveNodeResponse)(nil), // 43: headscale.v1.MoveNodeResponse - (*BackfillNodeIPsResponse)(nil), // 44: headscale.v1.BackfillNodeIPsResponse - (*GetRoutesResponse)(nil), // 45: headscale.v1.GetRoutesResponse - (*EnableRouteResponse)(nil), // 46: headscale.v1.EnableRouteResponse - (*DisableRouteResponse)(nil), // 47: headscale.v1.DisableRouteResponse - (*GetNodeRoutesResponse)(nil), // 48: headscale.v1.GetNodeRoutesResponse - (*DeleteRouteResponse)(nil), // 49: headscale.v1.DeleteRouteResponse - (*CreateApiKeyResponse)(nil), // 50: headscale.v1.CreateApiKeyResponse - (*ExpireApiKeyResponse)(nil), // 51: headscale.v1.ExpireApiKeyResponse - (*ListApiKeysResponse)(nil), // 52: headscale.v1.ListApiKeysResponse - (*DeleteApiKeyResponse)(nil), // 53: headscale.v1.DeleteApiKeyResponse + (*GetPolicyRequest)(nil), // 27: headscale.v1.GetPolicyRequest + (*SetPolicyRequest)(nil), // 28: headscale.v1.SetPolicyRequest + (*GetUserResponse)(nil), // 29: headscale.v1.GetUserResponse + (*CreateUserResponse)(nil), // 30: headscale.v1.CreateUserResponse + (*RenameUserResponse)(nil), // 31: headscale.v1.RenameUserResponse + (*DeleteUserResponse)(nil), // 32: headscale.v1.DeleteUserResponse + (*ListUsersResponse)(nil), // 33: headscale.v1.ListUsersResponse + (*CreatePreAuthKeyResponse)(nil), // 34: headscale.v1.CreatePreAuthKeyResponse + (*ExpirePreAuthKeyResponse)(nil), // 35: headscale.v1.ExpirePreAuthKeyResponse + (*ListPreAuthKeysResponse)(nil), // 36: headscale.v1.ListPreAuthKeysResponse + (*DebugCreateNodeResponse)(nil), // 37: headscale.v1.DebugCreateNodeResponse + (*GetNodeResponse)(nil), // 38: headscale.v1.GetNodeResponse + (*SetTagsResponse)(nil), // 39: headscale.v1.SetTagsResponse + (*RegisterNodeResponse)(nil), // 40: headscale.v1.RegisterNodeResponse + (*DeleteNodeResponse)(nil), // 41: headscale.v1.DeleteNodeResponse + (*ExpireNodeResponse)(nil), // 42: headscale.v1.ExpireNodeResponse + (*RenameNodeResponse)(nil), // 43: headscale.v1.RenameNodeResponse + (*ListNodesResponse)(nil), // 44: headscale.v1.ListNodesResponse + (*MoveNodeResponse)(nil), // 45: headscale.v1.MoveNodeResponse + (*BackfillNodeIPsResponse)(nil), // 46: headscale.v1.BackfillNodeIPsResponse + (*GetRoutesResponse)(nil), // 47: headscale.v1.GetRoutesResponse + (*EnableRouteResponse)(nil), // 48: headscale.v1.EnableRouteResponse + (*DisableRouteResponse)(nil), // 49: headscale.v1.DisableRouteResponse + (*GetNodeRoutesResponse)(nil), // 50: headscale.v1.GetNodeRoutesResponse + (*DeleteRouteResponse)(nil), // 51: headscale.v1.DeleteRouteResponse + (*CreateApiKeyResponse)(nil), // 52: headscale.v1.CreateApiKeyResponse + (*ExpireApiKeyResponse)(nil), // 53: headscale.v1.ExpireApiKeyResponse + (*ListApiKeysResponse)(nil), // 54: headscale.v1.ListApiKeysResponse + (*DeleteApiKeyResponse)(nil), // 55: headscale.v1.DeleteApiKeyResponse + (*GetPolicyResponse)(nil), // 56: headscale.v1.GetPolicyResponse + (*SetPolicyResponse)(nil), // 57: headscale.v1.SetPolicyResponse } var file_headscale_v1_headscale_proto_depIdxs = []int32{ 0, // 0: headscale.v1.HeadscaleService.GetUser:input_type -> headscale.v1.GetUserRequest @@ -326,35 +345,39 @@ var file_headscale_v1_headscale_proto_depIdxs = []int32{ 24, // 24: headscale.v1.HeadscaleService.ExpireApiKey:input_type -> headscale.v1.ExpireApiKeyRequest 25, // 25: headscale.v1.HeadscaleService.ListApiKeys:input_type -> headscale.v1.ListApiKeysRequest 26, // 26: headscale.v1.HeadscaleService.DeleteApiKey:input_type -> headscale.v1.DeleteApiKeyRequest - 27, // 27: headscale.v1.HeadscaleService.GetUser:output_type -> headscale.v1.GetUserResponse - 28, // 28: headscale.v1.HeadscaleService.CreateUser:output_type -> headscale.v1.CreateUserResponse - 29, // 29: headscale.v1.HeadscaleService.RenameUser:output_type -> headscale.v1.RenameUserResponse - 30, // 30: headscale.v1.HeadscaleService.DeleteUser:output_type -> headscale.v1.DeleteUserResponse - 31, // 31: headscale.v1.HeadscaleService.ListUsers:output_type -> headscale.v1.ListUsersResponse - 32, // 32: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse - 33, // 33: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse - 34, // 34: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse - 35, // 35: headscale.v1.HeadscaleService.DebugCreateNode:output_type -> headscale.v1.DebugCreateNodeResponse - 36, // 36: headscale.v1.HeadscaleService.GetNode:output_type -> headscale.v1.GetNodeResponse - 37, // 37: headscale.v1.HeadscaleService.SetTags:output_type -> headscale.v1.SetTagsResponse - 38, // 38: headscale.v1.HeadscaleService.RegisterNode:output_type -> headscale.v1.RegisterNodeResponse - 39, // 39: headscale.v1.HeadscaleService.DeleteNode:output_type -> headscale.v1.DeleteNodeResponse - 40, // 40: headscale.v1.HeadscaleService.ExpireNode:output_type -> headscale.v1.ExpireNodeResponse - 41, // 41: headscale.v1.HeadscaleService.RenameNode:output_type -> headscale.v1.RenameNodeResponse - 42, // 42: headscale.v1.HeadscaleService.ListNodes:output_type -> headscale.v1.ListNodesResponse - 43, // 43: headscale.v1.HeadscaleService.MoveNode:output_type -> headscale.v1.MoveNodeResponse - 44, // 44: headscale.v1.HeadscaleService.BackfillNodeIPs:output_type -> headscale.v1.BackfillNodeIPsResponse - 45, // 45: headscale.v1.HeadscaleService.GetRoutes:output_type -> headscale.v1.GetRoutesResponse - 46, // 46: headscale.v1.HeadscaleService.EnableRoute:output_type -> headscale.v1.EnableRouteResponse - 47, // 47: headscale.v1.HeadscaleService.DisableRoute:output_type -> headscale.v1.DisableRouteResponse - 48, // 48: headscale.v1.HeadscaleService.GetNodeRoutes:output_type -> headscale.v1.GetNodeRoutesResponse - 49, // 49: headscale.v1.HeadscaleService.DeleteRoute:output_type -> headscale.v1.DeleteRouteResponse - 50, // 50: headscale.v1.HeadscaleService.CreateApiKey:output_type -> headscale.v1.CreateApiKeyResponse - 51, // 51: headscale.v1.HeadscaleService.ExpireApiKey:output_type -> headscale.v1.ExpireApiKeyResponse - 52, // 52: headscale.v1.HeadscaleService.ListApiKeys:output_type -> headscale.v1.ListApiKeysResponse - 53, // 53: headscale.v1.HeadscaleService.DeleteApiKey:output_type -> headscale.v1.DeleteApiKeyResponse - 27, // [27:54] is the sub-list for method output_type - 0, // [0:27] is the sub-list for method input_type + 27, // 27: headscale.v1.HeadscaleService.GetPolicy:input_type -> headscale.v1.GetPolicyRequest + 28, // 28: headscale.v1.HeadscaleService.SetPolicy:input_type -> headscale.v1.SetPolicyRequest + 29, // 29: headscale.v1.HeadscaleService.GetUser:output_type -> headscale.v1.GetUserResponse + 30, // 30: headscale.v1.HeadscaleService.CreateUser:output_type -> headscale.v1.CreateUserResponse + 31, // 31: headscale.v1.HeadscaleService.RenameUser:output_type -> headscale.v1.RenameUserResponse + 32, // 32: headscale.v1.HeadscaleService.DeleteUser:output_type -> headscale.v1.DeleteUserResponse + 33, // 33: headscale.v1.HeadscaleService.ListUsers:output_type -> headscale.v1.ListUsersResponse + 34, // 34: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse + 35, // 35: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse + 36, // 36: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse + 37, // 37: headscale.v1.HeadscaleService.DebugCreateNode:output_type -> headscale.v1.DebugCreateNodeResponse + 38, // 38: headscale.v1.HeadscaleService.GetNode:output_type -> headscale.v1.GetNodeResponse + 39, // 39: headscale.v1.HeadscaleService.SetTags:output_type -> headscale.v1.SetTagsResponse + 40, // 40: headscale.v1.HeadscaleService.RegisterNode:output_type -> headscale.v1.RegisterNodeResponse + 41, // 41: headscale.v1.HeadscaleService.DeleteNode:output_type -> headscale.v1.DeleteNodeResponse + 42, // 42: headscale.v1.HeadscaleService.ExpireNode:output_type -> headscale.v1.ExpireNodeResponse + 43, // 43: headscale.v1.HeadscaleService.RenameNode:output_type -> headscale.v1.RenameNodeResponse + 44, // 44: headscale.v1.HeadscaleService.ListNodes:output_type -> headscale.v1.ListNodesResponse + 45, // 45: headscale.v1.HeadscaleService.MoveNode:output_type -> headscale.v1.MoveNodeResponse + 46, // 46: headscale.v1.HeadscaleService.BackfillNodeIPs:output_type -> headscale.v1.BackfillNodeIPsResponse + 47, // 47: headscale.v1.HeadscaleService.GetRoutes:output_type -> headscale.v1.GetRoutesResponse + 48, // 48: headscale.v1.HeadscaleService.EnableRoute:output_type -> headscale.v1.EnableRouteResponse + 49, // 49: headscale.v1.HeadscaleService.DisableRoute:output_type -> headscale.v1.DisableRouteResponse + 50, // 50: headscale.v1.HeadscaleService.GetNodeRoutes:output_type -> headscale.v1.GetNodeRoutesResponse + 51, // 51: headscale.v1.HeadscaleService.DeleteRoute:output_type -> headscale.v1.DeleteRouteResponse + 52, // 52: headscale.v1.HeadscaleService.CreateApiKey:output_type -> headscale.v1.CreateApiKeyResponse + 53, // 53: headscale.v1.HeadscaleService.ExpireApiKey:output_type -> headscale.v1.ExpireApiKeyResponse + 54, // 54: headscale.v1.HeadscaleService.ListApiKeys:output_type -> headscale.v1.ListApiKeysResponse + 55, // 55: headscale.v1.HeadscaleService.DeleteApiKey:output_type -> headscale.v1.DeleteApiKeyResponse + 56, // 56: headscale.v1.HeadscaleService.GetPolicy:output_type -> headscale.v1.GetPolicyResponse + 57, // 57: headscale.v1.HeadscaleService.SetPolicy:output_type -> headscale.v1.SetPolicyResponse + 29, // [29:58] is the sub-list for method output_type + 0, // [0:29] 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 @@ -370,6 +393,7 @@ func file_headscale_v1_headscale_proto_init() { file_headscale_v1_node_proto_init() file_headscale_v1_routes_proto_init() file_headscale_v1_apikey_proto_init() + file_headscale_v1_policy_proto_init() type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/gen/go/headscale/v1/headscale.pb.gw.go b/gen/go/headscale/v1/headscale.pb.gw.go index adc7beeb07..98c6039b8d 100644 --- a/gen/go/headscale/v1/headscale.pb.gw.go +++ b/gen/go/headscale/v1/headscale.pb.gw.go @@ -87,7 +87,11 @@ func request_HeadscaleService_CreateUser_0(ctx context.Context, marshaler runtim var protoReq CreateUserRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + 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) } @@ -100,7 +104,11 @@ func local_request_HeadscaleService_CreateUser_0(ctx context.Context, marshaler var protoReq CreateUserRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + 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) } @@ -255,7 +263,11 @@ func request_HeadscaleService_CreatePreAuthKey_0(ctx context.Context, marshaler var protoReq CreatePreAuthKeyRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + 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) } @@ -268,7 +280,11 @@ func local_request_HeadscaleService_CreatePreAuthKey_0(ctx context.Context, mars var protoReq CreatePreAuthKeyRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + 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) } @@ -281,7 +297,11 @@ func request_HeadscaleService_ExpirePreAuthKey_0(ctx context.Context, marshaler var protoReq ExpirePreAuthKeyRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + 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) } @@ -294,7 +314,11 @@ func local_request_HeadscaleService_ExpirePreAuthKey_0(ctx context.Context, mars var protoReq ExpirePreAuthKeyRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + 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) } @@ -343,7 +367,11 @@ func request_HeadscaleService_DebugCreateNode_0(ctx context.Context, marshaler r var protoReq DebugCreateNodeRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + 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) } @@ -356,7 +384,11 @@ func local_request_HeadscaleService_DebugCreateNode_0(ctx context.Context, marsh var protoReq DebugCreateNodeRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + 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) } @@ -421,7 +453,11 @@ func request_HeadscaleService_SetTags_0(ctx context.Context, marshaler runtime.M var protoReq SetTagsRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + 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) } @@ -451,7 +487,11 @@ func local_request_HeadscaleService_SetTags_0(ctx context.Context, marshaler run var protoReq SetTagsRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + 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) } @@ -1061,7 +1101,11 @@ func request_HeadscaleService_CreateApiKey_0(ctx context.Context, marshaler runt var protoReq CreateApiKeyRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + 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) } @@ -1074,7 +1118,11 @@ func local_request_HeadscaleService_CreateApiKey_0(ctx context.Context, marshale var protoReq CreateApiKeyRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + 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) } @@ -1087,7 +1135,11 @@ func request_HeadscaleService_ExpireApiKey_0(ctx context.Context, marshaler runt var protoReq ExpireApiKeyRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + 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) } @@ -1100,7 +1152,11 @@ func local_request_HeadscaleService_ExpireApiKey_0(ctx context.Context, marshale var protoReq ExpireApiKeyRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + 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) } @@ -1179,6 +1235,58 @@ func local_request_HeadscaleService_DeleteApiKey_0(ctx context.Context, marshale } +func request_HeadscaleService_GetPolicy_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetPolicyRequest + var metadata runtime.ServerMetadata + + msg, err := client.GetPolicy(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_HeadscaleService_GetPolicy_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetPolicyRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetPolicy(ctx, &protoReq) + return msg, metadata, err + +} + +func request_HeadscaleService_SetPolicy_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SetPolicyRequest + 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) + } + + msg, err := client.SetPolicy(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_HeadscaleService_SetPolicy_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SetPolicyRequest + 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) + } + + msg, err := server.SetPolicy(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterHeadscaleServiceHandlerServer registers the http handlers for service HeadscaleService to "mux". // UnaryRPC :call HeadscaleServiceServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -1860,13 +1968,63 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser }) + mux.Handle("GET", pattern_HeadscaleService_GetPolicy_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/GetPolicy", runtime.WithHTTPPathPattern("/api/v1/policy")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_HeadscaleService_GetPolicy_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_HeadscaleService_GetPolicy_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("PUT", pattern_HeadscaleService_SetPolicy_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/SetPolicy", runtime.WithHTTPPathPattern("/api/v1/policy")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_HeadscaleService_SetPolicy_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_HeadscaleService_SetPolicy_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } // RegisterHeadscaleServiceHandlerFromEndpoint is same as RegisterHeadscaleServiceHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterHeadscaleServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.DialContext(ctx, endpoint, opts...) + conn, err := grpc.Dial(endpoint, opts...) if err != nil { return err } @@ -2495,6 +2653,50 @@ func RegisterHeadscaleServiceHandlerClient(ctx context.Context, mux *runtime.Ser }) + mux.Handle("GET", pattern_HeadscaleService_GetPolicy_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/GetPolicy", runtime.WithHTTPPathPattern("/api/v1/policy")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_HeadscaleService_GetPolicy_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_HeadscaleService_GetPolicy_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("PUT", pattern_HeadscaleService_SetPolicy_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/SetPolicy", runtime.WithHTTPPathPattern("/api/v1/policy")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_HeadscaleService_SetPolicy_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_HeadscaleService_SetPolicy_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -2552,6 +2754,10 @@ var ( pattern_HeadscaleService_ListApiKeys_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "apikey"}, "")) pattern_HeadscaleService_DeleteApiKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "apikey", "prefix"}, "")) + + pattern_HeadscaleService_GetPolicy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "policy"}, "")) + + pattern_HeadscaleService_SetPolicy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "policy"}, "")) ) var ( @@ -2608,4 +2814,8 @@ var ( forward_HeadscaleService_ListApiKeys_0 = runtime.ForwardResponseMessage forward_HeadscaleService_DeleteApiKey_0 = runtime.ForwardResponseMessage + + forward_HeadscaleService_GetPolicy_0 = runtime.ForwardResponseMessage + + forward_HeadscaleService_SetPolicy_0 = runtime.ForwardResponseMessage ) diff --git a/gen/go/headscale/v1/headscale_grpc.pb.go b/gen/go/headscale/v1/headscale_grpc.pb.go index 6557f88090..df9cf197e4 100644 --- a/gen/go/headscale/v1/headscale_grpc.pb.go +++ b/gen/go/headscale/v1/headscale_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 +// - protoc-gen-go-grpc v1.2.0 // - protoc (unknown) // source: headscale/v1/headscale.proto @@ -18,36 +18,6 @@ import ( // Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 -const ( - HeadscaleService_GetUser_FullMethodName = "/headscale.v1.HeadscaleService/GetUser" - HeadscaleService_CreateUser_FullMethodName = "/headscale.v1.HeadscaleService/CreateUser" - HeadscaleService_RenameUser_FullMethodName = "/headscale.v1.HeadscaleService/RenameUser" - HeadscaleService_DeleteUser_FullMethodName = "/headscale.v1.HeadscaleService/DeleteUser" - HeadscaleService_ListUsers_FullMethodName = "/headscale.v1.HeadscaleService/ListUsers" - HeadscaleService_CreatePreAuthKey_FullMethodName = "/headscale.v1.HeadscaleService/CreatePreAuthKey" - HeadscaleService_ExpirePreAuthKey_FullMethodName = "/headscale.v1.HeadscaleService/ExpirePreAuthKey" - HeadscaleService_ListPreAuthKeys_FullMethodName = "/headscale.v1.HeadscaleService/ListPreAuthKeys" - HeadscaleService_DebugCreateNode_FullMethodName = "/headscale.v1.HeadscaleService/DebugCreateNode" - HeadscaleService_GetNode_FullMethodName = "/headscale.v1.HeadscaleService/GetNode" - HeadscaleService_SetTags_FullMethodName = "/headscale.v1.HeadscaleService/SetTags" - HeadscaleService_RegisterNode_FullMethodName = "/headscale.v1.HeadscaleService/RegisterNode" - HeadscaleService_DeleteNode_FullMethodName = "/headscale.v1.HeadscaleService/DeleteNode" - HeadscaleService_ExpireNode_FullMethodName = "/headscale.v1.HeadscaleService/ExpireNode" - HeadscaleService_RenameNode_FullMethodName = "/headscale.v1.HeadscaleService/RenameNode" - HeadscaleService_ListNodes_FullMethodName = "/headscale.v1.HeadscaleService/ListNodes" - HeadscaleService_MoveNode_FullMethodName = "/headscale.v1.HeadscaleService/MoveNode" - HeadscaleService_BackfillNodeIPs_FullMethodName = "/headscale.v1.HeadscaleService/BackfillNodeIPs" - HeadscaleService_GetRoutes_FullMethodName = "/headscale.v1.HeadscaleService/GetRoutes" - HeadscaleService_EnableRoute_FullMethodName = "/headscale.v1.HeadscaleService/EnableRoute" - HeadscaleService_DisableRoute_FullMethodName = "/headscale.v1.HeadscaleService/DisableRoute" - HeadscaleService_GetNodeRoutes_FullMethodName = "/headscale.v1.HeadscaleService/GetNodeRoutes" - HeadscaleService_DeleteRoute_FullMethodName = "/headscale.v1.HeadscaleService/DeleteRoute" - HeadscaleService_CreateApiKey_FullMethodName = "/headscale.v1.HeadscaleService/CreateApiKey" - HeadscaleService_ExpireApiKey_FullMethodName = "/headscale.v1.HeadscaleService/ExpireApiKey" - HeadscaleService_ListApiKeys_FullMethodName = "/headscale.v1.HeadscaleService/ListApiKeys" - HeadscaleService_DeleteApiKey_FullMethodName = "/headscale.v1.HeadscaleService/DeleteApiKey" -) - // HeadscaleServiceClient is the client API for HeadscaleService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. @@ -84,6 +54,9 @@ type HeadscaleServiceClient interface { ExpireApiKey(ctx context.Context, in *ExpireApiKeyRequest, opts ...grpc.CallOption) (*ExpireApiKeyResponse, error) ListApiKeys(ctx context.Context, in *ListApiKeysRequest, opts ...grpc.CallOption) (*ListApiKeysResponse, error) DeleteApiKey(ctx context.Context, in *DeleteApiKeyRequest, opts ...grpc.CallOption) (*DeleteApiKeyResponse, error) + // --- Policy start --- + GetPolicy(ctx context.Context, in *GetPolicyRequest, opts ...grpc.CallOption) (*GetPolicyResponse, error) + SetPolicy(ctx context.Context, in *SetPolicyRequest, opts ...grpc.CallOption) (*SetPolicyResponse, error) } type headscaleServiceClient struct { @@ -96,7 +69,7 @@ func NewHeadscaleServiceClient(cc grpc.ClientConnInterface) HeadscaleServiceClie func (c *headscaleServiceClient) GetUser(ctx context.Context, in *GetUserRequest, opts ...grpc.CallOption) (*GetUserResponse, error) { out := new(GetUserResponse) - err := c.cc.Invoke(ctx, HeadscaleService_GetUser_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/GetUser", in, out, opts...) if err != nil { return nil, err } @@ -105,7 +78,7 @@ func (c *headscaleServiceClient) GetUser(ctx context.Context, in *GetUserRequest func (c *headscaleServiceClient) CreateUser(ctx context.Context, in *CreateUserRequest, opts ...grpc.CallOption) (*CreateUserResponse, error) { out := new(CreateUserResponse) - err := c.cc.Invoke(ctx, HeadscaleService_CreateUser_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/CreateUser", in, out, opts...) if err != nil { return nil, err } @@ -114,7 +87,7 @@ func (c *headscaleServiceClient) CreateUser(ctx context.Context, in *CreateUserR func (c *headscaleServiceClient) RenameUser(ctx context.Context, in *RenameUserRequest, opts ...grpc.CallOption) (*RenameUserResponse, error) { out := new(RenameUserResponse) - err := c.cc.Invoke(ctx, HeadscaleService_RenameUser_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/RenameUser", in, out, opts...) if err != nil { return nil, err } @@ -123,7 +96,7 @@ func (c *headscaleServiceClient) RenameUser(ctx context.Context, in *RenameUserR func (c *headscaleServiceClient) DeleteUser(ctx context.Context, in *DeleteUserRequest, opts ...grpc.CallOption) (*DeleteUserResponse, error) { out := new(DeleteUserResponse) - err := c.cc.Invoke(ctx, HeadscaleService_DeleteUser_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/DeleteUser", in, out, opts...) if err != nil { return nil, err } @@ -132,7 +105,7 @@ func (c *headscaleServiceClient) DeleteUser(ctx context.Context, in *DeleteUserR func (c *headscaleServiceClient) ListUsers(ctx context.Context, in *ListUsersRequest, opts ...grpc.CallOption) (*ListUsersResponse, error) { out := new(ListUsersResponse) - err := c.cc.Invoke(ctx, HeadscaleService_ListUsers_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ListUsers", in, out, opts...) if err != nil { return nil, err } @@ -141,7 +114,7 @@ func (c *headscaleServiceClient) ListUsers(ctx context.Context, in *ListUsersReq func (c *headscaleServiceClient) CreatePreAuthKey(ctx context.Context, in *CreatePreAuthKeyRequest, opts ...grpc.CallOption) (*CreatePreAuthKeyResponse, error) { out := new(CreatePreAuthKeyResponse) - err := c.cc.Invoke(ctx, HeadscaleService_CreatePreAuthKey_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/CreatePreAuthKey", in, out, opts...) if err != nil { return nil, err } @@ -150,7 +123,7 @@ func (c *headscaleServiceClient) CreatePreAuthKey(ctx context.Context, in *Creat func (c *headscaleServiceClient) ExpirePreAuthKey(ctx context.Context, in *ExpirePreAuthKeyRequest, opts ...grpc.CallOption) (*ExpirePreAuthKeyResponse, error) { out := new(ExpirePreAuthKeyResponse) - err := c.cc.Invoke(ctx, HeadscaleService_ExpirePreAuthKey_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ExpirePreAuthKey", in, out, opts...) if err != nil { return nil, err } @@ -159,7 +132,7 @@ func (c *headscaleServiceClient) ExpirePreAuthKey(ctx context.Context, in *Expir func (c *headscaleServiceClient) ListPreAuthKeys(ctx context.Context, in *ListPreAuthKeysRequest, opts ...grpc.CallOption) (*ListPreAuthKeysResponse, error) { out := new(ListPreAuthKeysResponse) - err := c.cc.Invoke(ctx, HeadscaleService_ListPreAuthKeys_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ListPreAuthKeys", in, out, opts...) if err != nil { return nil, err } @@ -168,7 +141,7 @@ func (c *headscaleServiceClient) ListPreAuthKeys(ctx context.Context, in *ListPr func (c *headscaleServiceClient) DebugCreateNode(ctx context.Context, in *DebugCreateNodeRequest, opts ...grpc.CallOption) (*DebugCreateNodeResponse, error) { out := new(DebugCreateNodeResponse) - err := c.cc.Invoke(ctx, HeadscaleService_DebugCreateNode_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/DebugCreateNode", in, out, opts...) if err != nil { return nil, err } @@ -177,7 +150,7 @@ func (c *headscaleServiceClient) DebugCreateNode(ctx context.Context, in *DebugC func (c *headscaleServiceClient) GetNode(ctx context.Context, in *GetNodeRequest, opts ...grpc.CallOption) (*GetNodeResponse, error) { out := new(GetNodeResponse) - err := c.cc.Invoke(ctx, HeadscaleService_GetNode_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/GetNode", in, out, opts...) if err != nil { return nil, err } @@ -186,7 +159,7 @@ func (c *headscaleServiceClient) GetNode(ctx context.Context, in *GetNodeRequest func (c *headscaleServiceClient) SetTags(ctx context.Context, in *SetTagsRequest, opts ...grpc.CallOption) (*SetTagsResponse, error) { out := new(SetTagsResponse) - err := c.cc.Invoke(ctx, HeadscaleService_SetTags_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/SetTags", in, out, opts...) if err != nil { return nil, err } @@ -195,7 +168,7 @@ func (c *headscaleServiceClient) SetTags(ctx context.Context, in *SetTagsRequest func (c *headscaleServiceClient) RegisterNode(ctx context.Context, in *RegisterNodeRequest, opts ...grpc.CallOption) (*RegisterNodeResponse, error) { out := new(RegisterNodeResponse) - err := c.cc.Invoke(ctx, HeadscaleService_RegisterNode_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/RegisterNode", in, out, opts...) if err != nil { return nil, err } @@ -204,7 +177,7 @@ func (c *headscaleServiceClient) RegisterNode(ctx context.Context, in *RegisterN func (c *headscaleServiceClient) DeleteNode(ctx context.Context, in *DeleteNodeRequest, opts ...grpc.CallOption) (*DeleteNodeResponse, error) { out := new(DeleteNodeResponse) - err := c.cc.Invoke(ctx, HeadscaleService_DeleteNode_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/DeleteNode", in, out, opts...) if err != nil { return nil, err } @@ -213,7 +186,7 @@ func (c *headscaleServiceClient) DeleteNode(ctx context.Context, in *DeleteNodeR func (c *headscaleServiceClient) ExpireNode(ctx context.Context, in *ExpireNodeRequest, opts ...grpc.CallOption) (*ExpireNodeResponse, error) { out := new(ExpireNodeResponse) - err := c.cc.Invoke(ctx, HeadscaleService_ExpireNode_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ExpireNode", in, out, opts...) if err != nil { return nil, err } @@ -222,7 +195,7 @@ func (c *headscaleServiceClient) ExpireNode(ctx context.Context, in *ExpireNodeR func (c *headscaleServiceClient) RenameNode(ctx context.Context, in *RenameNodeRequest, opts ...grpc.CallOption) (*RenameNodeResponse, error) { out := new(RenameNodeResponse) - err := c.cc.Invoke(ctx, HeadscaleService_RenameNode_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/RenameNode", in, out, opts...) if err != nil { return nil, err } @@ -231,7 +204,7 @@ func (c *headscaleServiceClient) RenameNode(ctx context.Context, in *RenameNodeR func (c *headscaleServiceClient) ListNodes(ctx context.Context, in *ListNodesRequest, opts ...grpc.CallOption) (*ListNodesResponse, error) { out := new(ListNodesResponse) - err := c.cc.Invoke(ctx, HeadscaleService_ListNodes_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ListNodes", in, out, opts...) if err != nil { return nil, err } @@ -240,7 +213,7 @@ func (c *headscaleServiceClient) ListNodes(ctx context.Context, in *ListNodesReq func (c *headscaleServiceClient) MoveNode(ctx context.Context, in *MoveNodeRequest, opts ...grpc.CallOption) (*MoveNodeResponse, error) { out := new(MoveNodeResponse) - err := c.cc.Invoke(ctx, HeadscaleService_MoveNode_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/MoveNode", in, out, opts...) if err != nil { return nil, err } @@ -249,7 +222,7 @@ func (c *headscaleServiceClient) MoveNode(ctx context.Context, in *MoveNodeReque func (c *headscaleServiceClient) BackfillNodeIPs(ctx context.Context, in *BackfillNodeIPsRequest, opts ...grpc.CallOption) (*BackfillNodeIPsResponse, error) { out := new(BackfillNodeIPsResponse) - err := c.cc.Invoke(ctx, HeadscaleService_BackfillNodeIPs_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/BackfillNodeIPs", in, out, opts...) if err != nil { return nil, err } @@ -258,7 +231,7 @@ func (c *headscaleServiceClient) BackfillNodeIPs(ctx context.Context, in *Backfi func (c *headscaleServiceClient) GetRoutes(ctx context.Context, in *GetRoutesRequest, opts ...grpc.CallOption) (*GetRoutesResponse, error) { out := new(GetRoutesResponse) - err := c.cc.Invoke(ctx, HeadscaleService_GetRoutes_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/GetRoutes", in, out, opts...) if err != nil { return nil, err } @@ -267,7 +240,7 @@ func (c *headscaleServiceClient) GetRoutes(ctx context.Context, in *GetRoutesReq func (c *headscaleServiceClient) EnableRoute(ctx context.Context, in *EnableRouteRequest, opts ...grpc.CallOption) (*EnableRouteResponse, error) { out := new(EnableRouteResponse) - err := c.cc.Invoke(ctx, HeadscaleService_EnableRoute_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/EnableRoute", in, out, opts...) if err != nil { return nil, err } @@ -276,7 +249,7 @@ func (c *headscaleServiceClient) EnableRoute(ctx context.Context, in *EnableRout func (c *headscaleServiceClient) DisableRoute(ctx context.Context, in *DisableRouteRequest, opts ...grpc.CallOption) (*DisableRouteResponse, error) { out := new(DisableRouteResponse) - err := c.cc.Invoke(ctx, HeadscaleService_DisableRoute_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/DisableRoute", in, out, opts...) if err != nil { return nil, err } @@ -285,7 +258,7 @@ func (c *headscaleServiceClient) DisableRoute(ctx context.Context, in *DisableRo func (c *headscaleServiceClient) GetNodeRoutes(ctx context.Context, in *GetNodeRoutesRequest, opts ...grpc.CallOption) (*GetNodeRoutesResponse, error) { out := new(GetNodeRoutesResponse) - err := c.cc.Invoke(ctx, HeadscaleService_GetNodeRoutes_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/GetNodeRoutes", in, out, opts...) if err != nil { return nil, err } @@ -294,7 +267,7 @@ func (c *headscaleServiceClient) GetNodeRoutes(ctx context.Context, in *GetNodeR func (c *headscaleServiceClient) DeleteRoute(ctx context.Context, in *DeleteRouteRequest, opts ...grpc.CallOption) (*DeleteRouteResponse, error) { out := new(DeleteRouteResponse) - err := c.cc.Invoke(ctx, HeadscaleService_DeleteRoute_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/DeleteRoute", in, out, opts...) if err != nil { return nil, err } @@ -303,7 +276,7 @@ func (c *headscaleServiceClient) DeleteRoute(ctx context.Context, in *DeleteRout func (c *headscaleServiceClient) CreateApiKey(ctx context.Context, in *CreateApiKeyRequest, opts ...grpc.CallOption) (*CreateApiKeyResponse, error) { out := new(CreateApiKeyResponse) - err := c.cc.Invoke(ctx, HeadscaleService_CreateApiKey_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/CreateApiKey", in, out, opts...) if err != nil { return nil, err } @@ -312,7 +285,7 @@ func (c *headscaleServiceClient) CreateApiKey(ctx context.Context, in *CreateApi func (c *headscaleServiceClient) ExpireApiKey(ctx context.Context, in *ExpireApiKeyRequest, opts ...grpc.CallOption) (*ExpireApiKeyResponse, error) { out := new(ExpireApiKeyResponse) - err := c.cc.Invoke(ctx, HeadscaleService_ExpireApiKey_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ExpireApiKey", in, out, opts...) if err != nil { return nil, err } @@ -321,7 +294,7 @@ func (c *headscaleServiceClient) ExpireApiKey(ctx context.Context, in *ExpireApi func (c *headscaleServiceClient) ListApiKeys(ctx context.Context, in *ListApiKeysRequest, opts ...grpc.CallOption) (*ListApiKeysResponse, error) { out := new(ListApiKeysResponse) - err := c.cc.Invoke(ctx, HeadscaleService_ListApiKeys_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ListApiKeys", in, out, opts...) if err != nil { return nil, err } @@ -330,7 +303,25 @@ func (c *headscaleServiceClient) ListApiKeys(ctx context.Context, in *ListApiKey func (c *headscaleServiceClient) DeleteApiKey(ctx context.Context, in *DeleteApiKeyRequest, opts ...grpc.CallOption) (*DeleteApiKeyResponse, error) { out := new(DeleteApiKeyResponse) - err := c.cc.Invoke(ctx, HeadscaleService_DeleteApiKey_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/DeleteApiKey", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *headscaleServiceClient) GetPolicy(ctx context.Context, in *GetPolicyRequest, opts ...grpc.CallOption) (*GetPolicyResponse, error) { + out := new(GetPolicyResponse) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/GetPolicy", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *headscaleServiceClient) SetPolicy(ctx context.Context, in *SetPolicyRequest, opts ...grpc.CallOption) (*SetPolicyResponse, error) { + out := new(SetPolicyResponse) + err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/SetPolicy", in, out, opts...) if err != nil { return nil, err } @@ -373,6 +364,9 @@ type HeadscaleServiceServer interface { ExpireApiKey(context.Context, *ExpireApiKeyRequest) (*ExpireApiKeyResponse, error) ListApiKeys(context.Context, *ListApiKeysRequest) (*ListApiKeysResponse, error) DeleteApiKey(context.Context, *DeleteApiKeyRequest) (*DeleteApiKeyResponse, error) + // --- Policy start --- + GetPolicy(context.Context, *GetPolicyRequest) (*GetPolicyResponse, error) + SetPolicy(context.Context, *SetPolicyRequest) (*SetPolicyResponse, error) mustEmbedUnimplementedHeadscaleServiceServer() } @@ -461,6 +455,12 @@ func (UnimplementedHeadscaleServiceServer) ListApiKeys(context.Context, *ListApi func (UnimplementedHeadscaleServiceServer) DeleteApiKey(context.Context, *DeleteApiKeyRequest) (*DeleteApiKeyResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteApiKey not implemented") } +func (UnimplementedHeadscaleServiceServer) GetPolicy(context.Context, *GetPolicyRequest) (*GetPolicyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetPolicy not implemented") +} +func (UnimplementedHeadscaleServiceServer) SetPolicy(context.Context, *SetPolicyRequest) (*SetPolicyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetPolicy not implemented") +} func (UnimplementedHeadscaleServiceServer) mustEmbedUnimplementedHeadscaleServiceServer() {} // UnsafeHeadscaleServiceServer may be embedded to opt out of forward compatibility for this service. @@ -484,7 +484,7 @@ func _HeadscaleService_GetUser_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_GetUser_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/GetUser", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).GetUser(ctx, req.(*GetUserRequest)) @@ -502,7 +502,7 @@ func _HeadscaleService_CreateUser_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_CreateUser_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/CreateUser", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).CreateUser(ctx, req.(*CreateUserRequest)) @@ -520,7 +520,7 @@ func _HeadscaleService_RenameUser_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_RenameUser_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/RenameUser", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).RenameUser(ctx, req.(*RenameUserRequest)) @@ -538,7 +538,7 @@ func _HeadscaleService_DeleteUser_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_DeleteUser_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/DeleteUser", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).DeleteUser(ctx, req.(*DeleteUserRequest)) @@ -556,7 +556,7 @@ func _HeadscaleService_ListUsers_Handler(srv interface{}, ctx context.Context, d } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_ListUsers_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/ListUsers", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).ListUsers(ctx, req.(*ListUsersRequest)) @@ -574,7 +574,7 @@ func _HeadscaleService_CreatePreAuthKey_Handler(srv interface{}, ctx context.Con } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_CreatePreAuthKey_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/CreatePreAuthKey", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).CreatePreAuthKey(ctx, req.(*CreatePreAuthKeyRequest)) @@ -592,7 +592,7 @@ func _HeadscaleService_ExpirePreAuthKey_Handler(srv interface{}, ctx context.Con } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_ExpirePreAuthKey_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/ExpirePreAuthKey", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).ExpirePreAuthKey(ctx, req.(*ExpirePreAuthKeyRequest)) @@ -610,7 +610,7 @@ func _HeadscaleService_ListPreAuthKeys_Handler(srv interface{}, ctx context.Cont } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_ListPreAuthKeys_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/ListPreAuthKeys", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).ListPreAuthKeys(ctx, req.(*ListPreAuthKeysRequest)) @@ -628,7 +628,7 @@ func _HeadscaleService_DebugCreateNode_Handler(srv interface{}, ctx context.Cont } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_DebugCreateNode_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/DebugCreateNode", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).DebugCreateNode(ctx, req.(*DebugCreateNodeRequest)) @@ -646,7 +646,7 @@ func _HeadscaleService_GetNode_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_GetNode_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/GetNode", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).GetNode(ctx, req.(*GetNodeRequest)) @@ -664,7 +664,7 @@ func _HeadscaleService_SetTags_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_SetTags_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/SetTags", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).SetTags(ctx, req.(*SetTagsRequest)) @@ -682,7 +682,7 @@ func _HeadscaleService_RegisterNode_Handler(srv interface{}, ctx context.Context } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_RegisterNode_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/RegisterNode", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).RegisterNode(ctx, req.(*RegisterNodeRequest)) @@ -700,7 +700,7 @@ func _HeadscaleService_DeleteNode_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_DeleteNode_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/DeleteNode", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).DeleteNode(ctx, req.(*DeleteNodeRequest)) @@ -718,7 +718,7 @@ func _HeadscaleService_ExpireNode_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_ExpireNode_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/ExpireNode", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).ExpireNode(ctx, req.(*ExpireNodeRequest)) @@ -736,7 +736,7 @@ func _HeadscaleService_RenameNode_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_RenameNode_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/RenameNode", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).RenameNode(ctx, req.(*RenameNodeRequest)) @@ -754,7 +754,7 @@ func _HeadscaleService_ListNodes_Handler(srv interface{}, ctx context.Context, d } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_ListNodes_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/ListNodes", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).ListNodes(ctx, req.(*ListNodesRequest)) @@ -772,7 +772,7 @@ func _HeadscaleService_MoveNode_Handler(srv interface{}, ctx context.Context, de } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_MoveNode_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/MoveNode", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).MoveNode(ctx, req.(*MoveNodeRequest)) @@ -790,7 +790,7 @@ func _HeadscaleService_BackfillNodeIPs_Handler(srv interface{}, ctx context.Cont } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_BackfillNodeIPs_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/BackfillNodeIPs", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).BackfillNodeIPs(ctx, req.(*BackfillNodeIPsRequest)) @@ -808,7 +808,7 @@ func _HeadscaleService_GetRoutes_Handler(srv interface{}, ctx context.Context, d } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_GetRoutes_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/GetRoutes", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).GetRoutes(ctx, req.(*GetRoutesRequest)) @@ -826,7 +826,7 @@ func _HeadscaleService_EnableRoute_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_EnableRoute_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/EnableRoute", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).EnableRoute(ctx, req.(*EnableRouteRequest)) @@ -844,7 +844,7 @@ func _HeadscaleService_DisableRoute_Handler(srv interface{}, ctx context.Context } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_DisableRoute_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/DisableRoute", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).DisableRoute(ctx, req.(*DisableRouteRequest)) @@ -862,7 +862,7 @@ func _HeadscaleService_GetNodeRoutes_Handler(srv interface{}, ctx context.Contex } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_GetNodeRoutes_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/GetNodeRoutes", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).GetNodeRoutes(ctx, req.(*GetNodeRoutesRequest)) @@ -880,7 +880,7 @@ func _HeadscaleService_DeleteRoute_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_DeleteRoute_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/DeleteRoute", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).DeleteRoute(ctx, req.(*DeleteRouteRequest)) @@ -898,7 +898,7 @@ func _HeadscaleService_CreateApiKey_Handler(srv interface{}, ctx context.Context } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_CreateApiKey_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/CreateApiKey", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).CreateApiKey(ctx, req.(*CreateApiKeyRequest)) @@ -916,7 +916,7 @@ func _HeadscaleService_ExpireApiKey_Handler(srv interface{}, ctx context.Context } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_ExpireApiKey_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/ExpireApiKey", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).ExpireApiKey(ctx, req.(*ExpireApiKeyRequest)) @@ -934,7 +934,7 @@ func _HeadscaleService_ListApiKeys_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_ListApiKeys_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/ListApiKeys", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).ListApiKeys(ctx, req.(*ListApiKeysRequest)) @@ -952,7 +952,7 @@ func _HeadscaleService_DeleteApiKey_Handler(srv interface{}, ctx context.Context } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: HeadscaleService_DeleteApiKey_FullMethodName, + FullMethod: "/headscale.v1.HeadscaleService/DeleteApiKey", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HeadscaleServiceServer).DeleteApiKey(ctx, req.(*DeleteApiKeyRequest)) @@ -960,6 +960,42 @@ func _HeadscaleService_DeleteApiKey_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } +func _HeadscaleService_GetPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetPolicyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(HeadscaleServiceServer).GetPolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/headscale.v1.HeadscaleService/GetPolicy", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HeadscaleServiceServer).GetPolicy(ctx, req.(*GetPolicyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _HeadscaleService_SetPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetPolicyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(HeadscaleServiceServer).SetPolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/headscale.v1.HeadscaleService/SetPolicy", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HeadscaleServiceServer).SetPolicy(ctx, req.(*SetPolicyRequest)) + } + return interceptor(ctx, in, info, handler) +} + // HeadscaleService_ServiceDesc is the grpc.ServiceDesc for HeadscaleService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -1075,6 +1111,14 @@ var HeadscaleService_ServiceDesc = grpc.ServiceDesc{ MethodName: "DeleteApiKey", Handler: _HeadscaleService_DeleteApiKey_Handler, }, + { + MethodName: "GetPolicy", + Handler: _HeadscaleService_GetPolicy_Handler, + }, + { + MethodName: "SetPolicy", + Handler: _HeadscaleService_SetPolicy_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "headscale/v1/headscale.proto", diff --git a/gen/go/headscale/v1/node.pb.go b/gen/go/headscale/v1/node.pb.go index 93d2c6b0a8..b961ca7317 100644 --- a/gen/go/headscale/v1/node.pb.go +++ b/gen/go/headscale/v1/node.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.32.0 // protoc (unknown) // source: headscale/v1/node.proto diff --git a/gen/go/headscale/v1/policy.pb.go b/gen/go/headscale/v1/policy.pb.go new file mode 100644 index 0000000000..31ecffdfe8 --- /dev/null +++ b/gen/go/headscale/v1/policy.pb.go @@ -0,0 +1,352 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc (unknown) +// source: headscale/v1/policy.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type SetPolicyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Policy string `protobuf:"bytes,1,opt,name=policy,proto3" json:"policy,omitempty"` +} + +func (x *SetPolicyRequest) Reset() { + *x = SetPolicyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_headscale_v1_policy_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetPolicyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetPolicyRequest) ProtoMessage() {} + +func (x *SetPolicyRequest) ProtoReflect() protoreflect.Message { + mi := &file_headscale_v1_policy_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetPolicyRequest.ProtoReflect.Descriptor instead. +func (*SetPolicyRequest) Descriptor() ([]byte, []int) { + return file_headscale_v1_policy_proto_rawDescGZIP(), []int{0} +} + +func (x *SetPolicyRequest) GetPolicy() string { + if x != nil { + return x.Policy + } + return "" +} + +type SetPolicyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Policy string `protobuf:"bytes,1,opt,name=policy,proto3" json:"policy,omitempty"` + UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` +} + +func (x *SetPolicyResponse) Reset() { + *x = SetPolicyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_headscale_v1_policy_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetPolicyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetPolicyResponse) ProtoMessage() {} + +func (x *SetPolicyResponse) ProtoReflect() protoreflect.Message { + mi := &file_headscale_v1_policy_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetPolicyResponse.ProtoReflect.Descriptor instead. +func (*SetPolicyResponse) Descriptor() ([]byte, []int) { + return file_headscale_v1_policy_proto_rawDescGZIP(), []int{1} +} + +func (x *SetPolicyResponse) GetPolicy() string { + if x != nil { + return x.Policy + } + return "" +} + +func (x *SetPolicyResponse) GetUpdatedAt() *timestamppb.Timestamp { + if x != nil { + return x.UpdatedAt + } + return nil +} + +type GetPolicyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetPolicyRequest) Reset() { + *x = GetPolicyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_headscale_v1_policy_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetPolicyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPolicyRequest) ProtoMessage() {} + +func (x *GetPolicyRequest) ProtoReflect() protoreflect.Message { + mi := &file_headscale_v1_policy_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPolicyRequest.ProtoReflect.Descriptor instead. +func (*GetPolicyRequest) Descriptor() ([]byte, []int) { + return file_headscale_v1_policy_proto_rawDescGZIP(), []int{2} +} + +type GetPolicyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Policy string `protobuf:"bytes,1,opt,name=policy,proto3" json:"policy,omitempty"` + UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` +} + +func (x *GetPolicyResponse) Reset() { + *x = GetPolicyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_headscale_v1_policy_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetPolicyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPolicyResponse) ProtoMessage() {} + +func (x *GetPolicyResponse) ProtoReflect() protoreflect.Message { + mi := &file_headscale_v1_policy_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPolicyResponse.ProtoReflect.Descriptor instead. +func (*GetPolicyResponse) Descriptor() ([]byte, []int) { + return file_headscale_v1_policy_proto_rawDescGZIP(), []int{3} +} + +func (x *GetPolicyResponse) GetPolicy() string { + if x != nil { + return x.Policy + } + return "" +} + +func (x *GetPolicyResponse) GetUpdatedAt() *timestamppb.Timestamp { + if x != nil { + return x.UpdatedAt + } + return nil +} + +var File_headscale_v1_policy_proto protoreflect.FileDescriptor + +var file_headscale_v1_policy_proto_rawDesc = []byte{ + 0x0a, 0x19, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x68, 0x65, 0x61, + 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x2a, 0x0a, 0x10, 0x53, 0x65, + 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x66, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x12, + 0x0a, 0x10, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x66, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, + 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 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_policy_proto_rawDescOnce sync.Once + file_headscale_v1_policy_proto_rawDescData = file_headscale_v1_policy_proto_rawDesc +) + +func file_headscale_v1_policy_proto_rawDescGZIP() []byte { + file_headscale_v1_policy_proto_rawDescOnce.Do(func() { + file_headscale_v1_policy_proto_rawDescData = protoimpl.X.CompressGZIP(file_headscale_v1_policy_proto_rawDescData) + }) + return file_headscale_v1_policy_proto_rawDescData +} + +var file_headscale_v1_policy_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_headscale_v1_policy_proto_goTypes = []interface{}{ + (*SetPolicyRequest)(nil), // 0: headscale.v1.SetPolicyRequest + (*SetPolicyResponse)(nil), // 1: headscale.v1.SetPolicyResponse + (*GetPolicyRequest)(nil), // 2: headscale.v1.GetPolicyRequest + (*GetPolicyResponse)(nil), // 3: headscale.v1.GetPolicyResponse + (*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp +} +var file_headscale_v1_policy_proto_depIdxs = []int32{ + 4, // 0: headscale.v1.SetPolicyResponse.updated_at:type_name -> google.protobuf.Timestamp + 4, // 1: headscale.v1.GetPolicyResponse.updated_at:type_name -> google.protobuf.Timestamp + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_headscale_v1_policy_proto_init() } +func file_headscale_v1_policy_proto_init() { + if File_headscale_v1_policy_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_headscale_v1_policy_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetPolicyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_headscale_v1_policy_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetPolicyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_headscale_v1_policy_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetPolicyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_headscale_v1_policy_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetPolicyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_headscale_v1_policy_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_headscale_v1_policy_proto_goTypes, + DependencyIndexes: file_headscale_v1_policy_proto_depIdxs, + MessageInfos: file_headscale_v1_policy_proto_msgTypes, + }.Build() + File_headscale_v1_policy_proto = out.File + file_headscale_v1_policy_proto_rawDesc = nil + file_headscale_v1_policy_proto_goTypes = nil + file_headscale_v1_policy_proto_depIdxs = nil +} diff --git a/gen/go/headscale/v1/preauthkey.pb.go b/gen/go/headscale/v1/preauthkey.pb.go index c3ae281840..35a0dfe08f 100644 --- a/gen/go/headscale/v1/preauthkey.pb.go +++ b/gen/go/headscale/v1/preauthkey.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.32.0 // protoc (unknown) // source: headscale/v1/preauthkey.proto diff --git a/gen/go/headscale/v1/routes.pb.go b/gen/go/headscale/v1/routes.pb.go index 9c7475b46f..d2273047fe 100644 --- a/gen/go/headscale/v1/routes.pb.go +++ b/gen/go/headscale/v1/routes.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.32.0 // protoc (unknown) // source: headscale/v1/routes.proto diff --git a/gen/go/headscale/v1/user.pb.go b/gen/go/headscale/v1/user.pb.go index 3fcd12bf43..17cb4b548d 100644 --- a/gen/go/headscale/v1/user.pb.go +++ b/gen/go/headscale/v1/user.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.32.0 // protoc (unknown) // source: headscale/v1/user.proto diff --git a/gen/openapiv2/headscale/v1/apikey.swagger.json b/gen/openapiv2/headscale/v1/apikey.swagger.json index 8c8596a950..0d4ebbe90c 100644 --- a/gen/openapiv2/headscale/v1/apikey.swagger.json +++ b/gen/openapiv2/headscale/v1/apikey.swagger.json @@ -34,7 +34,6 @@ "details": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/protobufAny" } } diff --git a/gen/openapiv2/headscale/v1/device.swagger.json b/gen/openapiv2/headscale/v1/device.swagger.json index 99d20debf6..5360527a30 100644 --- a/gen/openapiv2/headscale/v1/device.swagger.json +++ b/gen/openapiv2/headscale/v1/device.swagger.json @@ -34,7 +34,6 @@ "details": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/protobufAny" } } diff --git a/gen/openapiv2/headscale/v1/headscale.swagger.json b/gen/openapiv2/headscale/v1/headscale.swagger.json index 51b4ad2288..9c1cf0e923 100644 --- a/gen/openapiv2/headscale/v1/headscale.swagger.json +++ b/gen/openapiv2/headscale/v1/headscale.swagger.json @@ -449,7 +449,15 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/HeadscaleServiceSetTagsBody" + "type": "object", + "properties": { + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + } } } ], @@ -495,6 +503,59 @@ ] } }, + "/api/v1/policy": { + "get": { + "summary": "--- Policy start ---", + "operationId": "HeadscaleService_GetPolicy", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetPolicyResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "tags": [ + "HeadscaleService" + ] + }, + "put": { + "operationId": "HeadscaleService_SetPolicy", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1SetPolicyResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1SetPolicyRequest" + } + } + ], + "tags": [ + "HeadscaleService" + ] + } + }, "/api/v1/preauthkey": { "get": { "operationId": "HeadscaleService_ListPreAuthKeys", @@ -853,17 +914,6 @@ } }, "definitions": { - "HeadscaleServiceSetTagsBody": { - "type": "object", - "properties": { - "tags": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, "protobufAny": { "type": "object", "properties": { @@ -886,7 +936,6 @@ "details": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/protobufAny" } } @@ -1085,19 +1134,29 @@ "routes": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/v1Route" } } } }, + "v1GetPolicyResponse": { + "type": "object", + "properties": { + "policy": { + "type": "string" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, "v1GetRoutesResponse": { "type": "object", "properties": { "routes": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/v1Route" } } @@ -1117,7 +1176,6 @@ "apiKeys": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/v1ApiKey" } } @@ -1129,7 +1187,6 @@ "nodes": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/v1Node" } } @@ -1141,7 +1198,6 @@ "preAuthKeys": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/v1PreAuthKey" } } @@ -1153,7 +1209,6 @@ "users": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/v1User" } } @@ -1346,6 +1401,26 @@ } } }, + "v1SetPolicyRequest": { + "type": "object", + "properties": { + "policy": { + "type": "string" + } + } + }, + "v1SetPolicyResponse": { + "type": "object", + "properties": { + "policy": { + "type": "string" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + }, "v1SetTagsResponse": { "type": "object", "properties": { diff --git a/gen/openapiv2/headscale/v1/node.swagger.json b/gen/openapiv2/headscale/v1/node.swagger.json index 163213470e..8271250ebd 100644 --- a/gen/openapiv2/headscale/v1/node.swagger.json +++ b/gen/openapiv2/headscale/v1/node.swagger.json @@ -34,7 +34,6 @@ "details": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/protobufAny" } } diff --git a/gen/openapiv2/headscale/v1/policy.swagger.json b/gen/openapiv2/headscale/v1/policy.swagger.json new file mode 100644 index 0000000000..63afc57562 --- /dev/null +++ b/gen/openapiv2/headscale/v1/policy.swagger.json @@ -0,0 +1,43 @@ +{ + "swagger": "2.0", + "info": { + "title": "headscale/v1/policy.proto", + "version": "version not set" + }, + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": {}, + "definitions": { + "protobufAny": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": {} + }, + "rpcStatus": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "$ref": "#/definitions/protobufAny" + } + } + } + } + } +} diff --git a/gen/openapiv2/headscale/v1/preauthkey.swagger.json b/gen/openapiv2/headscale/v1/preauthkey.swagger.json index 17a2be1a7e..ef16319c19 100644 --- a/gen/openapiv2/headscale/v1/preauthkey.swagger.json +++ b/gen/openapiv2/headscale/v1/preauthkey.swagger.json @@ -34,7 +34,6 @@ "details": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/protobufAny" } } diff --git a/gen/openapiv2/headscale/v1/routes.swagger.json b/gen/openapiv2/headscale/v1/routes.swagger.json index 11087f2a4e..34eda6763f 100644 --- a/gen/openapiv2/headscale/v1/routes.swagger.json +++ b/gen/openapiv2/headscale/v1/routes.swagger.json @@ -34,7 +34,6 @@ "details": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/protobufAny" } } diff --git a/gen/openapiv2/headscale/v1/user.swagger.json b/gen/openapiv2/headscale/v1/user.swagger.json index 008ca3e853..1355a9cc55 100644 --- a/gen/openapiv2/headscale/v1/user.swagger.json +++ b/gen/openapiv2/headscale/v1/user.swagger.json @@ -34,7 +34,6 @@ "details": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/protobufAny" } } diff --git a/hscontrol/app.go b/hscontrol/app.go index 253c2671b1..726b9d0bd2 100644 --- a/hscontrol/app.go +++ b/hscontrol/app.go @@ -8,7 +8,7 @@ import ( "io" "net" "net/http" - _ "net/http/pprof" //nolint + _ "net/http/pprof" // nolint "os" "os/signal" "path/filepath" @@ -23,16 +23,6 @@ import ( "github.com/gorilla/mux" grpcMiddleware "github.com/grpc-ecosystem/go-grpc-middleware" grpcRuntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "github.com/juanfont/headscale" - v1 "github.com/juanfont/headscale/gen/go/headscale/v1" - "github.com/juanfont/headscale/hscontrol/db" - "github.com/juanfont/headscale/hscontrol/derp" - derpServer "github.com/juanfont/headscale/hscontrol/derp/server" - "github.com/juanfont/headscale/hscontrol/mapper" - "github.com/juanfont/headscale/hscontrol/notifier" - "github.com/juanfont/headscale/hscontrol/policy" - "github.com/juanfont/headscale/hscontrol/types" - "github.com/juanfont/headscale/hscontrol/util" "github.com/patrickmn/go-cache" zerolog "github.com/philip-bui/grpc-zerolog" "github.com/pkg/profile" @@ -57,6 +47,17 @@ import ( "tailscale.com/types/dnstype" "tailscale.com/types/key" "tailscale.com/util/dnsname" + + "github.com/juanfont/headscale" + v1 "github.com/juanfont/headscale/gen/go/headscale/v1" + "github.com/juanfont/headscale/hscontrol/db" + "github.com/juanfont/headscale/hscontrol/derp" + derpServer "github.com/juanfont/headscale/hscontrol/derp/server" + "github.com/juanfont/headscale/hscontrol/mapper" + "github.com/juanfont/headscale/hscontrol/notifier" + "github.com/juanfont/headscale/hscontrol/policy" + "github.com/juanfont/headscale/hscontrol/types" + "github.com/juanfont/headscale/hscontrol/util" ) var ( @@ -516,6 +517,10 @@ func (h *Headscale) Serve() error { var err error + if err = h.loadACLPolicy(); err != nil { + return fmt.Errorf("failed to load ACL policy: %w", err) + } + if dumpConfig { spew.Dump(h.cfg) } @@ -784,17 +789,12 @@ func (h *Headscale) Serve() error { Msg("Received SIGHUP, reloading ACL and Config") // TODO(kradalby): Reload config on SIGHUP + if err := h.loadACLPolicy(); err != nil { + log.Error().Err(err).Msg("failed to reload ACL policy") + } - if h.cfg.ACL.PolicyPath != "" { - aclPath := util.AbsolutePathFromConfigPath(h.cfg.ACL.PolicyPath) - pol, err := policy.LoadACLPolicyFromPath(aclPath) - if err != nil { - log.Error().Err(err).Msg("Failed to reload ACL policy") - } - - h.ACLPolicy = pol + if h.ACLPolicy != nil { log.Info(). - Str("path", aclPath). Msg("ACL policy successfully reloaded, notifying nodes of change") ctx := types.NotifyCtx(context.Background(), "acl-sighup", "na") @@ -802,7 +802,6 @@ func (h *Headscale) Serve() error { Type: types.StateFullUpdate, }) } - default: trace := log.Trace().Msgf log.Info(). @@ -1012,3 +1011,48 @@ func readOrCreatePrivateKey(path string) (*key.MachinePrivate, error) { return &machineKey, nil } + +func (h *Headscale) loadACLPolicy() error { + var ( + pol *policy.ACLPolicy + err error + ) + + switch h.cfg.Policy.Mode { + case types.PolicyModeFile: + path := h.cfg.Policy.Path + + // It is fine to start headscale without a policy file. + if len(path) == 0 { + return nil + } + + absPath := util.AbsolutePathFromConfigPath(path) + pol, err = policy.LoadACLPolicyFromPath(absPath) + if err != nil { + return fmt.Errorf("failed to load ACL policy from file: %w", err) + } + case types.PolicyModeDB: + p, err := h.db.GetPolicy() + if err != nil { + if errors.Is(err, types.ErrPolicyNotFound) { + return nil + } + + return fmt.Errorf("failed to get policy from database: %w", err) + } + + pol, err = policy.LoadACLPolicyFromBytes([]byte(p.Data)) + if err != nil { + return fmt.Errorf("failed to parse policy: %w", err) + } + default: + log.Fatal(). + Str("mode", string(h.cfg.Policy.Mode)). + Msg("Unknown ACL policy mode") + } + + h.ACLPolicy = pol + + return nil +} diff --git a/hscontrol/db/db.go b/hscontrol/db/db.go index 69994d02f1..b44d76ab6a 100644 --- a/hscontrol/db/db.go +++ b/hscontrol/db/db.go @@ -395,6 +395,18 @@ func NewHeadscaleDatabase( return nil }, }, + { + ID: "202406021630", + Migrate: func(tx *gorm.DB) error { + err := tx.AutoMigrate(&types.Policy{}) + if err != nil { + return err + } + + return nil + }, + Rollback: func(db *gorm.DB) error { return nil }, + }, }, ) diff --git a/hscontrol/db/node_test.go b/hscontrol/db/node_test.go index e95ee4ae33..f1762a4484 100644 --- a/hscontrol/db/node_test.go +++ b/hscontrol/db/node_test.go @@ -8,13 +8,14 @@ import ( "testing" "time" - "github.com/juanfont/headscale/hscontrol/policy" - "github.com/juanfont/headscale/hscontrol/types" - "github.com/juanfont/headscale/hscontrol/util" "github.com/puzpuzpuz/xsync/v3" "gopkg.in/check.v1" "tailscale.com/tailcfg" "tailscale.com/types/key" + + "github.com/juanfont/headscale/hscontrol/policy" + "github.com/juanfont/headscale/hscontrol/types" + "github.com/juanfont/headscale/hscontrol/util" ) func (s *Suite) TestGetNode(c *check.C) { @@ -545,7 +546,7 @@ func (s *Suite) TestAutoApproveRoutes(c *check.C) { } `) - pol, err := policy.LoadACLPolicyFromBytes(acl, "hujson") + pol, err := policy.LoadACLPolicyFromBytes(acl) c.Assert(err, check.IsNil) c.Assert(pol, check.NotNil) diff --git a/hscontrol/db/policy.go b/hscontrol/db/policy.go new file mode 100644 index 0000000000..dcbdc8129f --- /dev/null +++ b/hscontrol/db/policy.go @@ -0,0 +1,44 @@ +package db + +import ( + "gorm.io/gorm" + "gorm.io/gorm/clause" + + "errors" + + "github.com/juanfont/headscale/hscontrol/types" +) + +// SetPolicy sets the policy in the database. +func (hsdb *HSDatabase) SetPolicy(policy string) (*types.Policy, error) { + // Create a new policy. + p := types.Policy{ + Data: policy, + } + + if err := hsdb.DB.Clauses(clause.Returning{}).Create(&p).Error; err != nil { + return nil, err + } + + return &p, nil +} + +// GetPolicy returns the latest policy in the database. +func (hsdb *HSDatabase) GetPolicy() (*types.Policy, error) { + var p types.Policy + + // Query: + // SELECT * FROM policies ORDER BY id DESC LIMIT 1; + if err := hsdb.DB. + Order("id DESC"). + Limit(1). + First(&p).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, types.ErrPolicyNotFound + } + + return nil, err + } + + return &p, nil +} diff --git a/hscontrol/grpcv1.go b/hscontrol/grpcv1.go index d9cd653d38..a351048fab 100644 --- a/hscontrol/grpcv1.go +++ b/hscontrol/grpcv1.go @@ -4,6 +4,8 @@ package hscontrol import ( "context" "errors" + "io" + "os" "sort" "strings" "time" @@ -11,12 +13,14 @@ import ( "github.com/rs/zerolog/log" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/timestamppb" "gorm.io/gorm" "tailscale.com/tailcfg" "tailscale.com/types/key" v1 "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/juanfont/headscale/hscontrol/db" + "github.com/juanfont/headscale/hscontrol/policy" "github.com/juanfont/headscale/hscontrol/types" "github.com/juanfont/headscale/hscontrol/util" ) @@ -671,6 +675,76 @@ func (api headscaleV1APIServer) DeleteApiKey( return &v1.DeleteApiKeyResponse{}, nil } +func (api headscaleV1APIServer) GetPolicy( + _ context.Context, + _ *v1.GetPolicyRequest, +) (*v1.GetPolicyResponse, error) { + switch api.h.cfg.Policy.Mode { + case types.PolicyModeDB: + p, err := api.h.db.GetPolicy() + if err != nil { + return nil, err + } + + return &v1.GetPolicyResponse{ + Policy: p.Data, + UpdatedAt: timestamppb.New(p.UpdatedAt), + }, nil + case types.PolicyModeFile: + // Read the file and return the contents as-is. + f, err := os.Open(api.h.cfg.Policy.Path) + if err != nil { + return nil, err + } + + defer f.Close() + + b, err := io.ReadAll(f) + if err != nil { + return nil, err + } + + return &v1.GetPolicyResponse{Policy: string(b)}, nil + } + + return nil, nil +} + +func (api headscaleV1APIServer) SetPolicy( + _ context.Context, + request *v1.SetPolicyRequest, +) (*v1.SetPolicyResponse, error) { + if api.h.cfg.Policy.Mode != types.PolicyModeDB { + return nil, types.ErrPolicyUpdateIsDisabled + } + + p := request.GetPolicy() + + valid, err := policy.LoadACLPolicyFromBytes([]byte(p)) + if err != nil { + return nil, err + } + + updated, err := api.h.db.SetPolicy(p) + if err != nil { + return nil, err + } + + api.h.ACLPolicy = valid + + ctx := types.NotifyCtx(context.Background(), "acl-update", "na") + api.h.nodeNotifier.NotifyAll(ctx, types.StateUpdate{ + Type: types.StateFullUpdate, + }) + + response := &v1.SetPolicyResponse{ + Policy: updated.Data, + UpdatedAt: timestamppb.New(updated.UpdatedAt), + } + + return response, nil +} + // The following service calls are for testing and debugging func (api headscaleV1APIServer) DebugCreateNode( ctx context.Context, diff --git a/hscontrol/policy/acls.go b/hscontrol/policy/acls.go index 9dde401b49..64697e3320 100644 --- a/hscontrol/policy/acls.go +++ b/hscontrol/policy/acls.go @@ -7,18 +7,17 @@ import ( "io" "net/netip" "os" - "path/filepath" "strconv" "strings" "time" - "github.com/juanfont/headscale/hscontrol/types" - "github.com/juanfont/headscale/hscontrol/util" "github.com/rs/zerolog/log" "github.com/tailscale/hujson" "go4.org/netipx" - "gopkg.in/yaml.v3" "tailscale.com/tailcfg" + + "github.com/juanfont/headscale/hscontrol/types" + "github.com/juanfont/headscale/hscontrol/util" ) var ( @@ -108,35 +107,22 @@ func LoadACLPolicyFromPath(path string) (*ACLPolicy, error) { Bytes("file", policyBytes). Msg("Loading ACLs") - switch filepath.Ext(path) { - case ".yml", ".yaml": - return LoadACLPolicyFromBytes(policyBytes, "yaml") - } - - return LoadACLPolicyFromBytes(policyBytes, "hujson") + return LoadACLPolicyFromBytes(policyBytes) } -func LoadACLPolicyFromBytes(acl []byte, format string) (*ACLPolicy, error) { +func LoadACLPolicyFromBytes(acl []byte) (*ACLPolicy, error) { var policy ACLPolicy - switch format { - case "yaml": - err := yaml.Unmarshal(acl, &policy) - if err != nil { - return nil, err - } - default: - ast, err := hujson.Parse(acl) - if err != nil { - return nil, err - } + ast, err := hujson.Parse(acl) + if err != nil { + return nil, fmt.Errorf("parsing hujson, err: %w", err) + } - ast.Standardize() - acl = ast.Pack() - err = json.Unmarshal(acl, &policy) - if err != nil { - return nil, err - } + ast.Standardize() + acl = ast.Pack() + + if err := json.Unmarshal(acl, &policy); err != nil { + return nil, fmt.Errorf("unmarshalling policy, err: %w", err) } if policy.IsZero() { @@ -846,7 +832,7 @@ func (pol *ACLPolicy) expandIPsFromUser( // shortcurcuit if we have no nodes to get ips from. if len(filteredNodes) == 0 { - return nil, nil //nolint + return nil, nil // nolint } for _, node := range filteredNodes { diff --git a/hscontrol/policy/acls_test.go b/hscontrol/policy/acls_test.go index c1e7ae080e..b3cc10f01a 100644 --- a/hscontrol/policy/acls_test.go +++ b/hscontrol/policy/acls_test.go @@ -6,14 +6,15 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/juanfont/headscale/hscontrol/types" - "github.com/juanfont/headscale/hscontrol/util" "github.com/rs/zerolog/log" "github.com/spf13/viper" "github.com/stretchr/testify/assert" "go4.org/netipx" "gopkg.in/check.v1" "tailscale.com/tailcfg" + + "github.com/juanfont/headscale/hscontrol/types" + "github.com/juanfont/headscale/hscontrol/util" ) var iap = func(ipStr string) *netip.Addr { @@ -321,44 +322,27 @@ func TestParsing(t *testing.T) { wantErr: false, }, { - name: "port-wildcard-yaml", - format: "yaml", + name: "ipv6", + format: "hujson", acl: ` ---- -hosts: - host-1: 100.100.100.100/32 - subnet-1: 100.100.101.100/24 -acls: - - action: accept - src: - - "*" - dst: - - host-1:* -`, - want: []tailcfg.FilterRule{ - { - SrcIPs: []string{"0.0.0.0/0", "::/0"}, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.100.100.100/32", Ports: tailcfg.PortRangeAny}, - }, - }, - }, - wantErr: false, - }, +{ + "hosts": { + "host-1": "100.100.100.100/32", + "subnet-1": "100.100.101.100/24", + }, + + "acls": [ { - name: "ipv6-yaml", - format: "yaml", - acl: ` ---- -hosts: - host-1: 100.100.100.100/32 - subnet-1: 100.100.101.100/24 -acls: - - action: accept - src: - - "*" - dst: - - host-1:* + "action": "accept", + "src": [ + "*", + ], + "dst": [ + "host-1:*", + ], + }, + ], +} `, want: []tailcfg.FilterRule{ { @@ -374,7 +358,7 @@ acls: for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - pol, err := LoadACLPolicyFromBytes([]byte(tt.acl), tt.format) + pol, err := LoadACLPolicyFromBytes([]byte(tt.acl)) if tt.wantErr && err == nil { t.Errorf("parsing() error = %v, wantErr %v", err, tt.wantErr) @@ -544,7 +528,7 @@ func (s *Suite) TestRuleInvalidGeneration(c *check.C) { ], } `) - pol, err := LoadACLPolicyFromBytes(acl, "hujson") + pol, err := LoadACLPolicyFromBytes(acl) c.Assert(pol.ACLs, check.HasLen, 6) c.Assert(err, check.IsNil) diff --git a/hscontrol/policy/acls_types.go b/hscontrol/policy/acls_types.go index e9c44909d1..25f02f16b5 100644 --- a/hscontrol/policy/acls_types.go +++ b/hscontrol/policy/acls_types.go @@ -6,26 +6,25 @@ import ( "strings" "github.com/tailscale/hujson" - "gopkg.in/yaml.v3" ) // ACLPolicy represents a Tailscale ACL Policy. type ACLPolicy struct { - Groups Groups `json:"groups" yaml:"groups"` - Hosts Hosts `json:"hosts" yaml:"hosts"` - TagOwners TagOwners `json:"tagOwners" yaml:"tagOwners"` - ACLs []ACL `json:"acls" yaml:"acls"` - Tests []ACLTest `json:"tests" yaml:"tests"` - AutoApprovers AutoApprovers `json:"autoApprovers" yaml:"autoApprovers"` - SSHs []SSH `json:"ssh" yaml:"ssh"` + Groups Groups `json:"groups" ` + Hosts Hosts `json:"hosts"` + TagOwners TagOwners `json:"tagOwners"` + ACLs []ACL `json:"acls"` + Tests []ACLTest `json:"tests"` + AutoApprovers AutoApprovers `json:"autoApprovers"` + SSHs []SSH `json:"ssh"` } // ACL is a basic rule for the ACL Policy. type ACL struct { - Action string `json:"action" yaml:"action"` - Protocol string `json:"proto" yaml:"proto"` - Sources []string `json:"src" yaml:"src"` - Destinations []string `json:"dst" yaml:"dst"` + Action string `json:"action"` + Protocol string `json:"proto"` + Sources []string `json:"src"` + Destinations []string `json:"dst"` } // Groups references a series of alias in the ACL rules. @@ -37,27 +36,27 @@ type Hosts map[string]netip.Prefix // TagOwners specify what users (users?) are allow to use certain tags. type TagOwners map[string][]string -// ACLTest is not implemented, but should be use to check if a certain rule is allowed. +// ACLTest is not implemented, but should be used to check if a certain rule is allowed. type ACLTest struct { - Source string `json:"src" yaml:"src"` - Accept []string `json:"accept" yaml:"accept"` - Deny []string `json:"deny,omitempty" yaml:"deny,omitempty"` + Source string `json:"src"` + Accept []string `json:"accept"` + Deny []string `json:"deny,omitempty"` } // AutoApprovers specify which users (users?), groups or tags have their advertised routes // or exit node status automatically enabled. type AutoApprovers struct { - Routes map[string][]string `json:"routes" yaml:"routes"` - ExitNode []string `json:"exitNode" yaml:"exitNode"` + Routes map[string][]string `json:"routes"` + ExitNode []string `json:"exitNode"` } // SSH controls who can ssh into which machines. type SSH struct { - Action string `json:"action" yaml:"action"` - Sources []string `json:"src" yaml:"src"` - Destinations []string `json:"dst" yaml:"dst"` - Users []string `json:"users" yaml:"users"` - CheckPeriod string `json:"checkPeriod,omitempty" yaml:"checkPeriod,omitempty"` + Action string `json:"action"` + Sources []string `json:"src"` + Destinations []string `json:"dst"` + Users []string `json:"users"` + CheckPeriod string `json:"checkPeriod,omitempty"` } // UnmarshalJSON allows to parse the Hosts directly into netip objects. @@ -89,27 +88,6 @@ func (hosts *Hosts) UnmarshalJSON(data []byte) error { return nil } -// UnmarshalYAML allows to parse the Hosts directly into netip objects. -func (hosts *Hosts) UnmarshalYAML(data []byte) error { - newHosts := Hosts{} - hostIPPrefixMap := make(map[string]string) - - err := yaml.Unmarshal(data, &hostIPPrefixMap) - if err != nil { - return err - } - for host, prefixStr := range hostIPPrefixMap { - prefix, err := netip.ParsePrefix(prefixStr) - if err != nil { - return err - } - newHosts[host] = prefix - } - *hosts = newHosts - - return nil -} - // IsZero is perhaps a bit naive here. func (pol ACLPolicy) IsZero() bool { if len(pol.Groups) == 0 && len(pol.Hosts) == 0 && len(pol.ACLs) == 0 { @@ -119,7 +97,7 @@ func (pol ACLPolicy) IsZero() bool { return false } -// Returns the list of autoApproving users, groups or tags for a given IPPrefix. +// GetRouteApprovers returns the list of autoApproving users, groups or tags for a given IPPrefix. func (autoApprovers *AutoApprovers) GetRouteApprovers( prefix netip.Prefix, ) ([]string, error) { @@ -127,7 +105,7 @@ func (autoApprovers *AutoApprovers) GetRouteApprovers( return autoApprovers.ExitNode, nil // 0.0.0.0/0, ::/0 or equivalent } - approverAliases := []string{} + approverAliases := make([]string, 0) for autoApprovedPrefix, autoApproverAliases := range autoApprovers.Routes { autoApprovedPrefix, err := netip.ParsePrefix(autoApprovedPrefix) diff --git a/hscontrol/types/config.go b/hscontrol/types/config.go index 8ac8dcc4c3..6eae9a32f8 100644 --- a/hscontrol/types/config.go +++ b/hscontrol/types/config.go @@ -11,7 +11,6 @@ import ( "time" "github.com/coreos/go-oidc/v3/oidc" - "github.com/juanfont/headscale/hscontrol/util" "github.com/prometheus/common/model" "github.com/rs/zerolog" "github.com/rs/zerolog/log" @@ -20,6 +19,8 @@ import ( "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" "tailscale.com/types/dnstype" + + "github.com/juanfont/headscale/hscontrol/util" ) const ( @@ -38,6 +39,13 @@ const ( IPAllocationStrategyRandom IPAllocationStrategy = "random" ) +type PolicyMode string + +const ( + PolicyModeDB = "database" + PolicyModeFile = "file" +) + // Config contains the initial Headscale configuration. type Config struct { ServerURL string @@ -76,7 +84,7 @@ type Config struct { CLI CLIConfig - ACL ACLConfig + Policy PolicyConfig Tuning Tuning } @@ -163,8 +171,9 @@ type CLIConfig struct { Insecure bool } -type ACLConfig struct { - PolicyPath string +type PolicyConfig struct { + Path string + Mode PolicyMode } type LogConfig struct { @@ -197,6 +206,8 @@ func LoadConfig(path string, isFile bool) error { viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) viper.AutomaticEnv() + viper.SetDefault("policy.mode", "file") + viper.SetDefault("tls_letsencrypt_cache_dir", "/var/www/.cache") viper.SetDefault("tls_letsencrypt_challenge_type", HTTP01ChallengeType) @@ -254,6 +265,13 @@ func LoadConfig(path string, isFile bool) error { return fmt.Errorf("fatal error reading config file: %w", err) } + // Register aliases for backward compatibility + // Has to be called _after_ viper.ReadInConfig() + // https://github.com/spf13/viper/issues/560 + + // Alias the old ACL Policy path with the new configuration option. + registerAliasAndDeprecate("policy.path", "acl_policy_path") + // Collect any validation errors and return them all at once var errorText string if (viper.GetString("tls_letsencrypt_hostname") != "") && @@ -390,11 +408,13 @@ func GetLogTailConfig() LogTailConfig { } } -func GetACLConfig() ACLConfig { - policyPath := viper.GetString("acl_policy_path") +func GetPolicyConfig() PolicyConfig { + policyPath := viper.GetString("policy.path") + policyMode := viper.GetString("policy.mode") - return ACLConfig{ - PolicyPath: policyPath, + return PolicyConfig{ + Path: policyPath, + Mode: PolicyMode(policyMode), } } @@ -764,7 +784,7 @@ func GetHeadscaleConfig() (*Config, error) { LogTail: logTailConfig, RandomizeClientPort: randomizeClientPort, - ACL: GetACLConfig(), + Policy: GetPolicyConfig(), CLI: CLIConfig{ Address: viper.GetString("cli.address"), @@ -787,3 +807,20 @@ func GetHeadscaleConfig() (*Config, error) { func IsCLIConfigured() bool { return viper.GetString("cli.address") != "" && viper.GetString("cli.api_key") != "" } + +// registerAliasAndDeprecate will register an alias between the newKey and the oldKey, +// and log a deprecation warning if the oldKey is set. +func registerAliasAndDeprecate(newKey, oldKey string) { + // NOTE: RegisterAlias is called with NEW KEY -> OLD KEY + viper.RegisterAlias(newKey, oldKey) + if viper.IsSet(oldKey) { + log.Warn().Msgf("The %q configuration key is deprecated. Please use %q instead. %q will be removed in the future.", oldKey, newKey, oldKey) + } +} + +// deprecateAndFatal will log a fatal deprecation warning if the oldKey is set. +func deprecateAndFatal(newKey, oldKey string) { + if viper.IsSet(oldKey) { + log.Fatal().Msgf("The %q configuration key is deprecated. Please use %q instead. %q has been removed.", oldKey, newKey, oldKey) + } +} diff --git a/hscontrol/types/policy.go b/hscontrol/types/policy.go new file mode 100644 index 0000000000..a30bf64072 --- /dev/null +++ b/hscontrol/types/policy.go @@ -0,0 +1,20 @@ +package types + +import ( + "errors" + + "gorm.io/gorm" +) + +var ( + ErrPolicyNotFound = errors.New("acl policy not found") + ErrPolicyUpdateIsDisabled = errors.New("update is disabled for modes other than 'database'") +) + +// Policy represents a policy in the database. +type Policy struct { + gorm.Model + + // Data contains the policy in HuJSON format. + Data string +} diff --git a/integration/acl_test.go b/integration/acl_test.go index 9d76396539..f7b59eb7f6 100644 --- a/integration/acl_test.go +++ b/integration/acl_test.go @@ -1,11 +1,13 @@ package integration import ( + "encoding/json" "fmt" "net/netip" "strings" "testing" + "github.com/google/go-cmp/cmp" "github.com/juanfont/headscale/hscontrol/policy" "github.com/juanfont/headscale/integration/hsic" "github.com/juanfont/headscale/integration/tsic" @@ -1012,3 +1014,156 @@ func TestACLDevice1CanAccessDevice2(t *testing.T) { }) } } + +func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) { + IntegrationSkip(t) + t.Parallel() + + scenario, err := NewScenario(dockertestMaxWait()) + assertNoErr(t, err) + defer scenario.Shutdown() + + spec := map[string]int{ + "user1": 1, + "user2": 1, + } + + err = scenario.CreateHeadscaleEnv(spec, + []tsic.Option{ + // Alpine containers dont have ip6tables set up, which causes + // tailscaled to stop configuring the wgengine, causing it + // to not configure DNS. + tsic.WithNetfilter("off"), + tsic.WithDockerEntrypoint([]string{ + "/bin/sh", + "-c", + "/bin/sleep 3 ; apk add python3 curl ; update-ca-certificates ; python3 -m http.server --bind :: 80 & tailscaled --tun=tsdev", + }), + tsic.WithDockerWorkdir("/"), + }, + hsic.WithTestName("policyreload"), + hsic.WithConfigEnv(map[string]string{ + "HEADSCALE_POLICY_MODE": "database", + }), + ) + assertNoErr(t, err) + + _, err = scenario.ListTailscaleClientsFQDNs() + assertNoErrListFQDN(t, err) + + err = scenario.WaitForTailscaleSync() + assertNoErrSync(t, err) + + user1Clients, err := scenario.ListTailscaleClients("user1") + assertNoErr(t, err) + + user2Clients, err := scenario.ListTailscaleClients("user2") + assertNoErr(t, err) + + all := append(user1Clients, user2Clients...) + + // Initially all nodes can reach each other + for _, client := range all { + for _, peer := range all { + if client.ID() == peer.ID() { + continue + } + + fqdn, err := peer.FQDN() + assertNoErr(t, err) + + url := fmt.Sprintf("http://%s/etc/hostname", fqdn) + t.Logf("url from %s to %s", client.Hostname(), url) + + result, err := client.Curl(url) + assert.Len(t, result, 13) + assertNoErr(t, err) + } + } + + headscale, err := scenario.Headscale() + assertNoErr(t, err) + + p := policy.ACLPolicy{ + ACLs: []policy.ACL{ + { + Action: "accept", + Sources: []string{"user1"}, + Destinations: []string{"user2:*"}, + }, + }, + Hosts: policy.Hosts{}, + } + + pBytes, _ := json.Marshal(p) + + policyFilePath := "/etc/headscale/policy.json" + + err = headscale.WriteFile(policyFilePath, pBytes) + assertNoErr(t, err) + + // No policy is present at this time. + // Add a new policy from a file. + _, err = headscale.Execute( + []string{ + "headscale", + "policy", + "set", + "-f", + policyFilePath, + }, + ) + assertNoErr(t, err) + + // Get the current policy and check + // if it is the same as the one we set. + var output *policy.ACLPolicy + err = executeAndUnmarshal( + headscale, + []string{ + "headscale", + "policy", + "get", + "--output", + "json", + }, + &output, + ) + assertNoErr(t, err) + + assert.Len(t, output.ACLs, 1) + + if diff := cmp.Diff(p, *output); diff != "" { + t.Errorf("unexpected policy(-want +got):\n%s", diff) + } + + // Test that user1 can visit all user2 + for _, client := range user1Clients { + for _, peer := range user2Clients { + fqdn, err := peer.FQDN() + assertNoErr(t, err) + + url := fmt.Sprintf("http://%s/etc/hostname", fqdn) + t.Logf("url from %s to %s", client.Hostname(), url) + + result, err := client.Curl(url) + assert.Len(t, result, 13) + assertNoErr(t, err) + } + } + + // Test that user2 _cannot_ visit user1 + for _, client := range user2Clients { + for _, peer := range user1Clients { + fqdn, err := peer.FQDN() + assertNoErr(t, err) + + url := fmt.Sprintf("http://%s/etc/hostname", fqdn) + t.Logf("url from %s to %s", client.Hostname(), url) + + result, err := client.Curl(url) + assert.Empty(t, result) + assert.Error(t, err) + } + } +} diff --git a/integration/cli_test.go b/integration/cli_test.go index 57edf58ef0..9bc67a8937 100644 --- a/integration/cli_test.go +++ b/integration/cli_test.go @@ -7,11 +7,12 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + v1 "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/juanfont/headscale/hscontrol/policy" "github.com/juanfont/headscale/integration/hsic" "github.com/juanfont/headscale/integration/tsic" - "github.com/stretchr/testify/assert" ) func executeAndUnmarshal[T any](headscale ControlServer, command []string, result T) error { @@ -1596,3 +1597,83 @@ func TestNodeMoveCommand(t *testing.T) { assert.Equal(t, node.GetUser().GetName(), "old-user") } + +func TestPolicyCommand(t *testing.T) { + IntegrationSkip(t) + t.Parallel() + + scenario, err := NewScenario(dockertestMaxWait()) + assertNoErr(t, err) + defer scenario.Shutdown() + + spec := map[string]int{ + "policy-user": 0, + } + + err = scenario.CreateHeadscaleEnv( + spec, + []tsic.Option{}, + hsic.WithTestName("clins"), + hsic.WithConfigEnv(map[string]string{ + "HEADSCALE_POLICY_MODE": "database", + }), + ) + assertNoErr(t, err) + + headscale, err := scenario.Headscale() + assertNoErr(t, err) + + p := policy.ACLPolicy{ + ACLs: []policy.ACL{ + { + Action: "accept", + Sources: []string{"*"}, + Destinations: []string{"*:*"}, + }, + }, + TagOwners: map[string][]string{ + "tag:exists": {"policy-user"}, + }, + } + + pBytes, _ := json.Marshal(p) + + policyFilePath := "/etc/headscale/policy.json" + + err = headscale.WriteFile(policyFilePath, pBytes) + assertNoErr(t, err) + + // No policy is present at this time. + // Add a new policy from a file. + _, err = headscale.Execute( + []string{ + "headscale", + "policy", + "set", + "-f", + policyFilePath, + }, + ) + + assertNoErr(t, err) + + // Get the current policy and check + // if it is the same as the one we set. + var output *policy.ACLPolicy + err = executeAndUnmarshal( + headscale, + []string{ + "headscale", + "policy", + "get", + "--output", + "json", + }, + &output, + ) + assertNoErr(t, err) + + assert.Len(t, output.TagOwners, 1) + assert.Len(t, output.ACLs, 1) + assert.Equal(t, output.TagOwners["tag:exists"], []string{"policy-user"}) +} diff --git a/integration/control.go b/integration/control.go index f5557495a0..4260ac4b22 100644 --- a/integration/control.go +++ b/integration/control.go @@ -1,8 +1,9 @@ package integration import ( - v1 "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/ory/dockertest/v3" + + v1 "github.com/juanfont/headscale/gen/go/headscale/v1" ) type ControlServer interface { @@ -10,6 +11,7 @@ type ControlServer interface { SaveLog(string) error SaveProfile(string) error Execute(command []string) (string, error) + WriteFile(path string, content []byte) error ConnectToNetwork(network *dockertest.Network) error GetHealthEndpoint() string GetEndpoint() string diff --git a/proto/headscale/v1/headscale.proto b/proto/headscale/v1/headscale.proto index 1ccc7029fd..183927edc5 100644 --- a/proto/headscale/v1/headscale.proto +++ b/proto/headscale/v1/headscale.proto @@ -9,6 +9,7 @@ import "headscale/v1/preauthkey.proto"; import "headscale/v1/node.proto"; import "headscale/v1/routes.proto"; import "headscale/v1/apikey.proto"; +import "headscale/v1/policy.proto"; // import "headscale/v1/device.proto"; service HeadscaleService { @@ -193,6 +194,22 @@ service HeadscaleService { } // --- ApiKeys end --- + // --- Policy start --- + rpc GetPolicy(GetPolicyRequest) returns (GetPolicyResponse) { + option (google.api.http) = { + get: "/api/v1/policy" + }; + } + + rpc SetPolicy(SetPolicyRequest) returns (SetPolicyResponse) { + option (google.api.http) = { + put: "/api/v1/policy" + body: "*" + }; + } + // --- Policy end --- + + // Implement Tailscale API // rpc GetDevice(GetDeviceRequest) returns(GetDeviceResponse) { // option(google.api.http) = { diff --git a/proto/headscale/v1/policy.proto b/proto/headscale/v1/policy.proto new file mode 100644 index 0000000000..3c92938556 --- /dev/null +++ b/proto/headscale/v1/policy.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; +package headscale.v1; +option go_package = "github.com/juanfont/headscale/gen/go/v1"; + +import "google/protobuf/timestamp.proto"; + +message SetPolicyRequest { + string policy = 1; +} + +message SetPolicyResponse { + string policy = 1; + google.protobuf.Timestamp updated_at = 2; +} + +message GetPolicyRequest {} + +message GetPolicyResponse { + string policy = 1; + google.protobuf.Timestamp updated_at = 2; +} \ No newline at end of file