transport_test.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. Copyright 2017 The Kubernetes Authors.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package certificate
  14. import (
  15. "context"
  16. "crypto/tls"
  17. "crypto/x509"
  18. "fmt"
  19. "math/big"
  20. "net/http"
  21. "net/http/httptest"
  22. "sync/atomic"
  23. "testing"
  24. "time"
  25. "k8s.io/apimachinery/pkg/runtime"
  26. "k8s.io/apimachinery/pkg/runtime/serializer"
  27. certificatesclient "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
  28. "k8s.io/client-go/rest"
  29. )
  30. var (
  31. client1CertData = newCertificateData(`-----BEGIN CERTIFICATE-----
  32. MIICBDCCAW2gAwIBAgIJAPgVBh+4xbGoMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV
  33. BAMMEHdlYmhvb2tfdGVzdHNfY2EwIBcNMTcwNzI4MjMxNTI4WhgPMjI5MTA1MTMy
  34. MzE1MjhaMB8xHTAbBgNVBAMMFHdlYmhvb2tfdGVzdHNfY2xpZW50MIGfMA0GCSqG
  35. SIb3DQEBAQUAA4GNADCBiQKBgQDkGXXSm6Yun5o3Jlmx45rItcQ2pmnoDk4eZfl0
  36. rmPa674s2pfYo3KywkXQ1Fp3BC8GUgzPLSfJ8xXya9Lg1Wo8sHrDln0iRg5HXxGu
  37. uFNhRBvj2S0sIff0ZG/IatB9I6WXVOUYuQj6+A0CdULNj1vBqH9+7uWbLZ6lrD4b
  38. a44x/wIDAQABo0owSDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAdBgNVHSUEFjAU
  39. BggrBgEFBQcDAgYIKwYBBQUHAwEwDwYDVR0RBAgwBocEfwAAATANBgkqhkiG9w0B
  40. AQsFAAOBgQCpN27uh/LjUVCaBK7Noko25iih/JSSoWzlvc8CaipvSPofNWyGx3Vu
  41. OdcSwNGYX/pp4ZoAzFij/Y5u0vKTVLkWXATeTMVmlPvhmpYjj9gPkCSY6j/SiKlY
  42. kGy0xr+0M5UQkMBcfIh9oAp9um1fZHVWAJAGP/ikZgkcUey0LmBn8w==
  43. -----END CERTIFICATE-----`, `-----BEGIN RSA PRIVATE KEY-----
  44. MIICWwIBAAKBgQDkGXXSm6Yun5o3Jlmx45rItcQ2pmnoDk4eZfl0rmPa674s2pfY
  45. o3KywkXQ1Fp3BC8GUgzPLSfJ8xXya9Lg1Wo8sHrDln0iRg5HXxGuuFNhRBvj2S0s
  46. Iff0ZG/IatB9I6WXVOUYuQj6+A0CdULNj1vBqH9+7uWbLZ6lrD4ba44x/wIDAQAB
  47. AoGAZbWwowvCq1GBq4vPPRI3h739Uz0bRl1ymf1woYXNguXRtCB4yyH+2BTmmrrF
  48. 6AIWkePuUEdbUaKyK5nGu3iOWM+/i6NP3kopQANtbAYJ2ray3kwvFlhqyn1bxX4n
  49. gl/Cbdw1If4zrDrB66y8mYDsjzK7n/gFaDNcY4GArjvOXKkCQQD9Lgv+WD73y4RP
  50. yS+cRarlEeLLWVsX/pg2oEBLM50jsdUnrLSW071MjBgP37oOXzqynF9SoDbP2Y5C
  51. x+aGux9LAkEA5qPlQPv0cv8Wc3qTI+LixZ/86PPHKWnOnwaHm3b9vQjZAkuVQg3n
  52. Wgg9YDmPM87t3UFH7ZbDihUreUxwr9ZjnQJAZ9Z95shMsxbOYmbSVxafu6m1Sc+R
  53. M+sghK7/D5jQpzYlhUspGf8n0YBX0hLhXUmjamQGGH5LXL4Owcb4/mM6twJAEVio
  54. SF/qva9jv+GrKVrKFXT374lOJFY53Qn/rvifEtWUhLCslCA5kzLlctRBafMZPrfH
  55. Mh5RrJP1BhVysDbenQJASGcc+DiF7rB6K++ZGyC11E2AP29DcZ0pgPESSV7npOGg
  56. +NqPRZNVCSZOiVmNuejZqmwKhZNGZnBFx1Y+ChAAgw==
  57. -----END RSA PRIVATE KEY-----`)
  58. client2CertData = newCertificateData(`-----BEGIN CERTIFICATE-----
  59. MIICBDCCAW2gAwIBAgIJAPgVBh+4xbGnMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV
  60. BAMMEHdlYmhvb2tfdGVzdHNfY2EwIBcNMTcwNzI4MjMxNTI4WhgPMjI5MTA1MTMy
  61. MzE1MjhaMB8xHTAbBgNVBAMMFHdlYmhvb2tfdGVzdHNfY2xpZW50MIGfMA0GCSqG
  62. SIb3DQEBAQUAA4GNADCBiQKBgQDQQLzbrmHbtlxE7wViaoXFp5tQx7zzM2Ed7O1E
  63. gs3JUws5KkPbNrejLwixvLkzzU152M43UGsyKDn7HPyjXDogTZSW6C257XpYodk3
  64. S/gZS9oZtPss4UJuJioQk/M8X1ZjYP8kCTArOvVRJeNQL8GM7h5QQ6J5LUq+IdZb
  65. T0retQIDAQABo0owSDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAdBgNVHSUEFjAU
  66. BggrBgEFBQcDAgYIKwYBBQUHAwEwDwYDVR0RBAgwBocEfwAAATANBgkqhkiG9w0B
  67. AQsFAAOBgQBdAxoU5YAmp0d+5b4qg/xOGC5rKcnksQEXYoGwFBWwaKvh9oUlGGxI
  68. A5Ykf2TEl24br4tLmicpdxUX4H4PbkdPxOjM9ghIKlmgHo8vBRC0iVIwYgQsw1W8
  69. ETY34Or+PJqaeslqx/t7kUKY5UIF9DLVolsIiAHveJNR2uBWiP0KiQ==
  70. -----END CERTIFICATE-----`, `-----BEGIN RSA PRIVATE KEY-----
  71. MIICXQIBAAKBgQDQQLzbrmHbtlxE7wViaoXFp5tQx7zzM2Ed7O1Egs3JUws5KkPb
  72. NrejLwixvLkzzU152M43UGsyKDn7HPyjXDogTZSW6C257XpYodk3S/gZS9oZtPss
  73. 4UJuJioQk/M8X1ZjYP8kCTArOvVRJeNQL8GM7h5QQ6J5LUq+IdZbT0retQIDAQAB
  74. AoGBAMFjTL4IKvG4X+jXub1RxFXvNkkGos2Jaec7TH5xpZ4OUv7L4+We41tTYxSC
  75. d83GGetLzPwK3vDd8DHkEiu1incket78rwmQ89LnQNyM0B5ejaTjW2zHcvKJ0Mtn
  76. nM32juQfq8St9JZVweS87k8RkLt9cOrg6219MRbFO+1Vn8WhAkEA+/rqHCspBdXr
  77. 7RL+H63k7RjqBllVEYlw1ukqTw1gp5IImmeOwgl3aRrJJfFV6gxxEqQ4CCb2vf9M
  78. yjrGEvP9KQJBANOTPcpskT/0dyipsAkvLFZTKjN+4fdfq37H3dVgMR6oQcMJwukd
  79. cEio1Hx+XzXuD0RHXighq7bUzel+IqzRuq0CQBJkzpIf1G7InuA/cq19VCi6mNq9
  80. yqftEH+fpab/ov6YemhLBvDDICRcADL02wCqx9ZEhpKRxZE5AbIBeFQJ24ECQG4f
  81. 9cmnOPNRC7TengIpy6ojH5QuNu/LnDghUBYAO5D5g0FBk3JDIG6xceha3rPzdX7U
  82. pu28mORRX9xpCyNpBwECQQCtDNZoehdPVuZA3Wocno31Rjmuy83ajgRRuEzqv0tj
  83. uC6Jo2eLcSV1sSdzTjaaWdM6XeYj6yHOAm8ZBIQs7m6V
  84. -----END RSA PRIVATE KEY-----`)
  85. )
  86. type certificateData struct {
  87. keyPEM []byte
  88. certificatePEM []byte
  89. certificate *tls.Certificate
  90. }
  91. func newCertificateData(certificatePEM string, keyPEM string) *certificateData {
  92. certificate, err := tls.X509KeyPair([]byte(certificatePEM), []byte(keyPEM))
  93. if err != nil {
  94. panic(fmt.Sprintf("Unable to initialize certificate: %v", err))
  95. }
  96. certs, err := x509.ParseCertificates(certificate.Certificate[0])
  97. if err != nil {
  98. panic(fmt.Sprintf("Unable to initialize certificate leaf: %v", err))
  99. }
  100. certificate.Leaf = certs[0]
  101. return &certificateData{
  102. keyPEM: []byte(keyPEM),
  103. certificatePEM: []byte(certificatePEM),
  104. certificate: &certificate,
  105. }
  106. }
  107. type fakeManager struct {
  108. cert atomic.Value // Always a *tls.Certificate
  109. healthy bool
  110. }
  111. func (f *fakeManager) SetCertificateSigningRequestClient(certificatesclient.CertificateSigningRequestInterface) error {
  112. return nil
  113. }
  114. func (f *fakeManager) ServerHealthy() bool { return f.healthy }
  115. func (f *fakeManager) Start() {}
  116. func (f *fakeManager) Stop() {}
  117. func (f *fakeManager) RotateCerts() (bool, error) { return false, nil }
  118. func (f *fakeManager) Current() *tls.Certificate {
  119. if val := f.cert.Load(); val != nil {
  120. return val.(*tls.Certificate)
  121. }
  122. return nil
  123. }
  124. func (f *fakeManager) setCurrent(cert *tls.Certificate) {
  125. f.cert.Store(cert)
  126. }
  127. func TestRotateShutsDownConnections(t *testing.T) {
  128. // This test fails if you comment out the t.closeAllConns() call in
  129. // transport.go and don't close connections on a rotate.
  130. stop := make(chan struct{})
  131. defer close(stop)
  132. m := new(fakeManager)
  133. m.setCurrent(client1CertData.certificate)
  134. // The last certificate we've seen.
  135. lastSeenLeafCert := new(atomic.Value) // Always *x509.Certificate
  136. lastSerialNumber := func() *big.Int {
  137. if cert := lastSeenLeafCert.Load(); cert != nil {
  138. return cert.(*x509.Certificate).SerialNumber
  139. }
  140. return big.NewInt(0)
  141. }
  142. h := func(w http.ResponseWriter, r *http.Request) {
  143. if r.TLS != nil && len(r.TLS.PeerCertificates) != 0 {
  144. // Record the last TLS certificate the client sent.
  145. lastSeenLeafCert.Store(r.TLS.PeerCertificates[0])
  146. }
  147. w.Write([]byte(`{}`))
  148. }
  149. s := httptest.NewUnstartedServer(http.HandlerFunc(h))
  150. s.TLS = &tls.Config{
  151. // Just request a cert, we don't need to verify it.
  152. ClientAuth: tls.RequestClientCert,
  153. }
  154. s.StartTLS()
  155. defer s.Close()
  156. c := &rest.Config{
  157. Host: s.URL,
  158. TLSClientConfig: rest.TLSClientConfig{
  159. // We don't care about the server's cert.
  160. Insecure: true,
  161. },
  162. ContentConfig: rest.ContentConfig{
  163. // This is a hack. We don't actually care about the serializer.
  164. NegotiatedSerializer: serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{}),
  165. },
  166. }
  167. // Check for a new cert every 10 milliseconds
  168. if _, err := updateTransport(stop, 10*time.Millisecond, c, m, 0); err != nil {
  169. t.Fatal(err)
  170. }
  171. client, err := rest.UnversionedRESTClientFor(c)
  172. if err != nil {
  173. t.Fatal(err)
  174. }
  175. if err := client.Get().Do(context.TODO()).Error(); err != nil {
  176. t.Fatal(err)
  177. }
  178. firstCertSerial := lastSerialNumber()
  179. // Change the manager's certificate. This should cause the client to shut down
  180. // its connections to the server.
  181. m.setCurrent(client2CertData.certificate)
  182. for i := 0; i < 5; i++ {
  183. time.Sleep(time.Millisecond * 10)
  184. client.Get().Do(context.TODO())
  185. if firstCertSerial.Cmp(lastSerialNumber()) != 0 {
  186. // The certificate changed!
  187. return
  188. }
  189. }
  190. t.Errorf("certificate rotated but client never reconnected with new cert")
  191. }