Skip to content

Commit

Permalink
Refactor guivm
Browse files Browse the repository at this point in the history
Changes:
- remove guivmExtraModules
- separate functionality, mostly to desktop and openpdf services
- add kernel config, allows now to centrally handle kernel configs
As kernel modules and parameters will have different sources such as hardware, security, etc. this allows
to join configurations and pass them to VMs
- add qemu config, for required extra configurations (here gui-vm)
- add namespace bridge, here to share a list of configured VMs
- continue work on reference programs, re-work windows-launcher
- fix to guard x86-generic

Signed-off-by: Manuel Bluhm <[email protected]>
  • Loading branch information
mbssrc authored and brianmcgillion committed Jun 24, 2024
1 parent 70e53b1 commit ae48500
Show file tree
Hide file tree
Showing 24 changed files with 602 additions and 404 deletions.
3 changes: 3 additions & 0 deletions modules/common/services/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@
./audio.nix
./wifi.nix
./firmware.nix
./desktop.nix
./pdfopen.nix
./namespaces.nix
];
}
128 changes: 128 additions & 0 deletions modules/common/services/desktop.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
{
config,
lib,
pkgs,
...
}: let
inherit (builtins) filter map hasAttr;
inherit (lib) mkIf mkEnableOption head any optionals optionalAttrs;
cfg = config.ghaf.services.desktop;

winConfig =
if (hasAttr "reference" config.ghaf)
then
if (hasAttr "programs" config.ghaf.reference)
then config.ghaf.reference.programs.windows-launcher
else {}
else {};
isIdsvmEnabled = any (vm: vm == "ids-vm") config.ghaf.namespaces.vms;
# TODO: The desktop configuration needs to be re-worked.
in {
options.ghaf.services.desktop = {
enable = mkEnableOption "Enable the desktop configuration";
};

config = mkIf cfg.enable {
ghaf = optionalAttrs (hasAttr "graphics" config.ghaf) {
profiles.graphics.compositor = "labwc";
graphics = {
launchers = let
hostEntry = filter (x: x.name == "ghaf-host-debug") config.ghaf.networking.hosts.entries;
hostAddress = head (map (x: x.ip) hostEntry);
powerControl = pkgs.callPackage ../../../packages/powercontrol {};
privateSshKeyPath = config.ghaf.security.sshKeys.sshKeyPath;
in
[
{
# The SPKI fingerprint is calculated like this:
# $ openssl x509 -noout -in mitmproxy-ca-cert.pem -pubkey | openssl asn1parse -noout -inform pem -out public.key
# $ openssl dgst -sha256 -binary public.key | openssl enc -base64
name = "Chromium";
path =
if isIdsvmEnabled
then "${pkgs.openssh}/bin/ssh -i ${privateSshKeyPath} -o StrictHostKeyChecking=no chromium-vm run-waypipe chromium --enable-features=UseOzonePlatform --ozone-platform=wayland --user-data-dir=/home/${config.ghaf.users.accounts.user}/.config/chromium/Default --ignore-certificate-errors-spki-list=Bq49YmAq1CG6FuBzp8nsyRXumW7Dmkp7QQ/F82azxGU="
else "${pkgs.openssh}/bin/ssh -i ${privateSshKeyPath} -o StrictHostKeyChecking=no chromium-vm run-waypipe chromium --enable-features=UseOzonePlatform --ozone-platform=wayland";
icon = "${pkgs.icon-pack}/chromium.svg";
}

{
name = "GALA";
path = "${pkgs.openssh}/bin/ssh -i ${privateSshKeyPath} -o StrictHostKeyChecking=no gala-vm run-waypipe gala --enable-features=UseOzonePlatform --ozone-platform=wayland";
icon = "${pkgs.icon-pack}/distributor-logo-android.svg";
}

{
name = "PDF Viewer";
path = "${pkgs.openssh}/bin/ssh -i ${privateSshKeyPath} -o StrictHostKeyChecking=no zathura-vm run-waypipe zathura";
icon = "${pkgs.icon-pack}/document-viewer.svg";
}

{
name = "Element";
path = "${pkgs.openssh}/bin/ssh -i ${privateSshKeyPath} -o StrictHostKeyChecking=no element-vm run-waypipe element-desktop --enable-features=UseOzonePlatform --ozone-platform=wayland";
icon = "${pkgs.icon-pack}/element-desktop.svg";
}

{
name = "AppFlowy";
path = "${pkgs.openssh}/bin/ssh -i ${privateSshKeyPath} -o StrictHostKeyChecking=no appflowy-vm run-waypipe appflowy";
icon = "${pkgs.appflowy}/opt/data/flutter_assets/assets/images/flowy_logo.svg";
}

{
name = "Network Settings";
path = "${pkgs.nm-launcher}/bin/nm-launcher";
icon = "${pkgs.icon-pack}/preferences-system-network.svg";
}

{
name = "Shutdown";
path = "${powerControl.makePowerOffCommand {
inherit hostAddress;
inherit privateSshKeyPath;
}}";
icon = "${pkgs.icon-pack}/system-shutdown.svg";
}

{
name = "Reboot";
path = "${powerControl.makeRebootCommand {
inherit hostAddress;
inherit privateSshKeyPath;
}}";
icon = "${pkgs.icon-pack}/system-reboot.svg";
}

# Temporarly disabled as it fails to turn off display when suspended
# {
# name = "Suspend";
# path = "${powerControl.makeSuspendCommand {
# inherit hostAddress;
# inherit privateSshKeyPath;
# }}";
# icon = "${pkgs.icon-pack}/system-suspend.svg";
# }

# Temporarly disabled as it doesn't work at all
# {
# name = "Hibernate";
# path = "${powerControl.makeHibernateCommand {
# inherit hostAddress;
# inherit privateSshKeyPath;
# }}";
# icon = "${pkgs.icon-pack}/system-suspend-hibernate.svg";
# }
]
++ optionals (hasAttr "spice-host" winConfig) [
{
name = "Windows";
path = "${pkgs.virt-viewer}/bin/remote-viewer -f spice://${winConfig.spice-host}:${toString winConfig.spice-port}";
icon = "${pkgs.icon-pack}/distributor-logo-windows.svg";
}
];
};
};
};
}
107 changes: 43 additions & 64 deletions modules/common/services/fprint.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,81 +6,60 @@
pkgs,
...
}: let
inherit (lib) mkEnableOption mkIf;
cfg = config.ghaf.services.fprint;
inherit (lib) mkEnableOption mkOption types mkIf;
in {
options.ghaf.services.fprint = {
enable = mkEnableOption "Enable fingerprint reader support";
qemuExtraArgs = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra arguments to pass to qemu when enabling the fingerprint reader.
'';
};
extraConfigurations = mkOption {
type = types.attrsOf types.anything;
default = {};
description = ''
Extra configurations when enabling the fingerprint reader in a guest.
'';
};
};

config = mkIf cfg.enable {
ghaf.services.fprint = {
# Use qemu arguments generated for the device
qemuExtraArgs = config.ghaf.hardware.usb.internal.qemuExtraArgs.fprint-reader;
# Enable service and package for fingerprint reader
services.fprintd.enable = true;
environment.systemPackages = [pkgs.fprintd];

extraConfigurations = {
# Enable service and package for fingerprint reader
services.fprintd.enable = true;
environment.systemPackages = [pkgs.fprintd];

# Enable polkit and add rules
ghaf.systemd.withPolkit = true;
security = {
polkit = {
enable = true;
debug = true;
# Polkit rules for fingerprint reader
extraConfig = ''
// Allow user to verify fingerprints
polkit.addRule(function(action, subject) {
if (action.id == "net.reactivated.fprint.device.verify" &&
subject.user == "ghaf") {
return polkit.Result.YES;
}
});
// Allow user to enroll fingerprints
polkit.addRule(function(action, subject) {
if (action.id == "net.reactivated.fprint.device.enroll" &&
subject.user == "ghaf") {
return polkit.Result.YES;
}
});
'';
};
# PAM rules for swaylock fingerprint reader
pam.services = {
swaylock.text = ''
# Account management.
account required pam_unix.so
# Enable polkit and add rules
ghaf.systemd.withPolkit = true;
security = {
polkit = {
enable = true;
debug = true;
# Polkit rules for fingerprint reader
extraConfig = ''
// Allow user to verify fingerprints
polkit.addRule(function(action, subject) {
if (action.id == "net.reactivated.fprint.device.verify" &&
subject.user == "ghaf") {
return polkit.Result.YES;
}
});
// Allow user to enroll fingerprints
polkit.addRule(function(action, subject) {
if (action.id == "net.reactivated.fprint.device.enroll" &&
subject.user == "ghaf") {
return polkit.Result.YES;
}
});
'';
};
# PAM rules for swaylock fingerprint reader
pam.services = {
swaylock.text = ''
# Account management.
account required pam_unix.so
# Authentication management.
auth sufficient pam_unix.so likeauth try_first_pass
auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so
auth required pam_deny.so
# Authentication management.
auth sufficient pam_unix.so likeauth try_first_pass
auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so
auth required pam_deny.so
# Password management.
password sufficient pam_unix.so nullok sha512
# Password management.
password sufficient pam_unix.so nullok sha512
# Session management.
session required pam_env.so conffile=/etc/pam/environment readenv=0
session required pam_unix.so
'';
};
};
# Session management.
session required pam_env.so conffile=/etc/pam/environment readenv=0
session required pam_unix.so
'';
};
};
};
Expand Down
25 changes: 25 additions & 0 deletions modules/common/services/namespaces.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
{
config,
lib,
...
}: let
inherit (builtins) attrNames hasAttr;
inherit (lib) mkOption types optionalAttrs;
in {
options.ghaf.namespaces = {
vms = mkOption {
type = types.listOf types.str;
default = [];
description = "List of VMs currently enabled.";
};
};
config = {
ghaf = optionalAttrs (hasAttr "microvm" config) {
namespaces = optionalAttrs (hasAttr "vms" config.microvm) {
vms = attrNames config.microvm.vms;
};
};
};
}
58 changes: 58 additions & 0 deletions modules/common/services/pdfopen.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
{
config,
lib,
pkgs,
...
}: let
inherit (builtins) toString;
inherit (lib) mkEnableOption mkOption mkIf types;
cfg = config.ghaf.services.pdfopener;

# TODO: Fix the path to get the sshKeyPath so that
# openPdf can be exported as a normal package from
# packaged/flake-module.nix and hence easily imported
# into all targets
openPdf = pkgs.callPackage ../../../packages/openPdf {
inherit (config.ghaf.security.sshKeys) sshKeyPath;
};
in {
options.ghaf.services.pdfopener = {
enable = mkEnableOption "Enable the pdf opening service";
xdgPdfPort = mkOption {
type = types.int;
default = 1200;
description = "TCP port for the PDF XDG socket";
};
};

config = mkIf cfg.enable {
# PDF XDG handler service receives a PDF file path from the chromium-vm and executes the openpdf script
systemd.user = {
sockets."pdf" = {
unitConfig = {
Description = "PDF socket";
};
socketConfig = {
ListenStream = "${toString cfg.xdgPdfPort}";
Accept = "yes";
};
wantedBy = ["sockets.target"];
};

services."pdf@" = {
description = "PDF opener";
serviceConfig = {
ExecStart = "${openPdf}/bin/openPdf";
StandardInput = "socket";
StandardOutput = "journal";
StandardError = "journal";
};
};
};

# Open TCP port for the PDF XDG socket.
networking.firewall.allowedTCPPorts = [cfg.xdgPdfPort];
};
}
4 changes: 3 additions & 1 deletion modules/hardware/common/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
imports = [
./usb/internal.nix
./usb/external.nix
./passthru.nix
./devices.nix
./kernel.nix
./qemu.nix
];
}
Loading

0 comments on commit ae48500

Please sign in to comment.