Skip to content

Commit 47f7748

Browse files
authored
Try different configuration for S3 SSE-C (#363)
* Try different configuration for S3 SSE-C * Switch to pod_environment_secret * Move sensitive information to Secret, leave everything else in ConfigMap * Disable linter as this is not the actual secret * Test ConfigMap and Secret at the same time * Read wal_g encryption key from central secret
1 parent 17b9212 commit 47f7748

File tree

3 files changed

+133
-14
lines changed

3 files changed

+133
-14
lines changed

controllers/postgres_controller.go

Lines changed: 85 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ const (
5353
postgresExporterServiceProjectIDAnnotationName string = pg.ProjectIDLabelName
5454
storageEncryptionKeyName string = "storage-encryption-key"
5555
storageEncryptionKeyFinalizerName string = "postgres.database.fits.cloud/secret-finalizer"
56+
walGEncryptionSecretNamePostfix string = "-walg-encryption"
57+
walGEncryptionSecretKeyName string = "key"
5658
)
5759

5860
// requeue defines in how many seconds a requeue should happen
@@ -80,6 +82,8 @@ type PostgresReconciler struct {
8082
PatroniLoopWait uint32
8183
PatroniRetryTimeout uint32
8284
EnableRandomStorageEncryptionSecret bool
85+
EnableWalGEncryption bool
86+
PostgresletFullname string
8387
}
8488

8589
// Reconcile is the entry point for postgres reconciliation.
@@ -403,6 +407,10 @@ func (r *PostgresReconciler) ensureZalandoDependencies(ctx context.Context, p *p
403407
return fmt.Errorf("error while updating backup config: %w", err)
404408
}
405409

410+
if err := r.updatePodEnvironmentSecret(ctx, p); err != nil {
411+
return fmt.Errorf("error while updating backup config secret: %w", err)
412+
}
413+
406414
return nil
407415
}
408416

@@ -433,19 +441,12 @@ func (r *PostgresReconciler) updatePodEnvironmentConfigMap(ctx context.Context,
433441

434442
// use the rest as provided in the secret
435443
bucketName := backupConfig.S3BucketName
436-
awsAccessKeyID := backupConfig.S3AccessKey
437-
awsSecretAccessKey := backupConfig.S3SecretKey
438444
backupSchedule := backupConfig.Schedule
439445
backupNumToRetain := backupConfig.Retention
440446

441-
// s3 server side encryption SSE is enabled if the key is given
442-
// TODO our s3 needs a small change to make this work
447+
// s3 server side encryption SSE is disabled
448+
// we use client side encryption
443449
walgDisableSSE := "true"
444-
walgSSE := ""
445-
if backupConfig.S3EncryptionKey != nil {
446-
walgDisableSSE = "false"
447-
walgSSE = *backupConfig.S3EncryptionKey
448-
}
449450

450451
// create updated content for pod environment configmap
451452
data := map[string]string{
@@ -457,12 +458,9 @@ func (r *PostgresReconciler) updatePodEnvironmentConfigMap(ctx context.Context,
457458
"WALE_BACKUP_THRESHOLD_PERCENTAGE": "100",
458459
"AWS_ENDPOINT": awsEndpoint,
459460
"WALE_S3_ENDPOINT": walES3Endpoint, // same as above, but slightly modified
460-
"AWS_ACCESS_KEY_ID": awsAccessKeyID,
461-
"AWS_SECRET_ACCESS_KEY": awsSecretAccessKey,
462461
"AWS_S3_FORCE_PATH_STYLE": "true",
463462
"AWS_REGION": region, // now we can use AWS S3
464-
"WALG_DISABLE_S3_SSE": walgDisableSSE, // disable server side encryption if key is nil
465-
"WALG_S3_SSE": walgSSE, // server side encryption key
463+
"WALG_DISABLE_S3_SSE": walgDisableSSE, // server side encryption
466464
"BACKUP_SCHEDULE": backupSchedule,
467465
"BACKUP_NUM_TO_RETAIN": backupNumToRetain,
468466
}
@@ -491,6 +489,62 @@ func (r *PostgresReconciler) updatePodEnvironmentConfigMap(ctx context.Context,
491489
return nil
492490
}
493491

492+
func (r *PostgresReconciler) updatePodEnvironmentSecret(ctx context.Context, p *pg.Postgres) error {
493+
log := r.Log.WithValues("postgres", p.Name)
494+
if p.Spec.BackupSecretRef == "" {
495+
log.Info("No configured backupSecretRef found, skipping configuration of postgres backup")
496+
return nil
497+
}
498+
499+
backupConfig, err := r.getBackupConfig(ctx, p.Namespace, p.Spec.BackupSecretRef)
500+
if err != nil {
501+
return err
502+
}
503+
504+
awsAccessKeyID := backupConfig.S3AccessKey
505+
awsSecretAccessKey := backupConfig.S3SecretKey
506+
507+
// create updated content for pod environment configmap
508+
data := map[string][]byte{
509+
"AWS_ACCESS_KEY_ID": []byte(awsAccessKeyID),
510+
"AWS_SECRET_ACCESS_KEY": []byte(awsSecretAccessKey),
511+
}
512+
513+
// libsodium client side encryption key
514+
if r.EnableWalGEncryption {
515+
s, err := r.getWalGEncryptionSecret(ctx)
516+
if err != nil {
517+
return err
518+
}
519+
k, exists := s.Data[walGEncryptionSecretKeyName]
520+
if !exists {
521+
return fmt.Errorf("could not find key %v in secret %v/%v-%v", walGEncryptionSecretKeyName, r.PostgresletNamespace, r.PostgresletFullname, walGEncryptionSecretNamePostfix)
522+
}
523+
// libsodium keys are fixed-size keys of 32 bytes, see https://github.com/wal-g/wal-g#encryption
524+
if len(k) != 32 {
525+
return fmt.Errorf("wal_g encryption key must be exactly 32 bytes, got %v", len(k))
526+
}
527+
data["WALG_LIBSODIUM_KEY"] = k
528+
}
529+
530+
var s *corev1.Secret
531+
ns := types.NamespacedName{
532+
Name: operatormanager.PodEnvCMName,
533+
Namespace: p.ToPeripheralResourceNamespace(),
534+
}
535+
536+
if s, err = r.CreateOrGetPodEnvironmentSecret(ctx, ns.Namespace); err != nil {
537+
return fmt.Errorf("error while accessing the pod environment secret %v: %w", ns.Namespace, err)
538+
}
539+
540+
s.Data = data
541+
if err := r.SvcClient.Update(ctx, s); err != nil {
542+
return fmt.Errorf("error while updating the pod environment secret in service cluster: %w", err)
543+
}
544+
545+
return nil
546+
}
547+
494548
func (r *PostgresReconciler) isManagedByUs(obj *pg.Postgres) bool {
495549
if obj.Spec.PartitionID != r.PartitionID {
496550
return false
@@ -1206,6 +1260,24 @@ func (r *PostgresReconciler) deleteExporterSidecarService(ctx context.Context, n
12061260
return nil
12071261
}
12081262

1263+
func (r *PostgresReconciler) getWalGEncryptionSecret(ctx context.Context) (*corev1.Secret, error) {
1264+
1265+
ns := r.PostgresletNamespace
1266+
name := r.PostgresletFullname + walGEncryptionSecretNamePostfix
1267+
1268+
// fetch secret
1269+
s := &corev1.Secret{}
1270+
nn := types.NamespacedName{
1271+
Name: name,
1272+
Namespace: ns,
1273+
}
1274+
if err := r.SvcClient.Get(ctx, nn, s); err != nil {
1275+
return nil, fmt.Errorf("error while getting the backup secret from service cluster: %w", err)
1276+
}
1277+
1278+
return s, nil
1279+
}
1280+
12091281
func (r *PostgresReconciler) ensureStorageEncryptionSecret(ctx context.Context, instance *pg.Postgres) error {
12101282

12111283
if !r.EnableRandomStorageEncryptionSecret {

main.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ const (
7070
postgresletFullnameFlg = "postgreslet-fullname"
7171
enableLBSourceRangesFlg = "enable-lb-source-ranges"
7272
enableRandomStorageEncrytionSecretFlg = "enable-random-storage-encryption-secret"
73+
enableWalGEncryptionFlg = "enable-walg-encryption"
7374
)
7475

7576
var (
@@ -120,6 +121,7 @@ func main() {
120121
deployEtcd bool
121122
enableLBSourceRanges bool
122123
enableRandomStorageEncrytionSecret bool
124+
enableWalGEncryption bool
123125

124126
portRangeStart int
125127
portRangeSize int
@@ -250,6 +252,9 @@ func main() {
250252
viper.SetDefault(enableRandomStorageEncrytionSecretFlg, false)
251253
enableRandomStorageEncrytionSecret = viper.GetBool(enableRandomStorageEncrytionSecretFlg)
252254

255+
viper.SetDefault(enableWalGEncryptionFlg, false)
256+
enableWalGEncryption = viper.GetBool(enableWalGEncryptionFlg)
257+
253258
ctrl.SetLogger(zap.New(zap.UseDevMode(true)))
254259

255260
ctrl.Log.Info("flag",
@@ -284,9 +289,10 @@ func main() {
284289
etcdBackupSidecarImageFlg, etcdBackupSidecarImage,
285290
etcdBackupSecretNameFlg, etcdBackupSecretName,
286291
etcdPSPNameFlg, etcdPSPName,
287-
postgresletFullnameFlg, postgresletFullname,
288292
enableLBSourceRangesFlg, enableLBSourceRanges,
289293
enableRandomStorageEncrytionSecretFlg, enableRandomStorageEncrytionSecret,
294+
postgresletFullnameFlg, postgresletFullname,
295+
enableWalGEncryptionFlg, enableWalGEncryption,
290296
)
291297

292298
svcClusterConf := ctrl.GetConfigOrDie()
@@ -391,6 +397,8 @@ func main() {
391397
PatroniLoopWait: patroniLoopWait,
392398
PatroniRetryTimeout: patroniRetryTimeout,
393399
EnableRandomStorageEncryptionSecret: enableRandomStorageEncrytionSecret,
400+
EnableWalGEncryption: enableWalGEncryption,
401+
PostgresletFullname: postgresletFullname,
394402
}).SetupWithManager(ctrlPlaneClusterMgr); err != nil {
395403
setupLog.Error(err, "unable to create controller", "controller", "Postgres")
396404
os.Exit(1)

pkg/operatormanager/operatormanager.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ const (
3939
// PodEnvCMName Name of the pod environment configmap to create and use
4040
PodEnvCMName string = "postgres-pod-config"
4141

42+
// PodEnvSecretName Name of the pod environment secret to create and use
43+
PodEnvSecretName string = "postgres-pod-secret" //nolint:gosec
44+
4245
operatorPodLabelName string = "name"
4346
operatorPodLabelValue string = "postgres-operator"
4447

@@ -124,6 +127,11 @@ func (m *OperatorManager) InstallOrUpdateOperator(ctx context.Context, namespace
124127
return fmt.Errorf("error while creating pod environment configmap %v: %w", namespace, err)
125128
}
126129

130+
// Add our (initially empty) custom pod environment secret
131+
if _, err := m.CreateOrGetPodEnvironmentSecret(ctx, namespace); err != nil {
132+
return fmt.Errorf("error while creating pod environment secret %v: %w", namespace, err)
133+
}
134+
127135
// Add our sidecars configmap
128136
if err := m.createOrUpdateSidecarsConfig(ctx, namespace); err != nil {
129137
return fmt.Errorf("error while creating sidecars config %v: %w", namespace, err)
@@ -396,6 +404,8 @@ func (m *OperatorManager) editConfigMap(cm *corev1.ConfigMap, namespace string,
396404
cm.Data["pod_service_account_name"] = serviceAccountName
397405
// set the reference to our custom pod environment configmap
398406
cm.Data["pod_environment_configmap"] = PodEnvCMName
407+
// set the reference to our custom pod environment secret
408+
cm.Data["pod_environment_secret"] = PodEnvSecretName
399409
// set the list of inherited labels that will be passed on to the pods
400410
s := []string{pg.TenantLabelName, pg.ProjectIDLabelName, pg.UIDLabelName, pg.NameLabelName}
401411
// TODO maybe use a precompiled string here
@@ -491,6 +501,35 @@ func (m *OperatorManager) CreatePodEnvironmentConfigMap(ctx context.Context, nam
491501
return cm, nil
492502
}
493503

504+
// CreateOrGetPodEnvironmentSecret creates a new Secret with additional environment variables for the pods or simply returns it if it already exists
505+
func (m *OperatorManager) CreateOrGetPodEnvironmentSecret(ctx context.Context, namespace string) (*corev1.Secret, error) {
506+
ns := types.NamespacedName{
507+
Namespace: namespace,
508+
Name: PodEnvSecretName,
509+
}
510+
s := &corev1.Secret{}
511+
if err := m.Get(ctx, ns, s); err == nil {
512+
// secret already exists, nothing to do here
513+
// we will update the secret with the correct S3 config in the postgres controller
514+
m.log.Info("Pod Environment Secret already exists")
515+
return s, nil
516+
}
517+
518+
if err := m.SetName(s, PodEnvSecretName); err != nil {
519+
return nil, fmt.Errorf("error while setting the name of the new Pod Environment Secret to %v: %w", namespace, err)
520+
}
521+
if err := m.SetNamespace(s, namespace); err != nil {
522+
return nil, fmt.Errorf("error while setting the namespace of the new Pod Environment Secret to %v: %w", namespace, err)
523+
}
524+
525+
if err := m.Create(ctx, s); err != nil {
526+
return nil, fmt.Errorf("error while creating the new Pod Environment Secret: %w", err)
527+
}
528+
m.log.Info("new Pod Environment Secret created")
529+
530+
return s, nil
531+
}
532+
494533
func (m *OperatorManager) createOrUpdateSidecarsConfig(ctx context.Context, namespace string) error {
495534
// try to fetch the global sidecars configmap
496535
cns := types.NamespacedName{

0 commit comments

Comments
 (0)