diff --git a/.claude/skills/checkpoint/SKILL.md b/.claude/skills/checkpoint/SKILL.md new file mode 100644 index 0000000..437dfeb --- /dev/null +++ b/.claude/skills/checkpoint/SKILL.md @@ -0,0 +1,8 @@ +# Checkpoint Skill + +1. Run `go build ./...` abort if errors +2. Run `go test ./...` abort if failures +3. Run `go vet ./...` +4. Run `git add -A && git status` show user what will be committed +5. Generate an appropriate commit message based on your instructions. +6. Run `git commit -m ""` and verify with `git log -1` \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index ab247d4..72f390c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -45,7 +45,7 @@ go test ./internal/sni -run TestExtract - `internal/proxy/` — bidirectional TCP relay with half-close propagation and idle timeout - `internal/server/` — orchestrates listeners → firewall → SNI → route → proxy pipeline; per-listener state with connection tracking - `internal/grpcserver/` — gRPC admin API: route/firewall CRUD, status, write-through to DB -- `proto/mc-proxy/v1/` — protobuf definitions; `gen/mc-proxy/v1/` has generated code +- `proto/mc_proxy/v1/` — protobuf definitions; `gen/mc_proxy/v1/` has generated code ## Signals diff --git a/Makefile b/Makefile index 344b288..08ad93d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: build test vet lint proto clean docker all devserver +.PHONY: build test vet lint proto proto-lint clean docker all devserver LDFLAGS := -trimpath -ldflags="-s -w -X main.version=$(shell git describe --tags --always --dirty)" @@ -20,7 +20,11 @@ lint: proto: protoc --go_out=. --go_opt=module=git.wntrmute.dev/kyle/mc-proxy \ --go-grpc_out=. --go-grpc_opt=module=git.wntrmute.dev/kyle/mc-proxy \ - proto/mc-proxy/v1/*.proto + proto/mc_proxy/v1/*.proto + +proto-lint: + buf lint + buf breaking --against '.git#branch=master,subdir=proto' clean: rm -f mc-proxy diff --git a/buf.yaml b/buf.yaml new file mode 100644 index 0000000..c7e30e3 --- /dev/null +++ b/buf.yaml @@ -0,0 +1,9 @@ +version: v2 +modules: + - path: proto +lint: + use: + - STANDARD +breaking: + use: + - FILE diff --git a/cmd/mc-proxy/root.go b/cmd/mc-proxy/root.go index 05d9369..7201d34 100644 --- a/cmd/mc-proxy/root.go +++ b/cmd/mc-proxy/root.go @@ -12,6 +12,7 @@ func rootCmd() *cobra.Command { } cmd.AddCommand(serverCmd()) + cmd.AddCommand(statusCmd()) cmd.AddCommand(snapshotCmd()) return cmd diff --git a/cmd/mc-proxy/status.go b/cmd/mc-proxy/status.go new file mode 100644 index 0000000..cf7c720 --- /dev/null +++ b/cmd/mc-proxy/status.go @@ -0,0 +1,101 @@ +package main + +import ( + "context" + "crypto/tls" + "crypto/x509" + "fmt" + "os" + "time" + + "github.com/spf13/cobra" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + + pb "git.wntrmute.dev/kyle/mc-proxy/gen/mc_proxy/v1" + "git.wntrmute.dev/kyle/mc-proxy/internal/config" +) + +func statusCmd() *cobra.Command { + var configPath string + + cmd := &cobra.Command{ + Use: "status", + Short: "Query a running instance's health and status", + RunE: func(cmd *cobra.Command, args []string) error { + cfg, err := config.Load(configPath) + if err != nil { + return err + } + + if cfg.GRPC.Addr == "" { + return fmt.Errorf("gRPC admin API is not configured (grpc.addr is empty)") + } + + conn, err := dialGRPC(cfg.GRPC) + if err != nil { + return fmt.Errorf("connecting to gRPC API: %w", err) + } + defer conn.Close() + + client := pb.NewProxyAdminServiceClient(conn) + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + resp, err := client.GetStatus(ctx, &pb.GetStatusRequest{}) + if err != nil { + return fmt.Errorf("getting status: %w", err) + } + + fmt.Printf("mc-proxy %s\n", resp.Version) + if resp.StartedAt != nil { + uptime := time.Since(resp.StartedAt.AsTime()).Truncate(time.Second) + fmt.Printf("uptime: %s\n", uptime) + } + fmt.Printf("connections: %d\n", resp.TotalConnections) + fmt.Println() + + for _, ls := range resp.Listeners { + fmt.Printf(" %s routes=%d active=%d\n", ls.Addr, ls.RouteCount, ls.ActiveConnections) + } + + return nil + }, + } + + cmd.Flags().StringVarP(&configPath, "config", "c", "mc-proxy.toml", "path to configuration file") + + return cmd +} + +func dialGRPC(cfg config.GRPC) (*grpc.ClientConn, error) { + tlsConfig := &tls.Config{ + MinVersion: tls.VersionTLS13, + } + + // Load CA cert for verifying the server. + if cfg.CACert != "" { + caCert, err := os.ReadFile(cfg.CACert) + if err != nil { + return nil, fmt.Errorf("reading CA cert: %w", err) + } + pool := x509.NewCertPool() + if !pool.AppendCertsFromPEM(caCert) { + return nil, fmt.Errorf("failed to parse CA certificate") + } + tlsConfig.RootCAs = pool + } + + // Load client cert for mTLS. + if cfg.TLSCert != "" && cfg.TLSKey != "" { + cert, err := tls.LoadX509KeyPair(cfg.TLSCert, cfg.TLSKey) + if err != nil { + return nil, fmt.Errorf("loading client cert: %w", err) + } + tlsConfig.Certificates = []tls.Certificate{cert} + } + + creds := credentials.NewTLS(tlsConfig) + return grpc.NewClient(cfg.Addr, grpc.WithTransportCredentials(creds)) +} diff --git a/deploy/scripts/install.sh b/deploy/scripts/install.sh index b563da8..53d2d95 100755 --- a/deploy/scripts/install.sh +++ b/deploy/scripts/install.sh @@ -21,6 +21,7 @@ echo "Installed ${BINARY}." # Create data directory structure. install -d -o "${SERVICE}" -g "${SERVICE}" -m 0700 "${DATA_DIR}" install -d -o "${SERVICE}" -g "${SERVICE}" -m 0700 "${DATA_DIR}/backups" +install -d -o "${SERVICE}" -g "${SERVICE}" -m 0700 "${DATA_DIR}/certs" echo "Created ${DATA_DIR}/." # Install example config if none exists. @@ -33,10 +34,14 @@ fi # Install systemd units. install -m 0644 "${REPO_DIR}/deploy/systemd/${SERVICE}.service" "${UNIT_DIR}/" +install -m 0644 "${REPO_DIR}/deploy/systemd/${SERVICE}-backup.service" "${UNIT_DIR}/" +install -m 0644 "${REPO_DIR}/deploy/systemd/${SERVICE}-backup.timer" "${UNIT_DIR}/" systemctl daemon-reload -echo "Installed systemd unit ${SERVICE}.service." +echo "Installed systemd units." echo "" echo "Done. Next steps:" echo " 1. Edit ${DATA_DIR}/${SERVICE}.toml" -echo " 2. systemctl enable --now ${SERVICE}" +echo " 2. Place TLS certs in ${DATA_DIR}/certs/ (if using gRPC admin API)" +echo " 3. systemctl enable --now ${SERVICE}" +echo " 4. systemctl enable --now ${SERVICE}-backup.timer" diff --git a/deploy/scripts/prune-backups.sh b/deploy/scripts/prune-backups.sh new file mode 100755 index 0000000..5e25912 --- /dev/null +++ b/deploy/scripts/prune-backups.sh @@ -0,0 +1,14 @@ +#!/bin/sh +set -eu + +# Prune mc-proxy database backups older than RETAIN_DAYS (default 30). +BACKUP_DIR="/srv/mc-proxy/backups" +RETAIN_DAYS="${1:-30}" + +if [ ! -d "${BACKUP_DIR}" ]; then + echo "Backup directory ${BACKUP_DIR} does not exist." + exit 0 +fi + +find "${BACKUP_DIR}" -name "mc-proxy-*.db" -type f -mtime "+${RETAIN_DAYS}" -delete +echo "Pruned backups older than ${RETAIN_DAYS} days from ${BACKUP_DIR}." diff --git a/deploy/systemd/mc-proxy-backup.service b/deploy/systemd/mc-proxy-backup.service new file mode 100644 index 0000000..9291ac2 --- /dev/null +++ b/deploy/systemd/mc-proxy-backup.service @@ -0,0 +1,25 @@ +[Unit] +Description=mc-proxy database backup +After=mc-proxy.service + +[Service] +Type=oneshot +User=mc-proxy +Group=mc-proxy +ExecStart=/usr/local/bin/mc-proxy snapshot --config /srv/mc-proxy/mc-proxy.toml +ExecStartPost=/usr/bin/find /srv/mc-proxy/backups -name "mc-proxy-*.db" -type f -mtime +30 -delete + +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=true +PrivateTmp=true +PrivateDevices=true +ProtectKernelTunables=true +ProtectKernelModules=true +ProtectControlGroups=true +RestrictSUIDSGID=true +RestrictNamespaces=true +LockPersonality=true +MemoryDenyWriteExecute=true +RestrictRealtime=true +ReadWritePaths=/srv/mc-proxy diff --git a/deploy/systemd/mc-proxy-backup.timer b/deploy/systemd/mc-proxy-backup.timer new file mode 100644 index 0000000..d452e7e --- /dev/null +++ b/deploy/systemd/mc-proxy-backup.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Daily mc-proxy database backup + +[Timer] +OnCalendar=*-*-* 02:00:00 UTC +RandomizedDelaySec=300 +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/gen/mc-proxy/v1/admin.pb.go b/gen/mc_proxy/v1/admin.pb.go similarity index 94% rename from gen/mc-proxy/v1/admin.pb.go rename to gen/mc_proxy/v1/admin.pb.go index 1d21a98..f6f30c3 100644 --- a/gen/mc-proxy/v1/admin.pb.go +++ b/gen/mc_proxy/v1/admin.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go v1.36.11 // protoc v6.33.4 -// source: proto/mc-proxy/v1/admin.proto +// source: proto/mc_proxy/v1/admin.proto package mcproxyv1 @@ -858,7 +858,7 @@ var File_proto_mc_proxy_v1_admin_proto protoreflect.FileDescriptor const file_proto_mc_proxy_v1_admin_proto_rawDesc = "" + "\n" + - "\x1dproto/mc-proxy/v1/admin.proto\x12\vmc_proxy.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"=\n" + + "\x1dproto/mc_proxy/v1/admin.proto\x12\vmc_proxy.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"=\n" + "\x05Route\x12\x1a\n" + "\bhostname\x18\x01 \x01(\tR\bhostname\x12\x18\n" + "\abackend\x18\x02 \x01(\tR\abackend\"8\n" + @@ -903,9 +903,8 @@ const file_proto_mc_proxy_v1_admin_proto_rawDesc = "" + "\x1eFIREWALL_RULE_TYPE_UNSPECIFIED\x10\x00\x12\x19\n" + "\x15FIREWALL_RULE_TYPE_IP\x10\x01\x12\x1b\n" + "\x17FIREWALL_RULE_TYPE_CIDR\x10\x02\x12\x1e\n" + - "\x1aFIREWALL_RULE_TYPE_COUNTRY\x10\x032\xe8\x04\n" + - "\n" + - "ProxyAdmin\x12M\n" + + "\x1aFIREWALL_RULE_TYPE_COUNTRY\x10\x032\xef\x04\n" + + "\x11ProxyAdminService\x12M\n" + "\n" + "ListRoutes\x12\x1e.mc_proxy.v1.ListRoutesRequest\x1a\x1f.mc_proxy.v1.ListRoutesResponse\x12G\n" + "\bAddRoute\x12\x1c.mc_proxy.v1.AddRouteRequest\x1a\x1d.mc_proxy.v1.AddRouteResponse\x12P\n" + @@ -913,7 +912,7 @@ const file_proto_mc_proxy_v1_admin_proto_rawDesc = "" + "\x10GetFirewallRules\x12$.mc_proxy.v1.GetFirewallRulesRequest\x1a%.mc_proxy.v1.GetFirewallRulesResponse\x12\\\n" + "\x0fAddFirewallRule\x12#.mc_proxy.v1.AddFirewallRuleRequest\x1a$.mc_proxy.v1.AddFirewallRuleResponse\x12e\n" + "\x12RemoveFirewallRule\x12&.mc_proxy.v1.RemoveFirewallRuleRequest\x1a'.mc_proxy.v1.RemoveFirewallRuleResponse\x12J\n" + - "\tGetStatus\x12\x1d.mc_proxy.v1.GetStatusRequest\x1a\x1e.mc_proxy.v1.GetStatusResponseB:Z8git.wntrmute.dev/kyle/mc-proxy/gen/mc-proxy/v1;mcproxyv1b\x06proto3" + "\tGetStatus\x12\x1d.mc_proxy.v1.GetStatusRequest\x1a\x1e.mc_proxy.v1.GetStatusResponseB:Z8git.wntrmute.dev/kyle/mc-proxy/gen/mc_proxy/v1;mcproxyv1b\x06proto3" var ( file_proto_mc_proxy_v1_admin_proto_rawDescOnce sync.Once @@ -959,20 +958,20 @@ var file_proto_mc_proxy_v1_admin_proto_depIdxs = []int32{ 8, // 5: mc_proxy.v1.RemoveFirewallRuleRequest.rule:type_name -> mc_proxy.v1.FirewallRule 18, // 6: mc_proxy.v1.GetStatusResponse.started_at:type_name -> google.protobuf.Timestamp 15, // 7: mc_proxy.v1.GetStatusResponse.listeners:type_name -> mc_proxy.v1.ListenerStatus - 2, // 8: mc_proxy.v1.ProxyAdmin.ListRoutes:input_type -> mc_proxy.v1.ListRoutesRequest - 4, // 9: mc_proxy.v1.ProxyAdmin.AddRoute:input_type -> mc_proxy.v1.AddRouteRequest - 6, // 10: mc_proxy.v1.ProxyAdmin.RemoveRoute:input_type -> mc_proxy.v1.RemoveRouteRequest - 9, // 11: mc_proxy.v1.ProxyAdmin.GetFirewallRules:input_type -> mc_proxy.v1.GetFirewallRulesRequest - 11, // 12: mc_proxy.v1.ProxyAdmin.AddFirewallRule:input_type -> mc_proxy.v1.AddFirewallRuleRequest - 13, // 13: mc_proxy.v1.ProxyAdmin.RemoveFirewallRule:input_type -> mc_proxy.v1.RemoveFirewallRuleRequest - 16, // 14: mc_proxy.v1.ProxyAdmin.GetStatus:input_type -> mc_proxy.v1.GetStatusRequest - 3, // 15: mc_proxy.v1.ProxyAdmin.ListRoutes:output_type -> mc_proxy.v1.ListRoutesResponse - 5, // 16: mc_proxy.v1.ProxyAdmin.AddRoute:output_type -> mc_proxy.v1.AddRouteResponse - 7, // 17: mc_proxy.v1.ProxyAdmin.RemoveRoute:output_type -> mc_proxy.v1.RemoveRouteResponse - 10, // 18: mc_proxy.v1.ProxyAdmin.GetFirewallRules:output_type -> mc_proxy.v1.GetFirewallRulesResponse - 12, // 19: mc_proxy.v1.ProxyAdmin.AddFirewallRule:output_type -> mc_proxy.v1.AddFirewallRuleResponse - 14, // 20: mc_proxy.v1.ProxyAdmin.RemoveFirewallRule:output_type -> mc_proxy.v1.RemoveFirewallRuleResponse - 17, // 21: mc_proxy.v1.ProxyAdmin.GetStatus:output_type -> mc_proxy.v1.GetStatusResponse + 2, // 8: mc_proxy.v1.ProxyAdminService.ListRoutes:input_type -> mc_proxy.v1.ListRoutesRequest + 4, // 9: mc_proxy.v1.ProxyAdminService.AddRoute:input_type -> mc_proxy.v1.AddRouteRequest + 6, // 10: mc_proxy.v1.ProxyAdminService.RemoveRoute:input_type -> mc_proxy.v1.RemoveRouteRequest + 9, // 11: mc_proxy.v1.ProxyAdminService.GetFirewallRules:input_type -> mc_proxy.v1.GetFirewallRulesRequest + 11, // 12: mc_proxy.v1.ProxyAdminService.AddFirewallRule:input_type -> mc_proxy.v1.AddFirewallRuleRequest + 13, // 13: mc_proxy.v1.ProxyAdminService.RemoveFirewallRule:input_type -> mc_proxy.v1.RemoveFirewallRuleRequest + 16, // 14: mc_proxy.v1.ProxyAdminService.GetStatus:input_type -> mc_proxy.v1.GetStatusRequest + 3, // 15: mc_proxy.v1.ProxyAdminService.ListRoutes:output_type -> mc_proxy.v1.ListRoutesResponse + 5, // 16: mc_proxy.v1.ProxyAdminService.AddRoute:output_type -> mc_proxy.v1.AddRouteResponse + 7, // 17: mc_proxy.v1.ProxyAdminService.RemoveRoute:output_type -> mc_proxy.v1.RemoveRouteResponse + 10, // 18: mc_proxy.v1.ProxyAdminService.GetFirewallRules:output_type -> mc_proxy.v1.GetFirewallRulesResponse + 12, // 19: mc_proxy.v1.ProxyAdminService.AddFirewallRule:output_type -> mc_proxy.v1.AddFirewallRuleResponse + 14, // 20: mc_proxy.v1.ProxyAdminService.RemoveFirewallRule:output_type -> mc_proxy.v1.RemoveFirewallRuleResponse + 17, // 21: mc_proxy.v1.ProxyAdminService.GetStatus:output_type -> mc_proxy.v1.GetStatusResponse 15, // [15:22] is the sub-list for method output_type 8, // [8:15] is the sub-list for method input_type 8, // [8:8] is the sub-list for extension type_name diff --git a/gen/mc-proxy/v1/admin_grpc.pb.go b/gen/mc_proxy/v1/admin_grpc.pb.go similarity index 50% rename from gen/mc-proxy/v1/admin_grpc.pb.go rename to gen/mc_proxy/v1/admin_grpc.pb.go index 0f80d57..c96d856 100644 --- a/gen/mc-proxy/v1/admin_grpc.pb.go +++ b/gen/mc_proxy/v1/admin_grpc.pb.go @@ -2,7 +2,7 @@ // versions: // - protoc-gen-go-grpc v1.6.1 // - protoc v6.33.4 -// source: proto/mc-proxy/v1/admin.proto +// source: proto/mc_proxy/v1/admin.proto package mcproxyv1 @@ -19,19 +19,19 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - ProxyAdmin_ListRoutes_FullMethodName = "/mc_proxy.v1.ProxyAdmin/ListRoutes" - ProxyAdmin_AddRoute_FullMethodName = "/mc_proxy.v1.ProxyAdmin/AddRoute" - ProxyAdmin_RemoveRoute_FullMethodName = "/mc_proxy.v1.ProxyAdmin/RemoveRoute" - ProxyAdmin_GetFirewallRules_FullMethodName = "/mc_proxy.v1.ProxyAdmin/GetFirewallRules" - ProxyAdmin_AddFirewallRule_FullMethodName = "/mc_proxy.v1.ProxyAdmin/AddFirewallRule" - ProxyAdmin_RemoveFirewallRule_FullMethodName = "/mc_proxy.v1.ProxyAdmin/RemoveFirewallRule" - ProxyAdmin_GetStatus_FullMethodName = "/mc_proxy.v1.ProxyAdmin/GetStatus" + ProxyAdminService_ListRoutes_FullMethodName = "/mc_proxy.v1.ProxyAdminService/ListRoutes" + ProxyAdminService_AddRoute_FullMethodName = "/mc_proxy.v1.ProxyAdminService/AddRoute" + ProxyAdminService_RemoveRoute_FullMethodName = "/mc_proxy.v1.ProxyAdminService/RemoveRoute" + ProxyAdminService_GetFirewallRules_FullMethodName = "/mc_proxy.v1.ProxyAdminService/GetFirewallRules" + ProxyAdminService_AddFirewallRule_FullMethodName = "/mc_proxy.v1.ProxyAdminService/AddFirewallRule" + ProxyAdminService_RemoveFirewallRule_FullMethodName = "/mc_proxy.v1.ProxyAdminService/RemoveFirewallRule" + ProxyAdminService_GetStatus_FullMethodName = "/mc_proxy.v1.ProxyAdminService/GetStatus" ) -// ProxyAdminClient is the client API for ProxyAdmin service. +// ProxyAdminServiceClient is the client API for ProxyAdminService 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 ProxyAdminClient interface { +type ProxyAdminServiceClient interface { // Routes ListRoutes(ctx context.Context, in *ListRoutesRequest, opts ...grpc.CallOption) (*ListRoutesResponse, error) AddRoute(ctx context.Context, in *AddRouteRequest, opts ...grpc.CallOption) (*AddRouteResponse, error) @@ -44,88 +44,88 @@ type ProxyAdminClient interface { GetStatus(ctx context.Context, in *GetStatusRequest, opts ...grpc.CallOption) (*GetStatusResponse, error) } -type proxyAdminClient struct { +type proxyAdminServiceClient struct { cc grpc.ClientConnInterface } -func NewProxyAdminClient(cc grpc.ClientConnInterface) ProxyAdminClient { - return &proxyAdminClient{cc} +func NewProxyAdminServiceClient(cc grpc.ClientConnInterface) ProxyAdminServiceClient { + return &proxyAdminServiceClient{cc} } -func (c *proxyAdminClient) ListRoutes(ctx context.Context, in *ListRoutesRequest, opts ...grpc.CallOption) (*ListRoutesResponse, error) { +func (c *proxyAdminServiceClient) ListRoutes(ctx context.Context, in *ListRoutesRequest, opts ...grpc.CallOption) (*ListRoutesResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ListRoutesResponse) - err := c.cc.Invoke(ctx, ProxyAdmin_ListRoutes_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ProxyAdminService_ListRoutes_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } return out, nil } -func (c *proxyAdminClient) AddRoute(ctx context.Context, in *AddRouteRequest, opts ...grpc.CallOption) (*AddRouteResponse, error) { +func (c *proxyAdminServiceClient) AddRoute(ctx context.Context, in *AddRouteRequest, opts ...grpc.CallOption) (*AddRouteResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(AddRouteResponse) - err := c.cc.Invoke(ctx, ProxyAdmin_AddRoute_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ProxyAdminService_AddRoute_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } return out, nil } -func (c *proxyAdminClient) RemoveRoute(ctx context.Context, in *RemoveRouteRequest, opts ...grpc.CallOption) (*RemoveRouteResponse, error) { +func (c *proxyAdminServiceClient) RemoveRoute(ctx context.Context, in *RemoveRouteRequest, opts ...grpc.CallOption) (*RemoveRouteResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(RemoveRouteResponse) - err := c.cc.Invoke(ctx, ProxyAdmin_RemoveRoute_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ProxyAdminService_RemoveRoute_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } return out, nil } -func (c *proxyAdminClient) GetFirewallRules(ctx context.Context, in *GetFirewallRulesRequest, opts ...grpc.CallOption) (*GetFirewallRulesResponse, error) { +func (c *proxyAdminServiceClient) GetFirewallRules(ctx context.Context, in *GetFirewallRulesRequest, opts ...grpc.CallOption) (*GetFirewallRulesResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetFirewallRulesResponse) - err := c.cc.Invoke(ctx, ProxyAdmin_GetFirewallRules_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ProxyAdminService_GetFirewallRules_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } return out, nil } -func (c *proxyAdminClient) AddFirewallRule(ctx context.Context, in *AddFirewallRuleRequest, opts ...grpc.CallOption) (*AddFirewallRuleResponse, error) { +func (c *proxyAdminServiceClient) AddFirewallRule(ctx context.Context, in *AddFirewallRuleRequest, opts ...grpc.CallOption) (*AddFirewallRuleResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(AddFirewallRuleResponse) - err := c.cc.Invoke(ctx, ProxyAdmin_AddFirewallRule_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ProxyAdminService_AddFirewallRule_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } return out, nil } -func (c *proxyAdminClient) RemoveFirewallRule(ctx context.Context, in *RemoveFirewallRuleRequest, opts ...grpc.CallOption) (*RemoveFirewallRuleResponse, error) { +func (c *proxyAdminServiceClient) RemoveFirewallRule(ctx context.Context, in *RemoveFirewallRuleRequest, opts ...grpc.CallOption) (*RemoveFirewallRuleResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(RemoveFirewallRuleResponse) - err := c.cc.Invoke(ctx, ProxyAdmin_RemoveFirewallRule_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ProxyAdminService_RemoveFirewallRule_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } return out, nil } -func (c *proxyAdminClient) GetStatus(ctx context.Context, in *GetStatusRequest, opts ...grpc.CallOption) (*GetStatusResponse, error) { +func (c *proxyAdminServiceClient) GetStatus(ctx context.Context, in *GetStatusRequest, opts ...grpc.CallOption) (*GetStatusResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetStatusResponse) - err := c.cc.Invoke(ctx, ProxyAdmin_GetStatus_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, ProxyAdminService_GetStatus_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } return out, nil } -// ProxyAdminServer is the server API for ProxyAdmin service. -// All implementations must embed UnimplementedProxyAdminServer +// ProxyAdminServiceServer is the server API for ProxyAdminService service. +// All implementations must embed UnimplementedProxyAdminServiceServer // for forward compatibility. -type ProxyAdminServer interface { +type ProxyAdminServiceServer interface { // Routes ListRoutes(context.Context, *ListRoutesRequest) (*ListRoutesResponse, error) AddRoute(context.Context, *AddRouteRequest) (*AddRouteResponse, error) @@ -136,220 +136,220 @@ type ProxyAdminServer interface { RemoveFirewallRule(context.Context, *RemoveFirewallRuleRequest) (*RemoveFirewallRuleResponse, error) // Status GetStatus(context.Context, *GetStatusRequest) (*GetStatusResponse, error) - mustEmbedUnimplementedProxyAdminServer() + mustEmbedUnimplementedProxyAdminServiceServer() } -// UnimplementedProxyAdminServer must be embedded to have +// UnimplementedProxyAdminServiceServer 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 UnimplementedProxyAdminServer struct{} +type UnimplementedProxyAdminServiceServer struct{} -func (UnimplementedProxyAdminServer) ListRoutes(context.Context, *ListRoutesRequest) (*ListRoutesResponse, error) { +func (UnimplementedProxyAdminServiceServer) ListRoutes(context.Context, *ListRoutesRequest) (*ListRoutesResponse, error) { return nil, status.Error(codes.Unimplemented, "method ListRoutes not implemented") } -func (UnimplementedProxyAdminServer) AddRoute(context.Context, *AddRouteRequest) (*AddRouteResponse, error) { +func (UnimplementedProxyAdminServiceServer) AddRoute(context.Context, *AddRouteRequest) (*AddRouteResponse, error) { return nil, status.Error(codes.Unimplemented, "method AddRoute not implemented") } -func (UnimplementedProxyAdminServer) RemoveRoute(context.Context, *RemoveRouteRequest) (*RemoveRouteResponse, error) { +func (UnimplementedProxyAdminServiceServer) RemoveRoute(context.Context, *RemoveRouteRequest) (*RemoveRouteResponse, error) { return nil, status.Error(codes.Unimplemented, "method RemoveRoute not implemented") } -func (UnimplementedProxyAdminServer) GetFirewallRules(context.Context, *GetFirewallRulesRequest) (*GetFirewallRulesResponse, error) { +func (UnimplementedProxyAdminServiceServer) GetFirewallRules(context.Context, *GetFirewallRulesRequest) (*GetFirewallRulesResponse, error) { return nil, status.Error(codes.Unimplemented, "method GetFirewallRules not implemented") } -func (UnimplementedProxyAdminServer) AddFirewallRule(context.Context, *AddFirewallRuleRequest) (*AddFirewallRuleResponse, error) { +func (UnimplementedProxyAdminServiceServer) AddFirewallRule(context.Context, *AddFirewallRuleRequest) (*AddFirewallRuleResponse, error) { return nil, status.Error(codes.Unimplemented, "method AddFirewallRule not implemented") } -func (UnimplementedProxyAdminServer) RemoveFirewallRule(context.Context, *RemoveFirewallRuleRequest) (*RemoveFirewallRuleResponse, error) { +func (UnimplementedProxyAdminServiceServer) RemoveFirewallRule(context.Context, *RemoveFirewallRuleRequest) (*RemoveFirewallRuleResponse, error) { return nil, status.Error(codes.Unimplemented, "method RemoveFirewallRule not implemented") } -func (UnimplementedProxyAdminServer) GetStatus(context.Context, *GetStatusRequest) (*GetStatusResponse, error) { +func (UnimplementedProxyAdminServiceServer) GetStatus(context.Context, *GetStatusRequest) (*GetStatusResponse, error) { return nil, status.Error(codes.Unimplemented, "method GetStatus not implemented") } -func (UnimplementedProxyAdminServer) mustEmbedUnimplementedProxyAdminServer() {} -func (UnimplementedProxyAdminServer) testEmbeddedByValue() {} +func (UnimplementedProxyAdminServiceServer) mustEmbedUnimplementedProxyAdminServiceServer() {} +func (UnimplementedProxyAdminServiceServer) testEmbeddedByValue() {} -// UnsafeProxyAdminServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to ProxyAdminServer will +// UnsafeProxyAdminServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ProxyAdminServiceServer will // result in compilation errors. -type UnsafeProxyAdminServer interface { - mustEmbedUnimplementedProxyAdminServer() +type UnsafeProxyAdminServiceServer interface { + mustEmbedUnimplementedProxyAdminServiceServer() } -func RegisterProxyAdminServer(s grpc.ServiceRegistrar, srv ProxyAdminServer) { - // If the following call panics, it indicates UnimplementedProxyAdminServer was +func RegisterProxyAdminServiceServer(s grpc.ServiceRegistrar, srv ProxyAdminServiceServer) { + // If the following call panics, it indicates UnimplementedProxyAdminServiceServer 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(&ProxyAdmin_ServiceDesc, srv) + s.RegisterService(&ProxyAdminService_ServiceDesc, srv) } -func _ProxyAdmin_ListRoutes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ProxyAdminService_ListRoutes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListRoutesRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(ProxyAdminServer).ListRoutes(ctx, in) + return srv.(ProxyAdminServiceServer).ListRoutes(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ProxyAdmin_ListRoutes_FullMethodName, + FullMethod: ProxyAdminService_ListRoutes_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ProxyAdminServer).ListRoutes(ctx, req.(*ListRoutesRequest)) + return srv.(ProxyAdminServiceServer).ListRoutes(ctx, req.(*ListRoutesRequest)) } return interceptor(ctx, in, info, handler) } -func _ProxyAdmin_AddRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ProxyAdminService_AddRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(AddRouteRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(ProxyAdminServer).AddRoute(ctx, in) + return srv.(ProxyAdminServiceServer).AddRoute(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ProxyAdmin_AddRoute_FullMethodName, + FullMethod: ProxyAdminService_AddRoute_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ProxyAdminServer).AddRoute(ctx, req.(*AddRouteRequest)) + return srv.(ProxyAdminServiceServer).AddRoute(ctx, req.(*AddRouteRequest)) } return interceptor(ctx, in, info, handler) } -func _ProxyAdmin_RemoveRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ProxyAdminService_RemoveRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RemoveRouteRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(ProxyAdminServer).RemoveRoute(ctx, in) + return srv.(ProxyAdminServiceServer).RemoveRoute(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ProxyAdmin_RemoveRoute_FullMethodName, + FullMethod: ProxyAdminService_RemoveRoute_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ProxyAdminServer).RemoveRoute(ctx, req.(*RemoveRouteRequest)) + return srv.(ProxyAdminServiceServer).RemoveRoute(ctx, req.(*RemoveRouteRequest)) } return interceptor(ctx, in, info, handler) } -func _ProxyAdmin_GetFirewallRules_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ProxyAdminService_GetFirewallRules_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetFirewallRulesRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(ProxyAdminServer).GetFirewallRules(ctx, in) + return srv.(ProxyAdminServiceServer).GetFirewallRules(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ProxyAdmin_GetFirewallRules_FullMethodName, + FullMethod: ProxyAdminService_GetFirewallRules_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ProxyAdminServer).GetFirewallRules(ctx, req.(*GetFirewallRulesRequest)) + return srv.(ProxyAdminServiceServer).GetFirewallRules(ctx, req.(*GetFirewallRulesRequest)) } return interceptor(ctx, in, info, handler) } -func _ProxyAdmin_AddFirewallRule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ProxyAdminService_AddFirewallRule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(AddFirewallRuleRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(ProxyAdminServer).AddFirewallRule(ctx, in) + return srv.(ProxyAdminServiceServer).AddFirewallRule(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ProxyAdmin_AddFirewallRule_FullMethodName, + FullMethod: ProxyAdminService_AddFirewallRule_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ProxyAdminServer).AddFirewallRule(ctx, req.(*AddFirewallRuleRequest)) + return srv.(ProxyAdminServiceServer).AddFirewallRule(ctx, req.(*AddFirewallRuleRequest)) } return interceptor(ctx, in, info, handler) } -func _ProxyAdmin_RemoveFirewallRule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ProxyAdminService_RemoveFirewallRule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RemoveFirewallRuleRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(ProxyAdminServer).RemoveFirewallRule(ctx, in) + return srv.(ProxyAdminServiceServer).RemoveFirewallRule(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ProxyAdmin_RemoveFirewallRule_FullMethodName, + FullMethod: ProxyAdminService_RemoveFirewallRule_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ProxyAdminServer).RemoveFirewallRule(ctx, req.(*RemoveFirewallRuleRequest)) + return srv.(ProxyAdminServiceServer).RemoveFirewallRule(ctx, req.(*RemoveFirewallRuleRequest)) } return interceptor(ctx, in, info, handler) } -func _ProxyAdmin_GetStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _ProxyAdminService_GetStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetStatusRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(ProxyAdminServer).GetStatus(ctx, in) + return srv.(ProxyAdminServiceServer).GetStatus(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ProxyAdmin_GetStatus_FullMethodName, + FullMethod: ProxyAdminService_GetStatus_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ProxyAdminServer).GetStatus(ctx, req.(*GetStatusRequest)) + return srv.(ProxyAdminServiceServer).GetStatus(ctx, req.(*GetStatusRequest)) } return interceptor(ctx, in, info, handler) } -// ProxyAdmin_ServiceDesc is the grpc.ServiceDesc for ProxyAdmin service. +// ProxyAdminService_ServiceDesc is the grpc.ServiceDesc for ProxyAdminService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) -var ProxyAdmin_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "mc_proxy.v1.ProxyAdmin", - HandlerType: (*ProxyAdminServer)(nil), +var ProxyAdminService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "mc_proxy.v1.ProxyAdminService", + HandlerType: (*ProxyAdminServiceServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "ListRoutes", - Handler: _ProxyAdmin_ListRoutes_Handler, + Handler: _ProxyAdminService_ListRoutes_Handler, }, { MethodName: "AddRoute", - Handler: _ProxyAdmin_AddRoute_Handler, + Handler: _ProxyAdminService_AddRoute_Handler, }, { MethodName: "RemoveRoute", - Handler: _ProxyAdmin_RemoveRoute_Handler, + Handler: _ProxyAdminService_RemoveRoute_Handler, }, { MethodName: "GetFirewallRules", - Handler: _ProxyAdmin_GetFirewallRules_Handler, + Handler: _ProxyAdminService_GetFirewallRules_Handler, }, { MethodName: "AddFirewallRule", - Handler: _ProxyAdmin_AddFirewallRule_Handler, + Handler: _ProxyAdminService_AddFirewallRule_Handler, }, { MethodName: "RemoveFirewallRule", - Handler: _ProxyAdmin_RemoveFirewallRule_Handler, + Handler: _ProxyAdminService_RemoveFirewallRule_Handler, }, { MethodName: "GetStatus", - Handler: _ProxyAdmin_GetStatus_Handler, + Handler: _ProxyAdminService_GetStatus_Handler, }, }, Streams: []grpc.StreamDesc{}, - Metadata: "proto/mc-proxy/v1/admin.proto", + Metadata: "proto/mc_proxy/v1/admin.proto", } diff --git a/internal/config/config.go b/internal/config/config.go index fc9d1a1..3f34f7d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -25,7 +25,8 @@ type GRPC struct { Addr string `toml:"addr"` TLSCert string `toml:"tls_cert"` TLSKey string `toml:"tls_key"` - ClientCA string `toml:"client_ca"` + CACert string `toml:"ca_cert"` // CA cert for verifying the server (client-side) + ClientCA string `toml:"client_ca"` // CA cert for verifying clients (server-side mTLS) } type Listener struct { diff --git a/internal/grpcserver/grpcserver.go b/internal/grpcserver/grpcserver.go index 8c5350d..a0cff93 100644 --- a/internal/grpcserver/grpcserver.go +++ b/internal/grpcserver/grpcserver.go @@ -16,7 +16,7 @@ import ( "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" - pb "git.wntrmute.dev/kyle/mc-proxy/gen/mc-proxy/v1" + pb "git.wntrmute.dev/kyle/mc-proxy/gen/mc_proxy/v1" "git.wntrmute.dev/kyle/mc-proxy/internal/config" "git.wntrmute.dev/kyle/mc-proxy/internal/db" "git.wntrmute.dev/kyle/mc-proxy/internal/server" @@ -24,7 +24,7 @@ import ( // AdminServer implements the ProxyAdmin gRPC service. type AdminServer struct { - pb.UnimplementedProxyAdminServer + pb.UnimplementedProxyAdminServiceServer srv *server.Server store *db.Store logger *slog.Logger @@ -63,7 +63,7 @@ func New(cfg config.GRPC, srv *server.Server, store *db.Store, logger *slog.Logg store: store, logger: logger, } - pb.RegisterProxyAdminServer(grpcServer, admin) + pb.RegisterProxyAdminServiceServer(grpcServer, admin) ln, err := net.Listen("tcp", cfg.Addr) if err != nil { diff --git a/proto/mc-proxy/v1/admin.proto b/proto/mc_proxy/v1/admin.proto similarity index 95% rename from proto/mc-proxy/v1/admin.proto rename to proto/mc_proxy/v1/admin.proto index 89009e3..e65bdd9 100644 --- a/proto/mc-proxy/v1/admin.proto +++ b/proto/mc_proxy/v1/admin.proto @@ -2,11 +2,11 @@ syntax = "proto3"; package mc_proxy.v1; -option go_package = "git.wntrmute.dev/kyle/mc-proxy/gen/mc-proxy/v1;mcproxyv1"; +option go_package = "git.wntrmute.dev/kyle/mc-proxy/gen/mc_proxy/v1;mcproxyv1"; import "google/protobuf/timestamp.proto"; -service ProxyAdmin { +service ProxyAdminService { // Routes rpc ListRoutes(ListRoutesRequest) returns (ListRoutesResponse); rpc AddRoute(AddRouteRequest) returns (AddRouteResponse);