From 2fcbe645d1d11a871cd152aa2ac86f287631ff65 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Tue, 4 May 2021 11:35:38 -0700 Subject: implement populating /etc/crypttab for LUKS containers Signed-off-by: Sean Whitton --- consfigurator.asd | 1 + src/package.lisp | 12 ++++++- src/property/crypttab.lisp | 88 +++++++++++++++++++++++++++++++++++++++++++++ src/property/installer.lisp | 18 +++++----- 4 files changed, 109 insertions(+), 10 deletions(-) create mode 100644 src/property/crypttab.lisp diff --git a/consfigurator.asd b/consfigurator.asd index 4fea201..f61220d 100644 --- a/consfigurator.asd +++ b/consfigurator.asd @@ -37,6 +37,7 @@ (:file "src/property/live-build") (:file "src/property/disk") (:file "src/property/fstab") + (:file "src/property/crypttab") (:file "src/property/user") (:file "src/property/git") (:file "src/property/gnupg") diff --git a/src/package.lisp b/src/package.lisp index f2fca72..c2292f9 100644 --- a/src/package.lisp +++ b/src/package.lisp @@ -379,6 +379,7 @@ #:all-subvolumes #:copy-volume-and-contents #:require-volumes-data + #:device-file #:physical-disk #:disk-image @@ -430,6 +431,14 @@ #:entries-for-volumes #:entries-for-opened-volumes)) +(defpackage :consfigurator.property.crypttab + (:use #:cl #:alexandria #:consfigurator #:consfigurator.property.disk) + (:local-nicknames (#:re #:cl-ppcre) + (#:os #:consfigurator.property.os) + (#:file #:consfigurator.property.file)) + (:export #:volume->entry + #:entries-for-opened-volumes)) + (defpackage :consfigurator.property.gnupg (:use #:cl #:consfigurator) (:export #:public-key-imported)) @@ -469,7 +478,8 @@ (:local-nicknames (#:os #:consfigurator.property.os) (#:file #:consfigurator.property.file) (#:chroot #:consfigurator.property.chroot) - (#:fstab #:consfigurator.property.fstab)) + (#:fstab #:consfigurator.property.fstab) + (#:crypttab #:consfigurator.property.crypttab)) (:export #:chroot-installed-to-volumes)) (defpackage :consfigurator.connection.local diff --git a/src/property/crypttab.lisp b/src/property/crypttab.lisp new file mode 100644 index 0000000..a24ac26 --- /dev/null +++ b/src/property/crypttab.lisp @@ -0,0 +1,88 @@ +;;; Consfigurator -- Lisp declarative configuration management system + +;;; Copyright (C) 2021 Sean Whitton + +;;; 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 . + +(in-package :consfigurator.property.crypttab) +(named-readtables:in-readtable :consfigurator) + +;;;; Methods on volumes to get strings for crypttab + +(defun get-lsblk-field (device field) + (let ((val (stripln (run "lsblk" "-ndo" field device)))) + (if (string= val "") nil val))) + +(defun get-device-parent (device) + (multiple-value-bind (match groups) + (re:scan-to-strings #?/^1\s+dependencies\s*:\s*\((\S+)\)$/ + (run "dmsetup" "deps" "-o" "blkdevname" device)) + (and match (merge-pathnames (elt groups 0) #P"/dev/")))) + +(defmethod ct-target ((volume opened-luks-container)) + (volume-label volume)) + +(defmethod ct-source ((volume opened-luks-container)) + (with-slots (device-file) volume + (let ((parent + (or (get-device-parent device-file) + (failed-change + "Could not determine parent device of ~A" device-file)))) + (if-let ((partuuid (get-lsblk-field parent "PARTUUID"))) + (strcat "PARTUUID=" partuuid) + (if-let ((uuid (get-lsblk-field parent "UUID"))) + (strcat "UUID=" uuid) + (failed-change + "Could not determine crypttab source field for ~A" device-file)))))) + +(defmethod ct-keyfile ((volume opened-luks-container)) + (if (slot-boundp volume 'crypttab-keyfile) + (crypttab-keyfile volume) + "none")) + +(defmethod ct-options ((volume opened-luks-container)) + (or (crypttab-options volume) '("none"))) + +(defmethod volume->entry ((volume opened-luks-container)) + (format nil "~A ~A ~A ~{~A~^,~}" + (ct-target volume) (ct-source volume) + (ct-keyfile volume) (ct-options volume))) + + +;;;; Properties + +(defprop entries :posix (&rest entries) + "Ensure that /etc/crypttab contains each of ENTRIES, using a simple merge +procedure: existing lines of the crypttab with the same mapped device name as +any of ENTRIES are updated to match the corresponding members of ENTRIES, +except that if the second field of the existing entry is not \"none\" and the +corresponding member of ENTRIES is \"none\" or \"PLACEHOLDER\", use the +existing field value." + (:desc + (let ((devices + (loop for entry in entries collect (car (split-string entry))))) + (format nil "crypttab entr~@P for ~{~A~^, ~}" (length devices) devices))) + (:apply (file:update-unix-table #P"/etc/crypttab" 1 0 entries))) + +(defprop entries-for-opened-volumes :posix () + "Add or update entries in /etc/crypttab for currently open volumes. + +This is used when building disk images and installing operating systems." + (:desc "crypttab entries for opened volumes") + (:hostattrs (os:required 'os:linux)) + (:apply + (apply #'entries + (mapcar #'volume->entry + (mapcan (curry #'subvolumes-of-type 'opened-luks-container) + (get-connattr :opened-volumes)))))) diff --git a/src/property/installer.lisp b/src/property/installer.lisp index 80229a6..04bccfb 100644 --- a/src/property/installer.lisp +++ b/src/property/installer.lisp @@ -50,14 +50,14 @@ Also update the fstab and crypttab, and try to install a bootloader." (debianlike (file:lacks-lines "/etc/fstab" "# UNCONFIGURED FSTAB FOR BASE SYSTEM") - ;; This will overwrite any custom mount options, etc., with - ;; values from VOLUMES. Possibly it would be better to use a - ;; property which only updates the fs-spec field. However, - ;; given that VOLUMES ultimately comes from the volumes the - ;; user has declared for the host, it is unlikely there are - ;; other properties setting mount options etc. which are in - ;; conflict with VOLUMES. - (fstab:entries-for-opened-volumes))))) - ;; TODO Update /etc/crypttab + ;; These will overwrite any custom mount options, etc., with + ;; values from VOLUMES. Possibly it would be better to use + ;; properties which only update the fs-spec/source fields. + ;; However, given that VOLUMES ultimately comes from the + ;; volumes the user has declared for the host, it is unlikely + ;; there are other properties setting mount options etc. which + ;; are in conflict with VOLUMES. + (fstab:entries-for-opened-volumes) + (crypttab:entries-for-opened-volumes))))) ;; TODO Install bootloader ))) -- cgit v1.2.3