...

Source file src/k8s.io/client-go/util/certificate/certificate_manager_test.go

Documentation: k8s.io/client-go/util/certificate

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

View as plain text