certs_test.go 24 KB

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