Switch gRPC admin API to Unix socket only, add client package
- Remove TCP listener support from gRPC server; Unix socket is now the only transport for the admin API (access controlled via filesystem permissions) - Add standard gRPC health check service (grpc.health.v1.Health) - Implement MCPROXY_* environment variable overrides for config - Create client/mcproxy package with full API coverage and tests - Update ARCHITECTURE.md and dev config (srv/mc-proxy.toml) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,8 +2,6 @@ package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net"
|
||||
@@ -14,7 +12,8 @@ import (
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/health"
|
||||
healthpb "google.golang.org/grpc/health/grpc_health_v1"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
@@ -34,8 +33,16 @@ type AdminServer struct {
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
// New creates a gRPC server. For Unix sockets, no TLS is used. For TCP
|
||||
// addresses, TLS is required with optional mTLS.
|
||||
// NewAdminServer creates an AdminServer for use in testing or custom setups.
|
||||
func NewAdminServer(srv *server.Server, store *db.Store, logger *slog.Logger) *AdminServer {
|
||||
return &AdminServer{
|
||||
srv: srv,
|
||||
store: store,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// New creates a gRPC server listening on a Unix socket.
|
||||
func New(cfg config.GRPC, srv *server.Server, store *db.Store, logger *slog.Logger) (*grpc.Server, net.Listener, error) {
|
||||
admin := &AdminServer{
|
||||
srv: srv,
|
||||
@@ -43,13 +50,6 @@ func New(cfg config.GRPC, srv *server.Server, store *db.Store, logger *slog.Logg
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
if cfg.IsUnixSocket() {
|
||||
return newUnixServer(cfg, admin)
|
||||
}
|
||||
return newTCPServer(cfg, admin)
|
||||
}
|
||||
|
||||
func newUnixServer(cfg config.GRPC, admin *AdminServer) (*grpc.Server, net.Listener, error) {
|
||||
path := cfg.SocketPath()
|
||||
|
||||
// Remove stale socket file from a previous run.
|
||||
@@ -67,41 +67,12 @@ func newUnixServer(cfg config.GRPC, admin *AdminServer) (*grpc.Server, net.Liste
|
||||
|
||||
grpcServer := grpc.NewServer()
|
||||
pb.RegisterProxyAdminServiceServer(grpcServer, admin)
|
||||
return grpcServer, ln, nil
|
||||
}
|
||||
|
||||
func newTCPServer(cfg config.GRPC, admin *AdminServer) (*grpc.Server, net.Listener, error) {
|
||||
cert, err := tls.LoadX509KeyPair(cfg.TLSCert, cfg.TLSKey)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("loading TLS keypair: %w", err)
|
||||
}
|
||||
|
||||
tlsConfig := &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
MinVersion: tls.VersionTLS13,
|
||||
}
|
||||
|
||||
if cfg.ClientCA != "" {
|
||||
caCert, err := os.ReadFile(cfg.ClientCA)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("reading client CA: %w", err)
|
||||
}
|
||||
pool := x509.NewCertPool()
|
||||
if !pool.AppendCertsFromPEM(caCert) {
|
||||
return nil, nil, fmt.Errorf("failed to parse client CA certificate")
|
||||
}
|
||||
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
|
||||
tlsConfig.ClientCAs = pool
|
||||
}
|
||||
|
||||
creds := credentials.NewTLS(tlsConfig)
|
||||
grpcServer := grpc.NewServer(grpc.Creds(creds))
|
||||
pb.RegisterProxyAdminServiceServer(grpcServer, admin)
|
||||
|
||||
ln, err := net.Listen("tcp", cfg.Addr)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("listening on %s: %w", cfg.Addr, err)
|
||||
}
|
||||
// Register standard gRPC health check service.
|
||||
healthServer := health.NewServer()
|
||||
healthServer.SetServingStatus("", healthpb.HealthCheckResponse_SERVING)
|
||||
healthServer.SetServingStatus("mc_proxy.v1.ProxyAdminService", healthpb.HealthCheckResponse_SERVING)
|
||||
healthpb.RegisterHealthServer(grpcServer, healthServer)
|
||||
|
||||
return grpcServer, ln, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user