Compare commits
No commits in common. "2ffca6984a03b2daa3bb114f70ea84e71439559a" and "f30a439bcd6aa97fac0f99cdd94381ae025aa64d" have entirely different histories.
2ffca6984a
...
f30a439bcd
@ -5,7 +5,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProxyPair is an upstream dbus address and a downstream socket path.
|
// ProxyPair is an upstream dbus address and a downstream socket path.
|
||||||
@ -28,61 +27,6 @@ type Config struct {
|
|||||||
Filter bool `json:"filter"`
|
Filter bool `json:"filter"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) interfaces(yield func(string) bool) {
|
|
||||||
for _, iface := range c.See {
|
|
||||||
if !yield(iface) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, iface := range c.Talk {
|
|
||||||
if !yield(iface) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, iface := range c.Own {
|
|
||||||
if !yield(iface) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for iface := range c.Call {
|
|
||||||
if !yield(iface) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for iface := range c.Broadcast {
|
|
||||||
if !yield(iface) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) checkInterfaces(segment string) error {
|
|
||||||
for iface := range c.interfaces {
|
|
||||||
/*
|
|
||||||
xdg-dbus-proxy fails without output when this condition is not met:
|
|
||||||
char *dot = strrchr (filter->interface, '.');
|
|
||||||
if (dot != NULL)
|
|
||||||
{
|
|
||||||
*dot = 0;
|
|
||||||
if (strcmp (dot + 1, "*") != 0)
|
|
||||||
filter->member = g_strdup (dot + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
trim ".*" since they are removed before searching for '.':
|
|
||||||
if (g_str_has_suffix (name, ".*"))
|
|
||||||
{
|
|
||||||
name[strlen (name) - 2] = 0;
|
|
||||||
wildcard = TRUE;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if strings.IndexByte(strings.TrimSuffix(iface, ".*"), '.') == -1 {
|
|
||||||
return &BadInterfaceError{iface, segment}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) Args(bus ProxyPair) (args []string) {
|
func (c *Config) Args(bus ProxyPair) (args []string) {
|
||||||
argc := 2 + len(c.See) + len(c.Talk) + len(c.Own) + len(c.Call) + len(c.Broadcast)
|
argc := 2 + len(c.See) + len(c.Talk) + len(c.Own) + len(c.Call) + len(c.Broadcast)
|
||||||
if c.Log {
|
if c.Log {
|
||||||
@ -119,7 +63,9 @@ func (c *Config) Args(bus ProxyPair) (args []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Load(r io.Reader) error { return json.NewDecoder(r).Decode(&c) }
|
func (c *Config) Load(r io.Reader) error {
|
||||||
|
return json.NewDecoder(r).Decode(&c)
|
||||||
|
}
|
||||||
|
|
||||||
// NewConfigFromFile opens the target config file at path and parses its contents into *Config.
|
// NewConfigFromFile opens the target config file at path and parses its contents into *Config.
|
||||||
func NewConfigFromFile(path string) (*Config, error) {
|
func NewConfigFromFile(path string) (*Config, error) {
|
||||||
|
@ -2,7 +2,6 @@ package dbus
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"sync"
|
"sync"
|
||||||
@ -15,15 +14,6 @@ import (
|
|||||||
// Overriding ProxyName will only affect Proxy instance created after the change.
|
// Overriding ProxyName will only affect Proxy instance created after the change.
|
||||||
var ProxyName = "xdg-dbus-proxy"
|
var ProxyName = "xdg-dbus-proxy"
|
||||||
|
|
||||||
type BadInterfaceError struct {
|
|
||||||
Interface string
|
|
||||||
Segment string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *BadInterfaceError) Error() string {
|
|
||||||
return fmt.Sprintf("bad interface string %q in %s bus configuration", e.Interface, e.Segment)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Proxy holds the state of a xdg-dbus-proxy process, and should never be copied.
|
// Proxy holds the state of a xdg-dbus-proxy process, and should never be copied.
|
||||||
type Proxy struct {
|
type Proxy struct {
|
||||||
helper helper.Helper
|
helper helper.Helper
|
||||||
@ -76,15 +66,9 @@ func Finalise(sessionBus, systemBus ProxyPair, session, system *Config) (final *
|
|||||||
|
|
||||||
var args []string
|
var args []string
|
||||||
if session != nil {
|
if session != nil {
|
||||||
if err = session.checkInterfaces("session"); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
args = append(args, session.Args(sessionBus)...)
|
args = append(args, session.Args(sessionBus)...)
|
||||||
}
|
}
|
||||||
if system != nil {
|
if system != nil {
|
||||||
if err = system.checkInterfaces("system"); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
args = append(args, system.Args(systemBus)...)
|
args = append(args, system.Args(systemBus)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
145
nixos.nix
145
nixos.nix
@ -8,10 +8,12 @@ packages:
|
|||||||
|
|
||||||
let
|
let
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
lists
|
|
||||||
mkMerge
|
mkMerge
|
||||||
mkIf
|
mkIf
|
||||||
mapAttrs
|
mapAttrs
|
||||||
|
mergeAttrsList
|
||||||
|
imap1
|
||||||
|
foldr
|
||||||
foldlAttrs
|
foldlAttrs
|
||||||
optional
|
optional
|
||||||
optionals
|
optionals
|
||||||
@ -28,27 +30,6 @@ in
|
|||||||
imports = [ (import ./options.nix packages) ];
|
imports = [ (import ./options.nix packages) ];
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
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 = {
|
security.wrappers.fsu = {
|
||||||
source = "${cfg.fsuPackage}/bin/fsu";
|
source = "${cfg.fsuPackage}/bin/fsu";
|
||||||
setuid = true;
|
setuid = true;
|
||||||
@ -68,19 +49,22 @@ in
|
|||||||
home-manager =
|
home-manager =
|
||||||
let
|
let
|
||||||
privPackages = mapAttrs (username: fid: {
|
privPackages = mapAttrs (username: fid: {
|
||||||
home.packages = foldlAttrs (
|
home.packages =
|
||||||
acc: id: app:
|
let
|
||||||
[
|
# aid 0 is reserved
|
||||||
(
|
wrappers = imap1 (
|
||||||
|
aid: app:
|
||||||
let
|
let
|
||||||
extendDBusDefault = id: ext: {
|
extendDBusDefault = id: ext: {
|
||||||
filter = true;
|
filter = true;
|
||||||
|
|
||||||
talk = [ "org.freedesktop.Notifications" ] ++ ext.talk;
|
talk = [ "org.freedesktop.Notifications" ] ++ ext.talk;
|
||||||
own = [
|
own =
|
||||||
"${id}.*"
|
(optionals (app.id != null) [
|
||||||
"org.mpris.MediaPlayer2.${id}.*"
|
"${id}.*"
|
||||||
] ++ ext.own;
|
"org.mpris.MediaPlayer2.${id}.*"
|
||||||
|
])
|
||||||
|
++ ext.own;
|
||||||
|
|
||||||
inherit (ext) call broadcast;
|
inherit (ext) call broadcast;
|
||||||
};
|
};
|
||||||
@ -94,7 +78,7 @@ in
|
|||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
session_bus = if app.dbus.session != null then (app.dbus.session (extendDBusDefault id)) else (extendDBusDefault id default);
|
session_bus = if app.dbus.session != null then (app.dbus.session (extendDBusDefault app.id)) else (extendDBusDefault app.id default);
|
||||||
system_bus = app.dbus.system;
|
system_bus = app.dbus.system;
|
||||||
};
|
};
|
||||||
command = if app.command == null then app.name else app.command;
|
command = if app.command == null then app.name else app.command;
|
||||||
@ -103,6 +87,8 @@ in
|
|||||||
isGraphical = if app.gpu != null then app.gpu else app.capability.wayland || app.capability.x11;
|
isGraphical = if app.gpu != null then app.gpu else app.capability.wayland || app.capability.x11;
|
||||||
|
|
||||||
conf = {
|
conf = {
|
||||||
|
inherit (app) id;
|
||||||
|
|
||||||
path =
|
path =
|
||||||
if app.path == null then
|
if app.path == null then
|
||||||
pkgs.writeScript "${app.name}-start" ''
|
pkgs.writeScript "${app.name}-start" ''
|
||||||
@ -113,15 +99,16 @@ in
|
|||||||
app.path;
|
app.path;
|
||||||
args = if app.args == null then [ "${app.name}-start" ] else app.args;
|
args = if app.args == null then [ "${app.name}-start" ] else app.args;
|
||||||
|
|
||||||
inherit id enablements;
|
inherit enablements;
|
||||||
|
|
||||||
inherit (dbusConfig) session_bus system_bus;
|
inherit (dbusConfig) session_bus system_bus;
|
||||||
direct_wayland = app.insecureWayland;
|
direct_wayland = app.insecureWayland;
|
||||||
|
|
||||||
username = getsubname fid app.identity;
|
username = getsubname fid aid;
|
||||||
data = getsubhome fid app.identity;
|
data = getsubhome fid aid;
|
||||||
|
|
||||||
inherit (app) identity groups;
|
identity = aid;
|
||||||
|
inherit (app) groups;
|
||||||
|
|
||||||
container = {
|
container = {
|
||||||
inherit (app)
|
inherit (app)
|
||||||
@ -201,9 +188,10 @@ in
|
|||||||
pkgs.writeShellScriptBin app.name ''
|
pkgs.writeShellScriptBin app.name ''
|
||||||
exec fortify${if app.verbose then " -v" else ""} app ${pkgs.writeText "fortify-${app.name}.json" (builtins.toJSON conf)} $@
|
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
|
let
|
||||||
pkg = if app.share != null then app.share else pkgs.${app.name};
|
pkg = if app.share != null then app.share else pkgs.${app.name};
|
||||||
copy = source: "[ -d '${source}' ] && cp -Lrv '${source}' $out/share || true";
|
copy = source: "[ -d '${source}' ] && cp -Lrv '${source}' $out/share || true";
|
||||||
@ -223,33 +211,30 @@ in
|
|||||||
fi
|
fi
|
||||||
''
|
''
|
||||||
)
|
)
|
||||||
)
|
++ acc
|
||||||
++ acc
|
) (wrappers ++ [ cfg.package ]) cfg.apps;
|
||||||
) [ cfg.package ] cfg.apps;
|
|
||||||
}) cfg.users;
|
}) cfg.users;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
useUserPackages = false; # prevent users.users entries from being added
|
useUserPackages = false; # prevent users.users entries from being added
|
||||||
|
|
||||||
users = mkMerge (
|
users = foldlAttrs (
|
||||||
foldlAttrs (
|
acc: _: fid:
|
||||||
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; }
|
||||||
acc
|
acc
|
||||||
++ foldlAttrs (
|
]
|
||||||
acc': _: app:
|
) privPackages cfg.users;
|
||||||
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 =
|
users =
|
||||||
@ -265,27 +250,33 @@ in
|
|||||||
getgroup = fid: aid: { gid = getsubuid fid aid; };
|
getgroup = fid: aid: { gid = getsubuid fid aid; };
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
users = mkMerge (
|
users = foldlAttrs (
|
||||||
foldlAttrs (
|
acc: _: fid:
|
||||||
acc: _: fid:
|
mkMerge [
|
||||||
|
(mergeAttrsList (
|
||||||
|
# aid 0 is reserved
|
||||||
|
imap1 (aid: _: {
|
||||||
|
${getsubname fid aid} = getuser fid aid;
|
||||||
|
}) cfg.apps
|
||||||
|
))
|
||||||
|
{ ${getsubname fid 0} = getuser fid 0; }
|
||||||
acc
|
acc
|
||||||
++ foldlAttrs (
|
]
|
||||||
acc': _: app:
|
) { } cfg.users;
|
||||||
acc' ++ [ { ${getsubname fid app.identity} = getuser fid app.identity; } ]
|
|
||||||
) [ { ${getsubname fid 0} = getuser fid 0; } ] cfg.apps
|
|
||||||
) [ ] cfg.users
|
|
||||||
);
|
|
||||||
|
|
||||||
groups = mkMerge (
|
groups = foldlAttrs (
|
||||||
foldlAttrs (
|
acc: _: fid:
|
||||||
acc: _: fid:
|
mkMerge [
|
||||||
|
(mergeAttrsList (
|
||||||
|
# aid 0 is reserved
|
||||||
|
imap1 (aid: _: {
|
||||||
|
${getsubname fid aid} = getgroup fid aid;
|
||||||
|
}) cfg.apps
|
||||||
|
))
|
||||||
|
{ ${getsubname fid 0} = getgroup fid 0; }
|
||||||
acc
|
acc
|
||||||
++ foldlAttrs (
|
]
|
||||||
acc': _: app:
|
) { } cfg.users;
|
||||||
acc' ++ [ { ${getsubname fid app.identity} = getgroup fid app.identity; } ]
|
|
||||||
) [ { ${getsubname fid 0} = getgroup fid 0; } ] cfg.apps
|
|
||||||
) [ ] cfg.users
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
13
options.nix
13
options.nix
@ -76,7 +76,6 @@ in
|
|||||||
type =
|
type =
|
||||||
let
|
let
|
||||||
inherit (types)
|
inherit (types)
|
||||||
ints
|
|
||||||
str
|
str
|
||||||
bool
|
bool
|
||||||
package
|
package
|
||||||
@ -88,7 +87,7 @@ in
|
|||||||
functionTo
|
functionTo
|
||||||
;
|
;
|
||||||
in
|
in
|
||||||
attrsOf (submodule {
|
listOf (submodule {
|
||||||
options = {
|
options = {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
type = str;
|
type = str;
|
||||||
@ -99,13 +98,13 @@ in
|
|||||||
|
|
||||||
verbose = mkEnableOption "launchers with verbose output";
|
verbose = mkEnableOption "launchers with verbose output";
|
||||||
|
|
||||||
identity = mkOption {
|
id = mkOption {
|
||||||
type = ints.between 1 9999;
|
type = nullOr str;
|
||||||
|
default = null;
|
||||||
description = ''
|
description = ''
|
||||||
Application identity. Identity 0 is reserved for system services.
|
Freedesktop application ID.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
shareUid = mkEnableOption "sharing identity with another application";
|
|
||||||
|
|
||||||
packages = mkOption {
|
packages = mkOption {
|
||||||
type = listOf package;
|
type = listOf package;
|
||||||
@ -274,7 +273,7 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
default = { };
|
default = [ ];
|
||||||
description = ''
|
description = ''
|
||||||
Declaratively configured fortify apps.
|
Declaratively configured fortify apps.
|
||||||
'';
|
'';
|
||||||
|
@ -99,10 +99,9 @@
|
|||||||
home.stateVersion = "23.05";
|
home.stateVersion = "23.05";
|
||||||
};
|
};
|
||||||
|
|
||||||
apps = {
|
apps = [
|
||||||
"cat.gensokyo.extern.foot.noEnablements" = {
|
{
|
||||||
name = "ne-foot";
|
name = "ne-foot";
|
||||||
identity = 1;
|
|
||||||
verbose = true;
|
verbose = true;
|
||||||
share = pkgs.foot;
|
share = pkgs.foot;
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
@ -116,21 +115,17 @@
|
|||||||
dbus = false;
|
dbus = false;
|
||||||
pulse = false;
|
pulse = false;
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
{
|
||||||
"cat.gensokyo.extern.foot.pulseaudio" = {
|
|
||||||
name = "pa-foot";
|
name = "pa-foot";
|
||||||
identity = 2;
|
|
||||||
verbose = true;
|
verbose = true;
|
||||||
share = pkgs.foot;
|
share = pkgs.foot;
|
||||||
packages = [ pkgs.foot ];
|
packages = [ pkgs.foot ];
|
||||||
command = "foot";
|
command = "foot";
|
||||||
capability.dbus = false;
|
capability.dbus = false;
|
||||||
};
|
}
|
||||||
|
{
|
||||||
"cat.gensokyo.extern.Alacritty.x11" = {
|
|
||||||
name = "x11-alacritty";
|
name = "x11-alacritty";
|
||||||
identity = 3;
|
|
||||||
verbose = true;
|
verbose = true;
|
||||||
share = pkgs.alacritty;
|
share = pkgs.alacritty;
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
@ -147,11 +142,9 @@
|
|||||||
dbus = false;
|
dbus = false;
|
||||||
pulse = false;
|
pulse = false;
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
{
|
||||||
"cat.gensokyo.extern.foot.directWayland" = {
|
|
||||||
name = "da-foot";
|
name = "da-foot";
|
||||||
identity = 4;
|
|
||||||
verbose = true;
|
verbose = true;
|
||||||
insecureWayland = true;
|
insecureWayland = true;
|
||||||
share = pkgs.foot;
|
share = pkgs.foot;
|
||||||
@ -166,11 +159,9 @@
|
|||||||
dbus = false;
|
dbus = false;
|
||||||
pulse = false;
|
pulse = false;
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
{
|
||||||
"cat.gensokyo.extern.strace.wantFail" = {
|
|
||||||
name = "strace-failure";
|
name = "strace-failure";
|
||||||
identity = 5;
|
|
||||||
verbose = true;
|
verbose = true;
|
||||||
share = pkgs.strace;
|
share = pkgs.strace;
|
||||||
command = "strace true";
|
command = "strace true";
|
||||||
@ -180,7 +171,7 @@
|
|||||||
dbus = false;
|
dbus = false;
|
||||||
pulse = false;
|
pulse = false;
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
};
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ let
|
|||||||
};
|
};
|
||||||
|
|
||||||
callTestCase =
|
callTestCase =
|
||||||
path: identity:
|
path:
|
||||||
let
|
let
|
||||||
tc = import path {
|
tc = import path {
|
||||||
inherit
|
inherit
|
||||||
@ -36,7 +36,6 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
name = "check-sandbox-${tc.name}";
|
name = "check-sandbox-${tc.name}";
|
||||||
inherit identity;
|
|
||||||
verbose = true;
|
verbose = true;
|
||||||
inherit (tc)
|
inherit (tc)
|
||||||
tty
|
tty
|
||||||
@ -52,12 +51,10 @@ let
|
|||||||
(toString (builtins.toFile "fortify-${tc.name}-want.json" (builtins.toJSON tc.want)))
|
(toString (builtins.toFile "fortify-${tc.name}-want.json" (builtins.toJSON tc.want)))
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
testCaseName = name: "cat.gensokyo.fortify.test." + name;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
${testCaseName "preset"} = callTestCase ./preset.nix 1;
|
preset = callTestCase ./preset.nix;
|
||||||
${testCaseName "tty"} = callTestCase ./tty.nix 2;
|
tty = callTestCase ./tty.nix;
|
||||||
${testCaseName "mapuid"} = callTestCase ./mapuid.nix 3;
|
mapuid = callTestCase ./mapuid.nix;
|
||||||
${testCaseName "device"} = callTestCase ./device.nix 4;
|
device = callTestCase ./device.nix;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
testProgram = pkgs.callPackage ./tool/package.nix { inherit (config.environment.fortify.package) version; };
|
testProgram = pkgs.callPackage ./tool/package.nix { inherit (config.environment.fortify.package) version; };
|
||||||
|
testCases = import ./case lib testProgram;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
users.users = {
|
users.users = {
|
||||||
@ -75,6 +76,11 @@ in
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
apps = import ./case lib testProgram;
|
apps = with testCases; [
|
||||||
|
preset
|
||||||
|
tty
|
||||||
|
mapuid
|
||||||
|
device
|
||||||
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user