grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / security / aesmd.nix
blob864d408c0220a9a728eaed5eb9e7f51ee34c7492
1 { config, options, pkgs, lib, ... }:
2 with lib;
3 let
4   cfg = config.services.aesmd;
5   opt = options.services.aesmd;
7   sgx-psw = pkgs.sgx-psw.override { inherit (cfg) debug; };
9   configFile = with cfg.settings; pkgs.writeText "aesmd.conf" (
10     concatStringsSep "\n" (
11       optional (whitelistUrl != null) "whitelist url = ${whitelistUrl}" ++
12       optional (proxy != null) "aesm proxy = ${proxy}" ++
13       optional (proxyType != null) "proxy type = ${proxyType}" ++
14       optional (defaultQuotingType != null) "default quoting type = ${defaultQuotingType}" ++
15       # Newline at end of file
16       [ "" ]
17     )
18   );
21   options.services.aesmd = {
22     enable = mkEnableOption "Intel's Architectural Enclave Service Manager (AESM) for Intel SGX";
23     debug = mkOption {
24       type = types.bool;
25       default = false;
26       description = "Whether to build the PSW package in debug mode.";
27     };
28     environment = mkOption {
29       type = with types; attrsOf str;
30       default = { };
31       description = "Additional environment variables to pass to the AESM service.";
32       # Example environment variable for `sgx-azure-dcap-client` provider library
33       example = {
34         AZDCAP_COLLATERAL_VERSION = "v2";
35         AZDCAP_DEBUG_LOG_LEVEL = "INFO";
36       };
37     };
38     quoteProviderLibrary = mkOption {
39       type = with types; nullOr path;
40       default = null;
41       example = literalExpression "pkgs.sgx-azure-dcap-client";
42       description = "Custom quote provider library to use.";
43     };
44     settings = mkOption {
45       description = "AESM configuration";
46       default = { };
47       type = types.submodule {
48         options.whitelistUrl = mkOption {
49           type = with types; nullOr str;
50           default = null;
51           example = "http://whitelist.trustedservices.intel.com/SGX/LCWL/Linux/sgx_white_list_cert.bin";
52           description = "URL to retrieve authorized Intel SGX enclave signers.";
53         };
54         options.proxy = mkOption {
55           type = with types; nullOr str;
56           default = null;
57           example = "http://proxy_url:1234";
58           description = "HTTP network proxy.";
59         };
60         options.proxyType = mkOption {
61           type = with types; nullOr (enum [ "default" "direct" "manual" ]);
62           default = if (cfg.settings.proxy != null) then "manual" else null;
63           defaultText = literalExpression ''
64             if (config.${opt.settings}.proxy != null) then "manual" else null
65           '';
66           example = "default";
67           description = ''
68             Type of proxy to use. The `default` uses the system's default proxy.
69             If `direct` is given, uses no proxy.
70             A value of `manual` uses the proxy from
71             {option}`services.aesmd.settings.proxy`.
72           '';
73         };
74         options.defaultQuotingType = mkOption {
75           type = with types; nullOr (enum [ "ecdsa_256" "epid_linkable" "epid_unlinkable" ]);
76           default = null;
77           example = "ecdsa_256";
78           description = "Attestation quote type.";
79         };
80       };
81     };
82   };
84   config = mkIf cfg.enable {
85     assertions = [{
86       assertion = !(config.boot.specialFileSystems."/dev".options ? "noexec");
87       message = "SGX requires exec permission for /dev";
88     }];
90     hardware.cpu.intel.sgx.provision.enable = true;
92     # Make sure the AESM service can find the SGX devices until
93     # https://github.com/intel/linux-sgx/issues/772 is resolved
94     # and updated in nixpkgs.
95     hardware.cpu.intel.sgx.enableDcapCompat = mkForce true;
97     systemd.services.aesmd =
98       let
99         storeAesmFolder = "${sgx-psw}/aesm";
100         # Hardcoded path AESM_DATA_FOLDER in psw/ae/aesm_service/source/oal/linux/aesm_util.cpp
101         aesmDataFolder = "/var/opt/aesmd/data";
102       in
103       {
104         description = "Intel Architectural Enclave Service Manager";
105         wantedBy = [ "multi-user.target" ];
107         after = [
108           "auditd.service"
109           "network.target"
110           "syslog.target"
111         ];
113         environment = {
114           NAME = "aesm_service";
115           AESM_PATH = storeAesmFolder;
116           LD_LIBRARY_PATH = makeLibraryPath [ cfg.quoteProviderLibrary ];
117         } // cfg.environment;
119         # Make sure any of the SGX application enclave devices is available
120         unitConfig.AssertPathExists = [
121           # legacy out-of-tree driver
122           "|/dev/isgx"
123           # DCAP driver
124           "|/dev/sgx/enclave"
125           # in-tree driver
126           "|/dev/sgx_enclave"
127         ];
129         serviceConfig = rec {
130           ExecStartPre = pkgs.writeShellScript "copy-aesmd-data-files.sh" ''
131             set -euo pipefail
132             whiteListFile="${aesmDataFolder}/white_list_cert_to_be_verify.bin"
133             if [[ ! -f "$whiteListFile" ]]; then
134               ${pkgs.coreutils}/bin/install -m 644 -D \
135                 "${storeAesmFolder}/data/white_list_cert_to_be_verify.bin" \
136                 "$whiteListFile"
137             fi
138           '';
139           ExecStart = "${sgx-psw}/bin/aesm_service --no-daemon";
140           ExecReload = ''${pkgs.coreutils}/bin/kill -SIGHUP "$MAINPID"'';
142           Restart = "on-failure";
143           RestartSec = "15s";
145           DynamicUser = true;
146           Group = "sgx";
147           SupplementaryGroups = [
148             config.hardware.cpu.intel.sgx.provision.group
149           ];
151           Type = "simple";
153           WorkingDirectory = storeAesmFolder;
154           StateDirectory = "aesmd";
155           StateDirectoryMode = "0700";
156           RuntimeDirectory = "aesmd";
157           RuntimeDirectoryMode = "0750";
159           # Hardening
161           # chroot into the runtime directory
162           RootDirectory = "%t/aesmd";
163           BindReadOnlyPaths = [
164             builtins.storeDir
165             # Hardcoded path AESM_CONFIG_FILE in psw/ae/aesm_service/source/utils/aesm_config.cpp
166             "${configFile}:/etc/aesmd.conf"
167           ];
168           BindPaths = [
169             # Hardcoded path CONFIG_SOCKET_PATH in psw/ae/aesm_service/source/core/ipc/SocketConfig.h
170             "%t/aesmd:/var/run/aesmd"
171             "%S/aesmd:/var/opt/aesmd"
172           ];
174           # PrivateDevices=true will mount /dev noexec which breaks AESM
175           PrivateDevices = false;
176           DevicePolicy = "closed";
177           DeviceAllow = [
178             # legacy out-of-tree driver
179             "/dev/isgx rw"
180             # DCAP driver
181             "/dev/sgx rw"
182             # in-tree driver
183             "/dev/sgx_enclave rw"
184             "/dev/sgx_provision rw"
185           ];
187           # Requires Internet access for attestation
188           PrivateNetwork = false;
190           RestrictAddressFamilies = [
191             # Allocates the socket /var/run/aesmd/aesm.socket
192             "AF_UNIX"
193             # Uses the HTTP protocol to initialize some services
194             "AF_INET"
195             "AF_INET6"
196           ];
198           # True breaks stuff
199           MemoryDenyWriteExecute = false;
201           # needs the ipc syscall in order to run
202           SystemCallFilter = [
203             "@system-service"
204             "~@aio"
205             "~@chown"
206             "~@clock"
207             "~@cpu-emulation"
208             "~@debug"
209             "~@keyring"
210             "~@memlock"
211             "~@module"
212             "~@mount"
213             "~@privileged"
214             "~@raw-io"
215             "~@reboot"
216             "~@resources"
217             "~@setuid"
218             "~@swap"
219             "~@sync"
220             "~@timer"
221           ];
222           SystemCallArchitectures = "native";
223           SystemCallErrorNumber = "EPERM";
225           CapabilityBoundingSet = "";
226           KeyringMode = "private";
227           LockPersonality = true;
228           NoNewPrivileges = true;
229           NotifyAccess = "none";
230           PrivateMounts = true;
231           PrivateTmp = true;
232           PrivateUsers = true;
233           ProcSubset = "pid";
234           ProtectClock = true;
235           ProtectControlGroups = true;
236           ProtectHome = true;
237           ProtectHostname = true;
238           ProtectKernelLogs = true;
239           ProtectKernelModules = true;
240           ProtectKernelTunables = true;
241           ProtectProc = "invisible";
242           ProtectSystem = "strict";
243           RemoveIPC = true;
244           RestrictNamespaces = true;
245           RestrictRealtime = true;
246           RestrictSUIDSGID = true;
247           UMask = "0066";
248         };
249       };
250   };