From 5f6db106ca8eaf0e797df27ee00a07b17ef2f8b4 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Fri, 31 Jul 2026 21:51:08 +0200 Subject: [PATCH] Add GRPC server to SMM --- README.md | 2 ++ globals/globals.go | 2 ++ grpc/api_key_interceptor.go | 26 ++++++++++++++++++++++++++ grpc/grpc_server.go | 34 ++++++++++++++++++++++++++++++++++ init.go | 17 +++++++++++++++++ main.go | 3 ++- 6 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 grpc/api_key_interceptor.go create mode 100644 grpc/grpc_server.go diff --git a/README.md b/README.md index 2627b6b..656bb57 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,8 @@ All configuration options are handled via environment variables | `PN_SMM_CONFIG_S3_ACCESS_SECRET` | S3 secret | Yes | | `PN_SMM_CONFIG_S3_BUCKET` | S3 bucket | Yes | | `PN_SMM_CONFIG_S3_KEY_BASE` | S3 Key prefix | Yes | +| `PN_SMM_GRPC_SERVER_PORT` | Port for the GRPC server | Yes | +| `PN_SMM_GRPC_API_KEY` | API key for your GRPC server | No (Assumed to be an open gRPC API) | | `PN_SMM_ACCOUNT_GRPC_HOST` | Host name for your account server gRPC service | Yes | | `PN_SMM_ACCOUNT_GRPC_PORT` | Port for your account server gRPC service | Yes | | `PN_SMM_ACCOUNT_GRPC_API_KEY` | API key for your account server gRPC service | No (Assumed to be an open gRPC API) | diff --git a/globals/globals.go b/globals/globals.go index 82152f0..ca30856 100644 --- a/globals/globals.go +++ b/globals/globals.go @@ -22,3 +22,5 @@ var GRPCAccountClient pb.AccountClient var GRPCAccountCommonMetadata metadata.MD var MinIOClient *minio.Client var Presigner *S3Presigner +var GRPCAPIKey string +var GRPCServerPort int diff --git a/grpc/api_key_interceptor.go b/grpc/api_key_interceptor.go new file mode 100644 index 0000000..961a95a --- /dev/null +++ b/grpc/api_key_interceptor.go @@ -0,0 +1,26 @@ +package grpc + +import ( + "context" + "errors" + + "github.com/PretendoNetwork/super-mario-maker/globals" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" +) + +func apiKeyInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + md, ok := metadata.FromIncomingContext(ctx) + + if ok { + apiKeyHeader := md.Get("X-API-Key") + + if len(apiKeyHeader) == 0 || apiKeyHeader[0] != globals.GRPCAPIKey { + return nil, errors.New("Missing or invalid API key") + } + } + + h, err := handler(ctx, req) + + return h, err +} diff --git a/grpc/grpc_server.go b/grpc/grpc_server.go new file mode 100644 index 0000000..c4a8ec4 --- /dev/null +++ b/grpc/grpc_server.go @@ -0,0 +1,34 @@ +package grpc + +import ( + "fmt" + "log" + "net" + + pb "github.com/PretendoNetwork/grpc/go/smm" + "github.com/PretendoNetwork/super-mario-maker/globals" + "google.golang.org/grpc" +) + +type gRPCSMMServer struct { + pb.UnimplementedSMMServer +} + +func StartGRPCServer() { + listener, err := net.Listen("tcp", fmt.Sprintf(":%d", globals.GRPCServerPort)) + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + + server := grpc.NewServer( + grpc.UnaryInterceptor(apiKeyInterceptor), + ) + + pb.RegisterSMMServer(server, &gRPCSMMServer{}) + + log.Printf("server listening at %v", listener.Addr()) + + if err := server.Serve(listener); err != nil { + log.Fatalf("failed to serve: %v", err) + } +} diff --git a/init.go b/init.go index ec2cad6..6fa1484 100644 --- a/init.go +++ b/init.go @@ -41,6 +41,8 @@ func init() { authenticationServerPort := os.Getenv("PN_SMM_AUTHENTICATION_SERVER_PORT") secureServerHost := os.Getenv("PN_SMM_SECURE_SERVER_HOST") secureServerPort := os.Getenv("PN_SMM_SECURE_SERVER_PORT") + gRPCServerPort := os.Getenv("PN_SMM_GRPC_SERVER_PORT") + gRPCAPIKey := os.Getenv("PN_SMM_GRPC_API_KEY") accountGRPCHost := os.Getenv("PN_SMM_ACCOUNT_GRPC_HOST") accountGRPCPort := os.Getenv("PN_SMM_ACCOUNT_GRPC_PORT") accountGRPCAPIKey := os.Getenv("PN_SMM_ACCOUNT_GRPC_API_KEY") @@ -93,6 +95,21 @@ func init() { os.Exit(0) } + gRPCPort, err := strconv.Atoi(gRPCServerPort) + if err != nil { + globals.Logger.Errorf("PN_SMM_GRPC_SERVER_PORT is not a valid port. Expected 0-65535, got %s", gRPCServerPort) + os.Exit(0) + } else if gRPCPort < 0 || gRPCPort > 65535 { + globals.Logger.Errorf("PN_SMM_GRPC_SERVER_PORT is not a valid port. Expected 0-65535, got %s", gRPCServerPort) + os.Exit(0) + } + globals.GRPCServerPort = gRPCPort; + + if strings.TrimSpace(gRPCAPIKey) == "" { + globals.Logger.Warning("Insecure gRPC server detected. PN_SMM_GRPC_API_KEY environment variable not set") + } + globals.GRPCAPIKey = gRPCAPIKey; + if strings.TrimSpace(accountGRPCHost) == "" { globals.Logger.Error("PN_SMM_ACCOUNT_GRPC_HOST environment variable not set") os.Exit(0) diff --git a/main.go b/main.go index 65258a4..edfa006 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "sync" + "github.com/PretendoNetwork/super-mario-maker/grpc" "github.com/PretendoNetwork/super-mario-maker/nex" ) @@ -11,7 +12,7 @@ var wg sync.WaitGroup func main() { wg.Add(2) - // TODO - Add gRPC server + go grpc.StartGRPCServer() go nex.StartAuthenticationServer() go nex.StartSecureServer()