Skip to content

Conversation

@mbssrc
Copy link
Collaborator

@mbssrc mbssrc commented Sep 16, 2025

Description of Changes

Add AD enrollment for systemd-homed, and initial support for AD users managed with SSSD.
Ghaf docs come with a separate PR.

Functionality

AD configuration

The AD domains options are defined in modules/common/users/active-directory.nix, and the test domain defined in modules/common/users/ad-users.nix. This should move to a provisioning file when available.

Aside from a shortlist of sanity checks, it configures the krb.conf (for krb tooling) and DNS for AD domains on all machines.
This should not impact any other network connectivity - in testing that worked fine. It allows configuration of machines without AD computer join and some future features, but can be removed from global config if it makes problems.

The majority of flags has been tested with single (working) domain configuration. Note that there are several important distinctions between local (sssd) and per-domain settings. Any other configuration aside from the test domain should be
evaluated (e.g. different providers and subsequent settings), as each one has their own implications.

Most notably, the limitation is the user setup script and subsequent tooling.

User provision

Ghaf now provides 3 mechanisms for user provisioning:

  1. Managed users: These are traditional NixOs users defined by configuration. For more details refer to the mutable-users enable option in modules/common/users/profiles.nix. This includes the "ghaf" admin user.
  2. Homed users: This is the default, local homed user profile as before. Can be configured locally or details fetched from AD. As of now, it doesn't do much as we enforce single users and fixed uid/gid.
  3. Active Directory users: These users are fetched from the AD domain the computer is enrolled in.

Provisioning Script:
The user provisioning script has been updated and moved to a package to accommodate all necessary functions and get rid of long scripts in .nix files, and be available as cli command.
This script is a temporary solution - this should be properly implemented (not bash). However, this can be used until the user enrollment flow is clear, e.g. admin logging into UI in which case we can make this a proper UI application.

  • It supports creation of local users (+ optional AD query), and domain joining
  • It (quite heavily) limits the choice of AD configuration (e.g. LDAP+GSSAPI). For details dm me
  • For AD related tasks, it automatically checks connectivity to the AD and allows to either use a cable of connect to WiFi

Notes for CI/CD testing:

The systemd service names for automated test setup have changed:

  • for automated user removal: systemctl start user-provision-remove.service
  • for automated user creation: systemctl start user-provision-test.service
  • user-provision can also be used as cli tool, homectl also works as before

AD User functionality (new)

Here a quick (possibly incomplete) list of features currently supported with "Active Directory users".
Note that there are a plethora of limitations by cosmic-greeter.

  • login: with compliant username (john.smith -> johnsmith, no domain name needed). For current test setup we go with RFC2307 compliance. Notably: the user has to enter the username every time in cosmic-greeter, and press enter before entering the password. Messages are confusing or missing.
  • offline login: enabled by default, user passwords are cached (defined by SSSD parameter, defaults to 7 days). Note that the first login must be done with connection to the backend, which should still be available due to previous domain join.
  • Home creation: homes are automatically created. No home encryption is enabled as of yet.
  • Login restrictions: in the test setup, all domain users are allowed to login. This can be limited via backend (e.g. policy + enforcing GPO access control).
  • Password update: works via command line 'passwd' command. cosmic-greeter does not support it, which also makes ADs 'change password on next login' option not possible via GUI
  • Desktop usability: should work the same as homed user

Shortlist of possible future improvements

  • Password change policy from AD not supported by cosmic-greeter
  • Add FIDO2 support + MFA
  • Support remote data (e.g. autofs+smb with local cache, or other)
  • Evaluate FS encryption with SSSD
  • Add sudo provider / AD sudo support
  • Support PAC service module for SSSD (upstream?)
  • Support TPM sealing
  • More AD controls and refinement

Other changes with this patch

  • remove waypipe ssh
  • persist log storage only when enabled
  • re-organize file structure
  • update mutable users logic (see option config.ghaf.users.profile.mutable-users.enable for details)

Type of Change

  • New Feature
  • Bug Fix
  • Improvement / Refactor

Related Issues / Tickets

Checklist

  • Clear summary in PR description
  • Detailed and meaningful commit message(s)
  • Commits are logically organized and squashed if appropriate
  • Contribution guidelines followed
  • Ghaf documentation updated with the commit - https://tiiuae.github.io/ghaf/
  • Author has run make-checks and it passes
  • All automatic GitHub Action checks pass - see actions
  • Author has added reviewers and removed PR draft status

Testing Instructions

Applicable Targets

  • Orin AGX aarch64
  • Orin NX aarch64
  • Lenovo X1 x86_64
  • Dell Latitude x86_64
  • System 76 x86_64

Installation Method

  • Requires full re-installation
  • Can be updated with nixos-rebuild ... switch
  • Other:

Test Steps To Verify:

  1. Regression test for simple local user creation.
  2. Get AD credentials to be able to join machines (DM me)
  3. Create local user account with AD query
  4. Rebuild and flash with homed profile disabled and ad-users enabled
  5. Test machine enrollment
  6. Test AD user functionality

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Active Directory (PoC) support to the Ghaf framework, introducing a new provisioning system for user enrollment and SSSD integration for AD users.

Key Changes

  • New provisioning script: Introduces ghaf-provision, a bash-based interactive tool for system setup and user enrollment, supporting both local systemd-homed users and Active Directory users
  • SSSD integration: Adds a comprehensive SSSD module for Active Directory authentication, including Kerberos, LDAP, and PAM integration
  • User profile reorganization: Refactors user management into separate profiles (homed users vs. AD users vs. auxiliary users) with mutual exclusivity enforcement

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 19 comments.

Show a summary per file
File Description
packages/pkgs-by-name/ghaf-provision/package.nix Package definition for the new ghaf-provision script with all required dependencies
packages/pkgs-by-name/ghaf-provision/ghaf-provision.sh 1875-line bash script implementing interactive provisioning with state machine, AD join, LDAP queries, and user creation
packages/own-pkgs-overlay.nix Adds ghaf-provision to the package overlay
modules/common/users/profiles.nix New module defining mutually exclusive user profiles (AD vs homed)
modules/common/users/homed.nix New module for systemd-homed user configuration
modules/common/users/ad-users.nix New module for Active Directory user configuration
modules/common/users/auxiliary.nix Refactored auxiliary user accounts (appUser, proxyUser)
modules/common/users/admin.nix Adds homeSize option for admin user
modules/common/users/managed.nix Updates references from loginUser to homedUser
modules/common/services/sssd.nix Comprehensive 640-line SSSD service module with AD, LDAP, Kerberos, and PAM configuration
modules/common/services/provisioning.nix Service definition for running ghaf-provision on first boot
modules/common/services/default.nix Imports new provisioning and SSSD services
modules/common/security/default.nix Removes sshkeys.nix (waypipe SSH cleanup)
modules/reference/profiles/mvp-user-trial.nix Configures homed-user profile
modules/microvm/sysvms/guivm.nix Updates to use new user profiles, removes waypipe SSH infrastructure
modules/microvm/modules.nix Passes user profile configuration to VMs
modules/microvm/host/*.nix Updates references from loginUser to homedUser, improves session detection
modules/microvm/common/storagevm.nix Adjusts home image sizing for both admin and homed users, makes log persistence conditional
modules/microvm/common/shared-directory.nix Removes conditional bookmark setup
modules/microvm/appvm.nix Removes waypipe SSH key infrastructure
modules/givc/appvm.nix Updates reference from loginUser to homedUser
modules/desktop/graphics/login-manager.nix Adds SSSD library path to greeter, adds group-based access control

else if config.ghaf.users.homedUser.enable then
config.ghaf.users.homedUser.homeSize
else
200000; # Default to 200 GB
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Incomplete documentation string. The description ends with "Defaults to 200 GB" but doesn't specify when this default applies. Consider clarifying: "Defaults to 200 GB if neither admin nor homed user is enabled."

Suggested change
200000; # Default to 200 GB
200000; # Defaults to 200 GB if neither admin nor homed user is enabled.

Copilot uses AI. Check for mistakes.
];
};

# Add bookmark to skel
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The condition config.ghaf.users.loginUser.enable was removed, but this file still sets up bookmarks for all users. The change at line 48 removes the conditional check, but the comment above (line 47) still refers to it. Consider updating or removing the outdated comment.

Suggested change
# Add bookmark to skel
# Add bookmark to skel for all users

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,64 @@
# SPDX-FileCopyrightText: 2025-2026 TII (SSRC) and the Ghaf contributors
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Inconsistent copyright year format. The header uses "2025-2026" but most other files in the Ghaf project use "2022-2025" or "2022-2026". Since this is being added in 2025, consider using "2022-2025" to match the project convention.

Suggested change
# SPDX-FileCopyrightText: 2025-2026 TII (SSRC) and the Ghaf contributors
# SPDX-FileCopyrightText: 2022-2026 TII (SSRC) and the Ghaf contributors

Copilot uses AI. Check for mistakes.
until [ "$state" == "active" ]; do
state=$(systemctl --user is-active xdg-desktop-portal.service --machine=${toString config.ghaf.users.loginUser.uid}@.host)
while [[ "$state" != "active" ]]; do
state=$(systemctl --user is-active session.slice --machine="$USER_ID"@.host) || true
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing validation for $USER_ID before using it in systemctl command. On line 122, $USER_ID is used to query systemctl but there's no validation that it's a valid UID. If the jq extraction fails and returns non-numeric data, this could cause systemctl to fail unexpectedly.

Copilot uses AI. Check for mistakes.
@mbssrc mbssrc marked this pull request as draft December 5, 2025 13:07
@mbssrc
Copy link
Collaborator Author

mbssrc commented Dec 5, 2025

converted to draft until the new AD test setup is ready

@milva-unikie
Copy link

Tested on Darter Pro (new images)

With homed user enabled (this PR as-is)

With AD user enabled

In modules/reference/profiles/mvp-user-trial.nix

      # Setup user profiles
      users.profile = {
        homed-user.enable = false;
        ad-users.enable = true;
        mutable-users.enable = false;
      };
  • Login to AD user works

Issues
(I tried to check that none of these were not addressed in the description)

  • Login on the second boot does not work without internet connection.
  • The first login attempt seems to always fail. I can see that the password I am typing is correct, but it always fails on first try.
  • Gui-vm name is ghaf@ghaf-4257395465 and janedoe@ghaf-4257395465 instead of ghaf@gui-vm and janedoe@gui-vm. It is now the same as net-vm.

@mbssrc
Copy link
Collaborator Author

mbssrc commented Dec 18, 2025

Tested on Darter Pro (new images)

With homed user enabled (this PR as-is)

* Enrolling a local user works

* Enrolling an AD user to homed works (required changing the DNS provider IP address)

* Automated tests pass with [Active Directory support ci-test-automation#584](https://github.com/tiiuae/ci-test-automation/pull/584)

With AD user enabled

In modules/reference/profiles/mvp-user-trial.nix

      # Setup user profiles
      users.profile = {
        homed-user.enable = false;
        ad-users.enable = true;
        mutable-users.enable = false;
      };
* Login to AD user works

Issues (I tried to check that none of these were not addressed in the description)

* Login on the second boot does not work without internet connection.

* The first login attempt seems to always fail. I can see that the password I am typing is correct, but it always fails on first try.

* Gui-vm name is `ghaf@ghaf-4257395465` and `janedoe@ghaf-4257395465` instead of `ghaf@gui-vm` and `janedoe@gui-vm`. It is now the same as net-vm.
  1. Is that after logging in successfully on first boot? After first login, credentials should be cached offline for the defined period (7 days by default)
  2. Will see if it can be solved neatly
  3. On purpose - each machine is registered with its hostname in AD - so cannot be gui-vm but has to be the unique machine name

@milva-unikie
Copy link

1. Is that after logging in successfully on first boot? After first login, credentials should be cached offline for the defined period (7 days by default)

Yes. I logged in the first time with an Ethernet connection. Then disconnected the Ethernet cable, rebooted and tried to login again. It did not work, I tried entering the username and password multiple times.

Remove unused waypipe ssh setup.

Signed-off-by: Manuel Bluhm <[email protected]>
Enable log storage only if logging is enabled. This prevents leaking
data from previous debug sessions where logging was disabled for privacy.

Signed-off-by: Manuel Bluhm <[email protected]>
Create user profiles:
- create homed and ad profiles
- re-organize file structure

Add ghaf-provision script for user enrollment:
- preserves local homed user creation
- add local user enrollment from AD
- add machine AD enrollment

Add AD and SSSD integration:
- AD domain configuration
- initial SSSD configuration

Signed-off-by: Manuel Bluhm <[email protected]>
Patch for cosmic-greeter to prompt for username if empty (e.g. no user
found), and only open a session if username is available.

Signed-off-by: Manuel Bluhm <[email protected]>
@mbssrc
Copy link
Collaborator Author

mbssrc commented Dec 25, 2025

Changes (+rebased):

  • admin user (ghaf): by default, the admin user is now a system user with UID 901. A new flag enables UI login and changes the UID to 1001 (as before), and allows login. This effectively removes the ghaf user from the greeter if the respective flag is not enabled, and removes the admin user enumeration and subsequent session start by the greeter (which then requires their password, and will throw an error even if username is changed as the session is already initiated)

  • Fix offline login: setting SSSD's pam verbosity to 0 as the subsequent offline cache message is not well received by the greeter and causes it to hang. Note: please use only a single user for UI login, do not login with both (online will work, offline will fail). This will later be enforced via backend, but is still possible in this test configuration as it requires an extra step

  • Fix cosmic-greeter: By default, a session is opened even when no username is available, which causes various errors. The patch enforces that (1) session establishment requires a username (2) username cannot be empty (hangs indefinitely), and (3) username is prompted if none is found

  • Execution condition of user provisioning is now again dependent on whether a homed user is available (homed-user) or machine is enrolled (ad-users)

@juliuskoskela
Copy link
Contributor

I've tested on X1 and provisioning via AD works as intended including offline login.

@juliuskoskela juliuskoskela self-requested a review December 29, 2025 14:05
@brianmcgillion brianmcgillion added the Needs Testing CI Team to pre-verify label Dec 29, 2025
@leivos-unikie
Copy link
Contributor

leivos-unikie commented Dec 31, 2025

Tested the homed user case on Lenovo-X1
homed-user.enable = true;

I was not able to get AD server connection working. Could not test AD user enabled case properly.

Noticed that when
ad-users.enable = true;
ssh ghaf@gui-vm does not work (with password login)
Is this expected?

@leivos-unikie
Copy link
Contributor

leivos-unikie commented Jan 2, 2026

Now inside Tampere office got connection to AD server working and AD users enrolled in ad-users.enable = true; mode. Both users, johnsmith and janedoe get enrolled automatically after typing the admin credentials.

  • First GUI login (as johnsmith) worked
  • Can ssh to gui-vm as ghaf (obviously ghaf user gets enrolled to gui-vm only with AD server)
  • Gui vm hostname has now the id form: ghaf-0213378729

Some users related problems found:

  • After GUI login as johnsmith can ssh gui-vm as johnsmith BUT not as janedoe
  • GUI login as janedoe works. Still cannot ssh to gui-vm as janedoe and terminal is opened as johnsmith@ghaf-0213378729.
  • After disconnecting and forgetting WiFi connection and rebooting GUI login as janedoe works. Then terminal is opened as janedoe@ghaf-0213378729. ssh johnsmith@gui-vm fails with "Failed to add the host to the list of known hosts (/var/empty/.ssh/known/hosts).
  • After logout GUI login as johnsmith does not work (still disconnected from internet)
  • After connecting WiFi and reboot GUI login as johnsmith/joanedoe succeeded
  • Opened terminal as johnsmith. ssh janedoe@gui-vm opens successfully a new ssh connection but prompt shows still johnsmith as username.
  • Again removed WiFi connection and rebooted. GUI login succeeded as janedoe. Logged out. GUI login as johnsmith keeps failing. After connected to internet via Ethernet GUI login as johnsmith succeeded.

@leivos-unikie leivos-unikie added bug on Lenovo X1 Carbon Issues found on Lenovo X1 Carbon while checking this PR and removed Needs Testing CI Team to pre-verify labels Jan 2, 2026
@leivos-unikie
Copy link
Contributor

Talked with Milla about the confusion between users. Probably for this PR it is enough that the AD user mode works only with single user because ghaf is supposed to support only single user at a time.

So if I consistently use only single user (johnsmith) login and terminal username are working fine both online and offline (after first login).

Removing the bug label.

@leivos-unikie leivos-unikie removed the bug on Lenovo X1 Carbon Issues found on Lenovo X1 Carbon while checking this PR label Jan 2, 2026
@leivos-unikie
Copy link
Contributor

And in homed-user.enable = true; mode enrolling an AD user to homed still works.

@leivos-unikie leivos-unikie added the Tested on Lenovo X1 Carbon This PR has been tested on Lenovo X1 Carbon label Jan 2, 2026
@brianmcgillion brianmcgillion merged commit 3fdd61f into tiiuae:main Jan 5, 2026
31 of 32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Tested on Lenovo X1 Carbon This PR has been tested on Lenovo X1 Carbon

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants