mirror of
https://github.com/open-cluster-management-io/ocm.git
synced 2026-05-06 09:16:59 +00:00
216 lines
7.6 KiB
Go
216 lines
7.6 KiB
Go
package clientcert
|
|
|
|
import (
|
|
"context"
|
|
"crypto/x509/pkix"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
certificates "k8s.io/api/certificates/v1"
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/client-go/informers"
|
|
kubefake "k8s.io/client-go/kubernetes/fake"
|
|
clienttesting "k8s.io/client-go/testing"
|
|
|
|
testinghelpers "open-cluster-management.io/registration/pkg/helpers/testing"
|
|
"open-cluster-management.io/registration/pkg/hub/user"
|
|
)
|
|
|
|
const (
|
|
testNamespace = "testns"
|
|
testAgentName = "testagent"
|
|
testSecretName = "testsecret"
|
|
testCSRName = "testcsr"
|
|
)
|
|
|
|
var commonName = fmt.Sprintf("%s%s:%s", user.SubjectPrefix, testinghelpers.TestManagedClusterName, testAgentName)
|
|
|
|
func TestSync(t *testing.T) {
|
|
testSubject := &pkix.Name{
|
|
CommonName: commonName,
|
|
}
|
|
|
|
cases := []struct {
|
|
name string
|
|
queueKey string
|
|
secrets []runtime.Object
|
|
approvedCSRCert *testinghelpers.TestCert
|
|
keyDataExpected bool
|
|
csrNameExpected bool
|
|
additonalSecretDataSensitive bool
|
|
validateActions func(t *testing.T, hubActions, agentActions []clienttesting.Action)
|
|
}{
|
|
{
|
|
name: "agent bootstrap",
|
|
secrets: []runtime.Object{},
|
|
queueKey: "key",
|
|
keyDataExpected: true,
|
|
csrNameExpected: true,
|
|
validateActions: func(t *testing.T, hubActions, agentActions []clienttesting.Action) {
|
|
testinghelpers.AssertActions(t, hubActions, "create")
|
|
actual := hubActions[0].(clienttesting.CreateActionImpl).Object
|
|
if _, ok := actual.(*certificates.CertificateSigningRequest); !ok {
|
|
t.Errorf("expected csr was created, but failed")
|
|
}
|
|
|
|
testinghelpers.AssertActions(t, agentActions, "get")
|
|
},
|
|
},
|
|
{
|
|
name: "syc csr after bootstrap",
|
|
queueKey: testSecretName,
|
|
secrets: []runtime.Object{
|
|
testinghelpers.NewHubKubeconfigSecret(testNamespace, testSecretName, "1", nil, map[string][]byte{
|
|
ClusterNameFile: []byte(testinghelpers.TestManagedClusterName),
|
|
AgentNameFile: []byte(testAgentName),
|
|
},
|
|
),
|
|
},
|
|
approvedCSRCert: testinghelpers.NewTestCert(commonName, 10*time.Second),
|
|
validateActions: func(t *testing.T, hubActions, agentActions []clienttesting.Action) {
|
|
testinghelpers.AssertActions(t, hubActions, "get")
|
|
testinghelpers.AssertActions(t, agentActions, "get", "update")
|
|
actual := agentActions[1].(clienttesting.UpdateActionImpl).Object
|
|
secret := actual.(*corev1.Secret)
|
|
valid, err := IsCertificateValid(secret.Data[TLSCertFile], testSubject)
|
|
if err != nil {
|
|
t.Errorf("unexpected error: %v", err)
|
|
}
|
|
if !valid {
|
|
t.Error("client certificate is invalid")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "sync a valid hub kubeconfig secret",
|
|
queueKey: testSecretName,
|
|
secrets: []runtime.Object{
|
|
testinghelpers.NewHubKubeconfigSecret(testNamespace, testSecretName, "1", testinghelpers.NewTestCert(commonName, 10000*time.Second), map[string][]byte{
|
|
ClusterNameFile: []byte(testinghelpers.TestManagedClusterName),
|
|
AgentNameFile: []byte(testAgentName),
|
|
KubeconfigFile: testinghelpers.NewKubeconfig(nil, nil),
|
|
}),
|
|
},
|
|
validateActions: func(t *testing.T, hubActions, agentActions []clienttesting.Action) {
|
|
testinghelpers.AssertNoActions(t, hubActions)
|
|
testinghelpers.AssertActions(t, agentActions, "get")
|
|
},
|
|
},
|
|
{
|
|
name: "sync an expiring hub kubeconfig secret",
|
|
queueKey: testSecretName,
|
|
secrets: []runtime.Object{
|
|
testinghelpers.NewHubKubeconfigSecret(testNamespace, testSecretName, "1", testinghelpers.NewTestCert(commonName, -3*time.Second), map[string][]byte{
|
|
ClusterNameFile: []byte(testinghelpers.TestManagedClusterName),
|
|
AgentNameFile: []byte(testAgentName),
|
|
KubeconfigFile: testinghelpers.NewKubeconfig(nil, nil),
|
|
}),
|
|
},
|
|
keyDataExpected: true,
|
|
csrNameExpected: true,
|
|
validateActions: func(t *testing.T, hubActions, agentActions []clienttesting.Action) {
|
|
testinghelpers.AssertActions(t, hubActions, "create")
|
|
actual := hubActions[0].(clienttesting.CreateActionImpl).Object
|
|
if _, ok := actual.(*certificates.CertificateSigningRequest); !ok {
|
|
t.Errorf("expected csr was created, but failed")
|
|
}
|
|
testinghelpers.AssertActions(t, agentActions, "get")
|
|
},
|
|
},
|
|
{
|
|
name: "sync when additional secret data changes",
|
|
queueKey: testSecretName,
|
|
secrets: []runtime.Object{
|
|
testinghelpers.NewHubKubeconfigSecret(testNamespace, testSecretName, "1", testinghelpers.NewTestCert(commonName, 10000*time.Second), map[string][]byte{
|
|
ClusterNameFile: []byte(testinghelpers.TestManagedClusterName),
|
|
AgentNameFile: []byte("invalid-name"),
|
|
}),
|
|
},
|
|
keyDataExpected: true,
|
|
csrNameExpected: true,
|
|
additonalSecretDataSensitive: true,
|
|
validateActions: func(t *testing.T, hubActions, agentActions []clienttesting.Action) {
|
|
testinghelpers.AssertActions(t, hubActions, "create")
|
|
actual := hubActions[0].(clienttesting.CreateActionImpl).Object
|
|
if _, ok := actual.(*certificates.CertificateSigningRequest); !ok {
|
|
t.Errorf("expected csr was created, but failed")
|
|
}
|
|
testinghelpers.AssertActions(t, agentActions, "get")
|
|
},
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
csrs := []runtime.Object{}
|
|
if c.approvedCSRCert != nil {
|
|
csr := testinghelpers.NewApprovedCSR(testinghelpers.CSRHolder{Name: testCSRName})
|
|
csr.Status.Certificate = c.approvedCSRCert.Cert
|
|
csrs = append(csrs, csr)
|
|
}
|
|
hubKubeClient := kubefake.NewSimpleClientset(csrs...)
|
|
|
|
// GenerateName is not working for fake clent, we set the name with prepend reactor
|
|
hubKubeClient.PrependReactor(
|
|
"create",
|
|
"certificatesigningrequests",
|
|
func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
|
return true, testinghelpers.NewCSR(testinghelpers.CSRHolder{Name: testCSRName}), nil
|
|
},
|
|
)
|
|
hubInformerFactory := informers.NewSharedInformerFactory(hubKubeClient, 3*time.Minute)
|
|
agentKubeClient := kubefake.NewSimpleClientset(c.secrets...)
|
|
|
|
clientCertOption := ClientCertOption{
|
|
SecretNamespace: testNamespace,
|
|
SecretName: testSecretName,
|
|
AdditonalSecretData: map[string][]byte{
|
|
ClusterNameFile: []byte(testinghelpers.TestManagedClusterName),
|
|
AgentNameFile: []byte(testAgentName),
|
|
},
|
|
AdditonalSecretDataSensitive: c.additonalSecretDataSensitive,
|
|
}
|
|
csrOption := CSROption{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
GenerateName: "test-",
|
|
},
|
|
Subject: testSubject,
|
|
SignerName: certificates.KubeAPIServerClientSignerName,
|
|
}
|
|
|
|
controller := &clientCertificateController{
|
|
ClientCertOption: clientCertOption,
|
|
CSROption: csrOption,
|
|
hubCSRLister: hubInformerFactory.Certificates().V1().CertificateSigningRequests().Lister(),
|
|
hubCSRClient: hubKubeClient.CertificatesV1().CertificateSigningRequests(),
|
|
spokeCoreClient: agentKubeClient.CoreV1(),
|
|
controllerName: "test-agent",
|
|
}
|
|
|
|
if c.approvedCSRCert != nil {
|
|
controller.csrName = testCSRName
|
|
controller.keyData = c.approvedCSRCert.Key
|
|
}
|
|
|
|
err := controller.sync(context.TODO(), testinghelpers.NewFakeSyncContext(t, c.queueKey))
|
|
if err != nil {
|
|
t.Errorf("unexpected error %v", err)
|
|
}
|
|
|
|
hasKeyData := controller.keyData != nil
|
|
if c.keyDataExpected != hasKeyData {
|
|
t.Error("controller.keyData should be set")
|
|
}
|
|
|
|
hasCSRName := controller.csrName != ""
|
|
if c.csrNameExpected != hasCSRName {
|
|
t.Error("controller.csrName should be set")
|
|
}
|
|
|
|
c.validateActions(t, hubKubeClient.Actions(), agentKubeClient.Actions())
|
|
})
|
|
}
|
|
}
|