k8s.io/client-go@v0.31.1/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 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 }