[Libguestfs] [libguestfs-common PATCH 12/12] options, mltools/tools_utils: add helper for network dependency

Richard W.M. Jones rjones at redhat.com
Tue Jun 28 14:50:56 UTC 2022


On Tue, Jun 28, 2022 at 01:49:15PM +0200, Laszlo Ersek wrote:
> For "--key ID:clevis" to actually work, the appliance needs network
> connectivity. Some tools allow the user to control that (for example,
> guestfish takes "--network"); those tools can already use "--key
> ID:clevis", provided they enable inspection and networking.
> 
> However, other tools have had no use for networking thus far. Introduce a
> helper function for the OCaml utils, and another for the C utils, so that
> the utils can query if there's at least one clevis selector, and if so,
> enable networking for the appliance, before launching the appliance.
> 
> Note that we need to implement both helpers separately from each other;
> that is, the OCaml one is not based on the C one. The reason is that
> "struct key_store" (from "options/options.h"), upon which we could
> logically base a common helper, exists in the OCaml tools only
> ephemerally, in guestfs_int_mllib_inspect_decrypt():
> 
>   inspect_decrypt                       [mltools/tools_utils.ml]
>     c_inspect_decrypt                   [mltools/tools_utils.ml]
>       guestfs_int_mllib_inspect_decrypt [mltools/tools_utils-c.c]
>         key_store_import_key()          [options/keys.c]
>         inspect_do_decrypt()            [options/decrypt.c]
>         free_key_store()                [options/keys.c]
> 
> At that time, it's too late for enabling networking for the appliance.
> Therefore, in the OCaml tools, search the "earlier" data structure called
> "cmdline_options.ks". *That* "key_store" type comes from
> "mltools/tools_utils.ml".
> 
> Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1809453
> Signed-off-by: Laszlo Ersek <lersek at redhat.com>
> ---
>  options/options.h       |  1 +
>  mltools/tools_utils.mli |  4 ++++
>  mltools/tools_utils.ml  |  5 +++++
>  options/keys.c          | 15 +++++++++++++++
>  options/key-option.pod  |  3 +++
>  5 files changed, 28 insertions(+)
> 
> diff --git a/options/options.h b/options/options.h
> index e7a0364cc926..60d5d8064113 100644
> --- a/options/options.h
> +++ b/options/options.h
> @@ -168,10 +168,11 @@ extern char *read_key (const char *param);
>  extern struct matching_key *get_keys (struct key_store *ks, const char *device,
>                                        const char *uuid, size_t *nr_matches);
>  extern void free_keys (struct matching_key *keys, size_t nr_matches);
>  extern struct key_store *key_store_add_from_selector (struct key_store *ks, const char *selector);
>  extern struct key_store *key_store_import_key (struct key_store *ks, const struct key_store_key *key);
> +extern bool key_store_requires_network (const struct key_store *ks);
>  extern void free_key_store (struct key_store *ks);
>  
>  /* in options.c */
>  extern void option_a (const char *arg, const char *format, int blocksize, struct drv **drvsp);
>  extern void option_d (const char *arg, struct drv **drvsp);
> diff --git a/mltools/tools_utils.mli b/mltools/tools_utils.mli
> index 8d9af7a0a661..ec900e6389bc 100644
> --- a/mltools/tools_utils.mli
> +++ b/mltools/tools_utils.mli
> @@ -194,10 +194,14 @@ val inspect_mount_root_ro : Guestfs.guestfs -> string -> unit
>      read-only. *)
>  
>  val is_btrfs_subvolume : Guestfs.guestfs -> string -> bool
>  (** Checks if a filesystem is a btrfs subvolume. *)
>  
> +val key_store_requires_network : key_store -> bool
> +(** [key_store_requires_network ks] returns [true] iff [ks] contains at least
> +    one "ID:clevis" selector. *)
> +
>  val inspect_decrypt : Guestfs.guestfs -> key_store -> unit
>  (** Simple implementation of decryption: look for any encrypted
>      partitions and decrypt them, then rescan for VGs. *)
>  
>  val with_timeout : string -> int -> ?sleep:int -> (unit -> 'a option) -> 'a
> diff --git a/mltools/tools_utils.ml b/mltools/tools_utils.ml
> index 1da5850340d4..562bfadc18a8 100644
> --- a/mltools/tools_utils.ml
> +++ b/mltools/tools_utils.ml
> @@ -694,10 +694,15 @@ let is_btrfs_subvolume g fs =
>      ignore (g#mountable_subvolume fs); true
>    with Guestfs.Error msg as exn ->
>      if g#last_errno () = Guestfs.Errno.errno_EINVAL then false
>      else raise exn
>  
> +let key_store_requires_network ks =
> +  List.exists (function
> +               | _, KeyClevis -> true
> +               | _ -> false) !(ks.keys)
> +
>  let inspect_decrypt g ks =
>    (* Note we pass original 'g' even though it is not used by the
>     * callee.  This is so that 'g' is kept as a root on the stack, and
>     * so cannot be garbage collected while we are in the c_inspect_decrypt
>     * function.
> diff --git a/options/keys.c b/options/keys.c
> index d53e3e774a9b..97da6df93ee6 100644
> --- a/options/keys.c
> +++ b/options/keys.c
> @@ -282,10 +282,25 @@ key_store_import_key (struct key_store *ks, const struct key_store_key *key)
>    ++ks->nr_keys;
>  
>    return ks;
>  }
>  
> +bool
> +key_store_requires_network (const struct key_store *ks)
> +{
> +  size_t i;
> +
> +  if (ks == NULL)
> +    return false;
> +
> +  for (i = 0; i < ks->nr_keys; ++i)
> +    if (ks->keys[i].type == key_clevis)
> +      return true;
> +
> +  return false;
> +}
> +
>  void
>  free_key_store (struct key_store *ks)
>  {
>    size_t i;
>  
> diff --git a/options/key-option.pod b/options/key-option.pod
> index 34229ce9cbb2..6bc04df177b1 100644
> --- a/options/key-option.pod
> +++ b/options/key-option.pod
> @@ -18,6 +18,9 @@ Read the passphrase from F<FILENAME>.
>  
>  Attempt passphrase-less unlocking for C<ID> with Clevis, over the
>  network.  Please refer to L<guestfs(3)/ENCRYPTED DISKS> for more
>  information on network-bound disk encryption (NBDE).
>  
> +Note that if any such option is present on the command line, QEMU user
> +networking will be automatically enabled for the libguestfs appliance.
> +
>  =back

options/ is just one of those crazy pieces of code that
accumulates special cases :-(


Reviewed-by: Richard W.M. Jones <rjones at redhat.com>


-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-top is 'top' for virtual machines.  Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://people.redhat.com/~rjones/virt-top


More information about the Libguestfs mailing list