From 738a864414153be57ea46f8e0ed933425a040d04 Mon Sep 17 00:00:00 2001 From: Zhecheng Date: Tue, 12 Jan 2021 22:01:56 +0800 Subject: [PATCH] Provide CipherSuites option between Clients and Servers Signed-off-by: Zhecheng --- build/yamls/antrea-aks.yml | 16 ++++- build/yamls/antrea-eks.yml | 16 ++++- build/yamls/antrea-gke.yml | 16 ++++- build/yamls/antrea-ipsec.yml | 16 ++++- build/yamls/antrea.yml | 16 ++++- build/yamls/base/conf/antrea-agent.conf | 10 +++ cmd/antrea-agent-simulator/simulator.go | 4 +- cmd/antrea-agent/agent.go | 7 +- cmd/antrea-agent/config.go | 6 ++ pkg/agent/client.go | 38 +++++++---- pkg/util/cipher/cipher.go | 66 ++++++++++++++++++ pkg/util/cipher/cipher_test.go | 91 +++++++++++++++++++++++++ test/e2e/tls_test.go | 49 +++++++++++++ 13 files changed, 320 insertions(+), 31 deletions(-) create mode 100644 pkg/util/cipher/cipher.go create mode 100644 pkg/util/cipher/cipher_test.go create mode 100644 test/e2e/tls_test.go diff --git a/build/yamls/antrea-aks.yml b/build/yamls/antrea-aks.yml index 9ad66112354..582987f4d65 100644 --- a/build/yamls/antrea-aks.yml +++ b/build/yamls/antrea-aks.yml @@ -1371,6 +1371,16 @@ data: # Provide the address of Kubernetes apiserver, to override any value provided in kubeconfig or InClusterConfig. # Defaults to "". It must be a host string, a host:port pair, or a URL to the base of the apiserver. #kubeAPIServerOverride: "" + + # Comma-separated list of cipher suites. If omitted, the default Go cipher suites will be used. + # https://golang.org/pkg/crypto/tls/#pkg-constants + #cipherSuites: + + # TLS min version from: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + #tlsMinVersion: + + # TLS max version from: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + #tlsMaxVersion: antrea-cni.conflist: | { "cniVersion":"0.3.0", @@ -1427,7 +1437,7 @@ metadata: annotations: {} labels: app: antrea - name: antrea-config-7d66b472ff + name: antrea-config-f98t5c7mhb namespace: kube-system --- apiVersion: v1 @@ -1538,7 +1548,7 @@ spec: key: node-role.kubernetes.io/master volumes: - configMap: - name: antrea-config-7d66b472ff + name: antrea-config-f98t5c7mhb name: antrea-config - name: antrea-controller-tls secret: @@ -1802,7 +1812,7 @@ spec: operator: Exists volumes: - configMap: - name: antrea-config-7d66b472ff + name: antrea-config-f98t5c7mhb name: antrea-config - hostPath: path: /etc/cni/net.d diff --git a/build/yamls/antrea-eks.yml b/build/yamls/antrea-eks.yml index b2bcc8df1bb..54c84414043 100644 --- a/build/yamls/antrea-eks.yml +++ b/build/yamls/antrea-eks.yml @@ -1371,6 +1371,16 @@ data: # Provide the address of Kubernetes apiserver, to override any value provided in kubeconfig or InClusterConfig. # Defaults to "". It must be a host string, a host:port pair, or a URL to the base of the apiserver. #kubeAPIServerOverride: "" + + # Comma-separated list of cipher suites. If omitted, the default Go cipher suites will be used. + # https://golang.org/pkg/crypto/tls/#pkg-constants + #cipherSuites: + + # TLS min version from: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + #tlsMinVersion: + + # TLS max version from: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + #tlsMaxVersion: antrea-cni.conflist: | { "cniVersion":"0.3.0", @@ -1427,7 +1437,7 @@ metadata: annotations: {} labels: app: antrea - name: antrea-config-7d66b472ff + name: antrea-config-f98t5c7mhb namespace: kube-system --- apiVersion: v1 @@ -1538,7 +1548,7 @@ spec: key: node-role.kubernetes.io/master volumes: - configMap: - name: antrea-config-7d66b472ff + name: antrea-config-f98t5c7mhb name: antrea-config - name: antrea-controller-tls secret: @@ -1804,7 +1814,7 @@ spec: operator: Exists volumes: - configMap: - name: antrea-config-7d66b472ff + name: antrea-config-f98t5c7mhb name: antrea-config - hostPath: path: /etc/cni/net.d diff --git a/build/yamls/antrea-gke.yml b/build/yamls/antrea-gke.yml index 664587c5ddb..4831682c371 100644 --- a/build/yamls/antrea-gke.yml +++ b/build/yamls/antrea-gke.yml @@ -1371,6 +1371,16 @@ data: # Provide the address of Kubernetes apiserver, to override any value provided in kubeconfig or InClusterConfig. # Defaults to "". It must be a host string, a host:port pair, or a URL to the base of the apiserver. #kubeAPIServerOverride: "" + + # Comma-separated list of cipher suites. If omitted, the default Go cipher suites will be used. + # https://golang.org/pkg/crypto/tls/#pkg-constants + #cipherSuites: + + # TLS min version from: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + #tlsMinVersion: + + # TLS max version from: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + #tlsMaxVersion: antrea-cni.conflist: | { "cniVersion":"0.3.0", @@ -1427,7 +1437,7 @@ metadata: annotations: {} labels: app: antrea - name: antrea-config-8hc5c7g4hb + name: antrea-config-ddb2982fm2 namespace: kube-system --- apiVersion: v1 @@ -1538,7 +1548,7 @@ spec: key: node-role.kubernetes.io/master volumes: - configMap: - name: antrea-config-8hc5c7g4hb + name: antrea-config-ddb2982fm2 name: antrea-config - name: antrea-controller-tls secret: @@ -1805,7 +1815,7 @@ spec: path: /home/kubernetes/bin name: host-cni-bin - configMap: - name: antrea-config-8hc5c7g4hb + name: antrea-config-ddb2982fm2 name: antrea-config - hostPath: path: /etc/cni/net.d diff --git a/build/yamls/antrea-ipsec.yml b/build/yamls/antrea-ipsec.yml index 9094fc04954..77f1bdba942 100644 --- a/build/yamls/antrea-ipsec.yml +++ b/build/yamls/antrea-ipsec.yml @@ -1376,6 +1376,16 @@ data: # Provide the address of Kubernetes apiserver, to override any value provided in kubeconfig or InClusterConfig. # Defaults to "". It must be a host string, a host:port pair, or a URL to the base of the apiserver. #kubeAPIServerOverride: "" + + # Comma-separated list of cipher suites. If omitted, the default Go cipher suites will be used. + # https://golang.org/pkg/crypto/tls/#pkg-constants + #cipherSuites: + + # TLS min version from: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + #tlsMinVersion: + + # TLS max version from: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + #tlsMaxVersion: antrea-cni.conflist: | { "cniVersion":"0.3.0", @@ -1432,7 +1442,7 @@ metadata: annotations: {} labels: app: antrea - name: antrea-config-k7574f7tdc + name: antrea-config-6c2b579h6g namespace: kube-system --- apiVersion: v1 @@ -1552,7 +1562,7 @@ spec: key: node-role.kubernetes.io/master volumes: - configMap: - name: antrea-config-k7574f7tdc + name: antrea-config-6c2b579h6g name: antrea-config - name: antrea-controller-tls secret: @@ -1851,7 +1861,7 @@ spec: operator: Exists volumes: - configMap: - name: antrea-config-k7574f7tdc + name: antrea-config-6c2b579h6g name: antrea-config - hostPath: path: /etc/cni/net.d diff --git a/build/yamls/antrea.yml b/build/yamls/antrea.yml index f92fdafee26..d6d3ed11979 100644 --- a/build/yamls/antrea.yml +++ b/build/yamls/antrea.yml @@ -1376,6 +1376,16 @@ data: # Provide the address of Kubernetes apiserver, to override any value provided in kubeconfig or InClusterConfig. # Defaults to "". It must be a host string, a host:port pair, or a URL to the base of the apiserver. #kubeAPIServerOverride: "" + + # Comma-separated list of cipher suites. If omitted, the default Go cipher suites will be used. + # https://golang.org/pkg/crypto/tls/#pkg-constants + #cipherSuites: + + # TLS min version from: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + #tlsMinVersion: + + # TLS max version from: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. + #tlsMaxVersion: antrea-cni.conflist: | { "cniVersion":"0.3.0", @@ -1432,7 +1442,7 @@ metadata: annotations: {} labels: app: antrea - name: antrea-config-2m4ktcghmf + name: antrea-config-6bc48b5tdd namespace: kube-system --- apiVersion: v1 @@ -1543,7 +1553,7 @@ spec: key: node-role.kubernetes.io/master volumes: - configMap: - name: antrea-config-2m4ktcghmf + name: antrea-config-6bc48b5tdd name: antrea-config - name: antrea-controller-tls secret: @@ -1807,7 +1817,7 @@ spec: operator: Exists volumes: - configMap: - name: antrea-config-2m4ktcghmf + name: antrea-config-6bc48b5tdd name: antrea-config - hostPath: path: /etc/cni/net.d diff --git a/build/yamls/base/conf/antrea-agent.conf b/build/yamls/base/conf/antrea-agent.conf index f03b6c6c000..72b60e832d3 100644 --- a/build/yamls/base/conf/antrea-agent.conf +++ b/build/yamls/base/conf/antrea-agent.conf @@ -120,3 +120,13 @@ featureGates: # Provide the address of Kubernetes apiserver, to override any value provided in kubeconfig or InClusterConfig. # Defaults to "". It must be a host string, a host:port pair, or a URL to the base of the apiserver. #kubeAPIServerOverride: "" + +# Comma-separated list of cipher suites. If omitted, the default Go cipher suites will be used. +# https://golang.org/pkg/crypto/tls/#pkg-constants +#cipherSuites: + +# TLS min version from: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. +#tlsMinVersion: + +# TLS max version from: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13. +#tlsMaxVersion: diff --git a/cmd/antrea-agent-simulator/simulator.go b/cmd/antrea-agent-simulator/simulator.go index 36ff1f33baf..e85ca393e7a 100644 --- a/cmd/antrea-agent-simulator/simulator.go +++ b/cmd/antrea-agent-simulator/simulator.go @@ -32,6 +32,7 @@ import ( "github.com/vmware-tanzu/antrea/pkg/agent" "github.com/vmware-tanzu/antrea/pkg/k8s" "github.com/vmware-tanzu/antrea/pkg/signals" + "github.com/vmware-tanzu/antrea/pkg/util/cipher" "github.com/vmware-tanzu/antrea/pkg/util/env" "github.com/vmware-tanzu/antrea/pkg/version" ) @@ -49,7 +50,8 @@ func run() error { } // Create Antrea Clientset for the given config. - antreaClientProvider := agent.NewAntreaClientProvider(componentbaseconfig.ClientConnectionConfiguration{}, k8sClient) + tlsConfig, _ := cipher.NewTLSConfig("", "", "") + antreaClientProvider := agent.NewAntreaClientProvider(componentbaseconfig.ClientConnectionConfiguration{}, k8sClient, tlsConfig) if err = antreaClientProvider.RunOnce(); err != nil { return err diff --git a/cmd/antrea-agent/agent.go b/cmd/antrea-agent/agent.go index 9fbb2b3ec64..3a9ce4d13af 100644 --- a/cmd/antrea-agent/agent.go +++ b/cmd/antrea-agent/agent.go @@ -51,6 +51,7 @@ import ( ofconfig "github.com/vmware-tanzu/antrea/pkg/ovs/openflow" "github.com/vmware-tanzu/antrea/pkg/ovs/ovsconfig" "github.com/vmware-tanzu/antrea/pkg/signals" + "github.com/vmware-tanzu/antrea/pkg/util/cipher" "github.com/vmware-tanzu/antrea/pkg/version" k8sproxy "github.com/vmware-tanzu/antrea/third_party/proxy" ) @@ -71,9 +72,13 @@ func run(o *Options) error { informerFactory := informers.NewSharedInformerFactory(k8sClient, informerDefaultResync) crdInformerFactory := crdinformers.NewSharedInformerFactory(crdClient, informerDefaultResync) traceflowInformer := crdInformerFactory.Ops().V1alpha1().Traceflows() + tlsConfig, err := cipher.NewTLSConfig(o.config.CipherSuites, o.config.TLSMinVersion, o.config.TLSMaxVersion) + if err != nil { + return fmt.Errorf("error generating TLS config: %v", err) + } // Create Antrea Clientset for the given config. - antreaClientProvider := agent.NewAntreaClientProvider(o.config.AntreaClientConnection, k8sClient) + antreaClientProvider := agent.NewAntreaClientProvider(o.config.AntreaClientConnection, k8sClient, tlsConfig) // Register Antrea Agent metrics if EnablePrometheusMetrics is set if o.config.EnablePrometheusMetrics { diff --git a/cmd/antrea-agent/config.go b/cmd/antrea-agent/config.go index 68602961071..5ef51841f84 100644 --- a/cmd/antrea-agent/config.go +++ b/cmd/antrea-agent/config.go @@ -127,4 +127,10 @@ type AgentConfig struct { // Provide the address of Kubernetes apiserver, to override any value provided in kubeconfig or InClusterConfig. // Defaults to "". It must be a host string, a host:port pair, or a URL to the base of the apiserver. KubeAPIServerOverride string `yaml:"kubeAPIServerOverride,omitempty"` + // Cipher suites to use on Client side. + CipherSuites string `yaml:"cipherSuites,omitempty"` + // TLS min version. + TLSMinVersion string `yaml:"tlsMinVersion,omitempty"` + // TLS max version. + TLSMaxVersion string `yaml:"tlsMaxVersion,omitempty"` } diff --git a/pkg/agent/client.go b/pkg/agent/client.go index 130482b88b5..4d9c73eb0c9 100644 --- a/pkg/agent/client.go +++ b/pkg/agent/client.go @@ -15,9 +15,11 @@ package agent import ( + "crypto/tls" "fmt" "io/ioutil" "net" + "net/http" "os" "sync" @@ -30,6 +32,7 @@ import ( cert "github.com/vmware-tanzu/antrea/pkg/apiserver/certificate" "github.com/vmware-tanzu/antrea/pkg/client/clientset/versioned" + "github.com/vmware-tanzu/antrea/pkg/util/cipher" ) // AntreaClientProvider provides a method to get Antrea client. @@ -46,11 +49,13 @@ type antreaClientProvider struct { client versioned.Interface // caContentProvider provides the very latest content of the ca bundle. caContentProvider *dynamiccertificates.ConfigMapCAController + // TLS config. + tlsConfig *tls.Config } var _ dynamiccertificates.Listener = &antreaClientProvider{} -func NewAntreaClientProvider(config config.ClientConnectionConfiguration, kubeClient kubernetes.Interface) *antreaClientProvider { +func NewAntreaClientProvider(config config.ClientConnectionConfiguration, kubeClient kubernetes.Interface, tlsConfig *tls.Config) *antreaClientProvider { // The key "ca.crt" may not exist at the beginning, no need to fail as the CA provider will watch the ConfigMap // and notify antreaClientProvider of any update. The consumers of antreaClientProvider are supposed to always // call GetAntreaClient() to get a client and not cache it. @@ -63,6 +68,7 @@ func NewAntreaClientProvider(config config.ClientConnectionConfiguration, kubeCl antreaClientProvider := &antreaClientProvider{ config: config, caContentProvider: antreaCAProvider, + tlsConfig: tlsConfig, } antreaCAProvider.AddListener(antreaClientProvider) @@ -108,14 +114,20 @@ func (p *antreaClientProvider) updateAntreaClient() error { klog.Info("Didn't get CA certificate, skip updating Antrea Client") return nil } - kubeConfig, err = inClusterConfig(caBundle) + kubeConfig, err = inClusterConfig(caBundle, p.tlsConfig) + if err != nil { + return err + } + } else { kubeConfig, err = clientcmd.NewNonInteractiveDeferredLoadingClientConfig( &clientcmd.ClientConfigLoadingRules{ExplicitPath: p.config.Kubeconfig}, &clientcmd.ConfigOverrides{}).ClientConfig() - } - if err != nil { - return err + if err != nil { + return err + } + tr := &http.Transport{TLSClientConfig: p.tlsConfig} + kubeConfig.Transport = tr } // ContentType will be used to define the Accept header if AcceptContentTypes is not set. @@ -139,7 +151,7 @@ func (p *antreaClientProvider) updateAntreaClient() error { // kubernetes gives to pods. It's intended for clients that expect to be // running inside a pod running on kubernetes. It will return error // if called from a process not running in a kubernetes environment. -func inClusterConfig(caBundle []byte) (*rest.Config, error) { +func inClusterConfig(caBundle []byte, tlsConfig *tls.Config) (*rest.Config, error) { // #nosec G101: false positive triggered by variable name which includes "token" const tokenFile = "/var/run/secrets/kubernetes.io/serviceaccount/token" host, port := os.Getenv("ANTREA_SERVICE_HOST"), os.Getenv("ANTREA_SERVICE_PORT") @@ -152,15 +164,13 @@ func inClusterConfig(caBundle []byte) (*rest.Config, error) { return nil, err } - tlsClientConfig := rest.TLSClientConfig{ - CAData: caBundle, - ServerName: cert.GetAntreaServerNames()[0], - } - - return &rest.Config{ + config := rest.Config{ Host: "https://" + net.JoinHostPort(host, port), - TLSClientConfig: tlsClientConfig, BearerToken: string(token), BearerTokenFile: tokenFile, - }, nil + } + if err := cipher.AppendTLSConfig(&config, tlsConfig, caBundle, cert.GetAntreaServerNames()[0]); err != nil { + return nil, err + } + return &config, nil } diff --git a/pkg/util/cipher/cipher.go b/pkg/util/cipher/cipher.go new file mode 100644 index 00000000000..4a2d448b67c --- /dev/null +++ b/pkg/util/cipher/cipher.go @@ -0,0 +1,66 @@ +// Copyright 2021 Antrea Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cipher + +import ( + "crypto/tls" + "crypto/x509" + "fmt" + "net/http" + "strings" + + "k8s.io/client-go/rest" + "k8s.io/component-base/cli/flag" +) + +var tlsVersionMap = map[string]uint16{ + "VersionTLS10": tls.VersionTLS10, + "VersionTLS11": tls.VersionTLS11, + "VersionTLS12": tls.VersionTLS12, + "VersionTLS13": tls.VersionTLS13, +} + +// NewTLSConfig generates a tls.Config with given cipher suites string, TLS min version and TLS max version. +func NewTLSConfig(cipherSuites string, minVersion string, maxVersion string) (*tls.Config, error) { + csStrList := strings.Split(strings.ReplaceAll(cipherSuites, " ", ""), ",") + csIntList, err := flag.TLSCipherSuites(csStrList) + if err != nil { + return nil, err + } + return &tls.Config{ + CipherSuites: csIntList, + MinVersion: tlsVersionMap[minVersion], + MaxVersion: tlsVersionMap[maxVersion], + }, nil +} + +// AppendTLSConfig appends TLS config (Cipher Suites, TLSVersion, PreferServerCipherSuites, caBundle, serverName) to +// *rest.Config. +func AppendTLSConfig(c *rest.Config, cipherTLSConfig *tls.Config, caBundle []byte, serverName string) error { + tlsConfig := new(tls.Config) + tlsConfig.RootCAs = x509.NewCertPool() + if ok := tlsConfig.RootCAs.AppendCertsFromPEM(caBundle); !ok { + return fmt.Errorf("error appending certificates from PEM encoded certificate") + } + tlsConfig.ServerName = serverName + tlsConfig.CipherSuites = cipherTLSConfig.CipherSuites + tlsConfig.MinVersion = cipherTLSConfig.MinVersion + tlsConfig.MaxVersion = cipherTLSConfig.MaxVersion + tlsConfig.PreferServerCipherSuites = false + + trans := http.Transport{TLSClientConfig: tlsConfig} + c.Transport = &trans + return nil +} diff --git a/pkg/util/cipher/cipher_test.go b/pkg/util/cipher/cipher_test.go new file mode 100644 index 00000000000..d674ff00dfa --- /dev/null +++ b/pkg/util/cipher/cipher_test.go @@ -0,0 +1,91 @@ +// Copyright 2021 Antrea Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cipher + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/client-go/rest" +) + +func TestAppendTLSConfig(t *testing.T) { + config := rest.Config{ + Host: "http://1.1.1.1:443", + BearerToken: "token", + BearerTokenFile: "/tmp/token-file", + } + caBundle := `-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRhbnRy +ZWEtY2FAMTYxMTY0NjczODAeFw0yMTAxMjYwNjM4NTdaFw0yMjAxMjYwNjM4NTda +MBwxGjAYBgNVBAMMEWFudHJlYUAxNjExNjQ2NzM4MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAmF24OvynHRA1VIn9lL9iDM0KhO1CxjoRm7Y/1c5bbaqw ++HkaQKLMGTxItTvoNV4UeotavLo+P1FH2E7fTFdfn8dMoSZXHaPtcTOzDWFPGage +iJI9f//wwS81ft+bkexP0s8C2bW7zP5q+MFmdUqiIYWkIHgNr+E607P4XEEuA1zu +QIyTVWvMyXqMMyQmsmwfikMEUvaWYXdYJA3A/va5di96PFddzplT7c10TgaLO2xV +A3HcRmI/SveNC8oFituLZYNgdFl80v/w8LUUKojCmRSCcnj2XGmAGFx7wNnA6U1/ +7Fs8tK26DNXCluKwxbKfvrfHNGEzbDASEEOoBAnCBQIDAQABo4GTMIGQMA4GA1Ud +DwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMB8G +A1UdIwQYMBaAFHmTa17VUt1cMIRwYQIC9l0XqfYtMDoGA1UdEQQzMDGCBmFudHJl +YYIWYW50cmVhLmt1YmUtc3lzdGVtLnN2Y4IJbG9jYWxob3N0hwR/AAABMA0GCSqG +SIb3DQEBCwUAA4IBAQB5H1rXfHvevVpO441WlRQ/4xBsHM4a65mLkvfU8agavowJ +cmtYMVHG4kKfs70pL2AQ1Ihb7pwO0kt3k8WkoLCEk9h8p+fXIIWEWtV2B7XG705n +uUU2wq3V0dUMPikm5Cba84MshiTwbAk9rEaAk2lx8q1qas0hHv36styo2U75iNoj +LTAv3m619xptKMl2I289YdB4I8TswTYARNFWkv4jfwzFQS8lPVLDNT52hab+NQAV +HCKn31MdhZgvTRwl0LXq1+VkQAfHei4cFEEyg9y+8uOGER9Ibi6CzEUN7EjfNRUu +X7/QTxqyi1tpU8NEdl48Ie6s1lJNj3AOjs3RJgpJ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRhbnRy +ZWEtY2FAMTYxMTY0NjczODAeFw0yMTAxMjYwNjM4NTdaFw0yMjAxMjYwNjM4NTda +MB8xHTAbBgNVBAMMFGFudHJlYS1jYUAxNjExNjQ2NzM4MIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAwuOLmmSkaKu7GgQePRhhgt5m25IovmEEsVZDksa8 +SzqjuevFoOR+QfHK/k8/3DKyM4Vqp9YxDg+GOcBuwX3eD/xiqguufou5rJ2gAinv +5F3c27Bj98mBoBvlsHLrHudHVxMZlTutely+kxXdVf2N/Gx00Duy5w8XeejKq/a/ +vyrmsHKOu0VMNKrYs+US/K63t4ROQtIUcdqN7rLhPRjgr/jDuZCUJhgQJW17+Lm6 ++xSu7MKUDLdBfodO/7sVwP2FfGPa+CugBPvbylw3D6O5TBqf+/4XmCswIyf7M2IC +zlbcY8Gix4CrowgvT1iY4Nr6enasIYyHxQ6O2F1a5blp4QIDAQABo0IwQDAOBgNV +HQ8BAf8EBAMCAqQwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUeZNrXtVS3Vww +hHBhAgL2XRep9i0wDQYJKoZIhvcNAQELBQADggEBAEL62bFwUK6fLzP6zYb0WfZY +RAyuhPZND2wXV9Lc8lsW253kGNY0CmKPRXU7mts0VxJB+0iCPm08Bi1PROmX4uKc +VbO4ZBS8CtZJNC8DBK0TdRWecfmo56lIFYJVPz0AWDU6oZ6HmPhuiZ2mBCIbJykd +HVmsjJ9eMihzlykNEj890jpDfSyPfF3qSzr11/pDZ1vOrVJGih9H6/dVyZ1QdqK9 +Z8VwpXnADeT4errNNUdPFDUi98GtGCc4vlHqAgt7pHzBpXlfRy//gby8+ymfwArf +eKBeyc0hPDwTthJZpSco4WntwwtFNUAmOz3qP5F7ESz0DKzLd98K/Q9VRZlIVkM= +-----END CERTIFICATE-----` + + tests := []struct { + config *rest.Config + cipherSuites string + tlsMinVersion string + tlsMaxVersion string + caBundle []byte + serverName string + }{ + {&config, + "TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA", + "VersionTLS12", + "VersionTLS13", + []byte(caBundle), + "serverName", + }, + } + for _, tc := range tests { + tlsConfig, err := NewTLSConfig(tc.cipherSuites, tc.tlsMinVersion, tc.tlsMaxVersion) + assert.NoError(t, err) + err = AppendTLSConfig(tc.config, tlsConfig, tc.caBundle, tc.serverName) + assert.NoError(t, err) + } +} diff --git a/test/e2e/tls_test.go b/test/e2e/tls_test.go new file mode 100644 index 00000000000..9b264f74821 --- /dev/null +++ b/test/e2e/tls_test.go @@ -0,0 +1,49 @@ +package e2e + +import ( + "context" + "crypto/tls" + "fmt" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestTLSCipherSuites(t *testing.T) { + // #nosec G402: ignore insecure options in test code + data, err := setupTest(t) + if err != nil { + t.Fatalf("Error when setting up test: %v", err) + } + defer teardownTest(t, data) + + const token = "/var/run/secrets/kubernetes.io/serviceaccount/token" + svc, err := data.clientset.CoreV1().Services(antreaNamespace).Get(context.TODO(), "antrea", metav1.GetOptions{}) + assert.NoError(t, err, "failed to get Antrea Service") + if len(svc.Spec.Ports) == 0 { + t.Fatal("Antrea Service has no ports") + } + url := fmt.Sprintf("https://%s:%d", svc.Spec.ClusterIP, svc.Spec.Ports[0].Port) + + cs := tls.TLS_RSA_WITH_AES_128_CBC_SHA + config := &tls.Config{ + InsecureSkipVerify: true, + CipherSuites: []uint16{cs}, + MaxVersion: tls.VersionTLS12, + PreferServerCipherSuites: false, + } + tr := &http.Transport{TLSClientConfig: config} + client := &http.Client{Transport: tr} + + req, err := http.NewRequest("GET", url, nil) + assert.NoError(t, err, "failed to create HTTP request") + req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token)) + resp, err := client.Do(req) + assert.NoError(t, err, "failed to connect to %s", url) + respCS := resp.TLS.CipherSuite + defer resp.Body.Close() + + assert.Equal(t, cs, respCS, "Cipher Suite used by Server should be %s", tls.CipherSuiteName(cs)) +}