at master 9.1 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.services.usbguard; 9 10 # valid policy options 11 policy = ( 12 lib.types.enum [ 13 "allow" 14 "block" 15 "reject" 16 "keep" 17 "apply-policy" 18 ] 19 ); 20 21 # decide what file to use for rules 22 ruleFile = if cfg.rules != null then pkgs.writeText "usbguard-rules" cfg.rules else cfg.ruleFile; 23 24 daemonConf = '' 25 # generated by nixos/modules/services/security/usbguard.nix 26 RuleFile=${ruleFile} 27 ImplicitPolicyTarget=${cfg.implicitPolicyTarget} 28 PresentDevicePolicy=${cfg.presentDevicePolicy} 29 PresentControllerPolicy=${cfg.presentControllerPolicy} 30 InsertedDevicePolicy=${cfg.insertedDevicePolicy} 31 RestoreControllerDeviceState=${lib.boolToString cfg.restoreControllerDeviceState} 32 # this does not seem useful for endusers to change 33 DeviceManagerBackend=uevent 34 IPCAllowedUsers=${lib.concatStringsSep " " cfg.IPCAllowedUsers} 35 IPCAllowedGroups=${lib.concatStringsSep " " cfg.IPCAllowedGroups} 36 IPCAccessControlFiles=/var/lib/usbguard/IPCAccessControl.d/ 37 DeviceRulesWithPort=${lib.boolToString cfg.deviceRulesWithPort} 38 # HACK: that way audit logs still land in the journal 39 AuditFilePath=/dev/null 40 ''; 41 42 daemonConfFile = pkgs.writeText "usbguard-daemon-conf" daemonConf; 43 44in 45{ 46 47 ###### interface 48 49 options = { 50 services.usbguard = { 51 enable = lib.mkEnableOption "USBGuard daemon"; 52 53 package = lib.mkPackageOption pkgs "usbguard" { }; 54 55 ruleFile = lib.mkOption { 56 type = lib.types.nullOr lib.types.path; 57 default = "/var/lib/usbguard/rules.conf"; 58 example = "/run/secrets/usbguard-rules"; 59 description = '' 60 This tells the USBGuard daemon which file to load as policy rule set. 61 62 The file can be changed manually or via the IPC interface assuming it has the right file permissions. 63 64 For more details see {manpage}`usbguard-rules.conf(5)`. 65 ''; 66 67 }; 68 rules = lib.mkOption { 69 type = lib.types.nullOr lib.types.lines; 70 default = null; 71 example = '' 72 allow with-interface equals { 08:*:* } 73 ''; 74 description = '' 75 The USBGuard daemon will load this as the policy rule set. 76 As these rules are NixOS managed they are immutable and can't 77 be changed by the IPC interface. 78 79 If you do not set this option, the USBGuard daemon will load 80 it's policy rule set from the option configured in `services.usbguard.ruleFile`. 81 82 Running `usbguard generate-policy` as root will 83 generate a config for your currently plugged in devices. 84 85 For more details see {manpage}`usbguard-rules.conf(5)`. 86 ''; 87 }; 88 89 implicitPolicyTarget = lib.mkOption { 90 type = lib.types.enum [ 91 "allow" 92 "block" 93 "reject" 94 ]; 95 default = "block"; 96 description = '' 97 How to treat USB devices that don't match any rule in the policy. 98 Target should be one of allow, block or reject (logically remove the 99 device node from the system). 100 ''; 101 }; 102 103 presentDevicePolicy = lib.mkOption { 104 type = policy; 105 default = "apply-policy"; 106 description = '' 107 How to treat USB devices that are already connected when the daemon 108 starts. Policy should be one of allow, block, reject, keep (keep 109 whatever state the device is currently in) or apply-policy (evaluate 110 the rule set for every present device). 111 ''; 112 }; 113 114 presentControllerPolicy = lib.mkOption { 115 type = policy; 116 default = "keep"; 117 description = '' 118 How to treat USB controller devices that are already connected when 119 the daemon starts. One of allow, block, reject, keep or apply-policy. 120 ''; 121 }; 122 123 insertedDevicePolicy = lib.mkOption { 124 type = lib.types.enum [ 125 "block" 126 "reject" 127 "apply-policy" 128 ]; 129 default = "apply-policy"; 130 description = '' 131 How to treat USB devices that are already connected after the daemon 132 starts. One of block, reject, apply-policy. 133 ''; 134 }; 135 136 restoreControllerDeviceState = lib.mkOption { 137 type = lib.types.bool; 138 default = false; 139 description = '' 140 The USBGuard daemon modifies some attributes of controller 141 devices like the default authorization state of new child device 142 instances. Using this setting, you can control whether the daemon 143 will try to restore the attribute values to the state before 144 modification on shutdown. 145 ''; 146 }; 147 148 IPCAllowedUsers = lib.mkOption { 149 type = lib.types.listOf lib.types.str; 150 default = [ "root" ]; 151 example = [ 152 "root" 153 "yourusername" 154 ]; 155 description = '' 156 A list of usernames that the daemon will accept IPC connections from. 157 ''; 158 }; 159 160 IPCAllowedGroups = lib.mkOption { 161 type = lib.types.listOf lib.types.str; 162 default = [ ]; 163 example = [ "wheel" ]; 164 description = '' 165 A list of groupnames that the daemon will accept IPC connections 166 from. 167 ''; 168 }; 169 170 deviceRulesWithPort = lib.mkOption { 171 type = lib.types.bool; 172 default = false; 173 description = '' 174 Generate device specific rules including the "via-port" attribute. 175 ''; 176 }; 177 178 dbus.enable = lib.mkEnableOption "USBGuard dbus daemon"; 179 }; 180 }; 181 182 ###### implementation 183 184 config = lib.mkIf cfg.enable { 185 186 environment.systemPackages = [ cfg.package ]; 187 188 systemd.services = { 189 usbguard = { 190 description = "USBGuard daemon"; 191 192 wantedBy = [ "basic.target" ]; 193 wants = [ "systemd-udevd.service" ]; 194 195 # make sure an empty rule file exists 196 preStart = ''[ -f "${ruleFile}" ] || touch ${ruleFile}''; 197 198 serviceConfig = { 199 Type = "simple"; 200 ExecStart = "${cfg.package}/bin/usbguard-daemon -P -k -c ${daemonConfFile}"; 201 Restart = "on-failure"; 202 203 StateDirectory = [ 204 "usbguard" 205 "usbguard/IPCAccessControl.d" 206 ]; 207 208 AmbientCapabilities = ""; 209 CapabilityBoundingSet = "CAP_CHOWN CAP_FOWNER"; 210 DeviceAllow = "/dev/null rw"; 211 DevicePolicy = "strict"; 212 IPAddressDeny = "any"; 213 LockPersonality = true; 214 MemoryDenyWriteExecute = true; 215 NoNewPrivileges = true; 216 PrivateDevices = true; 217 PrivateTmp = true; 218 ProtectControlGroups = true; 219 ProtectHome = true; 220 ProtectKernelModules = true; 221 ProtectSystem = true; 222 ReadOnlyPaths = "-/"; 223 ReadWritePaths = "-/dev/shm -/tmp"; 224 RestrictAddressFamilies = [ 225 "AF_UNIX" 226 "AF_NETLINK" 227 ]; 228 RestrictNamespaces = true; 229 RestrictRealtime = true; 230 SystemCallArchitectures = "native"; 231 SystemCallFilter = "@system-service"; 232 UMask = "0077"; 233 }; 234 }; 235 236 usbguard-dbus = lib.mkIf cfg.dbus.enable { 237 description = "USBGuard D-Bus Service"; 238 239 wantedBy = [ "multi-user.target" ]; 240 requires = [ "usbguard.service" ]; 241 242 serviceConfig = { 243 Type = "dbus"; 244 BusName = "org.usbguard1"; 245 ExecStart = "${cfg.package}/bin/usbguard-dbus --system"; 246 Restart = "on-failure"; 247 }; 248 249 aliases = [ "dbus-org.usbguard.service" ]; 250 }; 251 }; 252 253 security.polkit.extraConfig = 254 let 255 groupCheck = 256 (lib.concatStrings (map (g: "subject.isInGroup(\"${g}\") || ") cfg.IPCAllowedGroups)) + "false"; 257 in 258 lib.optionalString cfg.dbus.enable '' 259 polkit.addRule(function(action, subject) { 260 if ((action.id == "org.usbguard.Policy1.listRules" || 261 action.id == "org.usbguard.Policy1.appendRule" || 262 action.id == "org.usbguard.Policy1.removeRule" || 263 action.id == "org.usbguard.Devices1.applyDevicePolicy" || 264 action.id == "org.usbguard.Devices1.listDevices" || 265 action.id == "org.usbguard1.getParameter" || 266 action.id == "org.usbguard1.setParameter") && 267 subject.active == true && subject.local == true && 268 (${groupCheck})) { 269 return polkit.Result.YES; 270 } 271 }); 272 ''; 273 }; 274 imports = [ 275 (lib.mkRemovedOptionModule [ "services" "usbguard" "IPCAccessControlFiles" ] 276 "The usbguard module now hardcodes IPCAccessControlFiles to /var/lib/usbguard/IPCAccessControl.d." 277 ) 278 (lib.mkRemovedOptionModule [ 279 "services" 280 "usbguard" 281 "auditFilePath" 282 ] "Removed usbguard module audit log files. Audit logs can be found in the systemd journal.") 283 (lib.mkRenamedOptionModule 284 [ "services" "usbguard" "implictPolicyTarget" ] 285 [ "services" "usbguard" "implicitPolicyTarget" ] 286 ) 287 ]; 288}