mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #14601 from dusk125/release-3.4
Backport #14500 to 3.4
This commit is contained in:
commit
ce1630f68f
@ -566,13 +566,9 @@ func updateCipherSuites(tls *transport.TLSInfo, ss []string) error {
|
||||
return fmt.Errorf("TLSInfo.CipherSuites is already specified (given %v)", ss)
|
||||
}
|
||||
if len(ss) > 0 {
|
||||
cs := make([]uint16, len(ss))
|
||||
for i, s := range ss {
|
||||
var ok bool
|
||||
cs[i], ok = tlsutil.GetCipherSuite(s)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected TLS cipher suite %q", s)
|
||||
}
|
||||
cs, err := tlsutil.GetCipherSuites(ss)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tls.CipherSuites = cs
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import (
|
||||
pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
|
||||
"go.etcd.io/etcd/pkg/debugutil"
|
||||
"go.etcd.io/etcd/pkg/logutil"
|
||||
"go.etcd.io/etcd/pkg/tlsutil"
|
||||
"go.etcd.io/etcd/pkg/transport"
|
||||
"go.etcd.io/etcd/proxy/grpcproxy"
|
||||
|
||||
@ -70,11 +71,12 @@ var (
|
||||
|
||||
// tls for clients connecting to proxy
|
||||
|
||||
grpcProxyListenCA string
|
||||
grpcProxyListenCert string
|
||||
grpcProxyListenKey string
|
||||
grpcProxyListenAutoTLS bool
|
||||
grpcProxyListenCRL string
|
||||
grpcProxyListenCA string
|
||||
grpcProxyListenCert string
|
||||
grpcProxyListenKey string
|
||||
grpcProxyListenCipherSuites []string
|
||||
grpcProxyListenAutoTLS bool
|
||||
grpcProxyListenCRL string
|
||||
|
||||
grpcProxyAdvertiseClientURL string
|
||||
grpcProxyResolverPrefix string
|
||||
@ -140,6 +142,7 @@ func newGRPCProxyStartCommand() *cobra.Command {
|
||||
cmd.Flags().StringVar(&grpcProxyListenCert, "cert-file", "", "identify secure connections to the proxy using this TLS certificate file")
|
||||
cmd.Flags().StringVar(&grpcProxyListenKey, "key-file", "", "identify secure connections to the proxy using this TLS key file")
|
||||
cmd.Flags().StringVar(&grpcProxyListenCA, "trusted-ca-file", "", "verify certificates of TLS-enabled secure proxy using this CA bundle")
|
||||
cmd.Flags().StringSliceVar(&grpcProxyListenCipherSuites, "listen-cipher-suites", grpcProxyListenCipherSuites, "Comma-separated list of supported TLS cipher suites between client/proxy (empty will be auto-populated by Go).")
|
||||
cmd.Flags().BoolVar(&grpcProxyListenAutoTLS, "auto-tls", false, "proxy TLS using generated certificates")
|
||||
cmd.Flags().StringVar(&grpcProxyListenCRL, "client-crl-file", "", "proxy client certificate revocation list file.")
|
||||
|
||||
@ -176,20 +179,27 @@ func startGRPCProxy(cmd *cobra.Command, args []string) {
|
||||
}
|
||||
grpclog.SetLoggerV2(gl)
|
||||
|
||||
tlsinfo := newTLS(grpcProxyListenCA, grpcProxyListenCert, grpcProxyListenKey)
|
||||
if tlsinfo == nil && grpcProxyListenAutoTLS {
|
||||
tlsInfo := newTLS(grpcProxyListenCA, grpcProxyListenCert, grpcProxyListenKey)
|
||||
if len(grpcProxyListenCipherSuites) > 0 {
|
||||
cs, err := tlsutil.GetCipherSuites(grpcProxyListenCipherSuites)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
tlsInfo.CipherSuites = cs
|
||||
}
|
||||
if tlsInfo == nil && grpcProxyListenAutoTLS {
|
||||
host := []string{"https://" + grpcProxyListenAddr}
|
||||
dir := filepath.Join(grpcProxyDataDir, "fixtures", "proxy")
|
||||
autoTLS, err := transport.SelfCert(lg, dir, host)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
tlsinfo = &autoTLS
|
||||
tlsInfo = &autoTLS
|
||||
}
|
||||
if tlsinfo != nil {
|
||||
lg.Info("gRPC proxy server TLS", zap.String("tls-info", fmt.Sprintf("%+v", tlsinfo)))
|
||||
if tlsInfo != nil {
|
||||
lg.Info("gRPC proxy server TLS", zap.String("tls-info", fmt.Sprintf("%+v", tlsInfo)))
|
||||
}
|
||||
m := mustListenCMux(lg, tlsinfo)
|
||||
m := mustListenCMux(lg, tlsInfo)
|
||||
grpcl := m.Match(cmux.HTTP2())
|
||||
defer func() {
|
||||
grpcl.Close()
|
||||
@ -199,7 +209,7 @@ func startGRPCProxy(cmd *cobra.Command, args []string) {
|
||||
client := mustNewClient(lg)
|
||||
httpClient := mustNewHTTPClient(lg)
|
||||
|
||||
srvhttp, httpl := mustHTTPListener(lg, m, tlsinfo, client)
|
||||
srvhttp, httpl := mustHTTPListener(lg, m, tlsInfo, client)
|
||||
|
||||
if err := http2.ConfigureServer(srvhttp, &http2.Server{
|
||||
MaxConcurrentStreams: maxConcurrentStreams,
|
||||
@ -212,7 +222,7 @@ func startGRPCProxy(cmd *cobra.Command, args []string) {
|
||||
go func() { errc <- srvhttp.Serve(httpl) }()
|
||||
go func() { errc <- m.Serve() }()
|
||||
if len(grpcProxyMetricsListenAddr) > 0 {
|
||||
mhttpl := mustMetricsListener(lg, tlsinfo)
|
||||
mhttpl := mustMetricsListener(lg, tlsInfo)
|
||||
go func() {
|
||||
mux := http.NewServeMux()
|
||||
grpcproxy.HandleMetrics(mux, httpClient, client.Endpoints())
|
||||
|
@ -1,5 +1,3 @@
|
||||
// +build !go1.15
|
||||
|
||||
// Copyright 2018 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -16,38 +14,43 @@
|
||||
|
||||
package tlsutil
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
// cipher suites implemented by Go
|
||||
// https://github.com/golang/go/blob/dev.boringcrypto.go1.10/src/crypto/tls/cipher_suites.go
|
||||
var cipherSuites = 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,
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||
}
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// GetCipherSuite returns the corresponding cipher suite,
|
||||
// and boolean value if it is supported.
|
||||
func GetCipherSuite(s string) (uint16, bool) {
|
||||
v, ok := cipherSuites[s]
|
||||
return v, ok
|
||||
for _, c := range tls.CipherSuites() {
|
||||
if s == c.Name {
|
||||
return c.ID, true
|
||||
}
|
||||
}
|
||||
for _, c := range tls.InsecureCipherSuites() {
|
||||
if s == c.Name {
|
||||
return c.ID, true
|
||||
}
|
||||
}
|
||||
switch s {
|
||||
case "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305":
|
||||
return tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, true
|
||||
case "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305":
|
||||
return tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// GetCipherSuites returns a list of corresponding cipher suite IDs.
|
||||
func GetCipherSuites(ss []string) ([]uint16, error) {
|
||||
cs := make([]uint16, len(ss))
|
||||
for i, s := range ss {
|
||||
var ok bool
|
||||
cs[i], ok = GetCipherSuite(s)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected TLS cipher suite %q", s)
|
||||
}
|
||||
}
|
||||
|
||||
return cs, nil
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
// +build go1.15
|
||||
|
||||
// Copyright 2018 The etcd 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 tlsutil
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
// GetCipherSuite returns the corresponding cipher suite,
|
||||
// and boolean value if it is supported.
|
||||
func GetCipherSuite(s string) (uint16, bool) {
|
||||
for _, c := range tls.CipherSuites() {
|
||||
if s == c.Name {
|
||||
return c.ID, true
|
||||
}
|
||||
}
|
||||
for _, c := range tls.InsecureCipherSuites() {
|
||||
if s == c.Name {
|
||||
return c.ID, true
|
||||
}
|
||||
}
|
||||
switch s {
|
||||
case "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305":
|
||||
return tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, true
|
||||
case "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305":
|
||||
return tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
// +build go1.15
|
||||
|
||||
// Copyright 2018 The etcd 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 tlsutil
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetCipherSuite_not_existing(t *testing.T) {
|
||||
_, ok := GetCipherSuite("not_existing")
|
||||
if ok {
|
||||
t.Fatal("Expected not ok")
|
||||
}
|
||||
}
|
||||
|
||||
func CipherSuiteExpectedToExist(tb testing.TB, cipher string, expectedId uint16) {
|
||||
vid, ok := GetCipherSuite(cipher)
|
||||
if !ok {
|
||||
tb.Errorf("Expected %v cipher to exist", cipher)
|
||||
}
|
||||
if vid != expectedId {
|
||||
tb.Errorf("For %v expected=%v found=%v", cipher, expectedId, vid)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCipherSuite_success(t *testing.T) {
|
||||
CipherSuiteExpectedToExist(t, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
|
||||
CipherSuiteExpectedToExist(t, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
|
||||
|
||||
// Explicit test for legacy names
|
||||
CipherSuiteExpectedToExist(t, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256)
|
||||
CipherSuiteExpectedToExist(t, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)
|
||||
}
|
||||
|
||||
func TestGetCipherSuite_insecure(t *testing.T) {
|
||||
CipherSuiteExpectedToExist(t, "TLS_ECDHE_RSA_WITH_RC4_128_SHA", tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA)
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
// +build !go1.15
|
||||
|
||||
// Copyright 2018 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -17,28 +15,36 @@
|
||||
package tlsutil
|
||||
|
||||
import (
|
||||
"go/importer"
|
||||
"reflect"
|
||||
"strings"
|
||||
"crypto/tls"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetCipherSuites(t *testing.T) {
|
||||
pkg, err := importer.For("source", nil).Import("crypto/tls")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cm := make(map[string]uint16)
|
||||
for _, s := range pkg.Scope().Names() {
|
||||
if strings.HasPrefix(s, "TLS_RSA_") || strings.HasPrefix(s, "TLS_ECDHE_") {
|
||||
v, ok := GetCipherSuite(s)
|
||||
if !ok {
|
||||
t.Fatalf("Go implements missing cipher suite %q (%v)", s, v)
|
||||
}
|
||||
cm[s] = v
|
||||
}
|
||||
}
|
||||
if !reflect.DeepEqual(cm, cipherSuites) {
|
||||
t.Fatalf("found unmatched cipher suites %v (Go) != %v", cm, cipherSuites)
|
||||
func TestGetCipherSuite_not_existing(t *testing.T) {
|
||||
_, ok := GetCipherSuite("not_existing")
|
||||
if ok {
|
||||
t.Fatal("Expected not ok")
|
||||
}
|
||||
}
|
||||
|
||||
func CipherSuiteExpectedToExist(tb testing.TB, cipher string, expectedId uint16) {
|
||||
vid, ok := GetCipherSuite(cipher)
|
||||
if !ok {
|
||||
tb.Errorf("Expected %v cipher to exist", cipher)
|
||||
}
|
||||
if vid != expectedId {
|
||||
tb.Errorf("For %v expected=%v found=%v", cipher, expectedId, vid)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCipherSuite_success(t *testing.T) {
|
||||
CipherSuiteExpectedToExist(t, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
|
||||
CipherSuiteExpectedToExist(t, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
|
||||
|
||||
// Explicit test for legacy names
|
||||
CipherSuiteExpectedToExist(t, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256)
|
||||
CipherSuiteExpectedToExist(t, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)
|
||||
}
|
||||
|
||||
func TestGetCipherSuite_insecure(t *testing.T) {
|
||||
CipherSuiteExpectedToExist(t, "TLS_ECDHE_RSA_WITH_RC4_128_SHA", tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA)
|
||||
}
|
||||
|
@ -298,3 +298,41 @@ func TestGrpcproxyAndCommonName(t *testing.T) {
|
||||
}
|
||||
p.Stop()
|
||||
}
|
||||
|
||||
func TestGrpcproxyAndListenCipherSuite(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
args []string
|
||||
}{
|
||||
{
|
||||
name: "ArgsWithCipherSuites",
|
||||
args: []string{
|
||||
binDir + "/etcd",
|
||||
"grpc-proxy",
|
||||
"start",
|
||||
"--listen-cipher-suites", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ArgsWithoutCipherSuites",
|
||||
args: []string{
|
||||
binDir + "/etcd",
|
||||
"grpc-proxy",
|
||||
"start",
|
||||
"--listen-cipher-suites", "",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
pw, err := spawnCmd(test.args)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = pw.Stop(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user