Repository: systemd/mkosi

Issue:
Allow setting `RootPassword` to empty string
Due to some checks for truthiness instead of explicitly checking against None it is not possible to assign the root password. This means that it is not possible to create a passwordless, unlocked root account. While I do not endorse open root accounts there are certainly use cases for them and we should not stand in the way of creating them. The attached patch adds the ability to add such accounts using `hashed:` (without an actual hash following it). Using `RootPassword=hashed:` instead of `RootPassword=` allows to preserve the intended behaviour that assigning the empty value resets previous assignments (and supporting the latter would also have complicated the configparser a decent bit.

```patch
From 0b46aca23e67c41618aee931fa6910b32a42111e Mon Sep 17 00:00:00 2001
From: Septatrix <24257556+Septatrix@users.noreply.github.com>
Date: Sat, 25 Nov 2023 23:14:08 +0100
Subject: [PATCH] Add ability to create passwordless root account

To create a passwordless root account one may specify `hashed:`
without passing an actual hash.

---
 mkosi/__init__.py        | 7 ++++---
 mkosi/resources/mkosi.md | 3 ++-
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/mkosi/__init__.py b/mkosi/__init__.py
index f0fe850..fe8e8de 100644
--- a/mkosi/__init__.py
+++ b/mkosi/__init__.py
@@ -1117,8 +1117,8 @@ def build_initrd(state: MkosiState) -> Path:
     # Default values are assigned via the parser so we go via the argument parser to construct
     # the config for the initrd.
 
-    password, hashed = state.config.root_password or (None, False)
-    if password:
+    if state.config.root_password:
+        password, hashed = state.config.root_password
         rootpwopt = f"hashed:{password}" if hashed else password
     else:
         rootpwopt = None
@@ -1845,7 +1845,8 @@ def run_firstboot(state: MkosiState) -> None:
     creds = []
 
     for option, cred, value in settings:
-        if not value:
+        # Check for None as password might be the empty string
+        if value is None:
             continue
 
         options += [option, value]
diff --git a/mkosi/resources/mkosi.md b/mkosi/resources/mkosi.md
index fcb043a..ce05b94 100644
--- a/mkosi/resources/mkosi.md
+++ b/mkosi/resources/mkosi.md
@@ -1073,7 +1073,8 @@ boolean argument: either `1`, `yes`, or `true` to enable, or `0`, `no`,
 : Set the system root password. If this option is not used, but a `mkosi.rootpw` file is found in the local
   directory, the password is automatically read from it. If the password starts with `hashed:`, it is treated
   as an already hashed root password. The root password is also stored in `/usr/lib/credstore` under the
-  appropriate systemd credential so that it applies even if only `/usr` is shipped in the image.
+  appropriate systemd credential so that it applies even if only `/usr` is shipped in the image. The create
+  an unlocked account without any password use `hashed:` without a hash.
 
 `Autologin=`, `--autologin`
 
-- 
2.42.0
 ```


Discussion:

Resolving patch:
diff --git a/mkosi/__init__.py b/mkosi/__init__.py
--- a/mkosi/__init__.py
+++ b/mkosi/__init__.py
@@ -1117,8 +1117,8 @@ def build_initrd(state: MkosiState) -> Path:
     # Default values are assigned via the parser so we go via the argument parser to construct
     # the config for the initrd.
 
-    password, hashed = state.config.root_password or (None, False)
-    if password:
+    if state.config.root_password:
+        password, hashed = state.config.root_password
         rootpwopt = f"hashed:{password}" if hashed else password
     else:
         rootpwopt = None
@@ -1845,7 +1845,8 @@ def run_firstboot(state: MkosiState) -> None:
     creds = []
 
     for option, cred, value in settings:
-        if not value:
+        # Check for None as password might be the empty string
+        if value is None:
             continue
 
         options += [option, value]


Test patch: