Compare commits

...

24 Commits
master ... main

Author SHA1 Message Date
fa5e97fbe7 fix: shell restore 2024-08-30 02:51:17 -04:00
527ea74b48 add: probable bugfix from main 2024-03-20 01:58:24 -04:00
67e7e7953b change: default ssh tmout and shell id autorestore 2024-03-20 01:55:47 -04:00
429681c26f fix: gpg bug 2023-06-01 18:16:29 +02:00
0661280db5 add: docs 2023-04-18 17:07:58 -04:00
b70bd9ad17 Add: gitea and gh 2023-04-17 17:05:18 -04:00
0d0e0b9262 fix: mod gpg bg process condition 2023-04-17 17:05:00 -04:00
f74937c683 fix: init script 2023-04-17 14:42:37 -04:00
5214472316 fix: undeclared local variable 2023-04-17 14:41:54 -04:00
7744b3bda9 fix: gpg background process 2023-04-17 14:41:41 -04:00
d5805041f5 add: option to disable last_id 2023-04-17 14:41:24 -04:00
004b471d9d fix: PS1 handling 2023-04-17 14:40:55 -04:00
474725ff87 add: support for PS1_*FIX 2023-04-15 12:30:03 -04:00
1afe28bcde fix: undeclared XDG_RUNTIME_DIR var 2023-04-15 12:29:44 -04:00
acf21c2f86 wip: rework ssh parts 2023-04-04 01:56:26 -04:00
b469e0c425 Fix: Missed ssh keys when target is symlink 2022-05-31 01:30:12 -04:00
40401b8702 Add: Howto documentation about creating ssh key pairs 2021-01-12 18:31:20 -05:00
a4da2efa2e Add: Reenable last ID when shell opens 2021-01-12 18:19:44 -05:00
c2d840d136 Fix: idmgr call when idmgr is not in path 2021-01-12 18:18:41 -05:00
8ebbac4659 Add: alias already broken mod by design 2021-01-04 22:14:41 -05:00
054bfcd080 Add: mod_alias beta 2020-12-10 23:17:49 -05:00
4a716cb4fa Update: Messy commit 2020-12-09 19:40:11 -05:00
ca682c6477 Wip: Works well as I'm commiting with the good user 2020-04-25 00:27:17 +07:00
f722286fda Wip: fix the software ... 2020-04-24 17:36:19 +07:00
20 changed files with 1585 additions and 888 deletions

682
bin/idmgr
View File

@ -26,42 +26,35 @@ IDM_DATE='03/01/18'
IDM_LICENSE='MIT' IDM_LICENSE='MIT'
IDM_SCRIPT_NAME=idmgr IDM_SCRIPT_NAME=idmgr
# Ensure XDG vars
XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-$HOME/.local/run}
mkdir -p "$XDG_RUNTIME_DIR"
# Global app variables # Global app variables
IDM_BIN=${IDM_BIN:-$0} IDM_BIN=${IDM_BIN:-$0}
IDM_DIR_ROOT=${IDM_DIR_ROOT:-$( realpath "$(dirname $0)/../" )} IDM_DIR_ROOT=${IDM_DIR_ROOT:-$( realpath "$(dirname $(realpath $0))/../" )}
IDM_CONFIG_DIR=${IDM_CONFIG_DIR:-${XDG_CONFIG_HOME:-~/.config}/idmgr} IDM_ID_ENV_DIR=${IDM_ID_ENV_DIR:-${XDG_CONFIG_HOME:-~/.config}/idmgr}
IDM_DIR_ID=${IDM_DIR_ID:-$IDM_CONFIG_DIR/id} IDM_DIR_ID=${IDM_DIR_ID:-$IDM_ID_ENV_DIR/id}
IDM_DIR_LIB=${IDM_DIR_LIB:-$IDM_DIR_ROOT/lib} IDM_DIR_LIB=${IDM_DIR_LIB:-$IDM_DIR_ROOT/lib}
IDM_DIR_CACHE=${IDM_DIR_CACHE:-${XDG_CACHE_HOME:-~/.cache}/idmgr} IDM_DIR_CACHE=${IDM_DIR_CACHE:-${XDG_CACHE_HOME:-~/.cache}/idmgr}
mkdir -p $IDM_CONFIG_DIR $IDM_DIR_ID $IDM_DIR_CACHE IDM_SRC_WORDS='enable disable kill shell quit e d k s q'
mkdir -p $IDM_ID_ENV_DIR $IDM_DIR_ID $IDM_DIR_CACHE
# Mod vars ... # Mod vars ...
IDM_DISABLE_AUTO= IDM_DISABLE_AUTO=
IDM_ID_ENV=
# Main initialisation settings
idm_init ()
{
export EDITOR=${EDITOR:-vim}
# Create directories
mkdir -p $IDM_CONFIG_DIR $IDM_DIR_ID
IDM_MOD_FILES=$(idm_mod_files)
IDM_MOD_ORDER=$(idm_mod_list)
export IDM_TIMEOUT_USER=5
# Load modules
for i in $IDM_MOD_FILES ; do
source $i
done
}
## Required functions
## Base CLI commands
########################################## ##########################################
# Required libs:
# idm_core
idm_core__help () idm_core__help ()
{ {
@ -73,10 +66,11 @@ idm_core__help ()
echo " your pgp keys, kerberos and many other related identity item." echo " your pgp keys, kerberos and many other related identity item."
echo "" echo ""
echo "Sourced commands:" echo "Sourced commands:"
printf " %-20s: %s\n" "enable <id>" "Enable (and start) id" printf " %-20s: %s\n" "enable [id]" "Enable (and start) id"
printf " %-20s: %s\n" "disable id" "Disable id" printf " %-20s: %s\n" "disable [id]" "Disable id"
printf " %-20s: %s\n" "kill id" "Kill id and its associated processes" printf " %-20s: %s\n" "kill [id]" "Kill id and its processes"
printf " %-20s: %s\n" "shell " "Show bash code" echo
printf " %-20s: %s\n" "shell" "Show bash code"
printf " %-20s: %s\n" "comp " "Show completion code" printf " %-20s: %s\n" "comp " "Show completion code"
echo echo
echo "Other commands:" echo "Other commands:"
@ -85,7 +79,11 @@ idm_core__help ()
printf " %-20s: %s\n" "fun " "Show internal function (debug)" printf " %-20s: %s\n" "fun " "Show internal function (debug)"
printf " %-20s: %s\n" "hier " "Show cli function (debug)" printf " %-20s: %s\n" "hier " "Show cli function (debug)"
idm_core_exec_mod $id __help "\n%s" ${IDM_MOD_ORDER//:/ } local mods=$(idm_lib_order_get status)
echo
echo "Loaded mods: $mods"
idm_core_exec_mod $id __help "\n%s" $mods
echo echo
lib_log NOTICE "License:" lib_log NOTICE "License:"
@ -97,40 +95,30 @@ idm_core__help ()
idm_core__ls () idm_core__ls ()
{ {
local id=${1} local id=${1}
#set -x idm_core_exec_mod $id __ls "%s ls" $(idm_lib_order_get status)
idm_core_exec_mod $id __ls "%s ls" ${IDM_MOD_ORDER//:/ }
} }
idm_core__enable () idm_core__enable ()
{ {
local id=${1:-${SHELL_ID-}} local id=${1:-${SHELL_ID-}}
local conf
#set -x
# Local checks # Local checks
#lib_id_is_valid_syntax $id || idm_exit 1 ERR "You must provide an id"
lib_id_has_config $id || idm_exit 1 ERR "Configuration '$id' does not exists" lib_id_has_config $id || idm_exit 1 ERR "Configuration '$id' does not exists"
# Check if workspace is enabled # Check if workspace is enabled
#idm_validate is_enabled $id
if [ "${SHELL_ID-}" == "$id" ]; then if [ "${SHELL_ID-}" == "$id" ]; then
#idm_exit 0 INFO "Your workspace is already activated"
lib_log WARN "Your workspace is already activated" lib_log WARN "Your workspace is already activated"
elif [ -n "${SHELL_ID-}" ]; then elif [ -n "${SHELL_ID-}" ]; then
idm_exit 0 WARN "Your workspace is already activated with $SHELL_ID" lib_log WARN "Changing $SHELL_ID workspace to $id"
$IDM_BIN disable "${SHELL_ID-}"
fi fi
# Retrieve environment config
conf="$IDM_DIR_ID/$id.env"
# Notice user # Notice user
{ {
. $conf # Reload user config
idm_core_exec_mod $id __enable "Enabling %s ..." ${IDM_MOD_ORDER//:/ } . "$IDM_ID_ENV"
idm_core_exec_mod $id __enable "Enabling %s ..." $(idm_lib_order_get enable)
} # | lib_log DUMP - } # | lib_log DUMP -
lib_log NOTICE "Identity '$id' is loaded" lib_log NOTICE "Identity '$id' is loaded"
@ -141,37 +129,31 @@ idm_core__disable ()
{ {
local id=${1} local id=${1}
lib_id_is_enabled $id lib_id_is_enabled $id
idm_core_exec_mod $id __disable "Disabling %s ..." $(idm_lib_order_get disable)
# Reverse module unloading lib_log NOTICE "Identity '$id' is unloaded"
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 () idm_core__kill ()
{ {
local id=${1} local id=${1}
lib_id_is_enabled $id lib_id_is_enabled $id
idm_core_exec_mod $id __disable "Killing %s ..." $(idm_lib_order_get disable)
# Reverse module killing lib_log NOTICE "Id $id has been safely killed"
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"
} }
## Shell integration CLI commands
##########################################
idm_core__shell () 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_BIN=${IDM_BIN:-$IDM_DIR_ROOT/bin/idmgr}"
echo "export IDM_DIR_ROOT='$IDM_DIR_ROOT'" echo "export IDM_DIR_ROOT='$IDM_DIR_ROOT'"
#echo "IDM_SRC_WORDS='$IDM_SRC_WORDS $(lib_id_get_all_id | xargs)'"
echo "IDM_SRC_WORDS='$IDM_SRC_WORDS'" echo "IDM_SRC_WORDS='$IDM_SRC_WORDS'"
echo "IDM_DIR_ID='$IDM_DIR_ID'"
tail -n +2 $IDM_DIR_ROOT/shell/bash.sh tail -n +2 $IDM_DIR_ROOT/shell/bash.sh
} }
@ -186,7 +168,7 @@ idm_core__comp ()
} }
## Extended functions ## Debugging CLI commands
########################################## ##########################################
@ -208,22 +190,106 @@ idm_core__hier ()
| sed -e 's/__/ /' -e 's/()//' | sed -e 's/__/ /' -e 's/()//'
} }
idm_core__sourced_words()
## Mod libs
##########################################
# Return a list of mod source files that can be sourced
# Input: none
# Return: linelist
# Example return:
# idmgr_mod_git.sh
# idmgr_mod_ssh.sh
# ...
idm_mod_files ()
{ {
local id=${1-} #p=$IDM_DIR_ROOT/lib ${PATH//:/ }
local words= local p=$IDM_DIR_LIB
find $p -name 'idmgr_mod_*.sh' | xargs
# When we are asking to output source words
words="enable disable kill shell quit q $(lib_id_get_all_id | xargs)"
echo ":${words// /:}:"
} }
# Takes a list of files to scan for deps. This
# will tell idmgr in which order to load its deps
# Input: wordlist of paths
# Return: wordlist
# Usage:
# idm_mod_order mod1 mod2 modN
idm_mod_order ()
{
>&2 echo "DEPRECATED: idm_mod_order"
local mods=$@
export IDM_MOD_FILES="$( xargs <<< $mods)"
# 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
# TOCHECK? echo -e "$( xargs -I{} echo {} "$mod_name" <<<"$IDM_MOD_DEPS" )"
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
}
# Return a list of mods. Rescan mod source if
# no input mods provided.
# Input: [wordlist]
# Return: comalist
# Usage:
# idm_mod_list # Reload mods
# idm_mod_list mod1 mod2 modN
idm_mod_list ()
{
local mods="${@:-$(idm_mod_files)}"
mods=$(idm_mod_order ${mods})
echo ":${mods// /:}:"
}
## Core internal libs ## Core internal libs
########################################## ##########################################
# Required libs:
# idm_mod
# Return the list of required mods to run. High level
# call, can use cache.
idm_core_mods ()
{
local id=${1-}
idm_mod_list
}
# This function is the module execution engine.
# id: The current id to use
# action: The current command to run, ie `enable`
# sep: '_' Or a text to be displayed for the user
# mods: mod[,mod,...] list of mods to be triggered
idm_core_exec_mod () idm_core_exec_mod ()
{ {
local id=$1 local id=$1
@ -237,18 +303,8 @@ idm_core_exec_mod ()
if [ "$( type -t $val )" = function ]; then if [ "$( type -t $val )" = function ]; then
#set -x
# Skip if disabled ... # Skip if disabled ...
[[ ":${IDM_DISABLE_AUTO// /:}" =~ :${i}${action}: ]] && continue [[ ":${IDM_DISABLE_AUTO// /:}" =~ :${i}${action}: ]] && continue
#set +x
#lib_log INFO "Loading module $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)"
# }
export IDM_MOD_EXEC=chain export IDM_MOD_EXEC=chain
local rc=0 local rc=0
@ -270,94 +326,25 @@ idm_core_exec_mod ()
done done
} }
idm_mod_files ()
{
#p=$IDM_DIR_ROOT/lib ${PATH//:/ }
p=$IDM_DIR_LIB
find $p -name 'idmgr_mod_*.sh' | xargs
}
idm_core_mods() ## Application exit teardown
{ ##########################################
local id=${1-}
idm_mod_list
}
# Required libs:
# idm_std
idm_core_load_lib () # Call this function to exit main cli. You can
{ # give some parameters as well. It use
local lib_name=${1} # lib_log to display error messages. Usage examples:
local lib_args=${@-} # idm_exit rc lvl msg
local env_var=IDM_LIB_${lib_name^^} # idm_exit rc msg
# idm_exit
#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
else
idm_exit 1 "Could not find 'safe' executable in \$PATH (missing module dependency)"
fi
}
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 () idm_exit ()
{ {
set +x
local rc=${1:-0} local rc=${1:-0}
local msg lvl local msg lvl
#[ -p /dev/stdin ] \
# && dump="$(</dev/stdin)" \
# || dump=""
# Check exit status # Check exit status
if [ "$#" -eq 3 ]; then if [ "$#" -eq 3 ]; then
@ -377,194 +364,175 @@ idm_exit ()
lib_log $lvl "$msg" lib_log $lvl "$msg"
fi fi
# Remove trap # Remove trap to avoid to be called for normal and exit for good
trap "" INT TERM EXIT trap "" INT TERM EXIT
# Exit for good
exit $rc exit $rc
} }
# Script called when the script quits unexpectedly.
# Pretty useful for debugginf purpose.
idm_exit_trap () { idm_exit_trap () {
rc=$? local rc=$?
set +x set +x
echo "EXIT TRAP" >/dev/null
if [[ $rc -ne 0 ]]; then if [[ $rc -ne 0 ]]; then
lib_log ERR "The script exited with exit code: $rc" lib_log ERR "The script exited with exit code: $rc"
lib_trace || true lib_trace || true
#else #else
# lib_log WARN "The script exit has been trapped !" #lib_log INFO "The script exit has been correctly trapped."
# lib_trace || true #lib_trace || true
fi fi
exit $rc exit $rc
} }
## Data, tests ## Compat
# DEPRECATRED, replaced by lib_id
# Should be replaced by idm_validate ?
# Is a wrapper for enduser !!!
# idm_is_enabled ()
# {
# lib_log DEPRECATED "call: idm_is enabled $@, use lib_id_is_enabled ${1-} instead"
# lib_trace
# local id=${1}
# idm_validate is_enabled $id
# {
# lib_log WARN "You need to activate an id first"
# return 1
# }
# }
# # DEPRECATRED, replaced by lib_id
# idm_get ()
# {
# lib_log DEPRECATED "call: idm_get $@, use lib_id_has_config instead"
# lib_trace
# local item=$1
# local value=${2-}
#
# case $item in
# all_id)
# # idm_get all_id
# # => lib_id_get_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)
# # => lib_id_get_all_file
# ls $IDM_DIR_ID/*.env || true
# ;;
#
# id_config)
# # => lib_id_get_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
# }
# # DEPRECATRED, replaced by lib_id
# idm_validate ()
# {
# #lib_log DEPRECATED "call: idm_validate $@, sed with: lib_id_has_config or equivalent"
# local type=$1
# local value=${2-}
#
# case $type in
# id_filter|id)
# lib_log DEPRECATED "call: idm_validate id_filter $@, sed with: lib_id_is_valid_syntax \$id"
# [ "$value" != '_' ] && \
# [[ "$value" =~ ^[a-zA-Z0-9_-]+$ ]] && return $?
# ;;
# id_config)
# lib_log DEPRECATED "call: idm_validate id_config $@, sed with: lib_id_has_config \$id"
# if [[ -f "$IDM_DIR_ID/$value.env" ]]; then
# return 0
# fi
# ;;
# is_enabled)
# lib_log DEPRECATED "call: idm_validate is_enabled $@, sed with: lib_id_is_enabled \$id"
# 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)
# lib_log DEPRECATED "call: idm_validate is_disabled $@, sed with: ! lib_id_is_enabled \$id"
# [ -z "${SHELL_ID-}" ] && return $?
# ;;
#
# *)
# lib_log ERR "Cannot validate type '$type'"
# ;;
# esac
#
# return 1
# }
## User interface
########################################## ##########################################
# This function display a user skippable timeout. # This function display a user skippable timeout.
idm_cli_timeout () idm_cli_timeout ()
{ {
local default_rc=${1:-1} lib_log WARN "Deprecated use of idm_cli_timeout ..."
local wait_time=${2:-$IDM_TIMEOUT_USER} lib_cli_timeout $@
local start=$(date '+%s')
local human_word go_word
# Humanise ...
[ "$default_rc" -ge 0 ] || default_rc=1
if [ "$default_rc" -eq 0 ]; then
human_word="abort"
go_word=Q
elif [ "$default_rc" -ne 0 ]; then
human_word="continue"
go_word=Y
fi
# Notifying user
local human_date="$(date -d@$wait_time -u '+%Hh%Mm%Ss' | sed 's/00.//g' )"
local human_msg="Type '$go_word' to $human_word ($human_date):"
# Wait user input or timeout ...
local answer=
local rc=0
read -t $wait_time -p " ASK: ${human_msg} " answer || rc=$?
local remaining=$(( $wait_time - ( $(date '+%s') - $start ) ))
# Make a decision
if [[ "$rc" -eq 142 ]]; then
# We timeout, so GO! (142 is the timeout return code)
echo
return $default_rc
elif [[ "$answer" == "$go_word" ]]; then
# User asked to GO!
return 0
elif [[ $remaining -le 0 ]]; then
# Whatever, time passed, so GO!
return $default_rc
elif [[ "$rc" -ne 0 ]]; then
# Hmm, something wrong, we quit with error...
urm_log ERROR "Something went wrong (return code=$rc)"
return 1
fi
# We loop back
idm_cli_timeout $default_rc $remaining
} }
## Mods internal libs
##########################################
# Required libs: None
idm_lib_names ()
{
local type=$1
find "$IDM_DIR_LIB" \
-name "idmgr_${type}_*.sh" \
-printf '%f\n' |
sed -E "s@idmgr_${type}_([^\.]*).*@\\1@" |
xargs
}
idm_lib_order_set ()
{
local id args rec
id=$1
shift 1
args=$@
# Does not allow modifications
! grep -q "^$id," <<< "$IDM_LIB_TABLE" || return
rec="$id,${args// /,}"
IDM_LIB_TABLE=$(
grep -v "^$id," <<< "$IDM_LIB_TABLE";
echo "$rec"
)
}
idm_lib_order_get ()
{
#set +x
local f=${1}
# >&2 echo "fmt: ${IDM_LIB_TABLEFMT%%$f*}"
#>&2 echo -e "\n>order: $f\n>table: $IDM_LIB_TABLE"
local w="ignore ${IDM_LIB_TABLEFMT%%$f*}"
f=$( wc -w <<< "$w" )
sort -t, -k${f} <<< "$IDM_LIB_TABLE" | cut -d, -f1 | xargs
}
# This is the library wrapper. Any loading
# must use this function. Create environment vars.
# Input: [type] [wordlist of mods]
# Output: none
# Usage:
# idm_lib_load # Load all default libs
# idm_lib_load lib # Same
# idm_lib_load mod # Load all mods
# idm_lib_load mod mod1 mod2 # loads specific mods
idm_lib_load ()
{
local type=${1:-lib}
shift 1
local names=${@-}
# Create variables
local var_name
[ -n "$names" ] || names=$(idm_lib_names $type)
var_name="IDM_${type^^}_LOADED"
# Source lib/mods
for name in $names; do
source "$IDM_DIR_LIB/idmgr_${type}_${name}.sh"
if [ "$?" -eq 0 ] ; then
# Add mod/lib to the loaded list
declare -g $var_name="${!var_name-}:$name"
# Load the infile mod order
if [ "$type" == 'mod' ]; then
local p_var="IDM_${type^^}_${name^^}_PRIO"
local p_val="${!p_var-}"
[ -z "$p_val" ] || idm_lib_order_set $name ${p_val}
fi
else
echo " WARN: Error while loading $type: ${name:-NONE}"
fi
done
# set +x
}
## Entry points ## Entry points
########################################## ##########################################
idm_menu_main () # Main initialisation settings
idm_core_init ()
{
export EDITOR=${EDITOR:-vim}
mkdir -p $IDM_ID_ENV_DIR $IDM_DIR_ID
# Configure libraries
IDM_LIB_TABLE=
IDM_LIB_TABLEFMT="mod enable disable status"
# Force native library display order
idm_lib_order_set id 10 90 10
idm_lib_order_set ssh 12 88 12
idm_lib_order_set ps1 60 40 60
idm_lib_order_set alias 60 40 60
# idm_lib_order_set cd 60 40 60
idm_lib_order_set gpg 11 89 11
#idm_lib_order_set git 50 50 50
#idm_lib_order_set tomb 50 50 50
idm_lib_order_set gh 50 50 50
idm_lib_order_set gitea 50 50 50
# Load external lib
idm_lib_load lib
idm_lib_load mod
trap "idm_exit_trap" INT TERM EXIT
}
idm_core_cli ()
{ {
#set -x #set -x
@ -574,20 +542,10 @@ idm_menu_main ()
local opt= local opt=
local shell_id=${SHELL_ID:-_} local shell_id=${SHELL_ID:-_}
# Load external libs idm_core_init
#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 # Three way parsing
local dep_order="$(idm_lib_order_get enable)"
if [ "$#" -eq 0 ]; then if [ "$#" -eq 0 ]; then
if [ -z "${SHELL_ID-}" ]; then if [ -z "${SHELL_ID-}" ]; then
@ -621,7 +579,7 @@ idm_menu_main ()
shift 3 && opt=${@} || true shift 3 && opt=${@} || true
# Check mod contraint # Check mod contraint
elif [[ "${IDM_MOD_ORDER}" =~ :$1: ]]; then elif [[ ":${dep_order// /:}:" =~ :$1: ]]; then
menu=$1 menu=$1
action=${2:-ls} action=${2:-ls}
id=$shell_id id=$shell_id
@ -650,11 +608,23 @@ idm_menu_main ()
# Aliases # Aliases
case $action in case $action in
--help|-h)
action=help
;;
quit|q) quit|q)
action=disable action=disable
;; ;;
esac esac
# Retrieve environment config
local IDM_ID_ENV="$IDM_DIR_ID/$id.env"
if [[ -f "$IDM_ID_ENV" ]]; then
. "$IDM_ID_ENV"
fi
if [[ -f "$IDM_DIR_ID/$id.secrets" ]]; then
. "$IDM_DIR_ID/$id.secrets"
fi
# Dispatch # Dispatch
#lib_log DEBUG "menu=$menu action=${action:-_} id=$id opt=$opt" #lib_log DEBUG "menu=$menu action=${action:-_} id=$id opt=$opt"
#set -x #set -x
@ -677,49 +647,5 @@ idm_menu_main ()
## Main ## Main
########################################## ##########################################
idm_menu_main $@ idm_core_cli $@
# 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"

1
bin/idmgr.sh Symbolic link
View File

@ -0,0 +1 @@
idmgr

43
docs/config.md Normal file
View File

@ -0,0 +1,43 @@
## Environment vars
* `IDM_DEBUG`:
* Type: Bool
* Desc: Set true for shell debugging
### Core Config
* `IDM_BIN`:
* Type: String/Path
* desc: Path of the idmgr executable script
* `IDM_DIR_ROOT`:
* Type: String/Path
* desc: Path of the idmgr code/library path
* `IDM_NO_BG`:
* Type: Bool
* Default: false
* Desc: Disable background service start
* Note: Will not start ssh-agent or other services ...
* `IDM_DISABLE_AUTO`:
* Default: ''
* Type: Words
* Desc: Disable some module components
* Example:
* `IDM_DISABLE_AUTO+=" git__enable git__disable git__kill "`
* `IDM_DISABLE_AUTO+="ps1__ls"`
### Id
* `IDM_LAST_ID_SAVE`:
* Type: Bool
* Default: true
* desc: Should the last loaded ID saved
* `IDM_LAST_ID_AUTOLOAD`:
* Type: Bool
* Default: true
* desc: Should the last saved ID should be enabled at shell startup

118
docs/howto_ssh.md Normal file
View File

@ -0,0 +1,118 @@
## Create a new ssh key pair
In this example, we will create an `ed25519` and `rsa4096` ssh keys. The first one is more recent and faster while the second is slow as
fuck, but compatible everywhere. Then will see how to enable them.
> Note: For practical reasons, it's not recommanded to have more than 3 SSH key pairs per ID, as SSH client does not try more than 3 keys
before trying other authentications methods. Also you can use the same password for your ssh keys (belonging to the same ID!) if you want to
be able to unlock all your SSH keys at once.
### Create key pairs
First enable your id:
```
[joey@joeylaptop .ssh]$ i joey
NOTICE: Enabling id ...
NOTICE: Enabling ssh ...
NOTICE: Enabling ps1 ...
NOTICE: Identity 'joey' is loaded
```
Then create your new `ed25519` SSH key:
```
(joey) [joey@joeylaptop .ssh]$ i ssh new
INFO: Key destination dir: /home/joey/.ssh/joey
> Username [joey]:
> Hostname [joeylaptop.myhome.net]:
Please choose key types:
n) ed25519 strongest, fast
s) rsa4096 most compatible, slow
o) rsa2048 old compatility
> Key types [ns]: n
Define key passphrase for the key(s).
Leave it empty for no password (not recommemded).
> Key passphrase [none]:
> Confirm passphrase:
> Generating key ...
Generating public/private ed25519 key pair.
Your identification has been saved in /home/joey/.ssh/joey/joey_ed25519_20201104
Your public key has been saved in /home/joey/.ssh/joey/joey_ed25519_20201104.pub
The key fingerprint is:
SHA256:tMLyxatG1TtK+qaPV14wArZUqU/cGojvUycKVp/JDIw joey@joeylaptop.myhome.net:ed25519_20201104
The key's randomart image is:
+--[ED25519 256]--+
| ... |
| + . |
| * *.o |
| E.Bo*.= |
| .ooOS* + |
| oooo%.= . |
| . +.=.* o |
| *o+ . |
| .+Bo |
+----[SHA256]-----+
INFO: Key(s) has been created in /home/joey/.ssh/joey
```
Let's create another key `rsa4096`, with the same password as the previous one:
```
(joey) [joey@joeylaptop .ssh]$ i ssh new
INFO: Key destination dir: /home/joey/.ssh/joey
> Username [joey]:
> Hostname [joeylaptop.myhome.net]:
Please choose key types:
n) ed25519 strongest, fast
s) rsa4096 most compatible, slow
o) rsa2048 old compatility
> Key types [ns]: s
Define key passphrase for the key(s).
Leave it empty for no password (not recommemded).
> Key passphrase [none]:
> Confirm passphrase:
> Generating key ...
Generating public/private rsa key pair.
Your identification has been saved in /home/joey/.ssh/joey/joey_rsa4096_20201104
Your public key has been saved in /home/joey/.ssh/joey/joey_rsa4096_20201104.pub
The key fingerprint is:
SHA256:mxcxTOj57nXB5y6h5mQV9d+pFSxIoxJgvTtzn+6PJdw joey@joeylaptop.myhome.net:rsa4096_20201104
The key's randomart image is:
+---[RSA 4096]----+
| oo. ..o .|
| . .ooo o ...|
| o.o+. ..o.|
| .+ o ...=|
| S.. +o+|
| + +o...++ |
| *.oo=E...|
| ..**... |
| .+*o. ..|
+----[SHA256]-----+
INFO: Key(s) has been created in /home/joey/.ssh/joey
```
### Enable keypairs
Then you can enable with one password your ssh keys:
```
(joey) [joey@joeylaptop .ssh]$ i ssh add
INFO__: Adding keys:
~/.ssh/joey/joey_ed25519_20201104
~/.ssh/joey/joey_rsa4096_20201104
Enter passphrase for /home/joey/.ssh/joey/joey_ed25519_20201104:
Identity added: /home/joey/.ssh/joey/joey_ed25519_20201104 (joey@joeylaptop.myhome.net:ed25519_20201104)
Identity added: /home/joey/.ssh/joey/joey_rsa4096_20201104 (joey@joeylaptop.myhome.net:rsa4096_20201104)
(joey) [joey@joeylaptop .ssh]$ i ssh
256 SHA256:tMLyxatG1TtK+qaPV14wArZUqU/cGojvUycKVp/JDIw joey@joeylaptop.myhome.net:ed25519_20201104 (ED25519)
4096 SHA256:mxcxTOj57nXB5y6h5mQV9d+pFSxIoxJgvTtzn+6PJdw joey@joeylaptop.myhome.net:rsa4096_20201104 (RSA)
```

158
lib/idmgr_lib_cli.sh Normal file
View File

@ -0,0 +1,158 @@
lib_log ()
{
set +x
[[ "${1-}" =~ ERR|WARN|TIP|NOTICE|INFO|DEBUG|RUN|CODE|DUMP|DEPRECATED|ASK ]] ||
{
lib_log ERR "Wrong message level while calling '${1-}'"
return 1
}
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|DEPRECATED)
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
>&2 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_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 -
}
## CLI lib
#############################
# This function display a user skippable timeout.
lib_cli_timeout ()
{
local default_rc=${1:-1}
local wait_time=${2:-$IDM_TIMEOUT_USER}
local start=$(date '+%s')
local human_word go_word
# Humanise ...
[ "$default_rc" -ge 0 ] || default_rc=1
if [ "$default_rc" -eq 0 ]; then
human_word="abort"
go_word=Q
elif [ "$default_rc" -ne 0 ]; then
human_word="continue"
go_word=Y
fi
# Notifying user
local human_date="$(date -d@$wait_time -u '+%Hh%Mm%Ss' | sed 's/00.//g' )"
local human_msg="Type '$go_word' to $human_word ($human_date):"
# Wait user input or timeout ...
local answer=
local rc=0
read -t $wait_time -p " ASK: ${human_msg} " answer || rc=$?
local remaining=$(( $wait_time - ( $(date '+%s') - $start ) ))
# Make a decision
if [[ "$rc" -eq 142 ]]; then
# We timeout, so GO! (142 is the timeout return code)
echo
return $default_rc
elif [[ "$answer" == "$go_word" ]]; then
# User asked to GO!
return 0
elif [[ $remaining -le 0 ]]; then
# Whatever, time passed, so GO!
return $default_rc
elif [[ "$rc" -ne 0 ]]; then
# Hmm, something wrong, we quit with error...
urm_log ERROR "Something went wrong (return code=$rc)"
return 1
fi
# We loop back
idm_cli_timeout $default_rc $remaining
}

View File

@ -4,97 +4,24 @@
## Special libraries ## Special libraries
############################# #############################
lib_shred ()
{
lib_lob WARN "Will destroy all your secrets! (nor implemented yet)"
}
## Standard libraries ## 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 () lib_parse_filerules ()
{ {
local id=$1 local id=$1
local f=$2 local f=$2
#set -x
local YADM_ENCRYPT="$2" local YADM_ENCRYPT="$2"
ENCRYPT_INCLUDE_FILES=() ENCRYPT_INCLUDE_FILES=()
ENCRYPT_EXCLUDE_FILES=() ENCRYPT_EXCLUDE_FILES=()
#cd_work "Parsing encrypt" || return
cd ~ cd ~
exclude_pattern="^!(.+)" exclude_pattern="^!(.+)"
if [ -f "$YADM_ENCRYPT" ] ; then if [ -f "$YADM_ENCRYPT" ] ; then
#; parse both included/excluded #; parse both included/excluded
@ -105,17 +32,13 @@ lib_parse_filerules ()
if [[ "$pattern" =~ $exclude_pattern ]]; then if [[ "$pattern" =~ $exclude_pattern ]]; then
for ex_file in ${BASH_REMATCH[1]}; do for ex_file in ${BASH_REMATCH[1]}; do
for f in $( find $ex_file -type f ); do for f in $( find $ex_file -type f ); do
#if [ -e "$ex_file" ]; then
ENCRYPT_EXCLUDE_FILES+=("$f") ENCRYPT_EXCLUDE_FILES+=("$f")
#fi
done done
done done
else else
for in_file in $pattern; do for in_file in $pattern; do
for f in $( find $in_file -type f ); do for f in $( find $in_file -type f ); do
#if [ -e "$in_file" ]; then
ENCRYPT_INCLUDE_FILES+=("$f") ENCRYPT_INCLUDE_FILES+=("$f")
#fi
done done
done done
fi fi
@ -144,106 +67,6 @@ lib_parse_filerules ()
lib_log ()
{
set +x
[[ "${1-}" =~ ERR|WARN|TIP|NOTICE|INFO|DEBUG|RUN|CODE|DUMP|DEPRECATED|ASK ]] ||
{
lib_log ERR "Wrong message level while calling '${1-}'"
return 1
}
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|DEPRECATED)
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
>&2 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
}
@ -301,8 +124,10 @@ lib_vars_load ()
} }
## UI lib
#############################
## Id lib ## Id lib
@ -375,6 +200,7 @@ lib_id_get_all_config ()
lib_id_get_all_id () lib_id_get_all_id ()
{ {
local id=
for id in $( find $IDM_DIR_ID -type f -name '*.env' 2>/dev/null ); do for id in $( find $IDM_DIR_ID -type f -name '*.env' 2>/dev/null ); do
id=${id%%\.env} id=${id%%\.env}
echo "${id##*/}" echo "${id##*/}"

61
lib/idmgr_lib_utils.sh Normal file
View File

@ -0,0 +1,61 @@
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" | sed -E -e 's/ 00*/ /g' -e 's/ [ydhms]//g' | xargs
}
# Nifty trick to set var from pipes
lib_set_var () { read "$@" <&0; }
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"
}
# Ensure a binary is available in PATH and declare a global variable
# to call the binary with some prefixed options if any.
# Example:
# lib_require_bin ansible --dry
# Creates : ANSIBLE_BIN var with valude: "ansible --dry"
lib_require_bin () {
local bin=$1
shift 1 || true
local opts=${@-}
if command -v "$bin" &> /dev/null; then
local var_name=${bin^^}_BIN
declare -g ${var_name//-/_}="$bin $opts"
return 0
else
lib_log ERR "Missing '$bin'"
return 1
fi
}
# Securely delete a file or a folder
# lib_shred [DIR/FILE]
lib_shred ()
{
lib_log WARN "Will destroy all your secrets! (nor implemented yet)"
}

164
lib/idmgr_mod_alias.sh Normal file
View File

@ -0,0 +1,164 @@
#!/bin/bash
#IDM_MOD_SSH_DEPS="s0 id gpg"
# trap 'idm_alias_kill' 0
## SSH functions
##########################################
idm_alias__help ()
{
echo "Aliases"
printf " %-20s: %s\n" "alias virsh" "Start virsh"
printf " %-20s: %s\n" "alias virt-manager" "Start virt-manager"
printf " %-20s: %s\n" "alias sshuttle" "Start sshuttle on SSH host"
printf " %-20s: %s\n" "alias sshuttle_ls" "Display net routes on SSH host"
#printf " %-20s: %s\n" "alias set" "Set alias"
#printf " %-20s: %s\n" "alias rm" "Remove alias"
#printf " %-20s: %s\n" "alias enable" "Enable agent"
#printf " %-20s: %s\n" "alias disable" "Disable agent"
#printf " %-20s: %s\n" "alias kill" "Kill agent"
# cat <<EOF
#
# Documentation:
#
# You can create a new alias key with the assistant:
# i alias set NAME VALUE
# The you can add this key to your agent, it will ask you your key password:
# i alias rm NAME
# To see current aliases:
# i alias ls
#
# EOF
}
idm_alias ()
{
# Argument maangement
if [ "$#" -eq 1 ]; then
local id=$1
idm_alias__ls $id
return 0
else
local action=$1
local id=$2
shift 2 || true
local opt=${@-}
fi
# Internal override case
# Fallback to command
idm_alias__help
return 1
}
## Required functions
##########################################
idm_alias__ls ()
{
local id=$1
local opt=${2:--l}
echo "i alias virsh HOST"
echo "i alias virt_manager HOST"
echo "i alias shuttle HOST [NET,...]"
echo "i alias shuttle_ls HOST"
}
idm_alias__disable ()
{
local id=$1
lib_id_has_config $id
}
idm_alias__enable ()
{
local id=$1
lib_id_has_config $id
}
# LOGOUT
idm_alias__kill ()
{
#set -x
local id=$1
local run_dir="${XDG_RUNTIME_DIR}/alias-agent/${id}"
}
## Hardcoded aliases
##########################################
idm_alias__virsh ()
{
local id=$1
local host=${2-}
[[ -n "$host" ]] || idm_exit 0 ERR "Missing SSH hostname in command line"
shift 2
local key=$(idm_ssh_search_private_keys "$id" | head -n 1 )
[[ -f "$key" ]] || idm_exit 0 WARN "No keys found"
local cmd="virsh -c "qemu+ssh://root@$host/system?keyfile=$key" $@"
lib_log RUN "$cmd"
exec $cmd
}
idm_alias__virt_manager ()
{
local id=$1
local host=${2-}
[[ -n "$host" ]] || idm_exit 0 ERR "Missing SSH hostname in command line"
shift 2
local key=$(idm_ssh_search_private_keys "$id" | head -n 1 )
[[ -f "$key" ]] || idm_exit 0 WARN "No keys found"
local cmd="virt-manager -c "qemu+ssh://root@$host/system?keyfile=$key" $@"
lib_log RUN "$cmd"
exec $cmd
}
idm_alias__sshuttle ()
{
local id=$1
local host=${2-}
[[ -n "$host" ]] || idm_exit 0 ERR "Missing SSH hostname in command line"
shift 2
idm_alias__sshuttle_ls $id $host || true
local cmd="sshuttle --remote $host --auto-hosts ${@:---auto-nets --dns}"
lib_log RUN "$cmd"
exec $cmd
}
idm_alias__sshuttle_ls ()
{
local id=$1
local host=${2-}
[[ -n "$host" ]] || idm_exit 0 ERR "Missing SSH hostname in command line"
shift 2
local cmd="ssh $host ip route"
lib_log RUN "$cmd"
$cmd
}

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
IDM_MOD_DEPS="id pass gpg ssh" #IDM_MOD_CLOUD_DEPS="s3"
## Prompt functions ## Prompt functions
########################################## ##########################################

55
lib/idmgr_mod_gh.sh Normal file
View File

@ -0,0 +1,55 @@
#!/bin/bash
#IDM_MOD_PS1_DEPS="s4 id pass gpg ssh"
#IDM_DISABLE_AUTO+="gh__ls"
## Prompt functions
##########################################
#SHELL_PS1="${SHELL_PS1:-${PS1}"
idm_gh ()
{
local action=${1-}
shift || true
idm_gh__ls
}
idm_gh__ls ()
{
local id=${1}
if [[ -n "${GH_TOKEN-}" ]] ; then
echo " enabled (repo: ${GH_REPO})"
else
echo " disabled"
fi
}
idm_gh__help ()
{
echo "Github CLI"
printf " %-20s: %s\n" "gh enable" "Enable gh token"
printf " %-20s: %s\n" "gh disable" "Disable gh token"
}
idm_gh__enable ()
{
if [[ -n "${gh_token-}" ]] ; then
echo "export GH_TOKEN=\"$gh_token\""
echo "export GH_REPO=\"$gh_repo\""
fi
}
idm_gh__disable ()
{
echo "unset GH_TOKEN"
echo "unset GH_REPO"
}
idm_gh__kill () { idm_gh__disable ${@-}; }

View File

@ -1,7 +1,9 @@
#!/bin/bash #!/bin/bash
IDM_MOD_DEPS="id" #IDM_MOD_GIT_DEPS="s1 id ssh"
IDM_DISABLE_AUTO+=" git__enable git__disable git__kill " #IDM_DISABLE_AUTO+=" git__enable git__disable git__kill "
#idm_hook_register enable idm_git__enable 5
## Environments ## Environments
@ -418,10 +420,11 @@ idm_git__ls ()
fi fi
# Display repo infos # Display repo infos
{
echo " Work tree : $git_id_work_tree" echo " Work tree : $git_id_work_tree"
echo " Local config : $git_id_config" echo " Local config : $git_id_config"
echo " Git dir : $git_id_dir" echo " Git dir : $git_id_dir"
} | sed "s:$HOME:~:g"
} }
idm_git__enable () idm_git__enable ()

78
lib/idmgr_mod_gitea.sh Normal file
View File

@ -0,0 +1,78 @@
#!/bin/bash
#IDM_MOD_PS1_DEPS="s4 id pass gpg ssh"
#IDM_DISABLE_AUTO+="gitea__ls"
## Prompt functions
##########################################
#SHELL_PS1="${SHELL_PS1:-${PS1}"
idm_gitea ()
{
local action=${1-}
shift || true
idm_gitea__ls
}
idm_gitea__ls ()
{
local id=${1}
if [[ -n "${GITEA_LOGIN-}" ]] ; then
echo " enabled (repo: ${GITEA_LOGIN} ${GITEA_URL})"
else
echo " disabled"
fi
}
idm_gitea__help ()
{
echo "Github CLI"
printf " %-20s: %s\n" "gitea enable" "Enable gitea token"
printf " %-20s: %s\n" "gitea disable" "Disable gitea token"
}
idm_gitea__register ()
{
local gitea_url=$1
local gitea_login=$2
local gitea_token=$3
if tea login list -o simple | grep -q "^$gitea_login"; then
:
else
tea login add \
--url "$gitea_url" \
--name "$gitea_login" \
--token "$gitea_token" > /dev/null
>&2 echo "Tea login installed: $gitea_login ($gitea_url)"
fi
}
idm_gitea__enable ()
{
[[ -n "${gitea_url-}" ]] || return 0
[[ -n "${gitea_login-}" ]] || return 0
[[ -n "${gitea_token-}" ]] || return 0
idm_gitea__register $gitea_url $gitea_login $gitea_token
echo "export GITEA_SERVER_URL=\"$gitea_token\""
echo "export GITEA_LOGIN=\"$gitea_login\""
}
idm_gitea__disable ()
{
echo "unset GITEA_SERVER_URL"
echo "unset GITEA_LOGIN"
}
idm_gitea__kill () { idm_gitea__disable ${@-}; }

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
IDM_MOD_DEPS="id" #IDM_MOD_GPG_DEPS="s0 id"
idm_gpg__help () idm_gpg__help ()
@ -34,7 +34,7 @@ idm_gpg__cheat ()
sub: Public subkey sub: Public subkey
fpr: Fingerprint fpr: Fingerprint
grp: Keygrip grp: Keygrip
uid: Persona identification string uid: Personal identification string
Usage: Usage:
S: Signing S: Signing
C: Certification C: Certification
@ -52,6 +52,7 @@ idm_gpg__cheat ()
EOF EOF
# Notes: # Notes:
# ED25... : https://www.digitalneanderthal.com/post/gpg/
# See uses cases: http://www.saminiir.com/establish-cryptographic-identity-using-gnupg/ # See uses cases: http://www.saminiir.com/establish-cryptographic-identity-using-gnupg/
# Pass helper: https://github.com/avinson/gpg-helper # Pass helper: https://github.com/avinson/gpg-helper
@ -79,6 +80,7 @@ idm_gpg__enable ()
local id=${1} local id=${1}
lib_id_has_config $id lib_id_has_config $id
idm_gpg_header $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
@ -87,19 +89,25 @@ idm_gpg__enable ()
unset GPG_AGENT_INFO unset GPG_AGENT_INFO
fi fi
# Check if socket is present if [[ "${IDM_NO_BG:-false}" == true ]] || [[ -n "${DIRENV_IN_ENVRC-}" ]] ; then
if [ ! -S "${GPG_AGENT_INFO-}" ]; then lib_log WARN "Start of gpg-agent background process disabled because of: IDM_NO_BG=${IDM_NO_BG-} or DIRENV_IN_ENVRC=${DIRENV_IN_ENVRC-}"
rm -f "${XDG_RUNTIME_DIR}/pgp-agent/${id}/env" else
idm_gpg_start $id
fi
# Show config to source # Check if socket is present
if [ -f "${XDG_RUNTIME_DIR}/pgp-agent/${id}/env" ]; then if [ ! -S "${GPG_AGENT_INFO-}" ]; then
cat "${XDG_RUNTIME_DIR}/pgp-agent/${id}/env" rm -f "${XDG_RUNTIME_DIR}/pgp-agent/${id}/env"
idm_gpg_start $id
fi
# Show config to source
if [ -f "${XDG_RUNTIME_DIR}/pgp-agent/${id}/env" ]; then
cat "${XDG_RUNTIME_DIR}/pgp-agent/${id}/env"
fi
fi fi
# Export tty to the current shell # Export tty to the current shell
echo "export GPG_TTY=$(tty)" echo "export GPG_TTY=$(tty)"
echo "export GNUPGHOME=$GNUPGHOME"
} }
@ -197,7 +205,10 @@ idm_gpg__init ()
envsubst < $IDM_DIR_ROOT/shell/gpg_gen.tpl > $IDM_DIR_CACHE/gpg_gen_$id envsubst < $IDM_DIR_ROOT/shell/gpg_gen.tpl > $IDM_DIR_CACHE/gpg_gen_$id
) )
echo $IDM_DIR_CACHE
# Generate key # Generate key
mkdir -p "$gpghome"
gpg2 --batch --gen-key $IDM_DIR_CACHE/gpg_gen_$id gpg2 --batch --gen-key $IDM_DIR_CACHE/gpg_gen_$id
#gpg --verbose --batch --gen-key $IDM_DIR_CACHE/gpg_gen_$id #gpg --verbose --batch --gen-key $IDM_DIR_CACHE/gpg_gen_$id
#echo $? #echo $?
@ -454,7 +465,7 @@ lib_gpg_decrypt_dir ()
# Check required bin # Check required bin
lib_require_bin tar || idm_exit 1 lib_require_bin tar || idm_exit 1
lib_require_bin gpg2 || idm_exit 1 lib_require_bin gpg2 || idm_exit 1
export GPG=${GPG2:-$GPG} export GPG=${GPG2:-$GPG_BIN}
tar_opts=" -C ${dst%/*} -zx " tar_opts=" -C ${dst%/*} -zx "
if [ ! -z "$key" ]; then if [ ! -z "$key" ]; then
@ -463,7 +474,7 @@ lib_gpg_decrypt_dir ()
gpg_opts+="-d" gpg_opts+="-d"
fi fi
$GPG $gpg_opts $src | $TAR $tar_opts || \ $GPG_BIN $gpg_opts $src | $TAR_BIN $tar_opts || \
idm_exit 1 ERR "Could not decrypt file: $src into $dst" idm_exit 1 ERR "Could not decrypt file: $src into $dst"
} }
@ -479,7 +490,7 @@ lib_gpg_encrypt_dir ()
# Check required bin # Check required bin
lib_require_bin tar || idm_exit 1 lib_require_bin tar || idm_exit 1
lib_require_bin gpg2 || idm_exit 1 lib_require_bin gpg2 || idm_exit 1
export GPG=${GPG2:-$GPG} export GPG=${GPG2:-$GPG_BIN}
#GPG_KEY="$(yadm config yadm.gpg-recipient || true )" #GPG_KEY="$(yadm config yadm.gpg-recipient || true )"
#GPG_KEY="${GPG_DEFAULT_ID-}" #GPG_KEY="${GPG_DEFAULT_ID-}"
@ -537,8 +548,8 @@ lib_gpg_encrypt_dir ()
#set -x #set -x
# Encrypt all the stuffs # Encrypt all the stuffs
$TAR -C "${src%/*}" -cz "${src##*/}" 2>/dev/null | \ $TAR_BIN -C "${src%/*}" -cz "${src##*/}" 2>/dev/null | \
$GPG -a $gpg_opts --yes -o $dst || \ $GPG_BIN -a $gpg_opts --yes -o $dst || \
idm_exit 1 ERR "Could not encrypt directory: $src" idm_exit 1 ERR "Could not encrypt directory: $src"
#set +x #set +x
@ -546,7 +557,7 @@ lib_gpg_encrypt_dir ()
# File descritor tests ... # File descritor tests ...
#exec 3<> /tmp/foo #exec 3<> /tmp/foo
#>&3 echo "$pass" #>&3 echo "$pass"
#{ echo "$pass\n" >&3 ; $TAR -C "$(dirname $src)" -cz "$src" 2>/dev/null; } | \ #{ echo "$pass\n" >&3 ; $TAR_BIN -C "$(dirname $src)" -cz "$src" 2>/dev/null; } | \
#exec 3>&- #close fd 3. #exec 3>&- #close fd 3.
} }

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
IDM_MOD_DEPS="" #IDM_MOD_ID_DEPS="s0"
## Identity functions ## Identity functions
########################################## ##########################################
@ -27,21 +27,26 @@ idm_id ()
idm_id__disable() idm_id__disable()
{ {
# Disable internal variables # Disable internal variables
echo "unset SHELL_ID GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL" | lib_log CODE - echo "unset SHELL_ID GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL" | lib_log CODE -
idm_id_save_last_id _
} }
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"
[ -f "$conf" ] && source "$conf" [ -f "$conf" ] && source "$conf"
echo "export SHELL_ID=${id}" echo "export SHELL_ID='${id}'"
echo "export GIT_AUTHOR_NAME=${common_name:-$id}" echo "export GIT_AUTHOR_NAME='${common_name:-$id}'"
echo "export GIT_AUTHOR_EMAIL=${email}" echo "export GIT_AUTHOR_EMAIL='${email}'"
echo "export GIT_COMMITTER_NAME='${common_name:-$id}'"
echo "export GIT_COMMITTER_EMAIL='${email}'"
idm_id_save_last_id $id
# echo "export PATH=${XDG_OPT_HOME}/bin:$PATH" # echo "export PATH=${XDG_OPT_HOME}/bin:$PATH"
# echo "export SSH_CONFIG=${id}" # echo "export SSH_CONFIG=${id}"
@ -107,7 +112,6 @@ idm_id__show ()
idm_id__ls () idm_id__ls ()
{ {
local active local active
#set -x
for id in $(lib_id_get_all_id); do for id in $(lib_id_get_all_id); do
@ -129,6 +133,12 @@ idm_id__ls ()
done | column -t -s: -o' ' #| lib_log DUMP - done | column -t -s: -o' ' #| lib_log DUMP -
} }
# List all available IDs names
idm_id__names ()
{
lib_id_get_all_id | xargs
}
idm_id__edit () idm_id__edit ()
{ {
@ -180,19 +190,6 @@ idm_id__dump ()
done done
} }
idm_id_template ()
{
local cn=${1-}
local tz lang
# Auto guess
tz=$( timedatectl | grep "Time zone" | awk '{print $3}' || true )
echo "common_name=${cn}"
echo "email="
echo "tz=$tz"
}
idm_id__rm () idm_id__rm ()
{ {
local id=${1} local id=${1}
@ -210,3 +207,28 @@ idm_id__rm ()
lib_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
} }
idm_id_save_last_id ()
{
local id=${1}
[[ "${IDM_LAST_ID_SAVE:-true}" == "true" ]] || return 0
echo "$id" > "$IDM_DIR_CACHE/last_id"
}
idm_id_template ()
{
local cn=${1-}
local hostname=${2-}
local tz lang
# Auto guess
tz=$( timedatectl | grep "Time zone" | awk '{print $3}' || true )
echo "common_name=${cn}"
echo "login=${cn}"
echo "email="
echo "tz=$tz"
echo "public=false"
echo "hostname=${hostname:-$(hostname -f)}"
}

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
IDM_MOD_DEPS="id gpg" #IDM_MOD_PASS_DEPS="s2"
## Pass functions ## Pass functions

View File

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
IDM_MOD_DEPS="id pass gpg ssh" #IDM_MOD_PS1_DEPS="s4 id pass gpg ssh"
IDM_DISABLE_AUTO+="ps1__ls" #IDM_DISABLE_AUTO+="ps1__ls"
## Prompt functions ## Prompt functions
########################################## ##########################################
@ -13,17 +13,15 @@ idm_ps1 ()
local action=${1-} local action=${1-}
shift || true shift || true
idm_ps1_ls idm_ps1__ls
} }
idm_ps1__ls () idm_ps1__ls ()
{ {
local id=${1} local id=${1}
#set -x # Bug here: PS1 and vars are like nk existing ... weird
#echo "PS1=${SHELL_PS1:-${PS1-}}" if grep -q "($id)" <<<"${IDM_SHELL_PS1:-${PS1-}}" ; then
if grep -q "($id)" <<<"${SHELL_PS1:-${PS1-}}" ; then
echo " enabled" echo " enabled"
else else
echo " disabled" echo " disabled"
@ -39,21 +37,49 @@ idm_ps1__help ()
} }
idm_ps1__enable () idm_ps1__enable ()
{
# Detect is PS1_*FIX vars exists
if [ "${PS1_PREFIX+x}" == x ]; then
#>&2 echo "Prefix PS1_PREFIX: ${PS1_PREFIX+x}"
idm_ps1__enable_suffix $@
else
#>&2 echo "Classic PS1: ${PS1_PREFIX+x}"
idm_ps1__enable_raw $@
fi
}
idm_ps1__enable_raw ()
{ {
local id=${1} local id=${1}
id="\[\033[0;34m\]($id)\[\033[00m\]" id="\[\033[0;34m\]($id)\[\033[00m\]"
echo "export PS1=\"$id \${IDM_SHELL_PS1}\"" echo "export PS1=\"$id \${IDM_SHELL_PS1}\""
# Notes about colors: # Notes about colors:
# \033]00m\] # for shell # \033]00m # for shell
# \[\033]01;31m\] for ps1 # \[\033]01;31m\] # for ps1
} }
idm_ps1__enable_suffix ()
{
local id=${1}
id="\033[0;34m($id)\033[00m"
echo "export PS1_PREFIX=\"$id${PS1_PREFIX:+ $PS1_PREFIX}\""
}
idm_ps1__disable () idm_ps1__disable ()
{ {
echo "export PS1=\"\${IDM_SHELL_PS1}\""
return # Detect is PS1_*FIX vars exists
if [ "${PS1_PREFIX+x}" == x ]; then
#>&2 echo "Prefix PS1_PREFIX: ${PS1_PREFIX+x}"
echo "unset PS1_PREFIX"
else
#>&2 echo "Classic PS1: ${PS1_PREFIX+x}"
echo "export PS1=\"\${IDM_SHELL_PS1}\""
fi
} }
idm_ps1__kill () { idm_ps1__disable ${@-}; } idm_ps1__kill () { idm_ps1__disable ${@-}; }

View File

@ -1,19 +1,21 @@
#!/bin/bash #!/bin/bash
#IDM_MOD_SSH_DEPS="s0 id gpg"
IDM_MOD_DEPS="id gpg"
# trap 'idm_ssh_kill' 0 # trap 'idm_ssh_kill' 0
# See: https://github.com/kalbasit/ssh-agents
## 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" "ssh ls" "List unlocked keys" printf " %-20s: %s\n" "ssh ls" "List unlocked keys"
printf " %-20s: %s\n" "ssh new" "Create new ssh key (ssh-keygen)" printf " %-20s: %s\n" "ssh pub" "Show public keys"
printf " %-20s: %s\n" "ssh tree" "Show keypairs tree"
printf " %-20s: %s\n" "ssh new [dir]" "Create new ssh key dest dir"
printf " %-20s: %s\n" "ssh add" "Unlock known keypairs" printf " %-20s: %s\n" "ssh add" "Unlock known keypairs"
printf " %-20s: %s\n" "ssh rm" "Lock known keypairs" printf " %-20s: %s\n" "ssh rm" "Lock known keypairs"
printf " %-20s: %s\n" "ssh del" "Delete keypair" printf " %-20s: %s\n" "ssh del" "Delete keypair"
@ -22,6 +24,21 @@ idm_ssh__help ()
printf " %-20s: %s\n" "ssh disable" "Disable agent" printf " %-20s: %s\n" "ssh disable" "Disable agent"
printf " %-20s: %s\n" "ssh kill" "Kill agent" printf " %-20s: %s\n" "ssh kill" "Kill agent"
cat <<EOF
Documentation:
You can create a new ssh key with the assistant:
i ssh new
The you can add this key to your agent, it will ask you your key password:
i ssh add
If you want to kill the agent:
i ssh rm
If you want to delete your key files, simply run:
i ssh rm
EOF
} }
idm_ssh () idm_ssh ()
@ -56,7 +73,6 @@ idm_ssh__ls ()
local opt=${2:--l} local opt=${2:--l}
lib_id_is_enabled $id || return 0 lib_id_is_enabled $id || return 0
{ ssh-add $opt || true ; } 2>/dev/null | sed 's/^/ /' { ssh-add $opt || true ; } 2>/dev/null | sed 's/^/ /'
} }
@ -75,31 +91,40 @@ idm_ssh__enable ()
{ {
local id=$1 local id=$1
lib_id_has_config $id lib_id_has_config $id
local socket="${XDG_RUNTIME_DIR}/ssh-agent/${id}/socket"
# Source environment # Source environment
if [ -f "${XDG_RUNTIME_DIR}/ssh-agent/${id}/env" ] ; then # if [ -f "${XDG_RUNTIME_DIR}/ssh-agent/${id}/env" ] ; then
. "${XDG_RUNTIME_DIR}/ssh-agent/${id}/env" # . "${XDG_RUNTIME_DIR}/ssh-agent/${id}/env"
else # else
unset SSH_AUTH_SOCK SSH_AGENT_PID # unset SSH_AUTH_SOCK SSH_AGENT_PID
fi # fi
unset SSH_AUTH_SOCK SSH_AGENT_PID
# Check status # Check status
if ! idm_ssh__is_agent_working $id ${SSH_AUTH_SOCK:-_} ${SSH_AGENT_PID:-0}; then export SSH_AUTH_SOCK=$socket
if ! idm_ssh__agent_start $id; then if ! idm_ssh__is_agent_working $socket ; then
lib_log WARN "Could not start ssh agent :(" if [[ "${IDM_NO_BG:-false}" == true ]] || [[ -n "${DIRENV_IN_ENVRC-}" ]] ; then
return 1 lib_log WARN "Start of background process disabled because of: IDM_NO_BG=${IDM_NO_BG:-false}"
lib_log TIPS "Run '${0##*/} $id' to start ssh-agent"
else
idm_ssh__agent_start $id
fi fi
fi fi
# Display config to load # Display config to load
cat "${XDG_RUNTIME_DIR}/ssh-agent/${id}/env" # >&2 ls -ahl ${XDG_RUNTIME_DIR}/ssh-agent/${id}/
# cat "${XDG_RUNTIME_DIR}/ssh-agent/${id}/env" || true
echo "export SSH_AUTH_SOCK=$SSH_AUTH_SOCK"
} }
# LOGOUT # LOGOUT
idm_ssh__kill () idm_ssh__kill ()
{ {
#set -x
local id=$1 local id=$1
local run_dir="${XDG_RUNTIME_DIR}/ssh-agent/${id}" local run_dir="${XDG_RUNTIME_DIR}/ssh-agent/${id}"
@ -126,7 +151,139 @@ idm_ssh__kill ()
# Disable agent # Disable agent
idm_ssh__disable $id idm_ssh__disable $id
set +x
}
## Extra functions
##########################################
idm_ssh__tree ()
{
local id=$1
if lib_id_has_config $id &>/dev/null; then
tree -C "$HOME/.ssh/$id"
else
tree -C "$HOME/.ssh/"
fi
}
idm_ssh__pub ()
{
local id=$1
local path="$HOME/.ssh"
if lib_id_has_config $id &>/dev/null; then
path="$HOME/.ssh/$id"
fi
head -n 3 "$path"/*.pub
}
idm_ssh__new ()
{
local id=${1-}
local dest=${2-}
local default=
local key_vers=
local key_user=
local key_host=
local key_sizes=
local key_vers="$(date +'%Y%m%d')"
# Guess defaults
default=$(id -un)
if lib_id_has_config $id &>/dev/null; then
default=${login:-$id}
if [ -z "$dest" ]; then
dest="$HOME/.ssh/$id"
fi
else
dest=${dest:-.}
fi
mkdir -p "$dest"
echo "INFO: Key destination dir: $dest"
# Login
while ! grep -q '\w\+' <<< "$key_user"; do
read -rp "> Username [$default]: " ans
key_user="${ans:-$default}"
done
# Host name
default="${hostname:-$(hostname -f)}"
while ! grep -q '[a-zA-Z0-9.-]\+' <<< "$key_host"; do
read -rp "> Hostname [$default]: " ans
#echo ""
key_host="${ans:-$default}"
done
# Keys sizes
default="ns"
echo "Please choose key types:"
echo "n) ed25519 strongest, fast"
echo "s) rsa4096 most compatible, slow"
echo "o) rsa2048 old compatility"
while ! grep -q '[nso]\+' <<< "$key_sizes"; do
echo -n "> Key types [$default]: "
read -n 3 -r ans
echo ""
key_sizes="${ans:-$default}"
done
# Ask password
echo "Define key passphrase for the key(s)."
echo "Leave it empty for no password (not recommemded)."
echo -n "> Key passphrase [none]: "
read -rs key_pass
echo
key_pass="${key_pass:-}"
ans=""
while [ "$ans" != "$key_pass" ]; do
echo -n "> Confirm passphrase: "
read -rs ans
echo
done
# Create keys
local size=$key_sizes
while [ -n "$size" ]; do
local k=${size:0:1}
echo -e "\n> Generating key ..."
set +e
case $k in
n)
ssh-keygen -f "$dest/${key_user}_ed25519_${key_vers}" \
-t ed25519 -a 100 \
-N "$key_pass" \
-C "${key_user}@${key_host}:ed25519_${key_vers}"
;;
s)
ssh-keygen -f "$dest/${key_user}_rsa4096_${key_vers}" \
-t rsa -b 4096 -o -a 500 \
-N "$key_pass" \
-C "${key_user}@${key_host}:rsa4096_${key_vers}"
;;
o)
ssh-keygen -f "$dest/${key_user}_rsa2048_${key_vers}" \
-t rsa -b 2048 -o -a 100 \
-N "$key_pass" \
-C "${key_user}@${key_host}:rsa2048_${key_vers}"
;;
esac
set -e
size=${size:1}
done
echo
echo "INFO: Key(s) has been created in $dest"
} }
@ -136,45 +293,118 @@ idm_ssh__kill ()
idm_ssh__is_agent_working () idm_ssh__is_agent_working ()
{ {
local id=$1 local socket=$1
local socket=${2:-_}
local pid=${3:-0}
local rc= local rc=
set +e set +e
SSH_AUTH_SOCK=$socket SSH_AGENT_PID=$pid ssh-add -l &>/dev/null SSH_AUTH_SOCK=$socket ssh-add -l &>/dev/null
rc=$? rc=$?
set -e set -e
[ "$rc" -lt 2 ] && return 0 if ! [ "$rc" -lt 2 ]; then
} [[ -e "$socket" ]] && rm "$socket"
idm_ssh__agent_start() {
local id=$1
local life=5d
local run_dir="${XDG_RUNTIME_DIR}/ssh-agent/${id}"
# Check if we can recover from previous instance
idm_ssh__agent_clean $id "$run_dir/socket" 0 || true
# Ensure directory are present
[ -d "$run_dir" ] || \
mkdir -p "$run_dir"
# Ensure env file is not present
[ ! -f "${run_dir}/env" ] || \
rm -f "${run_dir}/env"
#set -x
# Start the agent
if ssh-agent -a "$run_dir/socket" -t $life -s | grep ^SSH_ > "$run_dir/env"; then
echo "$run_dir/env"
lib_log INFO "Start ssh-agent ..."
else
lib_log WARN "Could not start ssh agent :("
return 1 return 1
fi fi
return 0
}
background() {
>&2 echo "MY COMMAND: $@"
set +e
exec 0>&- || true
exec 1>&- || true
exec 2>&- || true
exec 3>&- || true
"$@" &
local pid=$!
disown $pid
echo $pid
set -e
}
idm_ssh__agent_start() {
# local socket=$1
local id=$1
local life=4w
local socket_dir="${XDG_RUNTIME_DIR}/ssh-agent/${id}"
local socket="${socket_dir}/socket"
# Ensure directory are present
[ -d "$socket_dir" ] || \
mkdir -p "$socket_dir"
# Start the agent
rm "$socket" 2>/dev/null || true
export SSH_AUTH_SOCK=
export SSH_AGENT_PID=
#nohup ssh-agent -D -a "$socket" -t $life 2>&1 >$socket_dir/env &
# local pid=$(background ssh-agent -a "$socket" -t $life)
ssh-agent -a "$socket" -t $life |& grep 'SSH_' > $socket_dir/env
source "$socket_dir/env"
#echo "SSH_AUTH_SOCK=$socket"
#echo "SSH_AGENT_PID=$pid"
# >&2 echo "PID=$pid"
# echo "SSH_AUTH_SOCK=$socket" > $socket_dir/env
# echo "SSH_AGENT_PID=$pid" >> $socket_dir/env
# # local pid=$!
# # ps aux | grep $pid >&2
# # Wait for service to be started
# . $socket_dir/env > /dev/null
# until [ ! -z "${SSH_AUTH_SOCK:-}" ]; do
# . $socket_dir/env > /dev/null
# >&2 echo "WAiting socket .... "
# sleep 3
# done
# # . $socket_dir/env
# >&2 jobs
# disown -ar
# >&2 jobs
# return
#local run_dir="${XDG_RUNTIME_DIR}/ssh-agent/${id}"
# Check if we can recover from previous instance
# idm_ssh__agent_clean $id "$run_dir/socket" 0 || true
# # Ensure env file is not present
# [ ! -f "${run_dir}/env" ] || \
# rm -f "${run_dir}/env"
# #set -x
# DEVEL # Start the agent
# DEVEL lib_log INFO "Start ssh-agent ..."
# DEVEL $IDM_DIR_ROOT/bin/start_ssh_agent.sh "$run_dir/socket" $life
# DEVEL
# DEVEL # nohup ssh-agent -D -a "$run_dir/socket" -t $life
# DEVEL # export SSH_AGENT_PID=$!
# DEVEL export SSH_AUTH_SOCK="$socket"
# DEVEL echo "export SSH_AUTH_SOCK=$SSH_AUTH_SOCK" > "$run_dir/env"
# DEVEL echo "export SSH_AGENT_PID=$SSH_AGENT_PID" >> "$run_dir/env"
# DEVEL #echo "VALUE='$SSH_AUTH_SOCK $SSH_AGENT_PID'"
# if nohup ssh-agent -a "$socket" -t $life ; then
# disown $pid
# #source "$run_dir/env"
# #cat "$run_dir/env"
# export SSH_AUTH_SOCK="$socket"
# lib_log INFO "Start ssh-agent ... ($pid)"
# else
# lib_log WARN "Could not start ssh agent :("
# return 1
# fi
} }
@ -186,7 +416,6 @@ idm_ssh__agent_clean ()
# We should kill all agents .... # We should kill all agents ....
if [ "${pid}" == '0' ]; then if [ "${pid}" == '0' ]; then
#set +x
pid=$(grep -a "$socket" /proc/*/cmdline \ pid=$(grep -a "$socket" /proc/*/cmdline \
| grep -a -v 'thread-self' \ | grep -a -v 'thread-self' \
| strings -s' ' -1 \ | strings -s' ' -1 \
@ -195,7 +424,6 @@ idm_ssh__agent_clean ()
#set -x #set -x
pid="$( sed -E 's@/proc/([0-9]*)/.*@\1@' <<<"$pid" )" pid="$( sed -E 's@/proc/([0-9]*)/.*@\1@' <<<"$pid" )"
fi fi
#set -x
# Remove process # Remove process
if [ ! -z "$pid" ]; then if [ ! -z "$pid" ]; then
@ -217,110 +445,121 @@ idm_ssh__agent_clean ()
## Extended functions ## Extended functions
########################################## ##########################################
idm_ssh_add () idm_ssh__add ()
{ {
local id=$1 local id=$1
local key=${2-} local key=${2-}
local maxdepth=2
#lib_id_is_enabled $id #lib_id_is_enabled $id
lib_id_is_enabled $id lib_id_is_enabled $id
key_list=$(idm_ssh_search_private_keys "$id" "$key")
if [[ ! -z "$key" ]]; then [ -n "$key_list" ] || \
pub_keys=$(
{
# Compat mode
find ~/.ssh/id -maxdepth $maxdepth -name "${id}_*" -name '*pub' -name "*$1*" | sort
# New mode (test)
find ~/.ssh/$id -maxdepth $maxdepth -name "${id}_*" -name '*pub' -name "*$1*" | sort
} | sort | uniq
)
else
pub_keys=$(find ~/.ssh/$id -maxdepth $maxdepth -name "${id}_*" -name '*pub' | sort)
fi
echo "$pub_keys"
# Get list of key
local key_list=""
while read -r pub_key; do
#if [[ -f "$(sed 's/\.pub$/.key/' <<< "${pub_key}" )" ]]; then
if [[ -f "${pub_key//\.pub/.key}" ]]; then
key_list="$key_list ${pub_key//\.pub/.key}"
else
#if [[ -f "$(sed 's/\.pub$//' <<< "${pub_key}" )" ]]; then
if [[ -f "${pub_key%\.pub}" ]]; then
key_list="$key_list ${pub_key%\.pub}"
fi
fi
done <<< "$pub_keys"
[ -n "$pub_keys" ] || \
idm_exit 0 WARN "No keys found" idm_exit 0 WARN "No keys found"
lib_log INFO "Adding keys:" lib_log INFO "Adding keys:"
xargs -n 1 <<<$key_list | lib_log DUMP - xargs -n 1 <<<$key_list | sed "s:$HOME:~:" | lib_log DUMP -
echo "" echo ""
ssh-add $key_list ssh-add $key_list
} }
## SSH Library
##########################################
# This function search the bests ssh key file to use matching to an ID
idm_ssh_search_private_keys ()
{
local id=$1
local key=${2-}
local maxdepth=2
if [[ ! -z "$key" ]]; then
pub_keys=$(
{
# Compat mode
find -L ~/.ssh/$id -maxdepth $maxdepth -name "${id}_*" -name '*pub' -name "*$id*" | sort
} | sort | uniq
)
else
pub_keys=$(find -L ~/.ssh/$id -maxdepth $maxdepth -name '*pub' | sort)
fi
# Get list of key
local key_list=""
while read -r pub_key; do
if [[ -z "$pub_key" ]]; then
continue
elif [[ -f "${pub_key//\.pub/.key}" ]]; then
key_list="${key_list:+$key_list\n}${pub_key//\.pub/.key}"
else
if [[ -f "${pub_key%\.pub}" ]]; then
key_list="${key_list:+$key_list\n}${pub_key%\.pub}"
else
lib_log WARN "Can't find private key of: $pub_key"
fi
fi
done <<< "$pub_keys"
echo -e "$key_list"
}
## Deprecated functions ## Deprecated functions
########################################## ##########################################
# Useless at this stage i guess ### DEPRECATED # Useless at this stage i guess
idm_ssh__agent_check () ### DEPRECATED idm_ssh__agent_check ()
{ ### DEPRECATED {
#set -x ### DEPRECATED #set -x
local id=$1 ### DEPRECATED local id=$1
local socket=${2:-_} ### DEPRECATED local socket=${2:-_}
local pid=${3:-0} ### DEPRECATED local pid=${3:-0}
### DEPRECATED
if [ "$socket" == '_' ] && [ "$pid" == '0' ] ; then ### DEPRECATED if [ "$socket" == '_' ] && [ "$pid" == '0' ] ; then
# Parameters are not valid, we assume ssh-agent is not launched at all ### DEPRECATED # Parameters are not valid, we assume ssh-agent is not launched at all
return 1 ### DEPRECATED return 1
elif SSH_AUTH_SOCK=$socket SSH_AGENT_PID=$pid ssh-add -l &>/dev/null ; then ### DEPRECATED elif SSH_AUTH_SOCK=$socket SSH_AGENT_PID=$pid ssh-add -l &>/dev/null ; then
return 0 ### DEPRECATED return 0
else ### DEPRECATED else
lib_log WARN "ssh-agent is not working as expected" ### DEPRECATED lib_log WARN "ssh-agent is not working as expected"
fi ### DEPRECATED fi
### DEPRECATED
# Is the socket valid ? ### DEPRECATED # Is the socket valid ?
if [ "$socket" != '_' -a ! -S "$socket" ]; then ### DEPRECATED if [ "$socket" != '_' -a ! -S "$socket" ]; then
lib_log WARN "Socket '$socket' is dead, can't recover ssh-agent" ### DEPRECATED lib_log WARN "Socket '$socket' is dead, can't recover ssh-agent"
idm_ssh__agent_clean $id $socket 0 ### DEPRECATED idm_ssh__agent_clean $id $socket 0
return 1 ### DEPRECATED return 1
fi ### DEPRECATED fi
### DEPRECATED
if [ "$pid" != '0' -a "$pid" -lt 1 ]; then ### DEPRECATED if [ "$pid" != '0' -a "$pid" -lt 1 ]; then
local pid="$( ps aux | grep "$socket" | grep -v 'grep' | head -n 1 | awk '{ print $2 }' )" || \ ### DEPRECATED 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 }' )" || \ ### DEPRECATED pid="$( ps aux | grep "" | grep -v 'grep' | head -n 1 | awk '{ print $2 }' )" || \
{ ### DEPRECATED {
lib_log WARN "Process ssh-agent is dead, cannot recover" ### DEPRECATED lib_log WARN "Process ssh-agent is dead, cannot recover"
idm_ssh__agent_clean $id $socket 0 ### DEPRECATED idm_ssh__agent_clean $id $socket 0
return 1 ### DEPRECATED return 1
} ### DEPRECATED }
### DEPRECATED
# Kill all processes ### DEPRECATED # Kill all processes
lib_log DEBUG "Multiple PID founds for ssh-agent: $pid" ### DEPRECATED lib_log DEBUG "Multiple PID founds for ssh-agent: $pid"
q=0 ### DEPRECATED q=0
for p in $pid; do ### DEPRECATED for p in $pid; do
return ### DEPRECATED return
idm_ssh__agent_clean $id $socket $pid || true ### DEPRECATED idm_ssh__agent_clean $id $socket $pid || true
q=1 ### DEPRECATED q=1
done ### DEPRECATED done
[ "$q" -eq 0 ] || return 1 ### DEPRECATED [ "$q" -eq 0 ] || return 1
### DEPRECATED
fi ### DEPRECATED fi
### DEPRECATED
# Ok, now we can try to recover the things ### DEPRECATED # Ok, now we can try to recover the things
### DEPRECATED
### DEPRECATED
# Hmm, we should not arrive here ... ### DEPRECATED # Hmm, we should not arrive here ...
lib_log WARN "ssh-agent is in a really weird state :/" ### DEPRECATED lib_log WARN "ssh-agent is in a really weird state :/"
return 1 ### DEPRECATED return 1
### DEPRECATED
} ### DEPRECATED }

View File

@ -1,12 +1,12 @@
#!/bin/bash #!/bin/bash
IDM_MOD_DEPS="id gpg git" #IDM_MOD_TOMB_DEPS="s3 id gpg git"
IDM_MOD_TAGS="id tool" #IDM_MOD_TAGS="id tool"
IDM_MOD_PROG="safe yadm" #IDM_MOD_PROG="safe yadm"
IDM_MOD_PREF="core id" #IDM_MOD_PREF="core id"
#
IDM_DISABLE_AUTO+=" tomb__enable tomb__disable tomb__kill " #IDM_DISABLE_AUTO+=" tomb__enable tomb__disable tomb__kill "
#
## Environments ## Environments

View File

@ -6,19 +6,29 @@ IDM_BIN=${IDM_BIN:-idmgr}
i () i ()
{ {
local IDM_SRC_IDS=$($IDM_BIN id names)
local result=
local idents=$()
local id=
for id in $( find $IDM_DIR_ID -type f -name '*.env' 2>/dev/null ); do
id=${id##*/}
idents="${idents:+$idents }${id%%\.env}"
done
if grep -q ":${1:-NONE}:" <<<"${IDM_SRC_WORDS}"; then local patterns=" ${IDM_SRC_WORDS} ${IDM_SRC_IDS} $idents"
if grep -q " ${1:-NONE} " <<<" $patterns "; then
result="$( $IDM_BIN $@)" result="$( $IDM_BIN $@)"
# Debug module # Debug module
if [ "${ID_DEBUG-}" == "true" ]; then if [ "${IDM_DEBUG-}" == "true" ]; then
>&2 echo "DEBUG: Source: $IDM_BIN $@"
if [ "${result:-NONE}" == "NONE" ]; then if [ "${result:-NONE}" == "NONE" ]; then
echo "======= ${result:-NONE}" >&2 echo "DEBUG: ======= ${result:-NONE}"
else else
echo ======= Shell has sourced ======= >&2 echo "DEBUG: ======= Shell has sourced ======="
echo "${result:-NONE}" echo "${result:-NONE}"
echo ======= >&2 echo "DEBUG: ======="
fi fi
fi fi
@ -26,149 +36,43 @@ i ()
eval "$result" eval "$result"
else else
if [ "${IDM_DEBUG-}" == "true" ]; then
>&2 echo "DEBUG: Command: $IDM_BIN $@"
>&2 echo "DEBUG: ======="
fi
$IDM_BIN $@ $IDM_BIN $@
fi fi
} }
i_restore_last_id ()
{
[[ "$IDM_LAST_ID_AUTOLOAD" == 'true' ]] || return 0
# Restore from SHELL_ID
if [[ -n "${SHELL_ID:-}" ]]; then
i enable $SHELL_ID
return
fi
# Restore from last loaded shell
local IDM_DIR_CACHE=${IDM_DIR_CACHE:-${XDG_CACHE_HOME:-~/.cache}/idmgr}
local state_file=$IDM_DIR_CACHE/last_id
if [ -f "$state_file" ]; then
local id=$(cat "$state_file")
if ! [ -z "${id//_/}" ]; then
# BUG: Should not reload if already loaded !!!!
>&2 echo "INFO: Auto enabling last id: $id"
i enable $id
fi
fi
}
# Disable when pressing C-b in shell :) # Disable when pressing C-b in shell :)
bind -x '"\C-b": i disable' bind -x '"\C-b": i disable'
i_restore_last_id
# completion file for bash
# Copyright (C) 2012 - 2014 Jason A. Donenfeld <Jason@zx2c4.com> and
# Brian Mattern <rephorm@rephorm.com>. All Rights Reserved.
# This file is licensed under the GPLv2+. Please see COPYING for more information.
_pass_complete_entries () {
prefix="${PASSWORD_STORE_DIR:-$HOME/.password-store/}"
prefix="${prefix%/}/"
suffix=".gpg"
autoexpand=${1:-0}
local IFS=$'\n'
local items=($(compgen -f $prefix$cur))
# Remember the value of the first item, to see if it is a directory. If
# it is a directory, then don't add a space to the completion
local firstitem=""
# Use counter, can't use ${#items[@]} as we skip hidden directories
local i=0
for item in ${items[@]}; do
[[ $item =~ /\.[^/]*$ ]] && continue
# if there is a unique match, and it is a directory with one entry
# autocomplete the subentry as well (recursively)
if [[ ${#items[@]} -eq 1 && $autoexpand -eq 1 ]]; then
while [[ -d $item ]]; do
local subitems=($(compgen -f "$item/"))
local filtereditems=( )
for item2 in "${subitems[@]}"; do
[[ $item2 =~ /\.[^/]*$ ]] && continue
filtereditems+=( "$item2" )
done
if [[ ${#filtereditems[@]} -eq 1 ]]; then
item="${filtereditems[0]}"
else
break
fi
done
fi
# append / to directories
[[ -d $item ]] && item="$item/"
item="${item%$suffix}"
COMPREPLY+=("${item#$prefix}")
if [[ $i -eq 0 ]]; then
firstitem=$item
fi
let i+=1
done
# The only time we want to add a space to the end is if there is only
# one match, and it is not a directory
if [[ $i -gt 1 || ( $i -eq 1 && -d $firstitem ) ]]; then
compopt -o nospace
fi
}
_pass_complete_folders () {
prefix="${PASSWORD_STORE_DIR:-$HOME/.password-store/}"
prefix="${prefix%/}/"
local IFS=$'\n'
local items=($(compgen -d $prefix$cur))
for item in ${items[@]}; do
[[ $item == $prefix.* ]] && continue
COMPREPLY+=("${item#$prefix}/")
done
}
_pass_complete_keys () {
local IFS=$'\n'
# Extract names and email addresses from gpg --list-keys
local keys="$(gpg2 --list-secret-keys --with-colons | cut -d : -f 10 | sort -u | sed '/^$/d')"
COMPREPLY+=($(compgen -W "${keys}" -- ${cur}))
}
_pass()
{
COMPREPLY=()
local cur="${COMP_WORDS[COMP_CWORD]}"
local commands="init ls find grep show insert generate edit rm mv cp git help version"
if [[ $COMP_CWORD -gt 1 ]]; then
local lastarg="${COMP_WORDS[$COMP_CWORD-1]}"
case "${COMP_WORDS[1]}" in
init)
if [[ $lastarg == "-p" || $lastarg == "--path" ]]; then
_pass_complete_folders
compopt -o nospace
else
COMPREPLY+=($(compgen -W "-p --path" -- ${cur}))
_pass_complete_keys
fi
;;
ls|list|edit)
_pass_complete_entries
;;
show|-*)
COMPREPLY+=($(compgen -W "-c --clip" -- ${cur}))
_pass_complete_entries 1
;;
insert)
COMPREPLY+=($(compgen -W "-e --echo -m --multiline -f --force" -- ${cur}))
_pass_complete_entries
;;
generate)
COMPREPLY+=($(compgen -W "-n --no-symbols -c --clip -f --force -i --in-place" -- ${cur}))
_pass_complete_entries
;;
cp|copy|mv|rename)
COMPREPLY+=($(compgen -W "-f --force" -- ${cur}))
_pass_complete_entries
;;
rm|remove|delete)
COMPREPLY+=($(compgen -W "-r --recursive -f --force" -- ${cur}))
_pass_complete_entries
;;
git)
COMPREPLY+=($(compgen -W "init push pull config log reflog rebase" -- ${cur}))
;;
esac
else
COMPREPLY+=($(compgen -W "${commands}" -- ${cur}))
_pass_complete_entries 1
fi
}
complete -o filenames -F _pass pass
# Show current identities
echo "INFO: idmgr has been loaded, use 'idmgr' or 'i' to call it"
#$IDM_BIN id ls

62
shell/bash/startup.sh Normal file
View File

@ -0,0 +1,62 @@
#!/bin/bash
idmgr_shell_words ()
{
# Generate command/ids list to be sourced
local IDM_SRC_CMDS='enable disable kill shell quit e d k s q'
local IDM_SRC_IDS=$(find "$XDG_CONFIG_HOME/idmgr/id/" \
-type f -name "*.env" \
-printf "%f " | sed 's/\.env//g')
echo "$IDM_SRC_CMDS $IDM_SRC_IDS"
}
idmgr_shell ()
{
IDM_SRC_WORDS="${IDM_SRC_WORDS:-$(idmgr_shell_words)}"
# Check if must be sourced or not
if [[ "${IDM_SRC_WORDS// /:}" =~ :$1: ]]; then
# Get output source
>&2 echo "INFO : Running sourced command ..."
shell_exec="$( command idmgr $@)"
# Debug module
if [ "${ID_DEBUG-}" == "true" ]; then
if [ "${shell_exec:-NONE}" == "NONE" ]; then
echo "======= ${shell_exec:-NONE}"
else
echo ======= Shell has sourced =======
echo "${shell_exec:-NONE}"
echo =======
fi
fi
# Exec output
eval "$shell_exec"
else
# Execute as regular command
command idmgr $@
fi
}
# Set aliases
alias idmgr='idmgr_shell'
alias i='idmgr'
# Save current state
export PS1="$PS1"
export IDM_SHELL_PS1=${IDM_SHELL_PS1:-${PS1-}}
# Disable when pressing C-b in shell :)
bind -x '"\C-b": i disable'
# Show current identities
echo "INFO: idmgr has been loaded, use 'idmgr' or 'i' to call it"
idmgr id ls