Subject: bug#25305: bug#37851: bug#25305: bug#37851: Grub installation only checks for encrypted /boot folder

From: Ludovic Courtès <[email-masked]>
Date: Mon, 14 Dec 2020 14:11:37 +0100

Hi Miguel,

Miguel Ángel Arruga Vivas <[email-masked]> skribis:

>>>From 52993db19da43699ea96ea16ebb051b9652934f9 Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Miguel=20=C3=81ngel=20Arruga=20Vivas?=
>  <[email-masked]>
> Date: Sun, 25 Oct 2020 16:31:17 +0100
> Subject: [PATCH v4 5/5] system: Allow separated /boot and encrypted root.
>
> * gnu/bootloader/grub.scm (grub-configuration-file): New parameter
> store-crypto-devices.
> [crypto-devices]: New helper function.
> [builder]: Use crypto-devices.
> * gnu/machine/ssh.scm (roll-back-managed-host): Use
> boot-parameters-store-crypto-devices to provide its contents to the
> bootloader configuration generation process.
> * gnu/tests/install.scm (%encrypted-root-not-boot-os,
> %encrypted-root-not-boot-os): New os declaration.
> (%encrypted-root-not-boot-installation-script): New script, whose contents
> were initially taken from %encrypted-root-installation-script.
> (%test-encrypted-root-not-boot-os): New test.
> * gnu/system.scm (define-module): Export
> operating-system-bootoader-crypto-devices and
> boot-parameters-store-crypto-devices.
> (<boot-parameters>): Add field store-crypto-devices.
> (read-boot-parameters): Parse store-crypto-devices field.
> [uuid-sexp->uuid]: New helper function extracted from
> device-sexp->device.
> (operating-system-bootloader-crypto-devices): New function.
> (operating-system-bootcfg): Use
> operating-system-bootloader-crypto-devices to provide its contents to
> the bootloader configuration generation process.
> (operating-system-boot-parameters): Add store-crypto-devices to the
> generated boot-parameters.
> (operating-system-boot-parameters-file): Likewise to the file with
> the serialized structure.
> * guix/scripts/system.scm (reinstall-bootloader): Use
> boot-parameters-store-crypto-devices to provide its contents to the
> bootloader configuration generation process.
> * tests/boot-parameters.scm (%default-store-crypto-devices): New
> variable.
> (%grub-boot-parameters, test-read-boot-parameters): Use
> %default-store-crypto-devices.
> (tests store-crypto-devices): New tests.
> ---
>  gnu/bootloader/grub.scm   |  21 +++++++-
>  gnu/machine/ssh.scm       |   3 ++
>  gnu/system.scm            |  57 ++++++++++++++++++++-
>  gnu/tests/install.scm     | 103 ++++++++++++++++++++++++++++++++++++++
>  guix/scripts/system.scm   |   2 +
>  tests/boot-parameters.scm |  29 ++++++++++-
>  6 files changed, 210 insertions(+), 5 deletions(-)

Woohoo!

> --- a/gnu/bootloader/grub.scm
> +++ b/gnu/bootloader/grub.scm
> @@ -4,7 +4,7 @@
>  ;;; Copyright © 2017 Leo Famulari <[email-masked]>
>  ;;; Copyright © 2017, 2020 Mathieu Othacehe <[email-masked]>
>  ;;; Copyright © 2019, 2020 Jan (janneke) Nieuwenhuizen <[email-masked]>
> -;;; Copyright © 2019 Miguel Ángel Arruga Vivas <[email-masked]>
> +;;; Copyright © 2019, 2020 Miguel Ángel Arruga Vivas <[email-masked]>
>  ;;; Copyright © 2020 Maxim Cournoyer <[email-masked]>
>  ;;; Copyright © 2020 Stefan <[email-masked]>
>  ;;;
> @@ -360,11 +360,14 @@ code."
>                                    (locale #f)
>                                    (system (%current-system))
>                                    (old-entries '())
> +                                  (store-crypto-devices '())
>                                    store-directory-prefix)
>    "Return the GRUB configuration file corresponding to CONFIG, a
>  <bootloader-configuration> object, and where the store is available at
>  STORE-FS, a <file-system> object.  OLD-ENTRIES is taken to be a list of menu
>  entries corresponding to old generations of the system.
> +STORE-CRYPTO-DEVICES contain the UUIDs of the encrypted units that must
> +be unlocked to access the store contents.
>  STORE-DIRECTORY-PREFIX may be used to specify a store prefix, as is required
>  when booting a root file system on a Btrfs subvolume."
>    (define all-entries
> @@ -412,6 +415,21 @@ menuentry ~s {
>                    (string-join (map string-join '#$modules)
>                                 "\n  module " 'prefix))))))
>  
> +  (define (crypto-devices)
> +    (define (crypto-device->cryptomount dev)
> +      (if (uuid? dev)
> +          #~(format port "cryptomount -u ~a~%"
> +                    ;; cryptomount only accepts UUID without the hypen.
> +                    #$(string-delete #\- (uuid->string dev)))
> +          ;; Other type of devices aren't implemented.
> +          #~()))
> +    (let ((devices (map crypto-device->cryptomount store-crypto-devices))
> +          ;; XXX: Add luks2 when grub 2.06 is packaged.
> +          (modules #~(format port "insmod luks~%")))
> +      (if (null? devices)
> +          devices
> +          (cons modules devices))))

What I don’t get is why we’re able to use an encrypted root right now
without emitting “cryptomount” GRUB commands?

> +      (store-crypto-devices
> +       (match (assq 'store rest)
> +         (('store . store-data)
> +          (match (assq 'crypto-devices store-data)
> +            (('crypto-devices devices)
> +             (if (list? devices)
> +                 (map uuid-sexp->uuid devices)
> +                 (begin
> +                   (warning (G_ "unrecognized crypto-device ~S at '~a'~%")
> +                            devices (port-filename port))
> +                   '())))

You could avoid ‘if’ by having clauses like:

  (('crypto-devices (devices ...))
   ;; …
   )
  (('crypto-devices _)
   (warning …)
   '())
  (_
   '())

> +            (_
> +             ;; No crypto-devices found
> +             '())))
> +         (_
> +          ;; No store found, old format.
> +          '())))

s/No store found/No crypto devices found/ ?

> +(define (operating-system-bootloader-crypto-devices os)
> +  "Return the subset of mapped devices that the bootloader must open.
> +Only devices specified by uuid are supported."
> +  (map mapped-device-source
> +       (filter (match-lambda
> +                 ((and (= mapped-device-type type)
> +                       (= mapped-device-source source))
> +                  (and (eq? luks-device-mapping type)
> +                       (or (uuid? source)
> +                           (begin
> +                             (warning (G_ "\
> +mapped-device '~a' won't be mounted by the bootloader.~%")
> +                                      source)
> +                             #f)))))
> +               ;; XXX: Ordering is important, we trust the returned one.
> +               (operating-system-boot-mapped-devices os))))

You can use ‘filter-map’ here.

The rest LGTM!  Make sure the “installed-os” and “encrypted-root-os”
system tests are still fine, and if they are, I guess you can go ahead.

Thanks!

Ludo’.