mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 19:31:44 +00:00
Warn when insecure TLS ciphers are selected.
This commit is contained in:
parent
4e975b9fc2
commit
550a67869a
@ -464,11 +464,13 @@ func AddKubeletConfigFlags(mainfs *pflag.FlagSet, c *kubeletconfig.KubeletConfig
|
||||
fs.StringVar(&c.TLSPrivateKeyFile, "tls-private-key-file", c.TLSPrivateKeyFile, "File containing x509 private key matching --tls-cert-file.")
|
||||
fs.BoolVar(&c.ServerTLSBootstrap, "rotate-server-certificates", c.ServerTLSBootstrap, "Auto-request and rotate the kubelet serving certificates by requesting new certificates from the kube-apiserver when the certificate expiration approaches. Requires the RotateKubeletServerCertificate feature gate to be enabled, and approval of the submitted CertificateSigningRequest objects.")
|
||||
|
||||
tlsCipherPossibleValues := cliflag.TLSCipherPossibleValues()
|
||||
tlsCipherPreferredValues := cliflag.PreferredTLSCipherNames()
|
||||
tlsCipherInsecureValues := cliflag.InsecureTLSCipherNames()
|
||||
fs.StringSliceVar(&c.TLSCipherSuites, "tls-cipher-suites", c.TLSCipherSuites,
|
||||
"Comma-separated list of cipher suites for the server. "+
|
||||
"If omitted, the default Go cipher suites will be used. "+
|
||||
"Possible values: "+strings.Join(tlsCipherPossibleValues, ","))
|
||||
"If omitted, the default Go cipher suites will be used. \n"+
|
||||
"Preferred values: "+strings.Join(tlsCipherPreferredValues, ", ")+". \n"+
|
||||
"Insecure values: "+strings.Join(tlsCipherInsecureValues, ", ")+".")
|
||||
tlsPossibleVersions := cliflag.TLSPossibleVersions()
|
||||
fs.StringVar(&c.TLSMinVersion, "tls-min-version", c.TLSMinVersion,
|
||||
"Minimum TLS version supported. "+
|
||||
|
@ -60,6 +60,7 @@ import (
|
||||
"k8s.io/client-go/util/connrotation"
|
||||
"k8s.io/client-go/util/keyutil"
|
||||
cloudprovider "k8s.io/cloud-provider"
|
||||
"k8s.io/component-base/cli/flag"
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
"k8s.io/component-base/configz"
|
||||
"k8s.io/component-base/featuregate"
|
||||
@ -1010,6 +1011,17 @@ func InitializeTLS(kf *options.KubeletFlags, kc *kubeletconfiginternal.KubeletCo
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(tlsCipherSuites) > 0 {
|
||||
insecureCiphers := flag.InsecureTLSCiphers()
|
||||
for i := 0; i < len(tlsCipherSuites); i++ {
|
||||
for cipherName, cipherID := range insecureCiphers {
|
||||
if tlsCipherSuites[i] == cipherID {
|
||||
klog.Warningf("Use of insecure cipher '%s' detected.", cipherName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
minTLSVersion, err := cliflag.TLSVersion(kc.TLSMinVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -117,6 +117,7 @@ go_library(
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/openapi:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/rest:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/cli/flag:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/logs:go_default_library",
|
||||
"//vendor/github.com/coreos/go-systemd/daemon:go_default_library",
|
||||
"//vendor/github.com/emicklei/go-restful:go_default_library",
|
||||
|
@ -171,11 +171,13 @@ func (s *SecureServingOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&s.ServerCert.CertKey.KeyFile, "tls-private-key-file", s.ServerCert.CertKey.KeyFile,
|
||||
"File containing the default x509 private key matching --tls-cert-file.")
|
||||
|
||||
tlsCipherPossibleValues := cliflag.TLSCipherPossibleValues()
|
||||
tlsCipherPreferredValues := cliflag.PreferredTLSCipherNames()
|
||||
tlsCipherInsecureValues := cliflag.InsecureTLSCipherNames()
|
||||
fs.StringSliceVar(&s.CipherSuites, "tls-cipher-suites", s.CipherSuites,
|
||||
"Comma-separated list of cipher suites for the server. "+
|
||||
"If omitted, the default Go cipher suites will be use. "+
|
||||
"Possible values: "+strings.Join(tlsCipherPossibleValues, ","))
|
||||
"If omitted, the default Go cipher suites will be used. \n"+
|
||||
"Preferred values: "+strings.Join(tlsCipherPreferredValues, ", ")+". \n"+
|
||||
"Insecure values: "+strings.Join(tlsCipherInsecureValues, ", ")+".")
|
||||
|
||||
tlsPossibleVersions := cliflag.TLSPossibleVersions()
|
||||
fs.StringVar(&s.MinTLSVersion, "tls-min-version", s.MinTLSVersion,
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/http2"
|
||||
"k8s.io/component-base/cli/flag"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
@ -56,6 +57,14 @@ func (s *SecureServingInfo) tlsConfig(stopCh <-chan struct{}) (*tls.Config, erro
|
||||
}
|
||||
if len(s.CipherSuites) > 0 {
|
||||
tlsConfig.CipherSuites = s.CipherSuites
|
||||
insecureCiphers := flag.InsecureTLSCiphers()
|
||||
for i := 0; i < len(s.CipherSuites); i++ {
|
||||
for cipherName, cipherID := range insecureCiphers {
|
||||
if s.CipherSuites[i] == cipherID {
|
||||
klog.Warningf("Use of insecure cipher '%s' detected.", cipherName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if s.ClientCA != nil {
|
||||
|
@ -25,23 +25,18 @@ import (
|
||||
|
||||
// ciphers maps strings into tls package cipher constants in
|
||||
// https://golang.org/pkg/crypto/tls/#pkg-constants
|
||||
// to be replaced by tls.CipherSuites() when the project migrates to go1.14.
|
||||
var ciphers = map[string]uint16{
|
||||
"TLS_RSA_WITH_RC4_128_SHA": tls.TLS_RSA_WITH_RC4_128_SHA,
|
||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA": tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA": tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||
"TLS_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
@ -53,7 +48,38 @@ var ciphers = map[string]uint16{
|
||||
"TLS_AES_256_GCM_SHA384": tls.TLS_AES_256_GCM_SHA384,
|
||||
}
|
||||
|
||||
func TLSCipherPossibleValues() []string {
|
||||
// to be replaced by tls.InsecureCipherSuites() when the project migrates to go1.14.
|
||||
var insecureCiphers = map[string]uint16{
|
||||
"TLS_RSA_WITH_RC4_128_SHA": tls.TLS_RSA_WITH_RC4_128_SHA,
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||
"TLS_ECDHE_RSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||
}
|
||||
|
||||
// InsecureTLSCiphers returns the cipher suites implemented by crypto/tls which have
|
||||
// security issues.
|
||||
func InsecureTLSCiphers() map[string]uint16 {
|
||||
cipherKeys := make(map[string]uint16, len(insecureCiphers))
|
||||
for k, v := range insecureCiphers {
|
||||
cipherKeys[k] = v
|
||||
}
|
||||
return cipherKeys
|
||||
}
|
||||
|
||||
// InsecureTLSCipherNames returns a list of cipher suite names implemented by crypto/tls
|
||||
// which have security issues.
|
||||
func InsecureTLSCipherNames() []string {
|
||||
cipherKeys := sets.NewString()
|
||||
for key := range insecureCiphers {
|
||||
cipherKeys.Insert(key)
|
||||
}
|
||||
return cipherKeys.List()
|
||||
}
|
||||
|
||||
// PreferredTLSCipherNames returns a list of cipher suite names implemented by crypto/tls.
|
||||
func PreferredTLSCipherNames() []string {
|
||||
cipherKeys := sets.NewString()
|
||||
for key := range ciphers {
|
||||
cipherKeys.Insert(key)
|
||||
@ -61,13 +87,37 @@ func TLSCipherPossibleValues() []string {
|
||||
return cipherKeys.List()
|
||||
}
|
||||
|
||||
func allCiphers() map[string]uint16 {
|
||||
acceptedCiphers := make(map[string]uint16, len(ciphers)+len(insecureCiphers))
|
||||
for k, v := range ciphers {
|
||||
acceptedCiphers[k] = v
|
||||
}
|
||||
for k, v := range insecureCiphers {
|
||||
acceptedCiphers[k] = v
|
||||
}
|
||||
return acceptedCiphers
|
||||
}
|
||||
|
||||
// TLSCipherPossibleValues returns all acceptable cipher suite names.
|
||||
// This is a combination of both InsecureTLSCipherNames() and PreferredTLSCipherNames().
|
||||
func TLSCipherPossibleValues() []string {
|
||||
cipherKeys := sets.NewString()
|
||||
acceptedCiphers := allCiphers()
|
||||
for key := range acceptedCiphers {
|
||||
cipherKeys.Insert(key)
|
||||
}
|
||||
return cipherKeys.List()
|
||||
}
|
||||
|
||||
// TLSCipherSuites returns a list of cipher suite IDs from the cipher suite names passed.
|
||||
func TLSCipherSuites(cipherNames []string) ([]uint16, error) {
|
||||
if len(cipherNames) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
ciphersIntSlice := make([]uint16, 0)
|
||||
possibleCiphers := allCiphers()
|
||||
for _, cipher := range cipherNames {
|
||||
intValue, ok := ciphers[cipher]
|
||||
intValue, ok := possibleCiphers[cipher]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Cipher suite %s not supported or doesn't exist", cipher)
|
||||
}
|
||||
@ -83,6 +133,7 @@ var versions = map[string]uint16{
|
||||
"VersionTLS13": tls.VersionTLS13,
|
||||
}
|
||||
|
||||
// TLSPossibleVersions returns all acceptable values for TLS Version.
|
||||
func TLSPossibleVersions() []string {
|
||||
versionsKeys := sets.NewString()
|
||||
for key := range versions {
|
||||
@ -91,6 +142,7 @@ func TLSPossibleVersions() []string {
|
||||
return versionsKeys.List()
|
||||
}
|
||||
|
||||
// TLSVersion returns the TLS Version ID for the version name passed.
|
||||
func TLSVersion(versionName string) (uint16, error) {
|
||||
if len(versionName) == 0 {
|
||||
return DefaultTLSVersion(), nil
|
||||
@ -101,6 +153,7 @@ func TLSVersion(versionName string) (uint16, error) {
|
||||
return 0, fmt.Errorf("unknown tls version %q", versionName)
|
||||
}
|
||||
|
||||
// DefaultTLSVersion defines the default TLS Version.
|
||||
func DefaultTLSVersion() uint16 {
|
||||
// Can't use SSLv3 because of POODLE and BEAST
|
||||
// Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher
|
||||
|
@ -86,18 +86,18 @@ func TestConstantMaps(t *testing.T) {
|
||||
if strings.HasPrefix(declName, "VersionTLS") {
|
||||
discoveredVersions[declName] = true
|
||||
}
|
||||
if strings.HasPrefix(declName, "TLS_RSA_") || strings.HasPrefix(declName, "TLS_ECDHE_") ||
|
||||
strings.HasPrefix(declName, "TLS_AES_") || strings.HasPrefix(declName, "TLS_CHACHA20_") {
|
||||
if strings.HasPrefix(declName, "TLS_") && !strings.HasPrefix(declName, "TLS_FALLBACK_") {
|
||||
discoveredCiphers[declName] = true
|
||||
}
|
||||
}
|
||||
|
||||
acceptedCiphers := allCiphers()
|
||||
for k := range discoveredCiphers {
|
||||
if _, ok := ciphers[k]; !ok {
|
||||
if _, ok := acceptedCiphers[k]; !ok {
|
||||
t.Errorf("discovered cipher tls.%s not in ciphers map", k)
|
||||
}
|
||||
}
|
||||
for k := range ciphers {
|
||||
for k := range acceptedCiphers {
|
||||
if _, ok := discoveredCiphers[k]; !ok {
|
||||
t.Errorf("ciphers map has %s not in tls package", k)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user