Dev: Completely refactor the code

This commit is contained in:
mrjk 2018-02-16 02:23:03 -05:00
parent 2c3ccab6ad
commit 9dea6bf7ef
11 changed files with 1694 additions and 1091 deletions

BIN
bin/.idmgr.swp Normal file

Binary file not shown.

887
bin/idmgr

File diff suppressed because it is too large Load Diff

272
lib/idm_lib_std.sh Normal file
View File

@ -0,0 +1,272 @@
#!/bin/bash
## Special libraries
#############################
lib_shred ()
{
lib_lob WARN "Will destroy all your secrets! (nor implemented yet)"
}
## Standard libraries
#############################
lib_require_bin () {
local bin=$1
shift 1 || true
local opts=${@-}
if command -v "$bin" &> /dev/null; then
declare -g ${bin^^}="$bin $opts"
return 0
else
lib_log ERR "Missing '$bin'"
return 1
fi
}
# Nifty trick to set var from pipes
lib_set_var () { read "$@" <&0; }
# Take an environment var name, an a list of vars to inject
lib_vars_inject ()
{
local env_name=$1
shift 1
# Check if not already loaded
if [ "${last_env_name}" == "$env_name" ]; then
return 0
fi
last_env_name=$env_name
# check if valid environment
[ "$( type -t idm_vars_${env_name} )" = function ] || return 1
# Inject var list
for var in ${@-}; do
name=${env}_${var}
$i=${!name}
done
}
lib_trace ()
{
local msg=${@}
local traces=
(
echo "Stack trace:"
for i in {0..10}; do
trace=$(caller $i 2>&1 || true )
if [ -z "$trace" ] ; then
continue
else
#lib_log DEBUG "Trace $i: $trace"
#traces="${traces}${trace}\n"
echo "$trace"
fi
done | tac | column -t
[ -z "$msg" ] || echo "Trace ctx: $msg"
) | >&2 lib_log DUMP -
}
lib_reverse_doted_list ()
{
local list=$1
awk 'BEGIN{FS=OFS=":"} {s=$NF; for (i=NF-1; i>=1; i--) s = s OFS $i; print s}' <<<"$list"
}
lib_parse_filerules ()
{
local id=$1
local f=$2
#set -x
local YADM_ENCRYPT="$2"
ENCRYPT_INCLUDE_FILES=()
ENCRYPT_EXCLUDE_FILES=()
#cd_work "Parsing encrypt" || return
cd ~
exclude_pattern="^!(.+)"
if [ -f "$YADM_ENCRYPT" ] ; then
#; parse both included/excluded
while IFS='' read -r line || [ -n "$line" ]; do
if [[ ! $line =~ ^# && ! $line =~ ^[[:space:]]*$ ]] ; then
local IFS=$'\n'
for pattern in $line; do
if [[ "$pattern" =~ $exclude_pattern ]]; then
for ex_file in ${BASH_REMATCH[1]}; do
for f in $( find $ex_file -type f ); do
#if [ -e "$ex_file" ]; then
ENCRYPT_EXCLUDE_FILES+=("$f")
#fi
done
done
else
for in_file in $pattern; do
for f in $( find $in_file -type f ); do
#if [ -e "$in_file" ]; then
ENCRYPT_INCLUDE_FILES+=("$f")
#fi
done
done
fi
done
fi
done < "$YADM_ENCRYPT"
#; remove excludes from the includes
#(SC2068 is disabled because in this case, we desire globbing)
FINAL_INCLUDE=()
#shellcheck disable=SC2068
for included in "${ENCRYPT_INCLUDE_FILES[@]}"; do
skip=
#shellcheck disable=SC2068
for ex_file in ${ENCRYPT_EXCLUDE_FILES[@]}; do
[ "$included" == "$ex_file" ] && { skip=1; break; }
done
[ -n "$skip" ] || FINAL_INCLUDE+=("$included")
done
ENCRYPT_INCLUDE_FILES=("${FINAL_INCLUDE[@]}")
echo "${ENCRYPT_INCLUDE_FILES[@]}"
fi
}
lib_log ()
{
set +x
local level=$1
shift || true
local msg="$@"
# Take from stdin if no message ...
[ "$msg" = - ] && msg=$( cat < /dev/stdin )
[ -z "$msg" ] && {
echo
return 0
}
if [ "$( wc -l <<<"$msg" )" -gt 1 ]; then
while read -r line; do
lib_log $level $line
done <<< "$msg"
return
fi
local color=
local reset='\033[0m'
case $level in
ERR)
color='\033[0;31m'
;;
WARN|TIP)
color='\033[0;33m'
;;
NOTICE)
color='\033[0;32m'
;;
INFO)
color='\033[0;37m'
;;
DEBUG)
color='\033[0;31m'
;;
RUN)
color='\033[0;34m'
;;
CODE)
echo "$msg"
return
;;
DUMP)
color='\033[0;36m'
echo -e "$color$msg$reset" | sed 's/^/ /'
return
;;
PREFIX)
color='\033[0;34m'
;;
esac
if [[ -n "$level" ]]; then
printf "$color%*.6s$reset: %s\n" 6 "${level}_____" "$msg" >&2
else
echo "Error while log output msg: $msg"
fi
}
# export PS4='+[${SECONDS}s][${BASH_SOURCE}:${LINENO}]: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'; set -x;
# export PS4='.[${SECONDS}s] \[\e[36m\] ${FUNCNAME[0]:+${FUNCNAME[0]}()[${LINENO}]: }\[\e[m\]'; set -x;
# export PS4='. $( f="${FUNCNAME[0]:+${FUNCNAME[0]//}}"; printf "%10s:%00d %00d %10s| " ${BASH_SOURCE#$HOME/} ${LINENO} ${SECONDS} "$f")' ; set -x;
# export PS4='. $(f="${FUNCNAME[0]:+${FUNCNAME[0]//}}"; s=${BASH_SOURCE#$HOME/}; l=${LINENO}; t=${SECONDS}; printf "%00d %0d %16.50s() " $l $t "$f")' ; set -x;
# export PS4=' \[\e[36m\]> $(f="${FUNCNAME[0]:+${FUNCNAME[0]//}}"; s=${BASH_SOURCE#$HOME/}; l=${LINENO}; t=${SECONDS}; printf "%00d %0d %s():" $l $t "$f")\[\e[m\]\n' ; set -x;
#export LOG="lib_log_wrap \$FUNCNAME "
#lib_date_diff ()
#{
#
#}
lib_date_diff_human ()
{
local early_date=$1
local late_date=${2:-$(date '+%s')}
local diff
diff=$(( $late_date - $early_date ))
data="$(date -d@$diff -u '+%yy %jd %Hh %Mm %Ss')"
IFS=, read -r y d h m s <<<"${data// /,}"
y=$(( ${y::-1} - 70 ))y
d=$(( ${d::-1} - 1 ))d
#echo " $y $d $h $m $s"
echo " $y $d $h $m $s" | sed -E -e 's/ 00*/ /g' -e 's/ [ydhms]//g' | xargs
}
# OLD PIEECES OF CODE
# echo "export MANPAGER=less"
# #echo "export VIMINIT=let \$MYVIMRC='$XDG_CONFIG_HOME/vim/vimrc' \| source \$MYVIMRC"
# #echo "export VIMINIT='let \$MYVIMRC="$XDG_CONFIG_HOME/vim/vimrc"'"
# # Misc
# echo "export PYENV_ROOT=${XDG_OPT_HOME}/pyenv"
# echo "export PYTHONUSERBASE=${XDG_OPT_HOME}/python"
# echo "export PYTHONZ_ROOT=${XDG_OPT_HOME}/pythonz"
# echo "export PIPSI_BIN_DIR=${XDG_OPT_HOME}/python-venv/bin"
# echo "export LUA_CPATH=${XDG_OPT_HOME}/lua/?.so"
# echo "export LUA_PATH=${XDG_OPT_HOME}/lua/?.lua"
# echo "export LUAROCKS_CONFIG=~/.config/lua-${id}/luarocks.lua"
# echo "export GEM_HOME=${XDG_OPT_HOME}/ruby"
# echo "export GEMRC=~/.config/ruby-${id}/gemrc"
# echo "export GEM_SPEC_CACHE=${XDG_OPT_HOME}/ruby/gem/specs"
# echo "export COMPOSER_CACHE_DIR=${XDG_OPT_HOME}/composer"
# echo "export COMPOSER_HOME=${XDG_OPT_HOME}/composer"
# echo "export NPM_CONFIG_USERCONFIG=~/.config/npmrc"
# echo "export VAGRANT_HOME=${XDG_OPT_HOME}/vagrant"
# echo "export GOPATH=${XDG_OPT_HOME}/go"

58
lib/idmgr_mod_cloud.sh Normal file
View File

@ -0,0 +1,58 @@
#!/bin/bash
IDM_MOD_DEPS="id pass gpg ssh"
## Prompt functions
##########################################
#SHELL_PS1="${SHELL_PS1:-${PS1}"
idm_cloud ()
{
local action=${1-}
shift || true
idm_cloud_ls
}
idm_cloud__ls ()
{
local id=${1}
if idm_validate is_enabled $id; then
if [ -f "${OS_CLOUD-}" ]; then
echo " enabled ($OS_CLOUD)"
else
echo " disabled (config is absent ${OS_CLOUD:-${OS_CLOUD:+$OS_CLOUD}})"
fi
else
echo " disabled"
fi
}
idm_cloud__help ()
{
echo "S"
printf " %-20s: %s\n" "clouds enable" "Enable prompt"
printf " %-20s: %s\n" "clouds disable" "Disable prompt"
}
idm_cloud__enable ()
{
local id=${1}
if [ -f "~/.config/openstack/${id}_clouds.yaml" ]; then
echo "export OS_CLOUD=~/.config/openstack/${id}_clouds.yaml"
#echo "export OS_REGION_NAME=~/.config/openstack/${id}_clouds.yaml"
fi
}
idm_cloud__disable ()
{
echo "unset OS_CLOUD"
return
}
idm_cloud__kill () { idm_cloud__disable ${@-}; }

View File

@ -2,20 +2,234 @@
IDM_MOD_DEPS="id" IDM_MOD_DEPS="id"
## Required functions
##########################################
## User functions
##############################
idm_git__help ()
{
local id=$1
echo "Git"
printf " %-20s: %s\n" "git init" "Start a local repo"
printf " %-20s: %s\n" "git scan" "Search and add interesting files"
printf " %-20s: %s\n" "git enabled" "Enable as default git"
printf " %-20s: %s\n" "git ls" "Show tracked files"
printf " %-20s: %s\n" "git disable" "Disable as default git"
printf " %-20s: %s\n" "git kill" "Like disable"
echo
printf " %-20s: %s\n" "git --help" "Git wrapper"
printf " %-20s: %s\n" "git [cmd]" "Git wrapper"
if idm_validate id_config $id; then
idm_git_init $id
if lib_git_is_repo $git_local_dir $git_local_work_tree ; then
echo
idm_git_init $id
echo " Config:"
$GIT_LOCAL config -l | sort \
| grep -E '(core|remote|include|remote|user|status)\.' #| sed 's/^/ /'
fi
fi
}
idm_git__init ()
{
local id=$1
shift 1
opts=${*-}
# Sanity check
idm_validate id_config $id
idm_git_init $id
# Check local repo
if lib_git_is_repo $git_local_dir $git_local_work_tree ; then
lib_log WARN "Do you want to override the esixting repo?"
idm_cli_timeout 1 || idm_exit 1 "User cancelled"
fi
$GIT_LOCAL init $opts
lib_log NOTICE "Repository has been created into '$git_local_dir'"
# Generate
$GIT_LOCAL config --add include.path "$git_local_config"
idm_git__gen_git_config > $git_local_config
}
idm_git__scan ()
{
local id=$1
idm_validate id_config $id
idm_git_init $id
# Ensure we have a valid repository
if ! lib_git_is_repo $git_local_dir $git_local_work_tree ; then
lib_log WARN "Do you want to create a local repository of your secrets?"
idm_cli_timeout 1 || idm_exit 1 "User cancelled"
$GIT_LOCAL init
fi
# Add all files
$GIT_LOCAL add -f $( xargs <<<"$( idm_git__get_files_of_interest $id )" )
# Check uncommited changes
if ! lib_git_is_all_commited $git_local_dir $git_local_work_tree ; then
lib_log INFO "There are the files we could add:"
$GIT_LOCAL status -s
lib_log PROMPT "Do you want to add these files to your repo?"
if idm_cli_timeout 1; then
tty=$(tty)
#$GIT_LOCAL commit -e
echo "Add: Import $(hostname) data" | $GIT_LOCAL commit --file=-
else
lib_log TIP "Commit your files with 'i git commit '"
fi
else
lib_log INFO "Nothing to add ..."
fi
}
idm_git__ls ()
{
local id=$1
idm_git_init $id
$GIT_LOCAL ls-files | sort
#$GIT_LOCAL ls-files | sort | sed 's@/[^\/]*@@'
return
if idm_validate id_config $id; then
idm_git_init $id
if lib_git_is_repo $git_local_dir $git_local_work_tree ; then
$GIT_LOCAL ls-files | sort | sed 's/^/ ~\//'
else
echo "Repository is not created"
fi
fi
#tree $
}
idm_git__enable ()
{
local id=$1
idm_git_init $id
cat <<EOF -
export GIT_DIR="$git_local_dir"
export GIT_WORK_TREE="$git_local_work_tree"
EOF
}
idm_git__disable ()
{
echo "unset GIT_DIR GIT_WORK_TREE"
}
idm_git__kill () { idm_git__disable ${@-}; }
idm_git ()
{
local action=$1
local id=$2
shift 2
local opts=${*-}
idm_git_init $id
$GIT_LOCAL $action $opts
}
## External deps
##############################
_git_local2 ()
{
lib_git_bin $git_local_dir $git_local_work_tree ${*-}
}
idm_vars_git_local () {
git_local_work_tree=$HOME
git_local_dir=$IDM_DIR_CACHE/git/$id/local.git
git_local_config=${IDM_CONFIG_DIR}/git/$id/local_gitconfig
git_local="lib_git_bin $git_local_dir $git_local_work_tree"
GIT_LOCAL=$git_local
}
idm_git_init ()
{
local id=$1
# Sanity check
idm_validate id_config $id
# Load local repo vars
idm_vars_git_local
}
####
idm_git__get_files_of_interest ()
{
local id=${1}
find_args="-maxdepth 2 -type f "
{
find $HOME/.ssh/ $find_args -name "${id}*" 2>/dev/null
find $HOME/.ssh/known_hosts.d/ $find_args -name "${id}*" 2>/dev/null
find $HOME/.openstack/$id/ $find_args 2>/dev/null
find $GNUPGHOME/private-keys-v1.d/ $find_args 2>/dev/null
find $PASSWORD_STORE_DIR/ $find_args 2>/dev/null
find $IDM_DIR_ID/ $find_args -name "$id*" 2>/dev/null
} | sed -E "s@$HOME/?@@g"
}
idm_git__gen_git_config ()
{
(
cat <<EOF -
[status]
showuntrackedfiles = no
EOF
) | sed "s@$HOME/@~/@g"
}
# Debug libs
########################
# Debug and shortcuts # Debug and shortcuts
_git () { idm_git__bin ${@-}; }
idm_git_f () { idm_git_f () {
local id=$1 local id=$1
local cmd=$2 local cmd=$2
shift 2 shift 2
local opts=${*-} local opts=${*-}
local rc=0
trap '' INT TERM EXIT trap '' INT TERM EXIT
idm_validate id_config $id idm_validate id_config $id
idm_vars_git_local $id idm_git_init $id
set -e set -e
idm_git_${cmd#idm_git_} $opts idm_git_${cmd#idm_git_} $opts
@ -30,209 +244,73 @@ idm_git_f () {
} }
idm_git () idm_git__d ()
{ {
local action=$1 $IDM_BIN git l
local id=$2 $IDM_BIN git status -s
shift 2 $IDM_BIN git remote -v
local opts=${*-} {
idm_validate id_config $id $IDM_BIN git config -l \
idm_vars_git_local $id | sort \
| grep -E '(core|remote|include|remote|user|status)\.'
idm_git__bin $action $opts }
} }
idm_git_help () ## Future lib
{
echo "Git"
printf " %-20s: %s\n" "git ls" "List maanged files"
printf " "
}
idm_git_ls ()
{
local id=$1
idm_validate id_config $id
idm_vars_git_local $id
_git ls-files | sed 's/^/ ~\//' | idm_log DUMP -
}
idm_git_enable ()
{
local id=$1
idm_validate id_config $id
idm_vars_git_local $id
cat <<EOF -
export GIT_DIR="$git_dir"
export GIT_WORK_TREE="$git_work_tree"
EOF
}
idm_git_disable ()
{
echo "unset GIT_DIR GIT_WORK_TREE"
}
idm_git_kill () { idm_git_disable ${@-}; }
## Internal functions
############################## ##############################
idm_vars_git_local()
{
#local id=$1
var_id=git_local
id=${id:-$SHELL_ID}
git_work_tree=$HOME
git_dir=$IDM_DIR_CACHE/git/$id/local.git
git_config=${IDM_CONFIG_DIR}/git/$id/local_gitconfig
#git_config=$git_dir/$config
} lib_git_bin ()
# A wrapper before calling git
# WARN: IMPLICIT $ID VARIABLE, will fail if not well used
idm_git__bin ()
{ {
local git_dir=$1
local git_work_tree=$2
shift 2
local opts=${@-} local opts=${@-}
local rc=0
# Check if config is loaded (when called from other mods)
[ -n "${git_dir:-}" ] || idm_vars_git_local $id
# Check binary presence # Check binary presence
#idm_require_bin git || \ lib_require_bin git || \
# idm_exit 1 "Please install git first." idm_exit 1 "Please install git first."
# REALLY FUN BREAKER :(
#lib_log RUN "git --git-dir "$git_dir" --work-tree "$git_work_tree" $opts"
set +e
git \ git \
--git-dir "$git_dir" \ --git-dir "$git_dir" \
--work-tree "$git_work_tree" \ --work-tree "$git_work_tree" \
-C "$git_work_tree" \ -C "$git_work_tree" \
$opts $opts || rc=$?
set -e
# --file "$git_config" \
# -C indlude.path=$gitconfig
# --include $gitconfig
#echo "You should be able to see $rc"
return ${rc:-0}
} }
idm_git__is_repo () lib_git_is_repo ()
{ {
[ -d "$git_dir" ] && _git rev-parse > /dev/null 2>&1 local git_dir=$1
local git_work_tree=$2
[ -d "$git_dir" ] && lib_git_bin $git_dir $git_work_tree rev-parse > /dev/null 2>&1 ; return $?
} }
idm_git__has_commits () lib_git_has_commits ()
{ {
if idm_git__is_repo $id; then local git_dir=$1
find "$git_dir" -type f &>/dev/null && return 0 local git_work_tree=$2
fi
return 1 lib_git_is_repo $git_dir $git_work_tree || return $?
find "$git_dir" -type f &>/dev/null || return 1
} }
idm_git__is_all_commited () lib_git_is_all_commited ()
{ {
[ "$( _git status -s | wc -l)" -eq 0 ] local git_dir=$1
local git_work_tree=$2
[ "$( lib_git_bin $git_dir $git_work_tree status -s | wc -l)" -eq 0 ]
} }
## Other internal functions
##############################
idm_git__get_files_of_interest ()
{
local id=${1}
find_args="-maxdepth 2 -type f "
{
find $HOME/.ssh/ $find_args -name "${id}*" 2>/dev/null
find $HOME/.ssh/known_hosts.d/ $find_args -name "${id}*" 2>/dev/null
find $GNUPGHOME/private-keys-v1.d/ $find_args 2>/dev/null
find $PASSWORD_STORE_DIR/ $find_args 2>/dev/null
find $IDM_DIR_ID/ $find_args -name "$id*" 2>/dev/null
} | sed -E "s@$HOME/?@@g"
}
## User functions
##############################
idm_git_init ()
{
local id=$1
shift
local opts=${@-}
idm_validate id_config $id
idm_vars_git_local $id
if idm_git__is_repo ; then
idm_log WARN "Do you want to override the esixting repo?"
idm_cli_timeout 1 || idm_exit 1 "User cancelled"
fi
_git init $opts
idm_log NOTICE "Repository has been created into '$git_dir'"
# Generate
_git config --add include.path "$git_config"
idm_tomb__gen_git_config > $git_config
}
idm_tomb__gen_git_config ()
{
(
cat <<EOF -
[status]
showuntrackedfiles = no
EOF
) | sed "s@$HOME/@~/@g"
}
idm_git_scan ()
{
local id=$1
idm_validate id_config $id
idm_vars_git_local $id
# Ensure we have a valid repository
if ! idm_git__is_repo ; then
idm_log WARN "Do you want to create a local repository of your secrets?"
idm_cli_timeout 1 || idm_exit 1 "User cancelled"
_git init
fi
# Add all files
_git add -f $( xargs <<<"$( idm_git__get_files_of_interest $id )" )
# Check uncommited changes
if ! idm_git__is_all_commited ; then
idm_log INFO "There are the files we could add:"
_git status -s
idm_log PROMPT "Do you want to add these files to your repo?"
if idm_cli_timeout 1; then
tty=$(tty)
#_git commit -e
echo "Add: Import $(hostname) data" | _git commit --file=-
else
idm_log TIP "Commit your files with 'i git commit '"
fi
fi
}

View File

@ -3,7 +3,7 @@
IDM_MOD_DEPS="id" IDM_MOD_DEPS="id"
idm_gpg_help () idm_gpg__help ()
{ {
echo "Not implemented yet" echo "Not implemented yet"
} }
@ -11,10 +11,10 @@ idm_gpg_help ()
## Required functions ## Required functions
########################################## ##########################################
idm_gpg_enable () idm_gpg__enable ()
{ {
local id=${1} local id=${1}
idm_is_enabled $id idm_validate id_config $id
# Source environment # Source environment
if [ -f "${XDG_RUNTIME_DIR}/pgp-agent/${id}/env" ]; then if [ -f "${XDG_RUNTIME_DIR}/pgp-agent/${id}/env" ]; then
@ -26,7 +26,7 @@ idm_gpg_enable ()
# Check if socket is present # Check if socket is present
if [ ! -S "${GPG_AGENT_INFO-}" ]; then if [ ! -S "${GPG_AGENT_INFO-}" ]; then
rm -f "${XDG_RUNTIME_DIR}/pgp-agent/${id}/env" rm -f "${XDG_RUNTIME_DIR}/pgp-agent/${id}/env"
idm_gpg__start $id idm_gpg_start $id
fi fi
# Show config to source # Show config to source
@ -39,40 +39,89 @@ idm_gpg_enable ()
} }
idm_gpg_disable () idm_gpg__disable ()
{ {
local id=${1} local id=${1}
idm_is_enabled $id idm_validate id_config $id
echo "unset GPG_AGENT_INFO GNUPGHOME GPG_TTY" echo "unset GPG_AGENT_INFO GNUPGHOME GPG_TTY"
} }
idm_gpg_kill () idm_gpg__kill ()
{ {
local id=${1} local id=${1}
idm_is_enabled $id idm_is_enabled $id
gpgconf --kill gpg-agent gpgconf --kill gpg-agent
idm_log NOTICE "Kill gpg-agent ..." lib_log NOTICE "Kill gpg-agent ..."
idm_gpg_disable $id idm_gpg__disable $id
#killall gpg-agent || true #killall gpg-agent || true
#echo "echo 'GPG kill is not implemented yet ...'" #echo "echo 'GPG kill is not implemented yet ...'"
} }
idm_gpg_ls () idm_gpg__ls ()
{
local id=${1}
idm_validate is_enabled $id || return 0
gpg --list-keys | sed 's/^/ /' #| lib_log DUMP -
}
idm_gpg__new ()
{
local id=${1}
idm_is_enabled $id
key="$( idm_gpg_match_one_pubkey $id )"
idm_gpg_cli_helper $id sub
gpg --edit-key $key addkey
lib_log NOTICE "Your subkey $name is ready :)"
}
# Should be used for subkeys ....
idm_gpg__init ()
{ {
local id=${1} local id=${1}
idm_is_enabled $id idm_is_enabled $id
gpg --list-keys | idm_log DUMP - ! idm_gpg_match_one_pubkey $id &>/dev/null || \
idm_exit 1 "You already have an id !"
# Generate top secret id
idm_gpg_cli_helper $id main
gpg --gen-key
# Generate encyption key
idm_gpg_new $id
lib_log NOTICE "Your personal key $name is ready :)"
} }
idm_gpg__del ()
{
local id=${1}
local key=${2:-$1}
# Scan key
key=$(idm_gpg_match_one_pubkey $key)
lib_log WARN "Do you really want to destroy the '$key' key?"
idm_cli_timeout 1 || rc=$?
gpg --delete-key "$key" || true
gpg --delete-secret-key "$key" || true
}
## Internal functions ## Internal functions
########################################## ##########################################
idm_gpg__start () idm_gpg_start ()
{ {
local id=${1} local id=${1}
local gpghome=~/.config/gpg/$id local gpghome=~/.config/gpg/$id
@ -98,15 +147,12 @@ idm_gpg__start ()
echo "export GPG_DEFAULT_ID=${GIT_AUTHOR_EMAIL:-$id}" >> "$runtime/env" echo "export GPG_DEFAULT_ID=${GIT_AUTHOR_EMAIL:-$id}" >> "$runtime/env"
# Start agent # Start agent
idm_log INFO "Start gpg-agent ..." lib_log INFO "Start gpg-agent ..."
gpg-agent --daemon --extra-socket "$runtime/socket" gpg-agent --daemon --extra-socket "$runtime/socket" || true
} }
## Extended functions idm_gpg_cli_helper ()
##########################################
idm_gpg__cli_helper ()
{ {
local id=${1} local id=${1}
local type=${2:-sub} local type=${2:-sub}
@ -119,65 +165,34 @@ idm_gpg__cli_helper ()
name=${GIT_AUTHOR_NAME} name=${GIT_AUTHOR_NAME}
fi fi
idm_log NOTICE "Please follow this recommendations:" lib_log NOTICE "Please follow this recommendations:"
if [ "$type" == "sub" ]; then if [ "$type" == "sub" ]; then
idm_log $lvl "You may have to enter your principal key password." lib_log $lvl "You may have to enter your principal key password."
idm_log $lvl "Type: 6 - RSA (encrypt only)" lib_log $lvl "Type: 6 - RSA (encrypt only)"
elif [ "$type" == "main" ]; then elif [ "$type" == "main" ]; then
idm_log $lvl "Type: 4 - RSA (sign only)" lib_log $lvl "Type: 4 - RSA (sign only)"
fi fi
# Common # Common
idm_log $lvl "Size: 4096" lib_log $lvl "Size: 4096"
idm_log $lvl "Type: 2y" lib_log $lvl "Type: 2y"
if [ "$type" == "main" ]; then if [ "$type" == "main" ]; then
idm_log $lvl "Name: ${name} (must be 5 char min!)" lib_log $lvl "Name: ${name} (must be 5 char min!)"
idm_log $lvl "Email: ${GIT_AUTHOR_EMAIL}" lib_log $lvl "Email: ${GIT_AUTHOR_EMAIL}"
idm_log $lvl "Comment: <none>" lib_log $lvl "Comment: <none>"
idm_log $lvl "Passphrase: Very strong" lib_log $lvl "Passphrase: Very strong"
elif [ "$type" == "main" ]; then elif [ "$type" == "main" ]; then
idm_log $lvl "Type: quit and save changes" lib_log $lvl "Type: quit and save changes"
fi fi
idm_log NOTICE "PGP key generation interface" lib_log NOTICE "PGP key generation interface"
} }
idm_gpg_new () idm_gpg_match_one_pubkey ()
{
local id=${1}
idm_is_enabled $id
key="$( idm_gpg__get_def_key $id )"
idm_gpg__cli_helper $id sub
gpg --edit-key $key addkey
idm_log NOTICE "Your subkey $name is ready :)"
}
# Should be used for subkeys ....
idm_gpg_init ()
{
local id=${1}
idm_is_enabled $id
! idm_gpg__get_def_key $id &>/dev/null || \
idm_exit 1 "You already have an id !"
# Generate top secret id
idm_gpg__cli_helper $id main
gpg --gen-key
# Generate encyption key
idm_gpg_new $id
idm_log NOTICE "Your personal key $name is ready :)"
}
idm_gpg__get_def_key ()
{ {
key=${1} key=${1}
@ -185,40 +200,26 @@ idm_gpg__get_def_key ()
gpg2 --list-keys | grep "uid"| grep "${key:-}" \ gpg2 --list-keys | grep "uid"| grep "${key:-}" \
| sed -E 's/[^<]*<([^>]*)>.*/\1/' | sed -E 's/[^<]*<([^>]*)>.*/\1/'
) || { ) || {
idm_log WARN "Could not find a matching key for '$key'" lib_log WARN "Could not find a matching key for '$key'"
return 1 return 1
} }
if [ "$( wc -l <<<"$key")" -ne 1 ]; then if [ "$( wc -l <<<"$key")" -ne 1 ]; then
idm_log WARN "Too much keys for matching '$1'" lib_log WARN "Too much keys for matching '$1'"
idm_log DUMP - <<<"$key" lib_log DUMP - <<<"$key"
return 1 return 1
fi fi
echo "$key" echo "$key"
} }
idm_gpg_del ()
{
local id=${1}
local key=${2:-$1}
# Scan key
key=$(idm_gpg__get_def_key $key)
idm_log WARN "Do you really want to destroy the '$key' key?"
idm_cli_timeout 1 || rc=$?
gpg --delete-key "$key" || true
gpg --delete-secret-key "$key" || true
}
## GPG shared lib
##############################
# Source: https://github.com/roddhjav/pass-tomb/blob/master/tomb.bash # Source: https://github.com/roddhjav/pass-tomb/blob/master/tomb.bash
# $@ is the list of all the recipient used to encrypt a tomb key # $@ is the list of all the recipient used to encrypt a tomb key
idm_gpg__is_valid_recipients() { lib_gpg_is_valid_recipients() {
typeset -a recipients typeset -a recipients
recipients=($@) recipients=($@)
@ -226,13 +227,13 @@ idm_gpg__is_valid_recipients() {
for gpg_id in "${recipients[@]}"; do for gpg_id in "${recipients[@]}"; do
gpg --list-keys "$gpg_id" &> /dev/null gpg --list-keys "$gpg_id" &> /dev/null
if [[ $? != 0 ]]; then if [[ $? != 0 ]]; then
idm_log ERR "${gpg_id} is not a valid key ID." lib_log ERR "${gpg_id} is not a valid key ID."
return 1 return 1
fi fi
done done
} }
idm_gpg__is_valid_key() { lib_gpg_is_valid_key() {
typeset -a recipients typeset -a recipients
recipients=($@) recipients=($@)
# At least one private key must be present # At least one private key must be present
@ -244,3 +245,109 @@ idm_gpg__is_valid_key() {
done done
return 1 return 1
} }
lib_gpg_decrypt_dir ()
{
local src=$1
local dst=${2-}
local key=${3-}
local gpg_opts=""
local tar_opts=
#set -x
# Check required bin
lib_require_bin tar || idm_exit 1
lib_require_bin gpg2 || idm_exit 1
export GPG=${GPG2:-$GPG}
tar_opts=" -C ${dst%/*} -zx "
if [ ! -z "$key" ]; then
gpg_opts+="--batch -d"
else
gpg_opts+="-d"
fi
$GPG $gpg_opts $src | $TAR $tar_opts || \
idm_exit 1 ERR "Could not decrypt file: $src into $dst"
}
lib_gpg_encrypt_dir ()
{
local src=$1
local dst=$2
local key=${3-}
local pass=
local recipients=
# Check required bin
lib_require_bin tar || idm_exit 1
lib_require_bin gpg2 || idm_exit 1
export GPG=${GPG2:-$GPG}
#GPG_KEY="$(yadm config yadm.gpg-recipient || true )"
#GPG_KEY="${GPG_DEFAULT_ID-}"
# Check pgp key and arguments
if lib_gpg_is_valid_key $key; then
shift 3
local ok=0 ko=0
recipients=${@:-${GPG_DEFAULT_ID-}}
gpg_opts="-e -r $recipients"
# Determine if we are looking for key or password
for r in $recipients; do
lib_gpg_is_valid_recipients $r &>/dev/null \
&& ok=$(( $ok + 1 ))\
|| ko=$(( $ko + 1 ))
if [[ "$ok" -ne 0 && "$ko" -ne 0 ]]; then
idm_exit 1 "One of the recipients is not known: $r in '$recipients'"
fi
done
# Act according our pattern
if [[ "$ok" -eq 0 && "$ko" -ne 0 ]]; then
pass="$@"
recipients=
gpg_opts="-c"
lib_log NOTICE "Secret will be encrypted with pass '$pass'"
else
lib_log NOTICE "Secret will be encrypted with key '$key' ${recipients:+ to '$recipients'}"
fi
else
if [ "$key" == "_ASK" ]; then
pass=_ASK
key=
gpg_opts="--no-default-recipient -e"
lib_log NOTICE "User will be prompted for known recipients"
elif [ -z "$key" -o "$key" == "_PASS" ]; then
pass=
key=
gpg_opts="-c"
lib_log NOTICE "User will be prompted for password (symetric)"
else
# Not available yet, see stdin for password input
# To fix: passwords in clear :/ use stdout3
pass="$key"
key=
gpg_opts="-c --passphrase $pass --batch "
lib_log NOTICE "Secret will be encrypted with pass '***' (symetric)"
fi
fi
# Encrypt all the stuffs
$TAR -C "${src%/*}" -cz "${src##*/}" 2>/dev/null | \
$GPG -a $gpg_opts --yes -o $dst || \
idm_exit 1 ERR "Could not encrypt directory: $src"
# File descritor tests ...
#exec 3<> /tmp/foo
#>&3 echo "$pass"
#{ echo "$pass\n" >&3 ; $TAR -C "$(dirname $src)" -cz "$src" 2>/dev/null; } | \
#exec 3>&- #close fd 3.
}

View File

@ -6,7 +6,7 @@ IDM_MOD_DEPS=""
########################################## ##########################################
idm_id_help () idm_id__help ()
{ {
echo "Identity management:" echo "Identity management:"
printf " %-20s: %s\n" "id ls" "List all disks of all policies" printf " %-20s: %s\n" "id ls" "List all disks of all policies"
@ -20,19 +20,19 @@ idm_id_help ()
idm_id () idm_id ()
{ {
idm_id_ls ${@-} idm_id__ls ${@-}
} }
idm_id_disable() idm_id__disable()
{ {
# Disable internal variables # Disable internal variables
echo "unset SHELL_ID GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL" | idm_log CODE - echo "unset SHELL_ID GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL" | lib_log CODE -
} }
idm_id_kill () { idm_id_disable ${@-}; } idm_id__kill () { idm_id__disable ${@-}; }
idm_id_enable() idm_id__enable()
{ {
local id=${1} local id=${1}
local conf="$IDM_DIR_ID/$id.env" local conf="$IDM_DIR_ID/$id.env"
@ -65,7 +65,7 @@ idm_id_enable()
# echo "export XDG_OPT_HOME=$XDG_OPT_HOME" # echo "export XDG_OPT_HOME=$XDG_OPT_HOME"
} }
idm_id_new () idm_id__new ()
{ {
local id=${2:-$1} local id=${2:-$1}
@ -81,12 +81,12 @@ idm_id_new ()
$EDITOR "$conf" $EDITOR "$conf"
# Notice user # Notice user
idm_log NOTICE "Id '$id' has been created:" lib_log NOTICE "Id '$id' has been created:"
cat $conf | idm_log CODE - cat $conf | lib_log CODE -
} }
idm_id_show () idm_id__show ()
{ {
local id=${1} local id=${1}
local conf local conf
@ -98,15 +98,16 @@ idm_id_show ()
conf="$IDM_DIR_ID/$id.env" conf="$IDM_DIR_ID/$id.env"
# Notice user # Notice user
idm_log INFO "Id '$id' configuration:" lib_log INFO "Id '$id' configuration:"
idm_get id_config $id | idm_log CODE - idm_get id_config $id | lib_log CODE -
# cat $conf | idm_log CODE # cat $conf | lib_log CODE
} }
idm_id_ls () idm_id__ls ()
{ {
local active local active
#set -x
for id in $(idm_get all_id); do for id in $(idm_get all_id); do
@ -125,11 +126,11 @@ idm_id_ls ()
eval "$(idm_get id_config $id)" eval "$(idm_get id_config $id)"
echo "$active:$id::::${common_name-} (${email-})" echo "$active:$id::::${common_name-} (${email-})"
) )
done | column -t -s: -o' ' | idm_log DUMP - done | column -t -s: -o' ' #| lib_log DUMP -
} }
idm_id_edit () idm_id__edit ()
{ {
local id=${1} local id=${1}
local md5 conf local md5 conf
@ -144,14 +145,14 @@ idm_id_edit ()
# Notice user # Notice user
if [[ "$md5" == "$(md5sum $conf)" ]] ;then if [[ "$md5" == "$(md5sum $conf)" ]] ;then
idm_log INFO "Id '$id' has not been updated:" lib_log INFO "Id '$id' has not been updated:"
else else
idm_log NOTICE "Id '$id' has been updated:" lib_log NOTICE "Id '$id' has been updated:"
fi fi
cat $conf | idm_log CODE - cat $conf | lib_log CODE -
} }
idm_id_get () idm_id__get ()
{ {
local id=${1} local id=${1}
@ -168,14 +169,14 @@ idm_id_get ()
} }
idm_id_dump () idm_id__dump ()
{ {
for id in $(idm_get all_id); do for id in $(idm_get all_id); do
#idm_log NOTICE "Identity $id" #lib_log NOTICE "Identity $id"
{ {
idm_get id_config $id idm_get id_config $id
echo " " echo " "
} | idm_log CODE - } | lib_log CODE -
done done
} }
@ -192,7 +193,7 @@ idm_id_template ()
echo "tz=$tz" echo "tz=$tz"
} }
idm_id_rm () idm_id__rm ()
{ {
local id=${1} local id=${1}
@ -206,6 +207,6 @@ idm_id_rm ()
rm "$IDM_DIR_ID/$id.env" || \ rm "$IDM_DIR_ID/$id.env" || \
idm_exit 1 ERR "File '$IDM_DIR_ID/$id.env' could not be deleted" idm_exit 1 ERR "File '$IDM_DIR_ID/$id.env' could not be deleted"
else else
idm_log WARN "File '$IDM_DIR_ID/$id.env' was already deleted" lib_log WARN "File '$IDM_DIR_ID/$id.env' was already deleted"
fi fi
} }

View File

@ -11,7 +11,7 @@ idm_pass ()
#set -x #set -x
if [ "$#" -eq 1 ]; then if [ "$#" -eq 1 ]; then
local id=$1 local id=$1
idm_pass_ls $id idm_pass__ls $id
return 0 return 0
else else
local action=$1 local action=$1
@ -28,15 +28,15 @@ idm_pass ()
} }
idm_pass_ls () idm_pass__ls ()
{ {
local id=${1} local id=${1}
idm_is_enabled $id idm_validate is_enabled $id || return 0
PASSWORD_STORE_DIR=~/.config/pass/${id} pass ls PASSWORD_STORE_DIR=~/.config/pass/${id} pass ls | sed 's/^/ /'
} }
idm_pass_help () idm_pass__help ()
{ {
echo "Standard UNIX Password Manager" echo "Standard UNIX Password Manager"
printf " %-20s: %s\n" "pass ls" "List passwords" printf " %-20s: %s\n" "pass ls" "List passwords"
@ -49,19 +49,19 @@ idm_pass_help ()
} }
idm_pass_enable () idm_pass__enable ()
{ {
local id=${1} local id=${1}
idm_is_enabled $id ! idm_validate id_config $id
echo "export PASSWORD_STORE_DIR=~/.config/pass/${id}" echo "export PASSWORD_STORE_DIR=~/.config/pass/${id}"
} }
idm_pass_disable () idm_pass__disable ()
{ {
local id=${1} local id=${1}
idm_is_enabled $id idm_validate id_config $id
echo "unset PASSWORD_STORE_DIR" echo "unset PASSWORD_STORE_DIR"
} }

View File

@ -15,7 +15,7 @@ idm_ps1 ()
idm_ps1_ls idm_ps1_ls
} }
idm_ps1_ls () idm_ps1__ls ()
{ {
local id=${1} local id=${1}
@ -23,21 +23,21 @@ idm_ps1_ls ()
#echo "PS1=${SHELL_PS1:-${PS1-}}" #echo "PS1=${SHELL_PS1:-${PS1-}}"
if grep -q "($id)" <<<"${SHELL_PS1:-${PS1-}}" ; then if grep -q "($id)" <<<"${SHELL_PS1:-${PS1-}}" ; then
echo "enabled" echo " enabled"
else else
echo "disabled" echo " disabled"
fi fi
} }
idm_ps1_help () idm_ps1__help ()
{ {
echo "Shell Prompt" echo "Shell Prompt"
printf " %-20s: %s\n" "ps1 enable" "Enable prompt" printf " %-20s: %s\n" "ps1 enable" "Enable prompt"
printf " %-20s: %s\n" "ps1 disable" "Disable prompt" printf " %-20s: %s\n" "ps1 disable" "Disable prompt"
} }
idm_ps1_enable () idm_ps1__enable ()
{ {
local id=${1} local id=${1}
id="\[\033[0;34m\]($id)\[\033[00m\]" id="\[\033[0;34m\]($id)\[\033[00m\]"
@ -49,10 +49,10 @@ idm_ps1_enable ()
} }
idm_ps1_disable () idm_ps1__disable ()
{ {
echo "export PS1=\"\${IDM_SHELL_PS1}\"" echo "export PS1=\"\${IDM_SHELL_PS1}\""
return return
} }
idm_ps1_kill () { idm_ps1_disable ${@-}; } idm_ps1__kill () { idm_ps1__disable ${@-}; }

View File

@ -8,7 +8,7 @@ IDM_MOD_DEPS="id gpg"
## SSH functions ## SSH functions
########################################## ##########################################
idm_ssh_help () idm_ssh__help ()
{ {
echo "Secure Shell" echo "Secure Shell"
# printf " %-20s: %s\n" "info" "Info submenu" # printf " %-20s: %s\n" "info" "Info submenu"
@ -29,7 +29,7 @@ idm_ssh ()
# Argument maangement # Argument maangement
if [ "$#" -eq 1 ]; then if [ "$#" -eq 1 ]; then
local id=$1 local id=$1
idm_ssh_ls $id idm_ssh__ls $id
return 0 return 0
else else
local action=$1 local action=$1
@ -50,30 +50,32 @@ idm_ssh ()
## Required functions ## Required functions
########################################## ##########################################
idm_ssh_ls () idm_ssh__ls ()
{ {
local id=$1 local id=$1
local opt=${2:--l} local opt=${2:--l}
local opt=-l
idm_is_enabled $id idm_validate is_enabled $id || return 0
{ ssh-add $opt || true ; } | idm_log DUMP - { ssh-add $opt || true ; } | sed 's/^/ /'
} }
idm_ssh_disable () idm_ssh__disable ()
{ {
local id=$1 local id=$1
idm_is_enabled $id #idm_is_enabled $id
idm_validate id_config $id
# Return portion of code to clean # Return portion of code to clean
echo "unset SSH_AUTH_SOCK SSH_AGENT_PID" echo "unset SSH_AUTH_SOCK SSH_AGENT_PID"
} }
idm_ssh_enable () idm_ssh__enable ()
{ {
local id=$1 local id=$1
idm_is_enabled $id idm_validate id_config $id
# Source environment # Source environment
if [ -f "${XDG_RUNTIME_DIR}/ssh-agent/${id}/env" ] ; then if [ -f "${XDG_RUNTIME_DIR}/ssh-agent/${id}/env" ] ; then
@ -85,7 +87,7 @@ idm_ssh_enable ()
# Check status # Check status
if ! idm_ssh__is_agent_working $id ${SSH_AUTH_SOCK:-_} ${SSH_AGENT_PID:-0}; then if ! idm_ssh__is_agent_working $id ${SSH_AUTH_SOCK:-_} ${SSH_AGENT_PID:-0}; then
if ! idm_ssh__agent_start $id; then if ! idm_ssh__agent_start $id; then
idm_log WARN "Could not start ssh agent :(" lib_log WARN "Could not start ssh agent :("
return 1 return 1
fi fi
fi fi
@ -95,7 +97,7 @@ idm_ssh_enable ()
} }
# LOGOUT # LOGOUT
idm_ssh_kill () { idm_ssh__kill () {
#set -x #set -x
@ -104,7 +106,7 @@ idm_ssh_kill () {
idm_is_enabled $id idm_is_enabled $id
#idm_log NOTICE "Cleaning ssh-agent ..." #lib_log NOTICE "Cleaning ssh-agent ..."
[ -z "${SSH_AGENT_PID-}" ] && \ [ -z "${SSH_AGENT_PID-}" ] && \
[ -f "$run_dir/env" ] && \ [ -f "$run_dir/env" ] && \
@ -113,7 +115,7 @@ idm_ssh_kill () {
# Clean ssh-agent process # Clean ssh-agent process
if kill -0 ${SSH_AGENT_PID-} &>/dev/null; then if kill -0 ${SSH_AGENT_PID-} &>/dev/null; then
/usr/bin/ssh-agent -k >/dev/null /usr/bin/ssh-agent -k >/dev/null
idm_log NOTICE "Kill ssh-agent ..." lib_log NOTICE "Kill ssh-agent ..."
fi fi
#eval "$(/usr/bin/ssh-agent -k 2>/dev/null)" #eval "$(/usr/bin/ssh-agent -k 2>/dev/null)"
@ -122,7 +124,7 @@ idm_ssh_kill () {
rm "${XDG_RUNTIME_DIR}/ssh-agent/${id}/env" rm "${XDG_RUNTIME_DIR}/ssh-agent/${id}/env"
# Disable agent # Disable agent
idm_ssh_disable $id idm_ssh__disable $id
set +x set +x
@ -168,9 +170,9 @@ idm_ssh__agent_start() {
if ssh-agent -a "$run_dir/socket" -t $life -s | grep ^SSH_ > "$run_dir/env"; then if ssh-agent -a "$run_dir/socket" -t $life -s | grep ^SSH_ > "$run_dir/env"; then
echo "$run_dir/env" echo "$run_dir/env"
idm_log INFO "Start ssh-agent ..." lib_log INFO "Start ssh-agent ..."
else else
idm_log WARN "Could not start ssh agent :(" lib_log WARN "Could not start ssh agent :("
return 1 return 1
fi fi
@ -205,7 +207,7 @@ idm_ssh__agent_clean () {
fi fi
unset SSH_AUTH_SOCK SSH_AGENT_PID unset SSH_AUTH_SOCK SSH_AGENT_PID
#idm_log INFO "ssh-agent env cleaned is now clean" #lib_log INFO "ssh-agent env cleaned is now clean"
} }
@ -244,8 +246,8 @@ idm_ssh_add ()
[ -n "$pub_keys" ] || \ [ -n "$pub_keys" ] || \
idm_exit 0 WARN "No keys found" idm_exit 0 WARN "No keys found"
idm_log INFO "Adding keys:" lib_log INFO "Adding keys:"
xargs -n 1 <<<$key_list | idm_log DUMP - xargs -n 1 <<<$key_list | lib_log DUMP -
echo "" echo ""
ssh-add $key_list ssh-add $key_list
@ -269,12 +271,12 @@ idm_ssh__agent_check ()
elif SSH_AUTH_SOCK=$socket SSH_AGENT_PID=$pid ssh-add -l &>/dev/null ; then elif SSH_AUTH_SOCK=$socket SSH_AGENT_PID=$pid ssh-add -l &>/dev/null ; then
return 0 return 0
else else
idm_log WARN "ssh-agent is not working as expected" lib_log WARN "ssh-agent is not working as expected"
fi fi
# Is the socket valid ? # Is the socket valid ?
if [ "$socket" != '_' -a ! -S "$socket" ]; then if [ "$socket" != '_' -a ! -S "$socket" ]; then
idm_log WARN "Socket '$socket' is dead, can't recover ssh-agent" lib_log WARN "Socket '$socket' is dead, can't recover ssh-agent"
idm_ssh__agent_clean $id $socket 0 idm_ssh__agent_clean $id $socket 0
return 1 return 1
fi fi
@ -283,13 +285,13 @@ idm_ssh__agent_check ()
local pid="$( ps aux | grep "$socket" | grep -v 'grep' | head -n 1 | awk '{ print $2 }' )" || \ local pid="$( ps aux | grep "$socket" | grep -v 'grep' | head -n 1 | awk '{ print $2 }' )" || \
pid="$( ps aux | grep "" | grep -v 'grep' | head -n 1 | awk '{ print $2 }' )" || \ pid="$( ps aux | grep "" | grep -v 'grep' | head -n 1 | awk '{ print $2 }' )" || \
{ {
idm_log WARN "Process ssh-agent is dead, cannot recover" lib_log WARN "Process ssh-agent is dead, cannot recover"
idm_ssh__agent_clean $id $socket 0 idm_ssh__agent_clean $id $socket 0
return 1 return 1
} }
# Kill all processes # Kill all processes
idm_log DEBUG "Multiple PID founds for ssh-agent: $pid" lib_log DEBUG "Multiple PID founds for ssh-agent: $pid"
q=0 q=0
for p in $pid; do for p in $pid; do
return return
@ -304,7 +306,7 @@ idm_ssh__agent_check ()
# Hmm, we should not arrive here ... # Hmm, we should not arrive here ...
idm_log WARN "ssh-agent is in a really weird state :/" lib_log WARN "ssh-agent is in a really weird state :/"
return 1 return 1
} }

View File

@ -14,17 +14,22 @@ IDM_MOD_PREF="core id"
# #
# This allow to secure your things .... # This allow to secure your things ....
#set -x
idm_vars_git_tomb () {
git_tomb_work_tree=$HOME
git_tomb_dir=$IDM_DIR_CACHE/git/$id/tomb.git
git_tomb_config=${IDM_CONFIG_DIR}/git/$id/tomb_gitconfig
git_tomb_enc=$IDM_CONFIG_DIR/enc/$id.tomb
}
## Common functions ## Front functions
############################## ##############################
idm_tomb_help () idm_tomb__help ()
{ {
local id=$1 local id=$1
idm_vars_git_tomb $id idm_vars_git_tomb
echo "tomb" echo "tomb"
echo " workflow:" echo " workflow:"
@ -33,286 +38,501 @@ idm_tomb_help ()
printf " %-20s: %s\n" "tomb decrypt" "Decrypt the tomb" printf " %-20s: %s\n" "tomb decrypt" "Decrypt the tomb"
printf " %-20s: %s\n" "tomb sync" "Synchronise tomb(s)" printf " %-20s: %s\n" "tomb sync" "Synchronise tomb(s)"
printf " %-20s: %s\n" "tomb encrypt" "Save the current configuration into the tomb" printf " %-20s: %s\n" "tomb encrypt" "Save the current configuration into the tomb"
printf " %-20s: %s\n" "tomb push <remote>|all" "Save the current configuration into the tomb"
printf " %-20s: %s\n" "tomb leave" "Remove all traces of your passage" printf " %-20s: %s\n" "tomb leave" "Remove all traces of your passage"
echo " config:" echo " config:"
printf " %-20s: %s\n" "tomb_enc" "$tomb_enc" printf " %-20s: %s\n" "git_tomb_enc" "$git_tomb_enc"
printf " %-20s: %s\n" "git_dir" "$git_dir" printf " %-20s: %s\n" "git_tomb_dir" "$git_tomb_dir"
printf " %-20s: %s\n" "git_config" "$git_config" printf " %-20s: %s\n" "git_tomb_config" "$git_tomb_config"
return 0 return 0
} }
idm_tomb_ls () idm_tomb__ls ()
{ {
local id=$1 local id=$1
idm_vars_git_tomb $id idm_vars_git_tomb
local g_st=
local t_st=
local d_c=
local d_m=
local date_today=$(date '+%s')
if [ -d "$git_tomb_dir" ]; then
g_st=open
g_m=$( lib_date_diff_human $(find $git_tomb_dir -maxdepth 0 -printf "%Ts") )
g_m=" $d_m"
else
g_st=closed
g_m=
fi
if [ -f "$git_tomb_enc" ]; then
t_st=present
t_m=$( lib_date_diff_human $(find $git_tomb_enc -printf "%Ts") )
t_m=", $t_m old"
else
t_st=absent
t_m=
fi
echo " Info:" echo " Info:"
printf " %-20s: %s\n" "opened" "yes" printf " %-20s: %s\n" "encrypted tomb" "$t_st${t_m}"
printf " %-20s: %s\n" "last mod." "yes" printf " %-20s: %s\n" "encrypted file" "$git_tomb_enc"
printf " %-20s: %s\n" "git" "$git_dir" printf " %-20s: %s\n" "tomb git status" "$g_st$g_m"
printf " %-20s: %s\n" "last date" "" printf " %-20s: %s\n" "tomb git dir" "$git_tomb_dir"
echo " Remotes:" if lib_git_is_repo $git_tomb_dir $git_tomb_work_tree; then
_git_local remote -v | sed 's/^/ /' echo " Git remotes:"
_git_tomb remote -v | sed 's/^/ /'
fi
} }
# This leave everything open at this stage !!!
idm_tomb__sync ()
{
local id=$1
local repo_name=${2:-tomb}
# Sanity check: id and local repo
idm_tomb_require_enabled $id
idm_tomb_require_valid_local_repo
# Tomb repo check
#set -x
if ! lib_git_is_repo $git_tomb_dir $git_tomb_work_tree; then
if [ -f "$git_tomb_enc" ]; then
lib_log WARN "An encrypted tomb has been found. Do you want to decrypt it?"
idm_cli_timeout 1 || idm_exit 1 ERR "Refuse to create a tomb duplicate"
idm_tomb__decrypt $id || idm_exit 1 ERR "Failed to create tomb repo"
elif [ ! -d "$git_tomb_dir" ]; then
idm_tomb__init $id || idm_exit 1 ERR "Tomb cannot be used without git"
lib_log NOTICE "A tomb has been created"
return 0
else
idm_exit 1 ERR "Unknow error"
fi
fi
# Work on local
_git_tomb remote show $repo_name &>/dev/null ||
_git_tomb remote add $repo_name $git_tomb_dir ||
idm_exit 1 ERR "Failed to add tomb remote to local git"
{
_git_tomb fetch --all --tags &&
_git_tomb push -u $repo_name --all &&
_git_tomb push -u $repo_name --tags
} >/dev/null || idm_exit 1 ERR "Something where wrong while syncinc"
lib_log NOTICE "Tomb and local repository are now synced"
# Restore ctx
}
# We manage distribution of our repo
# but maybe it should be the lib_git_local roles ...
idm_tomb__push ()
{
local id=$1
local arg=${2-}
idm_tomb__init $id
# Manage argument
if grep -sq "$arg" $IDM_CONFIG_DIR/git/$id/known_hosts ; then
arg=$( grep -sq "$arg" $IDM_CONFIG_DIR/git/$id/known_hosts | head -n 1 )
idm_tomb_ssh_sync $arg ||
idm_exit 1 "Could not copy tomb to $arg"
lib_log NOTICE "Tomb has been exported: $arg:$dst/$id.tomb"
elif [ "$arg" == 'all' ]; then
remotes="$(_git_tomb remote -v | awk '{ print $1 }' | uniq )"
for repo_name in $remotes; do
lib_log INFO "Synchronising remote $repo_name ..."
_git_tomb fetch --all --tags &&
_git_tomb push -u $repo_name --all &&
_git_tomb push -u $repo_name --tags ||
lib_log WARN "Could not sync with $reponame"
done
elif _git_tomb remote -v | grep -q "^$arg"; then
idm_tomb__sync $id $arg
else
# Actually export the tomb :p
#ssh $arg "hostname" ||
# idm_exit 1 "Could not connect to $arg"
#idm_tomb_gen_script_export | lib_log DUMP -
lib_log INFO "Trying to connect to $arg ..."
dst=$( ssh $arg "$(idm_tomb_gen_script_export)" ) ||
idm_exit 1 "Something failed $arg"
echo "$arg" >> $IDM_CONFIG_DIR/git/$id/known_hosts
scp $git_tomb_enc $arg:$dst/$id.tomb ||
idm_exit 1 "Could not copy tomb to $arg"
lib_log NOTICE "Tomb has been exported: $arg:$dst/$id.tomb"
fi
#if ssh $arg "hostname" > /den/null; then
# idm_exit 0 "SSH sync not implemented yet "
#else
# # Propagate with git
# idm_tomb__sync $id
#fi
}
idm_tomb_ssh_sync ()
{
local host=$1
local dst=
# Test connection and prepare destination
lib_log INFO "Trying to connect to $host ..."
dst=$( ssh $host "$(idm_tomb_gen_script_export)" ) ||
idm_exit 1 "Something failed $host"
# Save host
echo "$host" >> $IDM_CONFIG_DIR/git/$id/known_hosts
# Copy tomb to remote
scp $git_tomb_enc $host:$dst/$id.tomb
}
idm_tomb_gen_script_export ()
{
cat <<EOF -
dest=\${IDM_CONFIG_DIR:-\${XDG_CONFIG_HOME:-~/.config}/idmgr}/enc
mkdir -p \$dest || {
echo "Could not create destination dir: \$dest"
exit 1
}
echo \$dest
EOF
}
idm_tomb__encrypt ()
{
local id=$1
# Sanity check: id and local repo
idm_tomb__init $id
#idm_tomb_require_enabled $id
#idm_tomb_require_valid_local_repo || idm_exit 1 ERR "Cound not continue"
# We check tomb repo here
lib_git_is_repo $git_tomb_dir $git_tomb_work_tree || \
idm_tomb__init $id || \
idm_exit 1 ERR "Tomb cannot be used without git"
# Full sync both repo
idm_tomb__sync $id ||
idm_exit 1 ERR "Failed to push commits to tomb repo"
# Encrypt tomb data
lib_gpg_encrypt_dir $git_tomb_dir $git_tomb_enc || \
idm_exit 1 ERR "Failed to create tomb"
## Encrypt local data
lib_gpg_encrypt_dir $git_local_dir $git_local_enc $GIT_AUTHOR_EMAIL || \
idm_exit 1 ERR "Could not create local repo data"
# Clean tomb
rm -rf $git_tomb_dir
lib_log NOTICE "Tomb has been closed into: $git_tomb_enc"
}
idm_tomb__decrypt ()
{
local id=$1
shift || true
local opt=${@-}
# Sanity check
idm_tomb_require_enabled $id
idm_tomb_require_valid_local_repo || idm_exit 1 ERR "Cound not continue"
# Check if tomb repo is absent
##_load_tomb_env
if lib_git_is_repo $git_tomb_dir $git_local_work_tree ; then
lib_log WARN "A local repo is already present, we will overwrite it. Do you want to continue?"
idm_cli_timeout 0 || idm_exit 1 ERR "Refuse to override existing repo"
# Let's not delete existing repo, just for fun and wee how git react :p
fi
# Extract tomb
lib_gpg_decrypt_dir $git_tomb_enc $git_tomb_dir || \
idm_exit 1 ERR "Could not extract tomb"
# Extract local repo
if idm_tomb_require_valid_local_repo; then
# Local repo always win !, so we just sync
lib_log INFO "Local repo already present, we just start sync"
idm_tomb__sync $id
else
lib_gpg_decrypt_dir $git_tomb_enc $git_tomb_dir || \
idm_exit 1 ERR "Could not extract tomb"
fi
lib_log NOTICE "Your tomb has been decrypted"
}
idm_tomb__init()
{
local id=$1
shift
# Sanity check: id and local repo
idm_tomb_require_enabled $id
idm_tomb_require_valid_local_repo || idm_exit 1 ERR "Cound not continue"
# Load tomb environment from local
if [ ! -d "$git_tomb_dir" ] ; then
mkdir -p "$git_tomb_dir"
_git_tomb clone --bare $git_local_dir $git_tomb_dir || \
idm_exit 1 ERR "Could not create tomb repo"
lib_log NOTICE "Tomb repository has been created"
else
lib_log INFO "Tomb repository alreay exists"
fi
# Load tomb environment from encrypted_tomb
# Load tomb environment from user@server/encrypted.tomb
# Syncrhonise with tomb
if lib_git_has_commits $git_local_dir $git_local_work_tree ; then
idm_tomb__sync $id
fi
lib_log NOTICE "Tomb repository has been created"
}
idm_tomb__shred ()
{
local id=$1
local arg=${2-}
local files=
idm_tomb_require_enabled $id
case $arg in
local) files="$git_local_dir" ;;
tomb) files="$git_tomb_dir" ;;
all) files="$git_tomb_dir $git_local_dir" ;;
full) files="$git_tomb_dir $git_local_dir $git_local_enc" ;;
disapear) files="$git_tomb_dir $git_local_dir $git_local_enc $( idm_git__get_files_of_interest $id | sed 's@^@~/@' | xargs )" ;;
*)
idm_exit 1 "You need to say: local|tomb|all|full"
;;
esac
lib_log WARN "All these files will be IRREVOCABLY DELETED."
xargs -n 1 <<< "$files" | lib_log DUMP -
lib_log WARN "Do you want to continue ?"
idm_cli_timeout 1 || idm_exit 1 ERR "No data deleted"
lib_log WARN "Run it yourself: rm -rf $files"
}
idm_tomb__enable () { return 0; }
idm_tomb__disable () { return 0; }
idm_tomb__kill () { return 0; }
## IDM API functions
##############################
## Internal functions ## Internal functions
############################## ##############################
idm_git__bin_git () idm_tomb_require_enabled ()
{ {
if idm_validate id_config $1; then local id=$1
id=${1} ;shift
fi # Sanity check
idm_vars_git_local $id idm_validate id_config $id
idm_git__bin ${*-}
# Load local repo vars
idm_vars_git_local
git_local_enc=$IDM_CONFIG_DIR/enc/$id.tomb
# Load tomb vars
idm_vars_git_tomb
} }
# A wrapper before calling git _git_tomb ()
idm_tomb__bin_git ()
{ {
# Ugly bugfix :( lib_git_bin $git_tomb_dir $git_tomb_work_tree $@ || return
if idm_validate id_config $1; then rc=$?
id=${1} ;shift #echo "RETURN2: $rc"
fi return $rc
idm_vars_git_tomb $id
idm_git__bin ${*-}
} }
# Shortcuts _git_local ()
_git_local () { idm_git__bin_git ${*-}; } {
_git_tomb () { idm_tomb__bin_git ${*-}; } local rc=0
_load_local_env () { idm_vars_git_local ${*-}; } lib_git_bin $git_tomb_dir $git_tomb_work_tree $@ || rc=$?
_load_tomb_env () { idm_vars_git_tomb ${*-}; } return $rc
}
## Module functions ## Module functions
############################## ##############################
idm_vars_git_tomb() idm_tomb_require_valid_local_repo ()
{ {
var_id=git_tomb
id=${id:-$SHELL_ID}
git_work_tree=$HOME
git_dir=$IDM_DIR_CACHE/git/$id/tomb.git
git_config=${IDM_CONFIG_DIR}/git/$id/tomb_gitconfig
tomb_enc=$IDM_CONFIG_DIR/enc/$id.tomb
} if ! lib_git_is_repo $git_local_dir $git_local_work_tree ; then
idm_tomb_init()
{
local id=$1
shift || true
# Sanity check
idm_validate id_config $id
local old_var_id=${var_id-}
# Check local repository state
_load_local_env
local local_git_dir=$git_dir
if ! idm_git__is_repo; then
idm_exit 1 NOTICE "You need to have a local repo first" idm_exit 1 NOTICE "You need to have a local repo first"
elif ! idm_git__has_commits ; then elif ! lib_git_has_commits $git_local_dir $git_local_work_tree ; then
idm_exit 1 NOTICE "You need to commit all your changes" idm_exit 1 NOTICE "You need to commit all your changes"
fi fi
# Load tomb environment from local
_load_tomb_env
if [ ! -d "$git_dir" ] ; then
mkdir -p "$git_dir"
_git_tomb clone --bare $local_git_dir $git_dir || \
idm_exit 1 "Could not create tomb repo"
idm_exit 0 NOTICE "Tomb repository has been created"
fi
idm_log INFO "Tomb repository alreay exists"
# Load tomb environment from encrypted_tomb
# Load tomb environment from user@server/encrypted.tomb
[ "$old_var_id" == "$var_id" ] || idm_vars_${old_var_id} ${id}
} }
idm_tomb_sync () # Moved to mod_gpg
{ # ## GPG functions
local id=$1 # ##############################
shift || true #
#
# Sanity check # lib_gpg_decrypt_dir ()
idm_validate id_config $id # {
# local src=$1
# Load tomb config # local dst=${2-}
_load_tomb_env # local key=${3-}
local repo_url=$git_dir # local gpg_opts=""
local repo_name=tomb # local tar_opts=
#
# Work on local # # Check required bin
_git_local remote add $repo_name $repo_url || true # lib_require_bin tar || idm_exit 1
_git_local fetch --all # lib_require_bin gpg2 || idm_exit 1
_git_local fetch --all --tags # export GPG=${GPG2:-$GPG}
_git_local push -u $repo_name --all #
_git_local push -u $repo_name --tags # tar_opts=" -C ${dst%/*} -zx "
# if [ ! -z "$key" ]; then
idm_log NOTICE "Tomb and local repository are now synced" # gpg_opts+="--batch -d"
# else
} # gpg_opts+="-d"
# fi
idm_tomb_encrypt () #
{ # $GPG $gpg_opts $src | $TAR $tar_opts || \
local id=$1 # idm_exit 1 ERR "Could not decrypt file: $src into $dst"
shift || true #
local opt=${@-} # }
local TOFIX_opt=$opt #
local old_var_id=${var_id-} #
# lib_gpg_encrypt_dir ()
# Sanity check # {
idm_validate id_config $id # local src=$1
# local dst=$2
# We load LOCAL VARS HERE # local key=${3-}
_load_local_env # local pass=
idm_git__has_commits || \ # local recipients=
idm_exit 1 "You need to commit first" #
idm_git__is_all_commited || \ # # Check required bin
idm_exit 1 "You need to clean your stuffs" # lib_require_bin tar || idm_exit 1
# lib_require_bin gpg2 || idm_exit 1
# Full sync both repo # export GPG=${GPG2:-$GPG}
idm_tomb_sync $id #
# #GPG_KEY="$(yadm config yadm.gpg-recipient || true )"
# Encrypt data # #GPG_KEY="${GPG_DEFAULT_ID-}"
idm_tomb__encrypt_dir $git_dir $tomb_enc || \ #
idm_exit 1 "Could not create tomb" # # Check pgp key and arguments
# if lib_gpg_is_valid_key $key; then
idm_log NOTICE "Tomb has been created: $tomb_enc" #
} # shift 3
# local ok=0 ko=0
# recipients=${@:-${GPG_DEFAULT_ID-}}
# gpg_opts="-e -r $recipients"
#
# # Determine if we are looking for key or password
## GPG functions # for r in $recipients; do
############################## # lib_gpg_is_valid_recipients $r &>/dev/null \
# && ok=$(( $ok + 1 ))\
# || ko=$(( $ko + 1 ))
#
idm_tomb__decrypt_dir () # if [[ "$ok" -ne 0 && "$ko" -ne 0 ]]; then
{ # idm_exit 1 ERR "One of the recipients is not known: $r in '$recipients'"
local src=$1 # fi
local dst=${2-} # done
local key=${3-} #
local gpg_opts="" # # Act according our pattern
local tar_opts= # if [[ "$ok" -eq 0 && "$ko" -ne 0 ]]; then
# pass="$@"
set -x # recipients=
# gpg_opts="-c"
# Check required bin # lib_log NOTICE "Secret will be encrypted with pass '$pass'"
idm_require_bin tar || idm_exit 1 # else
idm_require_bin gpg2 || idm_exit 1 # lib_log NOTICE "Secret will be encrypted with key '$key' ${recipients:+ to '$recipients'}"
export GPG=${GPG2:-$GPG} # fi
#
tar_opts=" -C ${dst%/*} -zx " # else
if [ ! -z "$key" ]; then # if [ "$key" == "_ASK" ]; then
gpg_opts+="--batch -d" # pass=_ASK
else # key=
gpg_opts+="-d" # gpg_opts="--no-default-recipient -e"
fi # lib_log NOTICE "User will be prompted for known recipients"
# elif [ -z "$key" -o "$key" == "_PASS" ]; then
#set -x # pass=
$GPG $gpg_opts $src | $TAR $tar_opts || \ # key=
idm_exit 1 ERR "Could not decrypt file: $src into $dst" # gpg_opts="-c"
# lib_log NOTICE "User will be prompted for password (symetric)"
} # else
# # Not available yet, see stdin for password input
# # To fix: passwords in clear :/ use stdout3
# pass="$key"
idm_tomb__encrypt_dir () # key=
{ # gpg_opts="-c --passphrase $pass --batch "
local src=$1 # lib_log NOTICE "Secret will be encrypted with pass '***' (symetric)"
local dst=$2 # fi
local key=${3-} # fi
local pass= #
local recipients= # # Encrypt all the stuffs
# $TAR -C "${src%/*}" -cz "${src##*/}" 2>/dev/null | \
# Check required bin # $GPG -a $gpg_opts --yes -o $dst || \
idm_require_bin tar || idm_exit 1 # idm_exit 1 ERR "Could not encrypt directory: $src"
idm_require_bin gpg2 || idm_exit 1 #
export GPG=${GPG2:-$GPG} # # File descritor tests ...
# #exec 3<> /tmp/foo
#GPG_KEY="$(yadm config yadm.gpg-recipient || true )" # #>&3 echo "$pass"
#GPG_KEY="${GPG_DEFAULT_ID-}" # #{ echo "$pass\n" >&3 ; $TAR -C "$(dirname $src)" -cz "$src" 2>/dev/null; } | \
# #exec 3>&- #close fd 3.
# Check pgp key and arguments #
if idm_gpg__is_valid_key $key; then # }
#
shift 3 #
local ok=0 ko=0 #
recipients=${@:-${GPG_DEFAULT_ID-}} #
gpg_opts="-e -r $recipients" #
#
# Determine if we are looking for key or password #
for r in $recipients; do
idm_gpg__is_valid_recipients $r &>/dev/null \
&& ok=$(( $ok + 1 ))\
|| ko=$(( $ko + 1 ))
if [[ "$ok" -ne 0 && "$ko" -ne 0 ]]; then
idm_exit 1 "One of the recipients is not known: $r in '$recipients'"
fi
done
# Act according our pattern
if [[ "$ok" -eq 0 && "$ko" -ne 0 ]]; then
pass="$@"
recipients=
gpg_opts="-c"
idm_log NOTICE "Secret will be encrypted with pass '$pass'"
else
idm_log NOTICE "Secret will be encrypted with key '$key' ${recipients:+ to '$recipients'}"
fi
else
if [ "$key" == "_ASK" ]; then
pass=_ASK
key=
gpg_opts="--no-default-recipient -e"
idm_log NOTICE "User will be prompted for known recipients"
elif [ -z "$key" -o "$key" == "_PASS" ]; then
pass=
key=
gpg_opts="-c"
idm_log NOTICE "User will be prompted for password (symetric)"
else
# Not available yet, see stdin for password input
# To fix: passwords in clear :/ use stdout3
pass="$key"
key=
gpg_opts="-c --passphrase $pass --batch "
idm_log NOTICE "Secret will be encrypted with pass '***' (symetric)"
fi
fi
#set -x
# Encrypt all the stuffs
$TAR -C "${src%/*}" -cz "${src##*/}" 2>/dev/null | \
$GPG -a $gpg_opts --yes -o $dst || \
idm_exit 1 ERR "Could not encrypt directory: $src"
# File descritor tests ...
#exec 3<> /tmp/foo
#>&3 echo "$pass"
#{ echo "$pass\n" >&3 ; $TAR -C "$(dirname $src)" -cz "$src" 2>/dev/null; } | \
#exec 3>&- #close fd 3.
}