...

Source file src/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/certs_test.go

Documentation: k8s.io/kubernetes/cmd/kubeadm/app/phases/certs

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

View as plain text