From 9dea6bf7ef58d4b60ed7121be79f8e3771df547b Mon Sep 17 00:00:00 2001 From: mrjk Date: Fri, 16 Feb 2018 02:23:03 -0500 Subject: [PATCH] Dev: Completely refactor the code --- bin/.idmgr.swp | Bin 0 -> 16384 bytes bin/idmgr | 889 +++++++++++++++++------------------------ lib/idm_lib_std.sh | 272 +++++++++++++ lib/idmgr_mod_cloud.sh | 58 +++ lib/idmgr_mod_git.sh | 436 +++++++++++--------- lib/idmgr_mod_gpg.sh | 275 +++++++++---- lib/idmgr_mod_id.sh | 51 +-- lib/idmgr_mod_pass.sh | 18 +- lib/idmgr_mod_ps1.sh | 14 +- lib/idmgr_mod_ssh.sh | 50 +-- lib/idmgr_mod_tomb.sh | 722 +++++++++++++++++++++------------ 11 files changed, 1694 insertions(+), 1091 deletions(-) create mode 100644 bin/.idmgr.swp create mode 100644 lib/idm_lib_std.sh create mode 100644 lib/idmgr_mod_cloud.sh diff --git a/bin/.idmgr.swp b/bin/.idmgr.swp new file mode 100644 index 0000000000000000000000000000000000000000..dc5a5f854b3d694138cfe97df3f241ff1486a79f GIT binary patch literal 16384 zcmeI2U5p!76~_nq8E9!lBp#5EPR85rE{g5lMs1^QoMdA=yQ8k{mF*2_lgOI&T(56- zJY#0Y-fXkm7L+2jec?le1}G>zVbwK6MRE zTAVpnAXXq&AXXq&AXXq&AXXq&AXec2OM#$$hxRl~{&-~e*Q3vm-SGLZ=(-j?|HcjP z{~5i1HF|y`Dxg=+htd02qW9Ntcz;{;{6O@1B{Ha&KYAR0#0ta;#0ta;#0ta;#0ta; z#0ta;#0ta;#0ta;{1*zCmZlv8h90a4QzoHu)!jD z7(4{_gTH=C)BXtl0Dc9og71Ns!E>Ms&I1EH0uBNK`@jeHYTD1hPr*7k2KIwD@6oh3 z!0X@|xC*`xo&npS0gi)X;B(-^Pioq`;2rRL@DuO@@Evdkyac`lz64H#6;K5y!3pp% zxDEXM6PorOxC+jIA~+1L@6)tjgAI@a_ki2M`*&;FFM$M8;QhOx2e<})3|;}xfd)7M zj)M$13J!tKgU^Ef;6Cv7otpL*coVzyo&>w-+|wPm%(?zx4{)~8GIRd;2byxGJwE) z7)Rd(F9IG@m%&Xhq68UE!}VI!@r8$y2!9*kU(_r&5LV5W zen1l=DQQ~g+zBd&DG63|P<6+#UDHC%Jv+OmEiE$;B>kFj*gRz|=jCSXcxt(C_XHhu?%S;w4Ft{J&B>`V!# ztE<#y5qJ`65}ruUby{c*aUQ9}Y)DlH>me@6fM)0m^W`GxkGma@He7GrZ=0wLtu}2> znARql^+0wZy+s=`XwpPwF~78gYPmXL%LbjLq(l0|rQVC=wod0CrJyMsRaZ~oTds&p zjyg87(I}oO-I9%*Rhe{yJ(&zFl-96eYT)cLuEIf?ZHoFj7dN6yH2ijsObgz`GAlRQ z+EV_d?4PB4xlDRiz3q5rAYCUKU6w0+a@>HB&<}iNKDuULR_K&tN<)WHs{@Z}du~@+ zf=mZBasdfiQlr1l=KE}C!WRK0FY;~Z7;I?&OXwwY$>AOx^_gf8v&)1&(|4yELWk{> ze$GL(u>De<=JmzfxT+l`GutkyNMi<%&@% zMyYc1)jTKZ4aJ_XFTt@KU(EHg_d0c4SZoTr9ky<-rnNok1PwO!{^Wx*{v1N*IY%eG zDTRlpdZp=ZP~Dc)=s0jJ41_65tajF>*@WFPBW*t~iWi=P;P#&s;5R+^?^$VWaTM9I zM0d;d*Uz&(W<%JU&2c{VX{C0OB~frn}cmnMbb-feh*Qn)iNE+ z@5@Vjv=NCRZ%-h6v4xVS?pk6mZG7~L-Ospc`c2fkcb0V-noIg);T?R(A{ij&`Mz71 zD%ioT>caPh^2yygrZ-h`WQnFr#7-r|ZdoEx5v31_c;S;9&w+<9g8PBc>v9ta+5A9W`NT5>>$+Iw(^g znZ1=0syLLm%mV{>Q(41_kc*m*td|a7^;=OqKGMi%y!$vVh9Uei0zmyK@&66=~ODM({yOY zNuwBL#T|0ZY(v`x+g(NIHrs9Lnx5o!EHvdtSF&YexmqjE7xEe9BkE~1*JUOPMs+eY z3o}_}a^`S)W;Q*0BzzXlb$FbbrKwdBnA72lXmZR;_P| zS`aD=N-O1TK3AJBFH~UpiMeFWfpf5v@at^#OeXXZOB1%wPSbnLi+~Omh#IfF&W59M zdA_oCq*LiKoJ#iKV7r_hdVu4HLH<1W}ZxmMo&@LsN#daTvwNP7G~WO7UivQVvw8o203Uq)27CEu!DUbYp8;=U zkNy_m{k#N|-~sR#y{;BxN-@f9l&D-bIXD-bIXD-bIXD-bIXD-bL2 zKcfKQN<_!B(UHVLDcYU!sX+-FVBV8&r`KFQ0NRoI^!!43z8EILj&3wh*Ie^VCm5Tt zxQq>KxasF}neaBlClhMtpLW_UudaUJ*->YrF?4X;z)IDt^KUwaR?4- z_Q*f3y$g993@qof;d#oA%wA`8GrcBSX}>M%>YQ?i^(dj79cn0N!5IzCN;o68d5p|l zE%(FN3dgIov@%~VWgn|VDi76Ycg(0l+~G`h-B00WY`rL?Hg-55L;Coh*|K}&^D&sl zHFMcmt{63(&hS~" "Enable (and start) id" - printf " %-20s: %s\n" "disable " "Disable id" - printf " %-20s: %s\n" "kill " "Kill id and its associated processes" + printf " %-20s: %s\n" "disable id" "Disable id" + printf " %-20s: %s\n" "kill id" "Kill id and its associated processes" + printf " %-20s: %s\n" "shell " "Show bash code" + printf " %-20s: %s\n" "comp " "Show completion code" echo + echo "Other commands:" + printf " %-20s: %s\n" "id " "List all id" + printf " %-20s: %s\n" "shred [id|user|dev|ask]" "Safely schred data (definitive)" + printf " %-20s: %s\n" "fun " "Show internal function (debug)" + printf " %-20s: %s\n" "hier " "Show cli function (debug)" - for i in ${IDM_MOD_ORDER//:/ } ; do - local val="idm_${i}_help" - echo -n "$i: " - ${val} 2>/dev/null || \ - { - true - echo "No help" - } - echo "" - done + idm_core_exec_mod $id __help "\n%s" ${IDM_MOD_ORDER//:/ } - echo "License:" + echo + lib_log NOTICE "License:" echo " $IDM_VERSION, $IDM_DATE" echo " $IDM_LICENSE, $IDM_AUTHORS" } +idm_core__ls () +{ + local id=${1} + #set -x + + idm_core_exec_mod $id __ls "\n%s ls" ${IDM_MOD_ORDER//:/ } + +} -## Utils +idm_core__enable () +{ + local id=${1:-${SHELL_ID-}} + local conf + + #set -x + + # Local checks + idm_validate id $id || idm_exit 1 ERR "You must provide an id" + idm_validate id_config $id || idm_exit 1 ERR "Configuration '$id' does not exists" + + # Check if workspace is enabled + #idm_validate is_enabled $id + if [ "${SHELL_ID-}" == "$id" ]; then + #idm_exit 0 INFO "Your workspace is already activated" + lib_log WARN "Your workspace is already activated" + elif [ -n "${SHELL_ID-}" ]; then + idm_exit 0 WARN "Your workspace is already activated with $SHELL_ID" + fi + + # Retrieve environment config + conf="$IDM_DIR_ID/$id.env" + + # Notice user + { + . $conf + idm_core_exec_mod $id __enable "Enabling %s ..." ${IDM_MOD_ORDER//:/ } + } # | lib_log DUMP - + + lib_log NOTICE "Identity '$id' is loaded" + +} + +idm_core__disable () +{ + local id=${1} + #idm_is_enabled $id + idm_validate is_enabled $id + + # Reverse module unloading + IDM_MOD_ORDER="$( lib_reverse_doted_list $IDM_MOD_ORDER )" + idm_core_exec_mod $id __disable "Disabling %s ..." ${IDM_MOD_ORDER//:/ } + + # Inform user + lib_log NOTICE "Id $id is disabled" +} + +idm_core__kill () +{ + local id=${1} + idm_is_enabled $id + + # Reverse module killing + IDM_MOD_ORDER="$( lib_reverse_doted_list $IDM_MOD_ORDER )" + idm_core_exec_mod $id __disable "Killing %s ..." ${IDM_MOD_ORDER//:/ } + + # Inform user + lib_log NOTICE "Id $id is safely killed" + +} + + +idm_core__shell () +{ + IDM_SRC_WORDS=$( $IDM_DIR_ROOT/bin/idmgr sourced_words ) + + echo "export IDM_BIN=${IDM_BIN:-$IDM_DIR_ROOT/bin/idmgr}" + echo "export IDM_DIR_ROOT='$IDM_DIR_ROOT'" + echo "IDM_SRC_WORDS='$IDM_SRC_WORDS'" + + tail -n +2 $IDM_DIR_ROOT/shell/bash.sh +} + +idm_core__comp () +{ + cat $IDM_DIR_ROOT/comp/pass.sh + cat $IDM_DIR_ROOT/comp/yadm.sh + cat $IDM_DIR_ROOT/comp/ssh.sh + cat $IDM_DIR_ROOT/comp/gpg.sh + cat $IDM_DIR_ROOT/comp/idmgr.sh +} + + +## Extended functions ########################################## -idm_log () -{ - set +x +idm_core__fun () +{ + grep --colour=auto -IRE \ + '^[a-z0-9_]* \(\)' $IDM_DIR_ROOT/{bin,lib} \ + | sed "s@$IDM_DIR_ROOT/@@" \ + | awk -F: '{ print $2 ":" $1 }' \ + | column -t -s : \ + | LC_ALL=C sort # | lib_log DUMP - - local level=$1 - shift || true - local msg="$@" +} - # Take from stdin if no message ... - [[ "$msg" = - ]] && msg=$( cat < /dev/stdin ) +idm_core__hier () +{ + idm_core__fun \ + | grep __ \ + | sed -e 's/__/ /' -e 's/()//' +} - 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 +idm_core__sourced_words() +{ + local id=${1-} + local words= + + # When we are asking to output source words + words="enable disable kill shell quit q $(idm_get all_id | xargs)" + + echo ":${words// /:}:" + +} + + +## Core internal libs +########################################## + +idm_core_exec_mod () +{ + local id=$1 + local action=$2 + local sep=$3 + shift 3 + local mods=${@-} + + for i in $mods ; do + local val="idm_${i}${action}" + + if [ "$( type -t $val )" = function ]; then + #lib_log INFO "Loading module $i ..." + [ "$sep" == "_" ] || lib_log NOTICE "$(printf "$sep" $i )" + ${val} $id || \ + { + # DO NOT DISABLE THIS BLOCK, that force plugin to load in anyway + true + lib_log WARN "Module $i failed in some way ... ($action)" + } + else + echo "" + lib_log INFO "Skip module $i" + fi + done +} + +idm_mod_files () +{ + #p=$IDM_DIR_ROOT/lib ${PATH//:/ } + p=$IDM_DIR_LIB + find $p -name 'idmgr_mod_*.sh' | xargs +} + +idm_core_mods() +{ + local id=${1-} + idm_mod_list +} + + +idm_core_load_lib () +{ + local lib_name=${1} + local lib_args=${@-} + local env_var=IDM_LIB_${lib_name^^} + + #lib_log DEBUG "$env_var=${!env_var}" + [ -z "${!env_var-}" ] || return 0 + + cmd="$(command -v $lib_name || true )" + + if [ -x "${cmd:-_}" ]; then + + . "$cmd" $lib_args + declare -g $env_var=$cmd + lib_log INFO "Loaded lib: $env_var=${!env_var}" + #set -x - if [[ -n "$level" ]]; then - printf "$color%6s$reset: %s\n" "$level" "$msg" >&2 else - echo "Error while log output msg: $message" + idm_exit 1 "Could not find 'safe' executable in \$PATH (missing module dependency)" 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="idm_log_wrap \$FUNCNAME " +idm_mod_list () +{ + local mods= + if [ -z "${@-}" ] ; then + mods=$( idm_mod_order $(idm_mod_files) ) + else + mods=$( idm_mod_order ${@} ) + fi + + echo ":${mods// /:}:" +} + + +# Takes a list of files to scan for deps +idm_mod_order () +{ + export IDM_MOD_FILES="$( xargs <<<$@ )" + + # Generate dependency order + #result=$( + for f in $IDM_MOD_FILES; do + mod_name=${f##*mod_} + mod_name=${mod_name%\.sh} + + # A bit hackish ... + IDM_MOD_DEPS=$( grep '^IDM_MOD_DEPS=' $f ) + IDM_MOD_DEPS=${IDM_MOD_DEPS##*=} + IDM_MOD_DEPS=${IDM_MOD_DEPS//[^a-z0-9 ]} + IDM_MOD_DEPS="$( tr ' ' '\n' <<<${IDM_MOD_DEPS} )" + + # Output + echo -e "$( xargs -n1 -I{} echo {} "$mod_name" <<<"$IDM_MOD_DEPS" )" + done | tsort | grep -v 'core' | xargs + #) + + #lib_log DEBUG "Dependencies order: $result" + #echo $result +} + + +## Internal/Debug idm_exit () { @@ -180,14 +346,13 @@ idm_exit () msg=${2:-} fi - if [[ "$rc" -ne 0 ]]; then - #idm_trace || true - idm_log $lvl "$msg (rc=$rc)" + #lib_trace || true + lib_log $lvl "$msg (rc=$rc)" #[ -z "$dump" ] || \ - # idm_log DUMP "$dump" + # lib_log DUMP "$dump" else - idm_log $lvl "$msg" + lib_log $lvl "$msg" fi # Remove trap @@ -197,79 +362,113 @@ idm_exit () exit $rc } -idm_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 - #idm_log DEBUG "Trace $i: $trace" - #traces="${traces}${trace}\n" - echo "$trace" - fi - done | tac | column -t - [ -z "$msg" ] || echo "Trace ctx: $msg" - ) | >&2 idm_log DUMP - -} idm_exit_trap () { set +x rc=$? if [[ $rc -ne 0 ]]; then - idm_log ERR "The script exited with exit code: $rc" - idm_trace || true + lib_log ERR "The script exited with exit code: $rc" + lib_trace || true #else - # idm_log WARN "The script exit has been trapped !" - # idm_trace || true + # lib_log WARN "The script exit has been trapped !" + # lib_trace || true fi exit $rc } -idm_require_bin () { - local bin=$1 - shift 1 || true - local opts=${@-} +## Data, tests - if command -v "$bin" &> /dev/null; then - declare -g ${bin^^}="$bin $opts" - return 0 - else - idm_log ERR "Missing '$bin'" - return 1 - fi -} - - -idm__load_lib () +# Should be replaced by idm_validate ? +# Is a wrapper for enduser !!! +idm_is_enabled () { - local lib_name=${1} - local lib_args=${@-} - local env_var=IDM_LIB_${lib_name^^} - - #idm_log DEBUG "$env_var=${!env_var}" - [ -z "${!env_var-}" ] || return 0 - - cmd="$(command -v $lib_name || true )" - - if [ -x "${cmd:-_}" ]; then - - . "$cmd" $lib_args - declare -g $env_var=$cmd - idm_log INFO "Loaded lib: $env_var=${!env_var}" - #set -x - - else - idm_exit 1 "Could not find 'safe' executable in \$PATH (missing module dependency)" - fi + local id=${1} + idm_validate is_enabled $id + { + lib_log WARN "You need to activate an id first" + return 1 + } } +idm_get () +{ + local item=$1 + local value=${2-} + + case $item in + all_id) + for id in $( find $IDM_DIR_ID -type f -name '*.env' 2>/dev/null ); do + id=${id%%\.env} + echo "${id##*/}" + done + ;; + + all_id_files) + ls $IDM_DIR_ID/*.env || true + ;; + + id_config) + if [ -f "$IDM_DIR_ID/$value.env" ]; then + echo "id=$value" + cat $IDM_DIR_ID/$value.env + else + return 1 + fi + ;; + + *) + lib_log ERR "Cannot get item '$item'" + ;; + esac +} + +idm_validate () +{ + local type=$1 + local value=${2-} + + case $type in + id_filter|id) + [ "$value" != '_' ] && \ + [[ "$value" =~ ^[a-zA-Z0-9_-]+$ ]] && return $? + ;; + id_config) + if [[ -f "$IDM_DIR_ID/$value.env" ]]; then + return 0 + fi + ;; + is_enabled) + if [[ -z "${value-}" && "${value-}" != '_' ]]; then + if [ -z "${SHELL_ID-}" ] ; then + return 1 + else + return 0 + fi + else + if [ "${value-}" == "${SHELL_ID-}" ]; then + return 0 + else + return 1 + fi + fi + ;; + is_disabled) + [ -z "${SHELL_ID-}" ] && return $? + ;; + + *) + lib_log ERR "Cannot validate type '$type'" + ;; + esac + + return 1 +} + + +## User interface +########################################## + # This function display a user skippable timeout. idm_cli_timeout () { @@ -282,10 +481,10 @@ idm_cli_timeout () [ "$default_rc" -ge 0 ] || default_rc=1 if [ "$default_rc" -eq 0 ]; then human_word="abort" - go_word=QUIT + go_word=Q elif [ "$default_rc" -ne 0 ]; then human_word="continue" - go_word=GO + go_word=Y fi # Notifying user @@ -317,369 +516,12 @@ idm_cli_timeout () # We loop back idm_cli_timeout $default_rc $remaining - -} - - -idm_get () -{ - local item=$1 - local value=${2-} - - case $item in - all_id) - for id in $IDM_DIR_ID/*.env; do - id=${id%%\.env} - echo "${id##*/}" - done - ;; - - all_id_files) - ls $IDM_DIR_ID/*.env || true - ;; - - id_config) - if [ -f "$IDM_DIR_ID/$value.env" ]; then - echo "id=$value" - cat $IDM_DIR_ID/$value.env - else - return 1 - fi - ;; - - *) - idm_log ERR "Cannot get item '$item'" - ;; - esac -} - -idm_validate () -{ - local type=$1 - local value=${2-} - - case $type in - id) - [ "$value" != '_' ] && \ - [[ "$value" =~ ^[a-zA-Z0-9_-]+$ ]] && return $? - ;; - id_config) - if [[ -f "$IDM_DIR_ID/$value.env" ]]; then - return 0 - fi - ;; - is_enabled) - [ ! -z "${SHELL_ID}" ] && return $? - ;; - is_disabled) - [ -z "${SHELL_ID}" ] && return $? - ;; - - *) - idm_log ERR "Cannot validate type '$type'" - ;; - esac - - return 1 -} - -# Should be replaced by idm_validate ? -idm_is_enabled () -{ - local id=${1} - idm_validate id $id || \ - idm_exit 1 ERR "You need to activate an id first" - -} - - -idm_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" -} - - -idm_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 - -} - -## IDM Internal -########################################## - - -# Takes a list of files to scan for deps -idm_mod__order () -{ - export IDM_MOD_FILES="$( xargs <<<$@ )" - - # Generate dependency order - #result=$( - for f in $IDM_MOD_FILES; do - mod_name=${f##*mod_} - mod_name=${mod_name%\.sh} - - # A bit hackish ... - IDM_MOD_DEPS=$( grep '^IDM_MOD_DEPS=' $f ) - IDM_MOD_DEPS=${IDM_MOD_DEPS##*=} - IDM_MOD_DEPS=${IDM_MOD_DEPS//[^a-z0-9 ]} - IDM_MOD_DEPS="$( tr ' ' '\n' <<<${IDM_MOD_DEPS} )" - - # Output - echo -e "$( xargs -n1 -I{} echo {} "$mod_name" <<<"$IDM_MOD_DEPS" )" - done | tsort | grep -v 'core' | xargs - #) - - #idm_log DEBUG "Dependencies order: $result" - #echo $result - -} - -idm_mod_files () -{ - #p=$IDM_DIR_ROOT/lib ${PATH//:/ } - p=$IDM_DIR_LIB - find $p -name 'idmgr_mod_*.sh' | xargs -} - -idm_mod_list () -{ - local mods= - - if [ -z "${@-}" ] ; then - mods=$( idm_mod__order $(idm_mod_files) ) - else - mods=$( idm_mod__order ${@} ) - fi - - echo ":${mods// /:}:" -} - - -## Required functions -########################################## -idm_core_ls () -{ - local id=${1} - - for i in ${IDM_MOD_ORDER//:/ } ; do - local val="idm_${i}_ls" - idm_log NOTICE "List $i" - - ${val} $id || \ - { - true - idm_log INFO "No listing function for $i" - } - echo "" - done -} - - -idm_core_enable () -{ - local id=${1:-${SHELL_ID-}} - local conf - - # Local checks - idm_validate id $id || idm_exit 1 ERR "You must provide an id" - idm_validate id_config $id || idm_exit 1 ERR "Configuration '$id' does not exists" - - # Check if workspace is enabled - if [ "${SHELL_ID-}" == "$id" ]; then - idm_exit 0 INFO "Your workspace is already activated" - elif [ -n "${SHELL_ID-}" ]; then - idm_exit 0 WARN "Your workspace is already activated with $SHELL_ID" - fi - - # Retrieve environment config - conf="$IDM_DIR_ID/$id.env" - - # Notice user - { - . $conf - - for i in ${IDM_MOD_ORDER//:/ } ; do - local val="idm_${i}_enable" - idm_log INFO "Loading $i ..." - - ${val} $id || \ - { - true - idm_log INFO "No enable function for $i" - } - echo "" - done - - } | idm_log CODE - - - idm_log NOTICE "Identity '$id' is loaded" - -} - -idm_core_disable () -{ - local id=${1} - idm_is_enabled $id - - # Reverse module unloading - IDM_MOD_ORDER="$( idm_reverse_doted_list $IDM_MOD_ORDER )" - - # Loop over disable functions - ( - for i in ${IDM_MOD_ORDER//:/ } ; do - local val="idm_${i}_disable" - #idm_log INFO "Disable $i ..." - - ${val} $id 2>/dev/null || \ - { - true - idm_log INFO "No disable function for $i" - } - echo "" - done - ) | idm_log CODE - - - # Inform user - idm_log NOTICE "Id $id is disabled" -} - -idm_core_kill () -{ - local id=${1} - idm_is_enabled $id - - # Reverse module killing - IDM_MOD_ORDER="$( idm_reverse_doted_list $IDM_MOD_ORDER )" - - # Kill all modules - ( - for i in ${IDM_MOD_ORDER//:/ } ; do - local val="idm_${i}_kill" - #idm_log INFO "Disable $i ..." - - ${val} $id 2>/dev/null || \ - { - true - idm_log INFO "No kill function for $i" - } - echo "" - done - ) | idm_log CODE - - - # Inform user - idm_log NOTICE "Id $id is safely killed" - -} - - -## Extended functions -########################################## - -idm_core_mods() -{ - local id=${1-} - idm_mod_list -} - -idm_core_sourced_words() -{ - local id=${1-} - local words= - - # When we are asking to output source words - words="enable disable kill shell quit q $(idm_get all_id | xargs)" - - echo ":${words// /:}:" - -} - -idm_core_shell () -{ - IDM_SRC_WORDS=$( $IDM_DIR_ROOT/bin/idmgr sourced_words ) - - echo "IDM_DIR_ROOT='$IDM_DIR_ROOT'" - echo "IDM_SRC_WORDS='$IDM_SRC_WORDS'" - echo "IDM_BIN=${IDM_BIN:-$IDM_DIR_ROOT/bin/idmgr}" - - tail -n +2 $IDM_DIR_ROOT/shell/bash.sh -} - -idm_core_completion () -{ - cat $IDM_DIR_ROOT/comp/pass.sh - cat $IDM_DIR_ROOT/comp/yadm.sh - cat $IDM_DIR_ROOT/comp/ssh.sh - cat $IDM_DIR_ROOT/comp/gpg.sh - cat $IDM_DIR_ROOT/comp/idmgr.sh } ## Entry points ########################################## - - -trap "idm_exit_trap" INT TERM EXIT - - idm_menu_main () { #set -x @@ -688,9 +530,20 @@ idm_menu_main () local action= local id= local opt= - local shell_id=${SHELL_ID-:_} + local shell_id=${SHELL_ID:-_} + + # Load external libs + #for lib in $( find $IDM_DIR_LIB -name 'idm_lib_*.sh'); do + while read -r lib; do + #. $lib || lib_log WARN "Error while loading lib $lib :/" + . ${lib:-/dev/null} || echo " WARN: Error while loading lib: ${lib:-NONE}" + done <<< "$( find $IDM_DIR_LIB -name 'idm_lib_*.sh')" + + + trap "idm_exit_trap" INT TERM EXIT idm_init + #set -x # Three way parsing if [ "$#" -eq 0 ]; then @@ -761,8 +614,13 @@ idm_menu_main () esac # Dispatch - #idm_log DEBUG "menu=$menu action=${action:-_} id=$id opt=$opt" - if [ "$( type -t idm_${menu}_${action:-_} )" = function ]; then + #lib_log DEBUG "menu=$menu action=${action:-_} id=$id opt=$opt" + #set -x + if [ "$( type -t idm_${menu}__${action:-_} )" = function ]; then + idm_${menu}__${action:-_} $id $opt + return $? + elif [ "$( type -t idm_${menu}_${action:-_} )" = function ]; then + lib_log WARN "Debug mode enabled" idm_${menu}_${action:-_} $id $opt return $? elif [ "$( type -t idm_${menu} )" = function ]; then @@ -771,22 +629,29 @@ idm_menu_main () fi idm_exit 1 "Command not matched: menu=$menu action=$action id=$id opt=$opt" - - } - ## Main ########################################## - idm_menu_main $@ + + + + + + + + + + + # OLD PIEECES OF CODE diff --git a/lib/idm_lib_std.sh b/lib/idm_lib_std.sh new file mode 100644 index 0000000..bc0214f --- /dev/null +++ b/lib/idm_lib_std.sh @@ -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" + + diff --git a/lib/idmgr_mod_cloud.sh b/lib/idmgr_mod_cloud.sh new file mode 100644 index 0000000..a7927a6 --- /dev/null +++ b/lib/idmgr_mod_cloud.sh @@ -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 ${@-}; } diff --git a/lib/idmgr_mod_git.sh b/lib/idmgr_mod_git.sh index 1483759..a266e9d 100644 --- a/lib/idmgr_mod_git.sh +++ b/lib/idmgr_mod_git.sh @@ -2,20 +2,234 @@ 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 </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 < /dev/null 2>&1 -} - -idm_git__has_commits () -{ - if idm_git__is_repo $id; then - find "$git_dir" -type f &>/dev/null && return 0 - fi - - return 1 -} - -idm_git__is_all_commited () -{ - [ "$( _git 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 - + local git_dir=$1 + local git_work_tree=$2 - 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 + [ -d "$git_dir" ] && lib_git_bin $git_dir $git_work_tree rev-parse > /dev/null 2>&1 ; return $? } -idm_tomb__gen_git_config () +lib_git_has_commits () { - ( - cat </dev/null || return 1 } - - -idm_git_scan () +lib_git_is_all_commited () { - 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 + local git_dir=$1 + local git_work_tree=$2 + [ "$( lib_git_bin $git_dir $git_work_tree status -s | wc -l)" -eq 0 ] } - - - - diff --git a/lib/idmgr_mod_gpg.sh b/lib/idmgr_mod_gpg.sh index 0681d23..8cefeba 100644 --- a/lib/idmgr_mod_gpg.sh +++ b/lib/idmgr_mod_gpg.sh @@ -3,7 +3,7 @@ IDM_MOD_DEPS="id" -idm_gpg_help () +idm_gpg__help () { echo "Not implemented yet" } @@ -11,10 +11,10 @@ idm_gpg_help () ## Required functions ########################################## -idm_gpg_enable () +idm_gpg__enable () { local id=${1} - idm_is_enabled $id + idm_validate id_config $id # Source environment if [ -f "${XDG_RUNTIME_DIR}/pgp-agent/${id}/env" ]; then @@ -26,7 +26,7 @@ idm_gpg_enable () # Check if socket is present if [ ! -S "${GPG_AGENT_INFO-}" ]; then rm -f "${XDG_RUNTIME_DIR}/pgp-agent/${id}/env" - idm_gpg__start $id + idm_gpg_start $id fi # Show config to source @@ -39,40 +39,89 @@ idm_gpg_enable () } -idm_gpg_disable () +idm_gpg__disable () { local id=${1} - idm_is_enabled $id + idm_validate id_config $id echo "unset GPG_AGENT_INFO GNUPGHOME GPG_TTY" } -idm_gpg_kill () +idm_gpg__kill () { local id=${1} idm_is_enabled $id 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 #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} 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 ########################################## -idm_gpg__start () +idm_gpg_start () { local id=${1} local gpghome=~/.config/gpg/$id @@ -98,15 +147,12 @@ idm_gpg__start () echo "export GPG_DEFAULT_ID=${GIT_AUTHOR_EMAIL:-$id}" >> "$runtime/env" # Start agent - idm_log INFO "Start gpg-agent ..." - gpg-agent --daemon --extra-socket "$runtime/socket" + lib_log INFO "Start gpg-agent ..." + gpg-agent --daemon --extra-socket "$runtime/socket" || true } -## Extended functions -########################################## - -idm_gpg__cli_helper () +idm_gpg_cli_helper () { local id=${1} local type=${2:-sub} @@ -119,65 +165,34 @@ idm_gpg__cli_helper () name=${GIT_AUTHOR_NAME} fi - idm_log NOTICE "Please follow this recommendations:" + lib_log NOTICE "Please follow this recommendations:" if [ "$type" == "sub" ]; then - idm_log $lvl "You may have to enter your principal key password." - idm_log $lvl "Type: 6 - RSA (encrypt only)" + lib_log $lvl "You may have to enter your principal key password." + lib_log $lvl "Type: 6 - RSA (encrypt only)" elif [ "$type" == "main" ]; then - idm_log $lvl "Type: 4 - RSA (sign only)" + lib_log $lvl "Type: 4 - RSA (sign only)" fi # Common - idm_log $lvl "Size: 4096" - idm_log $lvl "Type: 2y" + lib_log $lvl "Size: 4096" + lib_log $lvl "Type: 2y" if [ "$type" == "main" ]; then - idm_log $lvl "Name: ${name} (must be 5 char min!)" - idm_log $lvl "Email: ${GIT_AUTHOR_EMAIL}" - idm_log $lvl "Comment: " - idm_log $lvl "Passphrase: Very strong" + lib_log $lvl "Name: ${name} (must be 5 char min!)" + lib_log $lvl "Email: ${GIT_AUTHOR_EMAIL}" + lib_log $lvl "Comment: " + lib_log $lvl "Passphrase: Very strong" elif [ "$type" == "main" ]; then - idm_log $lvl "Type: quit and save changes" + lib_log $lvl "Type: quit and save changes" fi - idm_log NOTICE "PGP key generation interface" + lib_log NOTICE "PGP key generation interface" } -idm_gpg_new () -{ - 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 () +idm_gpg_match_one_pubkey () { key=${1} @@ -185,40 +200,26 @@ idm_gpg__get_def_key () gpg2 --list-keys | grep "uid"| grep "${key:-}" \ | 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 } if [ "$( wc -l <<<"$key")" -ne 1 ]; then - idm_log WARN "Too much keys for matching '$1'" - idm_log DUMP - <<<"$key" + lib_log WARN "Too much keys for matching '$1'" + lib_log DUMP - <<<"$key" return 1 fi 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 # $@ 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 recipients=($@) @@ -226,13 +227,13 @@ idm_gpg__is_valid_recipients() { for gpg_id in "${recipients[@]}"; do gpg --list-keys "$gpg_id" &> /dev/null 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 fi done } -idm_gpg__is_valid_key() { +lib_gpg_is_valid_key() { typeset -a recipients recipients=($@) # At least one private key must be present @@ -244,3 +245,109 @@ idm_gpg__is_valid_key() { done 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. + +} + diff --git a/lib/idmgr_mod_id.sh b/lib/idmgr_mod_id.sh index 5780b5c..fe73653 100644 --- a/lib/idmgr_mod_id.sh +++ b/lib/idmgr_mod_id.sh @@ -6,7 +6,7 @@ IDM_MOD_DEPS="" ########################################## -idm_id_help () +idm_id__help () { echo "Identity management:" printf " %-20s: %s\n" "id ls" "List all disks of all policies" @@ -20,19 +20,19 @@ idm_id_help () idm_id () { - idm_id_ls ${@-} + idm_id__ls ${@-} } -idm_id_disable() +idm_id__disable() { # 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 conf="$IDM_DIR_ID/$id.env" @@ -65,7 +65,7 @@ idm_id_enable() # echo "export XDG_OPT_HOME=$XDG_OPT_HOME" } -idm_id_new () +idm_id__new () { local id=${2:-$1} @@ -81,12 +81,12 @@ idm_id_new () $EDITOR "$conf" # Notice user - idm_log NOTICE "Id '$id' has been created:" - cat $conf | idm_log CODE - + lib_log NOTICE "Id '$id' has been created:" + cat $conf | lib_log CODE - } -idm_id_show () +idm_id__show () { local id=${1} local conf @@ -98,15 +98,16 @@ idm_id_show () conf="$IDM_DIR_ID/$id.env" # Notice user - idm_log INFO "Id '$id' configuration:" - idm_get id_config $id | idm_log CODE - -# cat $conf | idm_log CODE + lib_log INFO "Id '$id' configuration:" + idm_get id_config $id | lib_log CODE - +# cat $conf | lib_log CODE } -idm_id_ls () +idm_id__ls () { local active + #set -x for id in $(idm_get all_id); do @@ -125,11 +126,11 @@ idm_id_ls () eval "$(idm_get id_config $id)" 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 md5 conf @@ -144,14 +145,14 @@ idm_id_edit () # Notice user if [[ "$md5" == "$(md5sum $conf)" ]] ;then - idm_log INFO "Id '$id' has not been updated:" + lib_log INFO "Id '$id' has not been updated:" else - idm_log NOTICE "Id '$id' has been updated:" + lib_log NOTICE "Id '$id' has been updated:" fi - cat $conf | idm_log CODE - + cat $conf | lib_log CODE - } -idm_id_get () +idm_id__get () { local id=${1} @@ -168,14 +169,14 @@ idm_id_get () } -idm_id_dump () +idm_id__dump () { for id in $(idm_get all_id); do - #idm_log NOTICE "Identity $id" + #lib_log NOTICE "Identity $id" { idm_get id_config $id echo " " - } | idm_log CODE - + } | lib_log CODE - done } @@ -192,7 +193,7 @@ idm_id_template () echo "tz=$tz" } -idm_id_rm () +idm_id__rm () { local id=${1} @@ -206,6 +207,6 @@ idm_id_rm () rm "$IDM_DIR_ID/$id.env" || \ idm_exit 1 ERR "File '$IDM_DIR_ID/$id.env' could not be deleted" 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 } diff --git a/lib/idmgr_mod_pass.sh b/lib/idmgr_mod_pass.sh index e309624..8260b3d 100644 --- a/lib/idmgr_mod_pass.sh +++ b/lib/idmgr_mod_pass.sh @@ -11,7 +11,7 @@ idm_pass () #set -x if [ "$#" -eq 1 ]; then local id=$1 - idm_pass_ls $id + idm_pass__ls $id return 0 else local action=$1 @@ -28,15 +28,15 @@ idm_pass () } -idm_pass_ls () +idm_pass__ls () { 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" printf " %-20s: %s\n" "pass ls" "List passwords" @@ -49,19 +49,19 @@ idm_pass_help () } -idm_pass_enable () +idm_pass__enable () { local id=${1} - idm_is_enabled $id + ! idm_validate id_config $id echo "export PASSWORD_STORE_DIR=~/.config/pass/${id}" } -idm_pass_disable () +idm_pass__disable () { local id=${1} - idm_is_enabled $id + idm_validate id_config $id echo "unset PASSWORD_STORE_DIR" } diff --git a/lib/idmgr_mod_ps1.sh b/lib/idmgr_mod_ps1.sh index 04c8fe9..0f429b3 100644 --- a/lib/idmgr_mod_ps1.sh +++ b/lib/idmgr_mod_ps1.sh @@ -15,7 +15,7 @@ idm_ps1 () idm_ps1_ls } -idm_ps1_ls () +idm_ps1__ls () { local id=${1} @@ -23,21 +23,21 @@ idm_ps1_ls () #echo "PS1=${SHELL_PS1:-${PS1-}}" if grep -q "($id)" <<<"${SHELL_PS1:-${PS1-}}" ; then - echo "enabled" + echo " enabled" else - echo "disabled" + echo " disabled" fi } -idm_ps1_help () +idm_ps1__help () { echo "Shell Prompt" printf " %-20s: %s\n" "ps1 enable" "Enable prompt" printf " %-20s: %s\n" "ps1 disable" "Disable prompt" } -idm_ps1_enable () +idm_ps1__enable () { local id=${1} 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}\"" return } -idm_ps1_kill () { idm_ps1_disable ${@-}; } +idm_ps1__kill () { idm_ps1__disable ${@-}; } diff --git a/lib/idmgr_mod_ssh.sh b/lib/idmgr_mod_ssh.sh index b2e8088..6403389 100644 --- a/lib/idmgr_mod_ssh.sh +++ b/lib/idmgr_mod_ssh.sh @@ -8,7 +8,7 @@ IDM_MOD_DEPS="id gpg" ## SSH functions ########################################## -idm_ssh_help () +idm_ssh__help () { echo "Secure Shell" # printf " %-20s: %s\n" "info" "Info submenu" @@ -29,7 +29,7 @@ idm_ssh () # Argument maangement if [ "$#" -eq 1 ]; then local id=$1 - idm_ssh_ls $id + idm_ssh__ls $id return 0 else local action=$1 @@ -50,30 +50,32 @@ idm_ssh () ## Required functions ########################################## -idm_ssh_ls () +idm_ssh__ls () { local id=$1 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 - idm_is_enabled $id + #idm_is_enabled $id + idm_validate id_config $id # Return portion of code to clean echo "unset SSH_AUTH_SOCK SSH_AGENT_PID" } -idm_ssh_enable () +idm_ssh__enable () { local id=$1 - idm_is_enabled $id + idm_validate id_config $id # Source environment if [ -f "${XDG_RUNTIME_DIR}/ssh-agent/${id}/env" ] ; then @@ -85,7 +87,7 @@ idm_ssh_enable () # Check status if ! idm_ssh__is_agent_working $id ${SSH_AUTH_SOCK:-_} ${SSH_AGENT_PID:-0}; 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 fi fi @@ -95,7 +97,7 @@ idm_ssh_enable () } # LOGOUT -idm_ssh_kill () { +idm_ssh__kill () { #set -x @@ -104,7 +106,7 @@ idm_ssh_kill () { idm_is_enabled $id - #idm_log NOTICE "Cleaning ssh-agent ..." + #lib_log NOTICE "Cleaning ssh-agent ..." [ -z "${SSH_AGENT_PID-}" ] && \ [ -f "$run_dir/env" ] && \ @@ -113,7 +115,7 @@ idm_ssh_kill () { # Clean ssh-agent process if kill -0 ${SSH_AGENT_PID-} &>/dev/null; then /usr/bin/ssh-agent -k >/dev/null - idm_log NOTICE "Kill ssh-agent ..." + lib_log NOTICE "Kill ssh-agent ..." fi #eval "$(/usr/bin/ssh-agent -k 2>/dev/null)" @@ -122,7 +124,7 @@ idm_ssh_kill () { rm "${XDG_RUNTIME_DIR}/ssh-agent/${id}/env" # Disable agent - idm_ssh_disable $id + idm_ssh__disable $id 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 echo "$run_dir/env" - idm_log INFO "Start ssh-agent ..." + lib_log INFO "Start ssh-agent ..." else - idm_log WARN "Could not start ssh agent :(" + lib_log WARN "Could not start ssh agent :(" return 1 fi @@ -205,7 +207,7 @@ idm_ssh__agent_clean () { fi 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" ] || \ idm_exit 0 WARN "No keys found" - idm_log INFO "Adding keys:" - xargs -n 1 <<<$key_list | idm_log DUMP - + lib_log INFO "Adding keys:" + xargs -n 1 <<<$key_list | lib_log DUMP - echo "" 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 return 0 else - idm_log WARN "ssh-agent is not working as expected" + lib_log WARN "ssh-agent is not working as expected" fi # Is the socket valid ? 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 return 1 fi @@ -283,13 +285,13 @@ idm_ssh__agent_check () 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 }' )" || \ { - 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 return 1 } # 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 for p in $pid; do return @@ -304,7 +306,7 @@ idm_ssh__agent_check () # 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 } diff --git a/lib/idmgr_mod_tomb.sh b/lib/idmgr_mod_tomb.sh index 3c3be0d..5b82fd9 100644 --- a/lib/idmgr_mod_tomb.sh +++ b/lib/idmgr_mod_tomb.sh @@ -14,17 +14,22 @@ IDM_MOD_PREF="core id" # # 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 - idm_vars_git_tomb $id + idm_vars_git_tomb echo "tomb" echo " workflow:" @@ -33,286 +38,501 @@ idm_tomb_help () printf " %-20s: %s\n" "tomb decrypt" "Decrypt the tomb" 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 push |all" "Save the current configuration into the tomb" printf " %-20s: %s\n" "tomb leave" "Remove all traces of your passage" echo " config:" - printf " %-20s: %s\n" "tomb_enc" "$tomb_enc" - printf " %-20s: %s\n" "git_dir" "$git_dir" - printf " %-20s: %s\n" "git_config" "$git_config" + printf " %-20s: %s\n" "git_tomb_enc" "$git_tomb_enc" + printf " %-20s: %s\n" "git_tomb_dir" "$git_tomb_dir" + printf " %-20s: %s\n" "git_tomb_config" "$git_tomb_config" return 0 } -idm_tomb_ls () +idm_tomb__ls () { 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:" - printf " %-20s: %s\n" "opened" "yes" - printf " %-20s: %s\n" "last mod." "yes" - printf " %-20s: %s\n" "git" "$git_dir" - printf " %-20s: %s\n" "last date" "" + printf " %-20s: %s\n" "encrypted tomb" "$t_st${t_m}" + printf " %-20s: %s\n" "encrypted file" "$git_tomb_enc" + printf " %-20s: %s\n" "tomb git status" "$g_st$g_m" + printf " %-20s: %s\n" "tomb git dir" "$git_tomb_dir" - echo " Remotes:" - _git_local remote -v | sed 's/^/ /' + if lib_git_is_repo $git_tomb_dir $git_tomb_work_tree; then + 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 </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. - -} - - - - - - - +# Moved to mod_gpg +# ## GPG functions +# ############################## +# +# +# lib_gpg_decrypt_dir () +# { +# local src=$1 +# local dst=${2-} +# local key=${3-} +# local gpg_opts="" +# local tar_opts= +# +# # 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 ERR "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. +# +# } +# +# +# +# +# +# +#