2025-06-08 03:04:14 +02:00
|
|
|
{
|
|
|
|
inputs,
|
|
|
|
lib,
|
|
|
|
pkgs,
|
|
|
|
config,
|
|
|
|
...
|
|
|
|
}:
|
|
|
|
|
|
|
|
with lib;
|
|
|
|
let
|
|
|
|
cfg = config.modules.domain;
|
|
|
|
domain = inputs.secrets.lab.domain;
|
|
|
|
domainUpper = lib.strings.toUpper domain;
|
|
|
|
in
|
|
|
|
{
|
|
|
|
options.modules.domain = {
|
|
|
|
enable = mkEnableOption "Domain Integration";
|
|
|
|
join = {
|
|
|
|
userFile = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
description = "File containing the user used to join the computer.";
|
|
|
|
};
|
|
|
|
passwordFile = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
description = "File containing the password for the join user.";
|
|
|
|
};
|
|
|
|
domainOUFile = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
description = "The OU to join the computer to.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = mkIf cfg.enable {
|
|
|
|
# Set network domain
|
|
|
|
networking.domain = domain;
|
|
|
|
networking.search = [ domain ];
|
|
|
|
|
|
|
|
# Automatically join the domain
|
|
|
|
systemd.services.adcli-join = {
|
|
|
|
description = "Automatically join the domain";
|
|
|
|
wantedBy = [ "default.target" ];
|
2025-06-11 14:13:25 +02:00
|
|
|
before = [ "sssd.service" ];
|
|
|
|
requiredBy = [ "sssd.service" ];
|
2025-06-08 03:04:14 +02:00
|
|
|
after = [
|
2025-06-08 03:39:12 +02:00
|
|
|
"network-online.target"
|
|
|
|
];
|
|
|
|
requires = [
|
|
|
|
"network-online.target"
|
2025-06-08 03:04:14 +02:00
|
|
|
];
|
|
|
|
serviceConfig = {
|
2025-06-11 11:58:54 +02:00
|
|
|
Type = "oneshot";
|
2025-06-08 03:04:14 +02:00
|
|
|
};
|
|
|
|
script = ''
|
|
|
|
ADCLI_JOIN_USER=$(cat ${cfg.join.userFile})
|
|
|
|
ADCLI_JOIN_OU=$(cat ${cfg.join.domainOUFile})
|
|
|
|
${pkgs.adcli}/bin/adcli join -D ${domain} \
|
|
|
|
-U $ADCLI_JOIN_USER \
|
2025-06-08 03:22:10 +02:00
|
|
|
-O $ADCLI_JOIN_OU \
|
2025-06-11 12:42:06 +02:00
|
|
|
--dont-expire-password=true \
|
2025-06-08 03:22:10 +02:00
|
|
|
--stdin-password < ${cfg.join.passwordFile}
|
2025-06-08 03:04:14 +02:00
|
|
|
'';
|
|
|
|
};
|
2025-06-08 03:39:12 +02:00
|
|
|
|
2025-06-09 01:47:48 +02:00
|
|
|
# Set up Kerberos
|
|
|
|
security.krb5 = {
|
|
|
|
enable = true;
|
|
|
|
settings = {
|
|
|
|
libdefaults = {
|
|
|
|
default_realm = domainUpper;
|
|
|
|
};
|
2025-06-09 01:54:39 +02:00
|
|
|
realms.${domainUpper} = {
|
|
|
|
};
|
2025-06-09 01:47:48 +02:00
|
|
|
domain_realm = {
|
|
|
|
"${domain}" = domainUpper;
|
|
|
|
".${domain}" = domainUpper;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2025-06-08 03:39:12 +02:00
|
|
|
# Set up SSSD
|
|
|
|
services.sssd = {
|
|
|
|
enable = true;
|
|
|
|
config = ''
|
|
|
|
[sssd]
|
|
|
|
domains = ${domain}
|
|
|
|
config_file_version = 2
|
2025-06-11 14:13:25 +02:00
|
|
|
services = nss, pam
|
2025-06-08 03:39:12 +02:00
|
|
|
|
2025-06-10 00:07:22 +02:00
|
|
|
[nss]
|
|
|
|
filter_users = ${concatStringsSep "," (lib.attrNames config.users.users)}
|
|
|
|
filter_groups = ${concatStringsSep "," (lib.attrNames config.users.groups)}
|
|
|
|
|
2025-06-08 03:39:12 +02:00
|
|
|
[domain/${domain}]
|
2025-06-09 03:09:14 +02:00
|
|
|
enumerate = False
|
2025-06-08 03:39:12 +02:00
|
|
|
ad_domain = ${domain}
|
2025-06-10 00:07:22 +02:00
|
|
|
krb5_realm = ${domainUpper}H
|
2025-06-08 03:39:12 +02:00
|
|
|
id_provider = ad
|
|
|
|
auth_provider = ad
|
|
|
|
access_provider = ad
|
|
|
|
chpass_provider = ad
|
2025-06-09 03:09:14 +02:00
|
|
|
use_fully_qualified_names = False
|
2025-06-09 01:34:29 +02:00
|
|
|
ldap_schema = ad
|
2025-06-09 03:09:14 +02:00
|
|
|
ldap_id_mapping = True
|
2025-06-09 01:34:29 +02:00
|
|
|
ad_gpo_access_control = enforcing
|
2025-06-09 03:09:14 +02:00
|
|
|
ad_gpo_implicit_deny = True
|
2025-06-11 13:01:02 +02:00
|
|
|
dyndns_update = True
|
|
|
|
dyndns_update_ptr = False
|
|
|
|
dyndns_refresh_interval = 86400
|
2025-06-08 03:45:33 +02:00
|
|
|
dyndns_ttl = 3600
|
2025-06-08 03:39:12 +02:00
|
|
|
'';
|
|
|
|
};
|
2025-06-09 04:05:52 +02:00
|
|
|
security.pam.services.login.sssdStrictAccess = true;
|
2025-06-09 03:42:25 +02:00
|
|
|
security.pam.services.sshd.sssdStrictAccess = true;
|
2025-06-11 14:13:25 +02:00
|
|
|
security.pam.services.su.sssdStrictAccess = true;
|
2025-06-09 02:17:05 +02:00
|
|
|
|
|
|
|
# Set up Sudo
|
|
|
|
security.sudo =
|
|
|
|
let
|
2025-06-11 14:13:25 +02:00
|
|
|
admin_group = "host_${lib.replaceStrings [ "-" ] [ "_" ] config.networking.hostName}_admin";
|
2025-06-09 02:17:05 +02:00
|
|
|
in
|
|
|
|
{
|
|
|
|
extraConfig = ''
|
|
|
|
%${admin_group} ALL=(ALL) SETENV: ALL
|
|
|
|
'';
|
|
|
|
};
|
2025-06-09 04:05:52 +02:00
|
|
|
|
2025-06-11 14:13:25 +02:00
|
|
|
# Set up SSH
|
2025-06-11 14:21:57 +02:00
|
|
|
services.openssh = {
|
|
|
|
package = pkgs.opensshWithKerberos;
|
|
|
|
settings = {
|
|
|
|
GSSAPIAuthentication = true;
|
|
|
|
GSSAPICleanupCredentials = true;
|
|
|
|
GSSAPIStrictAcceptorCheck = true;
|
|
|
|
};
|
2025-06-11 14:13:25 +02:00
|
|
|
};
|
|
|
|
|
2025-06-09 04:05:52 +02:00
|
|
|
# Set up home directory
|
2025-06-09 04:07:18 +02:00
|
|
|
security.pam.services.login.makeHomeDir = true;
|
|
|
|
security.pam.services.sshd.makeHomeDir = true;
|
2025-06-09 13:24:58 +02:00
|
|
|
environment.etc.profile.text =
|
2025-06-09 12:50:30 +02:00
|
|
|
let
|
2025-06-10 00:07:22 +02:00
|
|
|
# TODO: Activate configuration based on AD group
|
2025-06-09 12:50:30 +02:00
|
|
|
homeConfiguration = inputs.home-manager.lib.homeManagerConfiguration {
|
|
|
|
inherit pkgs;
|
|
|
|
modules = [
|
|
|
|
(
|
2025-06-10 03:04:44 +02:00
|
|
|
{ lib, ... }:
|
2025-06-09 12:50:30 +02:00
|
|
|
{
|
|
|
|
home.stateVersion = "24.11";
|
|
|
|
home.username = "$USER";
|
|
|
|
home.homeDirectory = "/.$HOME";
|
2025-06-09 13:06:29 +02:00
|
|
|
modules.profiles.base.enable = true;
|
2025-06-10 02:37:26 +02:00
|
|
|
|
|
|
|
# Mount the directories from the network share
|
2025-06-10 03:23:30 +02:00
|
|
|
home.activation.dirMount =
|
|
|
|
let
|
|
|
|
bindScript = dir: ''
|
|
|
|
mkdir -p /network/$USER/${dir}
|
2025-06-10 03:27:46 +02:00
|
|
|
mkdir -p $HOME/${dir}
|
2025-06-10 03:23:30 +02:00
|
|
|
${pkgs.bindfs}/bin/bindfs /network/$USER/${dir} $HOME/${dir}
|
|
|
|
'';
|
|
|
|
in
|
|
|
|
lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
|
|
|
if ! ${pkgs.krb5}/bin/klist -s; then
|
|
|
|
echo "No kerberos ticket found"
|
|
|
|
${pkgs.krb5}/bin/kinit
|
|
|
|
fi
|
|
|
|
|
|
|
|
if ${pkgs.krb5}/bin/klist -s; then
|
|
|
|
echo "Kerberos ticket found, mounting home directory"
|
|
|
|
${bindScript "Documents"}
|
|
|
|
${bindScript "Music"}
|
|
|
|
${bindScript "Pictures"}
|
|
|
|
${bindScript "Video"}
|
|
|
|
else
|
|
|
|
echo "Still no kerberos ticket found, skipping home directory mount"
|
|
|
|
fi
|
|
|
|
'';
|
2025-06-09 12:50:30 +02:00
|
|
|
}
|
|
|
|
)
|
|
|
|
] ++ config.home-manager.sharedModules;
|
|
|
|
};
|
|
|
|
in
|
2025-06-09 13:24:58 +02:00
|
|
|
mkAfter ''
|
2025-06-09 12:50:30 +02:00
|
|
|
# Activate Home Manager configuration for domain users
|
|
|
|
if id | egrep -o 'groups=.*' | sed 's/,/\n/g' | cut -d'(' -f2 | sed 's/)//' | egrep -o "^domain users$"; then
|
|
|
|
echo "Setting up environment for domain user"
|
2025-06-09 13:06:29 +02:00
|
|
|
SKIP_SANITY_CHECKS=1 ${homeConfiguration.activationPackage}/activate
|
2025-06-11 14:13:25 +02:00
|
|
|
if test -f "$HOME/.bashrc"; then
|
|
|
|
. $HOME/.bashrc
|
|
|
|
fi
|
2025-06-09 12:50:30 +02:00
|
|
|
fi
|
|
|
|
'';
|
2025-06-10 01:15:50 +02:00
|
|
|
|
2025-06-10 02:37:26 +02:00
|
|
|
# Automatically mount home share
|
|
|
|
# Can be accessed at /network/$USER
|
2025-06-10 01:15:50 +02:00
|
|
|
services.autofs = {
|
|
|
|
enable = true;
|
|
|
|
autoMaster =
|
|
|
|
let
|
|
|
|
networkMap = pkgs.writeText "auto" ''
|
2025-06-10 02:12:19 +02:00
|
|
|
* -fstype=cifs,sec=krb5,user=&,uid=$UID,gid=$GID,cruid=$UID ://${inputs.secrets.lab.nas.host}/home
|
2025-06-10 01:15:50 +02:00
|
|
|
'';
|
|
|
|
in
|
|
|
|
''
|
2025-06-10 02:12:19 +02:00
|
|
|
/network ${networkMap} --timeout=30
|
2025-06-10 01:15:50 +02:00
|
|
|
'';
|
|
|
|
};
|
2025-06-08 03:04:14 +02:00
|
|
|
};
|
|
|
|
}
|