From 2ffca6984a03b2daa3bb114f70ea84e71439559a Mon Sep 17 00:00:00 2001 From: Ophestra Date: Sun, 25 May 2025 20:12:30 +0900 Subject: [PATCH] nix: use reverse-DNS style id as unique identifier Signed-off-by: Ophestra --- nixos.nix | 145 +++++++++++++++++---------------- options.nix | 13 +-- test/configuration.nix | 33 +++++--- test/sandbox/case/default.nix | 13 +-- test/sandbox/configuration.nix | 8 +- 5 files changed, 114 insertions(+), 98 deletions(-) diff --git a/nixos.nix b/nixos.nix index 12b283a..307355b 100644 --- a/nixos.nix +++ b/nixos.nix @@ -8,12 +8,10 @@ packages: let inherit (lib) + lists mkMerge mkIf mapAttrs - mergeAttrsList - imap1 - foldr foldlAttrs optional optionals @@ -30,6 +28,27 @@ in imports = [ (import ./options.nix packages) ]; config = mkIf cfg.enable { + assertions = [ + ( + let + conflictingApps = foldlAttrs ( + acc: id: app: + ( + acc + ++ foldlAttrs ( + acc': id': app': + if id == id' || app.shareUid && app'.shareUid || app.identity != app'.identity then acc' else acc' ++ [ id ] + ) [ ] cfg.apps + ) + ) [ ] cfg.apps; + in + { + assertion = (lists.length conflictingApps) == 0; + message = "the following fortify apps have conflicting identities: " + (builtins.concatStringsSep ", " conflictingApps); + } + ) + ]; + security.wrappers.fsu = { source = "${cfg.fsuPackage}/bin/fsu"; setuid = true; @@ -49,22 +68,19 @@ in home-manager = let privPackages = mapAttrs (username: fid: { - home.packages = - let - # aid 0 is reserved - wrappers = imap1 ( - aid: app: + home.packages = foldlAttrs ( + acc: id: app: + [ + ( let extendDBusDefault = id: ext: { filter = true; talk = [ "org.freedesktop.Notifications" ] ++ ext.talk; - own = - (optionals (app.id != null) [ - "${id}.*" - "org.mpris.MediaPlayer2.${id}.*" - ]) - ++ ext.own; + own = [ + "${id}.*" + "org.mpris.MediaPlayer2.${id}.*" + ] ++ ext.own; inherit (ext) call broadcast; }; @@ -78,7 +94,7 @@ in }; in { - session_bus = if app.dbus.session != null then (app.dbus.session (extendDBusDefault app.id)) else (extendDBusDefault app.id default); + session_bus = if app.dbus.session != null then (app.dbus.session (extendDBusDefault id)) else (extendDBusDefault id default); system_bus = app.dbus.system; }; command = if app.command == null then app.name else app.command; @@ -87,8 +103,6 @@ in isGraphical = if app.gpu != null then app.gpu else app.capability.wayland || app.capability.x11; conf = { - inherit (app) id; - path = if app.path == null then pkgs.writeScript "${app.name}-start" '' @@ -99,16 +113,15 @@ in app.path; args = if app.args == null then [ "${app.name}-start" ] else app.args; - inherit enablements; + inherit id enablements; inherit (dbusConfig) session_bus system_bus; direct_wayland = app.insecureWayland; - username = getsubname fid aid; - data = getsubhome fid aid; + username = getsubname fid app.identity; + data = getsubhome fid app.identity; - identity = aid; - inherit (app) groups; + inherit (app) identity groups; container = { inherit (app) @@ -188,10 +201,9 @@ in pkgs.writeShellScriptBin app.name '' exec fortify${if app.verbose then " -v" else ""} app ${pkgs.writeText "fortify-${app.name}.json" (builtins.toJSON conf)} $@ '' - ) cfg.apps; - in - foldr ( - app: acc: + ) + ] + ++ ( let pkg = if app.share != null then app.share else pkgs.${app.name}; copy = source: "[ -d '${source}' ] && cp -Lrv '${source}' $out/share || true"; @@ -211,30 +223,33 @@ in fi '' ) - ++ acc - ) (wrappers ++ [ cfg.package ]) cfg.apps; + ) + ++ acc + ) [ cfg.package ] cfg.apps; }) cfg.users; in { useUserPackages = false; # prevent users.users entries from being added - users = foldlAttrs ( - acc: _: fid: - mkMerge [ - (mergeAttrsList ( - # aid 0 is reserved - imap1 (aid: app: { - ${getsubname fid aid} = mkMerge [ - cfg.extraHomeConfig - app.extraConfig - { home.packages = app.packages; } - ]; - }) cfg.apps - )) - { ${getsubname fid 0} = cfg.extraHomeConfig; } + users = mkMerge ( + foldlAttrs ( + acc: _: fid: acc - ] - ) privPackages cfg.users; + ++ foldlAttrs ( + acc': _: app: + acc' + ++ [ + { + ${getsubname fid app.identity} = mkMerge [ + cfg.extraHomeConfig + app.extraConfig + { home.packages = app.packages; } + ]; + } + ] + ) [ { ${getsubname fid 0} = cfg.extraHomeConfig; } ] cfg.apps + ) [ privPackages ] cfg.users + ); }; users = @@ -250,33 +265,27 @@ in getgroup = fid: aid: { gid = getsubuid fid aid; }; in { - users = foldlAttrs ( - acc: _: fid: - mkMerge [ - (mergeAttrsList ( - # aid 0 is reserved - imap1 (aid: _: { - ${getsubname fid aid} = getuser fid aid; - }) cfg.apps - )) - { ${getsubname fid 0} = getuser fid 0; } + users = mkMerge ( + foldlAttrs ( + acc: _: fid: acc - ] - ) { } cfg.users; + ++ foldlAttrs ( + acc': _: app: + acc' ++ [ { ${getsubname fid app.identity} = getuser fid app.identity; } ] + ) [ { ${getsubname fid 0} = getuser fid 0; } ] cfg.apps + ) [ ] cfg.users + ); - groups = foldlAttrs ( - acc: _: fid: - mkMerge [ - (mergeAttrsList ( - # aid 0 is reserved - imap1 (aid: _: { - ${getsubname fid aid} = getgroup fid aid; - }) cfg.apps - )) - { ${getsubname fid 0} = getgroup fid 0; } + groups = mkMerge ( + foldlAttrs ( + acc: _: fid: acc - ] - ) { } cfg.users; + ++ foldlAttrs ( + acc': _: app: + acc' ++ [ { ${getsubname fid app.identity} = getgroup fid app.identity; } ] + ) [ { ${getsubname fid 0} = getgroup fid 0; } ] cfg.apps + ) [ ] cfg.users + ); }; }; } diff --git a/options.nix b/options.nix index c8747f2..29c9a4f 100644 --- a/options.nix +++ b/options.nix @@ -76,6 +76,7 @@ in type = let inherit (types) + ints str bool package @@ -87,7 +88,7 @@ in functionTo ; in - listOf (submodule { + attrsOf (submodule { options = { name = mkOption { type = str; @@ -98,13 +99,13 @@ in verbose = mkEnableOption "launchers with verbose output"; - id = mkOption { - type = nullOr str; - default = null; + identity = mkOption { + type = ints.between 1 9999; description = '' - Freedesktop application ID. + Application identity. Identity 0 is reserved for system services. ''; }; + shareUid = mkEnableOption "sharing identity with another application"; packages = mkOption { type = listOf package; @@ -273,7 +274,7 @@ in }; }; }); - default = [ ]; + default = { }; description = '' Declaratively configured fortify apps. ''; diff --git a/test/configuration.nix b/test/configuration.nix index 6b3090c..0bee0b2 100644 --- a/test/configuration.nix +++ b/test/configuration.nix @@ -99,9 +99,10 @@ home.stateVersion = "23.05"; }; - apps = [ - { + apps = { + "cat.gensokyo.extern.foot.noEnablements" = { name = "ne-foot"; + identity = 1; verbose = true; share = pkgs.foot; packages = with pkgs; [ @@ -115,17 +116,21 @@ dbus = false; pulse = false; }; - } - { + }; + + "cat.gensokyo.extern.foot.pulseaudio" = { name = "pa-foot"; + identity = 2; verbose = true; share = pkgs.foot; packages = [ pkgs.foot ]; command = "foot"; capability.dbus = false; - } - { + }; + + "cat.gensokyo.extern.Alacritty.x11" = { name = "x11-alacritty"; + identity = 3; verbose = true; share = pkgs.alacritty; packages = with pkgs; [ @@ -142,9 +147,11 @@ dbus = false; pulse = false; }; - } - { + }; + + "cat.gensokyo.extern.foot.directWayland" = { name = "da-foot"; + identity = 4; verbose = true; insecureWayland = true; share = pkgs.foot; @@ -159,9 +166,11 @@ dbus = false; pulse = false; }; - } - { + }; + + "cat.gensokyo.extern.strace.wantFail" = { name = "strace-failure"; + identity = 5; verbose = true; share = pkgs.strace; command = "strace true"; @@ -171,7 +180,7 @@ dbus = false; pulse = false; }; - } - ]; + }; + }; }; } diff --git a/test/sandbox/case/default.nix b/test/sandbox/case/default.nix index d860b1e..21bdd4a 100644 --- a/test/sandbox/case/default.nix +++ b/test/sandbox/case/default.nix @@ -24,7 +24,7 @@ let }; callTestCase = - path: + path: identity: let tc = import path { inherit @@ -36,6 +36,7 @@ let in { name = "check-sandbox-${tc.name}"; + inherit identity; verbose = true; inherit (tc) tty @@ -51,10 +52,12 @@ let (toString (builtins.toFile "fortify-${tc.name}-want.json" (builtins.toJSON tc.want))) ]; }; + + testCaseName = name: "cat.gensokyo.fortify.test." + name; in { - preset = callTestCase ./preset.nix; - tty = callTestCase ./tty.nix; - mapuid = callTestCase ./mapuid.nix; - device = callTestCase ./device.nix; + ${testCaseName "preset"} = callTestCase ./preset.nix 1; + ${testCaseName "tty"} = callTestCase ./tty.nix 2; + ${testCaseName "mapuid"} = callTestCase ./mapuid.nix 3; + ${testCaseName "device"} = callTestCase ./device.nix 4; } diff --git a/test/sandbox/configuration.nix b/test/sandbox/configuration.nix index 903b99a..473e9d3 100644 --- a/test/sandbox/configuration.nix +++ b/test/sandbox/configuration.nix @@ -6,7 +6,6 @@ }: let testProgram = pkgs.callPackage ./tool/package.nix { inherit (config.environment.fortify.package) version; }; - testCases = import ./case lib testProgram; in { users.users = { @@ -76,11 +75,6 @@ in } ]; - apps = with testCases; [ - preset - tty - mapuid - device - ]; + apps = import ./case lib testProgram; }; }