infrastructure for private sharing commands (#463)

This commit is contained in:
Michael Quigley 2024-09-16 14:21:23 -04:00
parent 254251a3dc
commit dffb7832f3
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
5 changed files with 239 additions and 5 deletions

66
agent/privateShare.go Normal file
View File

@ -0,0 +1,66 @@
package agent
import (
"context"
"errors"
"github.com/openziti/zrok/agent/agentGrpc"
"github.com/openziti/zrok/agent/proctree"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/sdk/golang/sdk"
"github.com/sirupsen/logrus"
"os"
)
func (i *agentGrpcImpl) PrivateShare(_ context.Context, req *agentGrpc.PrivateShareRequest) (*agentGrpc.PrivateShareReply, error) {
root, err := environment.LoadRoot()
if err != nil {
return nil, err
}
if !root.IsEnabled() {
return nil, errors.New("unable to load environment; did you 'zrok enable'?")
}
shrCmd := []string{os.Args[0], "share", "private", "--agent", "-b", req.BackendMode}
shr := &share{
shareMode: sdk.PrivateShareMode,
backendMode: sdk.BackendMode(req.BackendMode),
bootComplete: make(chan struct{}),
a: i.a,
}
if req.Insecure {
shrCmd = append(shrCmd, "--insecure")
}
shr.insecure = req.Insecure
if req.Closed {
shrCmd = append(shrCmd, "--closed")
}
shr.closed = req.Closed
for _, grant := range req.AccessGrants {
shrCmd = append(shrCmd, "--access-grant", grant)
}
shr.accessGrants = req.AccessGrants
shrCmd = append(shrCmd, req.Target)
shr.target = req.Target
logrus.Infof("executing '%v'", shrCmd)
shr.process, err = proctree.StartChild(shr.tail, shrCmd...)
if err != nil {
return nil, err
}
go shr.monitor()
<-shr.bootComplete
if shr.bootErr == nil {
i.a.inShares <- shr
return &agentGrpc.PrivateShareReply{Token: shr.token}, nil
}
return nil, shr.bootErr
}

View File

@ -75,7 +75,7 @@ func (i *agentGrpcImpl) PublicShare(_ context.Context, req *agentGrpc.PublicShar
shr.process, err = proctree.StartChild(shr.tail, shrCmd...) shr.process, err = proctree.StartChild(shr.tail, shrCmd...)
if err != nil { if err != nil {
return &agentGrpc.PublicShareReply{}, err return nil, err
} }
go shr.monitor() go shr.monitor()
@ -88,5 +88,6 @@ func (i *agentGrpcImpl) PublicShare(_ context.Context, req *agentGrpc.PublicShar
FrontendEndpoints: shr.frontendEndpoints, FrontendEndpoints: shr.frontendEndpoints,
}, nil }, nil
} }
return &agentGrpc.PublicShareReply{}, shr.bootErr
return nil, shr.bootErr
} }

View File

@ -7,6 +7,7 @@ import (
"github.com/michaelquigley/pfxlog" "github.com/michaelquigley/pfxlog"
"github.com/openziti/zrok/agent/proctree" "github.com/openziti/zrok/agent/proctree"
"github.com/openziti/zrok/sdk/golang/sdk" "github.com/openziti/zrok/sdk/golang/sdk"
"github.com/sirupsen/logrus"
"strings" "strings"
"time" "time"
) )
@ -44,6 +45,11 @@ func (s *share) monitor() {
} }
func (s *share) tail(data []byte) { func (s *share) tail(data []byte) {
defer func() {
if r := recover(); r != nil {
logrus.Errorf("recovering: %v", r)
}
}()
s.readBuffer.Write(data) s.readBuffer.Write(data)
if line, err := s.readBuffer.ReadString('\n'); err == nil { if line, err := s.readBuffer.ReadString('\n'); err == nil {
line = strings.Trim(line, "\n") line = strings.Trim(line, "\n")

View File

@ -0,0 +1,164 @@
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
headless bool
insecure bool
closed bool
accessGrants []string
cmd *cobra.Command
}
func newAgentSharePrivateCommand() *agentSharePrivateCommand {
cmd := &cobra.Command{
Use: "private <target>",
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.headless, "headless", false, "Disable TUI and run headless")
cmd.Flags().BoolVar(&command.insecure, "insecure", false, "Enable insecure TLS certificate validation for <target>")
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 <target>", 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 <target>", 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 <target>", nil)
}
target = args[0]
case "udpTunnel":
if len(args) != 1 {
tui.Error("the 'udpTunnel' backend mode expects a <target>", nil)
}
target = args[0]
case "caddy":
if len(args) != 1 {
tui.Error("the 'caddy' backend mode expects a <target>", 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 <target>", 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 <target>", 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 <target>", 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.PrivateShare(context.Background(), &agentGrpc.PrivateShareRequest{
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)
}

View File

@ -27,7 +27,6 @@ func init() {
} }
type sharePrivateCommand struct { type sharePrivateCommand struct {
basicAuth []string
backendMode string backendMode string
headless bool headless bool
insecure bool insecure bool
@ -43,7 +42,6 @@ func newSharePrivateCommand() *sharePrivateCommand {
Args: cobra.RangeArgs(0, 1), Args: cobra.RangeArgs(0, 1),
} }
command := &sharePrivateCommand{cmd: cmd} command := &sharePrivateCommand{cmd: cmd}
cmd.Flags().StringArrayVar(&command.basicAuth, "basic-auth", []string{}, "Basic authentication users (<username:password>,...")
cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode {proxy, web, tcpTunnel, udpTunnel, caddy, drive, socks, vpn}") cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode {proxy, web, tcpTunnel, udpTunnel, caddy, drive, socks, vpn}")
cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless") 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 <target>") cmd.Flags().BoolVar(&command.insecure, "insecure", false, "Enable insecure TLS certificate validation for <target>")
@ -145,7 +143,6 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
req := &sdk.ShareRequest{ req := &sdk.ShareRequest{
BackendMode: sdk.BackendMode(cmd.backendMode), BackendMode: sdk.BackendMode(cmd.backendMode),
ShareMode: sdk.PrivateShareMode, ShareMode: sdk.PrivateShareMode,
BasicAuth: cmd.basicAuth,
Target: target, Target: target,
} }
if cmd.closed { if cmd.closed {