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