...

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

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

     1  /*
     2  Copyright 2018 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  	"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