139 lines
3.4 KiB
Go
139 lines
3.4 KiB
Go
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) (cancel func(), retErr error) {
|
|
var closers []io.Closer
|
|
cancel = func() {
|
|
for _, c := range closers {
|
|
c.Close()
|
|
}
|
|
}
|
|
defer func() {
|
|
if retErr != nil {
|
|
cancel()
|
|
}
|
|
}()
|
|
|
|
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, err
|
|
}
|
|
l, err := tls.Listen("tcp", cfg.Addr, tlsCfg)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "error setting up listener for pod http server")
|
|
}
|
|
|
|
mux := http.NewServeMux()
|
|
vkubelet.AttachPodRoutes(p, mux)
|
|
|
|
s := &http.Server{
|
|
Handler: mux,
|
|
TLSConfig: tlsCfg,
|
|
}
|
|
go serveHTTP(ctx, s, l, "pods")
|
|
closers = append(closers, s)
|
|
}
|
|
|
|
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 {
|
|
return nil, errors.Wrap(err, "could not setup listener for pod metrics http server")
|
|
}
|
|
|
|
mux := http.NewServeMux()
|
|
vkubelet.AttachMetricsRoutes(p, mux)
|
|
s := &http.Server{
|
|
Handler: mux,
|
|
}
|
|
go serveHTTP(ctx, s, l, "pod metrics")
|
|
closers = append(closers, s)
|
|
}
|
|
|
|
return cancel, 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
|
|
}
|