...

Source file src/edge-infra.dev/pkg/edge/iam/ctl/encryptionctl/encryption_secret_controller_test.go

Documentation: edge-infra.dev/pkg/edge/iam/ctl/encryptionctl

     1  package encryptionctl_test
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"testing"
     7  	"time"
     8  
     9  	corev1 "k8s.io/api/core/v1"
    10  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    11  	"k8s.io/apimachinery/pkg/types"
    12  	ctrl "sigs.k8s.io/controller-runtime"
    13  
    14  	"github.com/stretchr/testify/suite"
    15  	"k8s.io/apimachinery/pkg/runtime"
    16  	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    17  
    18  	api "edge-infra.dev/pkg/edge/iam/api/v1alpha1"
    19  	"edge-infra.dev/pkg/lib/fog"
    20  
    21  	"edge-infra.dev/pkg/edge/iam/ctl/encryptionctl"
    22  	"edge-infra.dev/pkg/edge/iam/ctl/providerctl"
    23  	"edge-infra.dev/pkg/k8s/runtime/controller"
    24  	"edge-infra.dev/test"
    25  	"edge-infra.dev/test/framework"
    26  	"edge-infra.dev/test/framework/k8s"
    27  	"edge-infra.dev/test/framework/k8s/envtest"
    28  )
    29  
    30  // test predicate when secret added
    31  // test updateStatus
    32  
    33  // we already test the updating of the databases in
    34  // pkg/edge/iam/crypto/encryption_key_rotation_test.go
    35  // so this just tests that the created secret triggers a reconciliation loop
    36  
    37  // bazel test pkg/edge/iam/ctl/encryptionctl:encryptionctl_test
    38  type Suite struct {
    39  	*framework.Framework
    40  	*k8s.K8s
    41  	ctx     context.Context
    42  	timeout time.Duration
    43  	tick    time.Duration
    44  }
    45  
    46  func TestEncryptionReconcilerSetup(t *testing.T) {
    47  	// set env variables
    48  	os.Setenv("IAM_CLUSTER_ID", "123")
    49  	os.Setenv("IAM_ENCRYPTION_ENABLED", "true")
    50  
    51  	// setup
    52  	testEnv := envtest.Setup()
    53  	cfg, opts := controller.ProcessOptions(controller.WithCfg(testEnv.Config), controller.WithMetricsAddress("0"))
    54  	opts.Scheme = createScheme()
    55  	ctrl.SetLogger(fog.New())
    56  	mgr, err := ctrl.NewManager(cfg, opts)
    57  	if err != nil {
    58  		t.Errorf("unable to create  manager: %v", err)
    59  	}
    60  
    61  	f := framework.New("providerctl").Component("providerctl")
    62  	s := &Suite{
    63  		Framework: f,
    64  		ctx:       context.Background(),
    65  		timeout:   10 * time.Second,
    66  		tick:      50 * time.Millisecond,
    67  	}
    68  	// create provider reconciler
    69  	providerRec := &providerctl.ProviderReconciler{
    70  		Name:   "provider-controller",
    71  		Client: mgr.GetClient(),
    72  		Scheme: mgr.GetScheme(),
    73  	}
    74  	err = providerRec.SetupWithManager(mgr)
    75  	test.NoError(err)
    76  
    77  	// create encryption reconciler
    78  	encryptionRec := &encryptionctl.EncryptionSecretReconciler{
    79  		Name:   "encryption-secret-controller",
    80  		Client: mgr.GetClient(),
    81  	}
    82  	err = encryptionRec.SetupWithManager(mgr)
    83  	test.NoError(err)
    84  
    85  	k := k8s.New(testEnv.Config, k8s.WithCtrlManager(mgr), k8s.WithKonfigKonnector())
    86  	s.K8s = k
    87  
    88  	f.Register(k)
    89  
    90  	suite.Run(t, s)
    91  
    92  	t.Cleanup(func() {
    93  		f.NoError(testEnv.Stop())
    94  	})
    95  }
    96  
    97  func (s *Suite) TestEncryptionSecretReconciler() {
    98  	// create edge-iam ns
    99  	namespace := &corev1.Namespace{
   100  		TypeMeta: metav1.TypeMeta{
   101  			Kind:       "Namespace",
   102  			APIVersion: "v1",
   103  		},
   104  		ObjectMeta: metav1.ObjectMeta{
   105  			Name: "edge-iam",
   106  		},
   107  	}
   108  	s.Require().NoError(s.Client.Create(s.ctx, namespace))
   109  
   110  	// create private-key-secret
   111  	secret := &corev1.Secret{}
   112  	secret.ObjectMeta = metav1.ObjectMeta{
   113  		Name:      "private-key-secret",
   114  		Namespace: "edge-iam",
   115  	}
   116  	secret.Data = map[string][]byte{
   117  		"private_key":    []byte("key"),
   118  		"private_key_id": []byte("key-id"),
   119  	}
   120  	s.Require().NoError(s.Client.Create(s.ctx, secret))
   121  
   122  	// create challenge-secret
   123  	challengeSecret := &corev1.Secret{}
   124  	challengeSecret.ObjectMeta = metav1.ObjectMeta{
   125  		Name:      "challenge-secret",
   126  		Namespace: "edge-iam",
   127  	}
   128  	challengeSecret.Data = map[string][]byte{
   129  		"secret": []byte("secret"),
   130  	}
   131  	s.Require().NoError(s.Client.Create(s.ctx, challengeSecret))
   132  
   133  	// create initial provider obj w/ v1
   134  	provider := createProviderObj("1", "1")
   135  	s.Require().NoError(s.Client.Create(s.ctx, provider))
   136  
   137  	// then create secret that would be created by External Secrets
   138  	encryptionSecret := getSecret()
   139  	s.Require().NoError(s.Client.Create(s.ctx, encryptionSecret.DeepCopy()))
   140  
   141  	// get provider to see if status is updated
   142  	providerObj := &api.Provider{}
   143  	s.Require().Eventually(func() bool {
   144  		err := s.Client.Get(s.ctx, types.NamespacedName{
   145  			Name:      "provider",
   146  			Namespace: "edge-iam",
   147  		}, providerObj)
   148  		return err == nil
   149  	}, s.timeout, s.tick, "expected provider object was never found")
   150  
   151  	// confirm status has the correct message
   152  	for _, status := range providerObj.Status.Conditions {
   153  		if status.Reason == "EncryptionRotationSucceeded" {
   154  			s.Require().Equal(status.Message, "successfully updated databases to version: 1")
   155  		}
   156  	}
   157  }
   158  
   159  func getSecret() corev1.Secret {
   160  	secret := corev1.Secret{
   161  		TypeMeta: metav1.TypeMeta{
   162  			Kind:       "Secret",
   163  			APIVersion: "v1",
   164  		},
   165  		ObjectMeta: metav1.ObjectMeta{
   166  			Name:      "id-encryption-key-1",
   167  			Namespace: "edge-iam",
   168  		},
   169  		Data: map[string][]byte{
   170  			"key": []byte("my-32bit-super-extra-secret-key!"),
   171  		},
   172  	}
   173  	return secret
   174  }
   175  
   176  func createProviderObj(specVersion string, statusVersion string) *api.Provider {
   177  	statusMessage := "successfully updated databases to version: " + statusVersion
   178  	providerObj := &api.Provider{
   179  		TypeMeta: metav1.TypeMeta{
   180  			APIVersion: "iam.edge-infra.dev/v1alpha1",
   181  			Kind:       "Provider",
   182  		},
   183  		ObjectMeta: metav1.ObjectMeta{
   184  			Name:      "provider",
   185  			Namespace: "edge-iam",
   186  		},
   187  		Spec: api.ProviderSpec{
   188  			Encryption: api.EncryptionFields{
   189  				Version: specVersion,
   190  			},
   191  			Issuer: "http://localhost:8080",
   192  			Target: "kind",
   193  		},
   194  		Status: api.ProviderStatus{
   195  			Conditions: []metav1.Condition{
   196  				{
   197  					Type:    "DatabaseUpdated",
   198  					Status:  metav1.ConditionTrue,
   199  					Reason:  "EncryptionRotationSucceeded",
   200  					Message: statusMessage,
   201  				},
   202  			},
   203  		},
   204  	}
   205  	return providerObj
   206  }
   207  
   208  func createScheme() *runtime.Scheme {
   209  	scheme := runtime.NewScheme()
   210  	utilruntime.Must(api.AddToScheme(scheme))
   211  	utilruntime.Must(corev1.AddToScheme(scheme))
   212  	return scheme
   213  }
   214  

View as plain text