From 05e0e3a9798d058b7f2754adf1672300b730b99c Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Mon, 23 Sep 2024 12:14:07 -0400 Subject: [PATCH] roughed-in dual-pathed cli implementation for 'zrok share [public|private|reserved] (#751) --- cmd/zrok/agentSharePrivate.go | 162 --------------------------------- cmd/zrok/agentSharePublic.go | 144 ----------------------------- cmd/zrok/agentShareReserved.go | 65 ------------- cmd/zrok/sharePrivate.go | 141 ++++++++++++++++++++++++++++ cmd/zrok/sharePublic.go | 119 +++++++++++++++++++++--- cmd/zrok/shareReserved.go | 16 ++-- 6 files changed, 255 insertions(+), 392 deletions(-) delete mode 100644 cmd/zrok/agentSharePrivate.go delete mode 100644 cmd/zrok/agentSharePublic.go delete mode 100644 cmd/zrok/agentShareReserved.go diff --git a/cmd/zrok/agentSharePrivate.go b/cmd/zrok/agentSharePrivate.go deleted file mode 100644 index a85263f5..00000000 --- a/cmd/zrok/agentSharePrivate.go +++ /dev/null @@ -1,162 +0,0 @@ -package main - -import ( - "context" - "fmt" - "github.com/openziti/zrok/agent/agentClient" - "github.com/openziti/zrok/agent/agentGrpc" - "github.com/openziti/zrok/endpoints/vpn" - "github.com/openziti/zrok/environment" - "github.com/openziti/zrok/tui" - "github.com/spf13/cobra" - "net" - "path/filepath" -) - -func init() { - agentShareCmd.AddCommand(newAgentSharePrivateCommand().cmd) -} - -type agentSharePrivateCommand struct { - backendMode string - insecure bool - closed bool - accessGrants []string - cmd *cobra.Command -} - -func newAgentSharePrivateCommand() *agentSharePrivateCommand { - cmd := &cobra.Command{ - Use: "private ", - Short: "Create a private share in the zrok Agent", - Args: cobra.RangeArgs(0, 1), - } - command := &agentSharePrivateCommand{cmd: cmd} - cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode {proxy, web, tcpTunnel, udpTunnel, caddy, drive, socks, vpn}") - cmd.Flags().BoolVar(&command.insecure, "insecure", false, "Enable insecure TLS certificate validation for ") - cmd.Flags().BoolVar(&command.closed, "closed", false, "Enable closed permission mode (see --access-grant)") - cmd.Flags().StringArrayVar(&command.accessGrants, "access-grant", []string{}, "zrok accounts that are allowed to access this share (see --closed)") - cmd.Run = command.run - return command -} - -func (cmd *agentSharePrivateCommand) run(_ *cobra.Command, args []string) { - var target string - - switch cmd.backendMode { - case "proxy": - if len(args) != 1 { - tui.Error("the 'proxy' backend mode expects a ", nil) - } - v, err := parseUrl(args[0]) - if err != nil { - if !panicInstead { - tui.Error("invalid target endpoint URL", err) - } - panic(err) - } - target = v - - case "web": - if len(args) != 1 { - tui.Error("the 'web' backend mode expects a ", nil) - } - v, err := filepath.Abs(args[0]) - if err != nil { - if !panicInstead { - tui.Error("invalid target endpoint URL", err) - } - panic(err) - } - target = v - - case "tcpTunnel": - if len(args) != 1 { - tui.Error("the 'tcpTunnel' backend mode expects a ", nil) - } - target = args[0] - - case "udpTunnel": - if len(args) != 1 { - tui.Error("the 'udpTunnel' backend mode expects a ", nil) - } - target = args[0] - - case "caddy": - if len(args) != 1 { - tui.Error("the 'caddy' backend mode expects a ", nil) - } - v, err := filepath.Abs(args[0]) - if err != nil { - if !panicInstead { - tui.Error("invalid target endpoint URL", err) - } - panic(err) - } - target = v - - case "drive": - if len(args) != 1 { - tui.Error("the 'drive' backend mode expects a ", nil) - } - v, err := filepath.Abs(args[0]) - if err != nil { - if !panicInstead { - tui.Error("invalid target endpoint URL", err) - } - panic(err) - } - target = v - - case "socks": - if len(args) != 0 { - tui.Error("the 'socks' backend mode does not expect ", nil) - } - target = "socks" - - case "vpn": - if len(args) == 1 { - _, _, err := net.ParseCIDR(args[0]) - if err != nil { - tui.Error("the 'vpn' backend expect valid CIDR ", err) - } - target = args[0] - } else { - target = vpn.DefaultTarget() - } - - default: - tui.Error(fmt.Sprintf("invalid backend mode '%v'", cmd.backendMode), nil) - } - - root, err := environment.LoadRoot() - if err != nil { - if !panicInstead { - tui.Error("unable to load environment", err) - } - panic(err) - } - - if !root.IsEnabled() { - tui.Error("unable to load environment; did you 'zrok enable'?", nil) - } - - client, conn, err := agentClient.NewClient(root) - if err != nil { - tui.Error("error connecting to agent", err) - } - defer conn.Close() - - shr, err := client.SharePrivate(context.Background(), &agentGrpc.SharePrivateRequest{ - Target: target, - BackendMode: cmd.backendMode, - Insecure: cmd.insecure, - Closed: cmd.closed, - AccessGrants: cmd.accessGrants, - }) - if err != nil { - tui.Error("error creating share", err) - } - - fmt.Println(shr) -} diff --git a/cmd/zrok/agentSharePublic.go b/cmd/zrok/agentSharePublic.go deleted file mode 100644 index 9f69da1c..00000000 --- a/cmd/zrok/agentSharePublic.go +++ /dev/null @@ -1,144 +0,0 @@ -package main - -import ( - "context" - "fmt" - "github.com/openziti/zrok/agent/agentClient" - "github.com/openziti/zrok/agent/agentGrpc" - "github.com/openziti/zrok/environment" - "github.com/openziti/zrok/tui" - "github.com/spf13/cobra" - "path/filepath" - "time" -) - -func init() { - agentShareCmd.AddCommand(newAgentSharePublicCommand().cmd) -} - -type agentSharePublicCommand struct { - basicAuth []string - frontendSelection []string - backendMode string - headless bool - insecure bool - oauthProvider string - oauthEmailAddressPatterns []string - oauthCheckInterval time.Duration - closed bool - accessGrants []string - cmd *cobra.Command -} - -func newAgentSharePublicCommand() *agentSharePublicCommand { - cmd := &cobra.Command{ - Use: "public ", - Short: "Create a public share in the zrok Agent", - Args: cobra.ExactArgs(1), - } - command := &agentSharePublicCommand{cmd: cmd} - defaultFrontends := []string{"public"} - if root, err := environment.LoadRoot(); err == nil { - defaultFrontend, _ := root.DefaultFrontend() - defaultFrontends = []string{defaultFrontend} - } - cmd.Flags().StringArrayVar(&command.frontendSelection, "frontend", defaultFrontends, "Selected frontends to use for the share") - cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode {proxy, web, caddy, drive}") - cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless") - cmd.Flags().BoolVar(&command.insecure, "insecure", false, "Enable insecure TLS certificate validation for ") - cmd.Flags().BoolVar(&command.closed, "closed", false, "Enable closed permission mode (see --access-grant)") - cmd.Flags().StringArrayVar(&command.accessGrants, "access-grant", []string{}, "zrok accounts that are allowed to access this share (see --closed)") - cmd.Flags().StringArrayVar(&command.basicAuth, "basic-auth", []string{}, "Basic authentication users (,...)") - cmd.Flags().StringVar(&command.oauthProvider, "oauth-provider", "", "Enable OAuth provider [google, github]") - cmd.Flags().StringArrayVar(&command.oauthEmailAddressPatterns, "oauth-email-address-patterns", []string{}, "Allow only these email domain globs to authenticate via OAuth") - cmd.Flags().DurationVar(&command.oauthCheckInterval, "oauth-check-interval", 3*time.Hour, "Maximum lifetime for OAuth authentication; reauthenticate after expiry") - cmd.MarkFlagsMutuallyExclusive("basic-auth", "oauth-provider") - - cmd.Run = command.run - return command -} - -func (cmd *agentSharePublicCommand) run(_ *cobra.Command, args []string) { - var target string - - switch cmd.backendMode { - case "proxy": - v, err := parseUrl(args[0]) - if err != nil { - if !panicInstead { - tui.Error("invalid target endpoint URL", err) - } - panic(err) - } - target = v - - case "web": - v, err := filepath.Abs(args[0]) - if err != nil { - if !panicInstead { - tui.Error("invalid target endpoint URL", err) - } - panic(err) - } - target = v - - case "caddy": - v, err := filepath.Abs(args[0]) - if err != nil { - if !panicInstead { - tui.Error("invalid target endpoint URL", err) - } - panic(err) - } - target = v - - case "drive": - v, err := filepath.Abs(args[0]) - if err != nil { - if !panicInstead { - tui.Error("invalid target endpoint URL", err) - } - panic(err) - } - target = v - - default: - tui.Error(fmt.Sprintf("invalid backend mode '%v'", cmd.backendMode), nil) - } - - root, err := environment.LoadRoot() - if err != nil { - if !panicInstead { - tui.Error("unable to load environment", err) - } - panic(err) - } - - if !root.IsEnabled() { - tui.Error("unable to load environment; did you 'zrok enable'?", nil) - } - - client, conn, err := agentClient.NewClient(root) - if err != nil { - tui.Error("error connecting to agent", err) - } - defer conn.Close() - - shr, err := client.SharePublic(context.Background(), &agentGrpc.SharePublicRequest{ - Target: target, - BasicAuth: cmd.basicAuth, - FrontendSelection: cmd.frontendSelection, - BackendMode: cmd.backendMode, - Insecure: cmd.insecure, - OauthProvider: cmd.oauthProvider, - OauthEmailAddressPatterns: cmd.oauthEmailAddressPatterns, - OauthCheckInterval: cmd.oauthCheckInterval.String(), - Closed: cmd.closed, - AccessGrants: cmd.accessGrants, - }) - if err != nil { - tui.Error("error creating share", err) - } - - fmt.Println(shr) -} diff --git a/cmd/zrok/agentShareReserved.go b/cmd/zrok/agentShareReserved.go deleted file mode 100644 index afcecd12..00000000 --- a/cmd/zrok/agentShareReserved.go +++ /dev/null @@ -1,65 +0,0 @@ -package main - -import ( - "context" - "fmt" - "github.com/openziti/zrok/agent/agentClient" - "github.com/openziti/zrok/agent/agentGrpc" - "github.com/openziti/zrok/environment" - "github.com/openziti/zrok/tui" - "github.com/spf13/cobra" -) - -func init() { - agentShareCmd.AddCommand(newAgentShareReservedCommand().cmd) -} - -type agentShareReservedCommand struct { - overrideEndpoint string - insecure bool - cmd *cobra.Command -} - -func newAgentShareReservedCommand() *agentShareReservedCommand { - cmd := &cobra.Command{ - Use: "reserved ", - Short: "Share an existing reserved share in the zrok Agent", - Args: cobra.ExactArgs(1), - } - command := &agentShareReservedCommand{cmd: cmd} - cmd.Flags().StringVar(&command.overrideEndpoint, "override-endpoint", "", "Override the stored target endpoint with a replacement") - cmd.Flags().BoolVar(&command.insecure, "insecure", false, "Enable insecure TLS certificate validation") - cmd.Run = command.run - return command -} - -func (cmd *agentShareReservedCommand) run(_ *cobra.Command, args []string) { - root, err := environment.LoadRoot() - if err != nil { - if !panicInstead { - tui.Error("unable to load environment", err) - } - panic(err) - } - - if !root.IsEnabled() { - tui.Error("unable to load environment; did you 'zrok enable'?", nil) - } - - client, conn, err := agentClient.NewClient(root) - if err != nil { - tui.Error("error connecting to agent", err) - } - defer conn.Close() - - shr, err := client.ShareReserved(context.Background(), &agentGrpc.ShareReservedRequest{ - Token: args[0], - OverrideEndpoint: cmd.overrideEndpoint, - Insecure: cmd.insecure, - }) - if err != nil { - tui.Error("error sharing reserved share", err) - } - - fmt.Println(shr) -} diff --git a/cmd/zrok/sharePrivate.go b/cmd/zrok/sharePrivate.go index 7dd4421d..24cb072a 100644 --- a/cmd/zrok/sharePrivate.go +++ b/cmd/zrok/sharePrivate.go @@ -1,9 +1,12 @@ package main import ( + "context" "encoding/json" "fmt" tea "github.com/charmbracelet/bubbletea" + "github.com/openziti/zrok/agent/agentClient" + "github.com/openziti/zrok/agent/agentGrpc" "github.com/openziti/zrok/endpoints" "github.com/openziti/zrok/endpoints/drive" "github.com/openziti/zrok/endpoints/proxy" @@ -20,6 +23,7 @@ import ( "net" "os" "os/signal" + "path/filepath" "syscall" ) @@ -56,6 +60,34 @@ func newSharePrivateCommand() *sharePrivateCommand { } func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) { + root, err := environment.LoadRoot() + if err != nil { + if !panicInstead { + tui.Error("error loading environment", err) + } + panic(err) + } + + if !root.IsEnabled() { + tui.Error("unable to load environment; did you 'zrok enable'?", nil) + } + + if cmd.agent { + cmd.shareLocal(args, root) + } else { + agent, err := agentClient.IsAgentRunning(root) + if err != nil { + tui.Error("error checking if agent is running", err) + } + if agent { + cmd.shareAgent(args, root) + } else { + cmd.shareLocal(args, root) + } + } +} + +func (cmd *sharePrivateCommand) shareLocal(args []string, root env_core.Root) { var target string switch cmd.backendMode { @@ -424,3 +456,112 @@ func (cmd *sharePrivateCommand) shutdown(root env_core.Root, shr *sdk.Share) { } logrus.Debugf("shutdown complete") } + +func (cmd *sharePrivateCommand) shareAgent(args []string, root env_core.Root) { + var target string + + switch cmd.backendMode { + case "proxy": + if len(args) != 1 { + tui.Error("the 'proxy' backend mode expects a ", nil) + } + v, err := parseUrl(args[0]) + if err != nil { + if !panicInstead { + tui.Error("invalid target endpoint URL", err) + } + panic(err) + } + target = v + + case "web": + if len(args) != 1 { + tui.Error("the 'web' backend mode expects a ", nil) + } + v, err := filepath.Abs(args[0]) + if err != nil { + if !panicInstead { + tui.Error("invalid target endpoint URL", err) + } + panic(err) + } + target = v + + case "tcpTunnel": + if len(args) != 1 { + tui.Error("the 'tcpTunnel' backend mode expects a ", nil) + } + target = args[0] + + case "udpTunnel": + if len(args) != 1 { + tui.Error("the 'udpTunnel' backend mode expects a ", nil) + } + target = args[0] + + case "caddy": + if len(args) != 1 { + tui.Error("the 'caddy' backend mode expects a ", nil) + } + v, err := filepath.Abs(args[0]) + if err != nil { + if !panicInstead { + tui.Error("invalid target endpoint URL", err) + } + panic(err) + } + target = v + + case "drive": + if len(args) != 1 { + tui.Error("the 'drive' backend mode expects a ", nil) + } + v, err := filepath.Abs(args[0]) + if err != nil { + if !panicInstead { + tui.Error("invalid target endpoint URL", err) + } + panic(err) + } + target = v + + case "socks": + if len(args) != 0 { + tui.Error("the 'socks' backend mode does not expect ", nil) + } + target = "socks" + + case "vpn": + if len(args) == 1 { + _, _, err := net.ParseCIDR(args[0]) + if err != nil { + tui.Error("the 'vpn' backend expect valid CIDR ", err) + } + target = args[0] + } else { + target = vpn.DefaultTarget() + } + + default: + tui.Error(fmt.Sprintf("invalid backend mode '%v'", cmd.backendMode), nil) + } + + client, conn, err := agentClient.NewClient(root) + if err != nil { + tui.Error("error connecting to agent", err) + } + defer func() { _ = conn.Close() }() + + shr, err := client.SharePrivate(context.Background(), &agentGrpc.SharePrivateRequest{ + Target: target, + BackendMode: cmd.backendMode, + Insecure: cmd.insecure, + Closed: cmd.closed, + AccessGrants: cmd.accessGrants, + }) + if err != nil { + tui.Error("error creating share", err) + } + + fmt.Println(shr) +} diff --git a/cmd/zrok/sharePublic.go b/cmd/zrok/sharePublic.go index b4190394..9ed9eb73 100644 --- a/cmd/zrok/sharePublic.go +++ b/cmd/zrok/sharePublic.go @@ -1,12 +1,15 @@ package main import ( + "context" "encoding/json" "fmt" tea "github.com/charmbracelet/bubbletea" "github.com/gobwas/glob" + "github.com/openziti/zrok/agent/agentClient" + "github.com/openziti/zrok/agent/agentGrpc" "github.com/openziti/zrok/endpoints" - drive "github.com/openziti/zrok/endpoints/drive" + "github.com/openziti/zrok/endpoints/drive" "github.com/openziti/zrok/endpoints/proxy" "github.com/openziti/zrok/environment" "github.com/openziti/zrok/environment/env_core" @@ -16,6 +19,7 @@ import ( "github.com/spf13/cobra" "os" "os/signal" + "path/filepath" "strings" "syscall" "time" @@ -71,6 +75,34 @@ func newSharePublicCommand() *sharePublicCommand { } func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) { + root, err := environment.LoadRoot() + if err != nil { + if !panicInstead { + tui.Error("error loading environment", err) + } + panic(err) + } + + if !root.IsEnabled() { + tui.Error("unable to load environment; did you 'zrok enable'?", nil) + } + + if cmd.agent { + cmd.shareLocal(args, root) + } else { + agent, err := agentClient.IsAgentRunning(root) + if err != nil { + tui.Error("error checking if agent is running", err) + } + if agent { + cmd.shareAgent(args, root) + } else { + cmd.shareLocal(args, root) + } + } +} + +func (cmd *sharePublicCommand) shareLocal(args []string, root env_core.Root) { var target string switch cmd.backendMode { @@ -98,18 +130,6 @@ func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) { tui.Error(fmt.Sprintf("invalid backend mode '%v'; expected {proxy, web, caddy, drive}", cmd.backendMode), nil) } - root, err := environment.LoadRoot() - if err != nil { - if !panicInstead { - tui.Error("unable to load environment", err) - } - panic(err) - } - - if !root.IsEnabled() { - tui.Error("unable to load environment; did you 'zrok enable'?", nil) - } - zif, err := root.ZitiIdentityNamed(root.EnvironmentIdentityName()) if err != nil { if !panicInstead { @@ -327,3 +347,76 @@ func (cmd *sharePublicCommand) shutdown(root env_core.Root, shr *sdk.Share) { } logrus.Debugf("shutdown complete") } + +func (cmd *sharePublicCommand) shareAgent(args []string, root env_core.Root) { + var target string + + switch cmd.backendMode { + case "proxy": + v, err := parseUrl(args[0]) + if err != nil { + if !panicInstead { + tui.Error("invalid target endpoint URL", err) + } + panic(err) + } + target = v + + case "web": + v, err := filepath.Abs(args[0]) + if err != nil { + if !panicInstead { + tui.Error("invalid target endpoint URL", err) + } + panic(err) + } + target = v + + case "caddy": + v, err := filepath.Abs(args[0]) + if err != nil { + if !panicInstead { + tui.Error("invalid target endpoint URL", err) + } + panic(err) + } + target = v + + case "drive": + v, err := filepath.Abs(args[0]) + if err != nil { + if !panicInstead { + tui.Error("invalid target endpoint URL", err) + } + panic(err) + } + target = v + + default: + tui.Error(fmt.Sprintf("invalid backend mode '%v'", cmd.backendMode), nil) + } + + client, conn, err := agentClient.NewClient(root) + if err != nil { + tui.Error("error connecting to agent", err) + } + defer func() { _ = conn.Close() }() + + shr, err := client.SharePublic(context.Background(), &agentGrpc.SharePublicRequest{ + Target: target, + BasicAuth: cmd.basicAuth, + FrontendSelection: cmd.frontendSelection, + BackendMode: cmd.backendMode, + Insecure: cmd.insecure, + OauthProvider: cmd.oauthProvider, + OauthEmailAddressPatterns: cmd.oauthEmailAddressPatterns, + OauthCheckInterval: cmd.oauthCheckInterval.String(), + Closed: cmd.closed, + AccessGrants: cmd.accessGrants, + }) + if err != nil { + tui.Error("error creating share", err) + } + + fmt.Println(shr) +} diff --git a/cmd/zrok/shareReserved.go b/cmd/zrok/shareReserved.go index 99824521..41daa7a4 100644 --- a/cmd/zrok/shareReserved.go +++ b/cmd/zrok/shareReserved.go @@ -67,22 +67,22 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) { tui.Error("unable to load environment; did you 'zrok enable'?", nil) } - if !cmd.agent { + if cmd.agent { + cmd.shareLocal(args, root) + } else { agent, err := agentClient.IsAgentRunning(root) if err != nil { tui.Error("error checking if agent is running", err) } if agent { - cmd.agentShareReserved(args, root) + cmd.shareAgent(args, root) } else { - cmd.shareReserved(args, root) + cmd.shareLocal(args, root) } - } else { - cmd.shareReserved(args, root) } } -func (cmd *shareReservedCommand) shareReserved(args []string, root env_core.Root) { +func (cmd *shareReservedCommand) shareLocal(args []string, root env_core.Root) { shrToken := args[0] var target string @@ -411,14 +411,14 @@ func (cmd *shareReservedCommand) shareReserved(args []string, root env_core.Root } } -func (cmd *shareReservedCommand) agentShareReserved(args []string, root env_core.Root) { +func (cmd *shareReservedCommand) shareAgent(args []string, root env_core.Root) { logrus.Info("starting") client, conn, err := agentClient.NewClient(root) if err != nil { tui.Error("error connecting to agent", err) } - defer conn.Close() + defer func() { _ = conn.Close() }() shr, err := client.ShareReserved(context.Background(), &agentGrpc.ShareReservedRequest{ Token: args[0],