0
0
Fork 0
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-07-13 13:40:28 +03:00

Merge pull request #148593 from veehaitch/sgx-psw

sgx-psw: init package and module
This commit is contained in:
Jörg Thalheim 2021-12-13 14:16:26 +00:00 committed by GitHub
commit afa3c99cd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 549 additions and 6 deletions

View file

@ -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>

View file

@ -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`.

View file

@ -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}"
'';
};
}

View file

@ -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

View file

@ -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";
};
};
};
}

62
nixos/tests/aesmd.nix Normal file
View file

@ -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"
'';
})

View file

@ -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 {};