certs_test.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package certs
  14. import (
  15. "bytes"
  16. "crypto"
  17. "crypto/sha256"
  18. "crypto/x509"
  19. "io/ioutil"
  20. "net"
  21. "os"
  22. "path"
  23. "path/filepath"
  24. "testing"
  25. "github.com/pkg/errors"
  26. "github.com/stretchr/testify/assert"
  27. certutil "k8s.io/client-go/util/cert"
  28. "k8s.io/client-go/util/keyutil"
  29. kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
  30. kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
  31. certstestutil "k8s.io/kubernetes/cmd/kubeadm/app/util/certs"
  32. "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
  33. testutil "k8s.io/kubernetes/cmd/kubeadm/test"
  34. )
  35. func createTestCSR(t *testing.T) (*x509.CertificateRequest, crypto.Signer) {
  36. csr, key, err := pkiutil.NewCSRAndKey(
  37. &certutil.Config{
  38. CommonName: "testCert",
  39. })
  40. if err != nil {
  41. t.Fatalf("couldn't create test cert: %v", err)
  42. }
  43. return csr, key
  44. }
  45. func TestWriteCertificateAuthorithyFilesIfNotExist(t *testing.T) {
  46. setupCert, setupKey := certstestutil.CreateCACert(t)
  47. caCert, caKey := certstestutil.CreateCACert(t)
  48. var tests = []struct {
  49. setupFunc func(pkiDir string) error
  50. expectedError bool
  51. expectedCa *x509.Certificate
  52. }{
  53. { // ca cert does not exists > ca written
  54. expectedCa: caCert,
  55. },
  56. { // ca cert exists, is ca > existing ca used
  57. setupFunc: func(pkiDir string) error {
  58. return writeCertificateAuthorithyFilesIfNotExist(pkiDir, "dummy", setupCert, setupKey)
  59. },
  60. expectedCa: setupCert,
  61. },
  62. { // some file exists, but it is not a valid ca cert > err
  63. setupFunc: func(pkiDir string) error {
  64. testutil.SetupEmptyFiles(t, pkiDir, "dummy.crt")
  65. return nil
  66. },
  67. expectedError: true,
  68. },
  69. { // cert exists, but it is not a ca > err
  70. setupFunc: func(pkiDir string) error {
  71. cert, key, config := certstestutil.CreateTestCert(t, setupCert, setupKey, certutil.AltNames{})
  72. return writeCertificateFilesIfNotExist(pkiDir, "dummy", setupCert, cert, key, config)
  73. },
  74. expectedError: true,
  75. },
  76. }
  77. for _, test := range tests {
  78. // Create temp folder for the test case
  79. tmpdir := testutil.SetupTempDir(t)
  80. defer os.RemoveAll(tmpdir)
  81. // executes setup func (if necessary)
  82. if test.setupFunc != nil {
  83. if err := test.setupFunc(tmpdir); err != nil {
  84. t.Errorf("error executing setupFunc: %v", err)
  85. continue
  86. }
  87. }
  88. // executes create func
  89. err := writeCertificateAuthorithyFilesIfNotExist(tmpdir, "dummy", caCert, caKey)
  90. if !test.expectedError && err != nil {
  91. t.Errorf("error writeCertificateAuthorithyFilesIfNotExist failed when not expected to fail: %v", err)
  92. continue
  93. } else if test.expectedError && err == nil {
  94. t.Error("error writeCertificateAuthorithyFilesIfNotExist didn't failed when expected")
  95. continue
  96. } else if test.expectedError {
  97. continue
  98. }
  99. // asserts expected files are there
  100. testutil.AssertFileExists(t, tmpdir, "dummy.key", "dummy.crt")
  101. // check created cert
  102. resultingCaCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(tmpdir, "dummy")
  103. if err != nil {
  104. t.Errorf("failure reading created cert: %v", err)
  105. continue
  106. }
  107. if !resultingCaCert.Equal(test.expectedCa) {
  108. t.Error("created ca cert does not match expected ca cert")
  109. }
  110. }
  111. }
  112. func TestWriteCertificateFilesIfNotExist(t *testing.T) {
  113. altNames := certutil.AltNames{
  114. DNSNames: []string{"example.com"},
  115. IPs: []net.IP{
  116. net.IPv4(0, 0, 0, 0),
  117. },
  118. }
  119. caCert, caKey := certstestutil.CreateCACert(t)
  120. setupCert, setupKey, _ := certstestutil.CreateTestCert(t, caCert, caKey, altNames)
  121. cert, key, config := certstestutil.CreateTestCert(t, caCert, caKey, altNames)
  122. var tests = []struct {
  123. setupFunc func(pkiDir string) error
  124. expectedError bool
  125. expectedCert *x509.Certificate
  126. }{
  127. { // cert does not exists > cert written
  128. expectedCert: cert,
  129. },
  130. { // cert exists, is signed by the same ca, missing SANs (dns name) > err
  131. setupFunc: func(pkiDir string) error {
  132. setupCert, setupKey, setupConfig := certstestutil.CreateTestCert(t, caCert, caKey, certutil.AltNames{
  133. IPs: []net.IP{
  134. net.IPv4(0, 0, 0, 0),
  135. },
  136. })
  137. return writeCertificateFilesIfNotExist(pkiDir, "dummy", caCert, setupCert, setupKey, setupConfig)
  138. },
  139. expectedError: true,
  140. },
  141. { // cert exists, is signed by the same ca, missing SANs (IP address) > err
  142. setupFunc: func(pkiDir string) error {
  143. setupCert, setupKey, setupConfig := certstestutil.CreateTestCert(t, caCert, caKey, certutil.AltNames{
  144. DNSNames: []string{"example.com"},
  145. })
  146. return writeCertificateFilesIfNotExist(pkiDir, "dummy", caCert, setupCert, setupKey, setupConfig)
  147. },
  148. expectedError: true,
  149. },
  150. { // cert exists, is signed by the same ca, all SANs present > existing cert used
  151. setupFunc: func(pkiDir string) error {
  152. return writeCertificateFilesIfNotExist(pkiDir, "dummy", caCert, setupCert, setupKey, config)
  153. },
  154. expectedCert: setupCert,
  155. },
  156. { // some file exists, but it is not a valid cert > err
  157. setupFunc: func(pkiDir string) error {
  158. testutil.SetupEmptyFiles(t, pkiDir, "dummy.crt")
  159. return nil
  160. },
  161. expectedError: true,
  162. },
  163. { // cert exists, is signed by another ca > err
  164. setupFunc: func(pkiDir string) error {
  165. anotherCaCert, anotherCaKey := certstestutil.CreateCACert(t)
  166. anotherCert, anotherKey, config := certstestutil.CreateTestCert(t, anotherCaCert, anotherCaKey, certutil.AltNames{})
  167. return writeCertificateFilesIfNotExist(pkiDir, "dummy", anotherCaCert, anotherCert, anotherKey, config)
  168. },
  169. expectedError: true,
  170. },
  171. }
  172. for _, test := range tests {
  173. // Create temp folder for the test case
  174. tmpdir := testutil.SetupTempDir(t)
  175. defer os.RemoveAll(tmpdir)
  176. // executes setup func (if necessary)
  177. if test.setupFunc != nil {
  178. if err := test.setupFunc(tmpdir); err != nil {
  179. t.Errorf("error executing setupFunc: %v", err)
  180. continue
  181. }
  182. }
  183. // executes create func
  184. err := writeCertificateFilesIfNotExist(tmpdir, "dummy", caCert, cert, key, config)
  185. if !test.expectedError && err != nil {
  186. t.Errorf("error writeCertificateFilesIfNotExist failed when not expected to fail: %v", err)
  187. continue
  188. } else if test.expectedError && err == nil {
  189. t.Error("error writeCertificateFilesIfNotExist didn't fail when expected")
  190. continue
  191. } else if test.expectedError {
  192. continue
  193. }
  194. // asserts expected files are there
  195. testutil.AssertFileExists(t, tmpdir, "dummy.key", "dummy.crt")
  196. // check created cert
  197. resultingCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(tmpdir, "dummy")
  198. if err != nil {
  199. t.Errorf("failure reading created cert: %v", err)
  200. continue
  201. }
  202. if !resultingCert.Equal(test.expectedCert) {
  203. t.Error("created cert does not match expected cert")
  204. }
  205. }
  206. }
  207. func TestWriteCSRFilesIfNotExist(t *testing.T) {
  208. csr, key := createTestCSR(t)
  209. csr2, key2 := createTestCSR(t)
  210. var tests = []struct {
  211. name string
  212. setupFunc func(csrPath string) error
  213. expectedError bool
  214. expectedCSR *x509.CertificateRequest
  215. }{
  216. {
  217. name: "no files exist",
  218. expectedCSR: csr,
  219. },
  220. {
  221. name: "other key exists",
  222. setupFunc: func(csrPath string) error {
  223. if err := pkiutil.WriteCSR(csrPath, "dummy", csr2); err != nil {
  224. return err
  225. }
  226. return pkiutil.WriteKey(csrPath, "dummy", key2)
  227. },
  228. expectedCSR: csr2,
  229. },
  230. {
  231. name: "existing CSR is garbage",
  232. setupFunc: func(csrPath string) error {
  233. return ioutil.WriteFile(path.Join(csrPath, "dummy.csr"), []byte("a--bunch--of-garbage"), os.ModePerm)
  234. },
  235. expectedError: true,
  236. },
  237. }
  238. for _, test := range tests {
  239. t.Run(test.name, func(t *testing.T) {
  240. tmpdir := testutil.SetupTempDir(t)
  241. defer os.RemoveAll(tmpdir)
  242. if test.setupFunc != nil {
  243. if err := test.setupFunc(tmpdir); err != nil {
  244. t.Fatalf("couldn't set up test: %v", err)
  245. }
  246. }
  247. if err := writeCSRFilesIfNotExist(tmpdir, "dummy", csr, key); err != nil {
  248. if test.expectedError {
  249. return
  250. }
  251. t.Fatalf("unexpected error %v: ", err)
  252. }
  253. if test.expectedError {
  254. t.Fatal("Expected error, but got none")
  255. }
  256. parsedCSR, _, err := pkiutil.TryLoadCSRAndKeyFromDisk(tmpdir, "dummy")
  257. if err != nil {
  258. t.Fatalf("couldn't load csr and key: %v", err)
  259. }
  260. if sha256.Sum256(test.expectedCSR.Raw) != sha256.Sum256(parsedCSR.Raw) {
  261. t.Error("expected csr's fingerprint does not match ")
  262. }
  263. })
  264. }
  265. }
  266. func TestCreateServiceAccountKeyAndPublicKeyFiles(t *testing.T) {
  267. setupKey, err := keyutil.MakeEllipticPrivateKeyPEM()
  268. if err != nil {
  269. t.Fatalf("Can't setup test: %v", err)
  270. }
  271. tcases := []struct {
  272. name string
  273. setupFunc func(pkiDir string) error
  274. expectedErr bool
  275. expectedKey []byte
  276. }{
  277. { // key does not exists > key written
  278. name: "generate successfully",
  279. },
  280. { // key exists > existing key used
  281. name: "use existing key",
  282. setupFunc: func(pkiDir string) error {
  283. err := keyutil.WriteKey(filepath.Join(pkiDir, kubeadmconstants.ServiceAccountPrivateKeyName), setupKey)
  284. return err
  285. },
  286. expectedKey: setupKey,
  287. },
  288. { // some file exists, but it is not a valid key > err
  289. name: "empty key",
  290. setupFunc: func(pkiDir string) error {
  291. testutil.SetupEmptyFiles(t, pkiDir, kubeadmconstants.ServiceAccountPrivateKeyName)
  292. return nil
  293. },
  294. expectedErr: true,
  295. },
  296. }
  297. for _, tt := range tcases {
  298. t.Run(tt.name, func(t *testing.T) {
  299. dir := testutil.SetupTempDir(t)
  300. defer os.RemoveAll(dir)
  301. if tt.setupFunc != nil {
  302. if err := tt.setupFunc(dir); err != nil {
  303. t.Fatalf("error executing setupFunc: %v", err)
  304. }
  305. }
  306. err := CreateServiceAccountKeyAndPublicKeyFiles(dir)
  307. if (err != nil) != tt.expectedErr {
  308. t.Fatalf("expected error: %v, got: %v, error: %v", tt.expectedErr, err != nil, err)
  309. } else if tt.expectedErr {
  310. return
  311. }
  312. resultingKeyPEM, wasGenerated, err := keyutil.LoadOrGenerateKeyFile(filepath.Join(dir, kubeadmconstants.ServiceAccountPrivateKeyName))
  313. if err != nil {
  314. t.Errorf("Can't load created key: %v", err)
  315. } else if wasGenerated {
  316. t.Error("The key was not created")
  317. } else if tt.expectedKey != nil && !bytes.Equal(resultingKeyPEM, tt.expectedKey) {
  318. t.Error("Non-existing key is used")
  319. }
  320. })
  321. }
  322. }
  323. func TestSharedCertificateExists(t *testing.T) {
  324. caCert, caKey := certstestutil.CreateCACert(t)
  325. _, key, _ := certstestutil.CreateTestCert(t, caCert, caKey, certutil.AltNames{})
  326. publicKey := key.Public()
  327. var tests = []struct {
  328. name string
  329. files certstestutil.PKIFiles
  330. expectedError bool
  331. }{
  332. {
  333. name: "success",
  334. files: certstestutil.PKIFiles{
  335. "ca.crt": caCert,
  336. "ca.key": caKey,
  337. "front-proxy-ca.crt": caCert,
  338. "front-proxy-ca.key": caKey,
  339. "sa.pub": publicKey,
  340. "sa.key": key,
  341. "etcd/ca.crt": caCert,
  342. "etcd/ca.key": caKey,
  343. },
  344. },
  345. {
  346. name: "missing ca.crt",
  347. files: certstestutil.PKIFiles{
  348. "ca.key": caKey,
  349. "front-proxy-ca.crt": caCert,
  350. "front-proxy-ca.key": caKey,
  351. "sa.pub": publicKey,
  352. "sa.key": key,
  353. "etcd/ca.crt": caCert,
  354. "etcd/ca.key": caKey,
  355. },
  356. expectedError: true,
  357. },
  358. {
  359. name: "missing sa.key",
  360. files: certstestutil.PKIFiles{
  361. "ca.crt": caCert,
  362. "ca.key": caKey,
  363. "front-proxy-ca.crt": caCert,
  364. "front-proxy-ca.key": caKey,
  365. "sa.pub": publicKey,
  366. "etcd/ca.crt": caCert,
  367. "etcd/ca.key": caKey,
  368. },
  369. expectedError: true,
  370. },
  371. {
  372. name: "missing front-proxy.crt",
  373. files: certstestutil.PKIFiles{
  374. "ca.crt": caCert,
  375. "ca.key": caKey,
  376. "front-proxy-ca.key": caKey,
  377. "sa.pub": publicKey,
  378. "sa.key": key,
  379. "etcd/ca.crt": caCert,
  380. "etcd/ca.key": caKey,
  381. },
  382. expectedError: true,
  383. },
  384. {
  385. name: "missing etcd/ca.crt",
  386. files: certstestutil.PKIFiles{
  387. "ca.crt": caCert,
  388. "ca.key": caKey,
  389. "front-proxy-ca.key": caKey,
  390. "sa.pub": publicKey,
  391. "sa.key": key,
  392. "etcd/ca.crt": caCert,
  393. "etcd/ca.key": caKey,
  394. },
  395. expectedError: true,
  396. },
  397. }
  398. for _, test := range tests {
  399. t.Run("", func(t *testing.T) {
  400. tmpdir := testutil.SetupTempDir(t)
  401. os.MkdirAll(tmpdir+"/etcd", os.ModePerm)
  402. defer os.RemoveAll(tmpdir)
  403. cfg := &kubeadmapi.ClusterConfiguration{
  404. CertificatesDir: tmpdir,
  405. }
  406. // created expected keys
  407. certstestutil.WritePKIFiles(t, tmpdir, test.files)
  408. // executes create func
  409. ret, err := SharedCertificateExists(cfg)
  410. switch {
  411. case !test.expectedError && err != nil:
  412. t.Errorf("error SharedCertificateExists failed when not expected to fail: %v", err)
  413. case test.expectedError && err == nil:
  414. t.Errorf("error SharedCertificateExists didn't failed when expected")
  415. case ret != (err == nil):
  416. t.Errorf("error SharedCertificateExists returned %v when expected to return %v", ret, err == nil)
  417. }
  418. })
  419. }
  420. }
  421. func TestCreatePKIAssetsWithSparseCerts(t *testing.T) {
  422. for _, test := range certstestutil.GetSparseCertTestCases(t) {
  423. t.Run(test.Name, func(t *testing.T) {
  424. tmpdir := testutil.SetupTempDir(t)
  425. defer os.RemoveAll(tmpdir)
  426. cfg := testutil.GetDefaultInternalConfig(t)
  427. cfg.ClusterConfiguration.CertificatesDir = tmpdir
  428. certstestutil.WritePKIFiles(t, tmpdir, test.Files)
  429. err := CreatePKIAssets(cfg)
  430. if err != nil {
  431. if test.ExpectError {
  432. return
  433. }
  434. t.Fatalf("Unexpected error: %v", err)
  435. }
  436. if test.ExpectError {
  437. t.Fatal("Expected error from CreatePKIAssets, got none")
  438. }
  439. assertCertsExist(t, tmpdir)
  440. })
  441. }
  442. }
  443. func TestUsingExternalCA(t *testing.T) {
  444. tests := []struct {
  445. name string
  446. setupFuncs []func(cfg *kubeadmapi.InitConfiguration) error
  447. externalCAFunc func(*kubeadmapi.ClusterConfiguration) (bool, error)
  448. expected bool
  449. expectedErr bool
  450. }{
  451. {
  452. name: "Test External CA, when complete PKI exists",
  453. setupFuncs: []func(cfg *kubeadmapi.InitConfiguration) error{
  454. CreatePKIAssets,
  455. },
  456. externalCAFunc: UsingExternalCA,
  457. expected: false,
  458. },
  459. {
  460. name: "Test External CA, when ca.key missing",
  461. setupFuncs: []func(cfg *kubeadmapi.InitConfiguration) error{
  462. CreatePKIAssets,
  463. deleteCertOrKey(kubeadmconstants.CAKeyName),
  464. },
  465. externalCAFunc: UsingExternalCA,
  466. expected: true,
  467. },
  468. {
  469. name: "Test External CA, when ca.key missing and signed certs are missing",
  470. setupFuncs: []func(cfg *kubeadmapi.InitConfiguration) error{
  471. CreatePKIAssets,
  472. deleteCertOrKey(kubeadmconstants.CAKeyName),
  473. deleteCertOrKey(kubeadmconstants.APIServerCertName),
  474. },
  475. externalCAFunc: UsingExternalCA,
  476. expected: true,
  477. expectedErr: true,
  478. },
  479. {
  480. name: "Test External CA, when ca.key missing",
  481. setupFuncs: []func(cfg *kubeadmapi.InitConfiguration) error{
  482. CreatePKIAssets,
  483. deleteCertOrKey(kubeadmconstants.CAKeyName),
  484. },
  485. externalCAFunc: UsingExternalCA,
  486. expected: true,
  487. },
  488. {
  489. name: "Test External Front Proxy CA, when complete PKI exists",
  490. setupFuncs: []func(cfg *kubeadmapi.InitConfiguration) error{
  491. CreatePKIAssets,
  492. },
  493. externalCAFunc: UsingExternalFrontProxyCA,
  494. expected: false,
  495. },
  496. {
  497. name: "Test External Front Proxy CA, when front-proxy-ca.key missing",
  498. setupFuncs: []func(cfg *kubeadmapi.InitConfiguration) error{
  499. CreatePKIAssets,
  500. deleteCertOrKey(kubeadmconstants.FrontProxyCAKeyName),
  501. },
  502. externalCAFunc: UsingExternalFrontProxyCA,
  503. expected: true,
  504. },
  505. {
  506. name: "Test External Front Proxy CA, when front-proxy-.key missing and signed certs are missing",
  507. setupFuncs: []func(cfg *kubeadmapi.InitConfiguration) error{
  508. CreatePKIAssets,
  509. deleteCertOrKey(kubeadmconstants.FrontProxyCAKeyName),
  510. deleteCertOrKey(kubeadmconstants.FrontProxyClientCertName),
  511. },
  512. externalCAFunc: UsingExternalFrontProxyCA,
  513. expected: true,
  514. expectedErr: true,
  515. },
  516. }
  517. for _, test := range tests {
  518. t.Run(test.name, func(t *testing.T) {
  519. dir := testutil.SetupTempDir(t)
  520. defer os.RemoveAll(dir)
  521. cfg := &kubeadmapi.InitConfiguration{
  522. LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4"},
  523. ClusterConfiguration: kubeadmapi.ClusterConfiguration{
  524. Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"},
  525. CertificatesDir: dir,
  526. },
  527. NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"},
  528. }
  529. for _, f := range test.setupFuncs {
  530. if err := f(cfg); err != nil {
  531. t.Errorf("error executing setup function: %v", err)
  532. }
  533. }
  534. val, err := test.externalCAFunc(&cfg.ClusterConfiguration)
  535. if val != test.expected {
  536. t.Errorf("UsingExternalCA did not match expected: %v", test.expected)
  537. }
  538. if (err != nil) != test.expectedErr {
  539. t.Errorf("UsingExternalCA returned un expected err: %v", err)
  540. }
  541. })
  542. }
  543. }
  544. func TestValidateMethods(t *testing.T) {
  545. caCert, caKey := certstestutil.CreateCACert(t)
  546. cert, key, _ := certstestutil.CreateTestCert(t, caCert, caKey, certutil.AltNames{})
  547. tests := []struct {
  548. name string
  549. files certstestutil.PKIFiles
  550. validateFunc func(l certKeyLocation) error
  551. loc certKeyLocation
  552. expectedSuccess bool
  553. }{
  554. {
  555. name: "validateCACert",
  556. files: certstestutil.PKIFiles{
  557. "ca.crt": caCert,
  558. },
  559. validateFunc: validateCACert,
  560. loc: certKeyLocation{caBaseName: "ca", baseName: "", uxName: "CA"},
  561. expectedSuccess: true,
  562. },
  563. {
  564. name: "validateCACertAndKey (files present)",
  565. files: certstestutil.PKIFiles{
  566. "ca.crt": caCert,
  567. "ca.key": caKey,
  568. },
  569. validateFunc: validateCACertAndKey,
  570. loc: certKeyLocation{caBaseName: "ca", baseName: "", uxName: "CA"},
  571. expectedSuccess: true,
  572. },
  573. {
  574. files: certstestutil.PKIFiles{
  575. "ca.crt": caCert,
  576. },
  577. name: "validateCACertAndKey (key missing)",
  578. validateFunc: validateCACertAndKey,
  579. loc: certKeyLocation{caBaseName: "ca", baseName: "", uxName: "CA"},
  580. expectedSuccess: false,
  581. },
  582. {
  583. name: "validateSignedCert",
  584. files: certstestutil.PKIFiles{
  585. "ca.crt": caCert,
  586. "ca.key": caKey,
  587. "apiserver.crt": cert,
  588. "apiserver.key": key,
  589. },
  590. validateFunc: validateSignedCert,
  591. loc: certKeyLocation{caBaseName: "ca", baseName: "apiserver", uxName: "apiserver"},
  592. expectedSuccess: true,
  593. },
  594. {
  595. name: "validatePrivatePublicKey",
  596. files: certstestutil.PKIFiles{
  597. "sa.pub": key.Public(),
  598. "sa.key": key,
  599. },
  600. validateFunc: validatePrivatePublicKey,
  601. loc: certKeyLocation{baseName: "sa", uxName: "service account"},
  602. expectedSuccess: true,
  603. },
  604. }
  605. for _, test := range tests {
  606. dir := testutil.SetupTempDir(t)
  607. defer os.RemoveAll(dir)
  608. test.loc.pkiDir = dir
  609. certstestutil.WritePKIFiles(t, dir, test.files)
  610. err := test.validateFunc(test.loc)
  611. if test.expectedSuccess && err != nil {
  612. t.Errorf("expected success, error executing validateFunc: %v, %v", test.name, err)
  613. } else if !test.expectedSuccess && err == nil {
  614. t.Errorf("expected failure, no error executing validateFunc: %v", test.name)
  615. }
  616. }
  617. }
  618. func TestNewCSR(t *testing.T) {
  619. kubeadmCert := KubeadmCertAPIServer
  620. cfg := testutil.GetDefaultInternalConfig(t)
  621. certConfig, err := kubeadmCert.GetConfig(cfg)
  622. if err != nil {
  623. t.Fatalf("couldn't get cert config: %v", err)
  624. }
  625. csr, _, err := NewCSR(&kubeadmCert, cfg)
  626. if err != nil {
  627. t.Errorf("invalid signature on CSR: %v", err)
  628. }
  629. assert.ElementsMatch(t, certConfig.Organization, csr.Subject.Organization, "organizations not equal")
  630. if csr.Subject.CommonName != certConfig.CommonName {
  631. t.Errorf("expected common name %q, got %q", certConfig.CommonName, csr.Subject.CommonName)
  632. }
  633. assert.ElementsMatch(t, certConfig.AltNames.DNSNames, csr.DNSNames, "dns names not equal")
  634. assert.Len(t, csr.IPAddresses, len(certConfig.AltNames.IPs))
  635. for i, ip := range csr.IPAddresses {
  636. if !ip.Equal(certConfig.AltNames.IPs[i]) {
  637. t.Errorf("[%d]: %v != %v", i, ip, certConfig.AltNames.IPs[i])
  638. }
  639. }
  640. }
  641. func TestCreateCertificateFilesMethods(t *testing.T) {
  642. var tests = []struct {
  643. createFunc func(cfg *kubeadmapi.InitConfiguration) error
  644. expectedFiles []string
  645. externalEtcd bool
  646. }{
  647. {
  648. createFunc: CreatePKIAssets,
  649. expectedFiles: []string{
  650. kubeadmconstants.CACertName, kubeadmconstants.CAKeyName,
  651. kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName,
  652. kubeadmconstants.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName,
  653. kubeadmconstants.EtcdCACertName, kubeadmconstants.EtcdCAKeyName,
  654. kubeadmconstants.EtcdServerCertName, kubeadmconstants.EtcdServerKeyName,
  655. kubeadmconstants.EtcdPeerCertName, kubeadmconstants.EtcdPeerKeyName,
  656. kubeadmconstants.EtcdHealthcheckClientCertName, kubeadmconstants.EtcdHealthcheckClientKeyName,
  657. kubeadmconstants.APIServerEtcdClientCertName, kubeadmconstants.APIServerEtcdClientKeyName,
  658. kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName,
  659. kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName,
  660. kubeadmconstants.FrontProxyClientCertName, kubeadmconstants.FrontProxyClientKeyName,
  661. },
  662. },
  663. {
  664. createFunc: CreatePKIAssets,
  665. externalEtcd: true,
  666. expectedFiles: []string{
  667. kubeadmconstants.CACertName, kubeadmconstants.CAKeyName,
  668. kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName,
  669. kubeadmconstants.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName,
  670. kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName,
  671. kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName,
  672. kubeadmconstants.FrontProxyClientCertName, kubeadmconstants.FrontProxyClientKeyName,
  673. },
  674. },
  675. }
  676. for _, test := range tests {
  677. // Create temp folder for the test case
  678. tmpdir := testutil.SetupTempDir(t)
  679. defer os.RemoveAll(tmpdir)
  680. cfg := &kubeadmapi.InitConfiguration{
  681. LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4"},
  682. ClusterConfiguration: kubeadmapi.ClusterConfiguration{
  683. Etcd: kubeadmapi.Etcd{Local: &kubeadmapi.LocalEtcd{}},
  684. Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"},
  685. CertificatesDir: tmpdir,
  686. },
  687. NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"},
  688. }
  689. if test.externalEtcd {
  690. if cfg.Etcd.External == nil {
  691. cfg.Etcd.External = &kubeadmapi.ExternalEtcd{}
  692. }
  693. cfg.Etcd.Local = nil
  694. cfg.Etcd.External.Endpoints = []string{"192.168.1.1:2379"}
  695. }
  696. // executes create func
  697. if err := test.createFunc(cfg); err != nil {
  698. t.Errorf("error executing createFunc: %v", err)
  699. continue
  700. }
  701. // asserts expected files are there
  702. testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
  703. }
  704. }
  705. func deleteCertOrKey(name string) func(*kubeadmapi.InitConfiguration) error {
  706. return func(cfg *kubeadmapi.InitConfiguration) error {
  707. if err := os.Remove(filepath.Join(cfg.CertificatesDir, name)); err != nil {
  708. return errors.Wrapf(err, "failed removing %s", name)
  709. }
  710. return nil
  711. }
  712. }
  713. func assertCertsExist(t *testing.T, dir string) {
  714. tree, err := GetDefaultCertList().AsMap().CertTree()
  715. if err != nil {
  716. t.Fatalf("unexpected error getting certificates: %v", err)
  717. }
  718. for caCert, certs := range tree {
  719. if err := validateCACert(certKeyLocation{dir, caCert.BaseName, "", caCert.Name}); err != nil {
  720. t.Errorf("couldn't validate CA certificate %v: %v", caCert.Name, err)
  721. // Don't bother validating child certs, but do try the other CAs
  722. continue
  723. }
  724. for _, cert := range certs {
  725. if err := validateSignedCert(certKeyLocation{dir, caCert.BaseName, cert.BaseName, cert.Name}); err != nil {
  726. t.Errorf("couldn't validate certificate %v: %v", cert.Name, err)
  727. }
  728. }
  729. }
  730. }