feat: add backup encryption using public key and decryption using private key

This commit is contained in:
Jonas Kaninda
2024-10-08 11:04:46 +02:00
parent 815aae28f8
commit 35c4a5475e
9 changed files with 339 additions and 69 deletions

View File

@@ -7,7 +7,6 @@
package pkg
import (
"fmt"
"github.com/jkaninda/pg-bkup/utils"
"github.com/spf13/cobra"
"os"
@@ -24,75 +23,76 @@ func StartRestore(cmd *cobra.Command) {
case "local":
utils.Info("Restore database from local")
copyToTmp(storagePath, restoreConf.file)
RestoreDatabase(dbConf, restoreConf.file)
RestoreDatabase(dbConf, restoreConf)
case "s3", "S3":
restoreFromS3(dbConf, restoreConf.file, restoreConf.bucket, restoreConf.s3Path)
restoreFromS3(dbConf, restoreConf)
case "ssh", "SSH", "remote":
restoreFromRemote(dbConf, restoreConf.file, restoreConf.remotePath)
restoreFromRemote(dbConf, restoreConf)
case "ftp", "FTP":
restoreFromFTP(dbConf, restoreConf.file, restoreConf.remotePath)
restoreFromFTP(dbConf, restoreConf)
default:
utils.Info("Restore database from local")
copyToTmp(storagePath, restoreConf.file)
RestoreDatabase(dbConf, restoreConf.file)
RestoreDatabase(dbConf, restoreConf)
}
}
func restoreFromS3(db *dbConfig, file, bucket, s3Path string) {
func restoreFromS3(db *dbConfig, conf *RestoreConfig) {
utils.Info("Restore database from s3")
err := DownloadFile(tmpPath, file, bucket, s3Path)
err := DownloadFile(tmpPath, conf.file, conf.bucket, conf.s3Path)
if err != nil {
utils.Fatal("Error download file from s3 %s %v ", file, err)
utils.Fatal("Error download file from s3 %s %v ", conf.file, err)
}
RestoreDatabase(db, file)
RestoreDatabase(db, conf)
}
func restoreFromRemote(db *dbConfig, file, remotePath string) {
func restoreFromRemote(db *dbConfig, conf *RestoreConfig) {
utils.Info("Restore database from remote server")
err := CopyFromRemote(file, remotePath)
err := CopyFromRemote(conf.file, conf.remotePath)
if err != nil {
utils.Fatal("Error download file from remote server: %s %v", filepath.Join(remotePath, file), err)
utils.Fatal("Error download file from remote server: %s %v", filepath.Join(conf.remotePath, conf.file), err)
}
RestoreDatabase(db, file)
RestoreDatabase(db, conf)
}
func restoreFromFTP(db *dbConfig, file, remotePath string) {
func restoreFromFTP(db *dbConfig, conf *RestoreConfig) {
utils.Info("Restore database from FTP server")
err := CopyFromFTP(file, remotePath)
err := CopyFromFTP(conf.file, conf.remotePath)
if err != nil {
utils.Fatal("Error download file from FTP server: %s %v", filepath.Join(remotePath, file), err)
utils.Fatal("Error download file from FTP server: %s %v", filepath.Join(conf.remotePath, conf.file), err)
}
RestoreDatabase(db, file)
RestoreDatabase(db, conf)
}
// RestoreDatabase restore database
func RestoreDatabase(db *dbConfig, file string) {
gpgPassphrase := os.Getenv("GPG_PASSPHRASE")
if file == "" {
func RestoreDatabase(db *dbConfig, conf *RestoreConfig) {
if conf.file == "" {
utils.Fatal("Error, file required")
}
extension := filepath.Ext(fmt.Sprintf("%s/%s", tmpPath, file))
extension := filepath.Ext(filepath.Join(tmpPath, conf.file))
if extension == ".gpg" {
if gpgPassphrase == "" {
utils.Fatal("Error: GPG passphrase is required, your file seems to be a GPG file.\nYou need to provide GPG keys. GPG_PASSPHRASE environment variable is required.")
} else {
//Decrypt file
err := Decrypt(filepath.Join(tmpPath, file), gpgPassphrase)
if conf.usingKey {
err := decrypt(filepath.Join(tmpPath, conf.file), conf.privateKey, conf.passphrase)
if err != nil {
utils.Fatal("Error decrypting file %s %v", file, err)
utils.Fatal("Error during decrypting backup %v", err)
}
} else {
if conf.passphrase == "" {
utils.Error("Error, passphrase or private key required")
utils.Fatal("Your file seems to be a GPG file.\nYou need to provide GPG keys. GPG_PASSPHRASE or GPG_PRIVATE_KEY environment variable is required.")
} else {
//Decrypt file
err := Decrypt(filepath.Join(tmpPath, conf.file), conf.passphrase)
if err != nil {
utils.Fatal("Error decrypting file %s %v", file, err)
}
//Update file name
file = RemoveLastExtension(file)
}
//Update file name
file = RemoveLastExtension(file)
}
}
err := utils.CheckEnvVars(dbHVars)
if err != nil {
utils.Error("Please make sure all required environment variables for database are set")
utils.Fatal("Error checking environment variables: %s", err)
}
if utils.FileExists(fmt.Sprintf("%s/%s", tmpPath, file)) {
if utils.FileExists(filepath.Join(tmpPath, conf.file)) {
err := os.Setenv("PGPASSWORD", db.dbPassword)
if err != nil {
@@ -101,10 +101,10 @@ func RestoreDatabase(db *dbConfig, file string) {
testDatabaseConnection(db)
utils.Info("Restoring database...")
extension := filepath.Ext(file)
extension := filepath.Ext(conf.file)
// Restore from compressed file / .sql.gz
if extension == ".gz" {
str := "zcat " + filepath.Join(tmpPath, file) + " | psql -h " + db.dbHost + " -p " + db.dbPort + " -U " + db.dbUserName + " -v -d " + db.dbName
str := "zcat " + filepath.Join(tmpPath, conf.file) + " | psql -h " + db.dbHost + " -p " + db.dbPort + " -U " + db.dbUserName + " -v -d " + db.dbName
_, err := exec.Command("sh", "-c", str).Output()
if err != nil {
utils.Fatal("Error, in restoring the database %v", err)
@@ -130,6 +130,6 @@ func RestoreDatabase(db *dbConfig, file string) {
}
} else {
utils.Fatal("File not found in %s", fmt.Sprintf("%s/%s", tmpPath, file))
utils.Fatal("File not found in %s", filepath.Join(tmpPath, conf.file))
}
}