638 lines
13 KiB
Bash
Executable File
638 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
|
|
## Initialisation
|
|
##########################################
|
|
|
|
# Get the way the script is called
|
|
IDM_PATH=${_:-_none}
|
|
IDM_ARGS=${0-}
|
|
|
|
# Ensure we are running strict mode
|
|
set -euo pipefail
|
|
|
|
# Detect how this script was started
|
|
if [[ $IDM_PATH == $IDM_ARGS ]]; then
|
|
IDM_CTX=executed
|
|
else
|
|
IDM_CTX=sourced
|
|
IDM_SOURCED_ARGS=${@:-_none}
|
|
fi
|
|
|
|
# Versionning infos
|
|
IDM_AUTHORS='mrjk'
|
|
IDM_VERSION='0.1 (beta)'
|
|
IDM_DATE='03/01/18'
|
|
IDM_LICENSE='MIT'
|
|
IDM_SCRIPT_NAME=idmgr
|
|
|
|
# Global app variables
|
|
IDM_BIN=${IDM_BIN:-$0}
|
|
IDM_DIR_ROOT=${IDM_DIR_ROOT:-$( realpath "$(dirname $(realpath $0))/../" )}
|
|
|
|
IDM_ID_ENV_DIR=${IDM_ID_ENV_DIR:-${XDG_CONFIG_HOME:-~/.config}/idmgr}
|
|
IDM_DIR_ID=${IDM_DIR_ID:-$IDM_ID_ENV_DIR/id}
|
|
IDM_DIR_LIB=${IDM_DIR_LIB:-$IDM_DIR_ROOT/lib}
|
|
IDM_DIR_CACHE=${IDM_DIR_CACHE:-${XDG_CACHE_HOME:-~/.cache}/idmgr}
|
|
|
|
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 ...
|
|
IDM_DISABLE_AUTO=
|
|
IDM_ID_ENV=
|
|
|
|
|
|
|
|
## Base CLI commands
|
|
##########################################
|
|
|
|
# Required libs:
|
|
# idm_core
|
|
|
|
idm_core__help ()
|
|
{
|
|
echo ""
|
|
echo " idmgr - Identity Manager for your shell"
|
|
echo ""
|
|
echo "Introduction:"
|
|
echo " Identity Manager can manage your ssh keys, your pass,"
|
|
echo " your pgp keys, kerberos and many other related identity item."
|
|
echo ""
|
|
echo "Sourced commands:"
|
|
printf " %-20s: %s\n" "enable [id]" "Enable (and start) id"
|
|
printf " %-20s: %s\n" "disable [id]" "Disable id"
|
|
printf " %-20s: %s\n" "kill [id]" "Kill id and its processes"
|
|
echo
|
|
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)"
|
|
|
|
local mods=$(idm_lib_order_get status)
|
|
echo
|
|
echo "Loaded mods: $mods"
|
|
|
|
idm_core_exec_mod $id __help "\n%s" $mods
|
|
|
|
echo
|
|
lib_log NOTICE "License:"
|
|
echo " $IDM_VERSION, $IDM_DATE"
|
|
echo " $IDM_LICENSE, $IDM_AUTHORS"
|
|
|
|
}
|
|
|
|
idm_core__ls ()
|
|
{
|
|
local id=${1}
|
|
idm_core_exec_mod $id __ls "%s ls" $(idm_lib_order_get status)
|
|
}
|
|
|
|
|
|
idm_core__enable ()
|
|
{
|
|
local id=${1:-${SHELL_ID-}}
|
|
|
|
# Local checks
|
|
lib_id_has_config $id || idm_exit 1 ERR "Configuration '$id' does not exists"
|
|
|
|
# Check if workspace is enabled
|
|
if [ "${SHELL_ID-}" == "$id" ]; then
|
|
lib_log WARN "Your workspace is already activated"
|
|
elif [ -n "${SHELL_ID-}" ]; then
|
|
lib_log WARN "Changing $SHELL_ID workspace to $id"
|
|
$IDM_BIN disable "${SHELL_ID-}"
|
|
fi
|
|
|
|
# Notice user
|
|
{
|
|
# Reload user config
|
|
. "$IDM_ID_ENV"
|
|
idm_core_exec_mod $id __enable "Enabling %s ..." $(idm_lib_order_get enable)
|
|
} # | lib_log DUMP -
|
|
|
|
lib_log NOTICE "Identity '$id' is loaded"
|
|
|
|
}
|
|
|
|
idm_core__disable ()
|
|
{
|
|
local id=${1}
|
|
lib_id_is_enabled $id
|
|
idm_core_exec_mod $id __disable "Disabling %s ..." $(idm_lib_order_get disable)
|
|
lib_log NOTICE "Identity '$id' is unloaded"
|
|
}
|
|
|
|
idm_core__kill ()
|
|
{
|
|
local id=${1}
|
|
lib_id_is_enabled $id
|
|
idm_core_exec_mod $id __disable "Killing %s ..." $(idm_lib_order_get disable)
|
|
lib_log NOTICE "Id $id has been safely killed"
|
|
}
|
|
|
|
|
|
|
|
## Shell integration CLI commands
|
|
##########################################
|
|
|
|
idm_core__shell ()
|
|
{
|
|
|
|
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 $(lib_id_get_all_id | xargs)'"
|
|
|
|
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
|
|
}
|
|
|
|
|
|
## Debugging CLI commands
|
|
##########################################
|
|
|
|
|
|
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 -
|
|
|
|
}
|
|
|
|
idm_core__hier ()
|
|
{
|
|
idm_core__fun \
|
|
| grep __ \
|
|
| sed -e 's/__/ /' -e 's/()//'
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
## 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 ()
|
|
{
|
|
#p=$IDM_DIR_ROOT/lib ${PATH//:/ }
|
|
local p=$IDM_DIR_LIB
|
|
find $p -name 'idmgr_mod_*.sh' | xargs
|
|
}
|
|
|
|
|
|
# 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
|
|
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
|
|
##########################################
|
|
|
|
# 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 ()
|
|
{
|
|
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
|
|
|
|
# Skip if disabled ...
|
|
[[ ":${IDM_DISABLE_AUTO// /:}" =~ :${i}${action}: ]] && continue
|
|
|
|
export IDM_MOD_EXEC=chain
|
|
local rc=0
|
|
out="$( ${val} $id || rc=$? )"
|
|
|
|
if [ "$rc" -eq 0 -a ! -z "$out" ]; then
|
|
[ "$sep" == "_" ] ||
|
|
lib_log NOTICE "$(printf "$sep" $i )"
|
|
echo -e "$out\n"
|
|
elif [ "$rc" -ne 0 ]; then
|
|
lib_log WARN "Module $i failed in some way ... ($action)"
|
|
echo -e "$out\n"
|
|
fi
|
|
|
|
else
|
|
echo ""
|
|
lib_log INFO "Skip module $i"
|
|
fi
|
|
done
|
|
}
|
|
|
|
|
|
## Application exit teardown
|
|
##########################################
|
|
|
|
# Required libs:
|
|
# idm_std
|
|
|
|
# Call this function to exit main cli. You can
|
|
# give some parameters as well. It use
|
|
# lib_log to display error messages. Usage examples:
|
|
# idm_exit rc lvl msg
|
|
# idm_exit rc msg
|
|
# idm_exit
|
|
|
|
|
|
idm_exit ()
|
|
{
|
|
local rc=${1:-0}
|
|
local msg lvl
|
|
|
|
# Check exit status
|
|
if [ "$#" -eq 3 ]; then
|
|
lvl=${2:-DEBUG}
|
|
msg=${3:-}
|
|
else
|
|
lvl=DEBUG
|
|
msg=${2:-}
|
|
fi
|
|
|
|
if [[ "$rc" -ne 0 ]]; then
|
|
#lib_trace || true
|
|
lib_log $lvl "$msg (rc=$rc)"
|
|
#[ -z "$dump" ] || \
|
|
# lib_log DUMP "$dump"
|
|
else
|
|
lib_log $lvl "$msg"
|
|
fi
|
|
|
|
# Remove trap to avoid to be called for normal and exit for good
|
|
trap "" INT TERM EXIT
|
|
exit $rc
|
|
}
|
|
|
|
# Script called when the script quits unexpectedly.
|
|
# Pretty useful for debugginf purpose.
|
|
idm_exit_trap () {
|
|
local rc=$?
|
|
set +x
|
|
|
|
if [[ $rc -ne 0 ]]; then
|
|
lib_log ERR "The script exited with exit code: $rc"
|
|
lib_trace || true
|
|
#else
|
|
#lib_log INFO "The script exit has been correctly trapped."
|
|
#lib_trace || true
|
|
fi
|
|
exit $rc
|
|
}
|
|
|
|
|
|
## Compat
|
|
##########################################
|
|
|
|
# This function display a user skippable timeout.
|
|
idm_cli_timeout ()
|
|
{
|
|
lib_log WARN "Deprecated use of idm_cli_timeout ..."
|
|
lib_cli_timeout $@
|
|
}
|
|
|
|
|
|
|
|
## 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
|
|
##########################################
|
|
|
|
# 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 disaply 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 gpg 11 89 11
|
|
#idm_lib_order_set git 50 50 50
|
|
#idm_lib_order_set tomb 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
|
|
|
|
local menu=
|
|
local action=
|
|
local id=
|
|
local opt=
|
|
local shell_id=${SHELL_ID:-_}
|
|
|
|
idm_core_init
|
|
|
|
# Three way parsing
|
|
local dep_order="$(idm_lib_order_get enable)"
|
|
if [ "$#" -eq 0 ]; then
|
|
|
|
if [ -z "${SHELL_ID-}" ]; then
|
|
# Not activated, show all ids
|
|
menu=id
|
|
action=ls
|
|
id=_
|
|
else
|
|
# Activated, show all id settings
|
|
menu=core
|
|
action=ls
|
|
id=$shell_id
|
|
fi
|
|
|
|
else
|
|
|
|
# Check id constraint
|
|
if lib_id_has_config ${1} &>/dev/null ; then
|
|
menu=core
|
|
action=enable
|
|
id=$1
|
|
elif lib_id_has_config ${2-_} &>/dev/null ; then
|
|
menu=core
|
|
action=$1
|
|
id=$2
|
|
shift 2 && opt=${@} || true
|
|
elif lib_id_has_config ${3-_} &>/dev/null ; then
|
|
menu=$1
|
|
action=$2
|
|
id=$3
|
|
shift 3 && opt=${@} || true
|
|
|
|
# Check mod contraint
|
|
elif [[ ":${dep_order// /:}:" =~ :$1: ]]; then
|
|
menu=$1
|
|
action=${2:-ls}
|
|
id=$shell_id
|
|
shift 2 && opt=${@} || true
|
|
|
|
# Free form
|
|
else
|
|
if [ "$#" -eq 1 ]; then
|
|
menu=core
|
|
action=${1}
|
|
id=$shell_id
|
|
# elif [ "$#" -eq 2 ]; then
|
|
# menu=${1}
|
|
# action=${2}
|
|
# id=$shell_id
|
|
# shift 2 && opt=${@} || true
|
|
else
|
|
menu=${1}
|
|
action=${2}
|
|
id=$shell_id
|
|
shift 2 && opt=${@} || true
|
|
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Aliases
|
|
case $action in
|
|
--help|-h)
|
|
action=help
|
|
;;
|
|
quit|q)
|
|
action=disable
|
|
;;
|
|
esac
|
|
|
|
# Retrieve environment config
|
|
local IDM_ID_ENV="$IDM_DIR_ID/$id.env"
|
|
if [[ -f "$IDM_ID_ENV" ]]; then
|
|
. "$IDM_ID_ENV"
|
|
fi
|
|
|
|
# Dispatch
|
|
#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
|
|
idm_${menu} ${action:-_} $id $opt
|
|
return $?
|
|
fi
|
|
|
|
idm_exit 1 "Command not matched: menu=$menu action=$action id=$id opt=$opt"
|
|
}
|
|
|
|
|
|
## Main
|
|
##########################################
|
|
|
|
idm_core_cli $@
|
|
|