github.com/cilium/cilium@v1.16.2/pkg/hubble/server/server.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Hubble
     3  
     4  package server
     5  
     6  import (
     7  	"crypto/tls"
     8  	"errors"
     9  	"fmt"
    10  
    11  	"github.com/sirupsen/logrus"
    12  	"google.golang.org/grpc"
    13  	"google.golang.org/grpc/credentials"
    14  	healthpb "google.golang.org/grpc/health/grpc_health_v1"
    15  	"google.golang.org/grpc/reflection"
    16  
    17  	observerpb "github.com/cilium/cilium/api/v1/observer"
    18  	peerpb "github.com/cilium/cilium/api/v1/peer"
    19  	recorderpb "github.com/cilium/cilium/api/v1/recorder"
    20  	"github.com/cilium/cilium/pkg/hubble/server/serveroption"
    21  )
    22  
    23  var (
    24  	errNoListener        = errors.New("no listener configured")
    25  	errNoServerTLSConfig = errors.New("no server TLS config is set")
    26  )
    27  
    28  // Server is hubble's gRPC server.
    29  type Server struct {
    30  	log  logrus.FieldLogger
    31  	srv  *grpc.Server
    32  	opts serveroption.Options
    33  }
    34  
    35  // NewServer creates a new hubble gRPC server.
    36  func NewServer(log logrus.FieldLogger, options ...serveroption.Option) (*Server, error) {
    37  	opts := serveroption.Options{}
    38  	for _, opt := range options {
    39  		if err := opt(&opts); err != nil {
    40  			return nil, fmt.Errorf("failed to apply option: %w", err)
    41  		}
    42  	}
    43  	if opts.Listener == nil {
    44  		return nil, errNoListener
    45  	}
    46  	if opts.ServerTLSConfig == nil && !opts.Insecure {
    47  		return nil, errNoServerTLSConfig
    48  	}
    49  
    50  	s := &Server{log: log, opts: opts}
    51  	if err := s.initGRPCServer(); err != nil {
    52  		return nil, err
    53  	}
    54  	return s, nil
    55  }
    56  
    57  func (s *Server) newGRPCServer() (*grpc.Server, error) {
    58  	var opts []grpc.ServerOption
    59  	for _, interceptor := range s.opts.GRPCUnaryInterceptors {
    60  		opts = append(opts, grpc.UnaryInterceptor(interceptor))
    61  	}
    62  	for _, interceptor := range s.opts.GRPCStreamInterceptors {
    63  		opts = append(opts, grpc.StreamInterceptor(interceptor))
    64  	}
    65  	if s.opts.ServerTLSConfig != nil {
    66  		// NOTE: gosec is unable to resolve the constant and warns about "TLS
    67  		// MinVersion too low".
    68  		tlsConfig := s.opts.ServerTLSConfig.ServerConfig(&tls.Config{ //nolint:gosec
    69  			MinVersion: serveroption.MinTLSVersion,
    70  		})
    71  		opts = append(opts, grpc.Creds(credentials.NewTLS(tlsConfig)))
    72  	}
    73  	return grpc.NewServer(opts...), nil
    74  }
    75  
    76  func (s *Server) initGRPCServer() error {
    77  	srv, err := s.newGRPCServer()
    78  	if err != nil {
    79  		return err
    80  	}
    81  	if s.opts.HealthService != nil {
    82  		healthpb.RegisterHealthServer(srv, s.opts.HealthService)
    83  	}
    84  	if s.opts.ObserverService != nil {
    85  		observerpb.RegisterObserverServer(srv, s.opts.ObserverService)
    86  	}
    87  	if s.opts.PeerService != nil {
    88  		peerpb.RegisterPeerServer(srv, s.opts.PeerService)
    89  	}
    90  	if s.opts.RecorderService != nil {
    91  		recorderpb.RegisterRecorderServer(srv, s.opts.RecorderService)
    92  	}
    93  	reflection.Register(srv)
    94  	if s.opts.GRPCMetrics != nil {
    95  		s.opts.GRPCMetrics.InitializeMetrics(srv)
    96  	}
    97  	s.srv = srv
    98  	return nil
    99  }
   100  
   101  // Serve starts the hubble server and accepts new connections on the configured
   102  // listener. Stop should be called to stop the server.
   103  func (s *Server) Serve() error {
   104  	return s.srv.Serve(s.opts.Listener)
   105  }
   106  
   107  // Stop stops the hubble server.
   108  func (s *Server) Stop() {
   109  	s.srv.Stop()
   110  }