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