@@ -2,10 +2,9 @@ package backup_operations
22
33import (
44 "context"
5+ "crypto/rand"
56 "errors"
67 "fmt"
7- "github.com/jonboulle/clockwork"
8- "github.com/ydb-platform/ydb-go-sdk/v3"
98 "path"
109 "regexp"
1110 "strings"
@@ -14,8 +13,12 @@ import (
1413 "ydbcp/internal/connectors/client"
1514 "ydbcp/internal/types"
1615 "ydbcp/internal/util/xlog"
16+ kp "ydbcp/pkg/plugins/kms"
1717 pb "ydbcp/pkg/proto/ydbcp/v1alpha1"
1818
19+ "github.com/jonboulle/clockwork"
20+ "github.com/ydb-platform/ydb-go-sdk/v3"
21+
1922 "go.uber.org/zap"
2023 "google.golang.org/grpc/codes"
2124 "google.golang.org/grpc/status"
@@ -36,6 +39,7 @@ type MakeBackupInternalRequest struct {
3639 ScheduleID * string
3740 Ttl * time.Duration
3841 ParentOperationID * string
42+ EncryptionSettings * pb.EncryptionSettings
3943}
4044
4145func FromBackupSchedule (schedule * types.BackupSchedule ) MakeBackupInternalRequest {
@@ -65,6 +69,7 @@ func FromTBWROperation(tbwr *types.TakeBackupWithRetryOperation) MakeBackupInter
6569 ScheduleID : tbwr .ScheduleID ,
6670 Ttl : tbwr .Ttl ,
6771 ParentOperationID : & tbwr .ID ,
72+ EncryptionSettings : tbwr .EncryptionSettings ,
6873 }
6974}
7075
@@ -282,6 +287,31 @@ func IsEmptyBackup(backup *types.Backup) bool {
282287 return backup .Size == 0 && backup .S3Endpoint == ""
283288}
284289
290+ func GetEncryptionParams (settings * pb.EncryptionSettings ) ([]byte , string , error ) {
291+ var algorithm string
292+ var length int
293+
294+ switch settings .Algorithm {
295+ case pb .EncryptionSettings_UNSPECIFIED :
296+ case pb .EncryptionSettings_AES_128_GCM :
297+ algorithm = "AES-128-GCM"
298+ length = 16
299+ case pb .EncryptionSettings_AES_256_GCM :
300+ algorithm = "AES-256-GCM"
301+ length = 32
302+ case pb .EncryptionSettings_CHACHA20_POLY1305 :
303+ algorithm = "ChaCha20-Poly1305"
304+ length = 32
305+ }
306+
307+ dek := make ([]byte , length )
308+ _ , err := rand .Read (dek )
309+ if err != nil {
310+ return nil , "" , err
311+ }
312+ return dek , algorithm , nil
313+ }
314+
285315func MakeBackup (
286316 ctx context.Context ,
287317 clientConn client.ClientConnector ,
@@ -292,6 +322,7 @@ func MakeBackup(
292322 subject string ,
293323 clock clockwork.Clock ,
294324 featureFlags config.FeatureFlagsConfig ,
325+ kmsProvider kp.KmsProvider ,
295326) (* types.Backup , * types.TakeBackupOperation , error ) {
296327 if req .ScheduleID != nil {
297328 ctx = xlog .With (ctx , zap .String ("ScheduleID" , * req .ScheduleID ))
@@ -359,6 +390,37 @@ func MakeBackup(
359390 S3ForcePathStyle : s3 .S3ForcePathStyle ,
360391 }
361392
393+ if req .EncryptionSettings != nil && featureFlags .EnableBackupEncryption {
394+ dek , algorithm , err := GetEncryptionParams (req .EncryptionSettings )
395+ if err != nil {
396+ return nil , nil , err
397+ }
398+
399+ s3Settings .EncryptionKey = dek
400+ s3Settings .EncryptionAlgorithm = algorithm
401+
402+ kmsKey := req .EncryptionSettings .GetKmsKey ()
403+ if kmsKey == nil {
404+ xlog .Error (ctx , "kms key is not specified" )
405+ return nil , nil , status .Errorf (codes .InvalidArgument , "kms key is not specified" )
406+ }
407+
408+ _ , err = kmsProvider .Encrypt (
409+ ctx ,
410+ & kp.EncryptRequest {
411+ KeyID : kmsKey .GetKeyId (),
412+ Plaintext : dek ,
413+ },
414+ )
415+
416+ if err != nil {
417+ xlog .Error (ctx , "can't encrypt data encryption key" , zap .Error (err ))
418+ return nil , nil , err
419+ }
420+
421+ // TODO: save encrypted key to s3
422+ }
423+
362424 clientOperationID , err := clientConn .ExportToS3 (ctx , client , s3Settings , featureFlags )
363425 if err != nil {
364426 xlog .Error (ctx , "can't start export operation" , zap .Error (err ))
@@ -388,9 +450,10 @@ func MakeBackup(
388450 CreatedAt : now ,
389451 Creator : subject ,
390452 },
391- ScheduleID : req .ScheduleID ,
392- ExpireAt : expireAt ,
393- SourcePaths : pathsForExport ,
453+ ScheduleID : req .ScheduleID ,
454+ ExpireAt : expireAt ,
455+ SourcePaths : pathsForExport ,
456+ EncryptionSettings : req .EncryptionSettings ,
394457 }
395458
396459 op := & types.TakeBackupOperation {
@@ -409,9 +472,10 @@ func MakeBackup(
409472 CreatedAt : now ,
410473 Creator : subject ,
411474 },
412- YdbOperationId : clientOperationID ,
413- UpdatedAt : now ,
414- ParentOperationID : req .ParentOperationID ,
475+ YdbOperationId : clientOperationID ,
476+ UpdatedAt : now ,
477+ ParentOperationID : req .ParentOperationID ,
478+ EncryptionSettings : req .EncryptionSettings ,
415479 }
416480
417481 return backup , op , nil
0 commit comments