Parcourir la source

Simplify ssh-agent script, do not persist in sudo

We no longer support persisting an agent across `sudo`: it is needlessly
insecure and not actually used often. The main benefit of symlinking the
socket is now persisting across multiplexers.

The symlink is now moved to within a user's `.ssh` folder, which
would/should have strict permissions (700).

Of course, the socket itself is still public and so exploitable by any
concurrent user with root access - the standard warning to use
ssh agent forwarding sparingly/only-on-super-trusted-machines applies.
Weiyi Lou il y a 9 ans
Parent
commit
b40fee656f
3 fichiers modifiés avec 70 ajouts et 117 suppressions
  1. 2 2
      shell/common/auto-ssh-hosts.sh
  2. 0 115
      shell/common/ssh-add.sh
  3. 68 0
      shell/common/ssh-agent.sh

+ 2 - 2
shell/common/auto-ssh-hosts.sh

@@ -1,6 +1,6 @@
 # Automagic ssh to known hosts.
 # Configure usernames for hosts in .ssh/config
-autosshhosts() {
+auto_ssh_hosts() {
   local line host
   IFS=$'\n\t'
   for line in $(grep "^[a-zA-Z]" ~/.ssh/known_hosts); do
@@ -11,7 +11,7 @@ autosshhosts() {
 }
 
 if [[ -f ~/.ssh/known_hosts ]]; then
-  autosshhosts
+  auto_ssh_hosts
 fi
 
 # Hosts file

+ 0 - 115
shell/common/ssh-add.sh

@@ -1,115 +0,0 @@
-# Standardize location of the ssh-agent authentication socket.
-# Perform automatic ssh-agent starting and key-loading as necessary.
-#
-# The `SSH_AUTH_SOCK` variable allows users interact with ssh-agent loaded
-# identities. Having this socket linked to a predictable place means a given
-# user can expect loaded identities to persist:
-#  - in tmux, screen and similar multiplexers
-#  - through `sudo su`/`su` to root (BUT NOT with '-' which clears envvars)
-
-# The `ID_FILES` variable contains the standard identity files that ssh-add
-# tries to load. The value can be overridden by simply declaring an alternate
-# array before this script is run i.e. near the top of bashrc/zshrc.
-ID_FILES=(${ID_FILES[@]:-~/.ssh/id_rsa ~/.ssh/id_dsa ~/.ssh/id_ecdsa ~/.ssh/identity})
-
-function agent_setup() {
-  # Try to reach an existing socket.
-  linksocket
-
-  # If that does not work, try to reach the socket of the sudo user.
-  if ! agent_available; then
-    linksocket_sudo
-  fi
-
-  # If nothing worked, a no valid socket is found. If there are any identities
-  # available, create a new agent.
-  if ! agent_available && ids_available; then
-    start_sshagent
-    linksocket
-  fi
-
-  # If the agent is empty, add identities with the default file names.
-  if ! ids_loaded && ids_available; then
-    ssh-add $ID_FILES 2> /dev/null
-  fi
-
-  # The End
-}
-
-# Start a new ssh-agent process.
-function start_sshagent() {
-  echo "Starting a new SSH Agent."
-  eval `ssh-agent` &> /dev/null
-}
-
-# Link up an existing socket to the expected location if it is not already.
-#
-# Also, if the socket in the environment is a symlink, try to get to the actual
-# socket itself.
-function linksocket() {
-  local link="/tmp/ssh-agent-$USER-tmux"
-  if [[ ! -z $SSH_AUTH_SOCK && $SSH_AUTH_SOCK != $link ]]; then
-    local target=$SSH_AUTH_SOCK
-    [[ -L $SSH_AUTH_SOCK ]] && target=`readlink $SSH_AUTH_SOCK`
-    [[ -e $target ]] && ln -sf $target $link &> /dev/null
-  fi
-  export SSH_AUTH_SOCK=$link
-}
-
-# If we detect sudo, try to link the current user (usually root) to the sudo
-# user's socket directly
-#
-# A user cannot access another user's socket using a symlink, even if that user
-# has super privileges. They can, however reach that socket directly, so a
-# personal symlink is attempted.
-function linksocket_sudo() {
-  local linksudo="/tmp/ssh-agent-$SUDO_USER-tmux"
-  if [[ ! -z $SUDO_USER && -L $linksudo ]]; then
-    local link="/tmp/ssh-agent-$USER-tmux"
-    ln -sf `readlink $linksudo` $link &> /dev/null
-    export SSH_AUTH_SOCK=$link
-  fi
-}
-
-# Check if there is a usable ssh-agent.
-#
-# `ssh-add`'s return value `2` means it was unable to contact an agent.
-# Return values:
-#   0 = success, agent contacted.
-#   1 = failed to connect to an agent.
-function agent_available() {
-  ssh-add -l &> /dev/null
-  [[ $? -eq 2 ]] && return 1 || return 0
-}
-
-# Check if there are identities to load.
-#
-# Return values:
-#   0 = success, found a file.
-#   1 = failed to match any files.
-function ids_available() {
-  for file in $ID_FILES; do
-    [[ -f $file ]] && return 0
-  done
-  return 1
-}
-
-# Check if there are any identities already loaded
-#
-# Return values:
-#   0 = success, there are ids loaded into the current agent.
-#   1 = failed, there are none.
-function ids_loaded() {
-  [[ `ssh-add -L 2> /dev/null | grep "^ssh-" | wc -l` -eq 0 ]] && return 1 || return 0
-}
-
-# Go!
-agent_setup
-
-# Clean up scripts which should not be used after setup. Leave `start_sshagent`.
-unset -f agent_setup
-unset -f linksocket
-unset -f linksocket_sudo
-unset -f agent_available
-unset -f ids_available
-unset -f ids_loaded

+ 68 - 0
shell/common/ssh-agent.sh

@@ -0,0 +1,68 @@
+# Start ssh-agent and load available identities. Standardize location of the
+# ssh-agent authentication socket.
+#
+# `$SSH_AUTH_SOCK` is an environment variable set by `ssh-agent`, that points to
+# a socket that allows users to connect to it. This script symlinks the socket
+# to a predefined location (in a user's `.ssh` folder) so that a user's
+# different shell instances (e.g. in screen or tmux) can be automatically
+# connected to that same agent.
+
+# Override `$KEY_FILES` before this script is loaded to specify which identities
+# to load. Defaults to `ssh-add`'s standard files.
+[[ ${#KEY_FILES[@]} = 0 ]] && KEY_FILES=(~/.ssh/id_rsa ~/.ssh/id_dsa ~/.ssh/id_ecdsa ~/.ssh/identity)
+
+function agent_setup() {
+  # Run if ssh is installed.
+  command -v ssh >/dev/null || return
+
+  # Make sure the folder for the symlink exists.
+  mkdir -p ~/.ssh
+
+  # Try to symlink an auth socket, to connect any existing agent.
+  link_socket
+
+  # Check for an agent:
+  # 0 = agent running, has keys.
+  # 1 = agent running, has no keys.
+  # 2 = agent not running.
+  ssh-add -l &>/dev/null
+  case $? in
+    1) has_key_files && add_keys ;;
+    2) has_key_files && start_agent && add_keys ;;
+  esac
+}
+
+# Create a symlink to an existing auth socket.
+function link_socket() {
+  local target="$SSH_AUTH_SOCK"
+  local link="$HOME/.ssh/authsock"
+  if [[ -n $target && $target != $link ]]; then
+    ln -sf $target $link &>/dev/null
+    export SSH_AUTH_SOCK=$link
+  fi
+}
+
+# Check if there are keys to load on this machine.
+# 0 = found a key file.
+# 1 = did not find any key files.
+function has_key_files() {
+  for file in $KEY_FILES; do
+    [[ -f $file ]] && return 0
+  done
+  return 1
+}
+
+# Add keys to an agent.
+function add_keys() {
+  ssh-add $KEY_FILES 2>/dev/null
+}
+
+# Start a new agent.
+function start_agent() {
+  echo "Starting a new SSH Agent."
+  eval `ssh-agent` &> /dev/null
+  link_socket
+}
+
+# Go!
+agent_setup