NewGRPCServer new a gRPC server.
(c *conf.Server, authConf *conf.Auth, byteService *service.ByteStreamService, rSvc *service.ResourceService, providers backend.Providers, validator protovalidate.Validator, logger log.Logger)
| 52 | |
| 53 | // NewGRPCServer new a gRPC server. |
| 54 | func NewGRPCServer(c *conf.Server, authConf *conf.Auth, byteService *service.ByteStreamService, rSvc *service.ResourceService, providers backend.Providers, validator protovalidate.Validator, logger log.Logger) (*grpc.Server, error) { |
| 55 | log := log.NewHelper(logger) |
| 56 | // Load the key on initialization instead of on every request |
| 57 | // TODO: implement jwks endpoint |
| 58 | publicKeyPath := authConf.GetPublicKeyPath() |
| 59 | if publicKeyPath == "" { |
| 60 | // Maintain backwards compatibility |
| 61 | publicKeyPath = authConf.RobotAccountPublicKeyPath |
| 62 | } |
| 63 | |
| 64 | log.Debugw("msg", "loading public key from file", "file", publicKeyPath) |
| 65 | |
| 66 | rawKey, err := os.ReadFile(publicKeyPath) |
| 67 | if err != nil { |
| 68 | return nil, fmt.Errorf("failed to load public key: %w", err) |
| 69 | } |
| 70 | |
| 71 | var opts = []grpc.ServerOption{ |
| 72 | // Kratos middleware are in practice unary interceptors |
| 73 | grpc.Middleware( |
| 74 | recovery.Recovery( |
| 75 | recovery.WithHandler(func(ctx context.Context, req, err interface{}) error { |
| 76 | sentry.CaptureMessage(fmt.Sprintf("%v", err)) |
| 77 | return errors.InternalServer("internal error", "there was an internal error") |
| 78 | }), |
| 79 | ), |
| 80 | logging.Server(logger), |
| 81 | // NOTE: JWT middleware only works for unary requests |
| 82 | // below you can see a re-implementation of the middleware as a stream interceptor |
| 83 | // If we require a logged in user we |
| 84 | selector.Server( |
| 85 | jwtMiddleware.Server( |
| 86 | loadPublicKey(rawKey), |
| 87 | jwtMiddleware.WithSigningMethod(casJWT.SigningMethod), |
| 88 | jwtMiddleware.WithClaims(func() jwt.Claims { return &casJWT.Claims{} })), |
| 89 | ).Match(requireAuthentication()).Build(), |
| 90 | ), |
| 91 | |
| 92 | // Streaming interceptors |
| 93 | grpc.StreamInterceptor( |
| 94 | grpcselector.StreamServerInterceptor( |
| 95 | grpc_auth.StreamServerInterceptor(jwtAuthFunc(loadPublicKey(rawKey), casJWT.SigningMethod)), |
| 96 | grpcselector.MatchFunc(allButReflectionAPI), |
| 97 | ), |
| 98 | // grpc prometheus metrics |
| 99 | grpc_prometheus.StreamServerInterceptor, |
| 100 | ), |
| 101 | grpc.UnaryInterceptor( |
| 102 | grpc_prometheus.UnaryServerInterceptor, |
| 103 | protovalidateMiddleware.UnaryServerInterceptor(validator), |
| 104 | ), |
| 105 | grpc.Options(grpcLib.StatsHandler(otelgrpc.NewServerHandler())), |
| 106 | } |
| 107 | |
| 108 | // Opt-in histogram metrics for the interceptor |
| 109 | // Since we track uploads / downloads we'll increase the buckets |
| 110 | grpc_prometheus.EnableHandlingTimeHistogram(grpc_prometheus.WithHistogramBuckets(prometheus.ExponentialBucketsRange(0.5, 60, 8))) |
| 111 |
no test coverage detected