function zssh_boot() { typeset -g zssh_ssh_dotdir="${HOME}/.ssh" typeset -g zssh_private_keys="${zssh_ssh_dotdir}/keystore" typeset -g zssh_private_configs="${zssh_ssh_dotdir}/config.d" typeset -g zssh_global_configs=${globaldots_path}/config/ssh typeset -g zssh_global_pubkeys=${globaldots_path}/keys/ssh zssh_configure zssh_process } function zssh_configure () { if [[ -n "$zssh_host" ]] then zbootstrap_message zssh "zssh_host is set" ztools_ensure -d $zssh_private_keys ztools_ensure -d $zssh_private_configs ztools_ensure -d ${zssh_global_configs} ztools_ensure -d ${zssh_global_pubkeys} zssh_enumeratenodes if [[ ${#zssh_host_config_accesses} -gt 0 ]] then zbootstrap_message zssh "zssh_host_config_accesses is set" typeset -g zssh_global_config_hostdir="${zssh_global_configs}/${zssh_host}" typeset -g zssh_global_pubkey_hostdir="${zssh_global_pubkeys}/${zssh_host}" ztools_ensure -d "${zssh_global_pubkey_hostdir}" ztools_ensure -d "${zssh_global_config_hostdir}" else zbootstrap_message zssh "zssh_host_config_accesses is NOT set, not going to bother accepting keys" fi else zbootstrap_message zssh "zssh_host is NOT set, which means we cannot neither publish keys nor accept them" fi } function zssh_process() { if [[ -n "$zssh_host" ]] then if [[ ${#zssh_host_config_accesses} -gt 0 ]] then zbootstrap_message zssh "processing ssh server setup" if [[ "${HOME}/.config/zsh/local.config.zsh" -nt "${zssh_global_config_hostdir}" ]] then zbootstrap_message zssh "publishing our configs …" zssh_publish_configs else zbootstrap_message zssh "not publishing our configs …" fi fi zbootstrap_message zssh "processing ssh client setup" zssh_install_peers zssh_publish_pubkeys fi } function zssh_install_peers() { [[ -n $zssh_host ]] || return 63 zbootstrap_message zssh "installing peers" for ssh_node in $zssh_nodes do zbootstrap_message zssh "installing peer $ssh_node …" zssh_generate_privkey4 $ssh_node zssh_generate_config4 $ssh_node done } function zssh_publish_pubkeys() { for ssh_node in $zssh_nodes do zssh_mail_pubkey2 $ssh_node done } function zssh_mail_pubkey2() { [[ -n $zssh_host ]] || return 63 ssh_node="$1" local targetspool="$zssh_global_pubkeys/$ssh_node" local srcpk="$zssh_private_keys/$ssh_node.key.pub" ztools_ensure -d "${targetspool}" cp -t "$targetspool" "$srcpk" } function zssh_publish_configs() { [[ -n "$zssh_host_config_accesses" ]] || return 62 for sshmatch in ${(k)zssh_host_config_accesses} do hostaccessconfig_file="${zssh_global_config_hostdir}/${sshmatch}.sshconf" zbootstrap_message zssh "generating our server access config '${hostaccessconfig_file}'" zssh_generate_hostaccessconfig $sshmatch > "$hostaccessconfig_file" done zbootstrap_message zssh "updating mtime for ${zssh_global_config_hostdir}" touch "${zssh_global_config_hostdir}" } function zssh_generate_hostaccessconfig() { sshmatch="${1}" sshcontents=${zssh_host_config_accesses[$sshmatch]} sshmatch_user=${sshmatch%%@*} sshmatch_host=${sshmatch##*@} if [[ "$sshmatch_host" == "$sshmatch_user" ]] then sshmatch_user='' fi << HERE Match ${sshmatch_host:+host $sshmatch_host,} ${sshmatch_user:+user $sshmatch_user,} ${sshcontents} ${zssh_host_config} HERE } function zssh_generate_config4 { ssh_node="$1" dst="$zssh_private_configs/$ssh_node.sshconf" srcs="$zssh_global_configs/$ssh_node" zbootstrap_message zssh "checking configs for $ssh_node …" if [[ -d "$srcs" ]] && ! [[ $dst -nt $srcs ]] then sshkey="$zssh_private_keys/$ssh_node.key" zbootstrap_message zssh "found fresh configs directory for $ssh_node" zbootstrap_message zssh "config destination is '$dst'" zbootstrap_message zssh "tied ssh key is '$sshkey'" rm "$dst" 2> /dev/null for src in "$srcs"/*.sshconf(N) do zbootstrap_message zssh "sourcing $src" cat "$src" >> "$dst" printf "\n IdentityFile %s\n\n" "$sshkey" >> "$dst" done fi zbootstrap_message zssh "done with $ssh_node" } function zssh_generate_privkey4 { ssh_node="$1" zbootstrap_message zssh "checking keys for peer $ssh_node …" local newkey=$zssh_private_keys/$ssh_node.key if ! [[ -s $newkey ]] then zbootstrap_message zssh "generate key for $ssh_node" ssh-keygen -t ed25519 -N '' -C "$ssh_host($USER@$HOST) for $ssh_node" -f $newkey >> "${HOME}/.log/ssh-keygen.log" if [[ "$ssh_node" == "$zssh_host" ]] then zbootstrap_message zssh "Self accepting key: $ssh_node" cat "$newkey.pub" >> ${HOME}/.ssh/authorized_keys fi fi } function zssh_offer_all() { # offers keys for every node if ! [[ -d $zssh_private_keys ]] then zbootstrap_message zssh "$zssh_private_keys not found" return fi if [[ -n $zssh_thishost ]] then for ssh_node in $zssh_nodes do local node_directory=$zssh_global_configs/$ssh_node local keytooffer=$node_directory/keyoffers/$zssh_thishost.pub local keysource=$zssh_private_keys/$ssh_node.key if ! [[ -s $keysource ]] then zbootstrap_message zssh "$ssh_node misses $keysource private key in keystore" continue fi if ! [[ -d $node_directory ]] then zbootstrap_message zssh "$ssh_node misses its config directory '$node_directory'" continue fi if ! [[ -d $node_directory/keyoffers ]] then zbootstrap_message zssh "creating keyoffer directory for $ssh_node" mkdir $node_directory/keyoffers fi # offering ... if ! [[ -s $keytooffer ]] then zbootstrap_message zssh "Offering public key for $ssh_node" ssh-keygen -y -f $keysource -C "$zssh_thishost offered to ${ssh_node}" > $keytooffer fi done else zbootstrap_message zssh "no zssh_thishost defined, offering skipped" fi } function zssh_accept_key() { local offered=$zssh_global_configs/$zssh_thishost/keyoffer/$1.pub cat $offered echo "do you accept key '$1'? :" read if [[ $REPLY == 'Y' ]] then echo "key $1 accepted" cat $offered >> ${HOME}/.ssh/authorized_keys else echo "key $1 NOT accepted" fi } function zssh_enumeratenodes() { typeset -g -a zssh_nodes; zbootstrap_message zssh "enumerating nodes" if [[ -d $zssh_global_configs ]] then for __ssh_node in ${zssh_global_configs}/*(/) do zssh_nodes+=($(basename $__ssh_node)) done fi zbootstrap_message zssh "got ${#zssh_nodes} nodes" }