istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/echo/server/forwarder/tls.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package forwarder 16 17 import ( 18 "context" 19 "crypto/tls" 20 "encoding/pem" 21 "fmt" 22 "strings" 23 "time" 24 25 "istio.io/istio/pkg/hbone" 26 "istio.io/istio/pkg/test/echo" 27 "istio.io/istio/pkg/test/echo/proto" 28 ) 29 30 var _ protocol = &tlsProtocol{} 31 32 type tlsProtocol struct { 33 e *executor 34 } 35 36 func newTLSProtocol(e *executor) protocol { 37 return &tlsProtocol{e: e} 38 } 39 40 func (c *tlsProtocol) ForwardEcho(ctx context.Context, cfg *Config) (*proto.ForwardEchoResponse, error) { 41 return doForward(ctx, cfg, c.e, c.makeRequest) 42 } 43 44 func (c *tlsProtocol) makeRequest(ctx context.Context, cfg *Config, requestID int) (string, error) { 45 conn, err := newTLSConnection(cfg) 46 if err != nil { 47 return "", err 48 } 49 defer func() { _ = conn.Close() }() 50 msgBuilder := strings.Builder{} 51 echo.ForwarderURLField.WriteForRequest(&msgBuilder, requestID, cfg.Request.Url) 52 53 // Apply per-request timeout to calculate deadline for reads/writes. 54 ctx, cancel := context.WithTimeout(ctx, cfg.timeout) 55 defer cancel() 56 57 // Apply the deadline to the connection. 58 deadline, _ := ctx.Deadline() 59 if err := conn.SetWriteDeadline(deadline); err != nil { 60 return msgBuilder.String(), err 61 } 62 if err := conn.SetReadDeadline(deadline); err != nil { 63 return msgBuilder.String(), err 64 } 65 66 if err := conn.HandshakeContext(ctx); err != nil { 67 return "", err 68 } 69 // Make sure the client writes something to the buffer 70 message := "HelloWorld" 71 if cfg.Request.Message != "" { 72 message = cfg.Request.Message 73 } 74 75 start := time.Now() 76 if _, err := conn.Write([]byte(message + "\n")); err != nil { 77 fwLog.Warnf("TCP write failed: %v", err) 78 return msgBuilder.String(), err 79 } 80 81 cs := conn.ConnectionState() 82 echo.LatencyField.WriteForRequest(&msgBuilder, requestID, fmt.Sprintf("%v", time.Since(start))) 83 echo.CipherField.WriteForRequest(&msgBuilder, requestID, tls.CipherSuiteName(cs.CipherSuite)) 84 echo.TLSVersionField.WriteForRequest(&msgBuilder, requestID, versionName(cs.Version)) 85 echo.TLSServerName.WriteForRequest(&msgBuilder, requestID, cs.ServerName) 86 echo.AlpnField.WriteForRequest(&msgBuilder, requestID, cs.NegotiatedProtocol) 87 for n, i := range cs.PeerCertificates { 88 pemBlock := pem.Block{ 89 Type: "CERTIFICATE", 90 Bytes: i.Raw, 91 } 92 echo.WriteBodyLine(&msgBuilder, requestID, fmt.Sprintf("Response%d=%q", n, string(pem.EncodeToMemory(&pemBlock)))) 93 } 94 95 msg := msgBuilder.String() 96 return msg, nil 97 } 98 99 func versionName(v uint16) string { 100 switch v { 101 case tls.VersionTLS10: 102 return "1.0" 103 case tls.VersionTLS11: 104 return "1.1" 105 case tls.VersionTLS12: 106 return "1.2" 107 case tls.VersionTLS13: 108 return "1.3" 109 default: 110 return fmt.Sprintf("unknown-%v", v) 111 } 112 } 113 114 func (c *tlsProtocol) Close() error { 115 return nil 116 } 117 118 func newTLSConnection(cfg *Config) (*tls.Conn, error) { 119 address := cfg.Request.Url[len(cfg.scheme+"://"):] 120 121 con, err := hbone.TLSDialWithDialer(newDialer(cfg), "tcp", address, cfg.tlsConfig) 122 if err != nil { 123 return nil, err 124 } 125 return con, nil 126 }