From 23061f9f71defbdee65afd0c4a41b5d2d2d874df Mon Sep 17 00:00:00 2001 From: Johannes Malsam Date: Tue, 1 Aug 2023 16:36:28 +0200 Subject: [PATCH] initialize cipher --- fleetshard/config/config.go | 33 ++++++- .../pkg/central/reconciler/reconciler.go | 2 + .../pkg/central/reconciler/reconciler_test.go | 90 ++++++++++++++----- fleetshard/pkg/cipher/cipher.go | 71 ++++++--------- fleetshard/pkg/cipher/cipher_test.go | 38 +------- fleetshard/pkg/runtime/runtime.go | 9 +- 6 files changed, 143 insertions(+), 100 deletions(-) diff --git a/fleetshard/config/config.go b/fleetshard/config/config.go index 09be6494a4..3a1b9a87a6 100644 --- a/fleetshard/config/config.go +++ b/fleetshard/config/config.go @@ -10,6 +10,13 @@ import ( "github.com/pkg/errors" ) +const ( + // EnvProd is the expected value of the environment variable "ENVIRONMENT" for prod deployments of fleetshard-sync + EnvProd = "prod" + // EnvStage is the expected value of the environment variable "ENVIRONMENT" for stage deployments of fleetshard-sync + EnvStage = "stage" +) + // Config contains this application's runtime configuration. type Config struct { FleetManagerEndpoint string `env:"FLEET_MANAGER_ENDPOINT" envDefault:"http://127.0.0.1:8000"` @@ -29,8 +36,9 @@ type Config struct { EgressProxyImage string `env:"EGRESS_PROXY_IMAGE"` BaseCrdURL string `env:"BASE_CRD_URL" envDefault:"https://raw.githubusercontent.com/stackrox/stackrox/%s/operator/bundle/manifests/"` - ManagedDB ManagedDB - Telemetry Telemetry + ManagedDB ManagedDB + Telemetry Telemetry + SecretEncryption SecretEncryption } // ManagedDB for configuring managed DB specific parameters @@ -47,6 +55,12 @@ type Telemetry struct { StorageKey string `env:"TELEMETRY_STORAGE_KEY"` } +// SecretEncryption defines paramaters to configure encryption of tenant secrest +type SecretEncryption struct { + Type string `env:"SECRET_ENCRYPTION_TYPE" envDefault:"local"` + KeyID string `env:"SECRET_ENCRYPTION_KEY_ID"` +} + // GetConfig retrieves the current runtime configuration from the environment and returns it. func GetConfig() (*Config, error) { c := Config{} @@ -65,6 +79,7 @@ func GetConfig() (*Config, error) { configErrors.AddError(errors.New("AUTH_TYPE unset in the environment")) } validateManagedDBConfig(c, &configErrors) + validateSecretEncryptionConfig(c, &configErrors) cfgErr := configErrors.ToError() if cfgErr != nil { @@ -81,3 +96,17 @@ func validateManagedDBConfig(c Config, configErrors *errorhelpers.ErrorList) { configErrors.AddError(errors.New("MANAGED_DB_ENABLED == true and MANAGED_DB_SECURITY_GROUP unset in the environment")) } } + +func validateSecretEncryptionConfig(c Config, configErrors *errorhelpers.ErrorList) { + if !isDevEnvironment(c) && c.SecretEncryption.Type == "local" { + configErrors.AddError(errors.New("SECRET_ENCRYPTION_TYPE == local not allowed for non dev environments")) // pragma: allowlist secret + } + + if c.SecretEncryption.Type == "kms" && c.SecretEncryption.KeyID == "" { + configErrors.AddError(errors.New("SECRET_ENCRYPTION_TYPE == kms and SECRET_ENCRYPTION_KEY_ID unset in the environment")) // pragma: allowlist secret + } +} + +func isDevEnvironment(c Config) bool { + return c.Environment != EnvProd && c.Environment != EnvStage +} diff --git a/fleetshard/pkg/central/reconciler/reconciler.go b/fleetshard/pkg/central/reconciler/reconciler.go index fdc4184463..d2da9b21de 100644 --- a/fleetshard/pkg/central/reconciler/reconciler.go +++ b/fleetshard/pkg/central/reconciler/reconciler.go @@ -1223,6 +1223,7 @@ var resourcesChart = charts.MustGetChart("tenant-resources", nil) // NewCentralReconciler ... func NewCentralReconciler(k8sClient ctrlClient.Client, central private.ManagedCentral, managedDBProvisioningClient cloudprovider.DBClient, managedDBInitFunc postgres.CentralDBInitFunc, + secretCipher cipher.Cipher, opts CentralReconcilerOptions, ) *CentralReconciler { return &CentralReconciler{ @@ -1233,6 +1234,7 @@ func NewCentralReconciler(k8sClient ctrlClient.Client, central private.ManagedCe wantsAuthProvider: opts.WantsAuthProvider, routeService: k8s.NewRouteService(k8sClient), secretService: k8s.NewSecretService(k8sClient), + secretCipher: secretCipher, // pragma: allowlist secret egressProxyImage: opts.EgressProxyImage, telemetry: opts.Telemetry, clusterName: opts.ClusterName, diff --git a/fleetshard/pkg/central/reconciler/reconciler_test.go b/fleetshard/pkg/central/reconciler/reconciler_test.go index 1645ec3d35..9621097eda 100644 --- a/fleetshard/pkg/central/reconciler/reconciler_test.go +++ b/fleetshard/pkg/central/reconciler/reconciler_test.go @@ -4,13 +4,14 @@ import ( "context" "embed" "fmt" + "testing" + "time" + "github.com/stackrox/rox/pkg/utils" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" "sigs.k8s.io/controller-runtime/pkg/client/fake" - "testing" - "time" "github.com/aws/aws-sdk-go/aws/credentials/stscreds" @@ -22,6 +23,7 @@ import ( "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/central/cloudprovider" "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/central/cloudprovider/awsclient" "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/central/postgres" + "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/cipher" "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/k8s" "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/testutils" "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/util" @@ -90,12 +92,19 @@ func conditionForType(conditions []private.DataPlaneClusterUpdateStatusRequestCo return nil, false } +func createBase64Cipher(t *testing.T) cipher.Cipher { + b64Cipher, err := cipher.NewLocalBase64Cipher() + require.NoError(t, err, "creating base64 cipher for tests") + return b64Cipher +} + func TestReconcileCreate(t *testing.T) { fakeClient := testutils.NewFakeClientBuilder(t).Build() r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), CentralReconcilerOptions{ClusterName: clusterName, Environment: environment, UseRoutes: true}, ) @@ -145,7 +154,12 @@ func TestReconcileCreateWithManagedDB(t *testing.T) { return connection, nil } - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, managedDBProvisioningClient, centralDBInitFunc, + r := NewCentralReconciler( + fakeClient, + private.ManagedCentral{}, + managedDBProvisioningClient, + centralDBInitFunc, + createBase64Cipher(t), CentralReconcilerOptions{ UseRoutes: true, ManagedDBEnabled: true, @@ -180,6 +194,7 @@ func TestReconcileCreateWithLabelOperatorVersion(t *testing.T) { t.Setenv(features.TargetedOperatorUpgrades.EnvVar(), "true") r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), CentralReconcilerOptions{ UseRoutes: true, }) @@ -215,6 +230,7 @@ func TestReconcileCreateWithManagedDBNoCredentials(t *testing.T) { require.NoError(t, err) r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, managedDBProvisioningClient, centralDBInitFunc, + createBase64Cipher(t), CentralReconcilerOptions{ UseRoutes: true, ManagedDBEnabled: true, @@ -235,7 +251,8 @@ func TestReconcileUpdateSucceeds(t *testing.T) { }, }, centralDeploymentObject()).Build() - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), CentralReconcilerOptions{}) status, err := r.Reconcile(context.TODO(), simpleManagedCentral) require.NoError(t, err) @@ -280,7 +297,9 @@ func TestReconcileLastHashSetOnSuccess(t *testing.T) { }, }, centralDeploymentObject()).Build() - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{}) managedCentral := simpleManagedCentral managedCentral.RequestStatus = centralConstants.CentralRequestStatusReady.String() @@ -312,7 +331,9 @@ func TestIgnoreCacheForCentralNotReady(t *testing.T) { }, }, centralDeploymentObject()).Build() - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{}) managedCentral := simpleManagedCentral managedCentral.RequestStatus = centralConstants.CentralRequestStatusProvisioning.String() @@ -337,7 +358,9 @@ func TestIgnoreCacheForCentralForceReconcileAlways(t *testing.T) { }, }, centralDeploymentObject()).Build() - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{}) managedCentral := simpleManagedCentral managedCentral.RequestStatus = centralConstants.CentralRequestStatusReady.String() @@ -356,7 +379,9 @@ func TestIgnoreCacheForCentralForceReconcileAlways(t *testing.T) { func TestReconcileDelete(t *testing.T) { fakeClient := testutils.NewFakeClientBuilder(t).Build() - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{UseRoutes: true}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{UseRoutes: true}) _, err := r.Reconcile(context.TODO(), simpleManagedCentral) require.NoError(t, err) @@ -389,7 +414,8 @@ func TestReconcileDelete(t *testing.T) { func TestDisablePauseAnnotation(t *testing.T) { fakeClient := testutils.NewFakeClientBuilder(t).Build() - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{UseRoutes: true}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), CentralReconcilerOptions{UseRoutes: true}) _, err := r.Reconcile(context.TODO(), simpleManagedCentral) require.NoError(t, err) @@ -428,6 +454,7 @@ func TestReconcileDeleteWithManagedDB(t *testing.T) { } r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, managedDBProvisioningClient, centralDBInitFunc, + createBase64Cipher(t), CentralReconcilerOptions{ UseRoutes: true, ManagedDBEnabled: true, @@ -512,7 +539,9 @@ func TestCentralChanged(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - reconciler := NewCentralReconciler(fakeClient, test.currentCentral, nil, centralDBInitFunc, CentralReconcilerOptions{}) + reconciler := NewCentralReconciler(fakeClient, test.currentCentral, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{}) if test.lastCentral != nil { err := reconciler.setLastCentralHash(*test.lastCentral) @@ -528,7 +557,9 @@ func TestCentralChanged(t *testing.T) { func TestNamespaceLabelsAreSet(t *testing.T) { fakeClient := testutils.NewFakeClientBuilder(t).Build() - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{UseRoutes: true}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{UseRoutes: true}) _, err := r.Reconcile(context.TODO(), simpleManagedCentral) require.NoError(t, err) @@ -542,7 +573,9 @@ func TestNamespaceLabelsAreSet(t *testing.T) { func TestReportRoutesStatuses(t *testing.T) { fakeClient := testutils.NewFakeClientBuilder(t).Build() - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{UseRoutes: true}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{UseRoutes: true}) status, err := r.Reconcile(context.TODO(), simpleManagedCentral) require.NoError(t, err) @@ -568,7 +601,9 @@ func TestChartResourcesAreAddedAndRemoved(t *testing.T) { require.NoError(t, err) fakeClient := testutils.NewFakeClientBuilder(t).Build() - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{}) r.resourcesChart = chart _, err = r.Reconcile(context.TODO(), simpleManagedCentral) @@ -601,7 +636,9 @@ func TestChartResourcesAreAddedAndUpdated(t *testing.T) { require.NoError(t, err) fakeClient := testutils.NewFakeClientBuilder(t).Build() - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{}) r.resourcesChart = chart _, err = r.Reconcile(context.TODO(), simpleManagedCentral) @@ -632,7 +669,9 @@ func TestChartResourcesAreAddedAndUpdated(t *testing.T) { func TestEgressProxyIsDeployed(t *testing.T) { fakeClient := testutils.NewFakeClientBuilder(t).Build() - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{}) _, err := r.Reconcile(context.TODO(), simpleManagedCentral) require.NoError(t, err) @@ -683,6 +722,7 @@ func TestEgressProxyIsDeployed(t *testing.T) { func TestEgressProxyCustomImage(t *testing.T) { fakeClient := testutils.NewFakeClientBuilder(t).Build() r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), CentralReconcilerOptions{ EgressProxyImage: "registry.redhat.io/openshift4/ose-egress-http-proxy:version-for-test", }) @@ -709,7 +749,9 @@ func TestEgressProxyCustomImage(t *testing.T) { func TestNoRoutesSentWhenOneNotCreated(t *testing.T) { fakeClient, tracker := testutils.NewFakeClientWithTracker(t) tracker.AddRouteError(centralReencryptRouteName, errors.New("fake error")) - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{UseRoutes: true}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{UseRoutes: true}) _, err := r.Reconcile(context.TODO(), simpleManagedCentral) require.Errorf(t, err, "fake error") } @@ -717,7 +759,9 @@ func TestNoRoutesSentWhenOneNotCreated(t *testing.T) { func TestNoRoutesSentWhenOneNotAdmitted(t *testing.T) { fakeClient, tracker := testutils.NewFakeClientWithTracker(t) tracker.SetRouteAdmitted(centralReencryptRouteName, false) - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{UseRoutes: true}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{UseRoutes: true}) _, err := r.Reconcile(context.TODO(), simpleManagedCentral) require.Errorf(t, err, "unable to find admitted ingress") } @@ -725,7 +769,9 @@ func TestNoRoutesSentWhenOneNotAdmitted(t *testing.T) { func TestNoRoutesSentWhenOneNotCreatedYet(t *testing.T) { fakeClient, tracker := testutils.NewFakeClientWithTracker(t) tracker.SetSkipRoute(centralReencryptRouteName, true) - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{UseRoutes: true}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{UseRoutes: true}) _, err := r.Reconcile(context.TODO(), simpleManagedCentral) require.Errorf(t, err, "unable to find admitted ingress") } @@ -759,7 +805,9 @@ func TestTelemetryOptionsAreSetInCR(t *testing.T) { for _, tc := range tt { t.Run(tc.testName, func(t *testing.T) { fakeClient := testutils.NewFakeClientBuilder(t).Build() - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{Telemetry: tc.telemetry}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{Telemetry: tc.telemetry}) _, err := r.Reconcile(context.TODO(), simpleManagedCentral) require.NoError(t, err) @@ -819,7 +867,9 @@ func TestReconcileUpdatesRoutes(t *testing.T) { for _, tc := range tt { t.Run(tc.testName, func(t *testing.T) { fakeClient := testutils.NewFakeClientBuilder(t).Build() - r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, CentralReconcilerOptions{UseRoutes: true}) + r := NewCentralReconciler(fakeClient, private.ManagedCentral{}, nil, centralDBInitFunc, + createBase64Cipher(t), + CentralReconcilerOptions{UseRoutes: true}) r.routeService = k8s.NewRouteService(fakeClient) central := simpleManagedCentral diff --git a/fleetshard/pkg/cipher/cipher.go b/fleetshard/pkg/cipher/cipher.go index db86d8021f..f9a6f28220 100644 --- a/fleetshard/pkg/cipher/cipher.go +++ b/fleetshard/pkg/cipher/cipher.go @@ -2,11 +2,10 @@ package cipher import ( - "crypto/aes" - "crypto/cipher" - "crypto/rand" + "encoding/base64" "fmt" - "io" + + "github.com/stackrox/acs-fleet-manager/fleetshard/config" ) const keySize = 32 @@ -19,58 +18,44 @@ type Cipher interface { Decrypt(ciphertext []byte) ([]byte, error) } -// LocalAES256Cipher implements encryption and decryption using AES256 GCM -type LocalAES256Cipher struct { - aesgcm cipher.AEAD -} +// NewCipher returns a new object implementing cipher, based on the Type defined in config +func NewCipher(config *config.Config) (Cipher, error) { + encryptionType := config.SecretEncryption.Type -// NewLocalAES256Cipher returns a new Cipher using the given key -func NewLocalAES256Cipher(key []byte) (Cipher, error) { - if len(key) != 32 { - return nil, fmt.Errorf("creating AES256Cipher, key does not match required lenght of %d", keySize) + if encryptionType == "local" { + return NewLocalBase64Cipher() } - block, err := aes.NewCipher(key) - if err != nil { - return nil, fmt.Errorf("creating cipher block: %s", err) + if encryptionType == "kms" { + return NewKMSCipher(config.SecretEncryption.KeyID) } - aesgcm, err := cipher.NewGCM(block) - if err != nil { - return nil, fmt.Errorf("creating AES GCM cipher %s", err) - } - - return LocalAES256Cipher{aesgcm: aesgcm}, nil + return nil, fmt.Errorf("no Cipher implementation for SecretEncryption.Type: %s", encryptionType) } -var _ Cipher = LocalAES256Cipher{} - -// Encrypt implementes the logic to encrypt plaintext -func (a LocalAES256Cipher) Encrypt(plaintext []byte) ([]byte, error) { - - nonce := make([]byte, a.aesgcm.NonceSize()) - if _, err := io.ReadFull(rand.Reader, nonce); err != nil { - return nil, fmt.Errorf("generating nonce for encryption %v", err) - } +// LocalBase64Cipher simulates encryption by using base64 encoding and decoding +// Warning: Only use this for development it does not encrypt data +type LocalBase64Cipher struct { +} - ciphertext := a.aesgcm.Seal(nil, nonce, plaintext, nil) +// NewLocalBase64Cipher returns a new Cipher using the given key +func NewLocalBase64Cipher() (Cipher, error) { + return LocalBase64Cipher{}, nil +} - // append nonce to ciphertext so decrypt can use it - ciphertext = append(ciphertext, nonce...) +var _ Cipher = LocalBase64Cipher{} - return ciphertext, nil +// Encrypt implementes the logic to encode plaintext with base64 +func (a LocalBase64Cipher) Encrypt(plaintext []byte) ([]byte, error) { + enc := base64.StdEncoding.EncodeToString(plaintext) + return []byte(enc), nil } -// Decrypt implements the logic to decrypt ciphertext, it assumes -// a nonce has been apended to ciphertext at encryption -func (a LocalAES256Cipher) Decrypt(ciphertext []byte) ([]byte, error) { - nonceIndex := len(ciphertext) - a.aesgcm.NonceSize() - cipher, nonce := ciphertext[:nonceIndex], ciphertext[nonceIndex:] - - plaintext, err := a.aesgcm.Open(nil, nonce, cipher, nil) +// Decrypt implements the logic to decode base64 text to plaintext +func (a LocalBase64Cipher) Decrypt(ciphertext []byte) ([]byte, error) { + plaintext, err := base64.StdEncoding.DecodeString(string(ciphertext)) if err != nil { - return nil, fmt.Errorf("decrypting ciphertext: %v", err) + return nil, fmt.Errorf("decoding base64 string %v", err) } - return plaintext, nil } diff --git a/fleetshard/pkg/cipher/cipher_test.go b/fleetshard/pkg/cipher/cipher_test.go index a165e6a329..3d10f09c59 100644 --- a/fleetshard/pkg/cipher/cipher_test.go +++ b/fleetshard/pkg/cipher/cipher_test.go @@ -1,51 +1,21 @@ package cipher import ( - "crypto/rand" - "io" "testing" "github.com/stretchr/testify/require" ) -func generateKey() ([]byte, error) { - key := make([]byte, 32) - if _, err := io.ReadFull(rand.Reader, key); err != nil { - return nil, err - } - - return key, nil -} - -// TestDifferentCipherForSamePlaintext tests the correct usage of nonce -// to ensure encrypting the same plaintext twice does not yield the same cipher text -func TestDifferentCipherForSamePlaintext(t *testing.T) { - plaintext := []byte("test plaintext") - key, err := generateKey() - require.NoError(t, err, "generating key") - - aes, err := NewLocalAES256Cipher(key) - require.NoError(t, err, "creating cipher") - cipher1, err := aes.Encrypt(plaintext) - require.NoError(t, err, "encrypting first plaintext") - cipher2, err := aes.Encrypt(plaintext) - require.NoError(t, err, "encrypting second plaintext") - - require.NotEqual(t, cipher1, cipher2, "encrypting same text twice yields same result") -} - -func TestEncryptDecryptMatch(t *testing.T) { +func TestEncryptDecryptMatchForB64Cipher(t *testing.T) { plaintext := []byte("test plaintext") - key, err := generateKey() - require.NoError(t, err, "generating key") - aes, err := NewLocalAES256Cipher(key) + b64Cipher, err := NewLocalBase64Cipher() require.NoError(t, err, "creating cipher") - cipher, err := aes.Encrypt(plaintext) + cipher, err := b64Cipher.Encrypt(plaintext) require.NoError(t, err, "encyrpting plaintext") - decrypted, err := aes.Decrypt(cipher) + decrypted, err := b64Cipher.Decrypt(cipher) require.NoError(t, err, "decrypting ciphertext") require.Equal(t, string(plaintext), string(decrypted), "decrypted string does not match plaintext") diff --git a/fleetshard/pkg/runtime/runtime.go b/fleetshard/pkg/runtime/runtime.go index e7a6774866..755c3fdc6a 100644 --- a/fleetshard/pkg/runtime/runtime.go +++ b/fleetshard/pkg/runtime/runtime.go @@ -14,6 +14,7 @@ import ( "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/central/operator" "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/central/postgres" centralReconciler "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/central/reconciler" + "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/cipher" "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/fleetshardmetrics" "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/k8s" "github.com/stackrox/acs-fleet-manager/internal/dinosaur/pkg/api/private" @@ -52,6 +53,7 @@ type Runtime struct { dbProvisionClient cloudprovider.DBClient statusResponseCh chan private.DataPlaneCentralStatus operatorManager *operator.ACSOperatorManager + secretCipher cipher.Cipher } // NewRuntime creates a new runtime @@ -89,6 +91,10 @@ func NewRuntime(config *config.Config, k8sClient ctrlClient.Client) (*Runtime, e } operatorManager := operator.NewACSOperatorManager(k8sClient, config.BaseCrdURL) + secretCipher, err := cipher.NewCipher(config) + if err != nil { + return nil, fmt.Errorf("creating secretCipher: %v", err) + } return &Runtime{ config: config, @@ -98,6 +104,7 @@ func NewRuntime(config *config.Config, k8sClient ctrlClient.Client) (*Runtime, e dbProvisionClient: dbProvisionClient, reconcilers: make(reconcilerRegistry), operatorManager: operatorManager, + secretCipher: secretCipher, // pragma: allowlist secret }, nil } @@ -145,7 +152,7 @@ func (r *Runtime) Start() error { for _, central := range list.Items { if _, ok := r.reconcilers[central.Id]; !ok { r.reconcilers[central.Id] = centralReconciler.NewCentralReconciler(r.k8sClient, central, - r.dbProvisionClient, postgres.InitializeDatabase, reconcilerOpts) + r.dbProvisionClient, postgres.InitializeDatabase, r.secretCipher, reconcilerOpts) } reconciler := r.reconcilers[central.Id]