1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-24 15:59:41 +02:00

Fix(db): needs encryption migration function fixed EE-2414 (#6494)

* fix(db) NeedsEncryptionMigration EE-2414
* fix for case where we started encrypted and restore unencrypted.  We don't want to have two databases
* fix(db): handle decryption error EE-2466

Co-authored-by: Matt Hook <hookenz@gmail.com>
Co-authored-by: andres-portainer <andres-portainer@users.noreply.github.com>
This commit is contained in:
Prabhat Khera 2022-02-02 09:53:59 +13:00 committed by GitHub
parent ad7f87122d
commit a8d3cda3fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 250 additions and 60 deletions

View file

@ -2,6 +2,7 @@ package boltdb
import (
"encoding/binary"
"errors"
"fmt"
"io"
"io/ioutil"
@ -10,7 +11,7 @@ import (
"time"
"github.com/boltdb/bolt"
"github.com/portainer/portainer/api/dataservices/errors"
dserrors "github.com/portainer/portainer/api/dataservices/errors"
"github.com/sirupsen/logrus"
)
@ -19,6 +20,11 @@ const (
EncryptedDatabaseFileName = "portainer.edb"
)
var (
ErrHaveEncryptedAndUnencrypted = errors.New("Portainer has detected both an encrypted and un-encrypted database and cannot start. Only one database should exist")
ErrHaveEncryptedWithNoKey = errors.New("The portainer database is encrypted, but no secret was loaded")
)
type DbConnection struct {
Path string
MaxBatchSize int
@ -64,19 +70,51 @@ func (connection *DbConnection) IsEncryptedStore() bool {
// NeedsEncryptionMigration returns true if database encryption is enabled and
// we have an un-encrypted DB that requires migration to an encrypted DB
func (connection *DbConnection) NeedsEncryptionMigration() bool {
if connection.EncryptionKey != nil {
dbFile := path.Join(connection.Path, DatabaseFileName)
if _, err := os.Stat(dbFile); err == nil {
return true
}
func (connection *DbConnection) NeedsEncryptionMigration() (bool, error) {
// This is an existing encrypted store or a new store.
// A new store will open encrypted from the outset
// Cases: Note, we need to check both portainer.db and portainer.edb
// to determine if it's a new store. We only need to differentiate between cases 2,3 and 5
// 1) portainer.edb + key => False
// 2) portainer.edb + no key => ERROR Fatal!
// 3) portainer.db + key => True (needs migration)
// 4) portainer.db + no key => False
// 5) NoDB (new) + key => False
// 6) NoDB (new) + no key => False
// 7) portainer.db & portainer.edb => ERROR Fatal!
// If we have a loaded encryption key, always set encrypted
if connection.EncryptionKey != nil {
connection.SetEncrypted(true)
}
return false
// Check for portainer.db
dbFile := path.Join(connection.Path, DatabaseFileName)
_, err := os.Stat(dbFile)
haveDbFile := err == nil
// Check for portainer.edb
edbFile := path.Join(connection.Path, EncryptedDatabaseFileName)
_, err = os.Stat(edbFile)
haveEdbFile := err == nil
if haveDbFile && haveEdbFile {
// 7 - encrypted and unencrypted db?
return false, ErrHaveEncryptedAndUnencrypted
}
if haveDbFile && connection.EncryptionKey != nil {
// 3 - needs migration
return true, nil
}
if haveEdbFile && connection.EncryptionKey == nil {
// 2 - encrypted db, but no key?
return false, ErrHaveEncryptedWithNoKey
}
// 1, 4, 5, 6
return false, nil
}
// Open opens and initializes the BoltDB database.
@ -159,7 +197,7 @@ func (connection *DbConnection) GetObject(bucketName string, key []byte, object
value := bucket.Get(key)
if value == nil {
return errors.ErrObjectNotFound
return dserrors.ErrObjectNotFound
}
data = make([]byte, len(value))