Skip to content

Commit

Permalink
test: enrich node configuration controller tests with signed configma…
Browse files Browse the repository at this point in the history
…ps (canonical#1032)

* tests: enrich node configuration controller tests with signed configmaps

Signed-off-by: Reza Abbasalipour <[email protected]>

* fix: change configmap to trigger restart in case of valid signature

Signed-off-by: Reza Abbasalipour <[email protected]>

* chore: try with different configs with invalid signature to make sure they are not applied

Signed-off-by: Reza Abbasalipour <[email protected]>

* tests: add a test case to update node configuration controller to account for signed configmaps

Signed-off-by: Reza Abbasalipour <[email protected]>

* fix: improve test case names

Signed-off-by: Reza Abbasalipour <[email protected]>

---------

Signed-off-by: Reza Abbasalipour <[email protected]>
  • Loading branch information
rapour authored and nhennigan committed Feb 5, 2025
1 parent bae6ccc commit 0992199
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 4 deletions.
81 changes: 79 additions & 2 deletions src/k8s/pkg/k8sd/controllers/node_configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package controllers

import (
"context"
"crypto/rand"
"crypto/rsa"
"os"
"path/filepath"
Expand All @@ -10,6 +11,7 @@ import (

"github.com/canonical/k8s/pkg/client/kubernetes"
"github.com/canonical/k8s/pkg/k8sd/setup"
"github.com/canonical/k8s/pkg/k8sd/types"
"github.com/canonical/k8s/pkg/snap/mock"
snaputil "github.com/canonical/k8s/pkg/snap/util"
. "github.com/onsi/gomega"
Expand All @@ -26,11 +28,19 @@ func TestConfigPropagation(t *testing.T) {

g := NewWithT(t)

privKey, err := rsa.GenerateKey(rand.Reader, 4096)
g.Expect(err).To(Not(HaveOccurred()))

wrongPrivKey, err := rsa.GenerateKey(rand.Reader, 4096)
g.Expect(err).To(Not(HaveOccurred()))

tests := []struct {
name string
configmap *corev1.ConfigMap
expectArgs map[string]string
expectRestart bool
privKey *rsa.PrivateKey
pubKey *rsa.PublicKey
}{
{
name: "Initial",
Expand Down Expand Up @@ -110,6 +120,62 @@ func TestConfigPropagation(t *testing.T) {
"--cloud-provider": "provider",
},
},
{
name: "WithSignature",
configmap: &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "k8sd-config", Namespace: "kube-system"},
Data: map[string]string{
"cluster-dns": "10.152.1.1",
"cluster-domain": "test-cluster.local",
"cloud-provider": "provider",
},
},
expectArgs: map[string]string{
"--cluster-dns": "10.152.1.1",
"--cluster-domain": "test-cluster.local",
"--cloud-provider": "provider",
},
privKey: privKey,
pubKey: &privKey.PublicKey,
expectRestart: true,
},
{
name: "MissingPrivKey",
configmap: &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "k8sd-config", Namespace: "kube-system"},
Data: map[string]string{
"cluster-dns": "10.152.1.1",
"cluster-domain": "test-cluster2.local",
"cloud-provider": "provider",
},
},
expectArgs: map[string]string{
"--cluster-dns": "10.152.1.1",
"--cluster-domain": "test-cluster.local",
"--cloud-provider": "provider",
},
pubKey: &privKey.PublicKey,
expectRestart: false,
},
{
name: "InvalidSignature",
configmap: &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "k8sd-config", Namespace: "kube-system"},
Data: map[string]string{
"cluster-dns": "10.152.1.1",
"cluster-domain": "test-cluster2.local",
"cloud-provider": "provider",
},
},
expectArgs: map[string]string{
"--cluster-dns": "10.152.1.1",
"--cluster-domain": "test-cluster.local",
"--cloud-provider": "provider",
},
privKey: wrongPrivKey,
pubKey: &privKey.PublicKey,
expectRestart: false,
},
}

clientset := fake.NewSimpleClientset()
Expand All @@ -129,8 +195,9 @@ func TestConfigPropagation(t *testing.T) {

ctrl := NewNodeConfigurationController(s, func() {})

// TODO: add test with signing key
go ctrl.Run(ctx, func(ctx context.Context) (*rsa.PublicKey, error) { return nil, nil })
keyCh := make(chan *rsa.PublicKey)

go ctrl.Run(ctx, func(ctx context.Context) (*rsa.PublicKey, error) { return <-keyCh, nil })
defer watcher.Stop()

for _, tc := range tests {
Expand All @@ -139,8 +206,18 @@ func TestConfigPropagation(t *testing.T) {

g := NewWithT(t)

if tc.privKey != nil {
kubelet, err := types.KubeletFromConfigMap(tc.configmap.Data, nil)
g.Expect(err).To(Not(HaveOccurred()))

tc.configmap.Data, err = kubelet.ToConfigMap(tc.privKey)
g.Expect(err).To(Not(HaveOccurred()))
}

watcher.Add(tc.configmap)

keyCh <- tc.pubKey

// TODO: this is to ensure that the controller has handled the event. This should ideally
// be replaced with something like a "<-sentCh" instead
time.Sleep(100 * time.Millisecond)
Expand Down
33 changes: 31 additions & 2 deletions src/k8s/pkg/k8sd/controllers/update_node_configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package controllers_test

import (
"context"
"crypto/rsa"
"os"
"path/filepath"
"testing"
Expand All @@ -12,13 +13,19 @@ import (
"github.com/canonical/k8s/pkg/k8sd/types"
"github.com/canonical/k8s/pkg/snap/mock"
"github.com/canonical/k8s/pkg/utils"
pkiutil "github.com/canonical/k8s/pkg/utils/pki"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)

func TestUpdateNodeConfigurationController(t *testing.T) {
g := NewWithT(t)

privPEM, pubPEM, err := pkiutil.GenerateRSAKey(2048)
g.Expect(err).To(Not(HaveOccurred()))

testCases := []struct {
name string
initialConfig types.ClusterConfig
Expand All @@ -35,6 +42,20 @@ func TestUpdateNodeConfigurationController(t *testing.T) {
},
expectedFailure: false,
},
{
name: "ControlPlane_DefaultConfig_WithClusterConfigurationKeys",
initialConfig: types.ClusterConfig{},
expectedConfig: types.ClusterConfig{
Kubelet: types.Kubelet{
ClusterDomain: utils.Pointer("cluster.local"),
},
Certificates: types.Certificates{
K8sdPublicKey: utils.Pointer(pubPEM),
K8sdPrivateKey: utils.Pointer(privPEM),
},
},
expectedFailure: false,
},
{
name: "ControlPlane_EmptyConfig",
initialConfig: types.ClusterConfig{},
Expand All @@ -51,7 +72,6 @@ func TestUpdateNodeConfigurationController(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

// TODO: add tests with a signed configmap
configProvider := &configProvider{config: tc.expectedConfig}
kubeletConfigMap, err := tc.initialConfig.Kubelet.ToConfigMap(nil)
g.Expect(err).ToNot(HaveOccurred())
Expand Down Expand Up @@ -94,7 +114,16 @@ func TestUpdateNodeConfigurationController(t *testing.T) {

result, err := clientset.CoreV1().ConfigMaps("kube-system").Get(ctx, "k8sd-config", metav1.GetOptions{})
g.Expect(err).ToNot(HaveOccurred())
expectedConfigMap, err := tc.expectedConfig.Kubelet.ToConfigMap(nil)

var priv *rsa.PrivateKey
if tc.expectedConfig.Certificates.K8sdPrivateKey != nil {
privKey, err := pkiutil.LoadRSAPrivateKey(tc.expectedConfig.Certificates.GetK8sdPrivateKey())
g.Expect(err).To(Not(HaveOccurred()))

priv = privKey
}

expectedConfigMap, err := tc.expectedConfig.Kubelet.ToConfigMap(priv)
g.Expect(err).ToNot(HaveOccurred())
if tc.expectedFailure {
g.Expect(result.Data).ToNot(Equal(expectedConfigMap))
Expand Down

0 comments on commit 0992199

Please sign in to comment.