1 { config, lib, pkgs, ... }:
4 inherit (builtins) attrNames head match readFile;
6 inherit (config.environment) etc;
7 cfg = config.security.apparmor;
13 enable = lib.mkEnableOption "Enable the AppArmor Mandatory Access Control system.";
14 profiles = lib.mkOption {
15 type = types.attrsOf types.lines;
18 Available AppArmor profiles.
20 apply = lib.mapAttrs (name: text: pkgs.writeText "${name}" text);
22 enforceProfiles = lib.mkOption {
23 type = (types.listOf (types.enum (attrNames cfg.profiles))) // {
24 description = "list of profiles";
27 description = "List of AppArmor profiles to be enforced.";
29 complainProfiles = lib.mkOption {
30 type = (types.listOf (types.enum (attrNames cfg.profiles))) // {
31 description = "list of profiles";
34 description = "List of AppArmor profiles to be complained.";
36 includes = lib.mkOption {
37 type = types.listOf types.path;
40 List of paths to be added to AppArmor's searched paths
41 when resolving absolute #include directives.
47 config = lib.mkIf cfg.enable {
48 environment.systemPackages = [ pkgs.apparmor-utils ];
49 environment.etc."apparmor.d".source = pkgs.linkFarm "apparmor.d" (
50 lib.mapAttrsToList (name: path: {inherit name path;}) cfg.profiles
52 environment.etc."apparmor/parser.conf".text =
53 lib.concatMapStringsSep "\n" (p: "#Include ${p}") cfg.includes;
54 environment.etc."apparmor/logprof.conf".text = ''
56 profiledir = /etc/apparmor.d /etc/subdomain.d
57 inactive_profiledir = ${pkgs.apparmor-profiles}/share/apparmor/extra-profiles
58 logfiles = /var/log/audit/audit.log /var/log/syslog /var/log/messages
60 parser = ${pkgs.apparmor-parser}/bin/apparmor_parser ${pkgs.apparmor-parser}/bin/subdomain_parser
61 ldd = ${pkgs.glibc.bin}/bin/ldd
62 logger = ${pkgs.utillinux}/bin/logger
64 # customize how file ownership permissions are presented
66 # 1 - default of what ever mode the log reported
67 # 2 - force the new permissions to be user
68 # 3 - force all perms on the rule to be user
69 default_owner_prompt = 1
71 # custom directory locations to look for #includes
73 # each name should be a valid directory containing possible #include
74 # candidate files under the profile dir which by default is /etc/apparmor.d.
76 # So an entry of my-includes will allow /etc/apparmor.d/my-includes to
77 # be used by the yast UI and profiling tools as a source of #include
82 ${pkgs.runtimeShell} = icnu
83 '' + head (match "^.*\\[qualifiers](.*)" (readFile "${pkgs.apparmor-utils}/etc/apparmor/logprof.conf"));
84 security.apparmor.profiles = {
85 "abstractions/tunables/alias" = ''
86 alias /bin -> /run/current-system/sw/bin,
87 #alias /etc -> /run/current-system/etc,
88 alias /lib/modules -> /run/current-system/kernel/lib/modules,
89 alias /sbin -> /run/current-system/sw/sbin,
90 alias /usr -> /run/current-system/sw,
92 "abstractions/base" = ''
93 #include ${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base
94 ${etc."hosts".source} r,
95 /etc/ld-nix.so.preload r,
96 ${etc."ld-nix.so.preload".source} r,
97 ${lib.concatMapStrings (p: lib.optionalString (p != "") (p+" mr,\n"))
98 (lib.splitString "\n" etc."ld-nix.so.preload".text)}
99 ${pkgs.tzdata}/share/zoneinfo/** r,
101 "abstractions/consoles" = ''
102 #include ${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/consoles
104 "abstractions/ldapclient" = ''
105 #include ${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/ldapclient
107 "abstractions/kerberosclient" = ''
108 #include ${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/kerberosclient
110 "abstractions/likewise" = ''
111 #include ${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/likewise
113 "abstractions/mdns" = ''
114 #include ${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/mdns
116 "abstractions/nameservice" = ''
117 #include ${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice
119 "abstractions/nis" = ''
120 #include ${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nis
122 "abstractions/ssl_certs" = ''
123 #include ${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/ssl_certs
124 ${etc."ssl/certs/ca-certificates.crt".source} r,
125 ${etc."ssl/certs/ca-bundle.crt".source} r,
127 "abstractions/winbind" = ''
128 #include ${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/winbind
131 security.apparmor.includes = [ (pkgs.apparmor-profiles+"/etc/apparmor.d/") ];
133 boot.kernelParams = [ "apparmor=1" "security=apparmor" ];
135 systemd.services.apparmor = {
136 after = [ "local-fs.target" ];
137 before = [ "sysinit.target" ];
138 wantedBy = [ "multi-user.target" ];
140 DefaultDependencies = "no";
143 let includes = lib.concatMapStringsSep " " (p: "-I ${p}") cfg.includes;
146 RemainAfterExit = "yes";
148 map (p: ''${pkgs.apparmor-parser}/bin/apparmor_parser -rKv ${includes} "${cfg.profiles."${p}"}"'') cfg.enforceProfiles ++
149 map (p: ''${pkgs.apparmor-parser}/bin/apparmor_parser -rKvC ${includes} "${cfg.profiles."${p}"}"'') cfg.complainProfiles;
151 map (p: ''${pkgs.apparmor-parser}/bin/apparmor_parser -Rv ${includes} "${cfg.profiles."${p}"}"'') cfg.enforceProfiles ++
152 map (p: ''${pkgs.apparmor-parser}/bin/apparmor_parser -RvC ${includes} "${cfg.profiles."${p}"}"'') cfg.complainProfiles;
154 map (p: ''${pkgs.apparmor-parser}/bin/apparmor_parser --reload ${includes} "${cfg.profiles."${p}"}"'') cfg.enforceProfiles ++
155 map (p: ''${pkgs.apparmor-parser}/bin/apparmor_parser --reload -C ${includes} "${cfg.profiles."${p}"}"'') cfg.complainProfiles;
160 meta.maintainers = with lib.maintainers; [ julm ];