(cherry picked from commit bdeb032fba
)
Co-authored-by: Ankush Menat <ankush@frappe.io>
version-14
@@ -142,7 +142,7 @@ def restore( | |||||
is_partial, | is_partial, | ||||
validate_database_sql, | validate_database_sql, | ||||
) | ) | ||||
from frappe.utils.backups import Backup | |||||
from frappe.utils.backups import Backup, get_or_generate_backup_encryption_key | |||||
_backup = Backup(sql_file_path) | _backup = Backup(sql_file_path) | ||||
@@ -171,7 +171,7 @@ def restore( | |||||
else: | else: | ||||
click.secho("Encrypted backup file detected. Decrypting using site config.", fg="yellow") | click.secho("Encrypted backup file detected. Decrypting using site config.", fg="yellow") | ||||
encryption_key = frappe.get_site_config().encryption_key | |||||
encryption_key = get_or_generate_backup_encryption_key() | |||||
_backup.backup_decryption(encryption_key) | _backup.backup_decryption(encryption_key) | ||||
# Rollback on unsuccessful decryrption | # Rollback on unsuccessful decryrption | ||||
@@ -268,7 +268,7 @@ def restore( | |||||
@pass_context | @pass_context | ||||
def partial_restore(context, sql_file_path, verbose, encryption_key=None): | def partial_restore(context, sql_file_path, verbose, encryption_key=None): | ||||
from frappe.installer import extract_sql_from_archive, partial_restore | from frappe.installer import extract_sql_from_archive, partial_restore | ||||
from frappe.utils.backups import Backup | |||||
from frappe.utils.backups import Backup, get_or_generate_backup_encryption_key | |||||
if not os.path.exists(sql_file_path): | if not os.path.exists(sql_file_path): | ||||
print("Invalid path", sql_file_path) | print("Invalid path", sql_file_path) | ||||
@@ -304,7 +304,7 @@ def partial_restore(context, sql_file_path, verbose, encryption_key=None): | |||||
else: | else: | ||||
click.secho("Encrypted backup file detected. Decrypting using site config.", fg="yellow") | click.secho("Encrypted backup file detected. Decrypting using site config.", fg="yellow") | ||||
key = frappe.get_site_config().encryption_key | |||||
key = get_or_generate_backup_encryption_key() | |||||
_backup.backup_decryption(key) | _backup.backup_decryption(key) | ||||
@@ -208,4 +208,5 @@ frappe.patches.v14_0.update_auto_account_deletion_duration | |||||
frappe.patches.v14_0.update_integration_request | frappe.patches.v14_0.update_integration_request | ||||
frappe.patches.v14_0.set_document_expiry_default | frappe.patches.v14_0.set_document_expiry_default | ||||
frappe.patches.v14_0.delete_data_migration_tool | frappe.patches.v14_0.delete_data_migration_tool | ||||
frappe.patches.v14_0.set_suspend_email_queue_default | |||||
frappe.patches.v14_0.set_suspend_email_queue_default | |||||
frappe.patches.v14_0.different_encryption_key |
@@ -0,0 +1,16 @@ | |||||
import pathlib | |||||
import frappe | |||||
from frappe.installer import update_site_config | |||||
from frappe.utils.backups import BACKUP_ENCRYPTION_CONFIG_KEY, get_backup_path | |||||
def execute(): | |||||
if frappe.conf.get(BACKUP_ENCRYPTION_CONFIG_KEY): | |||||
return | |||||
backup_path = pathlib.Path(get_backup_path()) | |||||
encrypted_backups_present = bool(list(backup_path.glob("*-enc*"))) | |||||
if encrypted_backups_present: | |||||
update_site_config(BACKUP_ENCRYPTION_CONFIG_KEY, frappe.local.conf.encryption_key) |
@@ -11,12 +11,12 @@ from shutil import which | |||||
# imports - third party imports | # imports - third party imports | ||||
import click | import click | ||||
from cryptography.fernet import Fernet | |||||
# imports - module imports | # imports - module imports | ||||
import frappe | import frappe | ||||
from frappe import conf | from frappe import conf | ||||
from frappe.utils import cint, get_file_size, get_url, now, now_datetime | from frappe.utils import cint, get_file_size, get_url, now, now_datetime | ||||
from frappe.utils.password import get_encryption_key | |||||
# backup variable for backwards compatibility | # backup variable for backwards compatibility | ||||
verbose = False | verbose = False | ||||
@@ -24,6 +24,8 @@ compress = False | |||||
_verbose = verbose | _verbose = verbose | ||||
base_tables = ["__Auth", "__global_search", "__UserSettings"] | base_tables = ["__Auth", "__global_search", "__UserSettings"] | ||||
BACKUP_ENCRYPTION_CONFIG_KEY = "backup_encryption_key" | |||||
class BackupGenerator: | class BackupGenerator: | ||||
""" | """ | ||||
@@ -230,7 +232,7 @@ class BackupGenerator: | |||||
cmd_string = "gpg --yes --passphrase {passphrase} --pinentry-mode loopback -c {filelocation}" | cmd_string = "gpg --yes --passphrase {passphrase} --pinentry-mode loopback -c {filelocation}" | ||||
try: | try: | ||||
command = cmd_string.format( | command = cmd_string.format( | ||||
passphrase=get_encryption_key(), | |||||
passphrase=get_or_generate_backup_encryption_key(), | |||||
filelocation=path, | filelocation=path, | ||||
) | ) | ||||
@@ -628,7 +630,20 @@ def get_backup_path(): | |||||
@frappe.whitelist() | @frappe.whitelist() | ||||
def get_backup_encryption_key(): | def get_backup_encryption_key(): | ||||
frappe.only_for("System Manager") | frappe.only_for("System Manager") | ||||
return frappe.conf.encryption_key | |||||
return frappe.conf.get(BACKUP_ENCRYPTION_CONFIG_KEY) | |||||
def get_or_generate_backup_encryption_key(): | |||||
from frappe.installer import update_site_config | |||||
key = frappe.conf.get(BACKUP_ENCRYPTION_CONFIG_KEY) | |||||
if key: | |||||
return key | |||||
key = Fernet.generate_key().decode() | |||||
update_site_config(BACKUP_ENCRYPTION_CONFIG_KEY, key) | |||||
return key | |||||
class Backup: | class Backup: | ||||