diff options
-rw-r--r-- | consfigurator.asd | 3 | ||||
-rw-r--r-- | doc/introduction.rst | 44 | ||||
-rw-r--r-- | src/data/ssh-askpass.lisp | 52 | ||||
-rw-r--r-- | src/package.lisp | 4 |
4 files changed, 73 insertions, 30 deletions
diff --git a/consfigurator.asd b/consfigurator.asd index 3d3f743..4fea201 100644 --- a/consfigurator.asd +++ b/consfigurator.asd @@ -57,7 +57,8 @@ (:file "src/data/asdf") (:file "src/data/pgp") (:file "src/data/git-snapshot") - (:file "src/data/gpgpubkeys")) + (:file "src/data/gpgpubkeys") + (:file "src/data/ssh-askpass")) :in-order-to ((test-op (test-op "consfigurator/tests")))) (defsystem "consfigurator/tests" diff --git a/doc/introduction.rst b/doc/introduction.rst index 0512723..3e65235 100644 --- a/doc/introduction.rst +++ b/doc/introduction.rst @@ -4,7 +4,10 @@ Introduction Try it out / quick start ------------------------ -1. Install Consfigurator: :ref:`Installation`. +1. Install Consfigurator (:ref:`Installation`) and ensure that some + implementation of ssh-askpass_ is available. + +.. ssh-askpass_: https://manpages.debian.org/buster/ssh-askpass/ssh-askpass.1.en.html 2. Create a new directory ``consfig`` somewhere where ASDF will pick it up, such as ``~/common-lisp/consfig``. @@ -25,12 +28,12 @@ Try it out / quick start (defpackage :com.example.consfig (:use #:cl #:alexandria #:consfigurator) - (:local-nicknames (#:os #:consfigurator.property.os) - (#:apt #:consfigurator.property.apt) - (#:cmd #:consfigurator.property.cmd) - (#:file #:consfigurator.property.file) - (#:chroot #:consfigurator.property.chroot) - (#:data.pgp #:consfigurator.data.pgp))) + (:local-nicknames (#:os #:consfigurator.property.os) + (#:apt #:consfigurator.property.apt) + (#:cmd #:consfigurator.property.cmd) + (#:file #:consfigurator.property.file) + (#:chroot #:consfigurator.property.chroot) + (#:data.ssh-askpass #:consfigurator.data.ssh-askpass))) 4. Define some hosts and deployments. @@ -40,8 +43,7 @@ Try it out / quick start (in-consfig "com.example.consfig") (named-readtables:in-readtable :consfigurator) - (try-register-data-source - :pgp :location #P"/path/to/com.example.consfig.gpg") + (try-register-data-source :ssh-askpass :iden1-re "^--user-passwd--" :iden2-re "") (defparameter my-substitution "substititions") @@ -91,26 +93,10 @@ Try it out / quick start ``:AS`` keyword parameter and its argument. 5. Get a Lisp REPL started up -- ``M-x slime`` in Emacs or ``sbcl`` at a shell - prompt. Evaluate ``(asdf:load-system "consfigurator")``. - -6. When it's asked to use sudo to become root, Consfigurator will query your - registered sources of secrets to try to find the password it will need to - give to sudo. You can easily write code to let Consfigurator query your - own sources of secrets, but for the purposes of this guide we'll use the - simple, PGP-based secrets source included with Consfigurator. Unless - you've passwordless sudo access set up on athena, evaluate something like - this to initialise the store:: - - (consfigurator.data.pgp:set-data #P"/path/to/com.example.consfig.gpg" - "--user-passwd--athena.example.com" - "spwhitton" - "s3cre+") - -7. Now you can evaluate ``(asdf:load-system "com.example.consfig")`` followed - by ``(in-package :com.example.consfig)`` (or ``C-c ~`` in Emacs). In the - future, now the secrets store exists, you can start with this step. - -8. You should now be able to evaluate ``(athena.example.com)`` to deploy + prompt. Evaluate ``(asdf:load-system "com.example.consfig")``, then + ``(in-package :com.example.consfig)`` (or ``C-c ~`` in Emacs). + +6. You should now be able to evaluate ``(athena.example.com)`` to deploy properties to athena, using the connection chain of SSH, sudo and then handing over to a remote Lisp image. diff --git a/src/data/ssh-askpass.lisp b/src/data/ssh-askpass.lisp new file mode 100644 index 0000000..6d644d9 --- /dev/null +++ b/src/data/ssh-askpass.lisp @@ -0,0 +1,52 @@ +;;; Consfigurator -- Lisp declarative configuration management system + +;;; Copyright (C) 2021 Sean Whitton <spwhitton@spwhitton.name> + +;;; This file is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3, or (at your option) +;;; any later version. + +;;; This file is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. + +;;; You should have received a copy of the GNU General Public License +;;; along with this program. If not, see <http://www.gnu.org/licenses/>. + +(in-package :consfigurator.data.ssh-askpass) +(named-readtables:in-readtable :consfigurator) + +(defmethod register-data-source + ((type (eql :ssh-askpass)) &key iden1-re iden2-re) + "Data source which will attempt to provide any piece of data matching the +CL-PPCRE regular expressions IDEN1-RE and IDEN2-RE, obtaining the data by +using ssh-askpass(1) to prompt the user to input it. Useful for things like +sudo passwords." + (unless (uiop:getenv "DISPLAY") + (missing-data-source "DISPLAY not set; cannot launch ssh-askpass(1).")) + (let ((cache (make-hash-table :test #'equal))) + (cons + (lambda (iden1 iden2) + (and (re:scan iden1-re iden1) (re:scan iden2-re iden2))) + (lambda (iden1 iden2) + (let ((pair (cons iden1 iden2))) + (or (gethash pair cache) + (setf (gethash pair cache) + (loop with msg + for first = (ssh-askpass iden1 iden2 msg) + for second = (ssh-askpass iden1 iden2 "confirm") + if (string= first second) + return (make-instance + 'string-data + :string first :mime "text/plain" + :version (get-universal-time) + :iden1 iden1 :iden2 iden2) + else do (setq msg "did not match; try again"))))))))) + +(defun ssh-askpass (iden1 iden2 &optional note) + (stripln (run-program + (list "ssh-askpass" + (format nil "~A | ~A~:[~; (~:*~A)~]" iden1 iden2 note)) + :output :string))) diff --git a/src/package.lisp b/src/package.lisp index 112b648..0334b66 100644 --- a/src/package.lisp +++ b/src/package.lisp @@ -536,3 +536,7 @@ (defpackage :consfigurator.data.gpgpubkeys (:use #:cl #:consfigurator)) + +(defpackage :consfigurator.data.ssh-askpass + (:use #:cl #:consfigurator) + (:local-nicknames (#:re #:cl-ppcre))) |