]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Set MKOSI_UID and MKOSI_GID when running scripts 1919/head
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 25 Sep 2023 08:40:46 +0000 (10:40 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 25 Sep 2023 09:00:36 +0000 (11:00 +0200)
These point to the UID/GID of the user running mkosi and can be used
to run commands as that user in scripts by using setpriv.

mkosi/__init__.py
mkosi/resources/mkosi.md
mkosi/state.py

index b89a74ea51df8da7781f0b92965a955949e1ea89..88150c82e7fa1ea36835fcf0d7ac83300f30d409 100644 (file)
@@ -265,6 +265,8 @@ def run_prepare_script(state: MkosiState, build: bool) -> None:
         SRCDIR=str(Path.cwd()),
         CHROOT_SRCDIR="/work/src",
         BUILDROOT=str(state.root),
+        MKOSI_UID=str(state.uid),
+        MKOSI_GID=str(state.gid),
     )
 
     chroot: list[PathString] = chroot_cmd(
@@ -319,6 +321,8 @@ def run_build_script(state: MkosiState) -> None:
         OUTPUTDIR=str(state.staging),
         CHROOT_OUTPUTDIR="/work/out",
         BUILDROOT=str(state.root),
+        MKOSI_UID=str(state.uid),
+        MKOSI_GID=str(state.gid),
     )
 
     if state.config.build_dir is not None:
@@ -369,6 +373,8 @@ def run_postinst_script(state: MkosiState) -> None:
         OUTPUTDIR=str(state.staging),
         CHROOT_OUTPUTDIR="/work/out",
         BUILDROOT=str(state.root),
+        MKOSI_UID=str(state.uid),
+        MKOSI_GID=str(state.gid),
     )
 
     chroot = chroot_cmd(
@@ -408,6 +414,8 @@ def run_finalize_script(state: MkosiState) -> None:
         OUTPUTDIR=str(state.staging),
         CHROOT_OUTPUTDIR="/work/out",
         BUILDROOT=str(state.root),
+        MKOSI_UID=str(state.uid),
+        MKOSI_GID=str(state.gid),
     )
 
     chroot = chroot_cmd(
@@ -978,7 +986,7 @@ def build_initrd(state: MkosiState) -> Path:
     with complete_step("Building initrd"):
         args, [config] = parse_config(cmdline)
         unlink_output(args, config)
-        build_image(args, config)
+        build_image(args, config, state.uid, state.gid)
 
     symlink.symlink_to(config.output_dir / config.output)
 
@@ -1842,12 +1850,12 @@ def normalize_mtime(root: Path, mtime: Optional[int], directory: Optional[Path]
             os.utime(p, (mtime, mtime), follow_symlinks=False)
 
 
-def build_image(args: MkosiArgs, config: MkosiConfig) -> None:
+def build_image(args: MkosiArgs, config: MkosiConfig, uid: int, gid: int) -> None:
     manifest = Manifest(config) if config.manifest_format else None
     workspace = tempfile.TemporaryDirectory(dir=config.workspace_dir, prefix=".mkosi-tmp")
 
     with workspace, scopedenv({"TMPDIR" : workspace.name}):
-        state = MkosiState(args, config, Path(workspace.name))
+        state = MkosiState(args, config, Path(workspace.name), uid, gid)
         install_package_manager_trees(state)
 
         with mount_base_trees(state):
@@ -2390,7 +2398,7 @@ def run_verb(args: MkosiArgs, presets: Sequence[MkosiConfig]) -> None:
                     run(["mkdir", "--parents", p], user=uid, group=gid)
 
             with acl_toggle_build(config, uid):
-                build_image(args, config)
+                build_image(args, config, uid, gid)
 
             # Make sure all build outputs that are not directories are owned by the user running mkosi.
             for p in config.output_dir.iterdir():
index 85092a4a6004ade7f873bed816ca59af0a52e6db..8b88c28a487847703003c4c5b39ede4b615928e2 100644 (file)
@@ -1270,12 +1270,13 @@ Then, for each preset, we execute the following steps:
 To allow for image customization that cannot be implemented using
 mkosi's builtin features, mkosi supports running scripts at various
 points during the image build process that can customize the image as
-needed. Scripts are executed on the host system with a customized
-environment to simplify modifying the image. For each script, the
-configured build sources (`BuildSources=`) are mounted into the current
-working directory before running the script and `$SRCDIR` is set to
-point to the current working directory. The following scripts are
-supported:
+needed. Scripts are executed on the host system as root (either real
+root or root within the user namespace that mkosi created when running
+unprivileged) with a customized environment to simplify modifying the
+image. For each script, the configured build sources (`BuildSources=`)
+are mounted into the current working directory before running the script
+and `$SRCDIR` is set to point to the current working directory. The
+following scripts are supported:
 
 * If **`mkosi.prepare`** (`PrepareScript=`) exists, it is first called
   with the `final` argument, right after the software packages are
@@ -1363,6 +1364,12 @@ Scripts executed by mkosi receive the following environment variables:
   [SOURCE_DATE_EPOCH](https://reproducible-builds.org/specs/source-date-epoch/)
   for more information.
 
+* `$MKOSI_UID` and `$MKOSI_GID` are the respectively the uid, gid of the
+  user that invoked mkosi, potentially translated to a uid in the user
+  namespace that mkosi is running in. These can be used in combination
+  with `setpriv` to run commands as the user that invoked mkosi (e.g.
+  `setpriv --reuid=$MKOSI_UID --regid=$MKOSI_GID --clear-groups <command>`)
+
 Additionally, when a script is executed, a few scripts are made
 available via `$PATH` to simplify common usecases.
 
index 3b3b6d200522e7f15f6631aeba5e3eb2f794d5cc..949a3f33e9f356a9ab8c09d3e26ca293fbad9fd4 100644 (file)
@@ -10,10 +10,12 @@ from mkosi.util import umask
 class MkosiState:
     """State related properties."""
 
-    def __init__(self, args: MkosiArgs, config: MkosiConfig, workspace: Path) -> None:
+    def __init__(self, args: MkosiArgs, config: MkosiConfig, workspace: Path, uid: int, gid: int) -> None:
         self.args = args
         self.config = config
         self.workspace = workspace
+        self.uid = uid
+        self.gid = gid
 
         with umask(~0o755):
             # Using a btrfs subvolume as the upperdir in an overlayfs results in EXDEV so make sure we create