Add some helper functions to interact with pass
This commit is contained in:
parent
96ee23d777
commit
0419c90c9b
1 changed files with 65 additions and 0 deletions
65
modules/ordo/password-store.scm
Normal file
65
modules/ordo/password-store.scm
Normal file
|
@ -0,0 +1,65 @@
|
|||
(define-module (ordo password-store)
|
||||
#:use-module (ice-9 exceptions)
|
||||
#:use-module (ice-9 format)
|
||||
#:use-module (ice-9 popen)
|
||||
#:use-module ((srfi srfi-1) #:select (last))
|
||||
#:use-module ((srfi srfi-9) #:select (define-record-type))
|
||||
#:use-module (ordo util read-lines)
|
||||
#:use-module (ordo util shell-quote)
|
||||
#:export (make-password-store
|
||||
get-password
|
||||
generate-password))
|
||||
|
||||
(define-exception-type &password-store-error &external-error
|
||||
make-password-store-error
|
||||
password-store-error?
|
||||
(message password-store-error-message)
|
||||
(cause password-store-error-cause))
|
||||
|
||||
(define-record-type <password-store>
|
||||
(make-password-store dir)
|
||||
password-store?
|
||||
(dir password-store-dir))
|
||||
|
||||
(define (pass-command store . args)
|
||||
(let ((base-cmd (if (password-store-dir store)
|
||||
(format #f "env PASSWORD_STORE_DIR=~a pass" (string-shell-quote (password-store-dir store)))
|
||||
"pass")))
|
||||
(string-append base-cmd
|
||||
" "
|
||||
(string-join (map string-shell-quote args) " ")
|
||||
" 2>&1")))
|
||||
|
||||
(define (get-password store path)
|
||||
(let* ((command (pass-command store "show" path))
|
||||
(port (open-input-pipe command))
|
||||
(data (read-lines port))
|
||||
(status (close-pipe port)))
|
||||
(unless (zero? (status:exit-val status))
|
||||
(raise-exception (make-password-store-error (format #f "Error getting password ~a" path) data)))
|
||||
(car data)))
|
||||
|
||||
(define (password-exists? store path)
|
||||
(and (false-if-exception (get-password store path)) #t))
|
||||
|
||||
(define* (generate-password store path #:key (overwrite? #f) (password-length 25))
|
||||
;; WARNING: there is a race condition here between checking the password
|
||||
;; exists and calling pass generate to create it. We have to pass the
|
||||
;; -f option to generate in case we hit this race condition, when pass will prompt
|
||||
;; for confirmation to overwrite an existing file. With the -f option, we will
|
||||
;; go ahead and overwrite it, which seems the lesser of two evils.
|
||||
(unless (or overwrite? (not (password-exists? store path)))
|
||||
(raise-exception (make-password-store-error (format #f "Error generating password ~a" path)
|
||||
"Password already exists")))
|
||||
(let* ((command (pass-command store "generate" "-f" path (number->string password-length)))
|
||||
(port (open-input-pipe command))
|
||||
(data (read-lines port))
|
||||
(status (close-pipe port)))
|
||||
(unless (zero? (status:exit-val status))
|
||||
(raise-exception (make-password-store-error (format #f "Error generating password for ~a" path) data)))
|
||||
(let ((password (last data)))
|
||||
;; Pass wraps the generated password in an escape sequence to change the
|
||||
;; displayed colour: we strip this from the result.
|
||||
(define prefix-len (string-length "\x1b[1m\x1b[93m"))
|
||||
(define suffix-len (string-length "\x1b[0m"))
|
||||
(substring password prefix-len (- (string-length password) suffix-len)))))
|
Loading…
Add table
Add a link
Reference in a new issue