go.uber.org/yarpc@v1.72.1/transport/internal/tls/testscenario/tlsscenario.go (about) 1 // Copyright (c) 2022 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package testscenario 22 23 import ( 24 "crypto/ecdsa" 25 "crypto/elliptic" 26 "crypto/rand" 27 "crypto/tls" 28 "crypto/x509" 29 "crypto/x509/pkix" 30 "math/big" 31 "net" 32 "testing" 33 "time" 34 35 "github.com/stretchr/testify/require" 36 ) 37 38 // TLSScenario holds client & server tls credentials. 39 type TLSScenario struct { 40 CAs *x509.CertPool 41 ServerCert *x509.Certificate 42 ServerKey *ecdsa.PrivateKey 43 ClientCert *x509.Certificate 44 ClientKey *ecdsa.PrivateKey 45 } 46 47 // ServerTLSConfig returns server TLS config. 48 func (t TLSScenario) ServerTLSConfig() *tls.Config { 49 return &tls.Config{ 50 GetCertificate: func(_ *tls.ClientHelloInfo) (*tls.Certificate, error) { 51 return &tls.Certificate{ 52 Certificate: [][]byte{t.ServerCert.Raw}, 53 Leaf: t.ServerCert, 54 PrivateKey: t.ServerKey, 55 }, nil 56 }, 57 ClientAuth: tls.RequireAndVerifyClientCert, 58 ClientCAs: t.CAs, 59 } 60 } 61 62 // ClientTLSConfig returns client TLS config. 63 func (t TLSScenario) ClientTLSConfig() *tls.Config { 64 return &tls.Config{ 65 GetClientCertificate: func(_ *tls.CertificateRequestInfo) (*tls.Certificate, error) { 66 return &tls.Certificate{ 67 Certificate: [][]byte{t.ClientCert.Raw}, 68 Leaf: t.ClientCert, 69 PrivateKey: t.ClientKey, 70 }, nil 71 }, 72 ServerName: "127.0.0.1", 73 RootCAs: t.CAs, 74 } 75 } 76 77 // Create returns client and server TLS credentials generated during 78 // the runtime only for testing. 79 func Create(t *testing.T, clientValidity time.Duration, serverValidity time.Duration) TLSScenario { 80 now := time.Now() 81 82 caKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 83 require.NoError(t, err) 84 caBytes, err := x509.CreateCertificate( 85 rand.Reader, 86 &x509.Certificate{ 87 Subject: pkix.Name{ 88 CommonName: "test ca", 89 }, 90 SerialNumber: big.NewInt(1), 91 BasicConstraintsValid: true, 92 IsCA: true, 93 KeyUsage: x509.KeyUsageCertSign, 94 NotBefore: now, 95 NotAfter: now.Add(10 * time.Minute), 96 }, 97 &x509.Certificate{}, 98 caKey.Public(), 99 caKey, 100 ) 101 require.NoError(t, err) 102 ca, err := x509.ParseCertificate(caBytes) 103 require.NoError(t, err) 104 105 serverKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 106 require.NoError(t, err) 107 serverCertBytes, err := x509.CreateCertificate( 108 rand.Reader, 109 &x509.Certificate{ 110 Subject: pkix.Name{ 111 CommonName: "server", 112 }, 113 NotAfter: now.Add(serverValidity), 114 SerialNumber: big.NewInt(2), 115 IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, 116 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyAgreement, 117 }, 118 ca, 119 serverKey.Public(), 120 caKey, 121 ) 122 require.NoError(t, err) 123 serverCert, err := x509.ParseCertificate(serverCertBytes) 124 require.NoError(t, err) 125 126 clientKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 127 require.NoError(t, err) 128 clientCertBytes, err := x509.CreateCertificate( 129 rand.Reader, 130 &x509.Certificate{ 131 Subject: pkix.Name{ 132 CommonName: "client", 133 }, 134 NotAfter: now.Add(clientValidity), 135 SerialNumber: big.NewInt(3), 136 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyAgreement, 137 }, 138 ca, 139 clientKey.Public(), 140 caKey, 141 ) 142 require.NoError(t, err) 143 clientCert, err := x509.ParseCertificate(clientCertBytes) 144 require.NoError(t, err) 145 146 pool := x509.NewCertPool() 147 pool.AddCert(ca) 148 149 return TLSScenario{ 150 CAs: pool, 151 ServerCert: serverCert, 152 ServerKey: serverKey, 153 ClientCert: clientCert, 154 ClientKey: clientKey, 155 } 156 }