1/*
2Copyright 2017 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package certificate
18
19import (
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	"k8s.io/apimachinery/pkg/api/errors"
33	apierrors "k8s.io/apimachinery/pkg/api/errors"
34	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
35	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
36	"k8s.io/apimachinery/pkg/runtime"
37	"k8s.io/apimachinery/pkg/runtime/schema"
38	watch "k8s.io/apimachinery/pkg/watch"
39	clientset "k8s.io/client-go/kubernetes"
40	"k8s.io/client-go/kubernetes/fake"
41	certificatesclient "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
42	clienttesting "k8s.io/client-go/testing"
43)
44
45var storeCertData = newCertificateData(`-----BEGIN CERTIFICATE-----
46MIICRzCCAfGgAwIBAgIJALMb7ecMIk3MMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
47BAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNVBAcMBkxvbmRvbjEYMBYGA1UE
48CgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1JVCBEZXBhcnRtZW50MRswGQYD
49VQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTAwIBcNMTcwNDI2MjMyNjUyWhgPMjExNzA0
50MDIyMzI2NTJaMH4xCzAJBgNVBAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNV
51BAcMBkxvbmRvbjEYMBYGA1UECgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1J
52VCBEZXBhcnRtZW50MRswGQYDVQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTAwXDANBgkq
53hkiG9w0BAQEFAANLADBIAkEAtBMa7NWpv3BVlKTCPGO/LEsguKqWHBtKzweMY2CV
54tAL1rQm913huhxF9w+ai76KQ3MHK5IVnLJjYYA5MzP2H5QIDAQABo1AwTjAdBgNV
55HQ4EFgQU22iy8aWkNSxv0nBxFxerfsvnZVMwHwYDVR0jBBgwFoAU22iy8aWkNSxv
560nBxFxerfsvnZVMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAANBAEOefGbV
57NcHxklaW06w6OBYJPwpIhCVozC1qdxGX1dg8VkEKzjOzjgqVD30m59OFmSlBmHsl
58nkVA6wyOSDYBf3o=
59-----END CERTIFICATE-----`, `-----BEGIN RSA PRIVATE KEY-----
60MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAtBMa7NWpv3BVlKTC
61PGO/LEsguKqWHBtKzweMY2CVtAL1rQm913huhxF9w+ai76KQ3MHK5IVnLJjYYA5M
62zP2H5QIDAQABAkAS9BfXab3OKpK3bIgNNyp+DQJKrZnTJ4Q+OjsqkpXvNltPJosf
63G8GsiKu/vAt4HGqI3eU77NvRI+mL4MnHRmXBAiEA3qM4FAtKSRBbcJzPxxLEUSwg
64XSCcosCktbkXvpYrS30CIQDPDxgqlwDEJQ0uKuHkZI38/SPWWqfUmkecwlbpXABK
65iQIgZX08DA8VfvcA5/Xj1Zjdey9FVY6POLXen6RPiabE97UCICp6eUW7ht+2jjar
66e35EltCRCjoejRHTuN9TC0uCoVipAiAXaJIx/Q47vGwiw6Y8KXsNU6y54gTbOSxX
6754LzHNk/+Q==
68-----END RSA PRIVATE KEY-----`)
69var storeTwoCertsData = newCertificateData(`-----BEGIN CERTIFICATE-----
70MIIDfTCCAyegAwIBAgIUFBl4gUoqZDP/wUJDn37/VJ9upD0wDQYJKoZIhvcNAQEF
71BQAwfjELMAkGA1UEBhMCR0IxDzANBgNVBAgMBkxvbmRvbjEPMA0GA1UEBwwGTG9u
72ZG9uMRgwFgYDVQQKDA9HbG9iYWwgU2VjdXJpdHkxFjAUBgNVBAsMDUlUIERlcGFy
73dG1lbnQxGzAZBgNVBAMMEnRlc3QtY2VydGlmaWNhdGUtMDAeFw0yMDAzMDIxOTM3
74MDBaFw0yMTAzMDIxOTM3MDBaMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
75aWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEdMBsGA1UEChMURXhhbXBs
76ZSBDb21wYW55LCBMTEMxEzARBgNVBAsTCk9wZXJhdGlvbnMxGDAWBgNVBAMTD3d3
77dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMiR
78DNpmwTICFr+P16fKDVjbNCzSjWq+MTu8vAfS6GrLpBTUEe+6zVqxUza/fZenxo8O
79ucV2JTUv5J4nkT/vG6Qm/mToVJ4vQzLQ5jR2w7v/7cf3oWCwTAKUafgo6/Ga95gn
80lQB3+Fd8sy96zfFr/7wDSMPPueR5kSFax+cEd30wwv5O7tWj0ro1mrxLssBlwPaR
81ZlzkkvxBYTzWCqKZsWktQlXciqlFSos0ua7uvwqKN5CTxfC/xoyMxx9kfZm7BzPN
82ZDqYMFw2HiWdEiLzI4jj+Gh0D5t47tnvlpUMihcX9x0jP6/+hnfcQ8GAP2jR/BXY
835YZRRY70LiCXPevlRAECAwEAAaOBqTCBpjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0l
84BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYE
85FOoiE+kh7gGDpyx0KZuCc1lrlTRKMB8GA1UdIwQYMBaAFNtosvGlpDUsb9JwcRcX
86q37L52VTMCcGA1UdEQQgMB6CC2V4YW1wbGUuY29tgg93d3cuZXhhbXBsZS5jb20w
87DQYJKoZIhvcNAQEFBQADQQAw6mxQONAD2sivfzIf1eDFd6LU7aE+MnkdlEQjjPCi
88tlUITFIuO3XavISupP6V9wE0b1wTF1pTlVWArf/0YQXs
89-----END CERTIFICATE-----
90-----BEGIN CERTIFICATE-----
91MIICRzCCAfGgAwIBAgIJALMb7ecMIk3MMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
92BAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNVBAcMBkxvbmRvbjEYMBYGA1UE
93CgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1JVCBEZXBhcnRtZW50MRswGQYD
94VQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTAwIBcNMTcwNDI2MjMyNjUyWhgPMjExNzA0
95MDIyMzI2NTJaMH4xCzAJBgNVBAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNV
96BAcMBkxvbmRvbjEYMBYGA1UECgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1J
97VCBEZXBhcnRtZW50MRswGQYDVQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTAwXDANBgkq
98hkiG9w0BAQEFAANLADBIAkEAtBMa7NWpv3BVlKTCPGO/LEsguKqWHBtKzweMY2CV
99tAL1rQm913huhxF9w+ai76KQ3MHK5IVnLJjYYA5MzP2H5QIDAQABo1AwTjAdBgNV
100HQ4EFgQU22iy8aWkNSxv0nBxFxerfsvnZVMwHwYDVR0jBBgwFoAU22iy8aWkNSxv
1010nBxFxerfsvnZVMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAANBAEOefGbV
102NcHxklaW06w6OBYJPwpIhCVozC1qdxGX1dg8VkEKzjOzjgqVD30m59OFmSlBmHsl
103nkVA6wyOSDYBf3o=
104-----END CERTIFICATE-----`, `-----BEGIN RSA PRIVATE KEY-----
105MIIEowIBAAKCAQEAyJEM2mbBMgIWv4/Xp8oNWNs0LNKNar4xO7y8B9LoasukFNQR
10677rNWrFTNr99l6fGjw65xXYlNS/knieRP+8bpCb+ZOhUni9DMtDmNHbDu//tx/eh
107YLBMApRp+Cjr8Zr3mCeVAHf4V3yzL3rN8Wv/vANIw8+55HmRIVrH5wR3fTDC/k7u
1081aPSujWavEuywGXA9pFmXOSS/EFhPNYKopmxaS1CVdyKqUVKizS5ru6/Coo3kJPF
1098L/GjIzHH2R9mbsHM81kOpgwXDYeJZ0SIvMjiOP4aHQPm3ju2e+WlQyKFxf3HSM/
110r/6Gd9xDwYA/aNH8FdjlhlFFjvQuIJc96+VEAQIDAQABAoIBAQCc6R3tH8a1oPy7
111EYXeNy0J/zRqfK82e2V5HsbcOByssHTF9sOxkatm8KPxiQ5wv0mQUiz0VuH1Imrx
112cHMqWZ5+ZiNQPpM0zjT8ZII1OVUYl7knYIxYYJSW0BW3mAw/EMXzu8POgg1AJMbq
113tmC4J44DQW6EAtej75ejSKpsCgqRXVoi3iEk9eMLHUFIHqkzl/aKEc7k/P+eKo2h
114PHsDoKZdmOmZA3OKzw61xAqJICYyplRHatQcEiWJgnLer+9qvUGc4k8eqAYeDGm7
115T78XcUvsXOug2GClVWGZu1quFhf7MxjzFfOjz4q9HwPex7X6nQL0IX2hzMECkaMC
116iUMZGGEhAoGBAOLY1KSNOjvt54MkKznI8stHkx8V73c0Nxbz5Rj8gM0Gwk1FWVas
117jgoAbKPQ2UL/RglLX1JZvztKvNuWSEeZGqggDvhzB38leiEH+OY7DZ7a0c5sWwdF
118CpcT1mJb91ww5xEC09WO8Oq3i5olVBBivOl5EjwKHOQn2TUh2OSLhqf/AoGBAOJX
119mxqdTEUwFU9ecsAOK9labjI7mA5so0vIq8eq1Q670NFszChfSMKJAqQ90N1LEu9z
120L0f6CBXYCn7sMmOlF4CKE+u2/ieJfD1OkKq7RwEd3pi4X3xtAlcPK8F/QprmQWo0
121wi33BDBb4zYkuQB6Q5RYIV2di7k+HBpoQPottBP/AoGAIB4xJUc1qoyJjeDOGfVg
122ovV0WB9j8026Sw6nLj16Aw1k70nVV1dBGRtsRllomXrJMMGyMleworV3PePuQezk
123gE9hrz2iHxdwTkLxs69Cw24Z7I8c6E+XK0LMxMpeoHfwD1GGKqN9as4n/uAwIc3J
124D4lr0oJgCtG1iDdNnTZAD4MCgYAkOpWPCwJ8SJgAnkOLzjjij4D39WX/WRBCPxqP
1252R5FP3bLLrj29Vl2GewcUfCumyeqwCsfQDwvEueLLU9bd79tSayqnB3OQklqnrq1
126OUjCOv+4Pjq6ddBcEweT70S/+n8Z+tvh85nuC6cwsWwTUX6jrf+ZNnB49CIXb/yG
127ju42DQKBgAPtbB/ON3+GtnSTHBSY6HwZvGJrBDicrXmr1U9zuA8yYxv8qaRXZkpn
1282cpLLvO2MJutwXMYf+T3x1ZCFMkE56pOswSTGrCQWRl3hOiJayLHQyAOYHPnYeZB
12978iRJPUZ0biEQUZQ62GBxWkcB0qkxa9m759h/TvLwvV0RrO5Uzd0
130-----END RSA PRIVATE KEY-----`)
131var expiredStoreCertData = newCertificateData(`-----BEGIN CERTIFICATE-----
132MIIBFzCBwgIJALhygXnxXmN1MA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMMCGhv
133c3QtMTIzMB4XDTE4MTEwNDIzNTc1NFoXDTE4MTEwNTIzNTc1NFowEzERMA8GA1UE
134AwwIaG9zdC0xMjMwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAtBMa7NWpv3BVlKTC
135PGO/LEsguKqWHBtKzweMY2CVtAL1rQm913huhxF9w+ai76KQ3MHK5IVnLJjYYA5M
136zP2H5QIDAQABMA0GCSqGSIb3DQEBCwUAA0EAN2DPFUtCzqnidL+5nh+46Sk6dkMI
137T5DD11UuuIjZusKvThsHKVCIsyJ2bDo7cTbI+/nklLRP+FcC2wESFUgXbA==
138-----END CERTIFICATE-----`, `-----BEGIN RSA PRIVATE KEY-----
139MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAtBMa7NWpv3BVlKTC
140PGO/LEsguKqWHBtKzweMY2CVtAL1rQm913huhxF9w+ai76KQ3MHK5IVnLJjYYA5M
141zP2H5QIDAQABAkAS9BfXab3OKpK3bIgNNyp+DQJKrZnTJ4Q+OjsqkpXvNltPJosf
142G8GsiKu/vAt4HGqI3eU77NvRI+mL4MnHRmXBAiEA3qM4FAtKSRBbcJzPxxLEUSwg
143XSCcosCktbkXvpYrS30CIQDPDxgqlwDEJQ0uKuHkZI38/SPWWqfUmkecwlbpXABK
144iQIgZX08DA8VfvcA5/Xj1Zjdey9FVY6POLXen6RPiabE97UCICp6eUW7ht+2jjar
145e35EltCRCjoejRHTuN9TC0uCoVipAiAXaJIx/Q47vGwiw6Y8KXsNU6y54gTbOSxX
14654LzHNk/+Q==
147-----END RSA PRIVATE KEY-----`)
148var bootstrapCertData = newCertificateData(
149	`-----BEGIN CERTIFICATE-----
150MIICRzCCAfGgAwIBAgIJANXr+UzRFq4TMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
151BAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNVBAcMBkxvbmRvbjEYMBYGA1UE
152CgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1JVCBEZXBhcnRtZW50MRswGQYD
153VQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTEwIBcNMTcwNDI2MjMyNzMyWhgPMjExNzA0
154MDIyMzI3MzJaMH4xCzAJBgNVBAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNV
155BAcMBkxvbmRvbjEYMBYGA1UECgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1J
156VCBEZXBhcnRtZW50MRswGQYDVQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTEwXDANBgkq
157hkiG9w0BAQEFAANLADBIAkEAqvbkN4RShH1rL37JFp4fZPnn0JUhVWWsrP8NOomJ
158pXdBDUMGWuEQIsZ1Gf9JrCQLu6ooRyHSKRFpAVbMQ3ABJwIDAQABo1AwTjAdBgNV
159HQ4EFgQUEGBc6YYheEZ/5MhwqSUYYPYRj2MwHwYDVR0jBBgwFoAUEGBc6YYheEZ/
1605MhwqSUYYPYRj2MwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAANBAIyNmznk
1615dgJY52FppEEcfQRdS5k4XFPc22SHPcz77AHf5oWZ1WG9VezOZZPp8NCiFDDlDL8
162yma33a5eMyTjLD8=
163-----END CERTIFICATE-----`, `-----BEGIN RSA PRIVATE KEY-----
164MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqvbkN4RShH1rL37J
165Fp4fZPnn0JUhVWWsrP8NOomJpXdBDUMGWuEQIsZ1Gf9JrCQLu6ooRyHSKRFpAVbM
166Q3ABJwIDAQABAkBC2OBpGLMPHN8BJijIUDFkURakBvuOoX+/8MYiYk7QxEmfLCk6
167L6r+GLNFMfXwXcBmXtMKfZKAIKutKf098JaBAiEA10azfqt3G/5owrNA00plSyT6
168ZmHPzY9Uq1p/QTR/uOcCIQDLTkfBkLHm0UKeobbO/fSm6ZflhyBRDINy4FvwmZMt
169wQIgYV/tmQJeIh91q3wBepFQOClFykG8CTMoDUol/YyNqUkCIHfp6Rr7fGL3JIMq
170QQgf9DCK8SPZqq8DYXjdan0kKBJBAiEAyDb+07o2gpggo8BYUKSaiRCiyXfaq87f
171eVqgpBq/QN4=
172-----END RSA PRIVATE KEY-----`)
173var apiServerCertData = newCertificateData(
174	`-----BEGIN CERTIFICATE-----
175MIICRzCCAfGgAwIBAgIJAIydTIADd+yqMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
176BAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNVBAcMBkxvbmRvbjEYMBYGA1UE
177CgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1JVCBEZXBhcnRtZW50MRswGQYD
178VQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTIwIBcNMTcwNDI2MjMyNDU4WhgPMjExNzA0
179MDIyMzI0NThaMH4xCzAJBgNVBAYTAkdCMQ8wDQYDVQQIDAZMb25kb24xDzANBgNV
180BAcMBkxvbmRvbjEYMBYGA1UECgwPR2xvYmFsIFNlY3VyaXR5MRYwFAYDVQQLDA1J
181VCBEZXBhcnRtZW50MRswGQYDVQQDDBJ0ZXN0LWNlcnRpZmljYXRlLTIwXDANBgkq
182hkiG9w0BAQEFAANLADBIAkEAuiRet28DV68Dk4A8eqCaqgXmymamUEjW/DxvIQqH
1833lbhtm8BwSnS9wUAajSLSWiq3fci2RbRgaSPjUrnbOHCLQIDAQABo1AwTjAdBgNV
184HQ4EFgQU0vhI4OPGEOqT+VAWwxdhVvcmgdIwHwYDVR0jBBgwFoAU0vhI4OPGEOqT
185+VAWwxdhVvcmgdIwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAANBALNeJGDe
186nV5cXbp9W1bC12Tc8nnNXn4ypLE2JTQAvyp51zoZ8hQoSnRVx/VCY55Yu+br8gQZ
187+tW+O/PoE7B3tuY=
188-----END CERTIFICATE-----`, `-----BEGIN RSA PRIVATE KEY-----
189MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEAuiRet28DV68Dk4A8
190eqCaqgXmymamUEjW/DxvIQqH3lbhtm8BwSnS9wUAajSLSWiq3fci2RbRgaSPjUrn
191bOHCLQIDAQABAkEArDR1g9IqD3aUImNikDgAngbzqpAokOGyMoxeavzpEaFOgCzi
192gi7HF7yHRmZkUt8CzdEvnHSqRjFuaaB0gGA+AQIhAOc8Z1h8ElLRSqaZGgI3jCTp
193Izx9HNY//U5NGrXD2+ttAiEAzhOqkqI4+nDab7FpiD7MXI6fO549mEXeVBPvPtsS
194OcECIQCIfkpOm+ZBBpO3JXaJynoqK4gGI6ALA/ik6LSUiIlfPQIhAISjd9hlfZME
195bDQT1r8Q3Gx+h9LRqQeHgPBQ3F5ylqqBAiBaJ0hkYvrIdWxNlcLqD3065bJpHQ4S
196WQkuZUQN1M/Xvg==
197-----END RSA PRIVATE KEY-----`)
198
199type certificateData struct {
200	keyPEM         []byte
201	certificatePEM []byte
202	certificate    *tls.Certificate
203}
204
205func newCertificateData(certificatePEM string, keyPEM string) *certificateData {
206	certificate, err := tls.X509KeyPair([]byte(certificatePEM), []byte(keyPEM))
207	if err != nil {
208		panic(fmt.Sprintf("Unable to initialize certificate: %v", err))
209	}
210	certs, err := x509.ParseCertificates(certificate.Certificate[0])
211	if err != nil {
212		panic(fmt.Sprintf("Unable to initialize certificate leaf: %v", err))
213	}
214	certificate.Leaf = certs[0]
215	return &certificateData{
216		keyPEM:         []byte(keyPEM),
217		certificatePEM: []byte(certificatePEM),
218		certificate:    &certificate,
219	}
220}
221
222func TestNewManagerNoRotation(t *testing.T) {
223	store := &fakeStore{
224		cert: storeCertData.certificate,
225	}
226	if _, err := NewManager(&Config{
227		Template:         &x509.CertificateRequest{},
228		Usages:           []certificatesv1.KeyUsage{},
229		CertificateStore: store,
230	}); err != nil {
231		t.Fatalf("Failed to initialize the certificate manager: %v", err)
232	}
233}
234
235type metricMock struct {
236	calls     int
237	lastValue float64
238}
239
240func (g *metricMock) Set(v float64) {
241	g.calls++
242	g.lastValue = v
243}
244
245func (g *metricMock) Observe(v float64) {
246	g.calls++
247	g.lastValue = v
248}
249
250func TestSetRotationDeadline(t *testing.T) {
251	defer func(original func(float64) time.Duration) { jitteryDuration = original }(jitteryDuration)
252
253	now := time.Now()
254	testCases := []struct {
255		name         string
256		notBefore    time.Time
257		notAfter     time.Time
258		shouldRotate bool
259	}{
260		{"just issued, still good", now.Add(-1 * time.Hour), now.Add(99 * time.Hour), false},
261		{"half way expired, still good", now.Add(-24 * time.Hour), now.Add(24 * time.Hour), false},
262		{"mostly expired, still good", now.Add(-69 * time.Hour), now.Add(31 * time.Hour), false},
263		{"just about expired, should rotate", now.Add(-91 * time.Hour), now.Add(9 * time.Hour), true},
264		{"nearly expired, should rotate", now.Add(-99 * time.Hour), now.Add(1 * time.Hour), true},
265		{"already expired, should rotate", now.Add(-10 * time.Hour), now.Add(-1 * time.Hour), true},
266		{"long duration", now.Add(-6 * 30 * 24 * time.Hour), now.Add(6 * 30 * 24 * time.Hour), true},
267		{"short duration", now.Add(-30 * time.Second), now.Add(30 * time.Second), true},
268	}
269
270	for _, tc := range testCases {
271		t.Run(tc.name, func(t *testing.T) {
272			m := manager{
273				cert: &tls.Certificate{
274					Leaf: &x509.Certificate{
275						NotBefore: tc.notBefore,
276						NotAfter:  tc.notAfter,
277					},
278				},
279				getTemplate: func() *x509.CertificateRequest { return &x509.CertificateRequest{} },
280				usages:      []certificatesv1.KeyUsage{},
281				now:         func() time.Time { return now },
282			}
283			jitteryDuration = func(float64) time.Duration { return time.Duration(float64(tc.notAfter.Sub(tc.notBefore)) * 0.7) }
284			lowerBound := tc.notBefore.Add(time.Duration(float64(tc.notAfter.Sub(tc.notBefore)) * 0.7))
285
286			deadline := m.nextRotationDeadline()
287
288			if !deadline.Equal(lowerBound) {
289				t.Errorf("For notBefore %v, notAfter %v, the rotationDeadline %v should be %v.",
290					tc.notBefore,
291					tc.notAfter,
292					deadline,
293					lowerBound)
294			}
295		})
296	}
297}
298
299func TestCertSatisfiesTemplate(t *testing.T) {
300	testCases := []struct {
301		name          string
302		cert          *x509.Certificate
303		template      *x509.CertificateRequest
304		shouldSatisfy bool
305	}{
306		{
307			name:          "No certificate, no template",
308			cert:          nil,
309			template:      nil,
310			shouldSatisfy: false,
311		},
312		{
313			name:          "No certificate",
314			cert:          nil,
315			template:      &x509.CertificateRequest{},
316			shouldSatisfy: false,
317		},
318		{
319			name: "No template",
320			cert: &x509.Certificate{
321				Subject: pkix.Name{
322					CommonName: "system:node:fake-node-name",
323				},
324			},
325			template:      nil,
326			shouldSatisfy: true,
327		},
328		{
329			name: "Mismatched common name",
330			cert: &x509.Certificate{
331				Subject: pkix.Name{
332					CommonName: "system:node:fake-node-name-2",
333				},
334			},
335			template: &x509.CertificateRequest{
336				Subject: pkix.Name{
337					CommonName: "system:node:fake-node-name",
338				},
339			},
340			shouldSatisfy: false,
341		},
342		{
343			name: "Missing orgs in certificate",
344			cert: &x509.Certificate{
345				Subject: pkix.Name{
346					Organization: []string{"system:nodes"},
347				},
348			},
349			template: &x509.CertificateRequest{
350				Subject: pkix.Name{
351					Organization: []string{"system:nodes", "foobar"},
352				},
353			},
354			shouldSatisfy: false,
355		},
356		{
357			name: "Extra orgs in certificate",
358			cert: &x509.Certificate{
359				Subject: pkix.Name{
360					Organization: []string{"system:nodes", "foobar"},
361				},
362			},
363			template: &x509.CertificateRequest{
364				Subject: pkix.Name{
365					Organization: []string{"system:nodes"},
366				},
367			},
368			shouldSatisfy: true,
369		},
370		{
371			name: "Missing DNS names in certificate",
372			cert: &x509.Certificate{
373				Subject:  pkix.Name{},
374				DNSNames: []string{"foo.example.com"},
375			},
376			template: &x509.CertificateRequest{
377				Subject:  pkix.Name{},
378				DNSNames: []string{"foo.example.com", "bar.example.com"},
379			},
380			shouldSatisfy: false,
381		},
382		{
383			name: "Extra DNS names in certificate",
384			cert: &x509.Certificate{
385				Subject:  pkix.Name{},
386				DNSNames: []string{"foo.example.com", "bar.example.com"},
387			},
388			template: &x509.CertificateRequest{
389				Subject:  pkix.Name{},
390				DNSNames: []string{"foo.example.com"},
391			},
392			shouldSatisfy: true,
393		},
394		{
395			name: "Missing IP addresses in certificate",
396			cert: &x509.Certificate{
397				Subject:     pkix.Name{},
398				IPAddresses: []net.IP{net.ParseIP("192.168.1.1")},
399			},
400			template: &x509.CertificateRequest{
401				Subject:     pkix.Name{},
402				IPAddresses: []net.IP{net.ParseIP("192.168.1.1"), net.ParseIP("192.168.1.2")},
403			},
404			shouldSatisfy: false,
405		},
406		{
407			name: "Extra IP addresses in certificate",
408			cert: &x509.Certificate{
409				Subject:     pkix.Name{},
410				IPAddresses: []net.IP{net.ParseIP("192.168.1.1"), net.ParseIP("192.168.1.2")},
411			},
412			template: &x509.CertificateRequest{
413				Subject:     pkix.Name{},
414				IPAddresses: []net.IP{net.ParseIP("192.168.1.1")},
415			},
416			shouldSatisfy: true,
417		},
418		{
419			name: "Matching certificate",
420			cert: &x509.Certificate{
421				Subject: pkix.Name{
422					CommonName:   "system:node:fake-node-name",
423					Organization: []string{"system:nodes"},
424				},
425				DNSNames:    []string{"foo.example.com"},
426				IPAddresses: []net.IP{net.ParseIP("192.168.1.1")},
427			},
428			template: &x509.CertificateRequest{
429				Subject: pkix.Name{
430					CommonName:   "system:node:fake-node-name",
431					Organization: []string{"system:nodes"},
432				},
433				DNSNames:    []string{"foo.example.com"},
434				IPAddresses: []net.IP{net.ParseIP("192.168.1.1")},
435			},
436			shouldSatisfy: true,
437		},
438	}
439
440	for _, tc := range testCases {
441		t.Run(tc.name, func(t *testing.T) {
442			var tlsCert *tls.Certificate
443
444			if tc.cert != nil {
445				tlsCert = &tls.Certificate{
446					Leaf: tc.cert,
447				}
448			}
449
450			m := manager{
451				cert:        tlsCert,
452				getTemplate: func() *x509.CertificateRequest { return tc.template },
453				now:         time.Now,
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
464func TestRotateCertCreateCSRError(t *testing.T) {
465	now := time.Now()
466	m := manager{
467		cert: &tls.Certificate{
468			Leaf: &x509.Certificate{
469				NotBefore: now.Add(-2 * time.Hour),
470				NotAfter:  now.Add(-1 * time.Hour),
471			},
472		},
473		getTemplate: func() *x509.CertificateRequest { return &x509.CertificateRequest{} },
474		usages:      []certificatesv1.KeyUsage{},
475		clientsetFn: func(_ *tls.Certificate) (clientset.Interface, error) {
476			return newClientset(fakeClient{failureType: createError}), nil
477		},
478		now: func() time.Time { return now },
479	}
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
488func 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		usages:      []certificatesv1.KeyUsage{},
499		clientsetFn: func(_ *tls.Certificate) (clientset.Interface, error) {
500			return newClientset(fakeClient{failureType: watchError}), nil
501		},
502		now: func() time.Time { return now },
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
514func 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
541func 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
581func 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
646func 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
789func 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
893func 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:        errors.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:        errors.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:        errors.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:        errors.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
1041func 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	}
1062	ok, err := m.rotateCerts()
1063	if err != nil || !ok {
1064		t.Errorf("failed to rotate certs: %v", err)
1065	}
1066	if h.calls != 1 {
1067		t.Errorf("rotation metric was not called")
1068	}
1069	if h.lastValue != now.Sub(certIss).Seconds() {
1070		t.Errorf("rotation metric did not record the right value got: %f; want %f", h.lastValue, now.Sub(certIss).Seconds())
1071	}
1072
1073}
1074
1075type fakeClientFailureType int
1076
1077const (
1078	none fakeClientFailureType = iota
1079	createError
1080	watchError
1081	certificateSigningRequestDenied
1082)
1083
1084type fakeClient struct {
1085	noV1      bool
1086	noV1beta1 bool
1087	certificatesclient.CertificateSigningRequestInterface
1088	failureType    fakeClientFailureType
1089	certificatePEM []byte
1090	err            error
1091}
1092
1093func newClientset(opts fakeClient) *fake.Clientset {
1094	f := fake.NewSimpleClientset()
1095	switch opts.failureType {
1096	case createError:
1097		f.PrependReactor("create", "certificatesigningrequests", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
1098			if opts.err != nil {
1099				return true, nil, opts.err
1100			}
1101			return true, nil, fmt.Errorf("create error")
1102		})
1103	case watchError:
1104		f.PrependReactor("list", "certificatesigningrequests", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
1105			if opts.err != nil {
1106				return true, nil, opts.err
1107			}
1108			return true, nil, fmt.Errorf("watch error")
1109		})
1110		f.PrependWatchReactor("certificatesigningrequests", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
1111			if opts.err != nil {
1112				return true, nil, opts.err
1113			}
1114			return true, nil, fmt.Errorf("watch error")
1115		})
1116	default:
1117		f.PrependReactor("create", "certificatesigningrequests", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
1118			switch action.GetResource().Version {
1119			case "v1":
1120				if opts.noV1 {
1121					return true, nil, apierrors.NewNotFound(certificatesv1.Resource("certificatesigningrequests"), "")
1122				}
1123				return true, &certificatesv1.CertificateSigningRequest{ObjectMeta: metav1.ObjectMeta{UID: "fake-uid"}}, nil
1124			case "v1beta1":
1125				if opts.noV1beta1 {
1126					return true, nil, apierrors.NewNotFound(certificatesv1.Resource("certificatesigningrequests"), "")
1127				}
1128				return true, &certificatesv1beta1.CertificateSigningRequest{ObjectMeta: metav1.ObjectMeta{UID: "fake-uid"}}, nil
1129			default:
1130				return false, nil, nil
1131			}
1132		})
1133		f.PrependReactor("list", "certificatesigningrequests", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
1134			switch action.GetResource().Version {
1135			case "v1":
1136				if opts.noV1 {
1137					return true, nil, apierrors.NewNotFound(certificatesv1.Resource("certificatesigningrequests"), "")
1138				}
1139				return true, &certificatesv1.CertificateSigningRequestList{Items: []certificatesv1.CertificateSigningRequest{{ObjectMeta: v1.ObjectMeta{UID: "fake-uid"}}}}, nil
1140			case "v1beta1":
1141				if opts.noV1beta1 {
1142					return true, nil, apierrors.NewNotFound(certificatesv1.Resource("certificatesigningrequests"), "")
1143				}
1144				return true, &certificatesv1beta1.CertificateSigningRequestList{Items: []certificatesv1beta1.CertificateSigningRequest{{ObjectMeta: v1.ObjectMeta{UID: "fake-uid"}}}}, nil
1145			default:
1146				return false, nil, nil
1147			}
1148		})
1149		f.PrependWatchReactor("certificatesigningrequests", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
1150			switch action.GetResource().Version {
1151			case "v1":
1152				if opts.noV1 {
1153					return true, nil, apierrors.NewNotFound(certificatesv1.Resource("certificatesigningrequests"), "")
1154				}
1155				return true, &fakeWatch{
1156					version:        action.GetResource().Version,
1157					failureType:    opts.failureType,
1158					certificatePEM: opts.certificatePEM,
1159				}, nil
1160
1161			case "v1beta1":
1162				if opts.noV1beta1 {
1163					return true, nil, apierrors.NewNotFound(certificatesv1.Resource("certificatesigningrequests"), "")
1164				}
1165				return true, &fakeWatch{
1166					version:        action.GetResource().Version,
1167					failureType:    opts.failureType,
1168					certificatePEM: opts.certificatePEM,
1169				}, nil
1170			default:
1171				return false, nil, nil
1172			}
1173		})
1174	}
1175	return f
1176}
1177
1178type fakeWatch struct {
1179	version        string
1180	failureType    fakeClientFailureType
1181	certificatePEM []byte
1182}
1183
1184func (w *fakeWatch) Stop() {
1185}
1186
1187func (w *fakeWatch) ResultChan() <-chan watch.Event {
1188	var csr runtime.Object
1189
1190	switch w.version {
1191	case "v1":
1192		var condition certificatesv1.CertificateSigningRequestCondition
1193		if w.failureType == certificateSigningRequestDenied {
1194			condition = certificatesv1.CertificateSigningRequestCondition{
1195				Type: certificatesv1.CertificateDenied,
1196			}
1197		} else {
1198			condition = certificatesv1.CertificateSigningRequestCondition{
1199				Type: certificatesv1.CertificateApproved,
1200			}
1201		}
1202
1203		csr = &certificatesv1.CertificateSigningRequest{
1204			ObjectMeta: metav1.ObjectMeta{UID: "fake-uid"},
1205			Status: certificatesv1.CertificateSigningRequestStatus{
1206				Conditions: []certificatesv1.CertificateSigningRequestCondition{
1207					condition,
1208				},
1209				Certificate: []byte(w.certificatePEM),
1210			},
1211		}
1212
1213	case "v1beta1":
1214		var condition certificatesv1beta1.CertificateSigningRequestCondition
1215		if w.failureType == certificateSigningRequestDenied {
1216			condition = certificatesv1beta1.CertificateSigningRequestCondition{
1217				Type: certificatesv1beta1.CertificateDenied,
1218			}
1219		} else {
1220			condition = certificatesv1beta1.CertificateSigningRequestCondition{
1221				Type: certificatesv1beta1.CertificateApproved,
1222			}
1223		}
1224
1225		csr = &certificatesv1beta1.CertificateSigningRequest{
1226			ObjectMeta: metav1.ObjectMeta{UID: "fake-uid"},
1227			Status: certificatesv1beta1.CertificateSigningRequestStatus{
1228				Conditions: []certificatesv1beta1.CertificateSigningRequestCondition{
1229					condition,
1230				},
1231				Certificate: []byte(w.certificatePEM),
1232			},
1233		}
1234	}
1235
1236	c := make(chan watch.Event, 1)
1237	c <- watch.Event{
1238		Type:   watch.Added,
1239		Object: csr,
1240	}
1241	return c
1242}
1243
1244type fakeStore struct {
1245	cert *tls.Certificate
1246}
1247
1248func (s *fakeStore) Current() (*tls.Certificate, error) {
1249	if s.cert == nil {
1250		noKeyErr := NoCertKeyError("")
1251		return nil, &noKeyErr
1252	}
1253	return s.cert, nil
1254}
1255
1256// Accepts the PEM data for the cert/key pair and makes the new cert/key
1257// pair the 'current' pair, that will be returned by future calls to
1258// Current().
1259func (s *fakeStore) Update(certPEM, keyPEM []byte) (*tls.Certificate, error) {
1260	// In order to make the mocking work, whenever a cert/key pair is passed in
1261	// to be updated in the mock store, assume that the certificate manager
1262	// generated the key, and then asked the mock CertificateSigningRequest API
1263	// to sign it, then the faked API returned a canned response. The canned
1264	// signing response will not match the generated key. In order to make
1265	// things work out, search here for the correct matching key and use that
1266	// instead of the passed in key. That way this file of test code doesn't
1267	// have to implement an actual certificate signing process.
1268	for _, tc := range []*certificateData{storeCertData, bootstrapCertData, apiServerCertData} {
1269		if bytes.Equal(tc.certificatePEM, certPEM) {
1270			keyPEM = tc.keyPEM
1271		}
1272	}
1273	cert, err := tls.X509KeyPair(certPEM, keyPEM)
1274	if err != nil {
1275		return nil, err
1276	}
1277	now := time.Now()
1278	s.cert = &cert
1279	s.cert.Leaf = &x509.Certificate{
1280		NotBefore: now.Add(-24 * time.Hour),
1281		NotAfter:  now.Add(24 * time.Hour),
1282	}
1283	return s.cert, nil
1284}
1285
1286func certificatesEqual(c1 *tls.Certificate, c2 *tls.Certificate) bool {
1287	if c1 == nil || c2 == nil {
1288		return c1 == c2
1289	}
1290	if len(c1.Certificate) != len(c2.Certificate) {
1291		return false
1292	}
1293	for i := 0; i < len(c1.Certificate); i++ {
1294		if !bytes.Equal(c1.Certificate[i], c2.Certificate[i]) {
1295			return false
1296		}
1297	}
1298	return true
1299}
1300
1301func certificateString(c *tls.Certificate) string {
1302	if c == nil {
1303		return "certificate == nil"
1304	}
1305	if c.Leaf == nil {
1306		return "certificate.Leaf == nil"
1307	}
1308	return c.Leaf.Subject.CommonName
1309}
1310