k8s.io/client-go@v0.22.2/util/certificate/certificate_manager_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  	"bytes"
    21  	"crypto/tls"
    22  	"crypto/x509"
    23  	"crypto/x509/pkix"
    24  	"fmt"
    25  	"net"
    26  	"strings"
    27  	"testing"
    28  	"time"
    29  
    30  	certificatesv1 "k8s.io/api/certificates/v1"
    31  	certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
    32  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    33  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    34  	"k8s.io/apimachinery/pkg/runtime"
    35  	"k8s.io/apimachinery/pkg/runtime/schema"
    36  	watch "k8s.io/apimachinery/pkg/watch"
    37  	clientset "k8s.io/client-go/kubernetes"
    38  	"k8s.io/client-go/kubernetes/fake"
    39  	certificatesclient "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
    40  	clienttesting "k8s.io/client-go/testing"
    41  )
    42  
    43  var storeCertData = newCertificateData(`-----BEGIN CERTIFICATE-----
    44  MIICRzCCAfGgAwIBAgIJALMb7ecMIk3MMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
    45  BAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNVBAcMBkxvbmRvbjEYMBYGA1UE
    46  CgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1JVCBEZXBhcnRtZW50MRswGQYD
    47  VQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTAwIBcNMTcwNDI2MjMyNjUyWhgPMjExNzA0
    48  MDIyMzI2NTJaMH4xCzAJBgNVBAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNV
    49  BAcMBkxvbmRvbjEYMBYGA1UECgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1J
    50  VCBEZXBhcnRtZW50MRswGQYDVQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTAwXDANBgkq
    51  hkiG9w0BAQEFAANLADBIAkEAtBMa7NWpv3BVlKTCPGO/LEsguKqWHBtKzweMY2CV
    52  tAL1rQm913huhxF9w+ai76KQ3MHK5IVnLJjYYA5MzP2H5QIDAQABo1AwTjAdBgNV
    53  HQ4EFgQU22iy8aWkNSxv0nBxFxerfsvnZVMwHwYDVR0jBBgwFoAU22iy8aWkNSxv
    54  0nBxFxerfsvnZVMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAANBAEOefGbV
    55  NcHxklaW06w6OBYJPwpIhCVozC1qdxGX1dg8VkEKzjOzjgqVD30m59OFmSlBmHsl
    56  nkVA6wyOSDYBf3o=
    57  -----END CERTIFICATE-----`, `-----BEGIN RSA PRIVATE KEY-----
    58  MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAtBMa7NWpv3BVlKTC
    59  PGO/LEsguKqWHBtKzweMY2CVtAL1rQm913huhxF9w+ai76KQ3MHK5IVnLJjYYA5M
    60  zP2H5QIDAQABAkAS9BfXab3OKpK3bIgNNyp+DQJKrZnTJ4Q+OjsqkpXvNltPJosf
    61  G8GsiKu/vAt4HGqI3eU77NvRI+mL4MnHRmXBAiEA3qM4FAtKSRBbcJzPxxLEUSwg
    62  XSCcosCktbkXvpYrS30CIQDPDxgqlwDEJQ0uKuHkZI38/SPWWqfUmkecwlbpXABK
    63  iQIgZX08DA8VfvcA5/Xj1Zjdey9FVY6POLXen6RPiabE97UCICp6eUW7ht+2jjar
    64  e35EltCRCjoejRHTuN9TC0uCoVipAiAXaJIx/Q47vGwiw6Y8KXsNU6y54gTbOSxX
    65  54LzHNk/+Q==
    66  -----END RSA PRIVATE KEY-----`)
    67  var storeTwoCertsData = newCertificateData(`-----BEGIN CERTIFICATE-----
    68  MIIDfTCCAyegAwIBAgIUFBl4gUoqZDP/wUJDn37/VJ9upD0wDQYJKoZIhvcNAQEF
    69  BQAwfjELMAkGA1UEBhMCR0IxDzANBgNVBAgMBkxvbmRvbjEPMA0GA1UEBwwGTG9u
    70  ZG9uMRgwFgYDVQQKDA9HbG9iYWwgU2VjdXJpdHkxFjAUBgNVBAsMDUlUIERlcGFy
    71  dG1lbnQxGzAZBgNVBAMMEnRlc3QtY2VydGlmaWNhdGUtMDAeFw0yMDAzMDIxOTM3
    72  MDBaFw0yMTAzMDIxOTM3MDBaMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
    73  aWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEdMBsGA1UEChMURXhhbXBs
    74  ZSBDb21wYW55LCBMTEMxEzARBgNVBAsTCk9wZXJhdGlvbnMxGDAWBgNVBAMTD3d3
    75  dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMiR
    76  DNpmwTICFr+P16fKDVjbNCzSjWq+MTu8vAfS6GrLpBTUEe+6zVqxUza/fZenxo8O
    77  ucV2JTUv5J4nkT/vG6Qm/mToVJ4vQzLQ5jR2w7v/7cf3oWCwTAKUafgo6/Ga95gn
    78  lQB3+Fd8sy96zfFr/7wDSMPPueR5kSFax+cEd30wwv5O7tWj0ro1mrxLssBlwPaR
    79  ZlzkkvxBYTzWCqKZsWktQlXciqlFSos0ua7uvwqKN5CTxfC/xoyMxx9kfZm7BzPN
    80  ZDqYMFw2HiWdEiLzI4jj+Gh0D5t47tnvlpUMihcX9x0jP6/+hnfcQ8GAP2jR/BXY
    81  5YZRRY70LiCXPevlRAECAwEAAaOBqTCBpjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0l
    82  BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYE
    83  FOoiE+kh7gGDpyx0KZuCc1lrlTRKMB8GA1UdIwQYMBaAFNtosvGlpDUsb9JwcRcX
    84  q37L52VTMCcGA1UdEQQgMB6CC2V4YW1wbGUuY29tgg93d3cuZXhhbXBsZS5jb20w
    85  DQYJKoZIhvcNAQEFBQADQQAw6mxQONAD2sivfzIf1eDFd6LU7aE+MnkdlEQjjPCi
    86  tlUITFIuO3XavISupP6V9wE0b1wTF1pTlVWArf/0YQXs
    87  -----END CERTIFICATE-----
    88  -----BEGIN CERTIFICATE-----
    89  MIICRzCCAfGgAwIBAgIJALMb7ecMIk3MMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
    90  BAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNVBAcMBkxvbmRvbjEYMBYGA1UE
    91  CgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1JVCBEZXBhcnRtZW50MRswGQYD
    92  VQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTAwIBcNMTcwNDI2MjMyNjUyWhgPMjExNzA0
    93  MDIyMzI2NTJaMH4xCzAJBgNVBAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNV
    94  BAcMBkxvbmRvbjEYMBYGA1UECgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1J
    95  VCBEZXBhcnRtZW50MRswGQYDVQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTAwXDANBgkq
    96  hkiG9w0BAQEFAANLADBIAkEAtBMa7NWpv3BVlKTCPGO/LEsguKqWHBtKzweMY2CV
    97  tAL1rQm913huhxF9w+ai76KQ3MHK5IVnLJjYYA5MzP2H5QIDAQABo1AwTjAdBgNV
    98  HQ4EFgQU22iy8aWkNSxv0nBxFxerfsvnZVMwHwYDVR0jBBgwFoAU22iy8aWkNSxv
    99  0nBxFxerfsvnZVMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAANBAEOefGbV
   100  NcHxklaW06w6OBYJPwpIhCVozC1qdxGX1dg8VkEKzjOzjgqVD30m59OFmSlBmHsl
   101  nkVA6wyOSDYBf3o=
   102  -----END CERTIFICATE-----`, `-----BEGIN RSA PRIVATE KEY-----
   103  MIIEowIBAAKCAQEAyJEM2mbBMgIWv4/Xp8oNWNs0LNKNar4xO7y8B9LoasukFNQR
   104  77rNWrFTNr99l6fGjw65xXYlNS/knieRP+8bpCb+ZOhUni9DMtDmNHbDu//tx/eh
   105  YLBMApRp+Cjr8Zr3mCeVAHf4V3yzL3rN8Wv/vANIw8+55HmRIVrH5wR3fTDC/k7u
   106  1aPSujWavEuywGXA9pFmXOSS/EFhPNYKopmxaS1CVdyKqUVKizS5ru6/Coo3kJPF
   107  8L/GjIzHH2R9mbsHM81kOpgwXDYeJZ0SIvMjiOP4aHQPm3ju2e+WlQyKFxf3HSM/
   108  r/6Gd9xDwYA/aNH8FdjlhlFFjvQuIJc96+VEAQIDAQABAoIBAQCc6R3tH8a1oPy7
   109  EYXeNy0J/zRqfK82e2V5HsbcOByssHTF9sOxkatm8KPxiQ5wv0mQUiz0VuH1Imrx
   110  cHMqWZ5+ZiNQPpM0zjT8ZII1OVUYl7knYIxYYJSW0BW3mAw/EMXzu8POgg1AJMbq
   111  tmC4J44DQW6EAtej75ejSKpsCgqRXVoi3iEk9eMLHUFIHqkzl/aKEc7k/P+eKo2h
   112  PHsDoKZdmOmZA3OKzw61xAqJICYyplRHatQcEiWJgnLer+9qvUGc4k8eqAYeDGm7
   113  T78XcUvsXOug2GClVWGZu1quFhf7MxjzFfOjz4q9HwPex7X6nQL0IX2hzMECkaMC
   114  iUMZGGEhAoGBAOLY1KSNOjvt54MkKznI8stHkx8V73c0Nxbz5Rj8gM0Gwk1FWVas
   115  jgoAbKPQ2UL/RglLX1JZvztKvNuWSEeZGqggDvhzB38leiEH+OY7DZ7a0c5sWwdF
   116  CpcT1mJb91ww5xEC09WO8Oq3i5olVBBivOl5EjwKHOQn2TUh2OSLhqf/AoGBAOJX
   117  mxqdTEUwFU9ecsAOK9labjI7mA5so0vIq8eq1Q670NFszChfSMKJAqQ90N1LEu9z
   118  L0f6CBXYCn7sMmOlF4CKE+u2/ieJfD1OkKq7RwEd3pi4X3xtAlcPK8F/QprmQWo0
   119  wi33BDBb4zYkuQB6Q5RYIV2di7k+HBpoQPottBP/AoGAIB4xJUc1qoyJjeDOGfVg
   120  ovV0WB9j8026Sw6nLj16Aw1k70nVV1dBGRtsRllomXrJMMGyMleworV3PePuQezk
   121  gE9hrz2iHxdwTkLxs69Cw24Z7I8c6E+XK0LMxMpeoHfwD1GGKqN9as4n/uAwIc3J
   122  D4lr0oJgCtG1iDdNnTZAD4MCgYAkOpWPCwJ8SJgAnkOLzjjij4D39WX/WRBCPxqP
   123  2R5FP3bLLrj29Vl2GewcUfCumyeqwCsfQDwvEueLLU9bd79tSayqnB3OQklqnrq1
   124  OUjCOv+4Pjq6ddBcEweT70S/+n8Z+tvh85nuC6cwsWwTUX6jrf+ZNnB49CIXb/yG
   125  ju42DQKBgAPtbB/ON3+GtnSTHBSY6HwZvGJrBDicrXmr1U9zuA8yYxv8qaRXZkpn
   126  2cpLLvO2MJutwXMYf+T3x1ZCFMkE56pOswSTGrCQWRl3hOiJayLHQyAOYHPnYeZB
   127  78iRJPUZ0biEQUZQ62GBxWkcB0qkxa9m759h/TvLwvV0RrO5Uzd0
   128  -----END RSA PRIVATE KEY-----`)
   129  var expiredStoreCertData = newCertificateData(`-----BEGIN CERTIFICATE-----
   130  MIIBFzCBwgIJALhygXnxXmN1MA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCGhv
   131  c3QtMTIzMB4XDTE4MTEwNDIzNTc1NFoXDTE4MTEwNTIzNTc1NFowEzERMA8GA1UE
   132  AwwIaG9zdC0xMjMwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAtBMa7NWpv3BVlKTC
   133  PGO/LEsguKqWHBtKzweMY2CVtAL1rQm913huhxF9w+ai76KQ3MHK5IVnLJjYYA5M
   134  zP2H5QIDAQABMA0GCSqGSIb3DQEBCwUAA0EAN2DPFUtCzqnidL+5nh+46Sk6dkMI
   135  T5DD11UuuIjZusKvThsHKVCIsyJ2bDo7cTbI+/nklLRP+FcC2wESFUgXbA==
   136  -----END CERTIFICATE-----`, `-----BEGIN RSA PRIVATE KEY-----
   137  MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAtBMa7NWpv3BVlKTC
   138  PGO/LEsguKqWHBtKzweMY2CVtAL1rQm913huhxF9w+ai76KQ3MHK5IVnLJjYYA5M
   139  zP2H5QIDAQABAkAS9BfXab3OKpK3bIgNNyp+DQJKrZnTJ4Q+OjsqkpXvNltPJosf
   140  G8GsiKu/vAt4HGqI3eU77NvRI+mL4MnHRmXBAiEA3qM4FAtKSRBbcJzPxxLEUSwg
   141  XSCcosCktbkXvpYrS30CIQDPDxgqlwDEJQ0uKuHkZI38/SPWWqfUmkecwlbpXABK
   142  iQIgZX08DA8VfvcA5/Xj1Zjdey9FVY6POLXen6RPiabE97UCICp6eUW7ht+2jjar
   143  e35EltCRCjoejRHTuN9TC0uCoVipAiAXaJIx/Q47vGwiw6Y8KXsNU6y54gTbOSxX
   144  54LzHNk/+Q==
   145  -----END RSA PRIVATE KEY-----`)
   146  var bootstrapCertData = newCertificateData(
   147  	`-----BEGIN CERTIFICATE-----
   148  MIICRzCCAfGgAwIBAgIJANXr+UzRFq4TMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
   149  BAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNVBAcMBkxvbmRvbjEYMBYGA1UE
   150  CgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1JVCBEZXBhcnRtZW50MRswGQYD
   151  VQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTEwIBcNMTcwNDI2MjMyNzMyWhgPMjExNzA0
   152  MDIyMzI3MzJaMH4xCzAJBgNVBAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNV
   153  BAcMBkxvbmRvbjEYMBYGA1UECgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1J
   154  VCBEZXBhcnRtZW50MRswGQYDVQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTEwXDANBgkq
   155  hkiG9w0BAQEFAANLADBIAkEAqvbkN4RShH1rL37JFp4fZPnn0JUhVWWsrP8NOomJ
   156  pXdBDUMGWuEQIsZ1Gf9JrCQLu6ooRyHSKRFpAVbMQ3ABJwIDAQABo1AwTjAdBgNV
   157  HQ4EFgQUEGBc6YYheEZ/5MhwqSUYYPYRj2MwHwYDVR0jBBgwFoAUEGBc6YYheEZ/
   158  5MhwqSUYYPYRj2MwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAANBAIyNmznk
   159  5dgJY52FppEEcfQRdS5k4XFPc22SHPcz77AHf5oWZ1WG9VezOZZPp8NCiFDDlDL8
   160  yma33a5eMyTjLD8=
   161  -----END CERTIFICATE-----`, `-----BEGIN RSA PRIVATE KEY-----
   162  MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqvbkN4RShH1rL37J
   163  Fp4fZPnn0JUhVWWsrP8NOomJpXdBDUMGWuEQIsZ1Gf9JrCQLu6ooRyHSKRFpAVbM
   164  Q3ABJwIDAQABAkBC2OBpGLMPHN8BJijIUDFkURakBvuOoX+/8MYiYk7QxEmfLCk6
   165  L6r+GLNFMfXwXcBmXtMKfZKAIKutKf098JaBAiEA10azfqt3G/5owrNA00plSyT6
   166  ZmHPzY9Uq1p/QTR/uOcCIQDLTkfBkLHm0UKeobbO/fSm6ZflhyBRDINy4FvwmZMt
   167  wQIgYV/tmQJeIh91q3wBepFQOClFykG8CTMoDUol/YyNqUkCIHfp6Rr7fGL3JIMq
   168  QQgf9DCK8SPZqq8DYXjdan0kKBJBAiEAyDb+07o2gpggo8BYUKSaiRCiyXfaq87f
   169  eVqgpBq/QN4=
   170  -----END RSA PRIVATE KEY-----`)
   171  var apiServerCertData = newCertificateData(
   172  	`-----BEGIN CERTIFICATE-----
   173  MIICRzCCAfGgAwIBAgIJAIydTIADd+yqMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
   174  BAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNVBAcMBkxvbmRvbjEYMBYGA1UE
   175  CgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1JVCBEZXBhcnRtZW50MRswGQYD
   176  VQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTIwIBcNMTcwNDI2MjMyNDU4WhgPMjExNzA0
   177  MDIyMzI0NThaMH4xCzAJBgNVBAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNV
   178  BAcMBkxvbmRvbjEYMBYGA1UECgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1J
   179  VCBEZXBhcnRtZW50MRswGQYDVQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTIwXDANBgkq
   180  hkiG9w0BAQEFAANLADBIAkEAuiRet28DV68Dk4A8eqCaqgXmymamUEjW/DxvIQqH
   181  3lbhtm8BwSnS9wUAajSLSWiq3fci2RbRgaSPjUrnbOHCLQIDAQABo1AwTjAdBgNV
   182  HQ4EFgQU0vhI4OPGEOqT+VAWwxdhVvcmgdIwHwYDVR0jBBgwFoAU0vhI4OPGEOqT
   183  +VAWwxdhVvcmgdIwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAANBALNeJGDe
   184  nV5cXbp9W1bC12Tc8nnNXn4ypLE2JTQAvyp51zoZ8hQoSnRVx/VCY55Yu+br8gQZ
   185  +tW+O/PoE7B3tuY=
   186  -----END CERTIFICATE-----`, `-----BEGIN RSA PRIVATE KEY-----
   187  MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEAuiRet28DV68Dk4A8
   188  eqCaqgXmymamUEjW/DxvIQqH3lbhtm8BwSnS9wUAajSLSWiq3fci2RbRgaSPjUrn
   189  bOHCLQIDAQABAkEArDR1g9IqD3aUImNikDgAngbzqpAokOGyMoxeavzpEaFOgCzi
   190  gi7HF7yHRmZkUt8CzdEvnHSqRjFuaaB0gGA+AQIhAOc8Z1h8ElLRSqaZGgI3jCTp
   191  Izx9HNY//U5NGrXD2+ttAiEAzhOqkqI4+nDab7FpiD7MXI6fO549mEXeVBPvPtsS
   192  OcECIQCIfkpOm+ZBBpO3JXaJynoqK4gGI6ALA/ik6LSUiIlfPQIhAISjd9hlfZME
   193  bDQT1r8Q3Gx+h9LRqQeHgPBQ3F5ylqqBAiBaJ0hkYvrIdWxNlcLqD3065bJpHQ4S
   194  WQkuZUQN1M/Xvg==
   195  -----END RSA PRIVATE KEY-----`)
   196  
   197  type certificateData struct {
   198  	keyPEM         []byte
   199  	certificatePEM []byte
   200  	certificate    *tls.Certificate
   201  }
   202  
   203  func newCertificateData(certificatePEM string, keyPEM string) *certificateData {
   204  	certificate, err := tls.X509KeyPair([]byte(certificatePEM), []byte(keyPEM))
   205  	if err != nil {
   206  		panic(fmt.Sprintf("Unable to initialize certificate: %v", err))
   207  	}
   208  	certs, err := x509.ParseCertificates(certificate.Certificate[0])
   209  	if err != nil {
   210  		panic(fmt.Sprintf("Unable to initialize certificate leaf: %v", err))
   211  	}
   212  	certificate.Leaf = certs[0]
   213  	return &certificateData{
   214  		keyPEM:         []byte(keyPEM),
   215  		certificatePEM: []byte(certificatePEM),
   216  		certificate:    &certificate,
   217  	}
   218  }
   219  
   220  func TestNewManagerNoRotation(t *testing.T) {
   221  	store := &fakeStore{
   222  		cert: storeCertData.certificate,
   223  	}
   224  	if _, err := NewManager(&Config{
   225  		Template:         &x509.CertificateRequest{},
   226  		Usages:           []certificatesv1.KeyUsage{},
   227  		CertificateStore: store,
   228  	}); err != nil {
   229  		t.Fatalf("Failed to initialize the certificate manager: %v", err)
   230  	}
   231  }
   232  
   233  type metricMock struct {
   234  	calls     int
   235  	lastValue float64
   236  }
   237  
   238  func (g *metricMock) Set(v float64) {
   239  	g.calls++
   240  	g.lastValue = v
   241  }
   242  
   243  func (g *metricMock) Observe(v float64) {
   244  	g.calls++
   245  	g.lastValue = v
   246  }
   247  
   248  func TestSetRotationDeadline(t *testing.T) {
   249  	defer func(original func(float64) time.Duration) { jitteryDuration = original }(jitteryDuration)
   250  
   251  	now := time.Now()
   252  	testCases := []struct {
   253  		name         string
   254  		notBefore    time.Time
   255  		notAfter     time.Time
   256  		shouldRotate bool
   257  	}{
   258  		{"just issued, still good", now.Add(-1 * time.Hour), now.Add(99 * time.Hour), false},
   259  		{"half way expired, still good", now.Add(-24 * time.Hour), now.Add(24 * time.Hour), false},
   260  		{"mostly expired, still good", now.Add(-69 * time.Hour), now.Add(31 * time.Hour), false},
   261  		{"just about expired, should rotate", now.Add(-91 * time.Hour), now.Add(9 * time.Hour), true},
   262  		{"nearly expired, should rotate", now.Add(-99 * time.Hour), now.Add(1 * time.Hour), true},
   263  		{"already expired, should rotate", now.Add(-10 * time.Hour), now.Add(-1 * time.Hour), true},
   264  		{"long duration", now.Add(-6 * 30 * 24 * time.Hour), now.Add(6 * 30 * 24 * time.Hour), true},
   265  		{"short duration", now.Add(-30 * time.Second), now.Add(30 * time.Second), true},
   266  	}
   267  
   268  	for _, tc := range testCases {
   269  		t.Run(tc.name, func(t *testing.T) {
   270  			m := manager{
   271  				cert: &tls.Certificate{
   272  					Leaf: &x509.Certificate{
   273  						NotBefore: tc.notBefore,
   274  						NotAfter:  tc.notAfter,
   275  					},
   276  				},
   277  				getTemplate: func() *x509.CertificateRequest { return &x509.CertificateRequest{} },
   278  				usages:      []certificatesv1.KeyUsage{},
   279  				now:         func() time.Time { return now },
   280  				logf:        t.Logf,
   281  			}
   282  			jitteryDuration = func(float64) time.Duration { return time.Duration(float64(tc.notAfter.Sub(tc.notBefore)) * 0.7) }
   283  			lowerBound := tc.notBefore.Add(time.Duration(float64(tc.notAfter.Sub(tc.notBefore)) * 0.7))
   284  
   285  			deadline := m.nextRotationDeadline()
   286  
   287  			if !deadline.Equal(lowerBound) {
   288  				t.Errorf("For notBefore %v, notAfter %v, the rotationDeadline %v should be %v.",
   289  					tc.notBefore,
   290  					tc.notAfter,
   291  					deadline,
   292  					lowerBound)
   293  			}
   294  		})
   295  	}
   296  }
   297  
   298  func TestCertSatisfiesTemplate(t *testing.T) {
   299  	testCases := []struct {
   300  		name          string
   301  		cert          *x509.Certificate
   302  		template      *x509.CertificateRequest
   303  		shouldSatisfy bool
   304  	}{
   305  		{
   306  			name:          "No certificate, no template",
   307  			cert:          nil,
   308  			template:      nil,
   309  			shouldSatisfy: false,
   310  		},
   311  		{
   312  			name:          "No certificate",
   313  			cert:          nil,
   314  			template:      &x509.CertificateRequest{},
   315  			shouldSatisfy: false,
   316  		},
   317  		{
   318  			name: "No template",
   319  			cert: &x509.Certificate{
   320  				Subject: pkix.Name{
   321  					CommonName: "system:node:fake-node-name",
   322  				},
   323  			},
   324  			template:      nil,
   325  			shouldSatisfy: true,
   326  		},
   327  		{
   328  			name: "Mismatched common name",
   329  			cert: &x509.Certificate{
   330  				Subject: pkix.Name{
   331  					CommonName: "system:node:fake-node-name-2",
   332  				},
   333  			},
   334  			template: &x509.CertificateRequest{
   335  				Subject: pkix.Name{
   336  					CommonName: "system:node:fake-node-name",
   337  				},
   338  			},
   339  			shouldSatisfy: false,
   340  		},
   341  		{
   342  			name: "Missing orgs in certificate",
   343  			cert: &x509.Certificate{
   344  				Subject: pkix.Name{
   345  					Organization: []string{"system:nodes"},
   346  				},
   347  			},
   348  			template: &x509.CertificateRequest{
   349  				Subject: pkix.Name{
   350  					Organization: []string{"system:nodes", "foobar"},
   351  				},
   352  			},
   353  			shouldSatisfy: false,
   354  		},
   355  		{
   356  			name: "Extra orgs in certificate",
   357  			cert: &x509.Certificate{
   358  				Subject: pkix.Name{
   359  					Organization: []string{"system:nodes", "foobar"},
   360  				},
   361  			},
   362  			template: &x509.CertificateRequest{
   363  				Subject: pkix.Name{
   364  					Organization: []string{"system:nodes"},
   365  				},
   366  			},
   367  			shouldSatisfy: true,
   368  		},
   369  		{
   370  			name: "Missing DNS names in certificate",
   371  			cert: &x509.Certificate{
   372  				Subject:  pkix.Name{},
   373  				DNSNames: []string{"foo.example.com"},
   374  			},
   375  			template: &x509.CertificateRequest{
   376  				Subject:  pkix.Name{},
   377  				DNSNames: []string{"foo.example.com", "bar.example.com"},
   378  			},
   379  			shouldSatisfy: false,
   380  		},
   381  		{
   382  			name: "Extra DNS names in certificate",
   383  			cert: &x509.Certificate{
   384  				Subject:  pkix.Name{},
   385  				DNSNames: []string{"foo.example.com", "bar.example.com"},
   386  			},
   387  			template: &x509.CertificateRequest{
   388  				Subject:  pkix.Name{},
   389  				DNSNames: []string{"foo.example.com"},
   390  			},
   391  			shouldSatisfy: true,
   392  		},
   393  		{
   394  			name: "Missing IP addresses in certificate",
   395  			cert: &x509.Certificate{
   396  				Subject:     pkix.Name{},
   397  				IPAddresses: []net.IP{net.ParseIP("192.168.1.1")},
   398  			},
   399  			template: &x509.CertificateRequest{
   400  				Subject:     pkix.Name{},
   401  				IPAddresses: []net.IP{net.ParseIP("192.168.1.1"), net.ParseIP("192.168.1.2")},
   402  			},
   403  			shouldSatisfy: false,
   404  		},
   405  		{
   406  			name: "Extra IP addresses in certificate",
   407  			cert: &x509.Certificate{
   408  				Subject:     pkix.Name{},
   409  				IPAddresses: []net.IP{net.ParseIP("192.168.1.1"), net.ParseIP("192.168.1.2")},
   410  			},
   411  			template: &x509.CertificateRequest{
   412  				Subject:     pkix.Name{},
   413  				IPAddresses: []net.IP{net.ParseIP("192.168.1.1")},
   414  			},
   415  			shouldSatisfy: true,
   416  		},
   417  		{
   418  			name: "Matching certificate",
   419  			cert: &x509.Certificate{
   420  				Subject: pkix.Name{
   421  					CommonName:   "system:node:fake-node-name",
   422  					Organization: []string{"system:nodes"},
   423  				},
   424  				DNSNames:    []string{"foo.example.com"},
   425  				IPAddresses: []net.IP{net.ParseIP("192.168.1.1")},
   426  			},
   427  			template: &x509.CertificateRequest{
   428  				Subject: pkix.Name{
   429  					CommonName:   "system:node:fake-node-name",
   430  					Organization: []string{"system:nodes"},
   431  				},
   432  				DNSNames:    []string{"foo.example.com"},
   433  				IPAddresses: []net.IP{net.ParseIP("192.168.1.1")},
   434  			},
   435  			shouldSatisfy: true,
   436  		},
   437  	}
   438  
   439  	for _, tc := range testCases {
   440  		t.Run(tc.name, func(t *testing.T) {
   441  			var tlsCert *tls.Certificate
   442  
   443  			if tc.cert != nil {
   444  				tlsCert = &tls.Certificate{
   445  					Leaf: tc.cert,
   446  				}
   447  			}
   448  
   449  			m := manager{
   450  				cert:        tlsCert,
   451  				getTemplate: func() *x509.CertificateRequest { return tc.template },
   452  				now:         time.Now,
   453  				logf:        t.Logf,
   454  			}
   455  
   456  			result := m.certSatisfiesTemplate()
   457  			if result != tc.shouldSatisfy {
   458  				t.Errorf("cert: %+v, template: %+v, certSatisfiesTemplate returned %v, want %v", m.cert, tc.template, result, tc.shouldSatisfy)
   459  			}
   460  		})
   461  	}
   462  }
   463  
   464  func TestRotateCertCreateCSRError(t *testing.T) {
   465  	now := time.Now()
   466  	m := manager{
   467  		cert: &tls.Certificate{
   468  			Leaf: &x509.Certificate{
   469  				NotBefore: now.Add(-2 * time.Hour),
   470  				NotAfter:  now.Add(-1 * time.Hour),
   471  			},
   472  		},
   473  		getTemplate: func() *x509.CertificateRequest { return &x509.CertificateRequest{} },
   474  		usages:      []certificatesv1.KeyUsage{},
   475  		clientsetFn: func(_ *tls.Certificate) (clientset.Interface, error) {
   476  			return newClientset(fakeClient{failureType: createError}), nil
   477  		},
   478  		now:  func() time.Time { return now },
   479  		logf: t.Logf,
   480  	}
   481  
   482  	if success, err := m.rotateCerts(); success {
   483  		t.Errorf("Got success from 'rotateCerts', wanted failure")
   484  	} else if err != nil {
   485  		t.Errorf("Got error %v from 'rotateCerts', wanted no error.", err)
   486  	}
   487  }
   488  
   489  func TestRotateCertWaitingForResultError(t *testing.T) {
   490  	now := time.Now()
   491  	m := manager{
   492  		cert: &tls.Certificate{
   493  			Leaf: &x509.Certificate{
   494  				NotBefore: now.Add(-2 * time.Hour),
   495  				NotAfter:  now.Add(-1 * time.Hour),
   496  			},
   497  		},
   498  		getTemplate: func() *x509.CertificateRequest { return &x509.CertificateRequest{} },
   499  		usages:      []certificatesv1.KeyUsage{},
   500  		clientsetFn: func(_ *tls.Certificate) (clientset.Interface, error) {
   501  			return newClientset(fakeClient{failureType: watchError}), nil
   502  		},
   503  		now:  func() time.Time { return now },
   504  		logf: t.Logf,
   505  	}
   506  
   507  	defer func(t time.Duration) { certificateWaitTimeout = t }(certificateWaitTimeout)
   508  	certificateWaitTimeout = 1 * time.Millisecond
   509  	if success, err := m.rotateCerts(); success {
   510  		t.Errorf("Got success from 'rotateCerts', wanted failure.")
   511  	} else if err != nil {
   512  		t.Errorf("Got error %v from 'rotateCerts', wanted no error.", err)
   513  	}
   514  }
   515  
   516  func TestNewManagerBootstrap(t *testing.T) {
   517  	store := &fakeStore{}
   518  
   519  	var cm Manager
   520  	cm, err := NewManager(&Config{
   521  		Template:                &x509.CertificateRequest{},
   522  		Usages:                  []certificatesv1.KeyUsage{},
   523  		CertificateStore:        store,
   524  		BootstrapCertificatePEM: bootstrapCertData.certificatePEM,
   525  		BootstrapKeyPEM:         bootstrapCertData.keyPEM,
   526  	})
   527  	if err != nil {
   528  		t.Fatalf("Failed to initialize the certificate manager: %v", err)
   529  	}
   530  
   531  	cert := cm.Current()
   532  
   533  	if cert == nil {
   534  		t.Errorf("Certificate was nil, expected something.")
   535  	}
   536  	if m, ok := cm.(*manager); !ok {
   537  		t.Errorf("Expected a '*manager' from 'NewManager'")
   538  	} else if !m.forceRotation {
   539  		t.Errorf("Expected rotation should happen during bootstrap, but it won't.")
   540  	}
   541  }
   542  
   543  func TestNewManagerNoBootstrap(t *testing.T) {
   544  	now := time.Now()
   545  	cert, err := tls.X509KeyPair(storeCertData.certificatePEM, storeCertData.keyPEM)
   546  	if err != nil {
   547  		t.Fatalf("Unable to initialize a certificate: %v", err)
   548  	}
   549  	cert.Leaf = &x509.Certificate{
   550  		NotBefore: now.Add(-24 * time.Hour),
   551  		NotAfter:  now.Add(24 * time.Hour),
   552  	}
   553  	store := &fakeStore{
   554  		cert: &cert,
   555  	}
   556  
   557  	cm, err := NewManager(&Config{
   558  		Template:                &x509.CertificateRequest{},
   559  		Usages:                  []certificatesv1.KeyUsage{},
   560  		CertificateStore:        store,
   561  		BootstrapCertificatePEM: bootstrapCertData.certificatePEM,
   562  		BootstrapKeyPEM:         bootstrapCertData.keyPEM,
   563  	})
   564  
   565  	if err != nil {
   566  		t.Fatalf("Failed to initialize the certificate manager: %v", err)
   567  	}
   568  
   569  	currentCert := cm.Current()
   570  
   571  	if currentCert == nil {
   572  		t.Errorf("Certificate was nil, expected something.")
   573  	}
   574  	if m, ok := cm.(*manager); !ok {
   575  		t.Errorf("Expected a '*manager' from 'NewManager'")
   576  	} else {
   577  		if m.forceRotation {
   578  			t.Errorf("Expected rotation should not happen during bootstrap, but it won't.")
   579  		}
   580  	}
   581  }
   582  
   583  func TestGetCurrentCertificateOrBootstrap(t *testing.T) {
   584  	testCases := []struct {
   585  		description          string
   586  		storeCert            *tls.Certificate
   587  		bootstrapCertData    []byte
   588  		bootstrapKeyData     []byte
   589  		expectedCert         *tls.Certificate
   590  		expectedShouldRotate bool
   591  		expectedErrMsg       string
   592  	}{
   593  		{
   594  			"return cert from store",
   595  			storeCertData.certificate,
   596  			nil,
   597  			nil,
   598  			storeCertData.certificate,
   599  			false,
   600  			"",
   601  		},
   602  		{
   603  			"no cert in store and no bootstrap cert",
   604  			nil,
   605  			nil,
   606  			nil,
   607  			nil,
   608  			true,
   609  			"",
   610  		},
   611  	}
   612  
   613  	for _, tc := range testCases {
   614  		t.Run(tc.description, func(t *testing.T) {
   615  			store := &fakeStore{
   616  				cert: tc.storeCert,
   617  			}
   618  
   619  			certResult, shouldRotate, err := getCurrentCertificateOrBootstrap(
   620  				store,
   621  				tc.bootstrapCertData,
   622  				tc.bootstrapKeyData)
   623  			if certResult == nil || certResult.Certificate == nil || tc.expectedCert == nil {
   624  				if certResult != nil && tc.expectedCert != nil {
   625  					t.Errorf("Got certificate %v, wanted %v", certResult, tc.expectedCert)
   626  				}
   627  			} else {
   628  				if !certificatesEqual(certResult, tc.expectedCert) {
   629  					t.Errorf("Got certificate %v, wanted %v", certResult, tc.expectedCert)
   630  				}
   631  			}
   632  			if shouldRotate != tc.expectedShouldRotate {
   633  				t.Errorf("Got shouldRotate %t, wanted %t", shouldRotate, tc.expectedShouldRotate)
   634  			}
   635  			if err == nil {
   636  				if tc.expectedErrMsg != "" {
   637  					t.Errorf("Got err %v, wanted %q", err, tc.expectedErrMsg)
   638  				}
   639  			} else {
   640  				if tc.expectedErrMsg == "" || !strings.Contains(err.Error(), tc.expectedErrMsg) {
   641  					t.Errorf("Got err %v, wanted %q", err, tc.expectedErrMsg)
   642  				}
   643  			}
   644  		})
   645  	}
   646  }
   647  
   648  func TestInitializeCertificateSigningRequestClient(t *testing.T) {
   649  	var nilCertificate = &certificateData{}
   650  	testCases := []struct {
   651  		description             string
   652  		storeCert               *certificateData
   653  		bootstrapCert           *certificateData
   654  		apiCert                 *certificateData
   655  		noV1                    bool
   656  		noV1beta1               bool
   657  		expectedCertBeforeStart *certificateData
   658  		expectedCertAfterStart  *certificateData
   659  	}{
   660  		{
   661  			description:             "No current certificate, no bootstrap certificate",
   662  			storeCert:               nilCertificate,
   663  			bootstrapCert:           nilCertificate,
   664  			apiCert:                 apiServerCertData,
   665  			expectedCertBeforeStart: nilCertificate,
   666  			expectedCertAfterStart:  apiServerCertData,
   667  		},
   668  		{
   669  			description:             "No current certificate, no bootstrap certificate, no v1 API",
   670  			storeCert:               nilCertificate,
   671  			bootstrapCert:           nilCertificate,
   672  			apiCert:                 apiServerCertData,
   673  			expectedCertBeforeStart: nilCertificate,
   674  			expectedCertAfterStart:  apiServerCertData,
   675  			noV1:                    true,
   676  		},
   677  		{
   678  			description:             "No current certificate, no bootstrap certificate, no v1beta1 API",
   679  			storeCert:               nilCertificate,
   680  			bootstrapCert:           nilCertificate,
   681  			apiCert:                 apiServerCertData,
   682  			expectedCertBeforeStart: nilCertificate,
   683  			expectedCertAfterStart:  apiServerCertData,
   684  			noV1beta1:               true,
   685  		},
   686  		{
   687  			description:             "No current certificate, bootstrap certificate",
   688  			storeCert:               nilCertificate,
   689  			bootstrapCert:           bootstrapCertData,
   690  			apiCert:                 apiServerCertData,
   691  			expectedCertBeforeStart: bootstrapCertData,
   692  			expectedCertAfterStart:  apiServerCertData,
   693  		},
   694  		{
   695  			description:             "Current certificate, no bootstrap certificate",
   696  			storeCert:               storeCertData,
   697  			bootstrapCert:           nilCertificate,
   698  			apiCert:                 apiServerCertData,
   699  			expectedCertBeforeStart: storeCertData,
   700  			expectedCertAfterStart:  storeCertData,
   701  		},
   702  		{
   703  			description:             "Current certificate, bootstrap certificate",
   704  			storeCert:               storeCertData,
   705  			bootstrapCert:           bootstrapCertData,
   706  			apiCert:                 apiServerCertData,
   707  			expectedCertBeforeStart: storeCertData,
   708  			expectedCertAfterStart:  storeCertData,
   709  		},
   710  		{
   711  			description:             "Current certificate expired, no bootstrap certificate",
   712  			storeCert:               expiredStoreCertData,
   713  			bootstrapCert:           nilCertificate,
   714  			apiCert:                 apiServerCertData,
   715  			expectedCertBeforeStart: nil,
   716  			expectedCertAfterStart:  apiServerCertData,
   717  		},
   718  	}
   719  
   720  	for _, tc := range testCases {
   721  		t.Run(tc.description, func(t *testing.T) {
   722  			certificateStore := &fakeStore{
   723  				cert: tc.storeCert.certificate,
   724  			}
   725  
   726  			certificateManager, err := NewManager(&Config{
   727  				Template: &x509.CertificateRequest{
   728  					Subject: pkix.Name{
   729  						Organization: []string{"system:nodes"},
   730  						CommonName:   "system:node:fake-node-name",
   731  					},
   732  				},
   733  				SignerName: certificatesv1.KubeAPIServerClientSignerName,
   734  				Usages: []certificatesv1.KeyUsage{
   735  					certificatesv1.UsageDigitalSignature,
   736  					certificatesv1.UsageKeyEncipherment,
   737  					certificatesv1.UsageClientAuth,
   738  				},
   739  				CertificateStore:        certificateStore,
   740  				BootstrapCertificatePEM: tc.bootstrapCert.certificatePEM,
   741  				BootstrapKeyPEM:         tc.bootstrapCert.keyPEM,
   742  				ClientsetFn: func(_ *tls.Certificate) (clientset.Interface, error) {
   743  					return newClientset(fakeClient{
   744  						noV1:           tc.noV1,
   745  						noV1beta1:      tc.noV1beta1,
   746  						certificatePEM: tc.apiCert.certificatePEM,
   747  					}), nil
   748  				},
   749  			})
   750  			if err != nil {
   751  				t.Errorf("Got %v, wanted no error.", err)
   752  			}
   753  
   754  			certificate := certificateManager.Current()
   755  			if tc.expectedCertBeforeStart == nil {
   756  				if certificate != nil {
   757  					t.Errorf("Expected certificate to be nil, was %s", certificate.Leaf.NotAfter)
   758  				}
   759  			} else {
   760  				if !certificatesEqual(certificate, tc.expectedCertBeforeStart.certificate) {
   761  					t.Errorf("Got %v, wanted %v", certificateString(certificate), certificateString(tc.expectedCertBeforeStart.certificate))
   762  				}
   763  			}
   764  
   765  			if m, ok := certificateManager.(*manager); !ok {
   766  				t.Errorf("Expected a '*manager' from 'NewManager'")
   767  			} else {
   768  				if m.forceRotation {
   769  					if success, err := m.rotateCerts(); !success {
   770  						t.Errorf("Got failure from 'rotateCerts', wanted success.")
   771  					} else if err != nil {
   772  						t.Errorf("Got error %v, expected none.", err)
   773  					}
   774  				}
   775  			}
   776  
   777  			certificate = certificateManager.Current()
   778  			if tc.expectedCertAfterStart == nil {
   779  				if certificate != nil {
   780  					t.Errorf("Expected certificate to be nil, was %s", certificate.Leaf.NotAfter)
   781  				}
   782  				return
   783  			}
   784  			if !certificatesEqual(certificate, tc.expectedCertAfterStart.certificate) {
   785  				t.Errorf("Got %v, wanted %v", certificateString(certificate), certificateString(tc.expectedCertAfterStart.certificate))
   786  			}
   787  		})
   788  	}
   789  }
   790  
   791  func TestInitializeOtherRESTClients(t *testing.T) {
   792  	var nilCertificate = &certificateData{}
   793  	testCases := []struct {
   794  		description             string
   795  		storeCert               *certificateData
   796  		bootstrapCert           *certificateData
   797  		apiCert                 *certificateData
   798  		expectedCertBeforeStart *certificateData
   799  		expectedCertAfterStart  *certificateData
   800  	}{
   801  		{
   802  			description:             "No current certificate, no bootstrap certificate",
   803  			storeCert:               nilCertificate,
   804  			bootstrapCert:           nilCertificate,
   805  			apiCert:                 apiServerCertData,
   806  			expectedCertBeforeStart: nilCertificate,
   807  			expectedCertAfterStart:  apiServerCertData,
   808  		},
   809  		{
   810  			description:             "No current certificate, bootstrap certificate",
   811  			storeCert:               nilCertificate,
   812  			bootstrapCert:           bootstrapCertData,
   813  			apiCert:                 apiServerCertData,
   814  			expectedCertBeforeStart: bootstrapCertData,
   815  			expectedCertAfterStart:  apiServerCertData,
   816  		},
   817  		{
   818  			description:             "Current certificate, no bootstrap certificate",
   819  			storeCert:               storeCertData,
   820  			bootstrapCert:           nilCertificate,
   821  			apiCert:                 apiServerCertData,
   822  			expectedCertBeforeStart: storeCertData,
   823  			expectedCertAfterStart:  storeCertData,
   824  		},
   825  		{
   826  			description:             "Current certificate, bootstrap certificate",
   827  			storeCert:               storeCertData,
   828  			bootstrapCert:           bootstrapCertData,
   829  			apiCert:                 apiServerCertData,
   830  			expectedCertBeforeStart: storeCertData,
   831  			expectedCertAfterStart:  storeCertData,
   832  		},
   833  	}
   834  
   835  	for _, tc := range testCases {
   836  		t.Run(tc.description, func(t *testing.T) {
   837  			certificateStore := &fakeStore{
   838  				cert: tc.storeCert.certificate,
   839  			}
   840  
   841  			certificateManager, err := NewManager(&Config{
   842  				Template: &x509.CertificateRequest{
   843  					Subject: pkix.Name{
   844  						Organization: []string{"system:nodes"},
   845  						CommonName:   "system:node:fake-node-name",
   846  					},
   847  				},
   848  				Usages: []certificatesv1.KeyUsage{
   849  					certificatesv1.UsageDigitalSignature,
   850  					certificatesv1.UsageKeyEncipherment,
   851  					certificatesv1.UsageClientAuth,
   852  				},
   853  				CertificateStore:        certificateStore,
   854  				BootstrapCertificatePEM: tc.bootstrapCert.certificatePEM,
   855  				BootstrapKeyPEM:         tc.bootstrapCert.keyPEM,
   856  				ClientsetFn: func(_ *tls.Certificate) (clientset.Interface, error) {
   857  					return newClientset(fakeClient{
   858  						certificatePEM: tc.apiCert.certificatePEM,
   859  					}), nil
   860  				},
   861  			})
   862  			if err != nil {
   863  				t.Errorf("Got %v, wanted no error.", err)
   864  			}
   865  
   866  			certificate := certificateManager.Current()
   867  			if !certificatesEqual(certificate, tc.expectedCertBeforeStart.certificate) {
   868  				t.Errorf("Got %v, wanted %v", certificateString(certificate), certificateString(tc.expectedCertBeforeStart.certificate))
   869  			}
   870  
   871  			if m, ok := certificateManager.(*manager); !ok {
   872  				t.Errorf("Expected a '*manager' from 'NewManager'")
   873  			} else {
   874  				if m.forceRotation {
   875  					success, err := certificateManager.(*manager).rotateCerts()
   876  					if err != nil {
   877  						t.Errorf("Got error %v, expected none.", err)
   878  						return
   879  					}
   880  					if !success {
   881  						t.Errorf("Unexpected response 'rotateCerts': %t", success)
   882  						return
   883  					}
   884  				}
   885  			}
   886  
   887  			certificate = certificateManager.Current()
   888  			if !certificatesEqual(certificate, tc.expectedCertAfterStart.certificate) {
   889  				t.Errorf("Got %v, wanted %v", certificateString(certificate), certificateString(tc.expectedCertAfterStart.certificate))
   890  			}
   891  		})
   892  	}
   893  }
   894  
   895  func TestServerHealth(t *testing.T) {
   896  	type certs struct {
   897  		storeCert               *certificateData
   898  		bootstrapCert           *certificateData
   899  		apiCert                 *certificateData
   900  		expectedCertBeforeStart *certificateData
   901  		expectedCertAfterStart  *certificateData
   902  	}
   903  
   904  	updatedCerts := certs{
   905  		storeCert:               storeCertData,
   906  		bootstrapCert:           bootstrapCertData,
   907  		apiCert:                 apiServerCertData,
   908  		expectedCertBeforeStart: storeCertData,
   909  		expectedCertAfterStart:  apiServerCertData,
   910  	}
   911  
   912  	currentCerts := certs{
   913  		storeCert:               storeCertData,
   914  		bootstrapCert:           bootstrapCertData,
   915  		apiCert:                 apiServerCertData,
   916  		expectedCertBeforeStart: storeCertData,
   917  		expectedCertAfterStart:  storeCertData,
   918  	}
   919  
   920  	testCases := []struct {
   921  		description string
   922  		certs
   923  
   924  		failureType fakeClientFailureType
   925  		clientErr   error
   926  
   927  		expectRotateFail bool
   928  		expectHealthy    bool
   929  	}{
   930  		{
   931  			description:   "Current certificate, bootstrap certificate",
   932  			certs:         updatedCerts,
   933  			expectHealthy: true,
   934  		},
   935  		{
   936  			description: "Generic error on create",
   937  			certs:       currentCerts,
   938  
   939  			failureType:      createError,
   940  			expectRotateFail: true,
   941  		},
   942  		{
   943  			description: "Unauthorized error on create",
   944  			certs:       currentCerts,
   945  
   946  			failureType:      createError,
   947  			clientErr:        apierrors.NewUnauthorized("unauthorized"),
   948  			expectRotateFail: true,
   949  			expectHealthy:    true,
   950  		},
   951  		{
   952  			description: "Generic unauthorized error on create",
   953  			certs:       currentCerts,
   954  
   955  			failureType:      createError,
   956  			clientErr:        apierrors.NewGenericServerResponse(401, "POST", schema.GroupResource{}, "", "", 0, true),
   957  			expectRotateFail: true,
   958  			expectHealthy:    true,
   959  		},
   960  		{
   961  			description: "Generic not found error on create",
   962  			certs:       currentCerts,
   963  
   964  			failureType:      createError,
   965  			clientErr:        apierrors.NewGenericServerResponse(404, "POST", schema.GroupResource{}, "", "", 0, true),
   966  			expectRotateFail: true,
   967  			expectHealthy:    false,
   968  		},
   969  		{
   970  			description: "Not found error on create",
   971  			certs:       currentCerts,
   972  
   973  			failureType:      createError,
   974  			clientErr:        apierrors.NewGenericServerResponse(404, "POST", schema.GroupResource{}, "", "", 0, false),
   975  			expectRotateFail: true,
   976  			expectHealthy:    true,
   977  		},
   978  	}
   979  
   980  	for _, tc := range testCases {
   981  		t.Run(tc.description, func(t *testing.T) {
   982  			certificateStore := &fakeStore{
   983  				cert: tc.storeCert.certificate,
   984  			}
   985  
   986  			certificateManager, err := NewManager(&Config{
   987  				Template: &x509.CertificateRequest{
   988  					Subject: pkix.Name{
   989  						Organization: []string{"system:nodes"},
   990  						CommonName:   "system:node:fake-node-name",
   991  					},
   992  				},
   993  				Usages: []certificatesv1.KeyUsage{
   994  					certificatesv1.UsageDigitalSignature,
   995  					certificatesv1.UsageKeyEncipherment,
   996  					certificatesv1.UsageClientAuth,
   997  				},
   998  				CertificateStore:        certificateStore,
   999  				BootstrapCertificatePEM: tc.bootstrapCert.certificatePEM,
  1000  				BootstrapKeyPEM:         tc.bootstrapCert.keyPEM,
  1001  				ClientsetFn: func(_ *tls.Certificate) (clientset.Interface, error) {
  1002  					return newClientset(fakeClient{
  1003  						certificatePEM: tc.apiCert.certificatePEM,
  1004  						failureType:    tc.failureType,
  1005  						err:            tc.clientErr,
  1006  					}), nil
  1007  				},
  1008  			})
  1009  			if err != nil {
  1010  				t.Errorf("Got %v, wanted no error.", err)
  1011  			}
  1012  
  1013  			certificate := certificateManager.Current()
  1014  			if !certificatesEqual(certificate, tc.expectedCertBeforeStart.certificate) {
  1015  				t.Errorf("Got %v, wanted %v", certificateString(certificate), certificateString(tc.expectedCertBeforeStart.certificate))
  1016  			}
  1017  
  1018  			if _, ok := certificateManager.(*manager); !ok {
  1019  				t.Errorf("Expected a '*manager' from 'NewManager'")
  1020  			} else {
  1021  				success, err := certificateManager.(*manager).rotateCerts()
  1022  				if err != nil {
  1023  					t.Errorf("Got error %v, expected none.", err)
  1024  					return
  1025  				}
  1026  				if !success != tc.expectRotateFail {
  1027  					t.Errorf("Unexpected response 'rotateCerts': %t", success)
  1028  					return
  1029  				}
  1030  				if actual := certificateManager.(*manager).ServerHealthy(); actual != tc.expectHealthy {
  1031  					t.Errorf("Unexpected manager server health: %t", actual)
  1032  				}
  1033  			}
  1034  
  1035  			certificate = certificateManager.Current()
  1036  			if !certificatesEqual(certificate, tc.expectedCertAfterStart.certificate) {
  1037  				t.Errorf("Got %v, wanted %v", certificateString(certificate), certificateString(tc.expectedCertAfterStart.certificate))
  1038  			}
  1039  		})
  1040  	}
  1041  }
  1042  
  1043  func TestRotationLogsDuration(t *testing.T) {
  1044  	h := metricMock{}
  1045  	now := time.Now()
  1046  	certIss := now.Add(-2 * time.Hour)
  1047  	m := manager{
  1048  		cert: &tls.Certificate{
  1049  			Leaf: &x509.Certificate{
  1050  				NotBefore: certIss,
  1051  				NotAfter:  now.Add(-1 * time.Hour),
  1052  			},
  1053  		},
  1054  		certStore:   &fakeStore{cert: expiredStoreCertData.certificate},
  1055  		getTemplate: func() *x509.CertificateRequest { return &x509.CertificateRequest{} },
  1056  		clientsetFn: func(_ *tls.Certificate) (clientset.Interface, error) {
  1057  			return newClientset(fakeClient{
  1058  				certificatePEM: apiServerCertData.certificatePEM,
  1059  			}), nil
  1060  		},
  1061  		certificateRotation: &h,
  1062  		now:                 func() time.Time { return now },
  1063  		logf:                t.Logf,
  1064  	}
  1065  	ok, err := m.rotateCerts()
  1066  	if err != nil || !ok {
  1067  		t.Errorf("failed to rotate certs: %v", err)
  1068  	}
  1069  	if h.calls != 1 {
  1070  		t.Errorf("rotation metric was not called")
  1071  	}
  1072  	if h.lastValue != now.Sub(certIss).Seconds() {
  1073  		t.Errorf("rotation metric did not record the right value got: %f; want %f", h.lastValue, now.Sub(certIss).Seconds())
  1074  	}
  1075  
  1076  }
  1077  
  1078  type fakeClientFailureType int
  1079  
  1080  const (
  1081  	none fakeClientFailureType = iota
  1082  	createError
  1083  	watchError
  1084  	certificateSigningRequestDenied
  1085  )
  1086  
  1087  type fakeClient struct {
  1088  	noV1      bool
  1089  	noV1beta1 bool
  1090  	certificatesclient.CertificateSigningRequestInterface
  1091  	failureType    fakeClientFailureType
  1092  	certificatePEM []byte
  1093  	err            error
  1094  }
  1095  
  1096  func newClientset(opts fakeClient) *fake.Clientset {
  1097  	f := fake.NewSimpleClientset()
  1098  	switch opts.failureType {
  1099  	case createError:
  1100  		f.PrependReactor("create", "certificatesigningrequests", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
  1101  			if opts.err != nil {
  1102  				return true, nil, opts.err
  1103  			}
  1104  			return true, nil, fmt.Errorf("create error")
  1105  		})
  1106  	case watchError:
  1107  		f.PrependReactor("list", "certificatesigningrequests", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
  1108  			if opts.err != nil {
  1109  				return true, nil, opts.err
  1110  			}
  1111  			return true, nil, fmt.Errorf("watch error")
  1112  		})
  1113  		f.PrependWatchReactor("certificatesigningrequests", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
  1114  			if opts.err != nil {
  1115  				return true, nil, opts.err
  1116  			}
  1117  			return true, nil, fmt.Errorf("watch error")
  1118  		})
  1119  	default:
  1120  		f.PrependReactor("create", "certificatesigningrequests", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
  1121  			switch action.GetResource().Version {
  1122  			case "v1":
  1123  				if opts.noV1 {
  1124  					return true, nil, apierrors.NewNotFound(certificatesv1.Resource("certificatesigningrequests"), "")
  1125  				}
  1126  				return true, &certificatesv1.CertificateSigningRequest{ObjectMeta: metav1.ObjectMeta{UID: "fake-uid"}}, nil
  1127  			case "v1beta1":
  1128  				if opts.noV1beta1 {
  1129  					return true, nil, apierrors.NewNotFound(certificatesv1.Resource("certificatesigningrequests"), "")
  1130  				}
  1131  				return true, &certificatesv1beta1.CertificateSigningRequest{ObjectMeta: metav1.ObjectMeta{UID: "fake-uid"}}, nil
  1132  			default:
  1133  				return false, nil, nil
  1134  			}
  1135  		})
  1136  		f.PrependReactor("list", "certificatesigningrequests", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
  1137  			switch action.GetResource().Version {
  1138  			case "v1":
  1139  				if opts.noV1 {
  1140  					return true, nil, apierrors.NewNotFound(certificatesv1.Resource("certificatesigningrequests"), "")
  1141  				}
  1142  				return true, &certificatesv1.CertificateSigningRequestList{Items: []certificatesv1.CertificateSigningRequest{{ObjectMeta: metav1.ObjectMeta{UID: "fake-uid"}}}}, nil
  1143  			case "v1beta1":
  1144  				if opts.noV1beta1 {
  1145  					return true, nil, apierrors.NewNotFound(certificatesv1.Resource("certificatesigningrequests"), "")
  1146  				}
  1147  				return true, &certificatesv1beta1.CertificateSigningRequestList{Items: []certificatesv1beta1.CertificateSigningRequest{{ObjectMeta: metav1.ObjectMeta{UID: "fake-uid"}}}}, nil
  1148  			default:
  1149  				return false, nil, nil
  1150  			}
  1151  		})
  1152  		f.PrependWatchReactor("certificatesigningrequests", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
  1153  			switch action.GetResource().Version {
  1154  			case "v1":
  1155  				if opts.noV1 {
  1156  					return true, nil, apierrors.NewNotFound(certificatesv1.Resource("certificatesigningrequests"), "")
  1157  				}
  1158  				return true, &fakeWatch{
  1159  					version:        action.GetResource().Version,
  1160  					failureType:    opts.failureType,
  1161  					certificatePEM: opts.certificatePEM,
  1162  				}, nil
  1163  
  1164  			case "v1beta1":
  1165  				if opts.noV1beta1 {
  1166  					return true, nil, apierrors.NewNotFound(certificatesv1.Resource("certificatesigningrequests"), "")
  1167  				}
  1168  				return true, &fakeWatch{
  1169  					version:        action.GetResource().Version,
  1170  					failureType:    opts.failureType,
  1171  					certificatePEM: opts.certificatePEM,
  1172  				}, nil
  1173  			default:
  1174  				return false, nil, nil
  1175  			}
  1176  		})
  1177  	}
  1178  	return f
  1179  }
  1180  
  1181  type fakeWatch struct {
  1182  	version        string
  1183  	failureType    fakeClientFailureType
  1184  	certificatePEM []byte
  1185  }
  1186  
  1187  func (w *fakeWatch) Stop() {
  1188  }
  1189  
  1190  func (w *fakeWatch) ResultChan() <-chan watch.Event {
  1191  	var csr runtime.Object
  1192  
  1193  	switch w.version {
  1194  	case "v1":
  1195  		var condition certificatesv1.CertificateSigningRequestCondition
  1196  		if w.failureType == certificateSigningRequestDenied {
  1197  			condition = certificatesv1.CertificateSigningRequestCondition{
  1198  				Type: certificatesv1.CertificateDenied,
  1199  			}
  1200  		} else {
  1201  			condition = certificatesv1.CertificateSigningRequestCondition{
  1202  				Type: certificatesv1.CertificateApproved,
  1203  			}
  1204  		}
  1205  
  1206  		csr = &certificatesv1.CertificateSigningRequest{
  1207  			ObjectMeta: metav1.ObjectMeta{UID: "fake-uid"},
  1208  			Status: certificatesv1.CertificateSigningRequestStatus{
  1209  				Conditions: []certificatesv1.CertificateSigningRequestCondition{
  1210  					condition,
  1211  				},
  1212  				Certificate: []byte(w.certificatePEM),
  1213  			},
  1214  		}
  1215  
  1216  	case "v1beta1":
  1217  		var condition certificatesv1beta1.CertificateSigningRequestCondition
  1218  		if w.failureType == certificateSigningRequestDenied {
  1219  			condition = certificatesv1beta1.CertificateSigningRequestCondition{
  1220  				Type: certificatesv1beta1.CertificateDenied,
  1221  			}
  1222  		} else {
  1223  			condition = certificatesv1beta1.CertificateSigningRequestCondition{
  1224  				Type: certificatesv1beta1.CertificateApproved,
  1225  			}
  1226  		}
  1227  
  1228  		csr = &certificatesv1beta1.CertificateSigningRequest{
  1229  			ObjectMeta: metav1.ObjectMeta{UID: "fake-uid"},
  1230  			Status: certificatesv1beta1.CertificateSigningRequestStatus{
  1231  				Conditions: []certificatesv1beta1.CertificateSigningRequestCondition{
  1232  					condition,
  1233  				},
  1234  				Certificate: []byte(w.certificatePEM),
  1235  			},
  1236  		}
  1237  	}
  1238  
  1239  	c := make(chan watch.Event, 1)
  1240  	c <- watch.Event{
  1241  		Type:   watch.Added,
  1242  		Object: csr,
  1243  	}
  1244  	return c
  1245  }
  1246  
  1247  type fakeStore struct {
  1248  	cert *tls.Certificate
  1249  }
  1250  
  1251  func (s *fakeStore) Current() (*tls.Certificate, error) {
  1252  	if s.cert == nil {
  1253  		noKeyErr := NoCertKeyError("")
  1254  		return nil, &noKeyErr
  1255  	}
  1256  	return s.cert, nil
  1257  }
  1258  
  1259  // Accepts the PEM data for the cert/key pair and makes the new cert/key
  1260  // pair the 'current' pair, that will be returned by future calls to
  1261  // Current().
  1262  func (s *fakeStore) Update(certPEM, keyPEM []byte) (*tls.Certificate, error) {
  1263  	// In order to make the mocking work, whenever a cert/key pair is passed in
  1264  	// to be updated in the mock store, assume that the certificate manager
  1265  	// generated the key, and then asked the mock CertificateSigningRequest API
  1266  	// to sign it, then the faked API returned a canned response. The canned
  1267  	// signing response will not match the generated key. In order to make
  1268  	// things work out, search here for the correct matching key and use that
  1269  	// instead of the passed in key. That way this file of test code doesn't
  1270  	// have to implement an actual certificate signing process.
  1271  	for _, tc := range []*certificateData{storeCertData, bootstrapCertData, apiServerCertData} {
  1272  		if bytes.Equal(tc.certificatePEM, certPEM) {
  1273  			keyPEM = tc.keyPEM
  1274  		}
  1275  	}
  1276  	cert, err := tls.X509KeyPair(certPEM, keyPEM)
  1277  	if err != nil {
  1278  		return nil, err
  1279  	}
  1280  	now := time.Now()
  1281  	s.cert = &cert
  1282  	s.cert.Leaf = &x509.Certificate{
  1283  		NotBefore: now.Add(-24 * time.Hour),
  1284  		NotAfter:  now.Add(24 * time.Hour),
  1285  	}
  1286  	return s.cert, nil
  1287  }
  1288  
  1289  func certificatesEqual(c1 *tls.Certificate, c2 *tls.Certificate) bool {
  1290  	if c1 == nil || c2 == nil {
  1291  		return c1 == c2
  1292  	}
  1293  	if len(c1.Certificate) != len(c2.Certificate) {
  1294  		return false
  1295  	}
  1296  	for i := 0; i < len(c1.Certificate); i++ {
  1297  		if !bytes.Equal(c1.Certificate[i], c2.Certificate[i]) {
  1298  			return false
  1299  		}
  1300  	}
  1301  	return true
  1302  }
  1303  
  1304  func certificateString(c *tls.Certificate) string {
  1305  	if c == nil {
  1306  		return "certificate == nil"
  1307  	}
  1308  	if c.Leaf == nil {
  1309  		return "certificate.Leaf == nil"
  1310  	}
  1311  	return c.Leaf.Subject.CommonName
  1312  }