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

     1  // Code generated by go-swagger; DO NOT EDIT.
     2  
     3  // Copyright Authors of Cilium
     4  // SPDX-License-Identifier: Apache-2.0
     5  
     6  package server
     7  
     8  import (
     9  	"context"
    10  	"crypto/tls"
    11  	"crypto/x509"
    12  	"errors"
    13  	"fmt"
    14  	"log"
    15  	"net"
    16  	"net/http"
    17  	"os"
    18  	"strconv"
    19  	"sync"
    20  	"time"
    21  
    22  	"github.com/go-openapi/loads"
    23  	"github.com/go-openapi/runtime/middleware"
    24  	"github.com/go-openapi/swag"
    25  	"github.com/sirupsen/logrus"
    26  	"github.com/spf13/pflag"
    27  	"golang.org/x/net/netutil"
    28  
    29  	"github.com/cilium/cilium/api/v1/server/restapi"
    30  	"github.com/cilium/cilium/api/v1/server/restapi/bgp"
    31  	"github.com/cilium/cilium/api/v1/server/restapi/daemon"
    32  	"github.com/cilium/cilium/api/v1/server/restapi/endpoint"
    33  	"github.com/cilium/cilium/api/v1/server/restapi/ipam"
    34  	"github.com/cilium/cilium/api/v1/server/restapi/metrics"
    35  	"github.com/cilium/cilium/api/v1/server/restapi/policy"
    36  	"github.com/cilium/cilium/api/v1/server/restapi/prefilter"
    37  	"github.com/cilium/cilium/api/v1/server/restapi/recorder"
    38  	"github.com/cilium/cilium/api/v1/server/restapi/service"
    39  	"github.com/cilium/hive/cell"
    40  
    41  	"github.com/cilium/cilium/pkg/api"
    42  	"github.com/cilium/cilium/pkg/hive"
    43  )
    44  
    45  // Cell implements the cilium API REST API server when provided
    46  // the required request handlers.
    47  var Cell = cell.Module(
    48  	"cilium-api-server",
    49  	"cilium API server",
    50  
    51  	cell.Provide(newForCell),
    52  	APICell,
    53  )
    54  
    55  // APICell provides the restapi.CiliumAPIAPI type, populated
    56  // with the request handlers. This cell is an alternative to 'Cell' when only
    57  // the API type is required and not the full server implementation.
    58  var APICell = cell.Provide(newAPI)
    59  
    60  type apiParams struct {
    61  	cell.In
    62  
    63  	Spec *Spec
    64  
    65  	Middleware middleware.Builder `name:"cilium-api-middleware" optional:"true"`
    66  
    67  	EndpointDeleteEndpointHandler        endpoint.DeleteEndpointHandler
    68  	EndpointDeleteEndpointIDHandler      endpoint.DeleteEndpointIDHandler
    69  	PolicyDeleteFqdnCacheHandler         policy.DeleteFqdnCacheHandler
    70  	IpamDeleteIpamIPHandler              ipam.DeleteIpamIPHandler
    71  	PolicyDeletePolicyHandler            policy.DeletePolicyHandler
    72  	PrefilterDeletePrefilterHandler      prefilter.DeletePrefilterHandler
    73  	RecorderDeleteRecorderIDHandler      recorder.DeleteRecorderIDHandler
    74  	ServiceDeleteServiceIDHandler        service.DeleteServiceIDHandler
    75  	BgpGetBgpPeersHandler                bgp.GetBgpPeersHandler
    76  	BgpGetBgpRoutePoliciesHandler        bgp.GetBgpRoutePoliciesHandler
    77  	BgpGetBgpRoutesHandler               bgp.GetBgpRoutesHandler
    78  	DaemonGetCgroupDumpMetadataHandler   daemon.GetCgroupDumpMetadataHandler
    79  	DaemonGetClusterNodesHandler         daemon.GetClusterNodesHandler
    80  	DaemonGetConfigHandler               daemon.GetConfigHandler
    81  	DaemonGetDebuginfoHandler            daemon.GetDebuginfoHandler
    82  	EndpointGetEndpointHandler           endpoint.GetEndpointHandler
    83  	EndpointGetEndpointIDHandler         endpoint.GetEndpointIDHandler
    84  	EndpointGetEndpointIDConfigHandler   endpoint.GetEndpointIDConfigHandler
    85  	EndpointGetEndpointIDHealthzHandler  endpoint.GetEndpointIDHealthzHandler
    86  	EndpointGetEndpointIDLabelsHandler   endpoint.GetEndpointIDLabelsHandler
    87  	EndpointGetEndpointIDLogHandler      endpoint.GetEndpointIDLogHandler
    88  	PolicyGetFqdnCacheHandler            policy.GetFqdnCacheHandler
    89  	PolicyGetFqdnCacheIDHandler          policy.GetFqdnCacheIDHandler
    90  	PolicyGetFqdnNamesHandler            policy.GetFqdnNamesHandler
    91  	DaemonGetHealthzHandler              daemon.GetHealthzHandler
    92  	PolicyGetIPHandler                   policy.GetIPHandler
    93  	PolicyGetIdentityHandler             policy.GetIdentityHandler
    94  	PolicyGetIdentityEndpointsHandler    policy.GetIdentityEndpointsHandler
    95  	PolicyGetIdentityIDHandler           policy.GetIdentityIDHandler
    96  	ServiceGetLrpHandler                 service.GetLrpHandler
    97  	DaemonGetMapHandler                  daemon.GetMapHandler
    98  	DaemonGetMapNameHandler              daemon.GetMapNameHandler
    99  	DaemonGetMapNameEventsHandler        daemon.GetMapNameEventsHandler
   100  	MetricsGetMetricsHandler             metrics.GetMetricsHandler
   101  	DaemonGetNodeIdsHandler              daemon.GetNodeIdsHandler
   102  	PolicyGetPolicyHandler               policy.GetPolicyHandler
   103  	PolicyGetPolicySelectorsHandler      policy.GetPolicySelectorsHandler
   104  	PrefilterGetPrefilterHandler         prefilter.GetPrefilterHandler
   105  	RecorderGetRecorderHandler           recorder.GetRecorderHandler
   106  	RecorderGetRecorderIDHandler         recorder.GetRecorderIDHandler
   107  	RecorderGetRecorderMasksHandler      recorder.GetRecorderMasksHandler
   108  	ServiceGetServiceHandler             service.GetServiceHandler
   109  	ServiceGetServiceIDHandler           service.GetServiceIDHandler
   110  	DaemonPatchConfigHandler             daemon.PatchConfigHandler
   111  	EndpointPatchEndpointIDHandler       endpoint.PatchEndpointIDHandler
   112  	EndpointPatchEndpointIDConfigHandler endpoint.PatchEndpointIDConfigHandler
   113  	EndpointPatchEndpointIDLabelsHandler endpoint.PatchEndpointIDLabelsHandler
   114  	PrefilterPatchPrefilterHandler       prefilter.PatchPrefilterHandler
   115  	IpamPostIpamHandler                  ipam.PostIpamHandler
   116  	IpamPostIpamIPHandler                ipam.PostIpamIPHandler
   117  	EndpointPutEndpointIDHandler         endpoint.PutEndpointIDHandler
   118  	PolicyPutPolicyHandler               policy.PutPolicyHandler
   119  	RecorderPutRecorderIDHandler         recorder.PutRecorderIDHandler
   120  	ServicePutServiceIDHandler           service.PutServiceIDHandler
   121  }
   122  
   123  func newAPI(p apiParams) *restapi.CiliumAPIAPI {
   124  	api := restapi.NewCiliumAPIAPI(p.Spec.Document)
   125  
   126  	// Construct the API from the provided handlers
   127  
   128  	api.EndpointDeleteEndpointHandler = p.EndpointDeleteEndpointHandler
   129  	api.EndpointDeleteEndpointIDHandler = p.EndpointDeleteEndpointIDHandler
   130  	api.PolicyDeleteFqdnCacheHandler = p.PolicyDeleteFqdnCacheHandler
   131  	api.IpamDeleteIpamIPHandler = p.IpamDeleteIpamIPHandler
   132  	api.PolicyDeletePolicyHandler = p.PolicyDeletePolicyHandler
   133  	api.PrefilterDeletePrefilterHandler = p.PrefilterDeletePrefilterHandler
   134  	api.RecorderDeleteRecorderIDHandler = p.RecorderDeleteRecorderIDHandler
   135  	api.ServiceDeleteServiceIDHandler = p.ServiceDeleteServiceIDHandler
   136  	api.BgpGetBgpPeersHandler = p.BgpGetBgpPeersHandler
   137  	api.BgpGetBgpRoutePoliciesHandler = p.BgpGetBgpRoutePoliciesHandler
   138  	api.BgpGetBgpRoutesHandler = p.BgpGetBgpRoutesHandler
   139  	api.DaemonGetCgroupDumpMetadataHandler = p.DaemonGetCgroupDumpMetadataHandler
   140  	api.DaemonGetClusterNodesHandler = p.DaemonGetClusterNodesHandler
   141  	api.DaemonGetConfigHandler = p.DaemonGetConfigHandler
   142  	api.DaemonGetDebuginfoHandler = p.DaemonGetDebuginfoHandler
   143  	api.EndpointGetEndpointHandler = p.EndpointGetEndpointHandler
   144  	api.EndpointGetEndpointIDHandler = p.EndpointGetEndpointIDHandler
   145  	api.EndpointGetEndpointIDConfigHandler = p.EndpointGetEndpointIDConfigHandler
   146  	api.EndpointGetEndpointIDHealthzHandler = p.EndpointGetEndpointIDHealthzHandler
   147  	api.EndpointGetEndpointIDLabelsHandler = p.EndpointGetEndpointIDLabelsHandler
   148  	api.EndpointGetEndpointIDLogHandler = p.EndpointGetEndpointIDLogHandler
   149  	api.PolicyGetFqdnCacheHandler = p.PolicyGetFqdnCacheHandler
   150  	api.PolicyGetFqdnCacheIDHandler = p.PolicyGetFqdnCacheIDHandler
   151  	api.PolicyGetFqdnNamesHandler = p.PolicyGetFqdnNamesHandler
   152  	api.DaemonGetHealthzHandler = p.DaemonGetHealthzHandler
   153  	api.PolicyGetIPHandler = p.PolicyGetIPHandler
   154  	api.PolicyGetIdentityHandler = p.PolicyGetIdentityHandler
   155  	api.PolicyGetIdentityEndpointsHandler = p.PolicyGetIdentityEndpointsHandler
   156  	api.PolicyGetIdentityIDHandler = p.PolicyGetIdentityIDHandler
   157  	api.ServiceGetLrpHandler = p.ServiceGetLrpHandler
   158  	api.DaemonGetMapHandler = p.DaemonGetMapHandler
   159  	api.DaemonGetMapNameHandler = p.DaemonGetMapNameHandler
   160  	api.DaemonGetMapNameEventsHandler = p.DaemonGetMapNameEventsHandler
   161  	api.MetricsGetMetricsHandler = p.MetricsGetMetricsHandler
   162  	api.DaemonGetNodeIdsHandler = p.DaemonGetNodeIdsHandler
   163  	api.PolicyGetPolicyHandler = p.PolicyGetPolicyHandler
   164  	api.PolicyGetPolicySelectorsHandler = p.PolicyGetPolicySelectorsHandler
   165  	api.PrefilterGetPrefilterHandler = p.PrefilterGetPrefilterHandler
   166  	api.RecorderGetRecorderHandler = p.RecorderGetRecorderHandler
   167  	api.RecorderGetRecorderIDHandler = p.RecorderGetRecorderIDHandler
   168  	api.RecorderGetRecorderMasksHandler = p.RecorderGetRecorderMasksHandler
   169  	api.ServiceGetServiceHandler = p.ServiceGetServiceHandler
   170  	api.ServiceGetServiceIDHandler = p.ServiceGetServiceIDHandler
   171  	api.DaemonPatchConfigHandler = p.DaemonPatchConfigHandler
   172  	api.EndpointPatchEndpointIDHandler = p.EndpointPatchEndpointIDHandler
   173  	api.EndpointPatchEndpointIDConfigHandler = p.EndpointPatchEndpointIDConfigHandler
   174  	api.EndpointPatchEndpointIDLabelsHandler = p.EndpointPatchEndpointIDLabelsHandler
   175  	api.PrefilterPatchPrefilterHandler = p.PrefilterPatchPrefilterHandler
   176  	api.IpamPostIpamHandler = p.IpamPostIpamHandler
   177  	api.IpamPostIpamIPHandler = p.IpamPostIpamIPHandler
   178  	api.EndpointPutEndpointIDHandler = p.EndpointPutEndpointIDHandler
   179  	api.PolicyPutPolicyHandler = p.PolicyPutPolicyHandler
   180  	api.RecorderPutRecorderIDHandler = p.RecorderPutRecorderIDHandler
   181  	api.ServicePutServiceIDHandler = p.ServicePutServiceIDHandler
   182  
   183  	// Inject custom middleware if provided by Hive
   184  	if p.Middleware != nil {
   185  		api.Middleware = func(builder middleware.Builder) http.Handler {
   186  			return p.Middleware(api.Context().APIHandler(builder))
   187  		}
   188  	}
   189  
   190  	return api
   191  }
   192  
   193  type serverParams struct {
   194  	cell.In
   195  
   196  	Lifecycle  cell.Lifecycle
   197  	Shutdowner hive.Shutdowner
   198  	Logger     logrus.FieldLogger
   199  	Spec       *Spec
   200  	API        *restapi.CiliumAPIAPI
   201  }
   202  
   203  func newForCell(p serverParams) (*Server, error) {
   204  	s := NewServer(p.API)
   205  	s.shutdowner = p.Shutdowner
   206  	s.logger = p.Logger
   207  	p.Lifecycle.Append(s)
   208  	return s, nil
   209  }
   210  
   211  const (
   212  	schemeHTTP  = "http"
   213  	schemeHTTPS = "https"
   214  	schemeUnix  = "unix"
   215  )
   216  
   217  var defaultSchemes []string
   218  
   219  func init() {
   220  	defaultSchemes = []string{
   221  		schemeUnix,
   222  	}
   223  }
   224  
   225  var (
   226  	enabledListeners []string
   227  	gracefulTimeout  time.Duration
   228  	maxHeaderSize    int
   229  
   230  	socketPath string
   231  
   232  	host         string
   233  	port         int
   234  	listenLimit  int
   235  	keepAlive    time.Duration
   236  	readTimeout  time.Duration
   237  	writeTimeout time.Duration
   238  
   239  	tlsHost           string
   240  	tlsPort           int
   241  	tlsListenLimit    int
   242  	tlsKeepAlive      time.Duration
   243  	tlsReadTimeout    time.Duration
   244  	tlsWriteTimeout   time.Duration
   245  	tlsCertificate    string
   246  	tlsCertificateKey string
   247  	tlsCACertificate  string
   248  )
   249  
   250  type ServerConfig struct {
   251  	EnableCiliumAPIServerAccess []string
   252  }
   253  
   254  var (
   255  	defaultServerConfig = ServerConfig{
   256  		EnableCiliumAPIServerAccess: []string{"*"},
   257  	}
   258  	AdminEnableFlag = "enable-cilium-api-server-access"
   259  )
   260  
   261  func (cfg ServerConfig) Flags(flags *pflag.FlagSet) {
   262  	flags.StringSlice(AdminEnableFlag, cfg.EnableCiliumAPIServerAccess,
   263  		"List of cilium API APIs which are administratively enabled. Supports '*'.")
   264  }
   265  
   266  var SpecCell = cell.Module(
   267  	"cilium-api-spec",
   268  	"cilium API Specification",
   269  
   270  	cell.Config(defaultServerConfig),
   271  	cell.Provide(newSpec),
   272  )
   273  
   274  type Spec struct {
   275  	*loads.Document
   276  
   277  	// DeniedAPIs is a set of APIs that are administratively disabled.
   278  	DeniedAPIs api.PathSet
   279  }
   280  
   281  func newSpec(cfg ServerConfig) (*Spec, error) {
   282  	swaggerSpec, err := loads.Analyzed(SwaggerJSON, "")
   283  	if err != nil {
   284  		return nil, fmt.Errorf("failed to load swagger spec: %w", err)
   285  	}
   286  
   287  	deniedAPIs, err := api.AllowedFlagsToDeniedPaths(swaggerSpec, cfg.EnableCiliumAPIServerAccess)
   288  	if err != nil {
   289  		return nil, fmt.Errorf("failed to parse %q flag: %w",
   290  			AdminEnableFlag, err)
   291  	}
   292  
   293  	return &Spec{
   294  		Document:   swaggerSpec,
   295  		DeniedAPIs: deniedAPIs,
   296  	}, nil
   297  }
   298  
   299  // NewServer creates a new api cilium API server but does not configure it
   300  func NewServer(api *restapi.CiliumAPIAPI) *Server {
   301  	s := new(Server)
   302  	s.api = api
   303  	return s
   304  }
   305  
   306  // ConfigureAPI configures the API and handlers.
   307  func (s *Server) ConfigureAPI() {
   308  	if s.api != nil {
   309  		s.handler = configureAPI(s.api)
   310  	}
   311  }
   312  
   313  // ConfigureFlags configures the additional flags defined by the handlers. Needs to be called before the parser.Parse
   314  func (s *Server) ConfigureFlags() {
   315  	if s.api != nil {
   316  		configureFlags(s.api)
   317  	}
   318  }
   319  
   320  // Server for the cilium API API
   321  type Server struct {
   322  	EnabledListeners []string
   323  	CleanupTimeout   time.Duration
   324  	GracefulTimeout  time.Duration
   325  	MaxHeaderSize    int
   326  
   327  	SocketPath    string
   328  	domainSocketL *net.UnixListener
   329  
   330  	Host         string
   331  	Port         int
   332  	ListenLimit  int
   333  	KeepAlive    time.Duration
   334  	ReadTimeout  time.Duration
   335  	WriteTimeout time.Duration
   336  	httpServerL  net.Listener
   337  
   338  	TLSHost           string
   339  	TLSPort           int
   340  	TLSCertificate    string
   341  	TLSCertificateKey string
   342  	TLSCACertificate  string
   343  	TLSListenLimit    int
   344  	TLSKeepAlive      time.Duration
   345  	TLSReadTimeout    time.Duration
   346  	TLSWriteTimeout   time.Duration
   347  	httpsServerL      net.Listener
   348  
   349  	api          *restapi.CiliumAPIAPI
   350  	handler      http.Handler
   351  	hasListeners bool
   352  	servers      []*http.Server
   353  
   354  	wg         sync.WaitGroup
   355  	shutdowner hive.Shutdowner
   356  	logger     logrus.FieldLogger
   357  }
   358  
   359  // Logf logs message either via defined user logger or via system one if no user logger is defined.
   360  func (s *Server) Logf(f string, args ...interface{}) {
   361  	if s.logger != nil {
   362  		s.logger.Infof(f, args...)
   363  	} else if s.api != nil && s.api.Logger != nil {
   364  		s.api.Logger(f, args...)
   365  	} else {
   366  		log.Printf(f, args...)
   367  	}
   368  }
   369  
   370  // Fatalf logs message either via defined user logger or via system one if no user logger is defined.
   371  // Exits with non-zero status after printing
   372  func (s *Server) Fatalf(f string, args ...interface{}) {
   373  	if s.shutdowner != nil {
   374  		s.shutdowner.Shutdown(hive.ShutdownWithError(fmt.Errorf(f, args...)))
   375  	} else if s.api != nil && s.api.Logger != nil {
   376  		s.api.Logger(f, args...)
   377  		os.Exit(1)
   378  	} else {
   379  		log.Fatalf(f, args...)
   380  	}
   381  }
   382  
   383  // SetAPI configures the server with the specified API. Needs to be called before Serve
   384  func (s *Server) SetAPI(api *restapi.CiliumAPIAPI) {
   385  	if api == nil {
   386  		s.api = nil
   387  		s.handler = nil
   388  		return
   389  	}
   390  
   391  	s.api = api
   392  	s.handler = configureAPI(api)
   393  }
   394  
   395  // GetAPI returns the configured API. Modifications on the API must be performed
   396  // before server is started.
   397  func (s *Server) GetAPI() *restapi.CiliumAPIAPI {
   398  	return s.api
   399  }
   400  
   401  func (s *Server) hasScheme(scheme string) bool {
   402  	schemes := s.EnabledListeners
   403  	if len(schemes) == 0 {
   404  		schemes = defaultSchemes
   405  	}
   406  
   407  	for _, v := range schemes {
   408  		if v == scheme {
   409  			return true
   410  		}
   411  	}
   412  	return false
   413  }
   414  
   415  func (s *Server) Serve() error {
   416  	// TODO remove when this is not needed for compatibility anymore
   417  	if err := s.Start(context.TODO()); err != nil {
   418  		return err
   419  	}
   420  	s.wg.Wait()
   421  	return nil
   422  }
   423  
   424  // Start the server
   425  func (s *Server) Start(cell.HookContext) (err error) {
   426  	if !s.hasListeners {
   427  		if err = s.Listen(); err != nil {
   428  			return err
   429  		}
   430  	}
   431  
   432  	if len(s.servers) != 0 {
   433  		return errors.New("already started")
   434  	}
   435  
   436  	// set default handler, if none is set
   437  	if s.handler == nil {
   438  		if s.api == nil {
   439  			return errors.New("can't create the default handler, as no api is set")
   440  		}
   441  
   442  		s.ConfigureAPI()
   443  		s.SetHandler(s.api.Serve(nil))
   444  	}
   445  
   446  	if s.hasScheme(schemeUnix) {
   447  		domainSocket := new(http.Server)
   448  		domainSocket.MaxHeaderBytes = s.MaxHeaderSize
   449  		domainSocket.Handler = s.handler
   450  		if int64(s.CleanupTimeout) > 0 {
   451  			domainSocket.IdleTimeout = s.CleanupTimeout
   452  		}
   453  
   454  		configureServer(domainSocket, "unix", s.SocketPath)
   455  
   456  		if os.Getuid() == 0 {
   457  			err := api.SetDefaultPermissions(s.SocketPath)
   458  			if err != nil {
   459  				return err
   460  			}
   461  		}
   462  		s.servers = append(s.servers, domainSocket)
   463  		s.wg.Add(1)
   464  		s.Logf("Serving cilium API at unix://%s", s.SocketPath)
   465  		go func(l net.Listener) {
   466  			defer s.wg.Done()
   467  			if err := domainSocket.Serve(l); err != nil && err != http.ErrServerClosed {
   468  				s.Fatalf("%v", err)
   469  			}
   470  			s.Logf("Stopped serving cilium API at unix://%s", s.SocketPath)
   471  		}(s.domainSocketL)
   472  	}
   473  
   474  	if s.hasScheme(schemeHTTP) {
   475  		httpServer := new(http.Server)
   476  		httpServer.MaxHeaderBytes = s.MaxHeaderSize
   477  		httpServer.ReadTimeout = s.ReadTimeout
   478  		httpServer.WriteTimeout = s.WriteTimeout
   479  		httpServer.SetKeepAlivesEnabled(int64(s.KeepAlive) > 0)
   480  		if s.ListenLimit > 0 {
   481  			s.httpServerL = netutil.LimitListener(s.httpServerL, s.ListenLimit)
   482  		}
   483  
   484  		if int64(s.CleanupTimeout) > 0 {
   485  			httpServer.IdleTimeout = s.CleanupTimeout
   486  		}
   487  
   488  		httpServer.Handler = s.handler
   489  
   490  		configureServer(httpServer, "http", s.httpServerL.Addr().String())
   491  
   492  		s.servers = append(s.servers, httpServer)
   493  		s.wg.Add(1)
   494  		s.Logf("Serving cilium API at http://%s", s.httpServerL.Addr())
   495  		go func(l net.Listener) {
   496  			defer s.wg.Done()
   497  			if err := httpServer.Serve(l); err != nil && err != http.ErrServerClosed {
   498  				s.Fatalf("%v", err)
   499  			}
   500  			s.Logf("Stopped serving cilium API at http://%s", l.Addr())
   501  		}(s.httpServerL)
   502  	}
   503  
   504  	if s.hasScheme(schemeHTTPS) {
   505  		httpsServer := new(http.Server)
   506  		httpsServer.MaxHeaderBytes = s.MaxHeaderSize
   507  		httpsServer.ReadTimeout = s.TLSReadTimeout
   508  		httpsServer.WriteTimeout = s.TLSWriteTimeout
   509  		httpsServer.SetKeepAlivesEnabled(int64(s.TLSKeepAlive) > 0)
   510  		if s.TLSListenLimit > 0 {
   511  			s.httpsServerL = netutil.LimitListener(s.httpsServerL, s.TLSListenLimit)
   512  		}
   513  		if int64(s.CleanupTimeout) > 0 {
   514  			httpsServer.IdleTimeout = s.CleanupTimeout
   515  		}
   516  		httpsServer.Handler = s.handler
   517  
   518  		// Inspired by https://blog.bracebin.com/achieving-perfect-ssl-labs-score-with-go
   519  		httpsServer.TLSConfig = &tls.Config{
   520  			// Causes servers to use Go's default ciphersuite preferences,
   521  			// which are tuned to avoid attacks. Does nothing on clients.
   522  			PreferServerCipherSuites: true,
   523  			// Only use curves which have assembly implementations
   524  			// https://github.com/golang/go/tree/master/src/crypto/elliptic
   525  			CurvePreferences: []tls.CurveID{tls.CurveP256},
   526  			// Use modern tls mode https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
   527  			NextProtos: []string{"h2", "http/1.1"},
   528  			// https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet#Rule_-_Only_Support_Strong_Protocols
   529  			MinVersion: tls.VersionTLS12,
   530  			// These ciphersuites support Forward Secrecy: https://en.wikipedia.org/wiki/Forward_secrecy
   531  			CipherSuites: []uint16{
   532  				tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
   533  				tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
   534  				tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   535  				tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   536  				tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
   537  				tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
   538  			},
   539  		}
   540  
   541  		// build standard config from server options
   542  		if s.TLSCertificate != "" && s.TLSCertificateKey != "" {
   543  			httpsServer.TLSConfig.Certificates = make([]tls.Certificate, 1)
   544  			httpsServer.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(s.TLSCertificate, s.TLSCertificateKey)
   545  			if err != nil {
   546  				return err
   547  			}
   548  		}
   549  
   550  		if s.TLSCACertificate != "" {
   551  			// include specified CA certificate
   552  			caCert, caCertErr := os.ReadFile(s.TLSCACertificate)
   553  			if caCertErr != nil {
   554  				return caCertErr
   555  			}
   556  			caCertPool := x509.NewCertPool()
   557  			ok := caCertPool.AppendCertsFromPEM(caCert)
   558  			if !ok {
   559  				return fmt.Errorf("cannot parse CA certificate")
   560  			}
   561  			httpsServer.TLSConfig.ClientCAs = caCertPool
   562  			httpsServer.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert
   563  		}
   564  
   565  		// call custom TLS configurator
   566  		configureTLS(httpsServer.TLSConfig)
   567  
   568  		if len(httpsServer.TLSConfig.Certificates) == 0 && httpsServer.TLSConfig.GetCertificate == nil {
   569  			// after standard and custom config are passed, this ends up with no certificate
   570  			if s.TLSCertificate == "" {
   571  				if s.TLSCertificateKey == "" {
   572  					s.Fatalf("the required flags `--tls-certificate` and `--tls-key` were not specified")
   573  				}
   574  				s.Fatalf("the required flag `--tls-certificate` was not specified")
   575  			}
   576  			if s.TLSCertificateKey == "" {
   577  				s.Fatalf("the required flag `--tls-key` was not specified")
   578  			}
   579  			// this happens with a wrong custom TLS configurator
   580  			s.Fatalf("no certificate was configured for TLS")
   581  		}
   582  
   583  		// must have at least one certificate or panics
   584  		httpsServer.TLSConfig.BuildNameToCertificate()
   585  
   586  		configureServer(httpsServer, "https", s.httpsServerL.Addr().String())
   587  
   588  		s.servers = append(s.servers, httpsServer)
   589  		s.wg.Add(1)
   590  		s.Logf("Serving cilium API at https://%s", s.httpsServerL.Addr())
   591  		go func(l net.Listener) {
   592  			defer s.wg.Done()
   593  			if err := httpsServer.Serve(l); err != nil && err != http.ErrServerClosed {
   594  				s.Fatalf("%v", err)
   595  			}
   596  			s.Logf("Stopped serving cilium API at https://%s", l.Addr())
   597  		}(tls.NewListener(s.httpsServerL, httpsServer.TLSConfig))
   598  	}
   599  
   600  	return nil
   601  }
   602  
   603  // Listen creates the listeners for the server
   604  func (s *Server) Listen() error {
   605  	if s.hasListeners { // already done this
   606  		return nil
   607  	}
   608  
   609  	if s.hasScheme(schemeHTTPS) {
   610  		// Use http host if https host wasn't defined
   611  		if s.TLSHost == "" {
   612  			s.TLSHost = s.Host
   613  		}
   614  		// Use http listen limit if https listen limit wasn't defined
   615  		if s.TLSListenLimit == 0 {
   616  			s.TLSListenLimit = s.ListenLimit
   617  		}
   618  		// Use http tcp keep alive if https tcp keep alive wasn't defined
   619  		if int64(s.TLSKeepAlive) == 0 {
   620  			s.TLSKeepAlive = s.KeepAlive
   621  		}
   622  		// Use http read timeout if https read timeout wasn't defined
   623  		if int64(s.TLSReadTimeout) == 0 {
   624  			s.TLSReadTimeout = s.ReadTimeout
   625  		}
   626  		// Use http write timeout if https write timeout wasn't defined
   627  		if int64(s.TLSWriteTimeout) == 0 {
   628  			s.TLSWriteTimeout = s.WriteTimeout
   629  		}
   630  	}
   631  
   632  	if s.hasScheme(schemeUnix) {
   633  		addr, err := net.ResolveUnixAddr("unix", s.SocketPath)
   634  		if err != nil {
   635  			return err
   636  		}
   637  		domSockListener, err := net.ListenUnix("unix", addr)
   638  		if err != nil {
   639  			return err
   640  		}
   641  		s.domainSocketL = domSockListener
   642  	}
   643  
   644  	if s.hasScheme(schemeHTTP) {
   645  		listener, err := net.Listen("tcp", net.JoinHostPort(s.Host, strconv.Itoa(s.Port)))
   646  		if err != nil {
   647  			return err
   648  		}
   649  
   650  		h, p, err := swag.SplitHostPort(listener.Addr().String())
   651  		if err != nil {
   652  			return err
   653  		}
   654  		s.Host = h
   655  		s.Port = p
   656  		s.httpServerL = listener
   657  	}
   658  
   659  	if s.hasScheme(schemeHTTPS) {
   660  		tlsListener, err := net.Listen("tcp", net.JoinHostPort(s.TLSHost, strconv.Itoa(s.TLSPort)))
   661  		if err != nil {
   662  			return err
   663  		}
   664  
   665  		sh, sp, err := swag.SplitHostPort(tlsListener.Addr().String())
   666  		if err != nil {
   667  			return err
   668  		}
   669  		s.TLSHost = sh
   670  		s.TLSPort = sp
   671  		s.httpsServerL = tlsListener
   672  	}
   673  
   674  	s.hasListeners = true
   675  	return nil
   676  }
   677  
   678  // Shutdown server and clean up resources
   679  func (s *Server) Shutdown() error {
   680  	ctx, cancel := context.WithTimeout(context.TODO(), s.GracefulTimeout)
   681  	defer cancel()
   682  	return s.Stop(ctx)
   683  }
   684  
   685  func (s *Server) Stop(ctx cell.HookContext) error {
   686  	// first execute the pre-shutdown hook
   687  	s.api.PreServerShutdown()
   688  
   689  	shutdownChan := make(chan bool)
   690  	for i := range s.servers {
   691  		server := s.servers[i]
   692  		go func() {
   693  			var success bool
   694  			defer func() {
   695  				shutdownChan <- success
   696  			}()
   697  			if err := server.Shutdown(ctx); err != nil {
   698  				s.Logf("HTTP server Shutdown: %v", err)
   699  
   700  				// Forcefully close open connections.
   701  				server.Close()
   702  			} else {
   703  				success = true
   704  			}
   705  		}()
   706  	}
   707  
   708  	// Wait until all listeners have successfully shut down before calling ServerShutdown
   709  	success := true
   710  	for range s.servers {
   711  		success = success && <-shutdownChan
   712  	}
   713  	if success {
   714  		s.api.ServerShutdown()
   715  	}
   716  
   717  	s.wg.Wait()
   718  	s.servers = nil
   719  
   720  	return nil
   721  }
   722  
   723  // GetHandler returns a handler useful for testing
   724  func (s *Server) GetHandler() http.Handler {
   725  	return s.handler
   726  }
   727  
   728  // SetHandler allows for setting a http handler on this server
   729  func (s *Server) SetHandler(handler http.Handler) {
   730  	s.handler = handler
   731  }
   732  
   733  // UnixListener returns the domain socket listener
   734  func (s *Server) UnixListener() (*net.UnixListener, error) {
   735  	if !s.hasListeners {
   736  		if err := s.Listen(); err != nil {
   737  			return nil, err
   738  		}
   739  	}
   740  	return s.domainSocketL, nil
   741  }
   742  
   743  // HTTPListener returns the http listener
   744  func (s *Server) HTTPListener() (net.Listener, error) {
   745  	if !s.hasListeners {
   746  		if err := s.Listen(); err != nil {
   747  			return nil, err
   748  		}
   749  	}
   750  	return s.httpServerL, nil
   751  }
   752  
   753  // TLSListener returns the https listener
   754  func (s *Server) TLSListener() (net.Listener, error) {
   755  	if !s.hasListeners {
   756  		if err := s.Listen(); err != nil {
   757  			return nil, err
   758  		}
   759  	}
   760  	return s.httpsServerL, nil
   761  }