Modularize SSH key-file utility functions to increase reusability

This commit is contained in:
Daniel - 2023-07-16 10:14:43 +02:00
parent 82e50e8e22
commit c43291d23b
Signed by: dbo
GPG Key ID: 784AA8DF0CCDF625
1 changed files with 27 additions and 28 deletions

View File

@ -841,7 +841,6 @@ This is `db-light' and `solarized-light'."
PASSWORD-FN is supposed to be a function returning the password PASSWORD-FN is supposed to be a function returning the password
for KEY-FILE." for KEY-FILE."
;; XXX: check whether the key is already loaded in the current agent.
(with-environment-variables (("SSH_ASKPASS_REQUIRE" "never")) (with-environment-variables (("SSH_ASKPASS_REQUIRE" "never"))
(let* ((key-file (expand-file-name key-file)) (let* ((key-file (expand-file-name key-file))
(proc (make-process :name "ssh-add" (proc (make-process :name "ssh-add"
@ -875,26 +874,22 @@ for KEY-FILE."
(while (process-live-p proc) (while (process-live-p proc)
(sit-for 0.2))))) (sit-for 0.2)))))
(defun db/-filter-already-loaded-ssh-keys (key-entries) (defun db/ssh-key-hash-from-filename (key-file)
"Filter those values in KEY-ENTRIES that corresponed to loaded SSH keys. "Return the SHA256 hash value of the SSH key located in KEY-FILE.
KEY-ENTRIES is a list of values as specified for Return nil if KEY-FILE is not readable or does not contain an SSH key."
`db/known-ssh-keys'. This function then returns a list of those (let* ((key-file (expand-file-name key-file)))
entries whose SSH keys are not yet loaded in the currently (and (file-exists-p key-file)
running ssh-agent." (file-readable-p key-file)
(let ((loaded-ssh-keys (mapcar #'(lambda (line) (->> (shell-command-to-string (format "ssh-keygen -l -E sha256 -f %s" key-file))
(cl-second (split-string line))) (split-string)
(split-string (shell-command-to-string "ssh-add -l") "\n" t)))) (cl-second)))))
(cl-remove-if #'(lambda (key-entry)
(let* ((key-file (expand-file-name (car key-entry)))) (defun db/ssh-loaded-key-hashes ()
(and (file-exists-p key-file) "Return list of SHA256 hash values of all keys that are currently loaded."
(file-readable-p key-file) (mapcar #'(lambda (line)
(let ((key-hash (->> (shell-command-to-string (format "ssh-keygen -l -f %s" key-file)) (cl-second (split-string line)))
(split-string) (split-string (shell-command-to-string "ssh-add -E sha256 -l") "\n" t)))
(cl-second))))
(cl-member key-hash loaded-ssh-keys
:test #'string=)))))
key-entries)))
(defcustom db/known-ssh-keys nil (defcustom db/known-ssh-keys nil
"A alist mapping SSH key-files to their password entries. "A alist mapping SSH key-files to their password entries.
@ -915,15 +910,19 @@ holding the password to unlock the key."
(defun db/load-known-ssh-keys () (defun db/load-known-ssh-keys ()
"Add all keys from `db/known-ssh-keys' to currently running ssh-agent." "Add all keys from `db/known-ssh-keys' to currently running ssh-agent."
;; XXX: error handling
(interactive) (interactive)
(pcase-dolist (`(,ssh-key . ,pass-entry) (db/-filter-already-loaded-ssh-keys db/known-ssh-keys)) (let ((loaded-ssh-key-hashes (db/ssh-loaded-key-hashes)))
(if (not (file-readable-p (expand-file-name ssh-key))) (pcase-dolist (`(,ssh-key . ,pass-entry) db/known-ssh-keys)
(warn "SSH key file %s is not readable or does not exist, skipping" ssh-key) (let ((ssh-key-hash (db/ssh-key-hash-from-filename ssh-key)))
(db/add-ssh-key-with-password ssh-key (cond
#'(lambda () ((null ssh-key-hash)
(apply #'db/password-from-storage pass-entry))))) (warn "SSH key file %s is not readable or does not exist, skipping" ssh-key))
(message "All known SSH keys loaded.")) ((cl-member ssh-key-hash loaded-ssh-key-hashes :test #'string=)
(message "SSH key file %s already loaded, skipping" ssh-key))
(t
(db/add-ssh-key-with-password ssh-key
#'(lambda ()
(apply #'db/password-from-storage pass-entry)))))))))
(cl-defgeneric db/password-from-storage (type entry-key) (cl-defgeneric db/password-from-storage (type entry-key)
"Retrieve password from storage of type TYPE with lookup key ENTRY-KEY.") "Retrieve password from storage of type TYPE with lookup key ENTRY-KEY.")