Skip to content

Commit

Permalink
feat(user accounts): new ghaf user account setup
Browse files Browse the repository at this point in the history
  - introducing userborn
  - disabling mutable users
  - re-factoring ghaf account to admin account
  - introducing login user account with homed + auxiliary accounts

  - impermanence flake input pinned to userborn patch
  - /etc/machine-id (gui-vm) is currently hardcoded as login user identity file depends on it.
    It should be generated on first boot and persistet. Workaround is available upstream (after
    userborn patch) in impermanence but does not seem to work with our setup, investigation required
  - reverts .face patch, works by copying .face to user home
  - known login incoveniences: wrong password entry on lock results in multiple errors, user needs to click
    login if fprint is enabled (only for login not lock)

Signed-off-by: Manuel Bluhm <[email protected]>
  • Loading branch information
mbssrc committed Dec 15, 2024
1 parent 7c10e3a commit b8a9aef
Show file tree
Hide file tree
Showing 41 changed files with 946 additions and 390 deletions.
7 changes: 4 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@
};

impermanence = {
url = "github:nix-community/impermanence";
url = "github:nix-community/impermanence/32b1094d28d5fbedcc85a403bc08c8877b396255";
};

givc = {
Expand Down
2 changes: 1 addition & 1 deletion modules/common/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
./firewall
./profiles
./security
./users/accounts.nix
./users
./version
./virtualization/docker.nix
./systemd
Expand Down
1 change: 0 additions & 1 deletion modules/common/profiles/debug.nix
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ in
config = lib.mkIf cfg.enable {
# Enable default accounts and passwords
ghaf = {
users.accounts.enable = true;
# Enable development on target
development = {
nix-setup.enable = true;
Expand Down
2 changes: 1 addition & 1 deletion modules/common/profiles/release.nix
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ in
# TODO this needs to be refined when we define a policy for the
# processes and the UID/groups that should be enabled by default
# if not already covered by systemd
ghaf.users.accounts.enable = true;
# ghaf.users.admin.enable = true;
};
}
7 changes: 0 additions & 7 deletions modules/common/services/audio.nix
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,6 @@ in
};
};

# Allow ghaf user to access pulseaudio and pipewire
users.extraUsers.ghaf.extraGroups = [
"audio"
"video"
"pipewire"
];

# Start pipewire on system boot
systemd.services.pipewire.wantedBy = [ "multi-user.target" ];

Expand Down
23 changes: 2 additions & 21 deletions modules/common/services/fprint.nix
Original file line number Diff line number Diff line change
Expand Up @@ -46,38 +46,19 @@ in
// Allow user to verify fingerprints
polkit.addRule(function(action, subject) {
if (action.id == "net.reactivated.fprint.device.verify" &&
subject.user == "ghaf") {
subject.isInGroup ("users")) {
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") {
subject.isInGroup ("users")) {
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
# 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
'';
};
};
};
}
4 changes: 1 addition & 3 deletions modules/common/services/xdgopener.nix
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ let
# into all targets
ghaf-xdg-open = pkgs.callPackage ../../../packages/ghaf-xdg-open {
inherit (config.ghaf.security.sshKeys) sshKeyPath;
user = config.ghaf.users.appUser.name;
};
in
{
Expand Down Expand Up @@ -51,9 +52,6 @@ in
services."xdg@" = {
description = "XDG opener";
serviceConfig = {
# The user 'ghaf' is used here to access SSH keys for the scp command
# This is required to copy files to the zathuravm
User = "ghaf";
ExecStart = "${ghaf-xdg-open}/bin/ghaf-xdg-open";
StandardInput = "socket";
StandardOutput = "journal";
Expand Down
10 changes: 9 additions & 1 deletion modules/common/systemd/base.nix
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ let
inherit (cfg) withAudit;
withCompression = true;
withCoredump = cfg.withDebug || cfg.withMachines;
inherit (cfg) withCryptsetup;
withCryptsetup = cfg.withCryptsetup || cfg.withHomed;
inherit (cfg) withEfi;
inherit (cfg) withBootloader;
inherit (cfg) withFido2;
inherit (cfg) withHomed;
inherit (cfg) withHostnamed;
withImportd = cfg.withMachines;
withKexectools = cfg.withDebug;
Expand All @@ -55,6 +56,7 @@ let
inherit (cfg) withTimesyncd;
inherit (cfg) withTpm2Tss;
inherit (cfg) withUkify;
withUserDb = cfg.withHomed;
withUtmp = cfg.withJournal || cfg.withAudit;
}
// lib.optionalAttrs (lib.strings.versionAtLeast pkgs.systemdMinimal.version "255.0") {
Expand Down Expand Up @@ -230,6 +232,12 @@ in
default = false;
};

withHomed = mkOption {
description = "Enable systemd homed for users home functionality.";
type = types.bool;
default = false;
};

withHostnamed = mkOption {
description = "Enable systemd hostname daemon.";
type = types.bool;
Expand Down
66 changes: 0 additions & 66 deletions modules/common/users/accounts.nix

This file was deleted.

106 changes: 106 additions & 0 deletions modules/common/users/admin.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
{
config,
lib,
...
}:
let
cfg = config.ghaf.users.admin;
inherit (lib)
mkIf
types
mkOption
optionals
;
in
{
options.ghaf.users.admin = {
enable = mkOption {
description = "Enable the admin user account. Enabled by default.";
type = types.bool;
default = true;
};
name = mkOption {
description = "Admin account name. Defaults to 'ghaf'.";
type = types.str;
default = "ghaf";
};
uid = mkOption {
description = "User identifier (uid) for the admin account.";
type = types.int;
default = 1001;
};
initialPassword = mkOption {
description = "Default password for the admin user account.";
type = types.nullOr types.str;
default = "ghaf";
};
initialHashedPassword = mkOption {
description = "Initial hashed password for the admin user account.";
type = types.nullOr types.str;
default = null;
};
hashedPassword = mkOption {
description = "Hashed password for live updates.";
type = types.nullOr types.str;
default = null;
};
extraGroups = mkOption {
description = "Extra groups for the admin user.";
type = types.listOf types.str;
default = [ ];
};
};

config = mkIf cfg.enable {

# Assertions
assertions = [
{
assertion =
(cfg.initialPassword != null)
|| (cfg.initialHashedPassword != null)
|| (cfg.hashedPassword != null);
message = ''
No password set for the admin account. Please set one of the following options:
- initialPassword
- initialHashedPassword
- hashedPassword
to allow admin login.
'';
}
];

users = {
users = {
"${cfg.name}" = {
isNormalUser = true;
inherit (cfg) initialPassword;
inherit (cfg) initialHashedPassword;
inherit (cfg) hashedPassword;
inherit (cfg) uid;
createHome = false;
home = "/var/empty";
extraGroups =
[
"wheel"
"video"
]
++ cfg.extraGroups
++ optionals config.security.tpm2.enable [ "tss" ]
++ optionals config.ghaf.virtualization.docker.daemon.enable [ "docker" ];
};
};
groups = {
"${cfg.name}" = {
inherit (cfg) name;
members = [ cfg.name ];
};
};
};

# to build ghaf as admin with caches
nix.settings.trusted-users = mkIf config.ghaf.profiles.debug.enable [ cfg.name ];
};
}
25 changes: 25 additions & 0 deletions modules/common/users/common.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 (lib) mkDefault hasAttr;
hasStorageVm = (hasAttr "storagevm" config.ghaf) && config.ghaf.storagevm.enable;
in
{
# Common ghaf user settings
config = {

# Disable mutable users
users.mutableUsers = mkDefault false;

# Enable userborn
services.userborn = {
enable = mkDefault true;
passwordFilesLocation = if hasStorageVm then "/var/lib/nixos" else "/etc";
};
};
}
10 changes: 10 additions & 0 deletions modules/common/users/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copyright 2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
{
imports = [
./common.nix
./admin.nix
./desktop.nix
./managed.nix
];
}
Loading

0 comments on commit b8a9aef

Please sign in to comment.