k8s.io/kubernetes@v1.29.3/test/e2e_kubeadm/kubeadm_certs_test.go (about)

     1  /*
     2  Copyright 2019 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 kubeadm
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	authv1 "k8s.io/api/authorization/v1"
    24  	corev1 "k8s.io/api/core/v1"
    25  	rbacv1 "k8s.io/api/rbac/v1"
    26  	"k8s.io/kubernetes/test/e2e/framework"
    27  	admissionapi "k8s.io/pod-security-admission/api"
    28  
    29  	"github.com/onsi/ginkgo/v2"
    30  	"github.com/onsi/gomega"
    31  )
    32  
    33  const (
    34  	kubeadmCertsSecretName = "kubeadm-certs"
    35  )
    36  
    37  var (
    38  	kubeadmCertsRoleName        = fmt.Sprintf("kubeadm:%s", kubeadmCertsSecretName)
    39  	kubeadmCertsRoleBindingName = kubeadmCertsRoleName
    40  
    41  	kubeadmCertsSecretResource = &authv1.ResourceAttributes{
    42  		Namespace: kubeSystemNamespace,
    43  		Name:      kubeadmCertsSecretName,
    44  		Resource:  "secrets",
    45  		Verb:      "get",
    46  	}
    47  )
    48  
    49  // Define container for all the test specification aimed at verifying
    50  // that kubeadm creates the kubeadm-certs Secret, that it is properly configured
    51  // and that all the related RBAC rules are in place
    52  
    53  // Important! please note that kubeadm-certs is not created by default (still alpha)
    54  // in case you want to skip this test use SKIP=copy-certs
    55  var _ = Describe("kubeadm-certs [copy-certs]", func() {
    56  
    57  	// Get an instance of the k8s test framework
    58  	f := framework.NewDefaultFramework("kubeadm-certs")
    59  	f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
    60  
    61  	// Tests in this container are not expected to create new objects in the cluster
    62  	// so we are disabling the creation of a namespace in order to get a faster execution
    63  	f.SkipNamespaceCreation = true
    64  
    65  	ginkgo.It("should exist and be properly configured", func(ctx context.Context) {
    66  		s := GetSecret(f.ClientSet, kubeSystemNamespace, kubeadmCertsSecretName)
    67  
    68  		// Checks the kubeadm-certs is ownen by a time lived token
    69  		gomega.Expect(s.OwnerReferences).To(gomega.HaveLen(1), "%s should have one owner reference", kubeadmCertsSecretName)
    70  		ownRef := s.OwnerReferences[0]
    71  		gomega.Expect(ownRef.Kind).To(gomega.Equal("Secret"), "%s should be owned by a secret", kubeadmCertsSecretName)
    72  		gomega.Expect(*ownRef.BlockOwnerDeletion).To(gomega.BeTrue(), "%s should be deleted on owner deletion", kubeadmCertsSecretName)
    73  
    74  		o := GetSecret(f.ClientSet, kubeSystemNamespace, ownRef.Name)
    75  		gomega.Expect(o.Type).To(gomega.Equal(corev1.SecretTypeBootstrapToken), "%s should have an owner reference that refers to a bootstrap-token", kubeadmCertsSecretName)
    76  		gomega.Expect(o.Data).To(gomega.HaveKey("expiration"), "%s should have an owner reference with an expiration", kubeadmCertsSecretName)
    77  
    78  		// gets the ClusterConfiguration from the kubeadm kubeadm-config ConfigMap as a untyped map
    79  		m := getClusterConfiguration(f.ClientSet)
    80  
    81  		// Extract the etcd Type
    82  		etcdType := "local"
    83  		if _, ok := m["etcd"]; ok {
    84  			d := m["etcd"].(map[interface{}]interface{})
    85  			if _, ok := d["external"]; ok {
    86  				etcdType = "external"
    87  			}
    88  		}
    89  
    90  		// check if all the expected key exists
    91  		gomega.Expect(s.Data).To(gomega.HaveKey("ca.crt"))
    92  		gomega.Expect(s.Data).To(gomega.HaveKey("ca.key"))
    93  		gomega.Expect(s.Data).To(gomega.HaveKey("front-proxy-ca.crt"))
    94  		gomega.Expect(s.Data).To(gomega.HaveKey("front-proxy-ca.key"))
    95  		gomega.Expect(s.Data).To(gomega.HaveKey("sa.pub"))
    96  		gomega.Expect(s.Data).To(gomega.HaveKey("sa.key"))
    97  
    98  		if etcdType == "local" {
    99  			gomega.Expect(s.Data).To(gomega.HaveKey("etcd-ca.crt"))
   100  			gomega.Expect(s.Data).To(gomega.HaveKey("etcd-ca.key"))
   101  		} else {
   102  			gomega.Expect(s.Data).To(gomega.HaveKey("external-etcd-ca.crt"))
   103  			gomega.Expect(s.Data).To(gomega.HaveKey("external-etcd.crt"))
   104  			gomega.Expect(s.Data).To(gomega.HaveKey("external-etcd.key"))
   105  		}
   106  	})
   107  
   108  	ginkgo.It("should have related Role and RoleBinding", func(ctx context.Context) {
   109  		ExpectRole(f.ClientSet, kubeSystemNamespace, kubeadmCertsRoleName)
   110  		ExpectRoleBinding(f.ClientSet, kubeSystemNamespace, kubeadmCertsRoleBindingName)
   111  	})
   112  
   113  	ginkgo.It("should be accessible for bootstrap tokens", func(ctx context.Context) {
   114  		ExpectSubjectHasAccessToResource(f.ClientSet,
   115  			rbacv1.GroupKind, bootstrapTokensGroup,
   116  			kubeadmCertsSecretResource,
   117  		)
   118  	})
   119  })