nixos/home-assistant: harden systemd service
This is what is still exposed, and it should still allow things to work as usual. ✗ PrivateNetwork= Service has access to the host's … 0.5 ✗ RestrictAddressFamilies=~AF_(INET… Service may allocate Internet soc… 0.3 ✗ DeviceAllow= Service has a device ACL with som… 0.1 ✗ IPAddressDeny= Service does not define an IP add… 0.2 ✗ PrivateDevices= Service potentially has access to… 0.2 ✗ PrivateUsers= Service has access to other users 0.2 ✗ SystemCallFilter=~@resources System call allow list defined fo… 0.2 ✗ RootDirectory=/RootImage= Service runs within the host's ro… 0.1 ✗ SupplementaryGroups= Service runs with supplementary g… 0.1 ✗ RestrictAddressFamilies=~AF_UNIX Service may allocate local sockets 0.1 → Overall exposure level for home-assistant.service: 1.6 OK :-) This can grow to as much as ~1.9 if you use one of the bluetooth or nmap trackers or the emulated_hue component, all of which required elevated permisssions.
This commit is contained in:
parent
4518794ee5
commit
7d09d7f571
1 changed files with 66 additions and 6 deletions
|
@ -245,22 +245,83 @@ in {
|
||||||
rm -f "${cfg.configDir}/ui-lovelace.yaml"
|
rm -f "${cfg.configDir}/ui-lovelace.yaml"
|
||||||
ln -s ${lovelaceConfigFile} "${cfg.configDir}/ui-lovelace.yaml"
|
ln -s ${lovelaceConfigFile} "${cfg.configDir}/ui-lovelace.yaml"
|
||||||
'');
|
'');
|
||||||
serviceConfig = {
|
serviceConfig = let
|
||||||
|
# List of capabilities to equip home-assistant with, depending on configured components
|
||||||
|
capabilities = [
|
||||||
|
# Empty string first, so we will never accidentally have an empty capability bounding set
|
||||||
|
# https://github.com/NixOS/nixpkgs/issues/120617#issuecomment-830685115
|
||||||
|
""
|
||||||
|
] ++ (unique (optionals (useComponent "bluetooth_tracker" || useComponent "bluetooth_le_tracker") [
|
||||||
|
# Required for interaction with hci devices and bluetooth sockets
|
||||||
|
# https://www.home-assistant.io/integrations/bluetooth_le_tracker/#rootless-setup-on-core-installs
|
||||||
|
"CAP_NET_ADMIN"
|
||||||
|
"CAP_NET_RAW"
|
||||||
|
] ++ lib.optionals (useComponent "emulated_hue") [
|
||||||
|
# Alexa looks for the service on port 80
|
||||||
|
# https://www.home-assistant.io/integrations/emulated_hue
|
||||||
|
"CAP_NET_BIND_SERVICE"
|
||||||
|
] ++ lib.optionals (useComponent "nmap_tracker") [
|
||||||
|
# https://www.home-assistant.io/integrations/nmap_tracker#linux-capabilities
|
||||||
|
"CAP_NET_ADMIN"
|
||||||
|
"CAP_NET_BIND_SERVICE"
|
||||||
|
"CAP_NET_RAW"
|
||||||
|
]));
|
||||||
|
in {
|
||||||
ExecStart = "${package}/bin/hass --config '${cfg.configDir}'";
|
ExecStart = "${package}/bin/hass --config '${cfg.configDir}'";
|
||||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||||
User = "hass";
|
User = "hass";
|
||||||
Group = "hass";
|
Group = "hass";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
|
KillSignal = "SIGINT";
|
||||||
|
|
||||||
|
# Hardening
|
||||||
|
AmbientCapabilities = capabilities;
|
||||||
|
CapabilityBoundingSet = capabilities;
|
||||||
|
DeviceAllow = [
|
||||||
|
"char-ttyACM rw"
|
||||||
|
"char-ttyAMA rw"
|
||||||
|
"char-ttyUSB rw"
|
||||||
|
];
|
||||||
|
DevicePolicy = "closed";
|
||||||
|
LockPersonality = true;
|
||||||
|
MemoryDenyWriteExecute = true;
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
PrivateTmp = true;
|
||||||
|
PrivateUsers = false; # prevents gaining capabilities in the host namespace
|
||||||
|
ProtectClock = true;
|
||||||
|
ProtectControlGroups = true;
|
||||||
|
ProtectHome = true;
|
||||||
|
ProtectHostname = true;
|
||||||
|
ProtectKernelLogs = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
ProtectKernelTunables = true;
|
||||||
|
ProtectProc = "invisible";
|
||||||
|
ProcSubset = "pid";
|
||||||
ProtectSystem = "strict";
|
ProtectSystem = "strict";
|
||||||
|
RemoveIPC = true;
|
||||||
ReadWritePaths = let
|
ReadWritePaths = let
|
||||||
|
# Allow rw access to explicitly configured paths
|
||||||
cfgPath = [ "config" "homeassistant" "allowlist_external_dirs" ];
|
cfgPath = [ "config" "homeassistant" "allowlist_external_dirs" ];
|
||||||
value = attrByPath cfgPath [] cfg;
|
value = attrByPath cfgPath [] cfg;
|
||||||
allowPaths = if isList value then value else singleton value;
|
allowPaths = if isList value then value else singleton value;
|
||||||
in [ "${cfg.configDir}" ] ++ allowPaths;
|
in [ "${cfg.configDir}" ] ++ allowPaths;
|
||||||
KillSignal = "SIGINT";
|
RestrictAddressFamilies = [
|
||||||
PrivateTmp = true;
|
"AF_UNIX"
|
||||||
RemoveIPC = true;
|
"AF_INET"
|
||||||
AmbientCapabilities = "cap_net_raw,cap_net_admin+eip";
|
"AF_INET6"
|
||||||
|
] ++ optionals (useComponent "bluetooth_tracker" || useComponent "bluetooth_le_tracker") [
|
||||||
|
"AF_BLUETOOTH"
|
||||||
|
];
|
||||||
|
RestrictNamespaces = true;
|
||||||
|
RestrictRealtime = true;
|
||||||
|
RestrictSUIDSGID = true;
|
||||||
|
SupplementaryGroups = [ "dialout" ];
|
||||||
|
SystemCallArchitectures = "native";
|
||||||
|
SystemCallFilter = [
|
||||||
|
"@system-service"
|
||||||
|
"~@privileged"
|
||||||
|
];
|
||||||
|
UMask = "0077";
|
||||||
};
|
};
|
||||||
path = [
|
path = [
|
||||||
"/run/wrappers" # needed for ping
|
"/run/wrappers" # needed for ping
|
||||||
|
@ -278,7 +339,6 @@ in {
|
||||||
home = cfg.configDir;
|
home = cfg.configDir;
|
||||||
createHome = true;
|
createHome = true;
|
||||||
group = "hass";
|
group = "hass";
|
||||||
extraGroups = [ "dialout" ];
|
|
||||||
uid = config.ids.uids.hass;
|
uid = config.ids.uids.hass;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue