mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 07:16:38 +00:00
add status confirmation for certs and tunnel creation
This commit is contained in:
@@ -10,4 +10,6 @@ type Manager interface {
|
||||
CreateReverseProxy(ctx context.Context, accountID, userID string, reverseProxy *ReverseProxy) (*ReverseProxy, error)
|
||||
UpdateReverseProxy(ctx context.Context, accountID, userID string, reverseProxy *ReverseProxy) (*ReverseProxy, error)
|
||||
DeleteReverseProxy(ctx context.Context, accountID, userID, reverseProxyID string) error
|
||||
SetCertificateIssuedAt(ctx context.Context, accountID, reverseProxyID string) error
|
||||
SetStatus(ctx context.Context, accountID, reverseProxyID string, status ProxyStatus) error
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package manager
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/rs/xid"
|
||||
@@ -229,3 +230,40 @@ func (m *managerImpl) DeleteReverseProxy(ctx context.Context, accountID, userID,
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetCertificateIssuedAt sets the certificate issued timestamp to the current time.
|
||||
// Call this when receiving a gRPC notification that the certificate was issued.
|
||||
func (m *managerImpl) SetCertificateIssuedAt(ctx context.Context, accountID, reverseProxyID string) error {
|
||||
return m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
proxy, err := transaction.GetReverseProxyByID(ctx, store.LockingStrengthUpdate, accountID, reverseProxyID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get reverse proxy: %w", err)
|
||||
}
|
||||
|
||||
proxy.Meta.CertificateIssuedAt = time.Now()
|
||||
|
||||
if err = transaction.UpdateReverseProxy(ctx, proxy); err != nil {
|
||||
return fmt.Errorf("failed to update reverse proxy certificate timestamp: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// SetStatus updates the status of the reverse proxy (e.g., "active", "tunnel_not_created", etc.)
|
||||
func (m *managerImpl) SetStatus(ctx context.Context, accountID, reverseProxyID string, status reverseproxy.ProxyStatus) error {
|
||||
return m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
proxy, err := transaction.GetReverseProxyByID(ctx, store.LockingStrengthUpdate, accountID, reverseProxyID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get reverse proxy: %w", err)
|
||||
}
|
||||
|
||||
proxy.Meta.Status = string(status)
|
||||
|
||||
if err = transaction.UpdateReverseProxy(ctx, proxy); err != nil {
|
||||
return fmt.Errorf("failed to update reverse proxy status: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/rs/xid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
@@ -21,6 +22,17 @@ const (
|
||||
Delete Operation = "delete"
|
||||
)
|
||||
|
||||
type ProxyStatus string
|
||||
|
||||
const (
|
||||
StatusPending ProxyStatus = "pending"
|
||||
StatusActive ProxyStatus = "active"
|
||||
StatusTunnelNotCreated ProxyStatus = "tunnel_not_created"
|
||||
StatusCertificatePending ProxyStatus = "certificate_pending"
|
||||
StatusCertificateFailed ProxyStatus = "certificate_failed"
|
||||
StatusError ProxyStatus = "error"
|
||||
)
|
||||
|
||||
type Target struct {
|
||||
Path *string `json:"path,omitempty"`
|
||||
Host string `json:"host"`
|
||||
@@ -57,6 +69,12 @@ type AuthConfig struct {
|
||||
LinkAuth *LinkAuthConfig `json:"link_auth,omitempty" gorm:"serializer:json"`
|
||||
}
|
||||
|
||||
type ReverseProxyMeta struct {
|
||||
CreatedAt time.Time
|
||||
CertificateIssuedAt time.Time
|
||||
Status string
|
||||
}
|
||||
|
||||
type ReverseProxy struct {
|
||||
ID string `gorm:"primaryKey"`
|
||||
AccountID string `gorm:"index"`
|
||||
@@ -64,7 +82,8 @@ type ReverseProxy struct {
|
||||
Domain string `gorm:"index"`
|
||||
Targets []Target `gorm:"serializer:json"`
|
||||
Enabled bool
|
||||
Auth AuthConfig `gorm:"serializer:json"`
|
||||
Auth AuthConfig `gorm:"serializer:json"`
|
||||
Meta ReverseProxyMeta `gorm:"embedded;embeddedPrefix:meta_"`
|
||||
}
|
||||
|
||||
func NewReverseProxy(accountID, name, domain string, targets []Target, enabled bool) *ReverseProxy {
|
||||
@@ -75,6 +94,10 @@ func NewReverseProxy(accountID, name, domain string, targets []Target, enabled b
|
||||
Domain: domain,
|
||||
Targets: targets,
|
||||
Enabled: enabled,
|
||||
Meta: ReverseProxyMeta{
|
||||
CreatedAt: time.Now(),
|
||||
Status: string(StatusPending),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -162,6 +162,9 @@ func (s *BaseServer) GRPCServer() *grpc.Server {
|
||||
func (s *BaseServer) ReverseProxyGRPCServer() *nbgrpc.ProxyServiceServer {
|
||||
return Create(s, func() *nbgrpc.ProxyServiceServer {
|
||||
proxyService := nbgrpc.NewProxyServiceServer(s.Store(), s.AccountManager(), s.AccessLogsManager())
|
||||
s.AfterInit(func(s *BaseServer) {
|
||||
proxyService.SetProxyManager(s.ReverseProxyManager())
|
||||
})
|
||||
return proxyService
|
||||
})
|
||||
}
|
||||
|
||||
@@ -27,6 +27,11 @@ type reverseProxyStore interface {
|
||||
GetReverseProxyByID(ctx context.Context, lockStrength store.LockingStrength, accountID string, serviceID string) (*reverseproxy.ReverseProxy, error)
|
||||
}
|
||||
|
||||
type reverseProxyManager interface {
|
||||
SetCertificateIssuedAt(ctx context.Context, accountID, reverseProxyID string) error
|
||||
SetStatus(ctx context.Context, accountID, reverseProxyID string, status reverseproxy.ProxyStatus) error
|
||||
}
|
||||
|
||||
type keyStore interface {
|
||||
GetGroupByName(ctx context.Context, groupName string, accountID string) (*types.Group, error)
|
||||
CreateSetupKey(ctx context.Context, accountID string, keyName string, keyType types.SetupKeyType, expiresIn time.Duration, autoGroups []string, usageLimit int, userID string, ephemeral bool, allowExtraDNSLabels bool) (*types.SetupKey, error)
|
||||
@@ -50,6 +55,9 @@ type ProxyServiceServer struct {
|
||||
|
||||
// Manager for access logs
|
||||
accessLogManager accesslogs.Manager
|
||||
|
||||
// Manager for reverse proxy operations
|
||||
reverseProxyManager reverseProxyManager
|
||||
}
|
||||
|
||||
// proxyConnection represents a connected proxy
|
||||
@@ -73,6 +81,10 @@ func NewProxyServiceServer(store reverseProxyStore, keys keyStore, accessLogMgr
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ProxyServiceServer) SetProxyManager(manager reverseProxyManager) {
|
||||
s.reverseProxyManager = manager
|
||||
}
|
||||
|
||||
// GetMappingUpdate handles the control stream with proxy clients
|
||||
func (s *ProxyServiceServer) GetMappingUpdate(req *proto.GetMappingUpdateRequest, stream proto.ProxyService_GetMappingUpdateServer) error {
|
||||
ctx := stream.Context()
|
||||
@@ -301,3 +313,69 @@ func (s *ProxyServiceServer) Authenticate(ctx context.Context, req *proto.Authen
|
||||
Success: authenticated,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SendStatusUpdate handles status updates from proxy clients
|
||||
func (s *ProxyServiceServer) SendStatusUpdate(ctx context.Context, req *proto.SendStatusUpdateRequest) (*proto.SendStatusUpdateResponse, error) {
|
||||
accountID := req.GetAccountId()
|
||||
reverseProxyID := req.GetReverseProxyId()
|
||||
protoStatus := req.GetStatus()
|
||||
certificateIssued := req.GetCertificateIssued()
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"reverse_proxy_id": reverseProxyID,
|
||||
"account_id": accountID,
|
||||
"status": protoStatus,
|
||||
"certificate_issued": certificateIssued,
|
||||
"error_message": req.GetErrorMessage(),
|
||||
}).Debug("Status update from proxy")
|
||||
|
||||
if reverseProxyID == "" || accountID == "" {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "reverse_proxy_id and account_id are required")
|
||||
}
|
||||
|
||||
if certificateIssued {
|
||||
if err := s.reverseProxyManager.SetCertificateIssuedAt(ctx, accountID, reverseProxyID); err != nil {
|
||||
log.WithContext(ctx).WithError(err).Error("Failed to set certificate issued timestamp")
|
||||
return nil, status.Errorf(codes.Internal, "failed to update certificate timestamp: %v", err)
|
||||
}
|
||||
log.WithFields(log.Fields{
|
||||
"reverse_proxy_id": reverseProxyID,
|
||||
"account_id": accountID,
|
||||
}).Info("Certificate issued timestamp updated")
|
||||
}
|
||||
|
||||
internalStatus := protoStatusToInternal(protoStatus)
|
||||
|
||||
if err := s.reverseProxyManager.SetStatus(ctx, accountID, reverseProxyID, internalStatus); err != nil {
|
||||
log.WithContext(ctx).WithError(err).Error("Failed to set proxy status")
|
||||
return nil, status.Errorf(codes.Internal, "failed to update proxy status: %v", err)
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"reverse_proxy_id": reverseProxyID,
|
||||
"account_id": accountID,
|
||||
"status": internalStatus,
|
||||
}).Info("Proxy status updated")
|
||||
|
||||
return &proto.SendStatusUpdateResponse{}, nil
|
||||
}
|
||||
|
||||
// protoStatusToInternal maps proto status to internal status
|
||||
func protoStatusToInternal(protoStatus proto.ProxyStatus) reverseproxy.ProxyStatus {
|
||||
switch protoStatus {
|
||||
case proto.ProxyStatus_PROXY_STATUS_PENDING:
|
||||
return reverseproxy.StatusPending
|
||||
case proto.ProxyStatus_PROXY_STATUS_ACTIVE:
|
||||
return reverseproxy.StatusActive
|
||||
case proto.ProxyStatus_PROXY_STATUS_TUNNEL_NOT_CREATED:
|
||||
return reverseproxy.StatusTunnelNotCreated
|
||||
case proto.ProxyStatus_PROXY_STATUS_CERTIFICATE_PENDING:
|
||||
return reverseproxy.StatusCertificatePending
|
||||
case proto.ProxyStatus_PROXY_STATUS_CERTIFICATE_FAILED:
|
||||
return reverseproxy.StatusCertificateFailed
|
||||
case proto.ProxyStatus_PROXY_STATUS_ERROR:
|
||||
return reverseproxy.StatusError
|
||||
default:
|
||||
return reverseproxy.StatusError
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,20 +5,34 @@ import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/crypto/acme"
|
||||
"golang.org/x/crypto/acme/autocert"
|
||||
)
|
||||
|
||||
type certificateNotifier interface {
|
||||
NotifyCertificateIssued(ctx context.Context, accountID, reverseProxyID, domain string) error
|
||||
}
|
||||
|
||||
type Manager struct {
|
||||
*autocert.Manager
|
||||
|
||||
domainsMux sync.RWMutex
|
||||
domains map[string]struct{}
|
||||
domains map[string]struct {
|
||||
accountID string
|
||||
reverseProxyID string
|
||||
}
|
||||
|
||||
certNotifier certificateNotifier
|
||||
}
|
||||
|
||||
func NewManager(certDir, acmeURL string) *Manager {
|
||||
func NewManager(certDir, acmeURL string, notifier certificateNotifier) *Manager {
|
||||
mgr := &Manager{
|
||||
domains: make(map[string]struct{}),
|
||||
domains: make(map[string]struct {
|
||||
accountID string
|
||||
reverseProxyID string
|
||||
}),
|
||||
certNotifier: notifier,
|
||||
}
|
||||
mgr.Manager = &autocert.Manager{
|
||||
Prompt: autocert.AcceptTOS,
|
||||
@@ -31,19 +45,33 @@ func NewManager(certDir, acmeURL string) *Manager {
|
||||
return mgr
|
||||
}
|
||||
|
||||
func (mgr *Manager) hostPolicy(_ context.Context, domain string) error {
|
||||
func (mgr *Manager) hostPolicy(ctx context.Context, domain string) error {
|
||||
mgr.domainsMux.RLock()
|
||||
defer mgr.domainsMux.RUnlock()
|
||||
if _, exists := mgr.domains[domain]; exists {
|
||||
return nil
|
||||
info, exists := mgr.domains[domain]
|
||||
mgr.domainsMux.RUnlock()
|
||||
if !exists {
|
||||
return fmt.Errorf("unknown domain %q", domain)
|
||||
}
|
||||
return fmt.Errorf("unknown domain %q", domain)
|
||||
|
||||
if mgr.certNotifier != nil {
|
||||
if err := mgr.certNotifier.NotifyCertificateIssued(ctx, info.accountID, info.reverseProxyID, domain); err != nil {
|
||||
log.Warnf("failed to notify certificate issued for domain %q: %v", domain, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mgr *Manager) AddDomain(domain string) {
|
||||
func (mgr *Manager) AddDomain(domain, accountID, reverseProxyID string) {
|
||||
mgr.domainsMux.Lock()
|
||||
defer mgr.domainsMux.Unlock()
|
||||
mgr.domains[domain] = struct{}{}
|
||||
mgr.domains[domain] = struct {
|
||||
accountID string
|
||||
reverseProxyID string
|
||||
}{
|
||||
accountID: accountID,
|
||||
reverseProxyID: reverseProxyID,
|
||||
}
|
||||
}
|
||||
|
||||
func (mgr *Manager) RemoveDomain(domain string) {
|
||||
|
||||
@@ -17,6 +17,10 @@ import (
|
||||
|
||||
const deviceNamePrefix = "ingress-"
|
||||
|
||||
type statusNotifier interface {
|
||||
NotifyStatus(ctx context.Context, accountID, reverseProxyID, domain string, connected bool) error
|
||||
}
|
||||
|
||||
// NetBird provides an http.RoundTripper implementation
|
||||
// backed by underlying NetBird connections.
|
||||
type NetBird struct {
|
||||
@@ -25,20 +29,23 @@ type NetBird struct {
|
||||
|
||||
clientsMux sync.RWMutex
|
||||
clients map[string]*embed.Client
|
||||
|
||||
statusNotifier statusNotifier
|
||||
}
|
||||
|
||||
func NewNetBird(mgmtAddr string, logger *log.Logger) *NetBird {
|
||||
func NewNetBird(mgmtAddr string, logger *log.Logger, notifier statusNotifier) *NetBird {
|
||||
if logger == nil {
|
||||
logger = log.StandardLogger()
|
||||
}
|
||||
return &NetBird{
|
||||
mgmtAddr: mgmtAddr,
|
||||
logger: logger,
|
||||
clients: make(map[string]*embed.Client),
|
||||
mgmtAddr: mgmtAddr,
|
||||
logger: logger,
|
||||
clients: make(map[string]*embed.Client),
|
||||
statusNotifier: notifier,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NetBird) AddPeer(ctx context.Context, domain, key string) error {
|
||||
func (n *NetBird) AddPeer(ctx context.Context, domain, key, accountID, reverseProxyID string) error {
|
||||
client, err := embed.New(embed.Options{
|
||||
DeviceName: deviceNamePrefix + domain,
|
||||
ManagementURL: n.mgmtAddr,
|
||||
@@ -64,6 +71,16 @@ func (n *NetBird) AddPeer(ctx context.Context, domain, key string) error {
|
||||
return
|
||||
case err != nil:
|
||||
n.logger.WithField("domain", domain).WithError(err).Error("Unable to start netbird client, will try again later.")
|
||||
return
|
||||
}
|
||||
|
||||
// Notify management that tunnel is now active
|
||||
if n.statusNotifier != nil {
|
||||
if err := n.statusNotifier.NotifyStatus(ctx, accountID, reverseProxyID, domain, true); err != nil {
|
||||
n.logger.WithField("domain", domain).WithError(err).Warn("Failed to notify management about tunnel connection")
|
||||
} else {
|
||||
n.logger.WithField("domain", domain).Info("Successfully notified management about tunnel connection")
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -73,7 +90,7 @@ func (n *NetBird) AddPeer(ctx context.Context, domain, key string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NetBird) RemovePeer(ctx context.Context, domain string) error {
|
||||
func (n *NetBird) RemovePeer(ctx context.Context, domain, accountID, reverseProxyID string) error {
|
||||
n.clientsMux.RLock()
|
||||
client, exists := n.clients[domain]
|
||||
n.clientsMux.RUnlock()
|
||||
@@ -84,6 +101,16 @@ func (n *NetBird) RemovePeer(ctx context.Context, domain string) error {
|
||||
if err := client.Stop(ctx); err != nil {
|
||||
return fmt.Errorf("stop netbird client: %w", err)
|
||||
}
|
||||
|
||||
// Notify management that tunnel is disconnected
|
||||
if n.statusNotifier != nil {
|
||||
if err := n.statusNotifier.NotifyStatus(ctx, accountID, reverseProxyID, domain, false); err != nil {
|
||||
n.logger.WithField("domain", domain).WithError(err).Warn("Failed to notify management about tunnel disconnection")
|
||||
} else {
|
||||
n.logger.WithField("domain", domain).Info("Successfully notified management about tunnel disconnection")
|
||||
}
|
||||
}
|
||||
|
||||
n.clientsMux.Lock()
|
||||
defer n.clientsMux.Unlock()
|
||||
delete(n.clients, domain)
|
||||
|
||||
@@ -38,13 +38,13 @@ import (
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
mgmtConn *grpc.ClientConn
|
||||
proxy *proxy.ReverseProxy
|
||||
netbird *roundtrip.NetBird
|
||||
acme *acme.Manager
|
||||
auth *auth.Middleware
|
||||
http *http.Server
|
||||
https *http.Server
|
||||
mgmtClient proto.ProxyServiceClient
|
||||
proxy *proxy.ReverseProxy
|
||||
netbird *roundtrip.NetBird
|
||||
acme *acme.Manager
|
||||
auth *auth.Middleware
|
||||
http *http.Server
|
||||
https *http.Server
|
||||
|
||||
// Mostly used for debugging on management.
|
||||
startTime time.Time
|
||||
@@ -64,6 +64,33 @@ type Server struct {
|
||||
OIDCScopes []string
|
||||
}
|
||||
|
||||
// NotifyStatus sends a status update to management about tunnel connectivity
|
||||
func (s *Server) NotifyStatus(ctx context.Context, accountID, reverseProxyID, domain string, connected bool) error {
|
||||
status := proto.ProxyStatus_PROXY_STATUS_TUNNEL_NOT_CREATED
|
||||
if connected {
|
||||
status = proto.ProxyStatus_PROXY_STATUS_ACTIVE
|
||||
}
|
||||
|
||||
_, err := s.mgmtClient.SendStatusUpdate(ctx, &proto.SendStatusUpdateRequest{
|
||||
ReverseProxyId: reverseProxyID,
|
||||
AccountId: accountID,
|
||||
Status: status,
|
||||
CertificateIssued: false,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// NotifyCertificateIssued sends a notification to management that a certificate was issued
|
||||
func (s *Server) NotifyCertificateIssued(ctx context.Context, accountID, reverseProxyID, domain string) error {
|
||||
_, err := s.mgmtClient.SendStatusUpdate(ctx, &proto.SendStatusUpdateRequest{
|
||||
ReverseProxyId: reverseProxyID,
|
||||
AccountId: accountID,
|
||||
Status: proto.ProxyStatus_PROXY_STATUS_ACTIVE,
|
||||
CertificateIssued: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Server) ListenAndServe(ctx context.Context, addr string) (err error) {
|
||||
s.startTime = time.Now()
|
||||
|
||||
@@ -105,7 +132,7 @@ func (s *Server) ListenAndServe(ctx context.Context, addr string) (err error) {
|
||||
"gRPC_address": mgmtURL.Host,
|
||||
"TLS_enabled": mgmtURL.Scheme == "https",
|
||||
}).Debug("starting management gRPC client")
|
||||
s.mgmtConn, err = grpc.NewClient(mgmtURL.Host,
|
||||
mgmtConn, err := grpc.NewClient(mgmtURL.Host,
|
||||
grpc.WithTransportCredentials(creds),
|
||||
grpc.WithKeepaliveParams(keepalive.ClientParameters{
|
||||
Time: 20 * time.Second,
|
||||
@@ -116,18 +143,18 @@ func (s *Server) ListenAndServe(ctx context.Context, addr string) (err error) {
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create management connection: %w", err)
|
||||
}
|
||||
mgmtClient := proto.NewProxyServiceClient(s.mgmtConn)
|
||||
go s.newManagementMappingWorker(ctx, mgmtClient)
|
||||
s.mgmtClient = proto.NewProxyServiceClient(mgmtConn)
|
||||
go s.newManagementMappingWorker(ctx, s.mgmtClient)
|
||||
|
||||
// Initialize the netbird client, this is required to build peer connections
|
||||
// to proxy over.
|
||||
s.netbird = roundtrip.NewNetBird(s.ManagementAddress, s.Logger)
|
||||
s.netbird = roundtrip.NewNetBird(s.ManagementAddress, s.Logger, s)
|
||||
|
||||
// When generating ACME certificates, start a challenge server.
|
||||
tlsConfig := &tls.Config{}
|
||||
if s.GenerateACMECertificates {
|
||||
s.Logger.WithField("acme_server", s.ACMEDirectory).Debug("ACME certificates enabled, configuring certificate manager")
|
||||
s.acme = acme.NewManager(s.CertificateDirectory, s.ACMEDirectory)
|
||||
s.acme = acme.NewManager(s.CertificateDirectory, s.ACMEDirectory, s)
|
||||
s.http = &http.Server{
|
||||
Addr: s.ACMEChallengeAddress,
|
||||
Handler: s.acme.HTTPHandler(nil),
|
||||
@@ -175,7 +202,7 @@ func (s *Server) ListenAndServe(ctx context.Context, addr string) (err error) {
|
||||
s.auth = auth.NewMiddleware()
|
||||
|
||||
// Configure Access logs to management server.
|
||||
accessLog := accesslog.NewLogger(mgmtClient, s.Logger)
|
||||
accessLog := accesslog.NewLogger(s.mgmtClient, s.Logger)
|
||||
|
||||
// Finally, start the reverse proxy.
|
||||
s.https = &http.Server{
|
||||
@@ -279,11 +306,15 @@ func (s *Server) handleMappingStream(ctx context.Context, mappingClient proto.Pr
|
||||
}
|
||||
|
||||
func (s *Server) addMapping(ctx context.Context, mapping *proto.ProxyMapping) error {
|
||||
if err := s.netbird.AddPeer(ctx, mapping.GetDomain(), mapping.GetSetupKey()); err != nil {
|
||||
return fmt.Errorf("create peer for domain %q: %w", mapping.GetDomain(), err)
|
||||
domain := mapping.GetDomain()
|
||||
accountID := mapping.GetAccountId()
|
||||
reverseProxyID := mapping.GetId()
|
||||
|
||||
if err := s.netbird.AddPeer(ctx, domain, mapping.GetSetupKey(), accountID, reverseProxyID); err != nil {
|
||||
return fmt.Errorf("create peer for domain %q: %w", domain, err)
|
||||
}
|
||||
if s.acme != nil {
|
||||
s.acme.AddDomain(mapping.GetDomain())
|
||||
s.acme.AddDomain(domain, accountID, reverseProxyID)
|
||||
}
|
||||
|
||||
// Pass the mapping through to the update function to avoid duplicating the
|
||||
@@ -299,13 +330,12 @@ func (s *Server) updateMapping(ctx context.Context, mapping *proto.ProxyMapping)
|
||||
// the auth and proxy mappings.
|
||||
// Note: this does require the management server to always send a
|
||||
// full mapping rather than deltas during a modification.
|
||||
mgmtClient := proto.NewProxyServiceClient(s.mgmtConn)
|
||||
var schemes []auth.Scheme
|
||||
if mapping.GetAuth().GetPassword() {
|
||||
schemes = append(schemes, auth.NewPassword(mgmtClient, mapping.GetId(), mapping.GetAccountId()))
|
||||
schemes = append(schemes, auth.NewPassword(s.mgmtClient, mapping.GetId(), mapping.GetAccountId()))
|
||||
}
|
||||
if mapping.GetAuth().GetPin() {
|
||||
schemes = append(schemes, auth.NewPin(mgmtClient, mapping.GetId(), mapping.GetAccountId()))
|
||||
schemes = append(schemes, auth.NewPin(s.mgmtClient, mapping.GetId(), mapping.GetAccountId()))
|
||||
}
|
||||
if mapping.GetAuth().GetOidc() != nil {
|
||||
oidc := mapping.GetAuth().GetOidc()
|
||||
@@ -323,14 +353,14 @@ func (s *Server) updateMapping(ctx context.Context, mapping *proto.ProxyMapping)
|
||||
}
|
||||
}
|
||||
if mapping.GetAuth().GetLink() {
|
||||
schemes = append(schemes, auth.NewLink(mgmtClient, mapping.GetId(), mapping.GetAccountId()))
|
||||
schemes = append(schemes, auth.NewLink(s.mgmtClient, mapping.GetId(), mapping.GetAccountId()))
|
||||
}
|
||||
s.auth.AddDomain(mapping.GetDomain(), schemes)
|
||||
s.proxy.AddMapping(s.protoToMapping(mapping))
|
||||
}
|
||||
|
||||
func (s *Server) removeMapping(ctx context.Context, mapping *proto.ProxyMapping) {
|
||||
if err := s.netbird.RemovePeer(ctx, mapping.GetDomain()); err != nil {
|
||||
if err := s.netbird.RemovePeer(ctx, mapping.GetDomain(), mapping.GetAccountId(), mapping.GetId()); err != nil {
|
||||
s.Logger.WithFields(log.Fields{
|
||||
"domain": mapping.GetDomain(),
|
||||
"error": err,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.21.12
|
||||
// protoc v6.33.0
|
||||
// source: proxy_service.proto
|
||||
|
||||
package proto
|
||||
@@ -70,6 +70,64 @@ func (ProxyMappingUpdateType) EnumDescriptor() ([]byte, []int) {
|
||||
return file_proxy_service_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
type ProxyStatus int32
|
||||
|
||||
const (
|
||||
ProxyStatus_PROXY_STATUS_PENDING ProxyStatus = 0
|
||||
ProxyStatus_PROXY_STATUS_ACTIVE ProxyStatus = 1
|
||||
ProxyStatus_PROXY_STATUS_TUNNEL_NOT_CREATED ProxyStatus = 2
|
||||
ProxyStatus_PROXY_STATUS_CERTIFICATE_PENDING ProxyStatus = 3
|
||||
ProxyStatus_PROXY_STATUS_CERTIFICATE_FAILED ProxyStatus = 4
|
||||
ProxyStatus_PROXY_STATUS_ERROR ProxyStatus = 5
|
||||
)
|
||||
|
||||
// Enum value maps for ProxyStatus.
|
||||
var (
|
||||
ProxyStatus_name = map[int32]string{
|
||||
0: "PROXY_STATUS_PENDING",
|
||||
1: "PROXY_STATUS_ACTIVE",
|
||||
2: "PROXY_STATUS_TUNNEL_NOT_CREATED",
|
||||
3: "PROXY_STATUS_CERTIFICATE_PENDING",
|
||||
4: "PROXY_STATUS_CERTIFICATE_FAILED",
|
||||
5: "PROXY_STATUS_ERROR",
|
||||
}
|
||||
ProxyStatus_value = map[string]int32{
|
||||
"PROXY_STATUS_PENDING": 0,
|
||||
"PROXY_STATUS_ACTIVE": 1,
|
||||
"PROXY_STATUS_TUNNEL_NOT_CREATED": 2,
|
||||
"PROXY_STATUS_CERTIFICATE_PENDING": 3,
|
||||
"PROXY_STATUS_CERTIFICATE_FAILED": 4,
|
||||
"PROXY_STATUS_ERROR": 5,
|
||||
}
|
||||
)
|
||||
|
||||
func (x ProxyStatus) Enum() *ProxyStatus {
|
||||
p := new(ProxyStatus)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x ProxyStatus) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (ProxyStatus) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_proxy_service_proto_enumTypes[1].Descriptor()
|
||||
}
|
||||
|
||||
func (ProxyStatus) Type() protoreflect.EnumType {
|
||||
return &file_proxy_service_proto_enumTypes[1]
|
||||
}
|
||||
|
||||
func (x ProxyStatus) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ProxyStatus.Descriptor instead.
|
||||
func (ProxyStatus) EnumDescriptor() ([]byte, []int) {
|
||||
return file_proxy_service_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
// GetMappingUpdateRequest is sent to initialise a mapping stream.
|
||||
type GetMappingUpdateRequest struct {
|
||||
state protoimpl.MessageState
|
||||
@@ -997,6 +1055,125 @@ func (x *AuthenticateResponse) GetSuccess() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// SendStatusUpdateRequest is sent by the proxy to update its status
|
||||
type SendStatusUpdateRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
ReverseProxyId string `protobuf:"bytes,1,opt,name=reverse_proxy_id,json=reverseProxyId,proto3" json:"reverse_proxy_id,omitempty"`
|
||||
AccountId string `protobuf:"bytes,2,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"`
|
||||
Status ProxyStatus `protobuf:"varint,3,opt,name=status,proto3,enum=management.ProxyStatus" json:"status,omitempty"`
|
||||
CertificateIssued bool `protobuf:"varint,4,opt,name=certificate_issued,json=certificateIssued,proto3" json:"certificate_issued,omitempty"`
|
||||
ErrorMessage *string `protobuf:"bytes,5,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SendStatusUpdateRequest) Reset() {
|
||||
*x = SendStatusUpdateRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proxy_service_proto_msgTypes[14]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SendStatusUpdateRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SendStatusUpdateRequest) ProtoMessage() {}
|
||||
|
||||
func (x *SendStatusUpdateRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proxy_service_proto_msgTypes[14]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SendStatusUpdateRequest.ProtoReflect.Descriptor instead.
|
||||
func (*SendStatusUpdateRequest) Descriptor() ([]byte, []int) {
|
||||
return file_proxy_service_proto_rawDescGZIP(), []int{14}
|
||||
}
|
||||
|
||||
func (x *SendStatusUpdateRequest) GetReverseProxyId() string {
|
||||
if x != nil {
|
||||
return x.ReverseProxyId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *SendStatusUpdateRequest) GetAccountId() string {
|
||||
if x != nil {
|
||||
return x.AccountId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *SendStatusUpdateRequest) GetStatus() ProxyStatus {
|
||||
if x != nil {
|
||||
return x.Status
|
||||
}
|
||||
return ProxyStatus_PROXY_STATUS_PENDING
|
||||
}
|
||||
|
||||
func (x *SendStatusUpdateRequest) GetCertificateIssued() bool {
|
||||
if x != nil {
|
||||
return x.CertificateIssued
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *SendStatusUpdateRequest) GetErrorMessage() string {
|
||||
if x != nil && x.ErrorMessage != nil {
|
||||
return *x.ErrorMessage
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// SendStatusUpdateResponse is intentionally empty to allow for future expansion
|
||||
type SendStatusUpdateResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *SendStatusUpdateResponse) Reset() {
|
||||
*x = SendStatusUpdateResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proxy_service_proto_msgTypes[15]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SendStatusUpdateResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SendStatusUpdateResponse) ProtoMessage() {}
|
||||
|
||||
func (x *SendStatusUpdateResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proxy_service_proto_msgTypes[15]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SendStatusUpdateResponse.ProtoReflect.Descriptor instead.
|
||||
func (*SendStatusUpdateResponse) Descriptor() ([]byte, []int) {
|
||||
return file_proxy_service_proto_rawDescGZIP(), []int{15}
|
||||
}
|
||||
|
||||
var File_proxy_service_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_proxy_service_proto_rawDesc = []byte{
|
||||
@@ -1110,32 +1287,68 @@ var file_proxy_service_proto_rawDesc = []byte{
|
||||
0x72, 0x65, 0x63, 0x74, 0x22, 0x30, 0x0a, 0x14, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07,
|
||||
0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73,
|
||||
0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2a, 0x64, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d,
|
||||
0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65,
|
||||
0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0xfe, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x6e, 0x64, 0x53,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x5f, 0x70, 0x72,
|
||||
0x6f, 0x78, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65,
|
||||
0x76, 0x65, 0x72, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a,
|
||||
0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x06, 0x73,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x61,
|
||||
0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74,
|
||||
0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2d, 0x0a, 0x12,
|
||||
0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x73, 0x73, 0x75,
|
||||
0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66,
|
||||
0x69, 0x63, 0x61, 0x74, 0x65, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x0d, 0x65,
|
||||
0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01,
|
||||
0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61,
|
||||
0x67, 0x65, 0x88, 0x01, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f,
|
||||
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x65, 0x6e, 0x64, 0x53,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x2a, 0x64, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x61, 0x70, 0x70,
|
||||
0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a,
|
||||
0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x52, 0x45,
|
||||
0x41, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45,
|
||||
0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x01,
|
||||
0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
|
||||
0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x50, 0x44,
|
||||
0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x49, 0x46, 0x49, 0x45,
|
||||
0x44, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59,
|
||||
0x50, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x02, 0x32, 0x98, 0x02, 0x0a,
|
||||
0x0c, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a,
|
||||
0x10, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x12, 0x23, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47,
|
||||
0x65, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70,
|
||||
0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x54,
|
||||
0x0a, 0x0d, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x12,
|
||||
0x20, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e,
|
||||
0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53,
|
||||
0x65, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x63, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x08, 0x5a, 0x06, 0x2f, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x02, 0x2a, 0xc8, 0x01, 0x0a, 0x0b, 0x50, 0x72,
|
||||
0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x52, 0x4f,
|
||||
0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e,
|
||||
0x47, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41,
|
||||
0x54, 0x55, 0x53, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f,
|
||||
0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x54, 0x55, 0x4e,
|
||||
0x4e, 0x45, 0x4c, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10,
|
||||
0x02, 0x12, 0x24, 0x0a, 0x20, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55,
|
||||
0x53, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x5f, 0x50, 0x45,
|
||||
0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x23, 0x0a, 0x1f, 0x50, 0x52, 0x4f, 0x58, 0x59,
|
||||
0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43,
|
||||
0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12,
|
||||
0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52,
|
||||
0x4f, 0x52, 0x10, 0x05, 0x32, 0xf7, 0x02, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x70,
|
||||
0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x23, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
|
||||
0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e,
|
||||
0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24,
|
||||
0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4d,
|
||||
0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x54, 0x0a, 0x0d, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63,
|
||||
0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x12, 0x20, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c,
|
||||
0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
|
||||
0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73,
|
||||
0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0c,
|
||||
0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x6d,
|
||||
0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e,
|
||||
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e,
|
||||
0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x5d, 0x0a, 0x10, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64,
|
||||
0x61, 0x74, 0x65, 0x12, 0x23, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x2e, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
|
||||
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x08,
|
||||
0x5a, 0x06, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -1150,49 +1363,55 @@ func file_proxy_service_proto_rawDescGZIP() []byte {
|
||||
return file_proxy_service_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_proxy_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_proxy_service_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
|
||||
var file_proxy_service_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||
var file_proxy_service_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
|
||||
var file_proxy_service_proto_goTypes = []interface{}{
|
||||
(ProxyMappingUpdateType)(0), // 0: management.ProxyMappingUpdateType
|
||||
(*GetMappingUpdateRequest)(nil), // 1: management.GetMappingUpdateRequest
|
||||
(*GetMappingUpdateResponse)(nil), // 2: management.GetMappingUpdateResponse
|
||||
(*PathMapping)(nil), // 3: management.PathMapping
|
||||
(*Authentication)(nil), // 4: management.Authentication
|
||||
(*OIDC)(nil), // 5: management.OIDC
|
||||
(*ProxyMapping)(nil), // 6: management.ProxyMapping
|
||||
(*SendAccessLogRequest)(nil), // 7: management.SendAccessLogRequest
|
||||
(*SendAccessLogResponse)(nil), // 8: management.SendAccessLogResponse
|
||||
(*AccessLog)(nil), // 9: management.AccessLog
|
||||
(*AuthenticateRequest)(nil), // 10: management.AuthenticateRequest
|
||||
(*PasswordRequest)(nil), // 11: management.PasswordRequest
|
||||
(*PinRequest)(nil), // 12: management.PinRequest
|
||||
(*LinkRequest)(nil), // 13: management.LinkRequest
|
||||
(*AuthenticateResponse)(nil), // 14: management.AuthenticateResponse
|
||||
(*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp
|
||||
(ProxyStatus)(0), // 1: management.ProxyStatus
|
||||
(*GetMappingUpdateRequest)(nil), // 2: management.GetMappingUpdateRequest
|
||||
(*GetMappingUpdateResponse)(nil), // 3: management.GetMappingUpdateResponse
|
||||
(*PathMapping)(nil), // 4: management.PathMapping
|
||||
(*Authentication)(nil), // 5: management.Authentication
|
||||
(*OIDC)(nil), // 6: management.OIDC
|
||||
(*ProxyMapping)(nil), // 7: management.ProxyMapping
|
||||
(*SendAccessLogRequest)(nil), // 8: management.SendAccessLogRequest
|
||||
(*SendAccessLogResponse)(nil), // 9: management.SendAccessLogResponse
|
||||
(*AccessLog)(nil), // 10: management.AccessLog
|
||||
(*AuthenticateRequest)(nil), // 11: management.AuthenticateRequest
|
||||
(*PasswordRequest)(nil), // 12: management.PasswordRequest
|
||||
(*PinRequest)(nil), // 13: management.PinRequest
|
||||
(*LinkRequest)(nil), // 14: management.LinkRequest
|
||||
(*AuthenticateResponse)(nil), // 15: management.AuthenticateResponse
|
||||
(*SendStatusUpdateRequest)(nil), // 16: management.SendStatusUpdateRequest
|
||||
(*SendStatusUpdateResponse)(nil), // 17: management.SendStatusUpdateResponse
|
||||
(*timestamppb.Timestamp)(nil), // 18: google.protobuf.Timestamp
|
||||
}
|
||||
var file_proxy_service_proto_depIdxs = []int32{
|
||||
15, // 0: management.GetMappingUpdateRequest.started_at:type_name -> google.protobuf.Timestamp
|
||||
6, // 1: management.GetMappingUpdateResponse.mapping:type_name -> management.ProxyMapping
|
||||
5, // 2: management.Authentication.oidc:type_name -> management.OIDC
|
||||
18, // 0: management.GetMappingUpdateRequest.started_at:type_name -> google.protobuf.Timestamp
|
||||
7, // 1: management.GetMappingUpdateResponse.mapping:type_name -> management.ProxyMapping
|
||||
6, // 2: management.Authentication.oidc:type_name -> management.OIDC
|
||||
0, // 3: management.ProxyMapping.type:type_name -> management.ProxyMappingUpdateType
|
||||
3, // 4: management.ProxyMapping.path:type_name -> management.PathMapping
|
||||
4, // 5: management.ProxyMapping.auth:type_name -> management.Authentication
|
||||
9, // 6: management.SendAccessLogRequest.log:type_name -> management.AccessLog
|
||||
15, // 7: management.AccessLog.timestamp:type_name -> google.protobuf.Timestamp
|
||||
11, // 8: management.AuthenticateRequest.password:type_name -> management.PasswordRequest
|
||||
12, // 9: management.AuthenticateRequest.pin:type_name -> management.PinRequest
|
||||
13, // 10: management.AuthenticateRequest.link:type_name -> management.LinkRequest
|
||||
1, // 11: management.ProxyService.GetMappingUpdate:input_type -> management.GetMappingUpdateRequest
|
||||
7, // 12: management.ProxyService.SendAccessLog:input_type -> management.SendAccessLogRequest
|
||||
10, // 13: management.ProxyService.Authenticate:input_type -> management.AuthenticateRequest
|
||||
2, // 14: management.ProxyService.GetMappingUpdate:output_type -> management.GetMappingUpdateResponse
|
||||
8, // 15: management.ProxyService.SendAccessLog:output_type -> management.SendAccessLogResponse
|
||||
14, // 16: management.ProxyService.Authenticate:output_type -> management.AuthenticateResponse
|
||||
14, // [14:17] is the sub-list for method output_type
|
||||
11, // [11:14] is the sub-list for method input_type
|
||||
11, // [11:11] is the sub-list for extension type_name
|
||||
11, // [11:11] is the sub-list for extension extendee
|
||||
0, // [0:11] is the sub-list for field type_name
|
||||
4, // 4: management.ProxyMapping.path:type_name -> management.PathMapping
|
||||
5, // 5: management.ProxyMapping.auth:type_name -> management.Authentication
|
||||
10, // 6: management.SendAccessLogRequest.log:type_name -> management.AccessLog
|
||||
18, // 7: management.AccessLog.timestamp:type_name -> google.protobuf.Timestamp
|
||||
12, // 8: management.AuthenticateRequest.password:type_name -> management.PasswordRequest
|
||||
13, // 9: management.AuthenticateRequest.pin:type_name -> management.PinRequest
|
||||
14, // 10: management.AuthenticateRequest.link:type_name -> management.LinkRequest
|
||||
1, // 11: management.SendStatusUpdateRequest.status:type_name -> management.ProxyStatus
|
||||
2, // 12: management.ProxyService.GetMappingUpdate:input_type -> management.GetMappingUpdateRequest
|
||||
8, // 13: management.ProxyService.SendAccessLog:input_type -> management.SendAccessLogRequest
|
||||
11, // 14: management.ProxyService.Authenticate:input_type -> management.AuthenticateRequest
|
||||
16, // 15: management.ProxyService.SendStatusUpdate:input_type -> management.SendStatusUpdateRequest
|
||||
3, // 16: management.ProxyService.GetMappingUpdate:output_type -> management.GetMappingUpdateResponse
|
||||
9, // 17: management.ProxyService.SendAccessLog:output_type -> management.SendAccessLogResponse
|
||||
15, // 18: management.ProxyService.Authenticate:output_type -> management.AuthenticateResponse
|
||||
17, // 19: management.ProxyService.SendStatusUpdate:output_type -> management.SendStatusUpdateResponse
|
||||
16, // [16:20] is the sub-list for method output_type
|
||||
12, // [12:16] is the sub-list for method input_type
|
||||
12, // [12:12] is the sub-list for extension type_name
|
||||
12, // [12:12] is the sub-list for extension extendee
|
||||
0, // [0:12] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_proxy_service_proto_init() }
|
||||
@@ -1369,6 +1588,30 @@ func file_proxy_service_proto_init() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proxy_service_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*SendStatusUpdateRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proxy_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*SendStatusUpdateResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
file_proxy_service_proto_msgTypes[3].OneofWrappers = []interface{}{}
|
||||
file_proxy_service_proto_msgTypes[9].OneofWrappers = []interface{}{
|
||||
@@ -1376,13 +1619,14 @@ func file_proxy_service_proto_init() {
|
||||
(*AuthenticateRequest_Pin)(nil),
|
||||
(*AuthenticateRequest_Link)(nil),
|
||||
}
|
||||
file_proxy_service_proto_msgTypes[14].OneofWrappers = []interface{}{}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_proxy_service_proto_rawDesc,
|
||||
NumEnums: 1,
|
||||
NumMessages: 14,
|
||||
NumEnums: 2,
|
||||
NumMessages: 16,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
||||
@@ -14,6 +14,8 @@ service ProxyService {
|
||||
rpc SendAccessLog(SendAccessLogRequest) returns (SendAccessLogResponse);
|
||||
|
||||
rpc Authenticate(AuthenticateRequest) returns (AuthenticateResponse);
|
||||
|
||||
rpc SendStatusUpdate(SendStatusUpdateRequest) returns (SendStatusUpdateResponse);
|
||||
}
|
||||
|
||||
// GetMappingUpdateRequest is sent to initialise a mapping stream.
|
||||
@@ -113,3 +115,24 @@ message LinkRequest {
|
||||
message AuthenticateResponse {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
enum ProxyStatus {
|
||||
PROXY_STATUS_PENDING = 0;
|
||||
PROXY_STATUS_ACTIVE = 1;
|
||||
PROXY_STATUS_TUNNEL_NOT_CREATED = 2;
|
||||
PROXY_STATUS_CERTIFICATE_PENDING = 3;
|
||||
PROXY_STATUS_CERTIFICATE_FAILED = 4;
|
||||
PROXY_STATUS_ERROR = 5;
|
||||
}
|
||||
|
||||
// SendStatusUpdateRequest is sent by the proxy to update its status
|
||||
message SendStatusUpdateRequest {
|
||||
string reverse_proxy_id = 1;
|
||||
string account_id = 2;
|
||||
ProxyStatus status = 3;
|
||||
bool certificate_issued = 4;
|
||||
optional string error_message = 5;
|
||||
}
|
||||
|
||||
// SendStatusUpdateResponse is intentionally empty to allow for future expansion
|
||||
message SendStatusUpdateResponse {}
|
||||
|
||||
@@ -21,6 +21,7 @@ type ProxyServiceClient interface {
|
||||
GetMappingUpdate(ctx context.Context, in *GetMappingUpdateRequest, opts ...grpc.CallOption) (ProxyService_GetMappingUpdateClient, error)
|
||||
SendAccessLog(ctx context.Context, in *SendAccessLogRequest, opts ...grpc.CallOption) (*SendAccessLogResponse, error)
|
||||
Authenticate(ctx context.Context, in *AuthenticateRequest, opts ...grpc.CallOption) (*AuthenticateResponse, error)
|
||||
SendStatusUpdate(ctx context.Context, in *SendStatusUpdateRequest, opts ...grpc.CallOption) (*SendStatusUpdateResponse, error)
|
||||
}
|
||||
|
||||
type proxyServiceClient struct {
|
||||
@@ -81,6 +82,15 @@ func (c *proxyServiceClient) Authenticate(ctx context.Context, in *AuthenticateR
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *proxyServiceClient) SendStatusUpdate(ctx context.Context, in *SendStatusUpdateRequest, opts ...grpc.CallOption) (*SendStatusUpdateResponse, error) {
|
||||
out := new(SendStatusUpdateResponse)
|
||||
err := c.cc.Invoke(ctx, "/management.ProxyService/SendStatusUpdate", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ProxyServiceServer is the server API for ProxyService service.
|
||||
// All implementations must embed UnimplementedProxyServiceServer
|
||||
// for forward compatibility
|
||||
@@ -88,6 +98,7 @@ type ProxyServiceServer interface {
|
||||
GetMappingUpdate(*GetMappingUpdateRequest, ProxyService_GetMappingUpdateServer) error
|
||||
SendAccessLog(context.Context, *SendAccessLogRequest) (*SendAccessLogResponse, error)
|
||||
Authenticate(context.Context, *AuthenticateRequest) (*AuthenticateResponse, error)
|
||||
SendStatusUpdate(context.Context, *SendStatusUpdateRequest) (*SendStatusUpdateResponse, error)
|
||||
mustEmbedUnimplementedProxyServiceServer()
|
||||
}
|
||||
|
||||
@@ -104,6 +115,9 @@ func (UnimplementedProxyServiceServer) SendAccessLog(context.Context, *SendAcces
|
||||
func (UnimplementedProxyServiceServer) Authenticate(context.Context, *AuthenticateRequest) (*AuthenticateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Authenticate not implemented")
|
||||
}
|
||||
func (UnimplementedProxyServiceServer) SendStatusUpdate(context.Context, *SendStatusUpdateRequest) (*SendStatusUpdateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SendStatusUpdate not implemented")
|
||||
}
|
||||
func (UnimplementedProxyServiceServer) mustEmbedUnimplementedProxyServiceServer() {}
|
||||
|
||||
// UnsafeProxyServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
@@ -174,6 +188,24 @@ func _ProxyService_Authenticate_Handler(srv interface{}, ctx context.Context, de
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ProxyService_SendStatusUpdate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SendStatusUpdateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ProxyServiceServer).SendStatusUpdate(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/management.ProxyService/SendStatusUpdate",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ProxyServiceServer).SendStatusUpdate(ctx, req.(*SendStatusUpdateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// ProxyService_ServiceDesc is the grpc.ServiceDesc for ProxyService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@@ -189,6 +221,10 @@ var ProxyService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "Authenticate",
|
||||
Handler: _ProxyService_Authenticate_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SendStatusUpdate",
|
||||
Handler: _ProxyService_SendStatusUpdate_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user