mirror of https://github.com/sobolevn/git-secret
alpha-release
parent
5e07948831
commit
b7a343e1eb
@ -1,572 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Global variables:
|
||||
|
||||
WORKING_DIRECTORY="$PWD"
|
||||
# Folders:
|
||||
SECRETS_DIR=".gitsecret"
|
||||
SECRETS_DIR_KEYS="$SECRETS_DIR/keys"
|
||||
SECRETS_DIR_PATHS="$SECRETS_DIR/paths"
|
||||
|
||||
# Files:
|
||||
SECRETS_DIR_KEYS_MAPPING="$SECRETS_DIR_KEYS/mapping.cfg"
|
||||
SECRETS_DIR_KEYS_PUBRING="$SECRETS_DIR_KEYS/pubring.gpg"
|
||||
SECRETS_DIR_KEYS_TRUSTDB="$SECRETS_DIR_KEYS/trustdb.gpg"
|
||||
|
||||
SECRETS_DIR_PATHS_MAPPING="$SECRETS_DIR_PATHS/mapping.cfg"
|
||||
|
||||
: ${SECRETS_GPG_COMMAND:="gpg"}
|
||||
GPGLOCAL="$SECRETS_GPG_COMMAND --homedir=$SECRETS_DIR_KEYS --no-permission-warning"
|
||||
|
||||
: ${SECRETS_EXTENSION:=".secret"}
|
||||
|
||||
|
||||
# Inner bash :
|
||||
|
||||
function _function_exists {
|
||||
declare -f -F "$1" > /dev/null
|
||||
echo $?
|
||||
}
|
||||
|
||||
|
||||
# OS based :
|
||||
|
||||
function _os_based {
|
||||
# Pass function name as first parameter.
|
||||
# It will be invoked as os-based function with the postfix.
|
||||
|
||||
case "$(uname -s)" in
|
||||
|
||||
Darwin)
|
||||
$1_osx ${@:2}
|
||||
;;
|
||||
|
||||
Linux)
|
||||
$1_linux ${@:2}
|
||||
;;
|
||||
|
||||
# TODO: add MS Windows support.
|
||||
# CYGWIN*|MINGW32*|MSYS*)
|
||||
# $1_ms ${@:2}
|
||||
# ;;
|
||||
|
||||
*)
|
||||
_abort 'unsupported OS.'
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
# File System :
|
||||
|
||||
function _set_config {
|
||||
# First parameter is the KEY, second is VALUE, third is filename.
|
||||
|
||||
# The exit status is 0 (true) if the name was found, 1 (false) if not:
|
||||
local contains=$(grep -Fq "$1" $3; echo $?)
|
||||
|
||||
if [[ $contains -eq 0 ]]; then
|
||||
_os_based __replace_in_file $@
|
||||
elif [[ $contains -eq 1 ]]; then
|
||||
echo "$1 = $2" >> "$3"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function _file_has_line {
|
||||
# First parameter is the KEY, second is the filename.
|
||||
|
||||
local contains=$(grep -qw "$1" "$2"; echo $?)
|
||||
# 0 on contains, 1 for error.
|
||||
echo $contains;
|
||||
}
|
||||
|
||||
|
||||
function _delete_line {
|
||||
_os_based __delete_line $@
|
||||
}
|
||||
|
||||
|
||||
function _temporary_file {
|
||||
# This function creates temporary file
|
||||
# which will be removed on system exit.
|
||||
filename=$(_os_based __temp_file) # is not `local` on purpose.
|
||||
|
||||
trap "echo 'cleaning up...'; rm -f $filename;" EXIT
|
||||
}
|
||||
|
||||
|
||||
function _unique_filename {
|
||||
# First parameter is base-path, second is filename,
|
||||
# third is optional extension.
|
||||
local n=0 result=$2
|
||||
while [[ 1 ]]; do
|
||||
if [[ ! -f "$1/$result" ]]; then
|
||||
break
|
||||
fi
|
||||
|
||||
n=$(( $n + 1 ))
|
||||
result="$2-$n"
|
||||
done
|
||||
echo $result
|
||||
}
|
||||
|
||||
|
||||
# VCS :
|
||||
|
||||
function _check_ignore {
|
||||
git check-ignore -q "$1";
|
||||
echo $?
|
||||
}
|
||||
|
||||
|
||||
# Logic :
|
||||
|
||||
function _abort {
|
||||
>&2 echo "$1 abort."
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
function _secrets_dir_exists {
|
||||
if [[ ! -d $SECRETS_DIR ]]; then
|
||||
_abort "$SECRETS_DIR does not exist."
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function _user_required {
|
||||
_secrets_dir_exists
|
||||
|
||||
local error_message="no users found. run 'git secret tell' before adding files."
|
||||
if [[ ! -f "$SECRETS_DIR_KEYS_PUBRING" ]] ||
|
||||
[[ ! -f "$SECRETS_DIR_KEYS_TRUSTDB" ]]; then
|
||||
_abort "$error_message"
|
||||
fi
|
||||
|
||||
local keys_exist=$($GPGLOCAL -n --list-keys)
|
||||
if [[ -z $keys_exist ]]; then
|
||||
_abort "$error_message"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function _get_raw_filename {
|
||||
echo "$(dirname "$1")/$(basename "$1" "$SECRETS_EXTENSION")" | sed -e 's#^\./##'
|
||||
}
|
||||
|
||||
|
||||
function _get_encrypted_filename {
|
||||
echo "$(dirname "$1")/$(basename "$1" "$SECRETS_EXTENSION")$SECRETS_EXTENSION" | sed -e 's#^\./##'
|
||||
}
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
function __replace_in_file_linux {
|
||||
sed -i.bak -c "s/^\($1\s*=\s*\).*\$/\1$2/" "$3"
|
||||
}
|
||||
|
||||
|
||||
function __delete_line_linux {
|
||||
sed -i.bak -c "/$1/d" "$2"
|
||||
}
|
||||
|
||||
|
||||
function __temp_file_linux {
|
||||
local filename=$(mktemp)
|
||||
echo "$filename"
|
||||
}
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
function __replace_in_file_osx {
|
||||
sed -i.bak "s/^\($1[[:space:]]*=[[:space:]]*\).*\$/\1$2/" "$3"
|
||||
}
|
||||
|
||||
|
||||
function __delete_line_osx {
|
||||
sed -i.bak "/$1/d" "$2"
|
||||
}
|
||||
|
||||
|
||||
function __temp_file_osx {
|
||||
: "${TMPDIR:=/tmp}"
|
||||
local filename=$(mktemp -t _gitsecrets_ )
|
||||
echo "$filename";
|
||||
}
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
function add {
|
||||
_user_required
|
||||
|
||||
local not_ignored=()
|
||||
|
||||
for item in $@; do
|
||||
# Checking if all files in options are ignored:
|
||||
if [[ ! -f $item ]]; then
|
||||
_abort "$item is not a file."
|
||||
fi
|
||||
|
||||
local ignored=$(_check_ignore "$item")
|
||||
if [[ ! $ignored -eq 0 ]]; then
|
||||
# collect unignored files.
|
||||
not_ignored+=("$item")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ! ${#not_ignored[@]} -eq 0 ]]; then
|
||||
# and show them all at once.
|
||||
_abort "these files are not ignored: ${not_ignored[@]} ;"
|
||||
fi
|
||||
|
||||
for item in $@; do
|
||||
# adding files into system, skipping duplicates.
|
||||
local already_in=$(_file_has_line "$item" "$SECRETS_DIR_PATHS_MAPPING")
|
||||
if [[ $already_in -eq 1 ]]; then
|
||||
echo $item >> $SECRETS_DIR_PATHS_MAPPING
|
||||
fi
|
||||
done
|
||||
|
||||
echo "${#@} items added."
|
||||
}
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
function _show_help_clean {
|
||||
echo "usage: git secret clean"
|
||||
echo "removes all the hidden files."
|
||||
echo
|
||||
echo " -v shows which files are deleted."
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
function clean {
|
||||
OPTIND=1
|
||||
|
||||
local verbose=""
|
||||
while getopts "vh" opt; do
|
||||
case "$opt" in
|
||||
v)
|
||||
verbose="v"
|
||||
;;
|
||||
|
||||
h)
|
||||
_show_help_clean
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND-1))
|
||||
[ "$1" = "--" ] && shift
|
||||
|
||||
[[ ! -z $verbose ]] && echo && echo "cleaing:" || : # bug with custom bash on OSX
|
||||
|
||||
find . -name *$SECRETS_EXTENSION -type f | xargs rm -f$verbose
|
||||
|
||||
[[ ! -z $verbose ]] && echo || : # bug with custom bash on OSX
|
||||
|
||||
}
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
function _show_help_hide {
|
||||
echo "usage: git secret hide"
|
||||
echo "encrypts all the files added by the 'add' command."
|
||||
echo
|
||||
echo " -c clean files before creating new ones."
|
||||
echo " -v shows which files are deleted."
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
function _optional_clean {
|
||||
OPTIND=1
|
||||
local clean=0
|
||||
local opt_string=""
|
||||
|
||||
while getopts "cvh" opt; do
|
||||
case "$opt" in
|
||||
c) # -c is used for guaranted clean encryption.
|
||||
clean=1
|
||||
;;
|
||||
|
||||
h)
|
||||
_show_help_hide
|
||||
;;
|
||||
|
||||
*)
|
||||
opt_string="$opt_string -$opt"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND-1))
|
||||
[ "$1" = "--" ] && shift
|
||||
|
||||
if [[ $clean -eq 1 ]]; then
|
||||
clean ${opt_string}
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function hide {
|
||||
_user_required
|
||||
|
||||
_optional_clean $@
|
||||
|
||||
local counter=0
|
||||
while read line; do
|
||||
local encrypted_filename=$(_get_encrypted_filename $line)
|
||||
|
||||
local recipients=$($GPGLOCAL --list-keys | sed -n 's/.*<\(.*\)>.*/-r\1/p')
|
||||
$GPGLOCAL --use-agent --yes --trust-model=always --encrypt $recipients -o "$encrypted_filename" "$line"
|
||||
|
||||
counter=$((counter+1))
|
||||
done < $SECRETS_DIR_PATHS_MAPPING
|
||||
|
||||
echo "done. all $counter files are hidden."
|
||||
}
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
function init {
|
||||
|
||||
if [[ -d "$SECRETS_DIR" ]]; then
|
||||
_abort "already inited."
|
||||
fi
|
||||
|
||||
local ignores=$(_check_ignore "$SECRETS_DIR"/)
|
||||
|
||||
if [[ ! $ignores -eq 1 ]]; then
|
||||
_abort "'${SECRETS_DIR}/' is ignored."
|
||||
fi
|
||||
|
||||
mkdir "$SECRETS_DIR" "$SECRETS_DIR_KEYS" "$SECRETS_DIR_PATHS"
|
||||
touch "$SECRETS_DIR_KEYS_MAPPING" "$SECRETS_DIR_PATHS_MAPPING"
|
||||
echo "'${SECRETS_DIR}/' created."
|
||||
}
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
function killperson {
|
||||
_user_required
|
||||
|
||||
if [[ ${#@} -eq 0 ]]; then
|
||||
_abort "email is required."
|
||||
fi
|
||||
|
||||
$GPGLOCAL --batch --yes --delete-key "$1"
|
||||
}
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
function remove {
|
||||
_user_required
|
||||
|
||||
for item in $@; do
|
||||
if [[ ! -f "$item" ]]; then
|
||||
_abort "$item is not a file."
|
||||
fi
|
||||
|
||||
_delete_line "$item" "$SECRETS_DIR_PATHS_MAPPING"
|
||||
done
|
||||
|
||||
local all=${@}
|
||||
echo "removed from index."
|
||||
echo "ensure that files: [$all] are now not ignored."
|
||||
}
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
function _show_help_reveal {
|
||||
echo "usage: git secret reveal"
|
||||
echo "unencrypts all the files added by the 'add' command."
|
||||
echo
|
||||
echo " -d specifies --homedir option for gpg."
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
function reveal {
|
||||
_user_required
|
||||
|
||||
OPTIND=1
|
||||
local homedir=""
|
||||
local passphrase=""
|
||||
|
||||
while getopts "hd:p:" opt; do
|
||||
case "$opt" in
|
||||
h)
|
||||
_show_help_reveal
|
||||
;;
|
||||
|
||||
p)
|
||||
passphrase=$OPTARG
|
||||
;;
|
||||
|
||||
d)
|
||||
homedir=$OPTARG
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND-1))
|
||||
[ "$1" = "--" ] && shift
|
||||
|
||||
local counter=0
|
||||
while read line; do
|
||||
local encrypted_filename=$(_get_encrypted_filename "$line")
|
||||
echo "$line: $encrypted_filename"
|
||||
|
||||
local base="$SECRETS_GPG_COMMAND --use-agent -q --decrypt"
|
||||
if [[ ! -z "$homedir" ]]; then
|
||||
base="$base --homedir=$homedir"
|
||||
fi
|
||||
|
||||
if [[ ! -z "$passphrase" ]]; then
|
||||
base="$base --batch --yes --passphrase $passphrase"
|
||||
fi
|
||||
|
||||
$base -o "$line" "$encrypted_filename"
|
||||
|
||||
counter=$((counter+1))
|
||||
done < "$SECRETS_DIR_PATHS_MAPPING"
|
||||
|
||||
echo "done. all $counter files are revealed."
|
||||
}
|
||||
#!/usr/bin/env bash
|
||||
|
||||
function tell {
|
||||
_secrets_dir_exists
|
||||
|
||||
# A POSIX variable
|
||||
# Reset in case getopts has been used previously in the shell.
|
||||
OPTIND=1
|
||||
|
||||
local email
|
||||
local homedir
|
||||
|
||||
while getopts "h?md:" opt; do
|
||||
case "$opt" in
|
||||
h|\?)
|
||||
usage
|
||||
;;
|
||||
|
||||
m) # Set email of the git current user:
|
||||
email=$(git config user.email) || email=""
|
||||
|
||||
if [[ -z $email ]]; then
|
||||
_abort "empty email for current git user."
|
||||
else
|
||||
echo "$email is not empty"
|
||||
fi
|
||||
;;
|
||||
|
||||
d)
|
||||
homedir=$OPTARG
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND-1))
|
||||
[ "$1" = "--" ] && shift
|
||||
|
||||
# Custom argument-parsing:
|
||||
if [[ -z $email ]]; then
|
||||
# Email was not set via `-m` and is in $1:
|
||||
email="$1"
|
||||
if [[ -z $email ]]; then
|
||||
_abort "first argument must be an email address."
|
||||
fi
|
||||
shift
|
||||
fi
|
||||
|
||||
# This file will be removed automatically:
|
||||
_temporary_file
|
||||
local keyfile=$filename
|
||||
|
||||
if [[ -z $homedir ]]; then
|
||||
$SECRETS_GPG_COMMAND --export -a "$email" > "$keyfile"
|
||||
else
|
||||
# It means that homedir is set as an extra argument via `-d`:
|
||||
$SECRETS_GPG_COMMAND --no-permission-warning --homedir="$homedir" --export -a "$email" > "$keyfile"
|
||||
fi
|
||||
|
||||
if [[ ! -s $keyfile ]]; then
|
||||
_abort 'gpg key is empty. check your key name: `gpg --list-keys`.'
|
||||
fi
|
||||
|
||||
# Importing public key to the local keychain:
|
||||
$GPGLOCAL --import "$keyfile" > /dev/null 2>&1
|
||||
|
||||
echo
|
||||
echo "done. $email added as a person who knows the secret."
|
||||
}
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
function usage {
|
||||
|
||||
if [[ ! -z "$1" ]]; then
|
||||
echo $@
|
||||
fi
|
||||
|
||||
local commands=""
|
||||
local separator="|"
|
||||
|
||||
for com in `compgen -A function`
|
||||
do
|
||||
if [[ ! $com == _* ]]; then
|
||||
commands+="$com$separator"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "usage: git secret [${commands%?}]"
|
||||
exit 0
|
||||
}
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# encryption: https://www.gnupg.org/gph/en/manual.html#AEN111
|
||||
# git hooks: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
|
||||
# adding files to git on pre_commit hook:
|
||||
# http://stackoverflow.com/questions/3284292/can-a-git-hook-automatically-add-files-to-the-commit
|
||||
|
||||
|
||||
function _check_setup {
|
||||
# Checking git and secret-plugin setup:
|
||||
if [[ ! -d ".git" ]] || [[ ! -d ".git/hooks" ]]; then
|
||||
_abort "repository is broken. try running 'git init' or 'git clone'."
|
||||
fi
|
||||
|
||||
# Checking gpg setup:
|
||||
local secring="$SECRETS_DIR_KEYS/secring.gpg"
|
||||
if [[ -f $secring ]] && [[ -s $secring ]]; then
|
||||
# secring.gpg is not empty, someone has imported a private key.
|
||||
_abort "it seems that someone has imported a secret key."
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function _init_script {
|
||||
# checking for proper set-up:
|
||||
_check_setup
|
||||
|
||||
if [[ $# == 0 ]]; then
|
||||
usage "no input parameters provided."
|
||||
fi
|
||||
|
||||
# load dependencies:
|
||||
# for f in ${0%/*}/src/*/*; do [[ -f "$f" ]] && . "$f"; done
|
||||
|
||||
# routing the input command:
|
||||
if [[ `_function_exists $1` == 0 ]] && [[ ! $1 == _* ]]; then
|
||||
$1 "${@:2}"
|
||||
else
|
||||
usage "command $1 not found."
|
||||
fi
|
||||
}
|
||||
|
||||
set -e
|
||||
_init_script $@
|
Loading…
Reference in New Issue