Browse Source

Switch encryption from OpenSSL to GnuPG

Emmanuel Bouthenot 1 year ago
parent
commit
5b1f6b9e15
2 changed files with 63 additions and 13 deletions
  1. 19 0
      Readme.md
  2. 44 13
      autopostgresqlbackup

+ 19 - 0
Readme.md

@@ -32,6 +32,25 @@ That's it!
  * 2005: AutoPostgreSQLBackup was written by AutoPostgreSQLBackup (with some contributions of Friedrich Lobenstock)
    * Project webpage was http://autopgsqlbackup.frozenpc.net/ (offline)
 
+## Encryption
+
+Encryption (asymmetric) is now done with GnuPG, you just need to add the
+public key (armored or not) you want to encrypt the data to in the file pointed by the `${ENCRYPTION_PUBLIC_KEY}` configuration setting.
+
+Export your public key:
+
+`gpg --export 0xY0URK3Y1D --output mypubkey.gpg`
+
+or
+
+`gpg --export --armor 0xY0URK3Y1D --output mypubkey.asc`
+
+then copy `mypubkey.asc` or `mypubkey.gpg` to the path pointed by the `${ENCRYPTION_PUBLIC_KEY}` configuration setting and set the `${ENCRYPTION}` setting to `yes`.
+
+## OpenSSL Encryption
+
+Starting from version 2.0 encryption with OpenSSL is no longer supported as [it was discovered](https://github.com/k0lter/autopostgresqlbackup/issues/10) (but also [known for quite some time](https://github.com/cytopia/mysqldump-secure/issues/21)) that encrypting large files with [OpenSSL silently fail](https://github.com/openssl/openssl/issues/2515) and that decrypting these files is [close to be impossible](https://github.com/imreFitos/large_smime_decrypt).
+
 ## Authors
 
  * Emmanuel Bouthenot (Current maintainer)

+ 44 - 13
autopostgresqlbackup

@@ -96,26 +96,21 @@ EXT="sql"
 PERM=600
 
 # Encryption settings
-# (inspired by http://blog.altudov.com/2010/09/27/using-openssl-for-asymmetric-encryption-of-backups/)
 #
 # It is recommended to backup into a staging directory, and then use the
 # POSTBACKUP script to sync the encrypted files to the desired location.
 #
-# Encryption uses private/public keys. You can generate the key pairs like the following:
-# openssl req -x509 -nodes -days 100000 -newkey rsa:2048 -keyout backup.key -out backup.crt -subj '/'
+# For now the only encryption method supported is using GnuPG
 #
 # Decryption:
-# openssl smime -decrypt -in backup.sql.gz.enc -binary -inform DEM -inkey backup.key -out backup.sql.gz
-
+# gpg --decrypt --output backup.sql.gz backup.sql.gz.enc
+#
 # Enable encryption
 ENCRYPTION=no
 
 # Encryption public key (path to the key)
 ENCRYPTION_PUBLIC_KEY=""
 
-# Encryption Cipher (see enc manpage)
-ENCRYPTION_CIPHER="aes256"
-
 # Suffix for encyrpted files
 ENCRYPTION_SUFFIX=".enc"
 
@@ -204,6 +199,9 @@ LOG_FILE="${LOG_DIR}/${NAME}_${DBHOST//\//_}-$(date '+%Y-%m-%d_%Hh%Mm').log"
 # Debug mode
 DEBUG="no"
 
+# Encryption prerequisites
+GPG_HOMEDIR=
+
 # pg_dump options
 if [ -n "${OPT}" ]; then
     IFS=" " read -r -a PG_OPTIONS <<< "${OPT}"
@@ -302,6 +300,15 @@ log_warn() {
 }
 # }}}
 
+# {{{ gpg_setup()
+gpg_setup() {
+    GPG_HOMEDIR="$(mktemp --quiet --directory -t "${NAME}.XXXXXX")"
+    chmod 700 "${GPG_HOMEDIR}"
+    log_debug "With encryption enabled creating a temporary GnuPG home in ${GPG_HOMEDIR}"
+    gpg --quiet --homedir "${GPG_HOMEDIR}" --quick-gen-key --batch --passphrase-file /dev/null "root@$(hostname --fqdn)"
+}
+# }}}
+
 # {{{ dblist()
 dblist () {
     local cmd_prog cmd_args raw_dblist dblist dbexcl databases
@@ -385,8 +392,8 @@ dbdump () {
 
 # {{{ encryption()
 encryption() {
-    log_debug "Encrypting using cypher ${ENCRYPTION_CIPHER} and public key ${ENCRYPTION_PUBLIC_KEY}"
-    openssl smime -encrypt -${ENCRYPTION_CIPHER} -binary -outform DEM "${ENCRYPTION_PUBLIC_KEY}" 2>&7
+    log_debug "Encrypting using public key ${ENCRYPTION_PUBLIC_KEY}"
+    gpg --homedir "${GPG_HOMEDIR}" --encrypt --passphrase-file /dev/null --recipient-file "${ENCRYPTION_PUBLIC_KEY}" 2>&7
 }
 # }}}
 
@@ -552,9 +559,28 @@ if [ -n "${COMP}" ]; then
     fi
 fi
 
-if [ "${ENCRYPTION}" = "yes" ] && ! command -v "openssl" >/dev/null ; then
-    log_warn "Disabling encryption, 'openssl' command not found"
-    ENCRYPTION="no"
+if [ "${ENCRYPTION}" = "yes" ]; then
+    if [ ! -s "${ENCRYPTION_PUBLIC_KEY}" ]; then
+        log_warn "Disabling encryption, '${ENCRYPTION_PUBLIC_KEY}' is empty or does not exists"
+        ENCRYPTION="no"
+    elif ! command -v "gpg" >/dev/null ; then
+        log_warn "Disabling encryption, 'gpg' command not found"
+        ENCRYPTION="no"
+    else
+        gpg_setup
+        if ! keyinfo="$(gpg --quiet --homedir "${GPG_HOMEDIR}" "${ENCRYPTION_PUBLIC_KEY}" 2>/dev/null)"; then
+            log_warn "Disabling encryption, key in '${ENCRYPTION_PUBLIC_KEY}' does not seems to be a valid public key"
+            ENCRYPTION="no"
+            if command -v "openssl" >/dev/null && openssl x509 -noout -in "${ENCRYPTION_PUBLIC_KEY}" >/dev/null 2>&1; then
+                log_warn "public key in '${ENCRYPTION_PUBLIC_KEY}' seems to be in PEM format"
+                log_warn "Encryption using openssl is no longer supported: see ${HOMEPAGE}#openssl-encryption"
+            fi
+        else
+            keyfp="$(echo "${keyinfo}" | sed -r -n 's/^\s*([a-z0-9]+)\s*$/\1/pi')"
+            keyuid="$(echo "${keyinfo}" | sed -r -n 's/^\s*uid\s+(\S.*)$/\1/pi' | head -n1)"
+            log_info "Encryption public key is: 0x${keyfp} (${keyuid})"
+        fi
+    fi
 fi
 
 log_info "Backup Start: $(date)"
@@ -639,6 +665,11 @@ else
     rc=0
 fi
 
+# Cleanup GnuPG home dir
+if [ -d "${GPG_HOMEDIR}" ]; then
+    rm -rf "${GPG_HOMEDIR}"
+fi
+
 # Clean up log files
 rm -f "${LOG_FILE}"