aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--consfigurator.asd3
-rw-r--r--doc/introduction.rst44
-rw-r--r--src/data/ssh-askpass.lisp52
-rw-r--r--src/package.lisp4
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)))