Skip to content

Commit 4fba330

Browse files
authored
[cherry-pick] Fix Backup and Restore for TLS enabled mongo (#1805) (#1809)
Signed-off-by: Mohammad Fahim Abrar <fahimabrar@appscode.com>
1 parent 4c76961 commit 4fba330

File tree

2 files changed

+82
-42
lines changed

2 files changed

+82
-42
lines changed

pkg/backup.go

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ import (
5757
var (
5858
MongoCMD = "/usr/bin/mongo"
5959
OpenSSLCMD = "/usr/bin/openssl"
60-
adminCreds []interface{}
60+
mongoCreds []interface{}
61+
dumpCreds []interface{}
6162
cleanupFuncs []func() error
6263
)
6364

@@ -246,16 +247,24 @@ func (opt *mongoOptions) backupMongoDB(targetRef api_v1beta1.TargetRef) (*restic
246247
return nil, err
247248
}
248249

249-
appBindingSecret, err := opt.kubeClient.CoreV1().Secrets(opt.appBindingNamespace).Get(context.TODO(), appBinding.Spec.Secret.Name, metav1.GetOptions{})
250+
authSecret, err := opt.kubeClient.CoreV1().Secrets(opt.appBindingNamespace).Get(context.TODO(), appBinding.Spec.Secret.Name, metav1.GetOptions{})
250251
if err != nil {
251252
return nil, err
252253
}
253254

254-
err = appBinding.TransformSecret(opt.kubeClient, appBindingSecret.Data)
255+
err = appBinding.TransformSecret(opt.kubeClient, authSecret.Data)
255256
if err != nil {
256257
return nil, err
257258
}
258259

260+
var tlsSecret *core.Secret
261+
if appBinding.Spec.TLSSecret != nil {
262+
tlsSecret, err = opt.kubeClient.CoreV1().Secrets(opt.appBindingNamespace).Get(context.TODO(), appBinding.Spec.TLSSecret.Name, metav1.GetOptions{})
263+
if err != nil {
264+
return nil, err
265+
}
266+
}
267+
259268
hostname, err := appBinding.Hostname()
260269
if err != nil {
261270
return nil, err
@@ -313,24 +322,34 @@ func (opt *mongoOptions) backupMongoDB(targetRef api_v1beta1.TargetRef) (*restic
313322
}
314323

315324
if appBinding.Spec.ClientConfig.CABundle != nil {
325+
if tlsSecret == nil {
326+
return nil, errors.Wrap(err, "spec.tlsSecret needs to be set in appbinding for TLS secured database.")
327+
}
328+
316329
if err := os.WriteFile(filepath.Join(opt.setupOptions.ScratchDir, MongoTLSCertFileName), appBinding.Spec.ClientConfig.CABundle, os.ModePerm); err != nil {
317330
return nil, err
318331
}
319-
adminCreds = []interface{}{
332+
mongoCreds = []interface{}{
333+
"--tls",
334+
"--tlsCAFile", filepath.Join(opt.setupOptions.ScratchDir, MongoTLSCertFileName),
335+
"--tlsCertificateKeyFile", filepath.Join(opt.setupOptions.ScratchDir, MongoClientPemFileName),
336+
}
337+
dumpCreds = []interface{}{
320338
"--ssl",
321339
"--sslCAFile", filepath.Join(opt.setupOptions.ScratchDir, MongoTLSCertFileName),
340+
"--sslPEMKeyFile", filepath.Join(opt.setupOptions.ScratchDir, MongoClientPemFileName),
322341
}
323342

324343
// get certificate secret to get client certificate
325344
var pemBytes []byte
326345
var ok bool
327-
pemBytes, ok = appBindingSecret.Data[MongoClientPemFileName]
346+
pemBytes, ok = tlsSecret.Data[MongoClientPemFileName]
328347
if !ok {
329-
crt, ok := appBindingSecret.Data[core.TLSCertKey]
348+
crt, ok := tlsSecret.Data[core.TLSCertKey]
330349
if !ok {
331350
return nil, errors.Wrap(err, "unable to retrieve tls.crt from secret.")
332351
}
333-
key, ok := appBindingSecret.Data[core.TLSPrivateKeyKey]
352+
key, ok := tlsSecret.Data[core.TLSPrivateKeyKey]
334353
if !ok {
335354
return nil, errors.Wrap(err, "unable to retrieve tls.key from secret.")
336355
}
@@ -344,18 +363,22 @@ func (opt *mongoOptions) backupMongoDB(targetRef api_v1beta1.TargetRef) (*restic
344363
if err != nil {
345364
return nil, errors.Wrap(err, "unable to get user from ssl.")
346365
}
347-
adminCreds = append(adminCreds, []interface{}{
348-
"--sslPEMKeyFile", filepath.Join(opt.setupOptions.ScratchDir, MongoClientPemFileName),
366+
userAuth := []interface{}{
349367
"-u", user,
350368
"--authenticationMechanism", "MONGODB-X509",
351369
"--authenticationDatabase", "$external",
352-
}...)
370+
}
371+
mongoCreds = append(mongoCreds, userAuth...)
372+
dumpCreds = append(dumpCreds, userAuth...)
373+
353374
} else {
354-
adminCreds = []interface{}{
355-
fmt.Sprintf("--username=%s", appBindingSecret.Data[MongoUserKey]),
356-
fmt.Sprintf("--password=%s", appBindingSecret.Data[MongoPasswordKey]),
375+
userAuth := []interface{}{
376+
fmt.Sprintf("--username=%s", authSecret.Data[MongoUserKey]),
377+
fmt.Sprintf("--password=%s", authSecret.Data[MongoPasswordKey]),
357378
"--authenticationDatabase", opt.authenticationDatabase,
358379
}
380+
mongoCreds = append(mongoCreds, userAuth...)
381+
dumpCreds = append(dumpCreds, userAuth...)
359382
}
360383

361384
getBackupOpt := func(mongoDSN, hostKey string, isStandalone bool) restic.BackupOptions {
@@ -373,7 +396,7 @@ func (opt *mongoOptions) backupMongoDB(targetRef api_v1beta1.TargetRef) (*restic
373396
Args: append([]interface{}{
374397
"--host", mongoDSN,
375398
"--archive",
376-
}, adminCreds...),
399+
}, dumpCreds...),
377400
}
378401
userArgs := strings.Fields(opt.mongoArgs)
379402

@@ -533,7 +556,7 @@ func getPrimaryNSecondaryMember(mongoDSN string) (primary, secondary string, err
533556
"--host", mongoDSN,
534557
"--quiet",
535558
"--eval", "JSON.stringify(rs.isMaster())",
536-
}, adminCreds...)
559+
}, mongoCreds...)
537560
// even --quiet doesn't skip replicaset PrimaryConnection log. so take tha last line. issue tracker: https://jira.mongodb.org/browse/SERVER-27159
538561
if err := sh.Command(MongoCMD, args...).Command("/usr/bin/tail", "-1").UnmarshalJSON(&v); err != nil {
539562
return "", "", err
@@ -574,9 +597,9 @@ func disabelBalancer(mongosHost string) error {
574597
"--host", mongosHost,
575598
"--quiet",
576599
"--eval", "JSON.stringify(sh.stopBalancer())",
577-
}, adminCreds...)
600+
}, mongoCreds...)
578601
// disable balancer
579-
if err := sh.Command(MongoCMD, args...).UnmarshalJSON(&v); err != nil {
602+
if err := sh.Command(MongoCMD, args...).Command("/usr/bin/tail", "-1").UnmarshalJSON(&v); err != nil {
580603
return err
581604
}
582605

@@ -590,8 +613,8 @@ func disabelBalancer(mongosHost string) error {
590613
"--host", mongosHost,
591614
"--quiet",
592615
"--eval", "while(sh.isBalancerRunning()){ print('waiting for balancer to stop...'); sleep(1000);}",
593-
}, adminCreds...)
594-
if err := sh.Command(MongoCMD, args...).Run(); err != nil {
616+
}, mongoCreds...)
617+
if err := sh.Command(MongoCMD, args...).Command("/usr/bin/tail", "-1").Run(); err != nil {
595618
return err
596619
}
597620
return nil
@@ -608,8 +631,8 @@ func enableBalancer(mongosHost string) error {
608631
"--host", mongosHost,
609632
"--quiet",
610633
"--eval", "JSON.stringify(sh.setBalancerState(true))",
611-
}, adminCreds...)
612-
if err := sh.Command(MongoCMD, args...).UnmarshalJSON(&v); err != nil {
634+
}, mongoCreds...)
635+
if err := sh.Command(MongoCMD, args...).Command("/usr/bin/tail", "-1").UnmarshalJSON(&v); err != nil {
613636
return err
614637
}
615638

@@ -634,8 +657,8 @@ func lockConfigServer(configSVRDSN, secondaryHost string) error {
634657
"--host", configSVRDSN,
635658
"--quiet",
636659
"--eval", "db.BackupControl.findAndModify({query: { _id: 'BackupControlDocument' }, update: { $inc: { counter : 1 } }, new: true, upsert: true, writeConcern: { w: 'majority', wtimeout: 15000 }});",
637-
}, adminCreds...)
638-
if err := sh.Command(MongoCMD, args...).Command("tail", "-1").UnmarshalJSON(&v); err != nil {
660+
}, mongoCreds...)
661+
if err := sh.Command(MongoCMD, args...).Command("/usr/bin/tail", "-1").UnmarshalJSON(&v); err != nil {
639662
return err
640663
}
641664
val, ok := v["counter"].(float64)
@@ -651,8 +674,8 @@ func lockConfigServer(configSVRDSN, secondaryHost string) error {
651674
"config",
652675
"--host", secondaryHost,
653676
"--quiet",
654-
"--eval", "rs.slaveOk(); db.BackupControl.find({ '_id' : 'BackupControlDocument' }).readConcern('majority');",
655-
}, adminCreds...)
677+
"--eval", "rs.secondaryOk(); db.BackupControl.find({ '_id' : 'BackupControlDocument' }).readConcern('majority');",
678+
}, mongoCreds...)
656679

657680
if err := sh.Command(MongoCMD, args...).UnmarshalJSON(&v); err != nil {
658681
return err
@@ -688,8 +711,8 @@ func lockSecondaryMember(mongohost string) error {
688711
"--host", mongohost,
689712
"--quiet",
690713
"--eval", "JSON.stringify(db.fsyncLock())",
691-
}, adminCreds...)
692-
if err := sh.Command(MongoCMD, args...).UnmarshalJSON(&v); err != nil {
714+
}, mongoCreds...)
715+
if err := sh.Command(MongoCMD, args...).Command("/usr/bin/tail", "-1").UnmarshalJSON(&v); err != nil {
693716
return err
694717
}
695718

@@ -714,8 +737,8 @@ func unlockSecondaryMember(mongohost string) error {
714737
"--host", mongohost,
715738
"--quiet",
716739
"--eval", "JSON.stringify(db.fsyncUnlock())",
717-
}, adminCreds...)
718-
if err := sh.Command(MongoCMD, args...).UnmarshalJSON(&v); err != nil {
740+
}, mongoCreds...)
741+
if err := sh.Command(MongoCMD, args...).Command("/usr/bin/tail", "-1").UnmarshalJSON(&v); err != nil {
719742
return err
720743
}
721744

pkg/restore.go

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -185,16 +185,24 @@ func (opt *mongoOptions) restoreMongoDB(targetRef api_v1beta1.TargetRef) (*resti
185185
return nil, err
186186
}
187187

188-
appBindingSecret, err := opt.kubeClient.CoreV1().Secrets(opt.appBindingNamespace).Get(context.TODO(), appBinding.Spec.Secret.Name, metav1.GetOptions{})
188+
authSecret, err := opt.kubeClient.CoreV1().Secrets(opt.appBindingNamespace).Get(context.TODO(), appBinding.Spec.Secret.Name, metav1.GetOptions{})
189189
if err != nil {
190190
return nil, err
191191
}
192192

193-
err = appBinding.TransformSecret(opt.kubeClient, appBindingSecret.Data)
193+
err = appBinding.TransformSecret(opt.kubeClient, authSecret.Data)
194194
if err != nil {
195195
return nil, err
196196
}
197197

198+
var tlsSecret *core.Secret
199+
if appBinding.Spec.TLSSecret != nil {
200+
tlsSecret, err = opt.kubeClient.CoreV1().Secrets(opt.appBindingNamespace).Get(context.TODO(), appBinding.Spec.TLSSecret.Name, metav1.GetOptions{})
201+
if err != nil {
202+
return nil, err
203+
}
204+
}
205+
198206
hostname, err := appBinding.Hostname()
199207
if err != nil {
200208
return nil, err
@@ -248,21 +256,27 @@ func (opt *mongoOptions) restoreMongoDB(targetRef api_v1beta1.TargetRef) (*resti
248256
if err := os.WriteFile(filepath.Join(opt.setupOptions.ScratchDir, MongoTLSCertFileName), appBinding.Spec.ClientConfig.CABundle, os.ModePerm); err != nil {
249257
return nil, errors.Wrap(err, "failed to write key for CA certificate")
250258
}
251-
adminCreds = []interface{}{
259+
mongoCreds = []interface{}{
260+
"--tls",
261+
"--tlsCAFile", filepath.Join(opt.setupOptions.ScratchDir, MongoTLSCertFileName),
262+
"--tlsCertificateKeyFile", filepath.Join(opt.setupOptions.ScratchDir, MongoClientPemFileName),
263+
}
264+
dumpCreds = []interface{}{
252265
"--ssl",
253266
"--sslCAFile", filepath.Join(opt.setupOptions.ScratchDir, MongoTLSCertFileName),
267+
"--sslPEMKeyFile", filepath.Join(opt.setupOptions.ScratchDir, MongoClientPemFileName),
254268
}
255269

256270
// get certificate secret to get client certificate
257271
var pemBytes []byte
258272
var ok bool
259-
pemBytes, ok = appBindingSecret.Data[MongoClientPemFileName]
273+
pemBytes, ok = tlsSecret.Data[MongoClientPemFileName]
260274
if !ok {
261-
crt, ok := appBindingSecret.Data[core.TLSCertKey]
275+
crt, ok := tlsSecret.Data[core.TLSCertKey]
262276
if !ok {
263277
return nil, errors.Wrap(err, "unable to retrieve tls.crt from secret.")
264278
}
265-
key, ok := appBindingSecret.Data[core.TLSPrivateKeyKey]
279+
key, ok := tlsSecret.Data[core.TLSPrivateKeyKey]
266280
if !ok {
267281
return nil, errors.Wrap(err, "unable to retrieve tls.key from secret.")
268282
}
@@ -276,19 +290,22 @@ func (opt *mongoOptions) restoreMongoDB(targetRef api_v1beta1.TargetRef) (*resti
276290
if err != nil {
277291
return nil, errors.Wrap(err, "unable to get user from ssl.")
278292
}
279-
adminCreds = append(adminCreds, []interface{}{
280-
"--sslPEMKeyFile", filepath.Join(opt.setupOptions.ScratchDir, MongoClientPemFileName),
293+
userAuth := []interface{}{
281294
"-u", user,
282295
"--authenticationMechanism", "MONGODB-X509",
283296
"--authenticationDatabase", "$external",
284-
}...)
297+
}
298+
mongoCreds = append(mongoCreds, userAuth...)
299+
dumpCreds = append(dumpCreds, userAuth...)
285300

286301
} else {
287-
adminCreds = []interface{}{
288-
fmt.Sprintf("--username=%s", appBindingSecret.Data[MongoUserKey]),
289-
fmt.Sprintf("--password=%s", appBindingSecret.Data[MongoPasswordKey]),
302+
userAuth := []interface{}{
303+
fmt.Sprintf("--username=%s", authSecret.Data[MongoUserKey]),
304+
fmt.Sprintf("--password=%s", authSecret.Data[MongoPasswordKey]),
290305
"--authenticationDatabase", opt.authenticationDatabase,
291306
}
307+
mongoCreds = append(mongoCreds, userAuth...)
308+
dumpCreds = append(dumpCreds, userAuth...)
292309
}
293310

294311
getDumpOpts := func(mongoDSN, hostKey string, isStandalone bool) restic.DumpOptions {
@@ -306,7 +323,7 @@ func (opt *mongoOptions) restoreMongoDB(targetRef api_v1beta1.TargetRef) (*resti
306323
Args: append([]interface{}{
307324
"--host", mongoDSN,
308325
"--archive",
309-
}, adminCreds...),
326+
}, dumpCreds...),
310327
}
311328

312329
userArgs := strings.Fields(opt.mongoArgs)

0 commit comments

Comments
 (0)