k8s.io/kubernetes@v1.29.3/pkg/kubelet/certificate/transport_test.go (about)

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