From 0a56741bb6335ac4c54a4004e0406f05734a1654 Mon Sep 17 00:00:00 2001 From: Mohamed Awnallah Date: Wed, 30 Oct 2024 18:18:57 +0300 Subject: [PATCH] pkg/karmadactl/cmdinit: unit test bootstraptoken In this commit, we unit test bootstraptoken agent on tlsbootstrap functionality by testing `AllowBootstrapTokensToPostCSRs`, `AutoApproveKarmadaAgentBootstrapTokens`, and `AutoApproveAgentCertificateRotation` making sure they are working as expected. Signed-off-by: Mohamed Awnallah --- .../bootstraptoken/agent/tlsbootstrap.go | 6 +- .../bootstraptoken/agent/tlsbootstrap_test.go | 178 ++++++++++++++++++ 2 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 pkg/karmadactl/cmdinit/bootstraptoken/agent/tlsbootstrap_test.go diff --git a/pkg/karmadactl/cmdinit/bootstraptoken/agent/tlsbootstrap.go b/pkg/karmadactl/cmdinit/bootstraptoken/agent/tlsbootstrap.go index 34f284c3d..14a8e75ad 100644 --- a/pkg/karmadactl/cmdinit/bootstraptoken/agent/tlsbootstrap.go +++ b/pkg/karmadactl/cmdinit/bootstraptoken/agent/tlsbootstrap.go @@ -45,7 +45,7 @@ const ( ) // AllowBootstrapTokensToPostCSRs creates RBAC rules in a way the makes Karmada Agent Bootstrap Tokens able to post CSRs -func AllowBootstrapTokensToPostCSRs(clientSet *kubernetes.Clientset) error { +func AllowBootstrapTokensToPostCSRs(clientSet kubernetes.Interface) error { klog.Infoln("[bootstrap-token] configured RBAC rules to allow Karmada Agent Bootstrap tokens to post CSRs in order for agent to get long term certificate credentials") clusterRoleBinding := utils.ClusterRoleBindingFromSubjects(KarmadaAgentBootstrap, KarmadaAgentBootstrapperClusterRoleName, @@ -59,7 +59,7 @@ func AllowBootstrapTokensToPostCSRs(clientSet *kubernetes.Clientset) error { } // AutoApproveKarmadaAgentBootstrapTokens creates RBAC rules in a way that makes Karmada Agent Bootstrap Tokens' CSR auto-approved by the csrapprover controller -func AutoApproveKarmadaAgentBootstrapTokens(clientSet *kubernetes.Clientset) error { +func AutoApproveKarmadaAgentBootstrapTokens(clientSet kubernetes.Interface) error { klog.Infoln("[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Karmada Agent Bootstrap Token") clusterRoleBinding := utils.ClusterRoleBindingFromSubjects(KarmadaAgentAutoApproveBootstrapClusterRoleBinding, CSRAutoApprovalClusterRoleName, @@ -73,7 +73,7 @@ func AutoApproveKarmadaAgentBootstrapTokens(clientSet *kubernetes.Clientset) err } // AutoApproveAgentCertificateRotation creates RBAC rules in a way that makes Agent certificate rotation CSR auto-approved by the csrapprover controller -func AutoApproveAgentCertificateRotation(clientSet *kubernetes.Clientset) error { +func AutoApproveAgentCertificateRotation(clientSet kubernetes.Interface) error { klog.Infoln("[bootstrap-token] configured RBAC rules to allow certificate rotation for all agent client certificates in the member cluster") clusterRoleBinding := utils.ClusterRoleBindingFromSubjects(KarmadaAgentAutoApproveCertificateRotationClusterRoleBinding, KarmadaAgentSelfCSRAutoApprovalClusterRoleName, diff --git a/pkg/karmadactl/cmdinit/bootstraptoken/agent/tlsbootstrap_test.go b/pkg/karmadactl/cmdinit/bootstraptoken/agent/tlsbootstrap_test.go new file mode 100644 index 000000000..71ba4a63a --- /dev/null +++ b/pkg/karmadactl/cmdinit/bootstraptoken/agent/tlsbootstrap_test.go @@ -0,0 +1,178 @@ +/* +Copyright 2024 The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package agent + +import ( + "context" + "fmt" + "testing" + + rbacv1 "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + clientset "k8s.io/client-go/kubernetes" + fakeclientset "k8s.io/client-go/kubernetes/fake" + + "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils" +) + +func TestAllowBootstrapTokensToPostCSRs(t *testing.T) { + tests := []struct { + name string + client clientset.Interface + prep func(clientset.Interface) error + verify func(clientset.Interface) error + }{ + { + name: "AllowBootstrapTokensToPostCSRs_CreateClusterRoleBinding_Created", + client: fakeclientset.NewSimpleClientset(), + prep: func(clientset.Interface) error { return nil }, + verify: func(client clientset.Interface) error { + return verifyClusterRoleBinding(client, KarmadaAgentBootstrap, KarmadaAgentBootstrapperClusterRoleName) + }, + }, + { + name: "AllowBootstrapTokensToPostCSRs_ClusterRoleBindingAlreadyExists_Updated", + client: fakeclientset.NewSimpleClientset(), + prep: func(client clientset.Interface) error { + return createClusterRoleBinding(client, KarmadaAgentBootstrap, KarmadaAgentBootstrapperClusterRoleName, KarmadaAgentBootstrapTokenAuthGroup) + }, + verify: func(client clientset.Interface) error { + return verifyClusterRoleBinding(client, KarmadaAgentBootstrap, KarmadaAgentBootstrapperClusterRoleName) + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if err := test.prep(test.client); err != nil { + t.Fatalf("failed to prep before allowing bootstrap tokens to post CSRs, got: %v", err) + } + if err := AllowBootstrapTokensToPostCSRs(test.client); err != nil { + t.Errorf("unexpected error while allowing bootstrap tokens to post CSRs, got: %v", err) + } + if err := test.verify(test.client); err != nil { + t.Errorf("failed to verify the creation of cluster role bindings, got: %v", err) + } + }) + } +} + +func TestAutoApproveKarmadaAgentBootstrapTokens(t *testing.T) { + tests := []struct { + name string + client clientset.Interface + prep func(clientset.Interface) error + verify func(clientset.Interface) error + }{ + { + name: "AutoApproveKarmadaAgentBootstrapTokens_CreateClusterRoleBindings_Created", + client: fakeclientset.NewSimpleClientset(), + prep: func(clientset.Interface) error { return nil }, + verify: func(client clientset.Interface) error { + return verifyClusterRoleBinding(client, KarmadaAgentAutoApproveBootstrapClusterRoleBinding, CSRAutoApprovalClusterRoleName) + }, + }, + { + name: "AutoApproveKarmadaAgentBootstrapTokens_ClusterRoleBindingAlreadyExists_Updated", + client: fakeclientset.NewSimpleClientset(), + prep: func(client clientset.Interface) error { + return createClusterRoleBinding(client, KarmadaAgentAutoApproveBootstrapClusterRoleBinding, CSRAutoApprovalClusterRoleName, KarmadaAgentBootstrapTokenAuthGroup) + }, + verify: func(client clientset.Interface) error { + return verifyClusterRoleBinding(client, KarmadaAgentAutoApproveBootstrapClusterRoleBinding, CSRAutoApprovalClusterRoleName) + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if err := test.prep(test.client); err != nil { + t.Fatalf("failed to prep before auto-approve karmada agent bootstrap tokens, got: %v", err) + } + if err := AutoApproveKarmadaAgentBootstrapTokens(test.client); err != nil { + t.Errorf("unexpected error, got: %v", err) + } + if err := test.verify(test.client); err != nil { + t.Errorf("failed to verify the creation of cluster role bindings, got error: %v", err) + } + }) + } +} + +func TestAutoApproveAgentCertificateRotation(t *testing.T) { + tests := []struct { + name string + client clientset.Interface + prep func(clientset.Interface) error + verify func(clientset.Interface) error + }{ + { + name: "AutoApproveAgentCertificateRotation_CreateClusterRoleBindings_Created", + client: fakeclientset.NewSimpleClientset(), + prep: func(clientset.Interface) error { return nil }, + verify: func(client clientset.Interface) error { + return verifyClusterRoleBinding(client, KarmadaAgentAutoApproveCertificateRotationClusterRoleBinding, KarmadaAgentSelfCSRAutoApprovalClusterRoleName) + }, + }, + { + name: "AutoApproveAgentCertificateRotation_ClusterRoleBindingAlreadyExists_Updated", + client: fakeclientset.NewSimpleClientset(), + prep: func(client clientset.Interface) error { + return createClusterRoleBinding(client, KarmadaAgentAutoApproveCertificateRotationClusterRoleBinding, KarmadaAgentSelfCSRAutoApprovalClusterRoleName, KarmadaAgentGroup) + }, + verify: func(client clientset.Interface) error { + return verifyClusterRoleBinding(client, KarmadaAgentAutoApproveCertificateRotationClusterRoleBinding, KarmadaAgentSelfCSRAutoApprovalClusterRoleName) + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if err := test.prep(test.client); err != nil { + t.Fatalf("failed to prep before auto-approve agent certificate rotation, got: %v", err) + } + if err := AutoApproveAgentCertificateRotation(test.client); err != nil { + t.Errorf("unexpected error, got: %v", err) + } + if err := test.verify(test.client); err != nil { + t.Errorf("failed to verify the creation of cluster role bindings, got error: %v", err) + } + }) + } +} + +func createClusterRoleBinding(client clientset.Interface, crbName, crName, subjectName string) error { + clusterRoleBinding := utils.ClusterRoleBindingFromSubjects(crbName, crName, + []rbacv1.Subject{ + { + Kind: rbacv1.GroupKind, + Name: subjectName, + }, + }, nil) + if _, err := client.RbacV1().ClusterRoleBindings().Create(context.TODO(), clusterRoleBinding, metav1.CreateOptions{}); err != nil { + return fmt.Errorf("failed to create cluster role binding, got: %v", err) + } + return nil +} + +func verifyClusterRoleBinding(client clientset.Interface, crbName, crName string) error { + clusterRoleBinding, err := client.RbacV1().ClusterRoleBindings().Get(context.TODO(), crbName, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("failed to get cluster role binding, got: %v", err) + } + if clusterRoleBinding.RoleRef.Name != crName { + return fmt.Errorf("expected cluster role ref name to be %s, but got %s", crName, clusterRoleBinding.RoleRef.Name) + } + return nil +}