fortify/nixos.nix
Ophestra 2ffca6984a
All checks were successful
Test / Create distribution (push) Successful in 19s
Test / Sandbox (push) Successful in 31s
Test / Fortify (push) Successful in 35s
Test / Sandbox (race detector) (push) Successful in 31s
Test / Fortify (race detector) (push) Successful in 35s
Test / Fpkg (push) Successful in 33s
Test / Flake checks (push) Successful in 1m7s
nix: use reverse-DNS style id as unique identifier
Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-05-25 20:12:30 +09:00

292 lines
9.6 KiB
Nix

packages:
{
lib,
pkgs,
config,
...
}:
let
inherit (lib)
lists
mkMerge
mkIf
mapAttrs
foldlAttrs
optional
optionals
;
cfg = config.environment.fortify;
getsubuid = fid: aid: 1000000 + fid * 10000 + aid;
getsubname = fid: aid: "u${toString fid}_a${toString aid}";
getsubhome = fid: aid: "${cfg.stateDir}/u${toString fid}/a${toString aid}";
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;
owner = "root";
setgid = true;
group = "root";
};
environment.etc.fsurc = {
mode = "0400";
text = foldlAttrs (
acc: username: fid:
"${toString config.users.users.${username}.uid} ${toString fid}\n" + acc
) "" cfg.users;
};
home-manager =
let
privPackages = mapAttrs (username: fid: {
home.packages = foldlAttrs (
acc: id: app:
[
(
let
extendDBusDefault = id: ext: {
filter = true;
talk = [ "org.freedesktop.Notifications" ] ++ ext.talk;
own = [
"${id}.*"
"org.mpris.MediaPlayer2.${id}.*"
] ++ ext.own;
inherit (ext) call broadcast;
};
dbusConfig =
let
default = {
talk = [ ];
own = [ ];
call = { };
broadcast = { };
};
in
{
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;
script = if app.script == null then ("exec " + command + " $@") else app.script;
enablements = with app.capability; (if wayland then 1 else 0) + (if x11 then 2 else 0) + (if dbus then 4 else 0) + (if pulse then 8 else 0);
isGraphical = if app.gpu != null then app.gpu else app.capability.wayland || app.capability.x11;
conf = {
path =
if app.path == null then
pkgs.writeScript "${app.name}-start" ''
#!${pkgs.zsh}${pkgs.zsh.shellPath}
${script}
''
else
app.path;
args = if app.args == null then [ "${app.name}-start" ] else app.args;
inherit id enablements;
inherit (dbusConfig) session_bus system_bus;
direct_wayland = app.insecureWayland;
username = getsubname fid app.identity;
data = getsubhome fid app.identity;
inherit (app) identity groups;
container = {
inherit (app)
devel
userns
net
device
tty
multiarch
env
;
map_real_uid = app.mapRealUid;
filesystem =
let
bind = src: { inherit src; };
mustBind = src: {
inherit src;
require = true;
};
devBind = src: {
inherit src;
dev = true;
};
in
[
(mustBind "/bin")
(mustBind "/usr/bin")
(mustBind "/nix/store")
(bind "/sys/block")
(bind "/sys/bus")
(bind "/sys/class")
(bind "/sys/dev")
(bind "/sys/devices")
]
++ optionals app.nix [
(mustBind "/nix/var")
]
++ optionals isGraphical [
(devBind "/dev/dri")
(devBind "/dev/nvidiactl")
(devBind "/dev/nvidia-modeset")
(devBind "/dev/nvidia-uvm")
(devBind "/dev/nvidia-uvm-tools")
(devBind "/dev/nvidia0")
]
++ optionals app.useCommonPaths cfg.commonPaths
++ app.extraPaths;
auto_etc = true;
cover = [ "/var/run/nscd" ];
symlink =
[
[
"*/run/current-system"
"/run/current-system"
]
]
++ optionals (isGraphical && config.hardware.graphics.enable) (
[
[
config.systemd.tmpfiles.settings.graphics-driver."/run/opengl-driver"."L+".argument
"/run/opengl-driver"
]
]
++ optionals (app.multiarch && config.hardware.graphics.enable32Bit) [
[
config.systemd.tmpfiles.settings.graphics-driver."/run/opengl-driver-32"."L+".argument
/run/opengl-driver-32
]
]
);
};
};
in
pkgs.writeShellScriptBin app.name ''
exec fortify${if app.verbose then " -v" else ""} app ${pkgs.writeText "fortify-${app.name}.json" (builtins.toJSON conf)} $@
''
)
]
++ (
let
pkg = if app.share != null then app.share else pkgs.${app.name};
copy = source: "[ -d '${source}' ] && cp -Lrv '${source}' $out/share || true";
in
optional (app.capability.wayland || app.capability.x11) (
pkgs.runCommand "${app.name}-share" { } ''
mkdir -p $out/share
${copy "${pkg}/share/applications"}
${copy "${pkg}/share/pixmaps"}
${copy "${pkg}/share/icons"}
${copy "${pkg}/share/man"}
if test -d "$out/share/applications"; then
substituteInPlace $out/share/applications/* \
--replace-warn '${pkg}/bin/' "" \
--replace-warn '${pkg}/libexec/' ""
fi
''
)
)
++ acc
) [ cfg.package ] cfg.apps;
}) cfg.users;
in
{
useUserPackages = false; # prevent users.users entries from being added
users = mkMerge (
foldlAttrs (
acc: _: fid:
acc
++ 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 =
let
getuser = fid: aid: {
isSystemUser = true;
createHome = true;
description = "Fortify subordinate user ${toString aid} (u${toString fid})";
group = getsubname fid aid;
home = getsubhome fid aid;
uid = getsubuid fid aid;
};
getgroup = fid: aid: { gid = getsubuid fid aid; };
in
{
users = mkMerge (
foldlAttrs (
acc: _: fid:
acc
++ foldlAttrs (
acc': _: app:
acc' ++ [ { ${getsubname fid app.identity} = getuser fid app.identity; } ]
) [ { ${getsubname fid 0} = getuser fid 0; } ] cfg.apps
) [ ] cfg.users
);
groups = mkMerge (
foldlAttrs (
acc: _: fid:
acc
++ foldlAttrs (
acc': _: app:
acc' ++ [ { ${getsubname fid app.identity} = getgroup fid app.identity; } ]
) [ { ${getsubname fid 0} = getgroup fid 0; } ] cfg.apps
) [ ] cfg.users
);
};
};
}