You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
3.8 KiB

  1. #!/bin/bash
  2. RSYNC_KEY_PATH=/etc/rsync/keys
  3. ANSI_ESC=$'\e['
  4. NORMAL="${ANSI_ESC}0m"
  5. GRAY="${ANSI_ESC}1;30m"
  6. RED="${ANSI_ESC}1;31m"
  7. GREEN="${ANSI_ESC}1;32m"
  8. YELLOW="${ANSI_ESC}1;33m"
  9. BLUE="${ANSI_ESC}1;34m"
  10. PINK="${ANSI_ESC}1;35m"
  11. CYAN="${ANSI_ESC}1;36m"
  12. WHITE="${ANSI_ESC}1;37m"
  13. DARKGRAY="${ANSI_ESC}0;30m"
  14. DARKRED="${ANSI_ESC}0;31m"
  15. DARKGREEN="${ANSI_ESC}0;32m"
  16. DARKYELLOW="${ANSI_ESC}0;33m"
  17. DARKBLUE="${ANSI_ESC}0;34m"
  18. DARKPINK="${ANSI_ESC}0;35m"
  19. DARKCYAN="${ANSI_ESC}0;36m"
  20. DARKWHITE="${ANSI_ESC}0;37m"
  21. ssh-key-ls() {
  22. local label="$1" f content
  23. for f in "${RSYNC_KEY_PATH}"/backup/"$label"/*.pub; do
  24. [ -e "$f" ] || continue
  25. ident=${f##*/}
  26. ident=${ident%.pub}
  27. content=$(cat "$f")
  28. key=${content#* }
  29. key=${key% *}
  30. printf "${DARKGRAY}..${NORMAL}%24s ${DARKCYAN}%s${NORMAL}\n" "${key: -24}" "$ident"
  31. done
  32. }
  33. ssh-key-rm() {
  34. local label="$1" ident="$2" delete
  35. delete="${RSYNC_KEY_PATH}/backup/$label/$ident.pub"
  36. if ! [ -e "$delete" ]; then
  37. echo "Error: key '$ident' not found." >&2
  38. return 1
  39. fi
  40. rm "$delete"
  41. /usr/local/sbin/ssh-update-keys
  42. }
  43. ssh-key-get-type() {
  44. local label="$1" ident="$2" key content commentary
  45. key="${RSYNC_KEY_PATH}/backup/$label/$ident.pub"
  46. if ! [ -e "$key" ]; then
  47. echo "Error: key '$ident' not found." >&2
  48. return 1
  49. fi
  50. content=$(cat "$key") || return 1
  51. commentary=${content##* }
  52. printf "%s\n" "${commentary%%@*}"
  53. }
  54. ssh-key-add() {
  55. local label="$1" type="$2" key="$3" email="$4"
  56. [ "$type" == "ssh-rsa" ] || {
  57. echo "Error: expecting ssh-rsa key type" >&2
  58. return 1
  59. }
  60. ## ident are unique by construction (they are struct keys)
  61. ## but keys need to be also unique
  62. declare -A keys
  63. content="$type $key $email"
  64. ident="${email##*@}"
  65. target="${RSYNC_KEY_PATH}/backup/$label/$ident.pub"
  66. ## is key used already ? As key give access to a specified subdir,
  67. ## we need to make sure it is unique.
  68. for key_file in "${RSYNC_KEY_PATH}/backup/"*/*.pub; do
  69. [ -e "$key_file" ] || continue
  70. key_content=$(cat "$key_file")
  71. if [ "$type $key" == "${key_content% *}" ]; then
  72. if [ "$key_file" == "$target" ]; then
  73. echo "Provided key already present for '$ident'." >&2
  74. return 0
  75. elif [[ "$key_file" == "${RSYNC_KEY_PATH}/"*"/$label/"*.pub ]]; then
  76. type=${key_file#"${RSYNC_KEY_PATH}/"}
  77. type=${type%"/$label/"*.pub}
  78. key_ident=${key_file##*/}
  79. key_ident=${key_ident%.pub}
  80. echo "Provided key already used as $type key for '$key_ident'." >&2
  81. return 1
  82. else
  83. olabel=${key_file#"${RSYNC_KEY_PATH}/"*/}
  84. olabel=${olabel%/*.pub}
  85. echo "Specified key is already used by '$olabel' account, please pick another one." >&2
  86. return 1
  87. fi
  88. fi
  89. done
  90. mkdir -p "${target%/*}"
  91. if [ -e "$target" ]; then
  92. echo "Replacing key for '$ident'." >&2
  93. elif [ -e "${RSYNC_KEY_PATH}/"*"/"*"/$ident.pub" ]; then
  94. olabel=("${RSYNC_KEY_PATH}/"*"/"*"/$ident.pub")
  95. olabel="${olabel[0]}"
  96. olabel=${olabel#"${RSYNC_KEY_PATH}/"*/}
  97. olabel=${olabel%/*.pub}
  98. echo "ident '$ident' is already reserved by '$olabel', please pick another one." >&2
  99. return 1
  100. fi
  101. echo "$content" > "$target"
  102. /usr/local/sbin/ssh-update-keys
  103. }
  104. case "$1" in
  105. "add")
  106. shift
  107. ssh-key-add "$@"
  108. ;;
  109. "rm")
  110. shift
  111. ssh-key-rm "$@"
  112. ;;
  113. "ls")
  114. shift
  115. ssh-key-ls "$@"
  116. ;;
  117. "get-type")
  118. shift
  119. ssh-key-get-type "$@"
  120. ;;
  121. *)
  122. echo "Unknown command '$1'."
  123. ;;
  124. esac