mirror of
https://github.com/openziti/zrok.git
synced 2024-12-22 23:02:52 +01:00
commit
5af4aa6a8c
@ -4,6 +4,8 @@
|
||||
|
||||
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)
|
||||
|
||||
## v0.4.41
|
||||
|
||||
FIX: Fixed crash when invoking `zrok share reserved` with no arguments (https://github.com/openziti/zrok/issues/740)
|
||||
|
76
agent/access.go
Normal file
76
agent/access.go
Normal file
@ -0,0 +1,76 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/michaelquigley/pfxlog"
|
||||
"github.com/openziti/zrok/agent/proctree"
|
||||
"github.com/sirupsen/logrus"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type access struct {
|
||||
frontendToken string
|
||||
token string
|
||||
bindAddress string
|
||||
responseHeaders []string
|
||||
|
||||
process *proctree.Child
|
||||
readBuffer bytes.Buffer
|
||||
booted bool
|
||||
bootComplete chan struct{}
|
||||
bootErr error
|
||||
|
||||
a *Agent
|
||||
}
|
||||
|
||||
func (a *access) monitor() {
|
||||
if err := proctree.WaitChild(a.process); err != nil {
|
||||
pfxlog.ChannelLogger(a.token).Error(err)
|
||||
}
|
||||
a.a.outAccesses <- a
|
||||
}
|
||||
|
||||
func (a *access) tail(data []byte) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
logrus.Errorf("recovering: %v", r)
|
||||
}
|
||||
}()
|
||||
a.readBuffer.Write(data)
|
||||
if line, err := a.readBuffer.ReadString('\n'); err == nil {
|
||||
line = strings.Trim(line, "\n")
|
||||
if !a.booted {
|
||||
in := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(line), &in); err == nil {
|
||||
if v, found := in["frontend_token"]; found {
|
||||
if str, ok := v.(string); ok {
|
||||
a.frontendToken = str
|
||||
}
|
||||
}
|
||||
if v, found := in["bind_address"]; found {
|
||||
if str, ok := v.(string); ok {
|
||||
a.bindAddress = str
|
||||
}
|
||||
}
|
||||
a.booted = true
|
||||
} else {
|
||||
a.bootErr = errors.New(line)
|
||||
}
|
||||
close(a.bootComplete)
|
||||
|
||||
} else {
|
||||
if strings.HasPrefix(line, "{") {
|
||||
in := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(line), &in); err == nil {
|
||||
pfxlog.ChannelLogger(a.token).Info(in)
|
||||
}
|
||||
} else {
|
||||
pfxlog.ChannelLogger(a.token).Info(strings.Trim(line, "\n"))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
a.readBuffer.WriteString(line)
|
||||
}
|
||||
}
|
48
agent/accessPrivate.go
Normal file
48
agent/accessPrivate.go
Normal file
@ -0,0 +1,48 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/agent/proctree"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/sirupsen/logrus"
|
||||
"os"
|
||||
)
|
||||
|
||||
func (i *agentGrpcImpl) AccessPrivate(_ context.Context, req *agentGrpc.AccessPrivateRequest) (*agentGrpc.AccessPrivateResponse, 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'?")
|
||||
}
|
||||
|
||||
accCmd := []string{os.Args[0], "access", "private", "--agent", "-b", req.BindAddress, req.Token}
|
||||
acc := &access{
|
||||
token: req.Token,
|
||||
bindAddress: req.BindAddress,
|
||||
responseHeaders: req.ResponseHeaders,
|
||||
bootComplete: make(chan struct{}),
|
||||
a: i.a,
|
||||
}
|
||||
|
||||
logrus.Infof("executing '%v'", accCmd)
|
||||
|
||||
acc.process, err = proctree.StartChild(acc.tail, accCmd...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go acc.monitor()
|
||||
<-acc.bootComplete
|
||||
|
||||
if acc.bootErr == nil {
|
||||
i.a.inAccesses <- acc
|
||||
return &agentGrpc.AccessPrivateResponse{FrontendToken: acc.frontendToken}, nil
|
||||
}
|
||||
|
||||
return nil, acc.bootErr
|
||||
}
|
131
agent/agent.go
Normal file
131
agent/agent.go
Normal file
@ -0,0 +1,131 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/agent/proctree"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Agent struct {
|
||||
root env_core.Root
|
||||
agentSocket string
|
||||
shares map[string]*share
|
||||
inShares chan *share
|
||||
outShares chan *share
|
||||
accesses map[string]*access
|
||||
inAccesses chan *access
|
||||
outAccesses chan *access
|
||||
}
|
||||
|
||||
func NewAgent(root env_core.Root) (*Agent, error) {
|
||||
if !root.IsEnabled() {
|
||||
return nil, errors.Errorf("unable to load environment; did you 'zrok enable'?")
|
||||
}
|
||||
return &Agent{
|
||||
root: root,
|
||||
shares: make(map[string]*share),
|
||||
inShares: make(chan *share),
|
||||
outShares: make(chan *share),
|
||||
accesses: make(map[string]*access),
|
||||
inAccesses: make(chan *access),
|
||||
outAccesses: make(chan *access),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *Agent) Run() error {
|
||||
logrus.Infof("started")
|
||||
|
||||
if err := proctree.Init("zrok Agent"); err != nil {
|
||||
return err
|
||||
}
|
||||
go a.manager()
|
||||
|
||||
agentSocket, err := a.root.AgentSocket()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l, err := net.Listen("unix", agentSocket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.agentSocket = agentSocket
|
||||
|
||||
srv := grpc.NewServer()
|
||||
agentGrpc.RegisterAgentServer(srv, &agentGrpcImpl{a: a})
|
||||
if err := srv.Serve(l); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Agent) Shutdown() {
|
||||
logrus.Infof("stopping")
|
||||
|
||||
if err := os.Remove(a.agentSocket); err != nil {
|
||||
logrus.Warnf("unable to remove agent socket: %v", err)
|
||||
}
|
||||
for _, shr := range a.shares {
|
||||
logrus.Debugf("stopping share '%v'", shr.token)
|
||||
a.outShares <- shr
|
||||
}
|
||||
for _, acc := range a.accesses {
|
||||
logrus.Debugf("stopping access '%v'", acc.token)
|
||||
a.outAccesses <- acc
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) manager() {
|
||||
logrus.Info("started")
|
||||
defer logrus.Warn("exited")
|
||||
|
||||
for {
|
||||
select {
|
||||
case inShare := <-a.inShares:
|
||||
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)
|
||||
}
|
||||
if err := proctree.WaitChild(outShare.process); err != nil {
|
||||
logrus.Errorf("error joining share '%v': %v", outShare.token, err)
|
||||
}
|
||||
delete(a.shares, outShare.token)
|
||||
} else {
|
||||
logrus.Debug("skipping unidentified (orphaned) share removal")
|
||||
}
|
||||
|
||||
case inAccess := <-a.inAccesses:
|
||||
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)
|
||||
}
|
||||
if err := proctree.WaitChild(outAccess.process); err != nil {
|
||||
logrus.Errorf("error joining access '%v': %v", outAccess.frontendToken, err)
|
||||
}
|
||||
delete(a.accesses, outAccess.frontendToken)
|
||||
} else {
|
||||
logrus.Debug("skipping unidentified (orphaned) access removal")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type agentGrpcImpl struct {
|
||||
agentGrpc.UnimplementedAgentServer
|
||||
a *Agent
|
||||
}
|
33
agent/agentClient/agentClient.go
Normal file
33
agent/agentClient/agentClient.go
Normal file
@ -0,0 +1,33 @@
|
||||
package agentClient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"net"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
opts := []grpc.DialOption{
|
||||
grpc.WithContextDialer(func(_ context.Context, addr string) (net.Conn, error) {
|
||||
return net.Dial("unix", addr)
|
||||
}),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
}
|
||||
resolver.SetDefaultScheme("passthrough")
|
||||
conn, err = grpc.NewClient(agentSocket, opts...)
|
||||
if err != nil {
|
||||
tui.Error("error connecting to agent socket", err)
|
||||
}
|
||||
|
||||
return agentGrpc.NewAgentClient(conn), conn, nil
|
||||
}
|
1558
agent/agentGrpc/agent.pb.go
Normal file
1558
agent/agentGrpc/agent.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
115
agent/agentGrpc/agent.proto
Normal file
115
agent/agentGrpc/agent.proto
Normal file
@ -0,0 +1,115 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "github.com/openziti/zrok/agent/agentGrpc";
|
||||
|
||||
service Agent {
|
||||
rpc AccessPrivate(AccessPrivateRequest) returns (AccessPrivateResponse) {}
|
||||
rpc ReleaseAccess(ReleaseAccessRequest) returns (ReleaseAccessResponse) {}
|
||||
rpc ReleaseShare(ReleaseShareRequest) returns (ReleaseShareResponse) {}
|
||||
rpc ShareReserved(ShareReservedRequest) returns (ShareReservedResponse) {}
|
||||
rpc SharePrivate(SharePrivateRequest) returns (SharePrivateResponse) {}
|
||||
rpc SharePublic(SharePublicRequest) returns (SharePublicResponse) {}
|
||||
rpc Status(StatusRequest) returns (StatusResponse) {}
|
||||
rpc Version(VersionRequest) returns (VersionResponse) {}
|
||||
}
|
||||
|
||||
message AccessDetail {
|
||||
string frontendToken = 1;
|
||||
string token = 2;
|
||||
string bindAddress = 3;
|
||||
repeated string responseHeaders = 4;
|
||||
}
|
||||
|
||||
message AccessPrivateResponse{
|
||||
string frontendToken = 1;
|
||||
}
|
||||
|
||||
message AccessPrivateRequest{
|
||||
string token = 1;
|
||||
string bindAddress = 2;
|
||||
repeated string responseHeaders = 3;
|
||||
}
|
||||
|
||||
message ReleaseAccessRequest {
|
||||
string frontendToken = 1;
|
||||
}
|
||||
|
||||
message ReleaseAccessResponse {
|
||||
}
|
||||
|
||||
message ReleaseShareRequest {
|
||||
string token = 1;
|
||||
}
|
||||
|
||||
message ReleaseShareResponse {
|
||||
}
|
||||
|
||||
message ShareDetail {
|
||||
string token = 1;
|
||||
string shareMode = 2;
|
||||
string backendMode = 3;
|
||||
bool reserved = 4;
|
||||
repeated string frontendEndpoint = 5;
|
||||
string backendEndpoint = 6;
|
||||
bool closed = 7;
|
||||
string status = 8;
|
||||
}
|
||||
|
||||
message SharePrivateRequest {
|
||||
string target = 1;
|
||||
string backendMode = 2;
|
||||
bool insecure = 3;
|
||||
bool closed = 4;
|
||||
repeated string accessGrants = 5;
|
||||
}
|
||||
|
||||
message SharePrivateResponse {
|
||||
string token = 1;
|
||||
}
|
||||
|
||||
message SharePublicRequest {
|
||||
string target = 1;
|
||||
repeated string basicAuth = 2;
|
||||
repeated string frontendSelection = 3;
|
||||
string backendMode = 4;
|
||||
bool insecure = 5;
|
||||
string oauthProvider = 6;
|
||||
repeated string oauthEmailAddressPatterns = 7;
|
||||
string oauthCheckInterval = 8;
|
||||
bool closed = 9;
|
||||
repeated string accessGrants = 10;
|
||||
}
|
||||
|
||||
message SharePublicResponse {
|
||||
string token = 1;
|
||||
repeated string frontendEndpoints = 2;
|
||||
}
|
||||
|
||||
message ShareReservedRequest {
|
||||
string token = 1;
|
||||
string overrideEndpoint = 2;
|
||||
bool insecure = 3;
|
||||
}
|
||||
|
||||
message ShareReservedResponse {
|
||||
string token = 1;
|
||||
string backendMode = 2;
|
||||
string shareMode = 3;
|
||||
repeated string frontendEndpoints = 4;
|
||||
string target = 5;
|
||||
}
|
||||
|
||||
message StatusRequest {
|
||||
}
|
||||
|
||||
message StatusResponse {
|
||||
repeated AccessDetail accesses = 1;
|
||||
repeated ShareDetail shares = 2;
|
||||
}
|
||||
|
||||
message VersionRequest {
|
||||
}
|
||||
|
||||
message VersionResponse {
|
||||
string v = 1;
|
||||
}
|
387
agent/agentGrpc/agent_grpc.pb.go
Normal file
387
agent/agentGrpc/agent_grpc.pb.go
Normal file
@ -0,0 +1,387 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v5.27.3
|
||||
// source: agent/agentGrpc/agent.proto
|
||||
|
||||
package agentGrpc
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Agent_AccessPrivate_FullMethodName = "/Agent/AccessPrivate"
|
||||
Agent_ReleaseAccess_FullMethodName = "/Agent/ReleaseAccess"
|
||||
Agent_ReleaseShare_FullMethodName = "/Agent/ReleaseShare"
|
||||
Agent_ShareReserved_FullMethodName = "/Agent/ShareReserved"
|
||||
Agent_SharePrivate_FullMethodName = "/Agent/SharePrivate"
|
||||
Agent_SharePublic_FullMethodName = "/Agent/SharePublic"
|
||||
Agent_Status_FullMethodName = "/Agent/Status"
|
||||
Agent_Version_FullMethodName = "/Agent/Version"
|
||||
)
|
||||
|
||||
// AgentClient is the client API for Agent 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.
|
||||
type AgentClient interface {
|
||||
AccessPrivate(ctx context.Context, in *AccessPrivateRequest, opts ...grpc.CallOption) (*AccessPrivateResponse, error)
|
||||
ReleaseAccess(ctx context.Context, in *ReleaseAccessRequest, opts ...grpc.CallOption) (*ReleaseAccessResponse, error)
|
||||
ReleaseShare(ctx context.Context, in *ReleaseShareRequest, opts ...grpc.CallOption) (*ReleaseShareResponse, error)
|
||||
ShareReserved(ctx context.Context, in *ShareReservedRequest, opts ...grpc.CallOption) (*ShareReservedResponse, error)
|
||||
SharePrivate(ctx context.Context, in *SharePrivateRequest, opts ...grpc.CallOption) (*SharePrivateResponse, error)
|
||||
SharePublic(ctx context.Context, in *SharePublicRequest, opts ...grpc.CallOption) (*SharePublicResponse, error)
|
||||
Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error)
|
||||
Version(ctx context.Context, in *VersionRequest, opts ...grpc.CallOption) (*VersionResponse, error)
|
||||
}
|
||||
|
||||
type agentClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewAgentClient(cc grpc.ClientConnInterface) AgentClient {
|
||||
return &agentClient{cc}
|
||||
}
|
||||
|
||||
func (c *agentClient) AccessPrivate(ctx context.Context, in *AccessPrivateRequest, opts ...grpc.CallOption) (*AccessPrivateResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(AccessPrivateResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_AccessPrivate_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *agentClient) ReleaseAccess(ctx context.Context, in *ReleaseAccessRequest, opts ...grpc.CallOption) (*ReleaseAccessResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ReleaseAccessResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_ReleaseAccess_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *agentClient) ReleaseShare(ctx context.Context, in *ReleaseShareRequest, opts ...grpc.CallOption) (*ReleaseShareResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ReleaseShareResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_ReleaseShare_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *agentClient) ShareReserved(ctx context.Context, in *ShareReservedRequest, opts ...grpc.CallOption) (*ShareReservedResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ShareReservedResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_ShareReserved_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *agentClient) SharePrivate(ctx context.Context, in *SharePrivateRequest, opts ...grpc.CallOption) (*SharePrivateResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(SharePrivateResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_SharePrivate_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *agentClient) SharePublic(ctx context.Context, in *SharePublicRequest, opts ...grpc.CallOption) (*SharePublicResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(SharePublicResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_SharePublic_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *agentClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(StatusResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_Status_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *agentClient) Version(ctx context.Context, in *VersionRequest, opts ...grpc.CallOption) (*VersionResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(VersionResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_Version_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// AgentServer is the server API for Agent service.
|
||||
// All implementations must embed UnimplementedAgentServer
|
||||
// for forward compatibility.
|
||||
type AgentServer interface {
|
||||
AccessPrivate(context.Context, *AccessPrivateRequest) (*AccessPrivateResponse, error)
|
||||
ReleaseAccess(context.Context, *ReleaseAccessRequest) (*ReleaseAccessResponse, error)
|
||||
ReleaseShare(context.Context, *ReleaseShareRequest) (*ReleaseShareResponse, error)
|
||||
ShareReserved(context.Context, *ShareReservedRequest) (*ShareReservedResponse, error)
|
||||
SharePrivate(context.Context, *SharePrivateRequest) (*SharePrivateResponse, error)
|
||||
SharePublic(context.Context, *SharePublicRequest) (*SharePublicResponse, error)
|
||||
Status(context.Context, *StatusRequest) (*StatusResponse, error)
|
||||
Version(context.Context, *VersionRequest) (*VersionResponse, error)
|
||||
mustEmbedUnimplementedAgentServer()
|
||||
}
|
||||
|
||||
// UnimplementedAgentServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedAgentServer struct{}
|
||||
|
||||
func (UnimplementedAgentServer) AccessPrivate(context.Context, *AccessPrivateRequest) (*AccessPrivateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AccessPrivate not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) ReleaseAccess(context.Context, *ReleaseAccessRequest) (*ReleaseAccessResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ReleaseAccess not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) ReleaseShare(context.Context, *ReleaseShareRequest) (*ReleaseShareResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ReleaseShare not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) ShareReserved(context.Context, *ShareReservedRequest) (*ShareReservedResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ShareReserved not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) SharePrivate(context.Context, *SharePrivateRequest) (*SharePrivateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SharePrivate not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) SharePublic(context.Context, *SharePublicRequest) (*SharePublicResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SharePublic not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) Status(context.Context, *StatusRequest) (*StatusResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Status not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) Version(context.Context, *VersionRequest) (*VersionResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Version not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) mustEmbedUnimplementedAgentServer() {}
|
||||
func (UnimplementedAgentServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeAgentServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to AgentServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeAgentServer interface {
|
||||
mustEmbedUnimplementedAgentServer()
|
||||
}
|
||||
|
||||
func RegisterAgentServer(s grpc.ServiceRegistrar, srv AgentServer) {
|
||||
// If the following call pancis, it indicates UnimplementedAgentServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&Agent_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _Agent_AccessPrivate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AccessPrivateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).AccessPrivate(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_AccessPrivate_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).AccessPrivate(ctx, req.(*AccessPrivateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Agent_ReleaseAccess_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ReleaseAccessRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).ReleaseAccess(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_ReleaseAccess_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).ReleaseAccess(ctx, req.(*ReleaseAccessRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Agent_ReleaseShare_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ReleaseShareRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).ReleaseShare(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_ReleaseShare_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).ReleaseShare(ctx, req.(*ReleaseShareRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Agent_ShareReserved_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ShareReservedRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).ShareReserved(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_ShareReserved_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).ShareReserved(ctx, req.(*ShareReservedRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Agent_SharePrivate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SharePrivateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).SharePrivate(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_SharePrivate_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).SharePrivate(ctx, req.(*SharePrivateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Agent_SharePublic_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SharePublicRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).SharePublic(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_SharePublic_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).SharePublic(ctx, req.(*SharePublicRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Agent_Status_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(StatusRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).Status(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_Status_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).Status(ctx, req.(*StatusRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Agent_Version_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(VersionRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).Version(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_Version_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).Version(ctx, req.(*VersionRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Agent_ServiceDesc is the grpc.ServiceDesc for Agent service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var Agent_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "Agent",
|
||||
HandlerType: (*AgentServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "AccessPrivate",
|
||||
Handler: _Agent_AccessPrivate_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ReleaseAccess",
|
||||
Handler: _Agent_ReleaseAccess_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ReleaseShare",
|
||||
Handler: _Agent_ReleaseShare_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ShareReserved",
|
||||
Handler: _Agent_ShareReserved_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SharePrivate",
|
||||
Handler: _Agent_SharePrivate_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SharePublic",
|
||||
Handler: _Agent_SharePublic_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Status",
|
||||
Handler: _Agent_Status_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Version",
|
||||
Handler: _Agent_Version_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "agent/agentGrpc/agent.proto",
|
||||
}
|
59
agent/proctree/impl_posix.go
Normal file
59
agent/proctree/impl_posix.go
Normal file
@ -0,0 +1,59 @@
|
||||
//go:build !windows
|
||||
|
||||
package proctree
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func Init(_ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func StartChild(tail TailFunction, args ...string) (*Child, error) {
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
|
||||
cld := &Child{
|
||||
TailFunction: tail,
|
||||
cmd: cmd,
|
||||
outStream: make(chan []byte),
|
||||
errStream: make(chan []byte),
|
||||
wg: new(sync.WaitGroup),
|
||||
}
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cld.wg.Add(3)
|
||||
go reader(stdout, cld.outStream, cld.wg)
|
||||
go reader(stderr, cld.errStream, cld.wg)
|
||||
go cld.combiner(cld.wg)
|
||||
|
||||
return cld, nil
|
||||
}
|
||||
|
||||
func WaitChild(c *Child) error {
|
||||
c.wg.Wait()
|
||||
if err := c.cmd.Wait(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func StopChild(c *Child) error {
|
||||
if err := c.cmd.Process.Kill(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
79
agent/proctree/impl_windows.go
Executable file
79
agent/proctree/impl_windows.go
Executable file
@ -0,0 +1,79 @@
|
||||
//go:build windows
|
||||
|
||||
package proctree
|
||||
|
||||
import (
|
||||
"github.com/kolesnikovae/go-winjob"
|
||||
"golang.org/x/sys/windows"
|
||||
"os/exec"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var job *winjob.JobObject
|
||||
|
||||
func Init(name string) error {
|
||||
var err error
|
||||
if job == nil {
|
||||
job, err = winjob.Create(name, winjob.LimitKillOnJobClose, winjob.LimitBreakawayOK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func StartChild(tail TailFunction, args ...string) (*Child, error) {
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
cmd.SysProcAttr = &windows.SysProcAttr{CreationFlags: windows.CREATE_SUSPENDED}
|
||||
|
||||
cld := &Child{
|
||||
TailFunction: tail,
|
||||
cmd: cmd,
|
||||
outStream: make(chan []byte),
|
||||
errStream: make(chan []byte),
|
||||
wg: new(sync.WaitGroup),
|
||||
}
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := job.Assign(cmd.Process); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := winjob.ResumeProcess(cmd.Process.Pid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cld.wg.Add(3)
|
||||
go reader(stdout, cld.outStream, cld.wg)
|
||||
go reader(stderr, cld.errStream, cld.wg)
|
||||
go cld.combiner(cld.wg)
|
||||
|
||||
return cld, nil
|
||||
}
|
||||
|
||||
func WaitChild(c *Child) error {
|
||||
c.wg.Wait()
|
||||
if err := c.cmd.Wait(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func StopChild(c *Child) error {
|
||||
if err := c.cmd.Process.Kill(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
66
agent/proctree/proctree.go
Executable file
66
agent/proctree/proctree.go
Executable file
@ -0,0 +1,66 @@
|
||||
package proctree
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Child struct {
|
||||
TailFunction TailFunction
|
||||
cmd *exec.Cmd
|
||||
outStream chan []byte
|
||||
errStream chan []byte
|
||||
wg *sync.WaitGroup
|
||||
}
|
||||
|
||||
type TailFunction func(data []byte)
|
||||
|
||||
func (c *Child) combiner(wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
outDone := false
|
||||
errDone := false
|
||||
for {
|
||||
select {
|
||||
case data := <-c.outStream:
|
||||
if data != nil {
|
||||
if c.TailFunction != nil {
|
||||
c.TailFunction(data)
|
||||
}
|
||||
} else {
|
||||
outDone = true
|
||||
}
|
||||
case data := <-c.errStream:
|
||||
if data != nil {
|
||||
if c.TailFunction != nil {
|
||||
c.TailFunction(data)
|
||||
}
|
||||
} else {
|
||||
errDone = true
|
||||
}
|
||||
}
|
||||
if outDone && errDone {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func reader(r io.ReadCloser, o chan []byte, wg *sync.WaitGroup) {
|
||||
defer close(o)
|
||||
defer wg.Done()
|
||||
|
||||
buf := make([]byte, 64*1024)
|
||||
for {
|
||||
n, err := r.Read(buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return
|
||||
}
|
||||
fmt.Printf("error reading: %v", err)
|
||||
return
|
||||
}
|
||||
o <- buf[:n]
|
||||
}
|
||||
}
|
29
agent/releaseAccess.go
Normal file
29
agent/releaseAccess.go
Normal file
@ -0,0 +1,29 @@
|
||||
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)
|
||||
logrus.Infof("released access '%v'", acc.frontendToken)
|
||||
} else {
|
||||
return nil, errors.Errorf("agent has no access with frontend token '%v'", req.FrontendToken)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
29
agent/releaseShare.go
Executable file
29
agent/releaseShare.go
Executable file
@ -0,0 +1,29 @@
|
||||
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)
|
||||
logrus.Infof("released share '%v'", shr.token)
|
||||
} else {
|
||||
return nil, errors.Errorf("agent has no share with token '%v'", req.Token)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
107
agent/share.go
Normal file
107
agent/share.go
Normal file
@ -0,0 +1,107 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/michaelquigley/pfxlog"
|
||||
"github.com/openziti/zrok/agent/proctree"
|
||||
"github.com/openziti/zrok/sdk/golang/sdk"
|
||||
"github.com/sirupsen/logrus"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type share struct {
|
||||
token string
|
||||
frontendEndpoints []string
|
||||
target string
|
||||
basicAuth []string
|
||||
frontendSelection []string
|
||||
shareMode sdk.ShareMode
|
||||
backendMode sdk.BackendMode
|
||||
reserved bool
|
||||
insecure bool
|
||||
oauthProvider string
|
||||
oauthEmailAddressPatterns []string
|
||||
oauthCheckInterval time.Duration
|
||||
closed bool
|
||||
accessGrants []string
|
||||
|
||||
process *proctree.Child
|
||||
readBuffer bytes.Buffer
|
||||
booted bool
|
||||
bootComplete chan struct{}
|
||||
bootErr error
|
||||
|
||||
a *Agent
|
||||
}
|
||||
|
||||
func (s *share) monitor() {
|
||||
if err := proctree.WaitChild(s.process); err != nil {
|
||||
pfxlog.ChannelLogger(s.token).Error(err)
|
||||
}
|
||||
s.a.outShares <- s
|
||||
}
|
||||
|
||||
func (s *share) tail(data []byte) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
logrus.Errorf("recovering: %v", r)
|
||||
}
|
||||
}()
|
||||
s.readBuffer.Write(data)
|
||||
if line, err := s.readBuffer.ReadString('\n'); err == nil {
|
||||
line = strings.Trim(line, "\n")
|
||||
if !s.booted {
|
||||
in := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(line), &in); err == nil {
|
||||
if v, found := in["token"]; found {
|
||||
if str, ok := v.(string); ok {
|
||||
s.token = str
|
||||
}
|
||||
}
|
||||
if v, found := in["backend_mode"]; found {
|
||||
if str, ok := v.(string); ok {
|
||||
s.backendMode = sdk.BackendMode(str)
|
||||
}
|
||||
}
|
||||
if v, found := in["share_mode"]; found {
|
||||
if str, ok := v.(string); ok {
|
||||
s.shareMode = sdk.ShareMode(str)
|
||||
}
|
||||
}
|
||||
if v, found := in["frontend_endpoints"]; found {
|
||||
if vArr, ok := v.([]interface{}); ok {
|
||||
for _, v := range vArr {
|
||||
if str, ok := v.(string); ok {
|
||||
s.frontendEndpoints = append(s.frontendEndpoints, str)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if v, found := in["target"]; found {
|
||||
if str, ok := v.(string); ok {
|
||||
s.target = str
|
||||
}
|
||||
}
|
||||
s.booted = true
|
||||
} else {
|
||||
s.bootErr = errors.New(line)
|
||||
}
|
||||
close(s.bootComplete)
|
||||
|
||||
} else {
|
||||
if strings.HasPrefix(line, "{") {
|
||||
in := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(line), &in); err == nil {
|
||||
pfxlog.ChannelLogger(s.token).Info(in)
|
||||
}
|
||||
} else {
|
||||
pfxlog.ChannelLogger(s.token).Info(strings.Trim(line, "\n"))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s.readBuffer.WriteString(line)
|
||||
}
|
||||
}
|
66
agent/sharePrivate.go
Normal file
66
agent/sharePrivate.go
Normal 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) SharePrivate(_ context.Context, req *agentGrpc.SharePrivateRequest) (*agentGrpc.SharePrivateResponse, 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.SharePrivateResponse{Token: shr.token}, nil
|
||||
}
|
||||
|
||||
return nil, shr.bootErr
|
||||
}
|
93
agent/sharePublic.go
Normal file
93
agent/sharePublic.go
Normal file
@ -0,0 +1,93 @@
|
||||
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) SharePublic(_ context.Context, req *agentGrpc.SharePublicRequest) (*agentGrpc.SharePublicResponse, 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", "public", "--agent", "-b", req.BackendMode}
|
||||
shr := &share{
|
||||
shareMode: sdk.PublicShareMode,
|
||||
backendMode: sdk.BackendMode(req.BackendMode),
|
||||
bootComplete: make(chan struct{}),
|
||||
a: i.a,
|
||||
}
|
||||
|
||||
for _, basicAuth := range req.BasicAuth {
|
||||
shrCmd = append(shrCmd, "--basic-auth", basicAuth)
|
||||
}
|
||||
shr.basicAuth = req.BasicAuth
|
||||
|
||||
for _, frontendSelection := range req.FrontendSelection {
|
||||
shrCmd = append(shrCmd, "--frontend", frontendSelection)
|
||||
}
|
||||
shr.frontendSelection = req.FrontendSelection
|
||||
|
||||
if req.Insecure {
|
||||
shrCmd = append(shrCmd, "--insecure")
|
||||
}
|
||||
shr.insecure = req.Insecure
|
||||
|
||||
if req.OauthProvider != "" {
|
||||
shrCmd = append(shrCmd, "--oauth-provider", req.OauthProvider)
|
||||
}
|
||||
shr.oauthProvider = req.OauthProvider
|
||||
|
||||
for _, pattern := range req.OauthEmailAddressPatterns {
|
||||
shrCmd = append(shrCmd, "--oauth-email-address-patterns", pattern)
|
||||
}
|
||||
shr.oauthEmailAddressPatterns = req.OauthEmailAddressPatterns
|
||||
|
||||
if req.OauthCheckInterval != "" {
|
||||
shrCmd = append(shrCmd, "--oauth-check-interval", req.OauthCheckInterval)
|
||||
}
|
||||
|
||||
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.SharePublicResponse{
|
||||
Token: shr.token,
|
||||
FrontendEndpoints: shr.frontendEndpoints,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, shr.bootErr
|
||||
}
|
61
agent/shareReserved.go
Normal file
61
agent/shareReserved.go
Normal file
@ -0,0 +1,61 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/agent/proctree"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"os"
|
||||
)
|
||||
|
||||
func (i *agentGrpcImpl) ShareReserved(_ context.Context, req *agentGrpc.ShareReservedRequest) (*agentGrpc.ShareReservedResponse, 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", "reserved", "--agent"}
|
||||
shr := &share{
|
||||
reserved: true,
|
||||
bootComplete: make(chan struct{}),
|
||||
a: i.a,
|
||||
}
|
||||
|
||||
if req.OverrideEndpoint != "" {
|
||||
shrCmd = append(shrCmd, "--override-endpoint", req.OverrideEndpoint)
|
||||
}
|
||||
|
||||
if req.Insecure {
|
||||
shrCmd = append(shrCmd, "--insecure")
|
||||
}
|
||||
shr.insecure = req.Insecure
|
||||
|
||||
shrCmd = append(shrCmd, req.Token)
|
||||
shr.token = req.Token
|
||||
|
||||
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.ShareReservedResponse{
|
||||
Token: shr.token,
|
||||
BackendMode: string(shr.backendMode),
|
||||
ShareMode: string(shr.shareMode),
|
||||
FrontendEndpoints: shr.frontendEndpoints,
|
||||
Target: shr.target,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, shr.bootErr
|
||||
}
|
33
agent/status.go
Normal file
33
agent/status.go
Normal file
@ -0,0 +1,33 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
)
|
||||
|
||||
func (i *agentGrpcImpl) Status(_ context.Context, _ *agentGrpc.StatusRequest) (*agentGrpc.StatusResponse, error) {
|
||||
var accesses []*agentGrpc.AccessDetail
|
||||
for feToken, acc := range i.a.accesses {
|
||||
accesses = append(accesses, &agentGrpc.AccessDetail{
|
||||
FrontendToken: feToken,
|
||||
Token: acc.token,
|
||||
BindAddress: acc.bindAddress,
|
||||
ResponseHeaders: acc.responseHeaders,
|
||||
})
|
||||
}
|
||||
|
||||
var shares []*agentGrpc.ShareDetail
|
||||
for token, shr := range i.a.shares {
|
||||
shares = append(shares, &agentGrpc.ShareDetail{
|
||||
Token: token,
|
||||
ShareMode: string(shr.shareMode),
|
||||
BackendMode: string(shr.backendMode),
|
||||
Reserved: shr.reserved,
|
||||
FrontendEndpoint: shr.frontendSelection,
|
||||
BackendEndpoint: shr.target,
|
||||
Closed: shr.closed,
|
||||
})
|
||||
}
|
||||
|
||||
return &agentGrpc.StatusResponse{Accesses: accesses, Shares: shares}, nil
|
||||
}
|
14
agent/version.go
Normal file
14
agent/version.go
Normal file
@ -0,0 +1,14 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/build"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (i *agentGrpcImpl) Version(_ context.Context, _ *agentGrpc.VersionRequest) (*agentGrpc.VersionResponse, error) {
|
||||
v := build.String()
|
||||
logrus.Infof("responding to version inquiry with '%v'", v)
|
||||
return &agentGrpc.VersionResponse{V: v}, nil
|
||||
}
|
7
bin/generate_pb.sh
Executable file
7
bin/generate_pb.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
protoc --go_out=. \
|
||||
--go_opt=paths=source_relative \
|
||||
--go-grpc_out=. \
|
||||
--go-grpc_opt=paths=source_relative \
|
||||
agent/agentGrpc/agent.proto
|
@ -1,6 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/go-openapi/runtime"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
@ -30,6 +32,7 @@ func init() {
|
||||
type accessPrivateCommand struct {
|
||||
bindAddress string
|
||||
headless bool
|
||||
agent bool
|
||||
responseHeaders []string
|
||||
cmd *cobra.Command
|
||||
}
|
||||
@ -42,6 +45,8 @@ 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().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
|
||||
@ -81,7 +86,19 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
logrus.Infof("allocated frontend '%v'", accessResp.Payload.FrontendToken)
|
||||
|
||||
if cmd.agent {
|
||||
data := make(map[string]interface{})
|
||||
data["frontend_token"] = accessResp.Payload.FrontendToken
|
||||
data["bind_address"] = cmd.bindAddress
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(string(jsonData))
|
||||
} else {
|
||||
logrus.Infof("allocated frontend '%v'", accessResp.Payload.FrontendToken)
|
||||
}
|
||||
|
||||
protocol := "http://"
|
||||
switch accessResp.Payload.BackendMode {
|
||||
@ -231,6 +248,21 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
} else if cmd.agent {
|
||||
for {
|
||||
select {
|
||||
case req := <-requests:
|
||||
data := make(map[string]interface{})
|
||||
data["remote-address"] = req.RemoteAddr
|
||||
data["method"] = req.Method
|
||||
data["path"] = req.Path
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(string(jsonData))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mdl := newAccessModel(shrToken, endpointUrl.String())
|
||||
logrus.SetOutput(mdl)
|
||||
|
65
cmd/zrok/agentAccessPrivate.go
Normal file
65
cmd/zrok/agentAccessPrivate.go
Normal file
@ -0,0 +1,65 @@
|
||||
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)
|
||||
}
|
55
cmd/zrok/agentReleaseAccess.go
Normal file
55
cmd/zrok/agentReleaseAccess.go
Normal file
@ -0,0 +1,55 @@
|
||||
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() {
|
||||
agentReleaseCmd.AddCommand(newAgentReleaseAccessCommand().cmd)
|
||||
}
|
||||
|
||||
type agentReleaseAccessCommand struct {
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
func newAgentReleaseAccessCommand() *agentReleaseAccessCommand {
|
||||
cmd := &cobra.Command{
|
||||
Use: "access <frontendToken>",
|
||||
Short: "Unbind an access from the zrok Agent",
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
command := &agentReleaseAccessCommand{cmd: cmd}
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *agentReleaseAccessCommand) run(_ *cobra.Command, args []string) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to load environment", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
client, conn, err := agentClient.NewClient(root)
|
||||
if err != nil {
|
||||
tui.Error("error connecting to agent", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
_, err = client.ReleaseAccess(context.Background(), &agentGrpc.ReleaseAccessRequest{
|
||||
FrontendToken: args[0],
|
||||
})
|
||||
if err != nil {
|
||||
tui.Error("error releasing access", err)
|
||||
}
|
||||
|
||||
fmt.Println("success.")
|
||||
}
|
55
cmd/zrok/agentReleaseShare.go
Executable file
55
cmd/zrok/agentReleaseShare.go
Executable file
@ -0,0 +1,55 @@
|
||||
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() {
|
||||
agentReleaseCmd.AddCommand(newAgentReleaseShareCommand().cmd)
|
||||
}
|
||||
|
||||
type agentReleaseShareCommand struct {
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
func newAgentReleaseShareCommand() *agentReleaseShareCommand {
|
||||
cmd := &cobra.Command{
|
||||
Use: "share <token>",
|
||||
Short: "Release a share from the zrok Agent",
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
command := &agentReleaseShareCommand{cmd: cmd}
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *agentReleaseShareCommand) run(_ *cobra.Command, args []string) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to load environment", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
client, conn, err := agentClient.NewClient(root)
|
||||
if err != nil {
|
||||
tui.Error("error connecting to agent", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
_, err = client.ReleaseShare(context.Background(), &agentGrpc.ReleaseShareRequest{
|
||||
Token: args[0],
|
||||
})
|
||||
if err != nil {
|
||||
tui.Error("error releasing share", err)
|
||||
}
|
||||
|
||||
fmt.Println("success.")
|
||||
}
|
162
cmd/zrok/agentSharePrivate.go
Normal file
162
cmd/zrok/agentSharePrivate.go
Normal file
@ -0,0 +1,162 @@
|
||||
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)
|
||||
}
|
144
cmd/zrok/agentSharePublic.go
Normal file
144
cmd/zrok/agentSharePublic.go
Normal file
@ -0,0 +1,144 @@
|
||||
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)
|
||||
}
|
65
cmd/zrok/agentShareReserved.go
Normal file
65
cmd/zrok/agentShareReserved.go
Normal file
@ -0,0 +1,65 @@
|
||||
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)
|
||||
}
|
62
cmd/zrok/agentStart.go
Normal file
62
cmd/zrok/agentStart.go
Normal file
@ -0,0 +1,62 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/openziti/zrok/agent"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func init() {
|
||||
agentCmd.AddCommand(newAgentStartCommand().cmd)
|
||||
}
|
||||
|
||||
type agentStartCommand struct {
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
func newAgentStartCommand() *agentStartCommand {
|
||||
cmd := &cobra.Command{
|
||||
Use: "start",
|
||||
Short: "Start a zrok agent",
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
command := &agentStartCommand{cmd: cmd}
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *agentStartCommand) run(_ *cobra.Command, _ []string) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
tui.Error("error loading zrokdir", err)
|
||||
}
|
||||
|
||||
if !root.IsEnabled() {
|
||||
tui.Error("unable to load environment; did you 'zrok enable'?", nil)
|
||||
}
|
||||
|
||||
a, err := agent.NewAgent(root)
|
||||
if err != nil {
|
||||
tui.Error("error creating agent", err)
|
||||
}
|
||||
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-c
|
||||
cmd.shutdown(a)
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
if err := a.Run(); err != nil {
|
||||
tui.Error("agent aborted", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (cmd *agentStartCommand) shutdown(a *agent.Agent) {
|
||||
a.Shutdown()
|
||||
}
|
74
cmd/zrok/agentStatus.go
Normal file
74
cmd/zrok/agentStatus.go
Normal file
@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"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"
|
||||
"os"
|
||||
)
|
||||
|
||||
func init() {
|
||||
agentCmd.AddCommand(newAgentStatusCommand().cmd)
|
||||
}
|
||||
|
||||
type agentStatusCommand struct {
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
func newAgentStatusCommand() *agentStatusCommand {
|
||||
cmd := &cobra.Command{
|
||||
Use: "status",
|
||||
Short: "Show the status of the running zrok Agent",
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
command := &agentStatusCommand{cmd: cmd}
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *agentStatusCommand) run(_ *cobra.Command, _ []string) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
tui.Error("error loading zrokdir", err)
|
||||
}
|
||||
|
||||
client, conn, err := agentClient.NewClient(root)
|
||||
if err != nil {
|
||||
tui.Error("error connecting to agent", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
status, err := client.Status(context.Background(), &agentGrpc.StatusRequest{})
|
||||
if err != nil {
|
||||
tui.Error("error getting status", err)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
t := table.NewWriter()
|
||||
t.SetOutputMirror(os.Stdout)
|
||||
t.SetStyle(table.StyleColoredDark)
|
||||
t.AppendHeader(table.Row{"Frontend Token", "Token", "Bind Address"})
|
||||
for _, access := range status.GetAccesses() {
|
||||
t.AppendRow(table.Row{access.FrontendToken, access.Token, access.BindAddress})
|
||||
}
|
||||
t.Render()
|
||||
fmt.Printf("%d accesses in agent\n", len(status.GetAccesses()))
|
||||
|
||||
fmt.Println()
|
||||
t = table.NewWriter()
|
||||
t.SetOutputMirror(os.Stdout)
|
||||
t.SetStyle(table.StyleColoredDark)
|
||||
t.AppendHeader(table.Row{"Token", "Reserved", "Share Mode", "Backend Mode", "Target"})
|
||||
for _, share := range status.GetShares() {
|
||||
t.AppendRow(table.Row{share.Token, share.Reserved, share.ShareMode, share.BackendMode, share.BackendEndpoint})
|
||||
}
|
||||
t.Render()
|
||||
fmt.Printf("%d shares in agent\n", len(status.GetShares()))
|
||||
|
||||
fmt.Println()
|
||||
}
|
49
cmd/zrok/agentVersion.go
Normal file
49
cmd/zrok/agentVersion.go
Normal file
@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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() {
|
||||
agentCmd.AddCommand(newAgentVersionCommand().cmd)
|
||||
}
|
||||
|
||||
type agentVersionCommand struct {
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
func newAgentVersionCommand() *agentVersionCommand {
|
||||
cmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Retrieve the running zrok Agent version",
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
command := &agentVersionCommand{cmd: cmd}
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *agentVersionCommand) run(_ *cobra.Command, _ []string) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
tui.Error("error loading zrokdir", err)
|
||||
}
|
||||
|
||||
client, conn, err := agentClient.NewClient(root)
|
||||
if err != nil {
|
||||
tui.Error("error connecting to agent", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
v, err := client.Version(context.Background(), &agentGrpc.VersionRequest{})
|
||||
if err != nil {
|
||||
tui.Error("error getting agent version", err)
|
||||
}
|
||||
|
||||
println(v.GetV())
|
||||
}
|
@ -24,6 +24,10 @@ func init() {
|
||||
adminCmd.AddCommand(adminDeleteCmd)
|
||||
adminCmd.AddCommand(adminListCmd)
|
||||
adminCmd.AddCommand(adminUpdateCmd)
|
||||
rootCmd.AddCommand(agentCmd)
|
||||
agentCmd.AddCommand(agentAccessCmd)
|
||||
agentCmd.AddCommand(agentShareCmd)
|
||||
agentCmd.AddCommand(agentReleaseCmd)
|
||||
testCmd.AddCommand(loopCmd)
|
||||
rootCmd.AddCommand(adminCmd)
|
||||
rootCmd.AddCommand(configCmd)
|
||||
@ -77,6 +81,27 @@ var adminUpdateCmd = &cobra.Command{
|
||||
Short: "Update global resources",
|
||||
}
|
||||
|
||||
var agentAccessCmd = &cobra.Command{
|
||||
Use: "access",
|
||||
Short: "zrok Agent access commands",
|
||||
}
|
||||
|
||||
var agentCmd = &cobra.Command{
|
||||
Use: "agent",
|
||||
Short: "zrok Agent commands",
|
||||
Aliases: []string{"daemon"},
|
||||
}
|
||||
|
||||
var agentShareCmd = &cobra.Command{
|
||||
Use: "share",
|
||||
Short: "zrok Agent sharing commands",
|
||||
}
|
||||
|
||||
var agentReleaseCmd = &cobra.Command{
|
||||
Use: "release",
|
||||
Short: "zrok Agent release commands",
|
||||
}
|
||||
|
||||
var configCmd = &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Configure your zrok environment",
|
||||
|
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/openziti/zrok/endpoints"
|
||||
@ -27,9 +28,9 @@ func init() {
|
||||
}
|
||||
|
||||
type sharePrivateCommand struct {
|
||||
basicAuth []string
|
||||
backendMode string
|
||||
headless bool
|
||||
agent bool
|
||||
insecure bool
|
||||
closed bool
|
||||
accessGrants []string
|
||||
@ -43,9 +44,10 @@ func newSharePrivateCommand() *sharePrivateCommand {
|
||||
Args: cobra.RangeArgs(0, 1),
|
||||
}
|
||||
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().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.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)")
|
||||
@ -145,7 +147,6 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
req := &sdk.ShareRequest{
|
||||
BackendMode: sdk.BackendMode(cmd.backendMode),
|
||||
ShareMode: sdk.PrivateShareMode,
|
||||
BasicAuth: cmd.basicAuth,
|
||||
Target: target,
|
||||
}
|
||||
if cmd.closed {
|
||||
@ -160,9 +161,20 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if cmd.agent {
|
||||
data := make(map[string]interface{})
|
||||
data["token"] = shr.Token
|
||||
data["frontend_endpoints"] = shr.FrontendEndpoints
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(string(jsonData))
|
||||
}
|
||||
|
||||
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 {
|
||||
if !cmd.headless && !cmd.agent {
|
||||
proxy.SetCaddyLoggingWriter(mdl)
|
||||
}
|
||||
|
||||
@ -366,6 +378,22 @@ func (cmd *sharePrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
} else if cmd.agent {
|
||||
for {
|
||||
select {
|
||||
case req := <-requests:
|
||||
data := make(map[string]interface{})
|
||||
data["remote_address"] = req.RemoteAddr
|
||||
data["method"] = req.Method
|
||||
data["path"] = req.Path
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(string(jsonData))
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
logrus.SetOutput(mdl)
|
||||
prg := tea.NewProgram(mdl, tea.WithAltScreen())
|
||||
|
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/gobwas/glob"
|
||||
@ -29,6 +30,7 @@ type sharePublicCommand struct {
|
||||
frontendSelection []string
|
||||
backendMode string
|
||||
headless bool
|
||||
agent bool
|
||||
insecure bool
|
||||
oauthProvider string
|
||||
oauthEmailAddressPatterns []string
|
||||
@ -53,10 +55,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.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")
|
||||
@ -149,8 +152,19 @@ func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if cmd.agent {
|
||||
data := make(map[string]interface{})
|
||||
data["token"] = shr.Token
|
||||
data["frontend_endpoints"] = shr.FrontendEndpoints
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(string(jsonData))
|
||||
}
|
||||
|
||||
mdl := newShareModel(shr.Token, shr.FrontendEndpoints, sdk.PublicShareMode, sdk.BackendMode(cmd.backendMode))
|
||||
if !cmd.headless {
|
||||
if !cmd.headless && !cmd.agent {
|
||||
proxy.SetCaddyLoggingWriter(mdl)
|
||||
}
|
||||
|
||||
@ -267,6 +281,22 @@ func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
} else if cmd.agent {
|
||||
for {
|
||||
select {
|
||||
case req := <-requests:
|
||||
data := make(map[string]interface{})
|
||||
data["remote_address"] = req.RemoteAddr
|
||||
data["method"] = req.Method
|
||||
data["path"] = req.Path
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(string(jsonData))
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
logrus.SetOutput(mdl)
|
||||
prg := tea.NewProgram(mdl, tea.WithAltScreen())
|
||||
|
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
@ -28,6 +29,7 @@ func init() {
|
||||
type shareReservedCommand struct {
|
||||
overrideEndpoint string
|
||||
headless bool
|
||||
agent bool
|
||||
insecure bool
|
||||
cmd *cobra.Command
|
||||
}
|
||||
@ -41,6 +43,8 @@ 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.insecure, "insecure", false, "Enable insecure TLS certificate validation")
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
@ -96,7 +100,9 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
|
||||
if resp.Payload.BackendMode != "socks" {
|
||||
logrus.Infof("sharing target: '%v'", target)
|
||||
if !cmd.agent {
|
||||
logrus.Infof("sharing target: '%v'", target)
|
||||
}
|
||||
|
||||
if resp.Payload.BackendProxyEndpoint != target {
|
||||
upReq := share.NewUpdateShareParams()
|
||||
@ -110,9 +116,13 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
logrus.Infof("updated backend target to: %v", target)
|
||||
if !cmd.agent {
|
||||
logrus.Infof("updated backend target to: %v", target)
|
||||
}
|
||||
} else {
|
||||
logrus.Infof("using existing backend target: %v", target)
|
||||
if !cmd.agent {
|
||||
logrus.Infof("using existing backend target: %v", target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,8 +134,26 @@ 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 {
|
||||
data := make(map[string]interface{})
|
||||
data["token"] = resp.Payload.Token
|
||||
data["backend_mode"] = resp.Payload.BackendMode
|
||||
data["share_mode"] = resp.Payload.ShareMode
|
||||
if resp.Payload.FrontendEndpoint != "" {
|
||||
data["frontend_endpoints"] = resp.Payload.FrontendEndpoint
|
||||
}
|
||||
if resp.Payload.BackendProxyEndpoint != "" {
|
||||
data["target"] = resp.Payload.BackendProxyEndpoint
|
||||
}
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(string(jsonData))
|
||||
}
|
||||
|
||||
mdl := newShareModel(shrToken, []string{shareDescription}, sdk.ShareMode(resp.Payload.ShareMode), sdk.BackendMode(resp.Payload.BackendMode))
|
||||
if !cmd.headless {
|
||||
if !cmd.headless && !cmd.agent {
|
||||
proxy.SetCaddyLoggingWriter(mdl)
|
||||
}
|
||||
|
||||
@ -324,6 +352,23 @@ func (cmd *shareReservedCommand) run(_ *cobra.Command, args []string) {
|
||||
logrus.Infof("%v -> %v %v", req.RemoteAddr, req.Method, req.Path)
|
||||
}
|
||||
}
|
||||
|
||||
} else if cmd.agent {
|
||||
for {
|
||||
select {
|
||||
case req := <-requests:
|
||||
data := make(map[string]interface{})
|
||||
data["remote-address"] = req.RemoteAddr
|
||||
data["method"] = req.Method
|
||||
data["path"] = req.Path
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(string(jsonData))
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
logrus.SetOutput(mdl)
|
||||
prg := tea.NewProgram(mdl, tea.WithAltScreen())
|
||||
|
@ -67,6 +67,10 @@ func (b *Backend) Run() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Backend) Stop() error {
|
||||
return b.listener.Close()
|
||||
}
|
||||
|
||||
func newReverseProxy(cfg *BackendConfig) (*httputil.ReverseProxy, error) {
|
||||
targetURL, err := url.Parse(cfg.EndpointAddress)
|
||||
if err != nil {
|
||||
|
@ -81,6 +81,10 @@ func (c *CaddyWebBackend) Run() error {
|
||||
return caddy.Run(c.caddyCfg)
|
||||
}
|
||||
|
||||
func (c *CaddyWebBackend) Stop() error {
|
||||
return caddy.Stop()
|
||||
}
|
||||
|
||||
func (c *CaddyWebBackend) Requests() func() int32 {
|
||||
return func() int32 { return 0 }
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ type Root interface {
|
||||
ZitiIdentityNamed(name string) (string, error)
|
||||
SaveZitiIdentityNamed(name, data string) error
|
||||
DeleteZitiIdentityNamed(name string) error
|
||||
|
||||
AgentSocket() (string, error)
|
||||
}
|
||||
|
||||
type Environment struct {
|
||||
|
@ -174,6 +174,10 @@ func (r *Root) DeleteZitiIdentityNamed(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Root) AgentSocket() (string, error) {
|
||||
return "", errors.Errorf("this environment version does not support agent sockets; please 'zrok update' this environment")
|
||||
}
|
||||
|
||||
func (r *Root) Obliterate() error {
|
||||
zrd, err := rootDir()
|
||||
if err != nil {
|
||||
|
@ -174,6 +174,10 @@ func (r *Root) DeleteZitiIdentityNamed(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Root) AgentSocket() (string, error) {
|
||||
return agentSocket()
|
||||
}
|
||||
|
||||
func (r *Root) Obliterate() error {
|
||||
zrd, err := rootDir()
|
||||
if err != nil {
|
||||
|
@ -53,3 +53,11 @@ func identityFile(name string) (string, error) {
|
||||
}
|
||||
return filepath.Join(idd, fmt.Sprintf("%v.json", name)), nil
|
||||
}
|
||||
|
||||
func agentSocket() (string, error) {
|
||||
zrd, err := rootDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(zrd, "agent.socket"), nil
|
||||
}
|
||||
|
15
go.mod
15
go.mod
@ -27,6 +27,7 @@ require (
|
||||
github.com/jedib0t/go-pretty/v6 v6.4.3
|
||||
github.com/jessevdk/go-flags v1.6.1
|
||||
github.com/jmoiron/sqlx v1.3.5
|
||||
github.com/kolesnikovae/go-winjob v1.0.0
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/mattn/go-sqlite3 v1.14.16
|
||||
github.com/michaelquigley/cf v0.0.13
|
||||
@ -57,7 +58,10 @@ require (
|
||||
golang.org/x/crypto v0.25.0
|
||||
golang.org/x/net v0.27.0
|
||||
golang.org/x/oauth2 v0.21.0
|
||||
golang.org/x/sys v0.24.0
|
||||
golang.org/x/time v0.5.0
|
||||
google.golang.org/grpc v1.65.0
|
||||
google.golang.org/protobuf v1.34.2
|
||||
nhooyr.io/websocket v1.8.11
|
||||
)
|
||||
|
||||
@ -85,7 +89,7 @@ require (
|
||||
github.com/caddyserver/certmagic v0.20.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/chzyer/readline v1.5.1 // indirect
|
||||
github.com/containerd/console v1.0.3 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
@ -126,7 +130,7 @@ require (
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.2.1 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang/glog v1.2.0 // indirect
|
||||
github.com/golang/glog v1.2.1 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/cel-go v0.15.1 // indirect
|
||||
@ -253,17 +257,14 @@ require (
|
||||
golang.org/x/exp v0.0.0-20231127185646-65229373498e // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.24.0 // indirect
|
||||
golang.org/x/term v0.22.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 // indirect
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 // indirect
|
||||
google.golang.org/grpc v1.59.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
|
27
go.sum
27
go.sum
@ -119,8 +119,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/charmbracelet/bubbles v0.14.0 h1:DJfCwnARfWjZLvMglhSQzo76UZ2gucuHPy9jLWX45Og=
|
||||
github.com/charmbracelet/bubbles v0.14.0/go.mod h1:bbeTiXwPww4M031aGi8UK2HT9RDWoiNibae+1yCMtcc=
|
||||
github.com/charmbracelet/bubbletea v0.21.0/go.mod h1:GgmJMec61d08zXsOhqRC/AiOx4K4pmz+VIcRIm1FKr4=
|
||||
@ -298,8 +298,8 @@ github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
|
||||
github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4=
|
||||
github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@ -551,6 +551,8 @@ github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6K
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/kolesnikovae/go-winjob v1.0.0 h1:OKEtCHB3sYNAiqNwGDhf08Y6luM7C8mP+42rp1N6SeE=
|
||||
github.com/kolesnikovae/go-winjob v1.0.0/go.mod h1:k0joOLP3/NBrRmDQjPV2+oN1TPmEWt6arTNtFjVeQuM=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
@ -1182,6 +1184,7 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -1401,12 +1404,12 @@ google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6D
|
||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20231120223509-83a465c0220f h1:Vn+VyHU5guc9KjB5KrjI2q0wCOWEOIh0OEsleqakHJg=
|
||||
google.golang.org/genproto v0.0.0-20231120223509-83a465c0220f/go.mod h1:nWSwAFPb+qfNJXsoeO3Io7zf4tMSfN8EA8RlDA04GhY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4 h1:ZcOkrmX74HbKFYnpPY8Qsw93fC29TbJXspYKaBkSXDQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4/go.mod h1:k2dtGpRrbsSyKcNPKKI5sstZkrNCZwpU/ns96JoHbGg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 h1:DC7wcm+i+P1rN3Ff07vL+OndGg5OhNddHyTA+ocPqYE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4/go.mod h1:eJVxU6o+4G1PSczBr85xmyvSNYAKvAYgkub40YGomFM=
|
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ=
|
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@ -1427,8 +1430,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
||||
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
||||
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
||||
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
Loading…
Reference in New Issue
Block a user