diff options
author | Jörg Thalheim <Mic92@users.noreply.github.com> | 2021-12-13 14:16:26 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-13 14:16:26 +0000 |
commit | afa3c99cd5ea99dbf3f599506570be5d69b2aba1 (patch) | |
tree | dd566bcf19d25241274a313d1b4d0bbffdf1702c /nixos | |
parent | 0dadd5fabb2a10d39e2641b5b7857ea1131517a6 (diff) | |
parent | d6cc0ad96e0a8723d457d0a8c6c6bfc54df2920b (diff) | |
download | nixpkgs-afa3c99cd5ea99dbf3f599506570be5d69b2aba1.tar nixpkgs-afa3c99cd5ea99dbf3f599506570be5d69b2aba1.tar.gz nixpkgs-afa3c99cd5ea99dbf3f599506570be5d69b2aba1.tar.bz2 nixpkgs-afa3c99cd5ea99dbf3f599506570be5d69b2aba1.tar.lz nixpkgs-afa3c99cd5ea99dbf3f599506570be5d69b2aba1.tar.xz nixpkgs-afa3c99cd5ea99dbf3f599506570be5d69b2aba1.tar.zst nixpkgs-afa3c99cd5ea99dbf3f599506570be5d69b2aba1.zip |
Merge pull request #148593 from veehaitch/sgx-psw
sgx-psw: init package and module
Diffstat (limited to 'nixos')
-rw-r--r-- | nixos/doc/manual/from_md/release-notes/rl-2205.section.xml | 12 | ||||
-rw-r--r-- | nixos/doc/manual/release-notes/rl-2205.section.md | 2 | ||||
-rw-r--r-- | nixos/modules/hardware/cpu/intel-sgx.nix | 47 | ||||
-rw-r--r-- | nixos/modules/module-list.nix | 2 | ||||
-rw-r--r-- | nixos/modules/services/security/aesmd.nix | 227 | ||||
-rw-r--r-- | nixos/tests/aesmd.nix | 62 | ||||
-rw-r--r-- | nixos/tests/all-tests.nix | 1 |
7 files changed, 351 insertions, 2 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml index c84a3e3b019..144b277438a 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml @@ -19,8 +19,16 @@ </section> <section xml:id="sec-release-22.05-new-services"> <title>New Services</title> - <para> - </para> + <itemizedlist spacing="compact"> + <listitem> + <para> + <link xlink:href="https://github.com/intel/linux-sgx#install-the-intelr-sgx-psw">aesmd</link>, + the Intel SGX Architectural Enclave Service Manager. Available + as + <link linkend="opt-services.aesmd.enable">services.aesmd</link>. + </para> + </listitem> + </itemizedlist> </section> <section xml:id="sec-release-22.05-incompatibilities"> <title>Backward Incompatibilities</title> diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md index 45ed69cf1b0..4418c8142a1 100644 --- a/nixos/doc/manual/release-notes/rl-2205.section.md +++ b/nixos/doc/manual/release-notes/rl-2205.section.md @@ -8,6 +8,8 @@ In addition to numerous new and upgraded packages, this release has the followin ## New Services {#sec-release-22.05-new-services} +- [aesmd](https://github.com/intel/linux-sgx#install-the-intelr-sgx-psw), the Intel SGX Architectural Enclave Service Manager. Available as [services.aesmd](#opt-services.aesmd.enable). + ## Backward Incompatibilities {#sec-release-22.05-incompatibilities} - `pkgs.ghc` now refers to `pkgs.targetPackages.haskellPackages.ghc`. diff --git a/nixos/modules/hardware/cpu/intel-sgx.nix b/nixos/modules/hardware/cpu/intel-sgx.nix new file mode 100644 index 00000000000..04647940058 --- /dev/null +++ b/nixos/modules/hardware/cpu/intel-sgx.nix @@ -0,0 +1,47 @@ +{ config, lib, ... }: +with lib; +let + cfg = config.hardware.cpu.intel.sgx.provision; + defaultGroup = "sgx_prv"; +in +{ + options.hardware.cpu.intel.sgx.provision = { + enable = mkEnableOption "access to the Intel SGX provisioning device"; + user = mkOption { + description = "Owner to assign to the SGX provisioning device."; + type = types.str; + default = "root"; + }; + group = mkOption { + description = "Group to assign to the SGX provisioning device."; + type = types.str; + default = defaultGroup; + }; + mode = mkOption { + description = "Mode to set for the SGX provisioning device."; + type = types.str; + default = "0660"; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = hasAttr cfg.user config.users.users; + message = "Given user does not exist"; + } + { + assertion = (cfg.group == defaultGroup) || (hasAttr cfg.group config.users.groups); + message = "Given group does not exist"; + } + ]; + + users.groups = optionalAttrs (cfg.group == defaultGroup) { + "${cfg.group}" = { }; + }; + + services.udev.extraRules = '' + SUBSYSTEM=="misc", KERNEL=="sgx_provision", OWNER="${cfg.user}", GROUP="${cfg.group}", MODE="${cfg.mode}" + ''; + }; +} diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 3cc9ea88e17..1f826220a0f 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -45,6 +45,7 @@ ./hardware/ckb-next.nix ./hardware/cpu/amd-microcode.nix ./hardware/cpu/intel-microcode.nix + ./hardware/cpu/intel-sgx.nix ./hardware/corectrl.nix ./hardware/digitalbitbox.nix ./hardware/device-tree.nix @@ -928,6 +929,7 @@ ./services/search/kibana.nix ./services/search/meilisearch.nix ./services/search/solr.nix + ./services/security/aesmd.nix ./services/security/certmgr.nix ./services/security/cfssl.nix ./services/security/clamav.nix diff --git a/nixos/modules/services/security/aesmd.nix b/nixos/modules/services/security/aesmd.nix new file mode 100644 index 00000000000..bb53bc49e25 --- /dev/null +++ b/nixos/modules/services/security/aesmd.nix @@ -0,0 +1,227 @@ +{ config, pkgs, lib, ... }: +with lib; +let + cfg = config.services.aesmd; + + sgx-psw = pkgs.sgx-psw.override { inherit (cfg) debug; }; + + configFile = with cfg.settings; pkgs.writeText "aesmd.conf" ( + concatStringsSep "\n" ( + optional (whitelistUrl != null) "whitelist url = ${whitelistUrl}" ++ + optional (proxy != null) "aesm proxy = ${proxy}" ++ + optional (proxyType != null) "proxy type = ${proxyType}" ++ + optional (defaultQuotingType != null) "default quoting type = ${defaultQuotingType}" ++ + # Newline at end of file + [ "" ] + ) + ); +in +{ + options.services.aesmd = { + enable = mkEnableOption "Intel's Architectural Enclave Service Manager (AESM) for Intel SGX"; + debug = mkOption { + type = types.bool; + default = false; + description = "Whether to build the PSW package in debug mode."; + }; + settings = mkOption { + description = "AESM configuration"; + default = { }; + type = types.submodule { + options.whitelistUrl = mkOption { + type = with types; nullOr str; + default = null; + example = "http://whitelist.trustedservices.intel.com/SGX/LCWL/Linux/sgx_white_list_cert.bin"; + description = "URL to retrieve authorized Intel SGX enclave signers."; + }; + options.proxy = mkOption { + type = with types; nullOr str; + default = null; + example = "http://proxy_url:1234"; + description = "HTTP network proxy."; + }; + options.proxyType = mkOption { + type = with types; nullOr (enum [ "default" "direct" "manual" ]); + default = if (cfg.settings.proxy != null) then "manual" else null; + example = "default"; + description = '' + Type of proxy to use. The <literal>default</literal> uses the system's default proxy. + If <literal>direct</literal> is given, uses no proxy. + A value of <literal>manual</literal> uses the proxy from + <option>services.aesmd.settings.proxy</option>. + ''; + }; + options.defaultQuotingType = mkOption { + type = with types; nullOr (enum [ "ecdsa_256" "epid_linkable" "epid_unlinkable" ]); + default = null; + example = "ecdsa_256"; + description = "Attestation quote type."; + }; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [{ + assertion = !(config.boot.specialFileSystems."/dev".options ? "noexec"); + message = "SGX requires exec permission for /dev"; + }]; + + hardware.cpu.intel.sgx.provision.enable = true; + + systemd.services.aesmd = + let + storeAesmFolder = "${sgx-psw}/aesm"; + # Hardcoded path AESM_DATA_FOLDER in psw/ae/aesm_service/source/oal/linux/aesm_util.cpp + aesmDataFolder = "/var/opt/aesmd/data"; + aesmStateDirSystemd = "%S/aesmd"; + in + { + description = "Intel Architectural Enclave Service Manager"; + wantedBy = [ "multi-user.target" ]; + + after = [ + "auditd.service" + "network.target" + "syslog.target" + ]; + + environment = { + NAME = "aesm_service"; + AESM_PATH = storeAesmFolder; + LD_LIBRARY_PATH = storeAesmFolder; + }; + + # Make sure any of the SGX application enclave devices is available + unitConfig.AssertPathExists = [ + # legacy out-of-tree driver + "|/dev/isgx" + # DCAP driver + "|/dev/sgx/enclave" + # in-tree driver + "|/dev/sgx_enclave" + ]; + + serviceConfig = rec { + ExecStartPre = pkgs.writeShellScript "copy-aesmd-data-files.sh" '' + set -euo pipefail + whiteListFile="${aesmDataFolder}/white_list_cert_to_be_verify.bin" + if [[ ! -f "$whiteListFile" ]]; then + ${pkgs.coreutils}/bin/install -m 644 -D \ + "${storeAesmFolder}/data/white_list_cert_to_be_verify.bin" \ + "$whiteListFile" + fi + ''; + ExecStart = "${sgx-psw}/bin/aesm_service --no-daemon"; + ExecReload = ''${pkgs.coreutils}/bin/kill -SIGHUP "$MAINPID"''; + + Restart = "on-failure"; + RestartSec = "15s"; + + DynamicUser = true; + Group = "sgx"; + SupplementaryGroups = [ + config.hardware.cpu.intel.sgx.provision.group + ]; + + Type = "simple"; + + WorkingDirectory = storeAesmFolder; + StateDirectory = "aesmd"; + StateDirectoryMode = "0700"; + RuntimeDirectory = "aesmd"; + RuntimeDirectoryMode = "0750"; + + # Hardening + + # chroot into the runtime directory + RootDirectory = "%t/aesmd"; + BindReadOnlyPaths = [ + builtins.storeDir + # Hardcoded path AESM_CONFIG_FILE in psw/ae/aesm_service/source/utils/aesm_config.cpp + "${configFile}:/etc/aesmd.conf" + ]; + BindPaths = [ + # Hardcoded path CONFIG_SOCKET_PATH in psw/ae/aesm_service/source/core/ipc/SocketConfig.h + "%t/aesmd:/var/run/aesmd" + "%S/aesmd:/var/opt/aesmd" + ]; + + # PrivateDevices=true will mount /dev noexec which breaks AESM + PrivateDevices = false; + DevicePolicy = "closed"; + DeviceAllow = [ + # legacy out-of-tree driver + "/dev/isgx rw" + # DCAP driver + "/dev/sgx rw" + # in-tree driver + "/dev/sgx_enclave rw" + "/dev/sgx_provision rw" + ]; + + # Requires Internet access for attestation + PrivateNetwork = false; + + RestrictAddressFamilies = [ + # Allocates the socket /var/run/aesmd/aesm.socket + "AF_UNIX" + # Uses the HTTP protocol to initialize some services + "AF_INET" + "AF_INET6" + ]; + + # True breaks stuff + MemoryDenyWriteExecute = false; + + # needs the ipc syscall in order to run + SystemCallFilter = [ + "@system-service" + "~@aio" + "~@chown" + "~@clock" + "~@cpu-emulation" + "~@debug" + "~@keyring" + "~@memlock" + "~@module" + "~@mount" + "~@privileged" + "~@raw-io" + "~@reboot" + "~@resources" + "~@setuid" + "~@swap" + "~@sync" + "~@timer" + ]; + SystemCallArchitectures = "native"; + SystemCallErrorNumber = "EPERM"; + + CapabilityBoundingSet = ""; + KeyringMode = "private"; + LockPersonality = true; + NoNewPrivileges = true; + NotifyAccess = "none"; + PrivateMounts = true; + PrivateTmp = true; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + RemoveIPC = true; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + UMask = "0066"; + }; + }; + }; +} diff --git a/nixos/tests/aesmd.nix b/nixos/tests/aesmd.nix new file mode 100644 index 00000000000..59c04fe7e96 --- /dev/null +++ b/nixos/tests/aesmd.nix @@ -0,0 +1,62 @@ +import ./make-test-python.nix ({ pkgs, lib, ... }: { + name = "aesmd"; + meta = { + maintainers = with lib.maintainers; [ veehaitch ]; + }; + + machine = { lib, ... }: { + services.aesmd = { + enable = true; + settings = { + defaultQuotingType = "ecdsa_256"; + proxyType = "direct"; + whitelistUrl = "http://nixos.org"; + }; + }; + + # Should have access to the AESM socket + users.users."sgxtest" = { + isNormalUser = true; + extraGroups = [ "sgx" ]; + }; + + # Should NOT have access to the AESM socket + users.users."nosgxtest".isNormalUser = true; + + # We don't have a real SGX machine in NixOS tests + systemd.services.aesmd.unitConfig.AssertPathExists = lib.mkForce [ ]; + }; + + testScript = '' + with subtest("aesmd.service starts"): + machine.wait_for_unit("aesmd.service") + status, main_pid = machine.systemctl("show --property MainPID --value aesmd.service") + assert status == 0, "Could not get MainPID of aesmd.service" + main_pid = main_pid.strip() + + with subtest("aesmd.service runtime directory permissions"): + runtime_dir = "/run/aesmd"; + res = machine.succeed(f"stat -c '%a %U %G' {runtime_dir}").strip() + assert "750 aesmd sgx" == res, f"{runtime_dir} does not have the expected permissions: {res}" + + with subtest("aesm.socket available on host"): + socket_path = "/var/run/aesmd/aesm.socket" + machine.wait_until_succeeds(f"test -S {socket_path}") + machine.succeed(f"test 777 -eq $(stat -c '%a' {socket_path})") + for op in [ "-r", "-w", "-x" ]: + machine.succeed(f"sudo -u sgxtest test {op} {socket_path}") + machine.fail(f"sudo -u nosgxtest test {op} {socket_path}") + + with subtest("Copies white_list_cert_to_be_verify.bin"): + whitelist_path = "/var/opt/aesmd/data/white_list_cert_to_be_verify.bin" + whitelist_perms = machine.succeed( + f"nsenter -m -t {main_pid} ${pkgs.coreutils}/bin/stat -c '%a' {whitelist_path}" + ).strip() + assert "644" == whitelist_perms, f"white_list_cert_to_be_verify.bin has permissions {whitelist_perms}" + + with subtest("Writes and binds aesm.conf in service namespace"): + aesmd_config = machine.succeed(f"nsenter -m -t {main_pid} ${pkgs.coreutils}/bin/cat /etc/aesmd.conf") + + assert aesmd_config == "whitelist url = http://nixos.org\nproxy type = direct\ndefault quoting type = ecdsa_256\n", "aesmd.conf differs" + ''; +}) diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 06305460c6a..f86cc2544da 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -23,6 +23,7 @@ in { _3proxy = handleTest ./3proxy.nix {}; acme = handleTest ./acme.nix {}; + aesmd = handleTest ./aesmd.nix {}; agda = handleTest ./agda.nix {}; airsonic = handleTest ./airsonic.nix {}; amazon-init-shell = handleTest ./amazon-init-shell.nix {}; |