Skip to content

Commit 615b2a9

Browse files
Change local credentials server into credentials proxy
1 parent 9f4033d commit 615b2a9

File tree

3 files changed

+140
-143
lines changed

3 files changed

+140
-143
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package local
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net"
7+
"net/http"
8+
"net/http/httputil"
9+
"net/url"
10+
"time"
11+
12+
"github.com/loft-sh/log"
13+
"tailscale.com/tsnet"
14+
)
15+
16+
const (
17+
// Listen on this port via tsnet.
18+
LocalCredentialsServerPort = 9999 // FIXME - use random prot
19+
// Target server: local gRPC server running on port 5555.
20+
TargetServer = "http://localhost:5555" // FIXME - get port from request
21+
)
22+
23+
// LocalCredentialsServerProxy acts as a reverse proxy that blindly forwards
24+
// all incoming traffic to the local gRPC server on port 5555.
25+
type LocalCredentialsServerProxy struct {
26+
log log.Logger
27+
tsServer *tsnet.Server
28+
29+
ln net.Listener
30+
srv *http.Server
31+
}
32+
33+
// NewLocalCredentialsServerProxy initializes a new LocalCredentialsServerProxy.
34+
func NewLocalCredentialsServerProxy(tsServer *tsnet.Server, log log.Logger) (*LocalCredentialsServerProxy, error) {
35+
return &LocalCredentialsServerProxy{
36+
log: log,
37+
tsServer: tsServer,
38+
}, nil
39+
}
40+
41+
// Listen creates the tsnet listener and HTTP server,
42+
// and registers a catch-all handler that acts as the reverse proxy.
43+
func (s *LocalCredentialsServerProxy) Listen(ctx context.Context) error {
44+
s.log.Info("Starting reverse proxy for local gRPC server")
45+
46+
// Create a tsnet listener.
47+
ln, err := s.tsServer.Listen("tcp", fmt.Sprintf(":%d", LocalCredentialsServerPort))
48+
if err != nil {
49+
s.log.Infof("Failed to listen on tsnet port %d: %v", LocalCredentialsServerPort, err)
50+
return fmt.Errorf("failed to listen on tsnet port %d: %w", LocalCredentialsServerPort, err)
51+
}
52+
s.ln = ln
53+
54+
mux := http.NewServeMux()
55+
mux.HandleFunc("/", s.handleReverseProxy)
56+
57+
// Create the HTTP server.
58+
s.srv = &http.Server{
59+
Handler: mux,
60+
}
61+
62+
go func() {
63+
<-ctx.Done()
64+
s.log.Info("Context canceled, shutting down reverse proxy")
65+
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
66+
defer cancel()
67+
if err := s.srv.Shutdown(shutdownCtx); err != nil {
68+
s.log.Errorf("Error shutting down reverse proxy: %v", err)
69+
}
70+
}()
71+
72+
s.log.Infof("Reverse proxy listening on tsnet port %d", LocalCredentialsServerPort)
73+
err = s.srv.Serve(ln)
74+
if err != nil && err != http.ErrServerClosed {
75+
s.log.Errorf("Reverse proxy error: %v", err)
76+
return err
77+
}
78+
79+
return nil
80+
}
81+
82+
// handleReverseProxy forwards every request to the target gRPC server.
83+
func (s *LocalCredentialsServerProxy) handleReverseProxy(w http.ResponseWriter, r *http.Request) {
84+
s.log.Infof("Forwarding request %s %s to target server", r.Method, r.URL.String())
85+
86+
// Parse the target URL.
87+
targetURL, err := url.Parse(TargetServer)
88+
if err != nil {
89+
s.log.Errorf("Error parsing target URL %s: %v", TargetServer, err)
90+
http.Error(w, "Bad Gateway", http.StatusBadGateway)
91+
return
92+
}
93+
94+
// Create the reverse proxy.
95+
proxy := httputil.NewSingleHostReverseProxy(targetURL)
96+
97+
// Customize the director to forward the Host header to the target.
98+
originalDirector := proxy.Director
99+
proxy.Director = func(req *http.Request) {
100+
originalDirector(req)
101+
req.Host = targetURL.Host
102+
}
103+
104+
// Use an error handler to log any errors that occur.
105+
proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
106+
s.log.Errorf("Reverse proxy error: %v", err)
107+
http.Error(w, "Bad Gateway", http.StatusBadGateway)
108+
}
109+
110+
// Forward the request.
111+
proxy.ServeHTTP(w, r)
112+
}
113+
114+
// Close gracefully shuts down the reverse proxy.
115+
func (s *LocalCredentialsServerProxy) Close() error {
116+
s.log.Info("Closing reverse proxy")
117+
if s.srv != nil {
118+
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
119+
defer cancel()
120+
if err := s.srv.Shutdown(shutdownCtx); err != nil {
121+
s.log.Errorf("Error during reverse proxy shutdown: %v", err)
122+
return err
123+
}
124+
}
125+
return nil
126+
}

pkg/daemon/local/credentials_server.go

Lines changed: 0 additions & 129 deletions
This file was deleted.

pkg/daemon/local/daemon.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ import (
2323
)
2424

2525
type Daemon struct {
26-
socketListener net.Listener
27-
tsServer *tsnet.Server
28-
localServer *localServer
29-
credentialsServer *LocalCredentialsServer
30-
rootDir string
31-
log log.Logger
26+
socketListener net.Listener
27+
tsServer *tsnet.Server
28+
localServer *localServer
29+
credentialsServerProxy *LocalCredentialsServerProxy
30+
rootDir string
31+
log log.Logger
3232
}
3333

3434
type InitConfig struct {
@@ -63,18 +63,18 @@ func Init(ctx context.Context, config InitConfig) (*Daemon, error) {
6363
return nil, fmt.Errorf("create local server: %w", err)
6464
}
6565

66-
credentialsServer, err := NewLocalCredentialsServer(tsServer, log)
66+
credentialsProxy, err := NewLocalCredentialsServerProxy(tsServer, log)
6767
if err != nil {
6868
return nil, fmt.Errorf("create local credentials server: %w", err)
6969
}
7070

7171
return &Daemon{
72-
socketListener: socketListener,
73-
tsServer: tsServer,
74-
localServer: localServer,
75-
credentialsServer: credentialsServer,
76-
rootDir: config.RootDir,
77-
log: log,
72+
socketListener: socketListener,
73+
tsServer: tsServer,
74+
localServer: localServer,
75+
credentialsServerProxy: credentialsProxy,
76+
rootDir: config.RootDir,
77+
log: log,
7878
}, nil
7979
}
8080
func (d *Daemon) Start(ctx context.Context) error {
@@ -94,7 +94,7 @@ func (d *Daemon) Start(ctx context.Context) error {
9494
}()
9595
go func() {
9696
d.log.Info("Start credentials server")
97-
errChan <- d.credentialsServer.Listen(ctx)
97+
errChan <- d.credentialsServerProxy.Listen(ctx)
9898
}()
9999
defer func() {
100100
d.log.Info("Cleaning up daemon resources")

0 commit comments

Comments
 (0)