aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2021-06-24 11:36:28 -0700
committerSean Whitton <spwhitton@spwhitton.name>2021-06-25 16:10:56 -0700
commitcf7cf446cd90b7e543c970878b3a92b107826ca6 (patch)
tree7bb3c65778260afce173fc2aaf65de9ba7f16592 /src
parent4b6dc7906d48cd609367a83b051310f4967d5098 (diff)
downloadconsfigurator-cf7cf446cd90b7e543c970878b3a92b107826ca6.tar.gz
Let's Encrypt: fix looking for changed files & flatten DOMAINS
Signed-off-by: Sean Whitton <spwhitton@spwhitton.name>
Diffstat (limited to 'src')
-rw-r--r--src/package.lisp3
-rw-r--r--src/property.lisp13
-rw-r--r--src/property/lets-encrypt.lisp41
3 files changed, 36 insertions, 21 deletions
diff --git a/src/package.lisp b/src/package.lisp
index bb17b1c..c2c8374 100644
--- a/src/package.lisp
+++ b/src/package.lisp
@@ -169,6 +169,7 @@
#:maybe-writefile-string
#:call-with-os
#:with-change-if-changes-file
+ #:with-change-if-changes-files
#:with-change-if-changes-file-content
#:with-change-if-changes-file-content-or-mode
@@ -687,7 +688,7 @@
#:nice-system-job))
(defpackage :consfigurator.property.lets-encrypt
- (:use #:cl #:consfigurator)
+ (:use #:cl #:alexandria #:consfigurator)
(:local-nicknames (#:apt #:consfigurator.property.apt)
(#:os #:consfigurator.property.os))
(:export #:installed
diff --git a/src/property.lisp b/src/property.lisp
index 3f0b962..d23fd99 100644
--- a/src/property.lisp
+++ b/src/property.lisp
@@ -599,6 +599,19 @@ changes in properties which will change the file but not the output of `ls
(and ,before (equal ,before (ls-cksum ,file))))
:no-change result))))
+(defmacro with-change-if-changes-files ((&rest files) &body forms)
+ "Execute FORMS and yield :NO-CHANGE if none of FILES change.
+See WITH-CHANGE-IF-CHANGES-FILE docstring regarding the sense of 'change'."
+ (with-gensyms (filesg beforeg)
+ `(let* ((,filesg (list ,@files))
+ (,beforeg (mapcar #'ls-cksum ,filesg))
+ (result (progn ,@forms)))
+ (if (or (eql result :no-change)
+ (loop for file in ,filesg and before in ,beforeg
+ always before
+ always (equal before (ls-cksum file))))
+ :no-change result))))
+
(defmacro with-change-if-changes-file-content ((file) &body forms)
"Execute FORMS and yield :NO-CHANGE if FILE has the same content afterwards."
(with-gensyms (before)
diff --git a/src/property/lets-encrypt.lisp b/src/property/lets-encrypt.lisp
index 6db56e7..93f4bca 100644
--- a/src/property/lets-encrypt.lisp
+++ b/src/property/lets-encrypt.lisp
@@ -38,32 +38,33 @@ etc."))
(check-type agree-tos agree-tos)
(let ((dir (ensure-directory-pathname
(merge-pathnames (car domains) #P"/etc/letsencrypt/live/"))))
- (with-change-if-changes-file ((merge-pathnames "fullchain.pem" dir))
- (with-change-if-changes-file ((merge-pathnames "chain.pem" dir))
- (with-change-if-changes-file ((merge-pathnames "privkey.pem" dir))
- (with-change-if-changes-file ((merge-pathnames "cert.pem" dir))
- (mrun "letsencrypt" "certonly" "--agree-tos"
- (if (slot-boundp agree-tos 'email-address)
- (strcat "--email=" (slot-value agree-tos 'email-address))
- "--register-unsafely-without-email")
- "--webroot" "--webroot-path" htdocs
- "--text" "--noninteractive" "--keep-until-expiring"
- ;; Always request expansion in case DOMAINS has changed.
- "--expand"
- (loop for domain in domains
- collect (strcat "--domain=" domain))))))))))
+ (with-change-if-changes-files ((merge-pathnames "cert.pem" dir)
+ (merge-pathnames "chain.pem" dir)
+ (merge-pathnames "privkey.pem" dir)
+ (merge-pathnames "fullchain.pem" dir))
+ (mrun "letsencrypt" "certonly" "--agree-tos"
+ (if (slot-boundp agree-tos 'email-address)
+ (strcat "--email=" (slot-value agree-tos 'email-address))
+ "--register-unsafely-without-email")
+ "--webroot" "--webroot-path" htdocs
+ "--text" "--noninteractive" "--keep-until-expiring"
+ ;; Always request expansion in case DOMAINS has changed.
+ "--expand"
+ (loop for domain in domains
+ when (and (stringp domain) (plusp (length domain)))
+ collect (strcat "--domain=" domain)))))))
(defproplist certificate-obtained :posix (agree-tos htdocs &rest domains)
"Obtains, and renews as necessary, an SSL certificate for DOMAINS.
-The first element of DOMAINS is the Common Name of the certificate. Use of
-this property implies agreement with the Let's Encrypt Subscriber Agreement;
-AGREE-TOS is an instance of LETS-ENCRYPT:AGREE-TOS. HTDOCS is the web root
-for DOMAINS, which must be writeable, and publically available over plain
-HTTP.
+The first element of DOMAINS, after flattening, is the Common Name of the
+certificate. Use of this property implies agreement with the Let's Encrypt
+Subscriber Agreement; AGREE-TOS is an instance of LETS-ENCRYPT:AGREE-TOS.
+HTDOCS is the web root for DOMAINS, which must be writeable, and publically
+available over plain HTTP.
This property does nothing to ensure that your web server will actually use
the obtained certificate. Typically you'll want to combine this property with
web server-specific properties in a DEFPROPLIST/DEFPROPSPEC."
(:desc (format nil "Let's Encrypt for ~{~A~^, ~}" domains))
(installed)
- (%obtained agree-tos htdocs domains))
+ (%obtained agree-tos htdocs (flatten domains)))