improve IAM module

Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
hongming
2020-05-22 09:35:05 +08:00
parent 0d12529051
commit 8f93266ec0
640 changed files with 50221 additions and 18179 deletions

View File

@@ -19,24 +19,114 @@ package server
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"net"
"net/http"
"strings"
"time"
"golang.org/x/net/http2"
"k8s.io/klog"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apiserver/pkg/server/dynamiccertificates"
)
const (
defaultKeepAlivePeriod = 3 * time.Minute
)
// tlsConfig produces the tls.Config to serve with.
func (s *SecureServingInfo) tlsConfig(stopCh <-chan struct{}) (*tls.Config, error) {
tlsConfig := &tls.Config{
// Can't use SSLv3 because of POODLE and BEAST
// Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher
// Can't use TLSv1.1 because of RC4 cipher usage
MinVersion: tls.VersionTLS12,
// enable HTTP2 for go's 1.7 HTTP Server
NextProtos: []string{"h2", "http/1.1"},
}
// these are static aspects of the tls.Config
if s.DisableHTTP2 {
klog.Info("Forcing use of http/1.1 only")
tlsConfig.NextProtos = []string{"http/1.1"}
}
if s.MinTLSVersion > 0 {
tlsConfig.MinVersion = s.MinTLSVersion
}
if len(s.CipherSuites) > 0 {
tlsConfig.CipherSuites = s.CipherSuites
}
if s.ClientCA != nil {
// Populate PeerCertificates in requests, but don't reject connections without certificates
// This allows certificates to be validated by authenticators, while still allowing other auth types
tlsConfig.ClientAuth = tls.RequestClientCert
}
if s.ClientCA != nil || s.Cert != nil || len(s.SNICerts) > 0 {
dynamicCertificateController := dynamiccertificates.NewDynamicServingCertificateController(
*tlsConfig,
s.ClientCA,
s.Cert,
s.SNICerts,
nil, // TODO see how to plumb an event recorder down in here. For now this results in simply klog messages.
)
// register if possible
if notifier, ok := s.ClientCA.(dynamiccertificates.Notifier); ok {
notifier.AddListener(dynamicCertificateController)
}
if notifier, ok := s.Cert.(dynamiccertificates.Notifier); ok {
notifier.AddListener(dynamicCertificateController)
}
// start controllers if possible
if controller, ok := s.ClientCA.(dynamiccertificates.ControllerRunner); ok {
// runonce to try to prime data. If this fails, it's ok because we fail closed.
// Files are required to be populated already, so this is for convenience.
if err := controller.RunOnce(); err != nil {
klog.Warningf("Initial population of client CA failed: %v", err)
}
go controller.Run(1, stopCh)
}
if controller, ok := s.Cert.(dynamiccertificates.ControllerRunner); ok {
// runonce to try to prime data. If this fails, it's ok because we fail closed.
// Files are required to be populated already, so this is for convenience.
if err := controller.RunOnce(); err != nil {
klog.Warningf("Initial population of default serving certificate failed: %v", err)
}
go controller.Run(1, stopCh)
}
for _, sniCert := range s.SNICerts {
if notifier, ok := sniCert.(dynamiccertificates.Notifier); ok {
notifier.AddListener(dynamicCertificateController)
}
if controller, ok := sniCert.(dynamiccertificates.ControllerRunner); ok {
// runonce to try to prime data. If this fails, it's ok because we fail closed.
// Files are required to be populated already, so this is for convenience.
if err := controller.RunOnce(); err != nil {
klog.Warningf("Initial population of SNI serving certificate failed: %v", err)
}
go controller.Run(1, stopCh)
}
}
// runonce to try to prime data. If this fails, it's ok because we fail closed.
// Files are required to be populated already, so this is for convenience.
if err := dynamicCertificateController.RunOnce(); err != nil {
klog.Warningf("Initial population of dynamic certificates failed: %v", err)
}
go dynamicCertificateController.Run(1, stopCh)
tlsConfig.GetConfigForClient = dynamicCertificateController.GetConfigForClient
}
return tlsConfig, nil
}
// Serve runs the secure http server. It fails only if certificates cannot be loaded or the initial listen call fails.
// The actual server loop (stoppable by closing stopCh) runs in a go routine, i.e. Serve does not block.
// It returns a stoppedCh that is closed when all non-hijacked active requests have been processed.
@@ -45,51 +135,16 @@ func (s *SecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.Dur
return nil, fmt.Errorf("listener must not be nil")
}
tlsConfig, err := s.tlsConfig(stopCh)
if err != nil {
return nil, err
}
secureServer := &http.Server{
Addr: s.Listener.Addr().String(),
Handler: handler,
MaxHeaderBytes: 1 << 20,
TLSConfig: &tls.Config{
NameToCertificate: s.SNICerts,
// Can't use SSLv3 because of POODLE and BEAST
// Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher
// Can't use TLSv1.1 because of RC4 cipher usage
MinVersion: tls.VersionTLS12,
// enable HTTP2 for go's 1.7 HTTP Server
NextProtos: []string{"h2", "http/1.1"},
},
}
if s.DisableHTTP2 {
klog.Info("Forcing use of http/1.1 only")
secureServer.TLSConfig.NextProtos = []string{"http/1.1"}
}
if s.MinTLSVersion > 0 {
secureServer.TLSConfig.MinVersion = s.MinTLSVersion
}
if len(s.CipherSuites) > 0 {
secureServer.TLSConfig.CipherSuites = s.CipherSuites
}
if s.Cert != nil {
secureServer.TLSConfig.Certificates = []tls.Certificate{*s.Cert}
}
// append all named certs. Otherwise, the go tls stack will think no SNI processing
// is necessary because there is only one cert anyway.
// Moreover, if ServerCert.CertFile/ServerCert.KeyFile are not set, the first SNI
// cert will become the default cert. That's what we expect anyway.
for _, c := range s.SNICerts {
secureServer.TLSConfig.Certificates = append(secureServer.TLSConfig.Certificates, *c)
}
if s.ClientCA != nil {
// Populate PeerCertificates in requests, but don't reject connections without certificates
// This allows certificates to be validated by authenticators, while still allowing other auth types
secureServer.TLSConfig.ClientAuth = tls.RequestClientCert
// Specify allowed CAs for client certificates
secureServer.TLSConfig.ClientCAs = s.ClientCA
TLSConfig: tlsConfig,
}
// At least 99% of serialized resources in surveyed clusters were smaller than 256kb.
@@ -173,57 +228,6 @@ func RunServer(
return stoppedCh, nil
}
type NamedTLSCert struct {
TLSCert tls.Certificate
// Names is a list of domain patterns: fully qualified domain names, possibly prefixed with
// wildcard segments.
Names []string
}
// GetNamedCertificateMap returns a map of *tls.Certificate by name. It's
// suitable for use in tls.Config#NamedCertificates. Returns an error if any of the certs
// cannot be loaded. Returns nil if len(certs) == 0
func GetNamedCertificateMap(certs []NamedTLSCert) (map[string]*tls.Certificate, error) {
// register certs with implicit names first, reverse order such that earlier trump over the later
byName := map[string]*tls.Certificate{}
for i := len(certs) - 1; i >= 0; i-- {
if len(certs[i].Names) > 0 {
continue
}
cert := &certs[i].TLSCert
// read names from certificate common names and DNS names
if len(cert.Certificate) == 0 {
return nil, fmt.Errorf("empty SNI certificate, skipping")
}
x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
if err != nil {
return nil, fmt.Errorf("parse error for SNI certificate: %v", err)
}
cn := x509Cert.Subject.CommonName
if cn == "*" || len(validation.IsDNS1123Subdomain(strings.TrimPrefix(cn, "*."))) == 0 {
byName[cn] = cert
}
for _, san := range x509Cert.DNSNames {
byName[san] = cert
}
// intentionally all IPs in the cert are ignored as SNI forbids passing IPs
// to select a cert. Before go 1.6 the tls happily passed IPs as SNI values.
}
// register certs with explicit names last, overwriting every of the implicit ones,
// again in reverse order.
for i := len(certs) - 1; i >= 0; i-- {
namedCert := &certs[i]
for _, name := range namedCert.Names {
byName[name] = &certs[i].TLSCert
}
}
return byName, nil
}
// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually