@@ -18,7 +18,11 @@ package manager
1818
1919import (
2020 "context"
21+ "crypto/rand"
2122 "embed"
23+ "encoding/base64"
24+ "encoding/hex"
25+ "errors"
2226 "fmt"
2327 "io/fs"
2428 "net"
@@ -29,6 +33,8 @@ import (
2933 "google.golang.org/grpc"
3034 "gorm.io/gorm"
3135
36+ "bytes"
37+
3238 logger "d7y.io/dragonfly/v2/internal/dflog"
3339 "d7y.io/dragonfly/v2/internal/ratelimiter"
3440 "d7y.io/dragonfly/v2/manager/cache"
@@ -37,6 +43,7 @@ import (
3743 managergc "d7y.io/dragonfly/v2/manager/gc"
3844 "d7y.io/dragonfly/v2/manager/job"
3945 "d7y.io/dragonfly/v2/manager/metrics"
46+ "d7y.io/dragonfly/v2/manager/models"
4047 "d7y.io/dragonfly/v2/manager/permission/rbac"
4148 "d7y.io/dragonfly/v2/manager/router"
4249 "d7y.io/dragonfly/v2/manager/rpcserver"
@@ -48,6 +55,7 @@ import (
4855 "d7y.io/dragonfly/v2/pkg/objectstorage"
4956 "d7y.io/dragonfly/v2/pkg/redis"
5057 "d7y.io/dragonfly/v2/pkg/rpc"
58+ "gorm.io/plugin/soft_delete"
5159)
5260
5361const (
@@ -122,6 +130,16 @@ func New(cfg *config.Config, d dfpath.Dfpath) (*Server, error) {
122130 return nil , err
123131 }
124132
133+ // Initialize encryption key
134+ if cfg .Encryption .Enable {
135+ logger .Infof ("Encryption enabled" )
136+ if err := initializeEncryptionKey (cfg , db .DB ); err != nil {
137+ return nil , err
138+ }
139+ } else {
140+ logger .Infof ("Encryption disabled" )
141+ }
142+
125143 // Initialize enforcer.
126144 enforcer , err := rbac .NewEnforcer (db .DB )
127145 if err != nil {
@@ -250,6 +268,104 @@ func registerGCTasks(gc pkggc.GC, db *gorm.DB) error {
250268 return nil
251269}
252270
271+ // initializeEncryptionKey
272+ func initializeEncryptionKey (cfg * config.Config , db * gorm.DB ) error {
273+ // db.Delete(&models.EncryptionKey{}, "1 = 1")
274+
275+ var existingKey models.EncryptionKey
276+ hasDBKey := false
277+ if err := db .First (& existingKey ).Error ; err == nil {
278+ hasDBKey = true
279+ } else if ! errors .Is (err , gorm .ErrRecordNotFound ) {
280+ return fmt .Errorf ("failed to check encryption key: %v" , err )
281+ }
282+
283+ if cfg .Encryption .Key != nil {
284+ configKey := cfg .Encryption .Key
285+ keyBytes := configKey [:]
286+ if hasDBKey {
287+ // compare key in config with key in db
288+ if bytes .Equal (existingKey .Key , keyBytes ) {
289+ logger .Infof (
290+ "encryption key in config file is the same as in database, key(hex): %s, key(base64): %s" ,
291+ hex .EncodeToString (keyBytes ),
292+ base64 .StdEncoding .EncodeToString (keyBytes ),
293+ )
294+ return nil
295+ }
296+ // key in config is different from key in db, overwrite db
297+ oldKeyHex := hex .EncodeToString (existingKey .Key )
298+ oldKeyBase64 := base64 .StdEncoding .EncodeToString (existingKey .Key )
299+ newKeyHex := hex .EncodeToString (keyBytes )
300+ newKeyBase64 := base64 .StdEncoding .EncodeToString (keyBytes )
301+
302+ if err := db .Model (& existingKey ).Update ("key" , keyBytes ).Error ; err != nil {
303+ return fmt .Errorf ("failed to update encryption key in database: %v" , err )
304+ }
305+
306+ logger .Infof (
307+ "encryption key in database is overwritten by config file, old key(hex): %s, old key(base64): %s, new key(hex): %s, new key(base64): %s" ,
308+ oldKeyHex , oldKeyBase64 , newKeyHex , newKeyBase64 ,
309+ )
310+ return nil
311+ } else {
312+ // config has key, but db has no key, write it into db
313+ // check soft delete
314+ var oldKey models.EncryptionKey
315+ if err := db .Unscoped ().Where ("`key` = ?" , keyBytes ).First (& oldKey ).Error ; err == nil {
316+ if oldKey .IsDel != soft_delete .DeletedAt (soft_delete .FlagActived ) {
317+ // restore the key soft deleted
318+ db .Unscoped ().Model (& oldKey ).Update ("is_del" , soft_delete .FlagActived )
319+ logger .Infof ("Restore the key which was soft deleted before" )
320+ } else {
321+ logger .Fatalf ("key should be soft deleted in this situation" )
322+ }
323+ } else if errors .Is (err , gorm .ErrRecordNotFound ) {
324+ // insert new key
325+ if err := db .Create (& models.EncryptionKey {Key : keyBytes }).Error ; err != nil {
326+ return fmt .Errorf ("failed to save encryption key to database: %v" , err )
327+ }
328+ } else {
329+ // return fmt.Errorf("unknow failed when update encryption key in database: %v", err)
330+ logger .Fatalf ("unknow failed when update encryption key in database: %v" , err )
331+ // panic(err)
332+ }
333+
334+ logger .Infof (
335+ "encryption key from config file is saved to database, key(hex): %s, key(base64): %s" ,
336+ hex .EncodeToString (keyBytes ),
337+ base64 .StdEncoding .EncodeToString (keyBytes ),
338+ )
339+ return nil
340+ }
341+ }
342+
343+ // config has no key and db has key
344+ if hasDBKey {
345+ logger .Infof (
346+ "encryption key loaded from database, key(hex): %s, key(base64): %s" ,
347+ hex .EncodeToString (existingKey .Key ),
348+ base64 .StdEncoding .EncodeToString (existingKey .Key ),
349+ )
350+ return nil
351+ }
352+
353+ // config and db both have no key, generate one
354+ keyBytes := make ([]byte , 32 )
355+ if _ , err := rand .Read (keyBytes ); err != nil {
356+ return fmt .Errorf ("failed to generate random encryption key: %v" , err )
357+ }
358+ if err := db .Create (& models.EncryptionKey {Key : keyBytes }).Error ; err != nil {
359+ return fmt .Errorf ("failed to save random encryption key to database: %v" , err )
360+ }
361+ logger .Infof (
362+ "generated random encryption key and saved to database, key(hex): %s, key(base64): %s" ,
363+ hex .EncodeToString (keyBytes ),
364+ base64 .StdEncoding .EncodeToString (keyBytes ),
365+ )
366+ return nil
367+ }
368+
253369// Serve starts the manager server.
254370func (s * Server ) Serve () error {
255371 // Started REST server.
0 commit comments