1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-02 20:35:25 +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

@ -49,12 +49,12 @@ func initCLI() *portainer.CLIFlags {
var cliService portainer.CLIService = &cli.Service{}
flags, err := cliService.ParseFlags(portainer.APIVersion)
if err != nil {
log.Fatalf("Failed parsing flags: %v", err)
logrus.Fatalf("Failed parsing flags: %v", err)
}
err = cliService.ValidateFlags(flags)
if err != nil {
log.Fatalf("Failed validating flags:%v", err)
logrus.Fatalf("Failed validating flags:%v", err)
}
return flags
}
@ -62,7 +62,7 @@ func initCLI() *portainer.CLIFlags {
func initFileService(dataStorePath string) portainer.FileService {
fileService, err := filesystem.NewService(dataStorePath, "")
if err != nil {
log.Fatalf("Failed creating file service: %v", err)
logrus.Fatalf("Failed creating file service: %v", err)
}
return fileService
}
@ -70,7 +70,7 @@ func initFileService(dataStorePath string) portainer.FileService {
func initDataStore(flags *portainer.CLIFlags, secretKey []byte, fileService portainer.FileService, shutdownCtx context.Context) dataservices.DataStore {
connection, err := database.NewDatabase("boltdb", *flags.Data, secretKey)
if err != nil {
log.Fatalf("failed creating database connection: %s", err)
logrus.Fatalf("failed creating database connection: %s", err)
}
if bconn, ok := connection.(*boltdb.DbConnection); ok {
@ -78,22 +78,22 @@ func initDataStore(flags *portainer.CLIFlags, secretKey []byte, fileService port
bconn.MaxBatchDelay = *flags.MaxBatchDelay
bconn.InitialMmapSize = *flags.InitialMmapSize
} else {
log.Fatalf("failed creating database connection: expecting a boltdb database type but a different one was received")
logrus.Fatalf("failed creating database connection: expecting a boltdb database type but a different one was received")
}
store := datastore.NewStore(*flags.Data, fileService, connection)
isNew, err := store.Open()
if err != nil {
log.Fatalf("Failed opening store: %v", err)
logrus.Fatalf("Failed opening store: %v", err)
}
if *flags.Rollback {
err := store.Rollback(false)
if err != nil {
log.Fatalf("Failed rolling back: %v", err)
logrus.Fatalf("Failed rolling back: %v", err)
}
log.Println("Exiting rollback")
logrus.Println("Exiting rollback")
os.Exit(0)
return nil
}
@ -101,21 +101,26 @@ func initDataStore(flags *portainer.CLIFlags, secretKey []byte, fileService port
// Init sets some defaults - it's basically a migration
err = store.Init()
if err != nil {
log.Fatalf("Failed initializing data store: %v", err)
logrus.Fatalf("Failed initializing data store: %v", err)
}
if isNew {
// from MigrateData
store.VersionService.StoreDBVersion(portainer.DBVersion)
err := updateSettingsFromFlags(store, flags)
if err != nil {
logrus.Fatalf("Failed updating settings from flags: %v", err)
}
} else {
storedVersion, err := store.VersionService.DBVersion()
if err != nil {
log.Fatalf("Something Failed during creation of new database: %v", err)
logrus.Fatalf("Something Failed during creation of new database: %v", err)
}
if storedVersion != portainer.DBVersion {
err = store.MigrateData()
if err != nil {
log.Fatalf("Failed migration: %v", err)
logrus.Fatalf("Failed migration: %v", err)
}
}
}
@ -146,7 +151,7 @@ func initDataStore(flags *portainer.CLIFlags, secretKey []byte, fileService port
func initComposeStackManager(assetsPath string, configPath string, reverseTunnelService portainer.ReverseTunnelService, proxyManager *proxy.Manager) portainer.ComposeStackManager {
composeWrapper, err := exec.NewComposeStackManager(assetsPath, configPath, proxyManager)
if err != nil {
log.Fatalf("Failed creating compose manager: %v", err)
logrus.Fatalf("Failed creating compose manager: %v", err)
}
return composeWrapper
@ -329,9 +334,9 @@ func enableFeaturesFromFlags(dataStore dataservices.DataStore, flags *portainer.
}
if featureState {
log.Printf("Feature %v : on", *correspondingFeature)
logrus.Printf("Feature %v : on", *correspondingFeature)
} else {
log.Printf("Feature %v : off", *correspondingFeature)
logrus.Printf("Feature %v : off", *correspondingFeature)
}
settings.FeatureFlagSettings[*correspondingFeature] = featureState
@ -360,7 +365,7 @@ func generateAndStoreKeyPair(fileService portainer.FileService, signatureService
func initKeyPair(fileService portainer.FileService, signatureService portainer.DigitalSignatureService) error {
existingKeyPair, err := fileService.KeyPairFilesExist()
if err != nil {
log.Fatalf("Failed checking for existing key pair: %v", err)
logrus.Fatalf("Failed checking for existing key pair: %v", err)
}
if existingKeyPair {
@ -431,7 +436,7 @@ func createTLSSecuredEndpoint(flags *portainer.CLIFlags, dataStore dataservices.
err := snapshotService.SnapshotEndpoint(endpoint)
if err != nil {
log.Printf("http error: environment snapshot error (environment=%s, URL=%s) (err=%s)\n", endpoint.Name, endpoint.URL, err)
logrus.Printf("http error: environment snapshot error (environment=%s, URL=%s) (err=%s)\n", endpoint.Name, endpoint.URL, err)
}
return dataStore.Endpoint().Create(endpoint)
@ -477,7 +482,7 @@ func createUnsecuredEndpoint(endpointURL string, dataStore dataservices.DataStor
err := snapshotService.SnapshotEndpoint(endpoint)
if err != nil {
log.Printf("http error: environment snapshot error (environment=%s, URL=%s) (err=%s)\n", endpoint.Name, endpoint.URL, err)
logrus.Printf("http error: environment snapshot error (environment=%s, URL=%s) (err=%s)\n", endpoint.Name, endpoint.URL, err)
}
return dataStore.Endpoint().Create(endpoint)
@ -494,7 +499,7 @@ func initEndpoint(flags *portainer.CLIFlags, dataStore dataservices.DataStore, s
}
if len(endpoints) > 0 {
log.Println("Instance already has defined environments. Skipping the environment defined via CLI.")
logrus.Println("Instance already has defined environments. Skipping the environment defined via CLI.")
return nil
}
@ -508,9 +513,9 @@ func loadEncryptionSecretKey(keyfilename string) []byte {
content, err := os.ReadFile(path.Join("/run/secrets", keyfilename))
if err != nil {
if os.IsNotExist(err) {
log.Printf("Encryption key file `%s` not present", keyfilename)
logrus.Printf("Encryption key file `%s` not present", keyfilename)
} else {
log.Printf("Error reading encryption key file: %v", err)
logrus.Printf("Error reading encryption key file: %v", err)
}
return nil
@ -527,33 +532,33 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
fileService := initFileService(*flags.Data)
encryptionKey := loadEncryptionSecretKey(*flags.SecretKeyName)
if encryptionKey == nil {
log.Println("proceeding without encryption key")
logrus.Println("Proceeding without encryption key")
}
dataStore := initDataStore(flags, encryptionKey, fileService, shutdownCtx)
if err := dataStore.CheckCurrentEdition(); err != nil {
log.Fatal(err)
logrus.Fatal(err)
}
instanceID, err := dataStore.Version().InstanceID()
if err != nil {
log.Fatalf("Failed getting instance id: %v", err)
logrus.Fatalf("Failed getting instance id: %v", err)
}
apiKeyService := initAPIKeyService(dataStore)
settings, err := dataStore.Settings().Settings()
if err != nil {
log.Fatal(err)
logrus.Fatal(err)
}
jwtService, err := initJWTService(settings.UserSessionTimeout, dataStore)
if err != nil {
log.Fatalf("Failed initializing JWT service: %v", err)
logrus.Fatalf("Failed initializing JWT service: %v", err)
}
err = enableFeaturesFromFlags(dataStore, flags)
if err != nil {
log.Fatalf("Failed enabling feature flag: %v", err)
logrus.Fatalf("Failed enabling feature flag: %v", err)
}
ldapService := initLDAPService()
@ -567,17 +572,17 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
sslService, err := initSSLService(*flags.AddrHTTPS, *flags.Data, *flags.SSLCert, *flags.SSLKey, fileService, dataStore, shutdownTrigger)
if err != nil {
log.Fatal(err)
logrus.Fatal(err)
}
sslSettings, err := sslService.GetSSLSettings()
if err != nil {
log.Fatalf("Failed to get ssl settings: %s", err)
logrus.Fatalf("Failed to get ssl settings: %s", err)
}
err = initKeyPair(fileService, digitalSignatureService)
if err != nil {
log.Fatalf("Failed initializing key pair: %v", err)
logrus.Fatalf("Failed initializing key pair: %v", err)
}
reverseTunnelService := chisel.NewService(dataStore, shutdownCtx)
@ -587,7 +592,7 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
snapshotService, err := initSnapshotService(*flags.SnapshotInterval, dataStore, dockerClientFactory, kubernetesClientFactory, shutdownCtx)
if err != nil {
log.Fatalf("Failed initializing snapshot service: %v", err)
logrus.Fatalf("Failed initializing snapshot service: %v", err)
}
snapshotService.Start()
@ -608,37 +613,37 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
swarmStackManager, err := initSwarmStackManager(*flags.Assets, dockerConfigPath, digitalSignatureService, fileService, reverseTunnelService, dataStore)
if err != nil {
log.Fatalf("Failed initializing swarm stack manager: %v", err)
logrus.Fatalf("Failed initializing swarm stack manager: %v", err)
}
kubernetesDeployer := initKubernetesDeployer(kubernetesTokenCacheManager, kubernetesClientFactory, dataStore, reverseTunnelService, digitalSignatureService, proxyManager, *flags.Assets)
helmPackageManager, err := initHelmPackageManager(*flags.Assets)
if err != nil {
log.Fatalf("Failed initializing helm package manager: %v", err)
logrus.Fatalf("Failed initializing helm package manager: %v", err)
}
err = edge.LoadEdgeJobs(dataStore, reverseTunnelService)
if err != nil {
log.Fatalf("Failed loading edge jobs from database: %v", err)
logrus.Fatalf("Failed loading edge jobs from database: %v", err)
}
applicationStatus := initStatus(instanceID)
err = initEndpoint(flags, dataStore, snapshotService)
if err != nil {
log.Fatalf("Failed initializing environment: %v", err)
logrus.Fatalf("Failed initializing environment: %v", err)
}
adminPasswordHash := ""
if *flags.AdminPasswordFile != "" {
content, err := fileService.GetFileContent(*flags.AdminPasswordFile, "")
if err != nil {
log.Fatalf("Failed getting admin password file: %v", err)
logrus.Fatalf("Failed getting admin password file: %v", err)
}
adminPasswordHash, err = cryptoService.Hash(strings.TrimSuffix(string(content), "\n"))
if err != nil {
log.Fatalf("Failed hashing admin password: %v", err)
logrus.Fatalf("Failed hashing admin password: %v", err)
}
} else if *flags.AdminPassword != "" {
adminPasswordHash = *flags.AdminPassword
@ -647,11 +652,11 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
if adminPasswordHash != "" {
users, err := dataStore.User().UsersByRole(portainer.AdministratorRole)
if err != nil {
log.Fatalf("Failed getting admin user: %v", err)
logrus.Fatalf("Failed getting admin user: %v", err)
}
if len(users) == 0 {
log.Println("Created admin user with the given password.")
logrus.Println("Created admin user with the given password.")
user := &portainer.User{
Username: "admin",
Role: portainer.AdministratorRole,
@ -659,21 +664,21 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
}
err := dataStore.User().Create(user)
if err != nil {
log.Fatalf("Failed creating admin user: %v", err)
logrus.Fatalf("Failed creating admin user: %v", err)
}
} else {
log.Println("Instance already has an administrator user defined. Skipping admin password related flags.")
logrus.Println("Instance already has an administrator user defined. Skipping admin password related flags.")
}
}
err = reverseTunnelService.StartTunnelServer(*flags.TunnelAddr, *flags.TunnelPort, snapshotService)
if err != nil {
log.Fatalf("Failed starting tunnel server: %v", err)
logrus.Fatalf("Failed starting tunnel server: %v", err)
}
sslDBSettings, err := dataStore.SSLSettings().Settings()
if err != nil {
log.Fatalf("Failed to fetch ssl settings from DB")
logrus.Fatalf("Failed to fetch ssl settings from DB")
}
scheduler := scheduler.NewScheduler(shutdownCtx)
@ -724,8 +729,8 @@ func main() {
for {
server := buildServer(flags)
log.Printf("[INFO] [cmd,main] Starting Portainer version %s\n", portainer.APIVersion)
logrus.Printf("[INFO] [cmd,main] Starting Portainer version %s\n", portainer.APIVersion)
err := server.Start()
log.Printf("[INFO] [cmd,main] Http server exited: %v\n", err)
logrus.Printf("[INFO] [cmd,main] Http server exited: %v\n", err)
}
}