From 149ffb2c318a04b6a53ad8ae053c7f711c8747d9 Mon Sep 17 00:00:00 2001 From: ulya-sidorina Date: Tue, 30 Sep 2025 14:29:58 +0200 Subject: [PATCH] feat(backup_service): support backup encryption --- cmd/ydbcp/main.go | 2 +- internal/backup_operations/make_backup.go | 57 ++++++++++++++++-- internal/config/config.go | 5 +- internal/connectors/client/connector.go | 22 +++++++ internal/connectors/db/yql/queries/write.go | 42 ++++++++++++++ .../db/yql/schema/create_tables.yql | 8 +++ internal/handlers/schedule_backup.go | 8 +++ internal/handlers/schedule_backup_test.go | 3 +- .../server/services/backup/backup_service.go | 20 ++++++- .../backup_schedule_service.go | 2 +- internal/types/backup.go | 44 +++++++------- internal/types/operation.go | 7 ++- internal/types/settings.go | 48 ++++++++------- .../schedule_watcher/schedule_watcher_test.go | 11 ++-- pkg/proto/ydbcp/v1alpha1/operation.pb.go | 58 ++++++++++++------- pkg/proto/ydbcp/v1alpha1/operation.proto | 3 + 16 files changed, 256 insertions(+), 84 deletions(-) diff --git a/cmd/ydbcp/main.go b/cmd/ydbcp/main.go index 82c67529..95da988e 100644 --- a/cmd/ydbcp/main.go +++ b/cmd/ydbcp/main.go @@ -210,7 +210,7 @@ func main() { xlog.Info(ctx, "Created TtlWatcher") } - backupScheduleHandler := handlers.NewBackupScheduleHandler(queries.NewWriteTableQuery, clockwork.NewRealClock()) + backupScheduleHandler := handlers.NewBackupScheduleHandler(queries.NewWriteTableQuery, clockwork.NewRealClock(), configInstance.FeatureFlags) schedule_watcher.NewScheduleWatcher( ctx, &wg, configInstance.GetProcessorIntervalSeconds(), dbConnector, diff --git a/internal/backup_operations/make_backup.go b/internal/backup_operations/make_backup.go index 05d4c139..61109020 100644 --- a/internal/backup_operations/make_backup.go +++ b/internal/backup_operations/make_backup.go @@ -2,6 +2,7 @@ package backup_operations import ( "context" + "crypto/rand" "errors" "fmt" "github.com/jonboulle/clockwork" @@ -35,6 +36,7 @@ type MakeBackupInternalRequest struct { ScheduleID *string Ttl *time.Duration ParentOperationID *string + EncryptionSettings *pb.EncryptionSettings } func FromBackupSchedule(schedule *types.BackupSchedule) MakeBackupInternalRequest { @@ -62,6 +64,7 @@ func FromTBWROperation(tbwr *types.TakeBackupWithRetryOperation) MakeBackupInter ScheduleID: tbwr.ScheduleID, Ttl: tbwr.Ttl, ParentOperationID: &tbwr.ID, + EncryptionSettings: tbwr.EncryptionSettings, } } @@ -274,6 +277,34 @@ func IsEmptyBackup(backup *types.Backup) bool { return backup.Size == 0 && backup.S3Endpoint == "" } +func GetEncryptionParams(settings *pb.EncryptionSettings) ([]byte, string, error) { + var algorithm string + var length int + + switch settings.Algorithm { + case pb.EncryptionSettings_UNSPECIFIED: + case pb.EncryptionSettings_AES_128_GCM: + algorithm = "AES-128-GCM" + length = 16 + break + case pb.EncryptionSettings_AES_256_GCM: + algorithm = "AES-256-GCM" + length = 32 + break + case pb.EncryptionSettings_CHACHA20_POLY1305: + algorithm = "ChaCha20-Poly1305" + length = 32 + break + } + + dek := make([]byte, length) + _, err := rand.Read(dek) + if err != nil { + return nil, "", err + } + return dek, algorithm, nil +} + func MakeBackup( ctx context.Context, clientConn client.ClientConnector, @@ -350,6 +381,18 @@ func MakeBackup( S3ForcePathStyle: s3.S3ForcePathStyle, } + if req.EncryptionSettings != nil && featureFlags.EnableBackupEncryption { + dek, algorithm, err := GetEncryptionParams(req.EncryptionSettings) + if err != nil { + return nil, nil, err + } + + s3Settings.EncryptionKey = dek + s3Settings.EncryptionAlgorithm = algorithm + // TODO: encrypt the DEK using the specified KEK + // TODO: stores the encrypted DEK in S3 + } + clientOperationID, err := clientConn.ExportToS3(ctx, client, s3Settings, featureFlags) if err != nil { xlog.Error(ctx, "can't start export operation", zap.Error(err)) @@ -379,9 +422,10 @@ func MakeBackup( CreatedAt: now, Creator: subject, }, - ScheduleID: req.ScheduleID, - ExpireAt: expireAt, - SourcePaths: pathsForExport, + ScheduleID: req.ScheduleID, + ExpireAt: expireAt, + SourcePaths: pathsForExport, + EncryptionSettings: req.EncryptionSettings, } op := &types.TakeBackupOperation{ @@ -399,9 +443,10 @@ func MakeBackup( CreatedAt: now, Creator: subject, }, - YdbOperationId: clientOperationID, - UpdatedAt: now, - ParentOperationID: req.ParentOperationID, + YdbOperationId: clientOperationID, + UpdatedAt: now, + ParentOperationID: req.ParentOperationID, + EncryptionSettings: req.EncryptionSettings, } return backup, op, nil diff --git a/internal/config/config.go b/internal/config/config.go index ad7d8a7a..f669b361 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -66,8 +66,9 @@ type MetricsServerConfig struct { } type FeatureFlagsConfig struct { - DisableTTLDeletion bool `yaml:"disable_ttl_deletion" default:"false"` - EnableNewPathsFormat bool `yaml:"enable_new_paths_format" default:"false"` + DisableTTLDeletion bool `yaml:"disable_ttl_deletion" default:"false"` + EnableNewPathsFormat bool `yaml:"enable_new_paths_format" default:"false"` + EnableBackupEncryption bool `yaml:"enable_backup_encryption" default:"false"` } type LogConfig struct { diff --git a/internal/connectors/client/connector.go b/internal/connectors/client/connector.go index 1b8ac226..a9d0a651 100644 --- a/internal/connectors/client/connector.go +++ b/internal/connectors/client/connector.go @@ -272,6 +272,17 @@ func (d *ClientYdbConnector) ExportToS3( exportRequest.Settings.DestinationPrefix = s3Settings.DestinationPrefix } + if featureFlags.EnableBackupEncryption && len(s3Settings.EncryptionKey) > 0 { + exportRequest.Settings.EncryptionSettings = &Ydb_Export.EncryptionSettings{ + EncryptionAlgorithm: s3Settings.EncryptionAlgorithm, + Key: &Ydb_Export.EncryptionSettings_SymmetricKey_{ + SymmetricKey: &Ydb_Export.EncryptionSettings_SymmetricKey{ + Key: s3Settings.EncryptionKey, + }, + }, + } + } + response, err := exportClient.ExportToS3(ctx, exportRequest) if err != nil { @@ -425,6 +436,17 @@ func (d *ClientYdbConnector) ImportFromS3( importRequest.Settings.DestinationPath = path.Join(clientDb.Name(), s3Settings.DestinationPrefix) } + if len(s3Settings.EncryptionKey) > 0 { + importRequest.Settings.EncryptionSettings = &Ydb_Export.EncryptionSettings{ + EncryptionAlgorithm: s3Settings.EncryptionAlgorithm, + Key: &Ydb_Export.EncryptionSettings_SymmetricKey_{ + SymmetricKey: &Ydb_Export.EncryptionSettings_SymmetricKey{ + Key: s3Settings.EncryptionKey, + }, + }, + } + } + response, err := importClient.ImportFromS3(ctx, importRequest) if err != nil { diff --git a/internal/connectors/db/yql/queries/write.go b/internal/connectors/db/yql/queries/write.go index 685acfd1..bf97f53b 100644 --- a/internal/connectors/db/yql/queries/write.go +++ b/internal/connectors/db/yql/queries/write.go @@ -129,6 +129,16 @@ func BuildCreateOperationQuery(operation types.Operation, index int) WriteSingle if tb.ParentOperationID != nil { d.AddValueParam("$parent_operation_id", table_types.StringValueFromString(*tb.ParentOperationID)) } + if tb.EncryptionSettings != nil { + d.AddValueParam( + "$encryption_algorithm", + table_types.StringValueFromString(tb.EncryptionSettings.GetAlgorithm().String()), + ) + d.AddValueParam( + "$kms_key_id", + table_types.StringValueFromString(tb.EncryptionSettings.GetKmsKey().GetKeyId()), + ) + } } else if operation.GetType() == types.OperationTypeTBWR { tbwr, ok := operation.(*types.TakeBackupWithRetryOperation) if !ok { @@ -178,6 +188,16 @@ func BuildCreateOperationQuery(operation types.Operation, index int) WriteSingle if tbwr.Ttl != nil { d.AddValueParam("$ttl", table_types.IntervalValueFromDuration(*tbwr.Ttl)) } + if tbwr.EncryptionSettings != nil { + d.AddValueParam( + "$encryption_algorithm", + table_types.StringValueFromString(tbwr.EncryptionSettings.GetAlgorithm().String()), + ) + d.AddValueParam( + "$kms_key_id", + table_types.StringValueFromString(tbwr.EncryptionSettings.GetKmsKey().GetKeyId()), + ) + } } else if operation.GetType() == types.OperationTypeRB { rb, ok := operation.(*types.RestoreBackupOperation) if !ok { @@ -330,6 +350,17 @@ func BuildCreateBackupQuery(b types.Backup, index int) WriteSingleTableQueryImpl if b.ExpireAt != nil { d.AddValueParam("$expire_at", table_types.TimestampValueFromTime(*b.ExpireAt)) } + + if b.EncryptionSettings != nil { + d.AddValueParam( + "$encryption_algorithm", + table_types.StringValueFromString(b.EncryptionSettings.GetAlgorithm().String()), + ) + d.AddValueParam( + "$kms_key_id", + table_types.StringValueFromString(b.EncryptionSettings.GetKmsKey().GetKeyId()), + ) + } return d } @@ -380,6 +411,17 @@ func BuildCreateBackupScheduleQuery(schedule types.BackupSchedule, index int) Wr "$recovery_point_objective", table_types.IntervalValueFromDuration(schedule.ScheduleSettings.RecoveryPointObjective.AsDuration()), ) + + if schedule.ScheduleSettings.EncryptionSettings != nil { + d.AddValueParam( + "$encryption_algorithm", + table_types.StringValueFromString(schedule.ScheduleSettings.EncryptionSettings.GetAlgorithm().String()), + ) + d.AddValueParam( + "$kms_key_id", + table_types.StringValueFromString(schedule.ScheduleSettings.EncryptionSettings.GetKmsKey().GetKeyId()), + ) + } } if schedule.NextLaunch != nil { d.AddValueParam("$next_launch", table_types.TimestampValueFromTime(*schedule.NextLaunch)) diff --git a/internal/connectors/db/yql/schema/create_tables.yql b/internal/connectors/db/yql/schema/create_tables.yql index e9c04a76..fa3d0592 100644 --- a/internal/connectors/db/yql/schema/create_tables.yql +++ b/internal/connectors/db/yql/schema/create_tables.yql @@ -22,6 +22,9 @@ CREATE TABLE Backups ( schedule_id String, + encryption_algorithm String, + kms_key_id String, + INDEX idx_container_id GLOBAL ON (container_id), INDEX idx_created_at GLOBAL ON (created_at), INDEX idx_expire_at GLOBAL ON (status, expire_at), @@ -55,6 +58,8 @@ CREATE TABLE Operations ( paths_to_exclude String, operation_id String, parent_operation_id String, + encryption_algorithm String, + kms_key_id String, --used only in TBWR schedule_id String, ttl Interval, @@ -85,6 +90,9 @@ CREATE TABLE BackupSchedules ( initiated String, created_at Timestamp, + encryption_algorithm String, + kms_key_id String, + recovery_point_objective Interval, next_launch Timestamp, diff --git a/internal/handlers/schedule_backup.go b/internal/handlers/schedule_backup.go index 46e12634..9f72a6cd 100644 --- a/internal/handlers/schedule_backup.go +++ b/internal/handlers/schedule_backup.go @@ -8,6 +8,7 @@ import ( "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/timestamppb" "ydbcp/internal/audit" + "ydbcp/internal/config" "ydbcp/internal/connectors/db" "ydbcp/internal/connectors/db/yql/queries" "ydbcp/internal/types" @@ -20,11 +21,13 @@ type BackupScheduleHandlerType func(context.Context, db.DBConnector, *types.Back func NewBackupScheduleHandler( queryBuilderFactory queries.WriteQueryBuilderFactory, clock clockwork.Clock, + featureFlags config.FeatureFlagsConfig, ) BackupScheduleHandlerType { return func(ctx context.Context, driver db.DBConnector, schedule *types.BackupSchedule) error { return BackupScheduleHandler( ctx, driver, schedule, queryBuilderFactory, clock, + featureFlags, ) } } @@ -46,6 +49,7 @@ func BackupScheduleHandler( schedule *types.BackupSchedule, queryBuilderFactory queries.WriteQueryBuilderFactory, clock clockwork.Clock, + featureFlags config.FeatureFlagsConfig, ) error { if schedule.Status != types.BackupScheduleStateActive { xlog.Error(ctx, "backup schedule is not active", zap.String("ScheduleID", schedule.ID)) @@ -85,6 +89,10 @@ func BackupScheduleHandler( d := schedule.ScheduleSettings.Ttl.AsDuration() tbwr.Ttl = &d } + + if schedule.ScheduleSettings.EncryptionSettings != nil && featureFlags.EnableBackupEncryption { + tbwr.EncryptionSettings = schedule.ScheduleSettings.EncryptionSettings + } } xlog.Info( diff --git a/internal/handlers/schedule_backup_test.go b/internal/handlers/schedule_backup_test.go index a4bc4b50..d5c4d797 100644 --- a/internal/handlers/schedule_backup_test.go +++ b/internal/handlers/schedule_backup_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "testing" "time" + "ydbcp/internal/config" "ydbcp/internal/connectors/db" "ydbcp/internal/connectors/db/yql/queries" "ydbcp/internal/types" @@ -40,7 +41,7 @@ func TestBackupScheduleHandler(t *testing.T) { ) handler := NewBackupScheduleHandler( - queries.NewWriteTableQueryMock, clock, + queries.NewWriteTableQueryMock, clock, config.FeatureFlagsConfig{}, ) err := handler(ctx, dbConnector, &schedule) assert.Empty(t, err) diff --git a/internal/server/services/backup/backup_service.go b/internal/server/services/backup/backup_service.go index b97550bf..5a46eb4d 100644 --- a/internal/server/services/backup/backup_service.go +++ b/internal/server/services/backup/backup_service.go @@ -3,6 +3,7 @@ package backup import ( "context" "github.com/jonboulle/clockwork" + "google.golang.org/protobuf/proto" "strconv" "time" "ydbcp/internal/audit" @@ -110,9 +111,13 @@ func (s *BackupService) MakeBackup(ctx context.Context, req *pb.MakeBackupReques ctx = xlog.With(ctx, zap.String("SubjectID", subject)) now := timestamppb.Now() + var encryptionSettings *pb.EncryptionSettings if req.EncryptionSettings != nil { - s.IncApiCallsCounter(methodName, codes.Unimplemented) - return nil, status.Error(codes.Unimplemented, "backup encryption is not supported yet") + if !s.featureFlags.EnableBackupEncryption { + s.IncApiCallsCounter(methodName, codes.Unimplemented) + return nil, status.Error(codes.Unimplemented, "backup encryption is not supported yet") + } + encryptionSettings = proto.Clone(req.EncryptionSettings).(*pb.EncryptionSettings) } tbwr := &types.TakeBackupWithRetryOperation{ @@ -130,7 +135,8 @@ func (s *BackupService) MakeBackup(ctx context.Context, req *pb.MakeBackupReques Creator: subject, CreatedAt: now, }, - UpdatedAt: now, + UpdatedAt: now, + EncryptionSettings: encryptionSettings, }, Retries: 0, RetryConfig: &pb.RetryConfig{ @@ -383,6 +389,14 @@ func (s *BackupService) MakeRestore(ctx context.Context, req *pb.MakeRestoreRequ DestinationPrefix: req.GetDestinationPrefix(), } + if backup.EncryptionSettings != nil { + // TODO: read encrypted DEK from s3 + // TODO: decrypt DEC via KMS + // TODO: set EncryptionKey + _, algorithm, _ := backup_operations.GetEncryptionParams(backup.EncryptionSettings) + s3Settings.EncryptionAlgorithm = algorithm + } + clientOperationID, err := s.clientConn.ImportFromS3(ctx, clientDriver, s3Settings, s.featureFlags) if err != nil { xlog.Error(ctx, "can't start import operation", zap.Error(err)) diff --git a/internal/server/services/backup_schedule/backup_schedule_service.go b/internal/server/services/backup_schedule/backup_schedule_service.go index 3ffd00f2..f37e4911 100644 --- a/internal/server/services/backup_schedule/backup_schedule_service.go +++ b/internal/server/services/backup_schedule/backup_schedule_service.go @@ -119,7 +119,7 @@ func (s *BackupScheduleService) CreateBackupSchedule( return nil, status.Error(codes.FailedPrecondition, "no backup schedule settings for CreateBackupSchedule") } - if request.ScheduleSettings.EncryptionSettings != nil { + if !s.config.FeatureFlags.EnableBackupEncryption && request.ScheduleSettings.EncryptionSettings != nil { s.IncApiCallsCounter(methodName, codes.Unimplemented) return nil, status.Error(codes.Unimplemented, "backup encryption is not supported yet") } diff --git a/internal/types/backup.go b/internal/types/backup.go index 4b775f51..a1207bb4 100644 --- a/internal/types/backup.go +++ b/internal/types/backup.go @@ -37,21 +37,22 @@ func ParseObjectID(string string) (string, error) { } type Backup struct { - ID string - ContainerID string - DatabaseName string - DatabaseEndpoint string - S3Endpoint string - S3Region string - S3Bucket string - S3PathPrefix string - Status string - Message string - AuditInfo *pb.AuditInfo - Size int64 - ScheduleID *string - ExpireAt *time.Time - SourcePaths []string + ID string + ContainerID string + DatabaseName string + DatabaseEndpoint string + S3Endpoint string + S3Region string + S3Bucket string + S3PathPrefix string + Status string + Message string + AuditInfo *pb.AuditInfo + Size int64 + ScheduleID *string + ExpireAt *time.Time + SourcePaths []string + EncryptionSettings *pb.EncryptionSettings } func (o *Backup) String() string { @@ -77,12 +78,13 @@ func (o *Backup) Proto() *pb.Backup { Bucket: o.S3Bucket, PathPrefix: o.S3PathPrefix, }, - Audit: o.AuditInfo, - Size: o.Size, - Status: pb.Backup_Status(pb.Backup_Status_value[o.Status]), - Message: o.Message, - ExpireAt: nil, - SourcePaths: o.SourcePaths, + Audit: o.AuditInfo, + Size: o.Size, + Status: pb.Backup_Status(pb.Backup_Status_value[o.Status]), + Message: o.Message, + ExpireAt: nil, + SourcePaths: o.SourcePaths, + EncryptionSettings: o.EncryptionSettings, } if o.ScheduleID != nil { backup.ScheduleId = *o.ScheduleID diff --git a/internal/types/operation.go b/internal/types/operation.go index bf0b264a..f9bdc6c4 100644 --- a/internal/types/operation.go +++ b/internal/types/operation.go @@ -50,6 +50,7 @@ type TakeBackupOperation struct { Audit *pb.AuditInfo UpdatedAt *timestamppb.Timestamp ParentOperationID *string + EncryptionSettings *pb.EncryptionSettings } func (o *TakeBackupOperation) GetID() string { @@ -115,6 +116,7 @@ func (o *TakeBackupOperation) Proto() *pb.Operation { Message: o.Message, UpdatedAt: o.UpdatedAt, TypeDescription: o.GetTypeDescription(), + EncryptionSettings: o.EncryptionSettings, } if o.ParentOperationID != nil { op.ParentOperationId = *o.ParentOperationID @@ -377,8 +379,9 @@ func (o *TakeBackupWithRetryOperation) SpawnNewTBOperation(backupID string, subj Creator: subject, CreatedAt: timestamppb.Now(), }, - UpdatedAt: timestamppb.Now(), - ParentOperationID: &o.ID, + UpdatedAt: timestamppb.Now(), + ParentOperationID: &o.ID, + EncryptionSettings: o.EncryptionSettings, } } diff --git a/internal/types/settings.go b/internal/types/settings.go index 343e7bd6..e4b536cb 100644 --- a/internal/types/settings.go +++ b/internal/types/settings.go @@ -11,29 +11,33 @@ func MakeYdbConnectionString(params YdbConnectionParams) string { } type ExportSettings struct { - Endpoint string - Region string - Bucket string - AccessKey string - SecretKey string - Description string - NumberOfRetries uint32 - SourcePaths []string - DestinationPrefix string - S3ForcePathStyle bool + Endpoint string + Region string + Bucket string + AccessKey string + SecretKey string + Description string + NumberOfRetries uint32 + SourcePaths []string + DestinationPrefix string + S3ForcePathStyle bool + EncryptionAlgorithm string + EncryptionKey []byte } type ImportSettings struct { - Endpoint string - Region string - Bucket string - AccessKey string - SecretKey string - Description string - NumberOfRetries uint32 - BackupID string - BucketDbRoot string - SourcePaths map[string]bool - S3ForcePathStyle bool - DestinationPrefix string + Endpoint string + Region string + Bucket string + AccessKey string + SecretKey string + Description string + NumberOfRetries uint32 + BackupID string + BucketDbRoot string + SourcePaths map[string]bool + S3ForcePathStyle bool + DestinationPrefix string + EncryptionAlgorithm string + EncryptionKey []byte } diff --git a/internal/watchers/schedule_watcher/schedule_watcher_test.go b/internal/watchers/schedule_watcher/schedule_watcher_test.go index eeb66306..e8704b2b 100644 --- a/internal/watchers/schedule_watcher/schedule_watcher_test.go +++ b/internal/watchers/schedule_watcher/schedule_watcher_test.go @@ -9,6 +9,7 @@ import ( "sync" "testing" "time" + "ydbcp/internal/config" "ydbcp/internal/connectors/db" "ydbcp/internal/connectors/db/yql/queries" "ydbcp/internal/handlers" @@ -65,7 +66,7 @@ func TestScheduleWatcherSimple(t *testing.T) { metrics.InitializeMockMetricsRegistry(metrics.WithClock(clock)) handler := handlers.NewBackupScheduleHandler( - queries.NewWriteTableQueryMock, clock, + queries.NewWriteTableQueryMock, clock, config.FeatureFlagsConfig{}, ) scheduleWatcherActionCompleted := make(chan struct{}) @@ -178,7 +179,7 @@ func TestScheduleWatcherTwoSchedulesOneBackup(t *testing.T) { metrics.InitializeMockMetricsRegistry(metrics.WithClock(clock)) handler := handlers.NewBackupScheduleHandler( - queries.NewWriteTableQueryMock, clock, + queries.NewWriteTableQueryMock, clock, config.FeatureFlagsConfig{}, ) scheduleWatcherActionCompleted := make(chan struct{}) @@ -299,7 +300,7 @@ func TestScheduleWatcherTwoBackups(t *testing.T) { metrics.InitializeMockMetricsRegistry(metrics.WithClock(clock)) handler := handlers.NewBackupScheduleHandler( - queries.NewWriteTableQueryMock, clock, + queries.NewWriteTableQueryMock, clock, config.FeatureFlagsConfig{}, ) scheduleWatcherActionCompleted := make(chan struct{}) @@ -416,7 +417,7 @@ func TestAllScheduleMetrics(t *testing.T) { metrics.InitializeMockMetricsRegistry(metrics.WithClock(clock)) handler := handlers.NewBackupScheduleHandler( - queries.NewWriteTableQueryMock, clock, + queries.NewWriteTableQueryMock, clock, config.FeatureFlagsConfig{}, ) scheduleWatcherActionCompleted := make(chan struct{}) @@ -527,7 +528,7 @@ func TestAllScheduleMetricsBeforeFirstBackup(t *testing.T) { metrics.InitializeMockMetricsRegistry(metrics.WithClock(clock)) handler := handlers.NewBackupScheduleHandler( - queries.NewWriteTableQueryMock, clock, + queries.NewWriteTableQueryMock, clock, config.FeatureFlagsConfig{}, ) scheduleWatcherActionCompleted := make(chan struct{}) diff --git a/pkg/proto/ydbcp/v1alpha1/operation.pb.go b/pkg/proto/ydbcp/v1alpha1/operation.pb.go index 14217c98..2f6b2b6f 100644 --- a/pkg/proto/ydbcp/v1alpha1/operation.pb.go +++ b/pkg/proto/ydbcp/v1alpha1/operation.pb.go @@ -125,6 +125,9 @@ type Operation struct { RetryConfig *RetryConfig `protobuf:"bytes,16,opt,name=retry_config,json=retryConfig,proto3" json:"retry_config,omitempty"` // Human readable description for the operation type. TypeDescription string `protobuf:"bytes,17,opt,name=type_description,json=typeDescription,proto3" json:"type_description,omitempty"` + // Backup encryption settings, + // unspecified field means the backup is unencrypted (only for MakeBackup operation). + EncryptionSettings *EncryptionSettings `protobuf:"bytes,18,opt,name=encryption_settings,json=encryptionSettings,proto3" json:"encryption_settings,omitempty"` } func (x *Operation) Reset() { @@ -278,6 +281,13 @@ func (x *Operation) GetTypeDescription() string { return "" } +func (x *Operation) GetEncryptionSettings() *EncryptionSettings { + if x != nil { + return x.EncryptionSettings + } + return nil +} + var File_ydbcp_v1alpha1_operation_proto protoreflect.FileDescriptor var file_ydbcp_v1alpha1_operation_proto_rawDesc = []byte{ @@ -289,7 +299,7 @@ var file_ydbcp_v1alpha1_operation_proto_rawDesc = []byte{ 0x64, 0x62, 0x63, 0x70, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd8, 0x06, 0x0a, 0x09, 0x4f, + 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xad, 0x07, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, @@ -334,20 +344,26 @@ var file_ydbcp_v1alpha1_operation_proto_rawDesc = []byte{ 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, - 0x74, 0x79, 0x70, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0x83, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, - 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, - 0x08, 0x0a, 0x04, 0x44, 0x4f, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, - 0x4f, 0x52, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x49, - 0x4e, 0x47, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x45, 0x44, - 0x10, 0x05, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x41, 0x52, 0x54, 0x5f, 0x43, 0x41, 0x4e, 0x43, - 0x45, 0x4c, 0x4c, 0x49, 0x4e, 0x47, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, - 0x49, 0x4e, 0x47, 0x10, 0x07, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x79, 0x64, 0x62, 0x2d, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, - 0x2f, 0x79, 0x64, 0x62, 0x63, 0x70, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x79, 0x64, 0x62, 0x63, 0x70, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, - 0x79, 0x64, 0x62, 0x63, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x79, 0x70, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x53, 0x0a, 0x13, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x79, + 0x64, 0x62, 0x63, 0x70, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6e, + 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x52, 0x12, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, + 0x69, 0x6e, 0x67, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x16, 0x0a, 0x12, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, + 0x4e, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x4f, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x09, + 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x41, 0x4e, + 0x43, 0x45, 0x4c, 0x4c, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x41, 0x4e, + 0x43, 0x45, 0x4c, 0x45, 0x44, 0x10, 0x05, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x41, 0x52, 0x54, + 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x49, 0x4e, 0x47, 0x10, 0x06, 0x12, 0x0b, 0x0a, + 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x07, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x79, 0x64, 0x62, 0x2d, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x79, 0x64, 0x62, 0x63, 0x70, 0x2f, 0x70, 0x6b, 0x67, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x79, 0x64, 0x62, 0x63, 0x70, 0x2f, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x3b, 0x79, 0x64, 0x62, 0x63, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -370,17 +386,19 @@ var file_ydbcp_v1alpha1_operation_proto_goTypes = []any{ (*AuditInfo)(nil), // 2: ydbcp.v1alpha1.AuditInfo (*timestamppb.Timestamp)(nil), // 3: google.protobuf.Timestamp (*RetryConfig)(nil), // 4: ydbcp.v1alpha1.RetryConfig + (*EncryptionSettings)(nil), // 5: ydbcp.v1alpha1.EncryptionSettings } var file_ydbcp_v1alpha1_operation_proto_depIdxs = []int32{ 2, // 0: ydbcp.v1alpha1.Operation.audit:type_name -> ydbcp.v1alpha1.AuditInfo 0, // 1: ydbcp.v1alpha1.Operation.status:type_name -> ydbcp.v1alpha1.Operation.Status 3, // 2: ydbcp.v1alpha1.Operation.updated_at:type_name -> google.protobuf.Timestamp 4, // 3: ydbcp.v1alpha1.Operation.retry_config:type_name -> ydbcp.v1alpha1.RetryConfig - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 5, // 4: ydbcp.v1alpha1.Operation.encryption_settings:type_name -> ydbcp.v1alpha1.EncryptionSettings + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_ydbcp_v1alpha1_operation_proto_init() } diff --git a/pkg/proto/ydbcp/v1alpha1/operation.proto b/pkg/proto/ydbcp/v1alpha1/operation.proto index 28467b5f..f9243c7a 100644 --- a/pkg/proto/ydbcp/v1alpha1/operation.proto +++ b/pkg/proto/ydbcp/v1alpha1/operation.proto @@ -54,4 +54,7 @@ message Operation { RetryConfig retry_config = 16; // Human readable description for the operation type. string type_description = 17; + // Backup encryption settings, + // unspecified field means the backup is unencrypted (only for MakeBackup operation). + EncryptionSettings encryption_settings = 18; } \ No newline at end of file