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 }