diff --git a/ixc_django_docker/bin/transcrypt b/ixc_django_docker/bin/transcrypt index 4ca98b2..ba871ce 100755 --- a/ixc_django_docker/bin/transcrypt +++ b/ixc_django_docker/bin/transcrypt @@ -497,6 +497,20 @@ clean_gitconfig() { fi } +# Remove from the local Git DB any objects containing the cached plaintext of +# secret files, created due to the setting diff.crypt.cachetextconv='true' +remove_cached_plaintext() { + # Delete ref to cached plaintext objects, to leave these objects + # unreferenced and available for removal + git update-ref -d refs/notes/textconv/crypt + + # Remove ANY unreferenced objects in Git's object DB (packed or unpacked), + # to ensure that cached plaintext objects are also removed. + # The vital sub-commands equivalents we require this `gc` command to do are: + # `git prune`, `git repack -ad` + git gc --prune=now --quiet +} + # force the checkout of any files with the crypt filter applied to them; # this will decrypt existing encrypted files if you've just cloned a repository, # or it will encrypt locally decrypted files if you've just flushed the credentials @@ -524,7 +538,8 @@ flush_credentials() { if [[ $interactive ]]; then printf 'You are about to flush the local credentials; make sure you have saved them elsewhere.\n' - printf 'All previously decrypted files will revert to their encrypted form.\n\n' + printf 'All previously decrypted files will revert to their encrypted form, and your\n' + printf 'repo will be garbage collected to remove any cached plaintext of secret files.\n\n' printf 'Proceed with credential flush? [y/N] ' read -r answer printf '\n' @@ -537,6 +552,8 @@ flush_credentials() { if [[ $answer =~ $YES_REGEX ]]; then clean_gitconfig + remove_cached_plaintext + # re-encrypt any files that had been previously decrypted force_checkout @@ -552,7 +569,8 @@ uninstall_transcrypt() { if [[ $interactive ]]; then printf 'You are about to remove all transcrypt configuration from your repository.\n' - printf 'All previously encrypted files will remain decrypted in this working copy.\n\n' + printf 'All previously encrypted files will remain decrypted in this working copy, but your\n' + printf 'repo will be garbage collected to remove any cached plaintext of secret files.\n\n' printf 'Proceed with uninstall? [y/N] ' read -r answer printf '\n' @@ -565,6 +583,10 @@ uninstall_transcrypt() { if [[ $answer =~ $YES_REGEX ]]; then clean_gitconfig + if [[ ! $upgrade ]]; then + remove_cached_plaintext + fi + # remove helper scripts for script in {clean,smudge,textconv,merge}; do [[ ! -f "${GIT_DIR}/crypt/${script}" ]] || rm "${GIT_DIR}/crypt/${script}" @@ -616,12 +638,70 @@ uninstall_transcrypt() { ;; esac - printf 'The transcrypt configuration has been completely removed from the repository.\n' + if [[ ! $upgrade ]]; then + printf 'The transcrypt configuration has been completely removed from the repository.\n' + fi else die 1 'uninstallation has been aborted' fi } +# uninstall and re-install transcrypt to upgrade scripts and update configuration +upgrade_transcrypt() { + CURRENT_VERSION=$(git config --get --local transcrypt.version 2>/dev/null) + + if [[ $interactive ]]; then + printf 'You are about to upgrade the transcrypt scripts in your repository.\n' + printf 'Your configuration settings will not be changed.\n\n' + printf ' Current version: %s\n' "$CURRENT_VERSION" + printf 'Upgraded version: %s\n\n' "$VERSION" + printf 'Proceed with upgrade? [y/N] ' + read -r answer + printf '\n' + + if [[ $answer =~ $YES_REGEX ]]; then + # User confirmed, don't prompt again + interactive='' + else + # User did not confirm, exit + # Exit if user did not confirm + die 1 'upgrade has been aborted' + fi + fi + + # Keep current cipher and password + cipher=$(git config --get --local transcrypt.cipher) + password=$(git config --get --local transcrypt.password) + + # Keep contents of .gitattributes + ORIG_GITATTRIBUTES=$(cat "$GIT_ATTRIBUTES") + + uninstall_transcrypt + save_configuration + + # Re-instate contents of .gitattributes + echo "$ORIG_GITATTRIBUTES" > "$GIT_ATTRIBUTES" + + # Update .gitattributes for transcrypt'ed files to include "merge=crypt" config + case $OSTYPE in + darwin*) + /usr/bin/sed -i '' 's/=crypt\(.*\)/=crypt diff=crypt merge=crypt/' "$GIT_ATTRIBUTES" + ;; + linux*) + sed -i 's/=crypt\(.*\)/=crypt diff=crypt merge=crypt/' "$GIT_ATTRIBUTES" + ;; + esac + + printf 'Upgrade is complete\n' + + LATEST_GITATTRIBUTES=$(cat "$GIT_ATTRIBUTES") + if [[ "$LATEST_GITATTRIBUTES" != "$ORIG_GITATTRIBUTES" ]]; then + printf '\nYour gitattributes file has been updated with the latest recommended values.\n' + printf 'Please review and commit the new values in:\n' + printf '%s\n' "$GIT_ATTRIBUTES" + fi +} + # list all of the currently encrypted files in the repository list_files() { if [[ $IS_BARE == 'false' ]]; then @@ -764,6 +844,10 @@ help() { remove all transcrypt configuration from the repository and leave files in the current working copy decrypted + --upgrade + apply the latest transcrypt scripts in the repository without + changing your configuration settings + -l, --list list all of the transparently encrypted files in the repository, relative to the top-level directory @@ -839,6 +923,7 @@ password='' rekey='' show_file='' uninstall='' +upgrade='' # used to bypass certain safety checks requires_existing_config='' @@ -886,6 +971,11 @@ while [[ "${1:-}" != '' ]]; do requires_existing_config='true' requires_clean_repo='' ;; + --upgrade) + upgrade='true' + requires_existing_config='true' + requires_clean_repo='' + ;; -l | --list) list='true' requires_clean_repo='' @@ -957,6 +1047,9 @@ if [[ $list ]]; then elif [[ $uninstall ]]; then uninstall_transcrypt exit 0 +elif [[ $upgrade ]]; then + upgrade_transcrypt + exit 0 elif [[ $display_config ]] && [[ $flush_creds ]]; then display_configuration printf '\n' diff --git a/ixc_django_docker/bin/transcrypt-v1-compatible b/ixc_django_docker/bin/transcrypt-v1-compatible index 48ae86c..e1d1178 100755 --- a/ixc_django_docker/bin/transcrypt-v1-compatible +++ b/ixc_django_docker/bin/transcrypt-v1-compatible @@ -502,6 +502,20 @@ clean_gitconfig() { fi } +# Remove from the local Git DB any objects containing the cached plaintext of +# secret files, created due to the setting diff.crypt.cachetextconv='true' +remove_cached_plaintext() { + # Delete ref to cached plaintext objects, to leave these objects + # unreferenced and available for removal + git update-ref -d refs/notes/textconv/crypt + + # Remove ANY unreferenced objects in Git's object DB (packed or unpacked), + # to ensure that cached plaintext objects are also removed. + # The vital sub-commands equivalents we require this `gc` command to do are: + # `git prune`, `git repack -ad` + git gc --prune=now --quiet +} + # force the checkout of any files with the crypt filter applied to them; # this will decrypt existing encrypted files if you've just cloned a repository, # or it will encrypt locally decrypted files if you've just flushed the credentials @@ -529,7 +543,8 @@ flush_credentials() { if [[ $interactive ]]; then printf 'You are about to flush the local credentials; make sure you have saved them elsewhere.\n' - printf 'All previously decrypted files will revert to their encrypted form.\n\n' + printf 'All previously decrypted files will revert to their encrypted form, and your\n' + printf 'repo will be garbage collected to remove any cached plaintext of secret files.\n\n' printf 'Proceed with credential flush? [y/N] ' read -r answer printf '\n' @@ -542,6 +557,8 @@ flush_credentials() { if [[ $answer =~ $YES_REGEX ]]; then clean_gitconfig + remove_cached_plaintext + # re-encrypt any files that had been previously decrypted force_checkout @@ -557,7 +574,8 @@ uninstall_transcrypt() { if [[ $interactive ]]; then printf 'You are about to remove all transcrypt configuration from your repository.\n' - printf 'All previously encrypted files will remain decrypted in this working copy.\n\n' + printf 'All previously encrypted files will remain decrypted in this working copy, but your\n' + printf 'repo will be garbage collected to remove any cached plaintext of secret files.\n\n' printf 'Proceed with uninstall? [y/N] ' read -r answer printf '\n' @@ -570,6 +588,10 @@ uninstall_transcrypt() { if [[ $answer =~ $YES_REGEX ]]; then clean_gitconfig + if [[ ! $upgrade ]]; then + remove_cached_plaintext + fi + # remove helper scripts for script in {clean,smudge,textconv,merge}; do [[ ! -f "${GIT_DIR}/crypt/${script}" ]] || rm "${GIT_DIR}/crypt/${script}" @@ -621,12 +643,70 @@ uninstall_transcrypt() { ;; esac - printf 'The transcrypt configuration has been completely removed from the repository.\n' + if [[ ! $upgrade ]]; then + printf 'The transcrypt configuration has been completely removed from the repository.\n' + fi else die 1 'uninstallation has been aborted' fi } +# uninstall and re-install transcrypt to upgrade scripts and update configuration +upgrade_transcrypt() { + CURRENT_VERSION=$(git config --get --local transcrypt.version 2>/dev/null) + + if [[ $interactive ]]; then + printf 'You are about to upgrade the transcrypt scripts in your repository.\n' + printf 'Your configuration settings will not be changed.\n\n' + printf ' Current version: %s\n' "$CURRENT_VERSION" + printf 'Upgraded version: %s\n\n' "$VERSION" + printf 'Proceed with upgrade? [y/N] ' + read -r answer + printf '\n' + + if [[ $answer =~ $YES_REGEX ]]; then + # User confirmed, don't prompt again + interactive='' + else + # User did not confirm, exit + # Exit if user did not confirm + die 1 'upgrade has been aborted' + fi + fi + + # Keep current cipher and password + cipher=$(git config --get --local transcrypt.cipher) + password=$(git config --get --local transcrypt.password) + + # Keep contents of .gitattributes + ORIG_GITATTRIBUTES=$(cat "$GIT_ATTRIBUTES") + + uninstall_transcrypt + save_configuration + + # Re-instate contents of .gitattributes + echo "$ORIG_GITATTRIBUTES" > "$GIT_ATTRIBUTES" + + # Update .gitattributes for transcrypt'ed files to include "merge=crypt" config + case $OSTYPE in + darwin*) + /usr/bin/sed -i '' 's/=crypt\(.*\)/=crypt diff=crypt merge=crypt/' "$GIT_ATTRIBUTES" + ;; + linux*) + sed -i 's/=crypt\(.*\)/=crypt diff=crypt merge=crypt/' "$GIT_ATTRIBUTES" + ;; + esac + + printf 'Upgrade is complete\n' + + LATEST_GITATTRIBUTES=$(cat "$GIT_ATTRIBUTES") + if [[ "$LATEST_GITATTRIBUTES" != "$ORIG_GITATTRIBUTES" ]]; then + printf '\nYour gitattributes file has been updated with the latest recommended values.\n' + printf 'Please review and commit the new values in:\n' + printf '%s\n' "$GIT_ATTRIBUTES" + fi +} + # list all of the currently encrypted files in the repository list_files() { if [[ $IS_BARE == 'false' ]]; then @@ -769,6 +849,10 @@ help() { remove all transcrypt configuration from the repository and leave files in the current working copy decrypted + --upgrade + apply the latest transcrypt scripts in the repository without + changing your configuration settings + -l, --list list all of the transparently encrypted files in the repository, relative to the top-level directory @@ -844,6 +928,7 @@ password='' rekey='' show_file='' uninstall='' +upgrade='' # used to bypass certain safety checks requires_existing_config='' @@ -891,6 +976,11 @@ while [[ "${1:-}" != '' ]]; do requires_existing_config='true' requires_clean_repo='' ;; + --upgrade) + upgrade='true' + requires_existing_config='true' + requires_clean_repo='' + ;; -l | --list) list='true' requires_clean_repo='' @@ -962,6 +1052,9 @@ if [[ $list ]]; then elif [[ $uninstall ]]; then uninstall_transcrypt exit 0 +elif [[ $upgrade ]]; then + upgrade_transcrypt + exit 0 elif [[ $display_config ]] && [[ $flush_creds ]]; then display_configuration printf '\n'