1
16
17 package certs
18
19 import (
20 "crypto"
21 "crypto/tls"
22 "crypto/x509"
23 "os"
24 "path/filepath"
25 "testing"
26
27 certutil "k8s.io/client-go/util/cert"
28
29 kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
30 kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
31 "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
32 )
33
34 func TestCertListOrder(t *testing.T) {
35 tests := []struct {
36 certs Certificates
37 name string
38 }{
39 {
40 name: "Default Certificate List",
41 certs: GetDefaultCertList(),
42 },
43 {
44 name: "Cert list less etcd",
45 certs: GetCertsWithoutEtcd(),
46 },
47 }
48
49 for _, test := range tests {
50 t.Run(test.name, func(t *testing.T) {
51 var lastCA *KubeadmCert
52 for i, cert := range test.certs {
53 if i > 0 && lastCA == nil {
54 t.Fatalf("CA not present in list before certificate %q", cert.Name)
55 }
56 if cert.CAName == "" {
57 lastCA = cert
58 } else {
59 if cert.CAName != lastCA.Name {
60 t.Fatalf("expected CA name %q, got %q, for certificate %q", lastCA.Name, cert.CAName, cert.Name)
61 }
62 }
63 }
64 })
65 }
66 }
67
68 func TestCAPointersValid(t *testing.T) {
69 tests := []struct {
70 certs Certificates
71 name string
72 }{
73 {
74 name: "Default Certificate List",
75 certs: GetDefaultCertList(),
76 },
77 {
78 name: "Cert list less etcd",
79 certs: GetCertsWithoutEtcd(),
80 },
81 }
82
83 for _, test := range tests {
84 t.Run(test.name, func(t *testing.T) {
85
86 certMap := test.certs.AsMap()
87
88 for _, cert := range test.certs {
89 if cert.CAName != "" && certMap[cert.CAName] == nil {
90 t.Errorf("Certificate %q references nonexistent CA %q", cert.Name, cert.CAName)
91 }
92 }
93 })
94 }
95 }
96
97 func TestMakeCertTree(t *testing.T) {
98 rootCert := &KubeadmCert{
99 Name: "root",
100 }
101 leaf0 := &KubeadmCert{
102 Name: "leaf0",
103 CAName: "root",
104 }
105 leaf1 := &KubeadmCert{
106 Name: "leaf1",
107 CAName: "root",
108 }
109 selfSigned := &KubeadmCert{
110 Name: "self-signed",
111 }
112
113 certMap := CertificateMap{
114 "root": rootCert,
115 "leaf0": leaf0,
116 "leaf1": leaf1,
117 "self-signed": selfSigned,
118 }
119
120 orphanCertMap := CertificateMap{
121 "leaf0": leaf0,
122 }
123
124 if _, err := orphanCertMap.CertTree(); err == nil {
125 t.Error("expected orphan cert map to error, but got nil")
126 }
127
128 certTree, err := certMap.CertTree()
129 t.Logf("cert tree: %v", certTree)
130 if err != nil {
131 t.Errorf("expected no error, but got %v", err)
132 }
133
134 if len(certTree) != 2 {
135 t.Errorf("Expected tree to have 2 roots, got %d", len(certTree))
136 }
137
138 if len(certTree[rootCert]) != 2 {
139 t.Errorf("Expected root to have 2 leaves, got %d", len(certTree[rootCert]))
140 }
141
142 if _, ok := certTree[selfSigned]; !ok {
143 t.Error("Expected selfSigned to be present in tree, but missing")
144 }
145 }
146
147 func TestCreateCertificateChain(t *testing.T) {
148 dir, err := os.MkdirTemp("", t.Name())
149 if err != nil {
150 t.Fatal(err)
151 }
152 defer os.RemoveAll(dir)
153
154 ic := &kubeadmapi.InitConfiguration{
155 NodeRegistration: kubeadmapi.NodeRegistrationOptions{
156 Name: "test-node",
157 },
158 ClusterConfiguration: kubeadmapi.ClusterConfiguration{
159 CertificatesDir: dir,
160 },
161 }
162
163 caCfg := Certificates{
164 {
165 config: pkiutil.CertConfig{},
166 Name: "test-ca",
167 BaseName: "test-ca",
168 },
169 {
170 config: pkiutil.CertConfig{
171 Config: certutil.Config{
172 AltNames: certutil.AltNames{
173 DNSNames: []string{"test-domain.space"},
174 },
175 Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
176 },
177 },
178 configMutators: []configMutatorsFunc{
179 setCommonNameToNodeName(),
180 },
181 CAName: "test-ca",
182 Name: "test-daughter",
183 BaseName: "test-daughter",
184 },
185 }
186
187 certTree, err := caCfg.AsMap().CertTree()
188 if err != nil {
189 t.Fatalf("unexpected error getting tree: %v", err)
190 }
191
192 if err := certTree.CreateTree(ic); err != nil {
193 t.Fatal(err)
194 }
195
196 caCert, _ := parseCertAndKey(filepath.Join(dir, "test-ca"), t)
197 daughterCert, _ := parseCertAndKey(filepath.Join(dir, "test-daughter"), t)
198
199 pool := x509.NewCertPool()
200 pool.AddCert(caCert)
201
202 _, err = daughterCert.Verify(x509.VerifyOptions{
203 DNSName: "test-domain.space",
204 Roots: pool,
205 KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
206 })
207 if err != nil {
208 t.Errorf("couldn't verify daughter cert: %v", err)
209 }
210
211 }
212
213 func parseCertAndKey(basePath string, t *testing.T) (*x509.Certificate, crypto.PrivateKey) {
214 certPair, err := tls.LoadX509KeyPair(basePath+".crt", basePath+".key")
215 if err != nil {
216 t.Fatalf("couldn't parse certificate and key: %v", err)
217 }
218
219 parsedCert, err := x509.ParseCertificate(certPair.Certificate[0])
220 if err != nil {
221 t.Fatalf("couldn't parse certificate: %v", err)
222 }
223
224 return parsedCert, certPair.PrivateKey
225 }
226
227 func TestCreateKeyAndCSR(t *testing.T) {
228 dir, err := os.MkdirTemp("", t.Name())
229 if err != nil {
230 t.Fatal(err)
231 }
232 defer os.RemoveAll(dir)
233
234 validKubeadmConfig := &kubeadmapi.InitConfiguration{
235 NodeRegistration: kubeadmapi.NodeRegistrationOptions{
236 Name: "test-node",
237 },
238 ClusterConfiguration: kubeadmapi.ClusterConfiguration{
239 CertificatesDir: dir,
240 },
241 }
242 validKubeadmCert := &KubeadmCert{
243 Name: "ca",
244 LongName: "self-signed Kubernetes CA to provision identities for other Kubernetes components",
245 BaseName: kubeadmconstants.CACertAndKeyBaseName,
246 config: pkiutil.CertConfig{
247 Config: certutil.Config{
248 CommonName: "kubernetes",
249 },
250 },
251 }
252
253 type args struct {
254 kubeadmConfig *kubeadmapi.InitConfiguration
255 cert *KubeadmCert
256 }
257 tests := []struct {
258 name string
259 args args
260 wantErr bool
261 createfile bool
262 }{
263 {
264 name: "kubeadmConfig is nil",
265 args: args{
266 kubeadmConfig: nil,
267 cert: validKubeadmCert,
268 },
269 wantErr: true,
270 },
271 {
272 name: "cert is nil",
273 args: args{
274 kubeadmConfig: validKubeadmConfig,
275 cert: nil,
276 },
277 wantErr: true,
278 },
279 {
280 name: "key and CSR do not exist",
281 args: args{
282 kubeadmConfig: validKubeadmConfig,
283 cert: validKubeadmCert,
284 },
285 wantErr: false,
286 },
287 {
288 name: "key or CSR already exist",
289 args: args{
290 kubeadmConfig: validKubeadmConfig,
291 cert: validKubeadmCert,
292 },
293 wantErr: true,
294 },
295 }
296 for _, tt := range tests {
297 t.Run(tt.name, func(t *testing.T) {
298 if err := createKeyAndCSR(tt.args.kubeadmConfig, tt.args.cert); (err != nil) != tt.wantErr {
299 t.Errorf("createKeyAndCSR() error = %v, wantErr %v", err, tt.wantErr)
300 }
301 })
302 }
303 }
304
View as plain text