Merge pull request #756 from openziti/dual_pathed

Dual-pathed CLI Implementation (#751)
This commit is contained in:
Michael Quigley 2024-09-25 16:12:24 -04:00 committed by GitHub
commit 73b32031ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 515 additions and 578 deletions

View File

@ -4,7 +4,9 @@
MAJOR RELEASE: zrok reaches version 1.0.0!
FEATURE: New "zrok Agent", a background manager process for your zrok environments, which allows you to easily manage and work with multiple `zrok share` and `zrok access` processes (https://github.com/openziti/zrok/issues/463)
FEATURE: New "zrok Agent", a background manager process for your zrok environments, which allows you to easily manage and work with multiple `zrok share` and `zrok access` processes. New `--subordinate` flag added to `zrok share [public|private|reserved]` and `zrok access private` to operate in a mode that allows an Agent to manage shares and accesses (https://github.com/openziti/zrok/issues/463)
FEATURE: `zrok share [public|private|reserved]` and `zrok access private` now auto-detect if the zrok Agent is running in an environment and will automatically service share and access requests through the Agent, rather than in-process if the Agent is running. If the Agent is not running, operation remains as it was in `v0.4.x` and the share or access is handled in-process. New `--force-agent` and `--force-local` flags exist to skip Agent detection and manually select an operating mode (https://github.com/openziti/zrok/issues/751)
## v0.4.41

View File

@ -22,14 +22,14 @@ type access struct {
bootComplete chan struct{}
bootErr error
a *Agent
agent *Agent
}
func (a *access) monitor() {
if err := proctree.WaitChild(a.process); err != nil {
pfxlog.ChannelLogger(a.token).Error(err)
}
a.a.outAccesses <- a
a.agent.rmAccess <- a
}
func (a *access) tail(data []byte) {

View File

@ -20,13 +20,13 @@ func (i *agentGrpcImpl) AccessPrivate(_ context.Context, req *agentGrpc.AccessPr
return nil, errors.New("unable to load environment; did you 'zrok enable'?")
}
accCmd := []string{os.Args[0], "access", "private", "--agent", "-b", req.BindAddress, req.Token}
accCmd := []string{os.Args[0], "access", "private", "--subordinate", "-b", req.BindAddress, req.Token}
acc := &access{
token: req.Token,
bindAddress: req.BindAddress,
responseHeaders: req.ResponseHeaders,
bootComplete: make(chan struct{}),
a: i.a,
agent: i.agent,
}
logrus.Infof("executing '%v'", accCmd)
@ -40,7 +40,7 @@ func (i *agentGrpcImpl) AccessPrivate(_ context.Context, req *agentGrpc.AccessPr
<-acc.bootComplete
if acc.bootErr == nil {
i.a.inAccesses <- acc
i.agent.addAccess <- acc
return &agentGrpc.AccessPrivateResponse{FrontendToken: acc.frontendToken}, nil
}

View File

@ -4,6 +4,7 @@ import (
"github.com/openziti/zrok/agent/agentGrpc"
"github.com/openziti/zrok/agent/proctree"
"github.com/openziti/zrok/environment/env_core"
"github.com/openziti/zrok/sdk/golang/sdk"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"google.golang.org/grpc"
@ -15,11 +16,11 @@ type Agent struct {
root env_core.Root
agentSocket string
shares map[string]*share
inShares chan *share
outShares chan *share
addShare chan *share
rmShare chan *share
accesses map[string]*access
inAccesses chan *access
outAccesses chan *access
addAccess chan *access
rmAccess chan *access
}
func NewAgent(root env_core.Root) (*Agent, error) {
@ -29,11 +30,11 @@ func NewAgent(root env_core.Root) (*Agent, error) {
return &Agent{
root: root,
shares: make(map[string]*share),
inShares: make(chan *share),
outShares: make(chan *share),
addShare: make(chan *share),
rmShare: make(chan *share),
accesses: make(map[string]*access),
inAccesses: make(chan *access),
outAccesses: make(chan *access),
addAccess: make(chan *access),
rmAccess: make(chan *access),
}, nil
}
@ -56,7 +57,7 @@ func (a *Agent) Run() error {
a.agentSocket = agentSocket
srv := grpc.NewServer()
agentGrpc.RegisterAgentServer(srv, &agentGrpcImpl{a: a})
agentGrpc.RegisterAgentServer(srv, &agentGrpcImpl{agent: a})
if err := srv.Serve(l); err != nil {
return err
}
@ -72,11 +73,11 @@ func (a *Agent) Shutdown() {
}
for _, shr := range a.shares {
logrus.Debugf("stopping share '%v'", shr.token)
a.outShares <- shr
a.rmShare <- shr
}
for _, acc := range a.accesses {
logrus.Debugf("stopping access '%v'", acc.token)
a.outAccesses <- acc
a.rmAccess <- acc
}
}
@ -86,38 +87,46 @@ func (a *Agent) manager() {
for {
select {
case inShare := <-a.inShares:
case inShare := <-a.addShare:
logrus.Infof("adding new share '%v'", inShare.token)
a.shares[inShare.token] = inShare
case outShare := <-a.outShares:
if outShare.token != "" {
logrus.Infof("removing share '%v'", outShare.token)
if err := proctree.StopChild(outShare.process); err != nil {
logrus.Errorf("error stopping share '%v': %v", outShare.token, err)
case outShare := <-a.rmShare:
if shr, found := a.shares[outShare.token]; found {
logrus.Infof("removing share '%v'", shr.token)
if err := proctree.StopChild(shr.process); err != nil {
logrus.Errorf("error stopping share '%v': %v", shr.token, err)
}
if err := proctree.WaitChild(outShare.process); err != nil {
logrus.Errorf("error joining share '%v': %v", outShare.token, err)
if err := proctree.WaitChild(shr.process); err != nil {
logrus.Errorf("error joining share '%v': %v", shr.token, err)
}
delete(a.shares, outShare.token)
if !shr.reserved {
if err := a.deleteShare(shr.token); err != nil {
logrus.Errorf("error deleting share '%v': %v", shr.token, err)
}
}
delete(a.shares, shr.token)
} else {
logrus.Debug("skipping unidentified (orphaned) share removal")
}
case inAccess := <-a.inAccesses:
case inAccess := <-a.addAccess:
logrus.Infof("adding new access '%v'", inAccess.frontendToken)
a.accesses[inAccess.frontendToken] = inAccess
case outAccess := <-a.outAccesses:
if outAccess.frontendToken != "" {
logrus.Infof("removing access '%v'", outAccess.frontendToken)
if err := proctree.StopChild(outAccess.process); err != nil {
logrus.Errorf("error stopping access '%v': %v", outAccess.frontendToken, err)
case outAccess := <-a.rmAccess:
if acc, found := a.accesses[outAccess.frontendToken]; found {
logrus.Infof("removing access '%v'", acc.frontendToken)
if err := proctree.StopChild(acc.process); err != nil {
logrus.Errorf("error stopping access '%v': %v", acc.frontendToken, err)
}
if err := proctree.WaitChild(outAccess.process); err != nil {
logrus.Errorf("error joining access '%v': %v", outAccess.frontendToken, err)
if err := proctree.WaitChild(acc.process); err != nil {
logrus.Errorf("error joining access '%v': %v", acc.frontendToken, err)
}
delete(a.accesses, outAccess.frontendToken)
if err := a.deleteAccess(acc.token, acc.frontendToken); err != nil {
logrus.Errorf("error deleting access '%v': %v", acc.frontendToken, err)
}
delete(a.accesses, acc.frontendToken)
} else {
logrus.Debug("skipping unidentified (orphaned) access removal")
}
@ -125,7 +134,23 @@ func (a *Agent) manager() {
}
}
func (a *Agent) deleteShare(token string) error {
logrus.Debugf("deleting share '%v'", token)
if err := sdk.DeleteShare(a.root, &sdk.Share{Token: token}); err != nil {
return err
}
return nil
}
func (a *Agent) deleteAccess(token, frontendToken string) error {
logrus.Debugf("deleting access '%v'", frontendToken)
if err := sdk.DeleteAccess(a.root, &sdk.Access{Token: frontendToken, ShareToken: token}); err != nil {
return err
}
return nil
}
type agentGrpcImpl struct {
agentGrpc.UnimplementedAgentServer
a *Agent
agent *Agent
}

View File

@ -3,18 +3,20 @@ package agentClient
import (
"context"
"github.com/openziti/zrok/agent/agentGrpc"
"github.com/openziti/zrok/build"
"github.com/openziti/zrok/environment/env_core"
"github.com/openziti/zrok/tui"
"github.com/pkg/errors"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/resolver"
"net"
"strings"
)
func NewClient(root env_core.Root) (client agentGrpc.AgentClient, conn *grpc.ClientConn, err error) {
agentSocket, err := root.AgentSocket()
if err != nil {
tui.Error("error getting agent socket", err)
return nil, nil, err
}
opts := []grpc.DialOption{
@ -26,8 +28,24 @@ func NewClient(root env_core.Root) (client agentGrpc.AgentClient, conn *grpc.Cli
resolver.SetDefaultScheme("passthrough")
conn, err = grpc.NewClient(agentSocket, opts...)
if err != nil {
tui.Error("error connecting to agent socket", err)
return nil, nil, err
}
return agentGrpc.NewAgentClient(conn), conn, nil
}
func IsAgentRunning(root env_core.Root) (bool, error) {
client, conn, err := NewClient(root)
if err != nil {
return false, err
}
defer func() { _ = conn.Close() }()
resp, err := client.Version(context.Background(), &agentGrpc.VersionRequest{})
if err != nil {
return false, nil
}
if !strings.HasPrefix(resp.GetV(), build.Series) {
return false, errors.Errorf("agent reported version '%v'; we expected version '%v'", resp.GetV(), build.Series)
}
return true, nil
}

View File

@ -3,7 +3,6 @@
package proctree
import (
"github.com/kolesnikovae/go-winjob"
"golang.org/x/sys/windows"
"os/exec"
"sync"

View File

@ -3,25 +3,15 @@ package agent
import (
"context"
"github.com/openziti/zrok/agent/agentGrpc"
"github.com/openziti/zrok/agent/proctree"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
func (i *agentGrpcImpl) ReleaseAccess(_ context.Context, req *agentGrpc.ReleaseAccessRequest) (*agentGrpc.ReleaseAccessResponse, error) {
if acc, found := i.a.accesses[req.FrontendToken]; found {
logrus.Infof("stopping access '%v'", acc.frontendToken)
if err := proctree.StopChild(acc.process); err != nil {
logrus.Error(err)
}
if err := proctree.WaitChild(acc.process); err != nil {
logrus.Error(err)
}
delete(i.a.accesses, acc.frontendToken)
if acc, found := i.agent.accesses[req.FrontendToken]; found {
i.agent.rmAccess <- acc
logrus.Infof("released access '%v'", acc.frontendToken)
} else {
return nil, errors.Errorf("agent has no access with frontend token '%v'", req.FrontendToken)
}

View File

@ -3,25 +3,15 @@ package agent
import (
"context"
"github.com/openziti/zrok/agent/agentGrpc"
"github.com/openziti/zrok/agent/proctree"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
func (i *agentGrpcImpl) ReleaseShare(_ context.Context, req *agentGrpc.ReleaseShareRequest) (*agentGrpc.ReleaseShareResponse, error) {
if shr, found := i.a.shares[req.Token]; found {
logrus.Infof("stopping share '%v'", shr.token)
if err := proctree.StopChild(shr.process); err != nil {
logrus.Error(err)
}
if err := proctree.WaitChild(shr.process); err != nil {
logrus.Error(err)
}
delete(i.a.shares, shr.token)
if shr, found := i.agent.shares[req.Token]; found {
i.agent.rmShare <- shr
logrus.Infof("released share '%v'", shr.token)
} else {
return nil, errors.Errorf("agent has no share with token '%v'", req.Token)
}

View File

@ -34,14 +34,14 @@ type share struct {
bootComplete chan struct{}
bootErr error
a *Agent
agent *Agent
}
func (s *share) monitor() {
if err := proctree.WaitChild(s.process); err != nil {
pfxlog.ChannelLogger(s.token).Error(err)
}
s.a.outShares <- s
s.agent.rmShare <- s
}
func (s *share) tail(data []byte) {

View File

@ -21,12 +21,12 @@ func (i *agentGrpcImpl) SharePrivate(_ context.Context, req *agentGrpc.SharePriv
return nil, errors.New("unable to load environment; did you 'zrok enable'?")
}
shrCmd := []string{os.Args[0], "share", "private", "--agent", "-b", req.BackendMode}
shrCmd := []string{os.Args[0], "share", "private", "--subordinate", "-b", req.BackendMode}
shr := &share{
shareMode: sdk.PrivateShareMode,
backendMode: sdk.BackendMode(req.BackendMode),
bootComplete: make(chan struct{}),
a: i.a,
agent: i.agent,
}
if req.Insecure {
@ -58,7 +58,7 @@ func (i *agentGrpcImpl) SharePrivate(_ context.Context, req *agentGrpc.SharePriv
<-shr.bootComplete
if shr.bootErr == nil {
i.a.inShares <- shr
i.agent.addShare <- shr
return &agentGrpc.SharePrivateResponse{Token: shr.token}, nil
}

View File

@ -21,12 +21,12 @@ func (i *agentGrpcImpl) SharePublic(_ context.Context, req *agentGrpc.SharePubli
return nil, errors.New("unable to load environment; did you 'zrok enable'?")
}
shrCmd := []string{os.Args[0], "share", "public", "--agent", "-b", req.BackendMode}
shrCmd := []string{os.Args[0], "share", "public", "--subordinate", "-b", req.BackendMode}
shr := &share{
shareMode: sdk.PublicShareMode,
backendMode: sdk.BackendMode(req.BackendMode),
bootComplete: make(chan struct{}),
a: i.a,
agent: i.agent,
}
for _, basicAuth := range req.BasicAuth {
@ -82,7 +82,7 @@ func (i *agentGrpcImpl) SharePublic(_ context.Context, req *agentGrpc.SharePubli
<-shr.bootComplete
if shr.bootErr == nil {
i.a.inShares <- shr
i.agent.addShare <- shr
return &agentGrpc.SharePublicResponse{
Token: shr.token,
FrontendEndpoints: shr.frontendEndpoints,

View File

@ -19,11 +19,11 @@ func (i *agentGrpcImpl) ShareReserved(_ context.Context, req *agentGrpc.ShareRes
return nil, errors.New("unable to load environment; did you 'zrok enable'?")
}
shrCmd := []string{os.Args[0], "share", "reserved", "--agent"}
shrCmd := []string{os.Args[0], "share", "reserved", "--subordinate"}
shr := &share{
reserved: true,
bootComplete: make(chan struct{}),
a: i.a,
agent: i.agent,
}
if req.OverrideEndpoint != "" {
@ -47,7 +47,7 @@ func (i *agentGrpcImpl) ShareReserved(_ context.Context, req *agentGrpc.ShareRes
<-shr.bootComplete
if shr.bootErr == nil {
i.a.inShares <- shr
i.agent.addShare <- shr
return &agentGrpc.ShareReservedResponse{
Token: shr.token,
BackendMode: string(shr.backendMode),

View File

@ -7,7 +7,7 @@ import (
func (i *agentGrpcImpl) Status(_ context.Context, _ *agentGrpc.StatusRequest) (*agentGrpc.StatusResponse, error) {
var accesses []*agentGrpc.AccessDetail
for feToken, acc := range i.a.accesses {
for feToken, acc := range i.agent.accesses {
accesses = append(accesses, &agentGrpc.AccessDetail{
FrontendToken: feToken,
Token: acc.token,
@ -17,7 +17,7 @@ func (i *agentGrpcImpl) Status(_ context.Context, _ *agentGrpc.StatusRequest) (*
}
var shares []*agentGrpc.ShareDetail
for token, shr := range i.a.shares {
for token, shr := range i.agent.shares {
shares = append(shares, &agentGrpc.ShareDetail{
Token: token,
ShareMode: string(shr.shareMode),

View File

@ -9,6 +9,6 @@ import (
func (i *agentGrpcImpl) Version(_ context.Context, _ *agentGrpc.VersionRequest) (*agentGrpc.VersionResponse, error) {
v := build.String()
logrus.Infof("responding to version inquiry with '%v'", v)
logrus.Debugf("responding to version inquiry with '%v'", v)
return &agentGrpc.VersionResponse{V: v}, nil
}

View File

@ -1,17 +1,21 @@
package main
import (
"context"
"encoding/json"
"fmt"
tea "github.com/charmbracelet/bubbletea"
"github.com/go-openapi/runtime"
httptransport "github.com/go-openapi/runtime/client"
"github.com/openziti/zrok/agent/agentClient"
"github.com/openziti/zrok/agent/agentGrpc"
"github.com/openziti/zrok/endpoints"
"github.com/openziti/zrok/endpoints/proxy"
"github.com/openziti/zrok/endpoints/tcpTunnel"
"github.com/openziti/zrok/endpoints/udpTunnel"
"github.com/openziti/zrok/endpoints/vpn"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/environment/env_core"
"github.com/openziti/zrok/rest_client_zrok"
"github.com/openziti/zrok/rest_client_zrok/share"
"github.com/openziti/zrok/rest_model_zrok"
@ -32,7 +36,9 @@ func init() {
type accessPrivateCommand struct {
bindAddress string
headless bool
agent bool
subordinate bool
forceLocal bool
forceAgent bool
responseHeaders []string
cmd *cobra.Command
}
@ -45,8 +51,11 @@ func newAccessPrivateCommand() *accessPrivateCommand {
}
command := &accessPrivateCommand{cmd: cmd}
cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless")
cmd.Flags().BoolVar(&command.agent, "agent", false, "Enable agent mode")
cmd.MarkFlagsMutuallyExclusive("headless", "agent")
cmd.Flags().BoolVar(&command.subordinate, "subordinate", false, "Enable subordinate mode")
cmd.MarkFlagsMutuallyExclusive("headless", "subordinate")
cmd.Flags().BoolVar(&command.forceLocal, "force-local", false, "Skip agent detection and force local mode")
cmd.Flags().BoolVar(&command.forceAgent, "force-agent", false, "Skip agent detection and force agent mode")
cmd.MarkFlagsMutuallyExclusive("force-local", "force-agent")
cmd.Flags().StringVarP(&command.bindAddress, "bind", "b", "127.0.0.1:9191", "The address to bind the private frontend")
cmd.Flags().StringArrayVar(&command.responseHeaders, "response-header", []string{}, "Add a response header ('key:value')")
cmd.Run = command.run
@ -54,18 +63,40 @@ func newAccessPrivateCommand() *accessPrivateCommand {
}
func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
shrToken := args[0]
env, err := environment.LoadRoot()
root, err := environment.LoadRoot()
if err != nil {
if !panicInstead {
tui.Error("error loading environment", err)
}
panic(err)
}
if !env.IsEnabled() {
if !root.IsEnabled() {
tui.Error("unable to load environment; did you 'zrok enable'?", nil)
}
zrok, err := env.Client()
if cmd.subordinate || cmd.forceLocal {
cmd.accessLocal(args, root)
} else {
agent := cmd.forceAgent
if !cmd.forceAgent {
agent, err = agentClient.IsAgentRunning(root)
if err != nil {
tui.Error("error checking if agent is running", err)
}
}
if agent {
cmd.accessAgent(args, root)
} else {
cmd.accessLocal(args, root)
}
}
}
func (cmd *accessPrivateCommand) accessLocal(args []string, root env_core.Root) {
shrToken := args[0]
zrok, err := root.Client()
if err != nil {
if !panicInstead {
tui.Error("unable to create zrok client", err)
@ -73,11 +104,11 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
panic(err)
}
auth := httptransport.APIKeyAuth("X-TOKEN", "header", env.Environment().Token)
auth := httptransport.APIKeyAuth("X-TOKEN", "header", root.Environment().Token)
req := share.NewAccessParams()
req.Body = &rest_model_zrok.AccessRequest{
ShrToken: shrToken,
EnvZID: env.Environment().ZitiIdentity,
EnvZID: root.Environment().ZitiIdentity,
}
accessResp, err := zrok.Share.Access(req, auth)
if err != nil {
@ -87,7 +118,7 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
panic(err)
}
if cmd.agent {
if cmd.subordinate {
data := make(map[string]interface{})
data["frontend_token"] = accessResp.Payload.FrontendToken
data["bind_address"] = cmd.bindAddress
@ -121,7 +152,7 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
case "tcpTunnel":
fe, err := tcpTunnel.NewFrontend(&tcpTunnel.FrontendConfig{
BindAddress: cmd.bindAddress,
IdentityName: env.EnvironmentIdentityName(),
IdentityName: root.EnvironmentIdentityName(),
ShrToken: args[0],
RequestsChan: requests,
})
@ -143,7 +174,7 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
case "udpTunnel":
fe, err := udpTunnel.NewFrontend(&udpTunnel.FrontendConfig{
BindAddress: cmd.bindAddress,
IdentityName: env.EnvironmentIdentityName(),
IdentityName: root.EnvironmentIdentityName(),
ShrToken: args[0],
RequestsChan: requests,
IdleTime: time.Minute,
@ -166,7 +197,7 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
case "socks":
fe, err := tcpTunnel.NewFrontend(&tcpTunnel.FrontendConfig{
BindAddress: cmd.bindAddress,
IdentityName: env.EnvironmentIdentityName(),
IdentityName: root.EnvironmentIdentityName(),
ShrToken: args[0],
RequestsChan: requests,
})
@ -190,7 +221,7 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
Scheme: "VPN",
}
fe, err := vpn.NewFrontend(&vpn.FrontendConfig{
IdentityName: env.EnvironmentIdentityName(),
IdentityName: root.EnvironmentIdentityName(),
ShrToken: args[0],
RequestsChan: requests,
})
@ -210,7 +241,7 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
}()
default:
cfg := proxy.DefaultFrontendConfig(env.EnvironmentIdentityName())
cfg := proxy.DefaultFrontendConfig(root.EnvironmentIdentityName())
cfg.ShrToken = shrToken
cfg.Address = cmd.bindAddress
cfg.ResponseHeaders = cmd.responseHeaders
@ -232,10 +263,10 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
}
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGHUP, syscall.SIGTERM, syscall.SIGKILL, syscall.SIGQUIT)
go func() {
<-c
cmd.destroy(accessResp.Payload.FrontendToken, env.Environment().ZitiIdentity, shrToken, zrok, auth)
cmd.destroy(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
os.Exit(0)
}()
@ -248,7 +279,7 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
}
}
} else if cmd.agent {
} else if cmd.subordinate {
for {
select {
case req := <-requests:
@ -285,12 +316,12 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
}
close(requests)
cmd.destroy(accessResp.Payload.FrontendToken, env.Environment().ZitiIdentity, shrToken, zrok, auth)
cmd.destroy(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
}
}
func (cmd *accessPrivateCommand) destroy(frontendName, envZId, shrToken string, zrok *rest_client_zrok.Zrok, auth runtime.ClientAuthInfoWriter) {
logrus.Debugf("shutting down '%v'", shrToken)
logrus.Infof("shutting down '%v'", shrToken)
req := share.NewUnaccessParams()
req.Body = &rest_model_zrok.UnaccessRequest{
FrontendToken: frontendName,
@ -303,3 +334,22 @@ func (cmd *accessPrivateCommand) destroy(frontendName, envZId, shrToken string,
logrus.Errorf("error shutting down: %v", err)
}
}
func (cmd *accessPrivateCommand) accessAgent(args []string, root env_core.Root) {
client, conn, err := agentClient.NewClient(root)
if err != nil {
tui.Error("error connecting to agent", err)
}
defer func() { _ = conn.Close() }()
acc, err := client.AccessPrivate(context.Background(), &agentGrpc.AccessPrivateRequest{
Token: args[0],
BindAddress: cmd.bindAddress,
ResponseHeaders: cmd.responseHeaders,
})
if err != nil {
tui.Error("error creating access", err)
}
fmt.Println(acc)
}

View File

@ -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() {
agentAccessCmd.AddCommand(newAgentAccessPrivateCommand().cmd)
}
type agentAccessPrivateCommand struct {
bindAddress string
responseHeaders []string
cmd *cobra.Command
}
func newAgentAccessPrivateCommand() *agentAccessPrivateCommand {
cmd := &cobra.Command{
Use: "private <token>",
Short: "Bind a private access in the zrok Agent",
Args: cobra.ExactArgs(1),
}
command := &agentAccessPrivateCommand{cmd: cmd}
cmd.Flags().StringVarP(&command.bindAddress, "bind", "b", "127.0.0.1:9191", "The address to bind the private frontend")
cmd.Flags().StringArrayVar(&command.responseHeaders, "response-header", []string{}, "Add a response header ('key:value')")
cmd.Run = command.run
return command
}
func (cmd *agentAccessPrivateCommand) 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()
acc, err := client.AccessPrivate(context.Background(), &agentGrpc.AccessPrivateRequest{
Token: args[0],
BindAddress: cmd.bindAddress,
ResponseHeaders: cmd.responseHeaders,
})
if err != nil {
tui.Error("error creating access", err)
}
fmt.Println(acc)
}

View File

@ -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 <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.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.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)
}

View File

@ -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 <target>",
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 <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.Flags().StringArrayVar(&command.basicAuth, "basic-auth", []string{}, "Basic authentication users (<username:password>,...)")
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)
}

View File

@ -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 <token>",
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)
}

View File

@ -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"
)
@ -30,7 +34,9 @@ func init() {
type sharePrivateCommand struct {
backendMode string
headless bool
agent bool
subordinate bool
forceLocal bool
forceAgent bool
insecure bool
closed bool
accessGrants []string
@ -46,8 +52,11 @@ func newSharePrivateCommand() *sharePrivateCommand {
command := &sharePrivateCommand{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.agent, "agent", false, "Enable agent mode")
cmd.MarkFlagsMutuallyExclusive("headless", "agent")
cmd.Flags().BoolVar(&command.subordinate, "subordinate", false, "Enable agent mode")
cmd.MarkFlagsMutuallyExclusive("headless", "subordinate")
cmd.Flags().BoolVar(&command.forceLocal, "force-local", false, "Skip agent detection and force local mode")
cmd.Flags().BoolVar(&command.forceAgent, "force-agent", false, "Skip agent detection and force agent mode")
cmd.MarkFlagsMutuallyExclusive("force-local", "force-agent")
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)")
@ -56,6 +65,37 @@ 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.subordinate || cmd.forceLocal {
cmd.shareLocal(args, root)
} else {
agent := cmd.forceAgent
if !cmd.forceAgent {
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 {
@ -161,7 +201,7 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
panic(err)
}
if cmd.agent {
if cmd.subordinate {
data := make(map[string]interface{})
data["token"] = shr.Token
data["frontend_endpoints"] = shr.FrontendEndpoints
@ -174,7 +214,7 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
shareDescription := fmt.Sprintf("access your share with: %v", tui.Code.Render(fmt.Sprintf("zrok access private %v", shr.Token)))
mdl := newShareModel(shr.Token, []string{shareDescription}, sdk.PrivateShareMode, sdk.BackendMode(cmd.backendMode))
if !cmd.headless && !cmd.agent {
if !cmd.headless && !cmd.subordinate {
proxy.SetCaddyLoggingWriter(mdl)
}
@ -378,7 +418,7 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
}
}
} else if cmd.agent {
} else if cmd.subordinate {
for {
select {
case req := <-requests:
@ -424,3 +464,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 <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)
}
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)
}

View File

@ -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"
@ -30,7 +34,9 @@ type sharePublicCommand struct {
frontendSelection []string
backendMode string
headless bool
agent bool
subordinate bool
forceLocal bool
forceAgent bool
insecure bool
oauthProvider string
oauthEmailAddressPatterns []string
@ -55,8 +61,11 @@ func newSharePublicCommand() *sharePublicCommand {
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.agent, "agent", false, "Enable agent mode")
cmd.MarkFlagsMutuallyExclusive("headless", "agent")
cmd.Flags().BoolVar(&command.subordinate, "subordinate", false, "Enable agent mode")
cmd.MarkFlagsMutuallyExclusive("headless", "subordinate")
cmd.Flags().BoolVar(&command.forceLocal, "force-local", false, "Skip agent detection and force local mode")
cmd.Flags().BoolVar(&command.forceAgent, "force-agent", false, "Skip agent detection and force agent mode")
cmd.MarkFlagsMutuallyExclusive("force-local", "force-agent")
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)")
@ -71,6 +80,37 @@ 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.subordinate || cmd.forceLocal {
cmd.shareLocal(args, root)
} else {
agent := cmd.forceAgent
if !cmd.forceAgent {
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 +138,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 {
@ -152,7 +180,7 @@ func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) {
panic(err)
}
if cmd.agent {
if cmd.subordinate {
data := make(map[string]interface{})
data["token"] = shr.Token
data["frontend_endpoints"] = shr.FrontendEndpoints
@ -164,7 +192,7 @@ func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) {
}
mdl := newShareModel(shr.Token, shr.FrontendEndpoints, sdk.PublicShareMode, sdk.BackendMode(cmd.backendMode))
if !cmd.headless && !cmd.agent {
if !cmd.headless && !cmd.subordinate {
proxy.SetCaddyLoggingWriter(mdl)
}
@ -281,7 +309,7 @@ func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) {
}
}
} else if cmd.agent {
} else if cmd.subordinate {
for {
select {
case req := <-requests:
@ -327,3 +355,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)
}

View File

@ -1,10 +1,13 @@
package main
import (
"context"
"encoding/json"
"fmt"
tea "github.com/charmbracelet/bubbletea"
httptransport "github.com/go-openapi/runtime/client"
"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"
@ -13,6 +16,7 @@ import (
"github.com/openziti/zrok/endpoints/udpTunnel"
"github.com/openziti/zrok/endpoints/vpn"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/environment/env_core"
"github.com/openziti/zrok/rest_client_zrok/metadata"
"github.com/openziti/zrok/rest_client_zrok/share"
"github.com/openziti/zrok/rest_model_zrok"
@ -29,7 +33,9 @@ func init() {
type shareReservedCommand struct {
overrideEndpoint string
headless bool
agent bool
subordinate bool
forceLocal bool
forceAgent bool
insecure bool
cmd *cobra.Command
}
@ -43,17 +49,17 @@ func newShareReservedCommand() *shareReservedCommand {
command := &shareReservedCommand{cmd: cmd}
cmd.Flags().StringVar(&command.overrideEndpoint, "override-endpoint", "", "Override the stored target endpoint with a replacement")
cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless")
cmd.Flags().BoolVar(&command.agent, "agent", false, "Enable agent mode")
cmd.MarkFlagsMutuallyExclusive("headless", "agent")
cmd.Flags().BoolVar(&command.subordinate, "subordinate", false, "Enable agent mode")
cmd.MarkFlagsMutuallyExclusive("headless", "subordinate")
cmd.Flags().BoolVar(&command.forceLocal, "force-local", false, "Skip agent detection and force local mode")
cmd.Flags().BoolVar(&command.forceAgent, "force-agent", false, "Skip agent detection and force agent mode")
cmd.MarkFlagsMutuallyExclusive("force-local", "force-agent")
cmd.Flags().BoolVar(&command.insecure, "insecure", false, "Enable insecure TLS certificate validation")
cmd.Run = command.run
return command
}
func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
shrToken := args[0]
var target string
root, err := environment.LoadRoot()
if err != nil {
if !panicInstead {
@ -66,6 +72,28 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
tui.Error("unable to load environment; did you 'zrok enable'?", nil)
}
if cmd.subordinate || cmd.forceLocal {
cmd.shareLocal(args, root)
} else {
agent := cmd.forceAgent
if !cmd.forceAgent {
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 *shareReservedCommand) shareLocal(args []string, root env_core.Root) {
shrToken := args[0]
var target string
zrok, err := root.Client()
if err != nil {
if !panicInstead {
@ -100,7 +128,7 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
}
if resp.Payload.BackendMode != "socks" {
if !cmd.agent {
if !cmd.subordinate {
logrus.Infof("sharing target: '%v'", target)
}
@ -116,11 +144,11 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
}
panic(err)
}
if !cmd.agent {
if !cmd.subordinate {
logrus.Infof("updated backend target to: %v", target)
}
} else {
if !cmd.agent {
if !cmd.subordinate {
logrus.Infof("using existing backend target: %v", target)
}
}
@ -134,7 +162,7 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
shareDescription = fmt.Sprintf("access your share with: %v", tui.Code.Render(fmt.Sprintf("zrok access private %v", shrToken)))
}
if cmd.agent {
if cmd.subordinate {
data := make(map[string]interface{})
data["token"] = resp.Payload.Token
data["backend_mode"] = resp.Payload.BackendMode
@ -153,7 +181,7 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
}
mdl := newShareModel(shrToken, []string{shareDescription}, sdk.ShareMode(resp.Payload.ShareMode), sdk.BackendMode(resp.Payload.BackendMode))
if !cmd.headless && !cmd.agent {
if !cmd.headless && !cmd.subordinate {
proxy.SetCaddyLoggingWriter(mdl)
}
@ -353,7 +381,7 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
}
}
} else if cmd.agent {
} else if cmd.subordinate {
for {
select {
case req := <-requests:
@ -390,3 +418,24 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
close(requests)
}
}
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 func() { _ = 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)
}