package cmd import ( "context" "crypto/tls" "fmt" "io" "net" "net/http" "os" "strconv" "github.com/cpuguy83/strongerrors" "github.com/pkg/errors" "github.com/virtual-kubelet/virtual-kubelet/log" "github.com/virtual-kubelet/virtual-kubelet/vkubelet" ) // AcceptedCiphers is the list of accepted TLS ciphers, with known weak ciphers elided // Note this list should be a moving target. var AcceptedCiphers = []uint16{ tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, } func loadTLSConfig(certPath, keyPath string) (*tls.Config, error) { cert, err := tls.LoadX509KeyPair(certPath, keyPath) if err != nil { return nil, errors.Wrap(err, "error loading tls certs") } return &tls.Config{ Certificates: []tls.Certificate{cert}, MinVersion: tls.VersionTLS12, PreferServerCipherSuites: true, CipherSuites: AcceptedCiphers, }, nil } func setupHTTPServer(ctx context.Context, cfg *apiServerConfig) (io.Closer, io.Closer, error) { var ( podS *http.Server metricsS *http.Server ) if cfg.CertPath == "" || cfg.KeyPath == "" { log.G(ctx). WithField("certPath", cfg.CertPath). WithField("keyPath", cfg.KeyPath). Error("TLS certificates not provided, not setting up pod http server") } else { tlsCfg, err := loadTLSConfig(cfg.CertPath, cfg.KeyPath) if err != nil { return nil, nil, err } l, err := tls.Listen("tcp", cfg.Addr, tlsCfg) if err != nil { return nil, nil, errors.Wrap(err, "error setting up listener for pod http server") } mux := http.NewServeMux() vkubelet.AttachPodRoutes(p, mux) podS = &http.Server{ Handler: mux, TLSConfig: tlsCfg, } go serveHTTP(ctx, podS, l, "pods") } if cfg.MetricsAddr == "" { log.G(ctx).Info("Pod metrics server not setup due to empty metrics address") } else { l, err := net.Listen("tcp", cfg.MetricsAddr) if err != nil { if l != nil { podS.Close() } return nil, nil, errors.Wrap(err, "could not setup listenr for pod metrics http server") } mux := http.NewServeMux() vkubelet.AttachMetricsRoutes(p, mux) metricsS = &http.Server{ Handler: mux, } go serveHTTP(ctx, metricsS, l, "pod metrics") } return podS, metricsS, nil } func serveHTTP(ctx context.Context, s *http.Server, l net.Listener, name string) { if err := s.Serve(l); err != nil { select { case <-ctx.Done(): default: log.G(ctx).WithError(err).Errorf("Error setting up %s http server", name) } } l.Close() } type apiServerConfig struct { CertPath string KeyPath string Addr string MetricsAddr string } func getAPIConfig(metricsAddr string) (*apiServerConfig, error) { config := apiServerConfig{ CertPath: os.Getenv("APISERVER_CERT_LOCATION"), KeyPath: os.Getenv("APISERVER_KEY_LOCATION"), } port, err := strconv.Atoi(os.Getenv("KUBELET_PORT")) if err != nil { return nil, strongerrors.InvalidArgument(errors.Wrap(err, "error parsing KUBELET_PORT variable")) } config.Addr = fmt.Sprintf(":%d", port) config.MetricsAddr = metricsAddr return &config, nil }