mirror of
https://github.com/gensokyo-zone/infrastructure.git
synced 2026-02-09 12:29:19 -08:00
chore(idp): sys accounts
This commit is contained in:
parent
db2f7d27b3
commit
34d1b400e1
10 changed files with 561 additions and 81 deletions
|
|
@ -1,11 +1,70 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.options) mkOption;
|
||||
inherit (inputs.self.lib.lib) mkAlmostOptionDefault mapListToAttrs;
|
||||
inherit (lib.options) mkOption mkEnableOption;
|
||||
inherit (lib.modules) mkOptionDefault;
|
||||
inherit (lib.attrsets) mapAttrsToList;
|
||||
inherit (lib.lists) filter;
|
||||
cfg = config.users.ldap;
|
||||
ldap'lib = config.lib.ldap;
|
||||
sysaccountModule = {config, nixosConfig, name, ldap, ...}: {
|
||||
options = with lib.types; {
|
||||
enable = mkEnableOption "sys account" // {
|
||||
default = true;
|
||||
};
|
||||
uid = mkOption {
|
||||
type = str;
|
||||
default = name;
|
||||
};
|
||||
passwordFile = mkOption {
|
||||
type = nullOr path;
|
||||
default = null;
|
||||
};
|
||||
object = mkOption {
|
||||
type = ldap.lib.objectSettingsType;
|
||||
};
|
||||
};
|
||||
config = {
|
||||
object = {
|
||||
enable = mkAlmostOptionDefault config.enable;
|
||||
dn = mkOptionDefault (ldap.lib.withBaseDn "uid=${config.uid},${ldap.sysAccountDnSuffix}");
|
||||
settings = {
|
||||
changeType = mkAlmostOptionDefault "add";
|
||||
settings = {
|
||||
uid = mkOptionDefault config.uid;
|
||||
objectClass' = {
|
||||
name = "objectClass";
|
||||
initial = true;
|
||||
value = [ "account" "simplesecurityobject" ];
|
||||
};
|
||||
userPassword = {
|
||||
initial = true;
|
||||
value = mkOptionDefault "initial123";
|
||||
};
|
||||
passwordExpirationTime = {
|
||||
initial = true;
|
||||
value = mkOptionDefault "20010101031407Z";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
in {
|
||||
options.users.ldap = with lib.types; {
|
||||
management = {
|
||||
sysAccounts = mkOption {
|
||||
type = attrsOf (submoduleWith {
|
||||
modules = [ sysaccountModule ];
|
||||
inherit (config.lib.ldap) specialArgs;
|
||||
});
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
domainDnSuffix = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
|
|
@ -14,6 +73,10 @@ in {
|
|||
type = str;
|
||||
default = "";
|
||||
};
|
||||
hostGroupDnSuffix = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
serviceDnSuffix = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
|
|
@ -23,4 +86,10 @@ in {
|
|||
default = "";
|
||||
};
|
||||
};
|
||||
config.users.ldap = {
|
||||
management.objects = let
|
||||
sysAccountObjects = mapAttrsToList (_: acc: acc.object) cfg.management.sysAccounts;
|
||||
enabledObjects = filter (object: object.enable) sysAccountObjects;
|
||||
in mapListToAttrs ldap'lib.mapObjectSettingsToPair enabledObjects;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,12 @@ ldapwhoami() {
|
|||
command ldapwhoami "${LDAP_ARGS[@]}"
|
||||
}
|
||||
|
||||
ldappasswd() {
|
||||
local LDAP_ARGS=("$@")
|
||||
ldap_args_op
|
||||
command ldappasswd "${LDAP_ARGS[@]}"
|
||||
}
|
||||
|
||||
ldapsearch() {
|
||||
local LDAP_ARGS=("$@")
|
||||
ldap_args_op
|
||||
|
|
|
|||
|
|
@ -23,6 +23,80 @@ ldap_parse() {
|
|||
fi
|
||||
}
|
||||
|
||||
sysaccount_password() {
|
||||
local LDAP_SYSACCOUNT_UID=$1
|
||||
local LDAP_SYSACCOUNT_PASSWORD_PATH=$2
|
||||
shift 2
|
||||
|
||||
echo "updating uid=$LDAP_SYSACCOUNT_UID,$LDAP_DNSUFFIX_SYSACCOUNT ..." >&2
|
||||
if ! ldappasswd -T "$LDAP_SYSACCOUNT_PASSWORD_PATH" "uid=$LDAP_SYSACCOUNT_UID,$LDAP_DNSUFFIX_SYSACCOUNT$LDAPBASE"; then
|
||||
echo "failed to use ldappasswd, falling back to modify..." >&2
|
||||
ldapmodify <<EOF
|
||||
dn: uid=$LDAP_SYSACCOUNT_UID,$LDAP_DNSUFFIX_SYSACCOUNT$LDAPBASE
|
||||
changetype: modify
|
||||
replace: userPassword
|
||||
userPassword:< file://$LDAP_SYSACCOUNT_PASSWORD_PATH
|
||||
-
|
||||
delete: passwordExpirationTime
|
||||
-
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
privilege_permissions() {
|
||||
local LDAP_PRIVILEGE_CN=$1 LDAP_PRIVILEGE_PERMISSION_CN
|
||||
shift 1
|
||||
|
||||
echo "updating cn=$LDAP_PRIVILEGE_CN,$LDAP_DNSUFFIX_PRIVILEGE ..." >&2
|
||||
for LDAP_PRIVILEGE_PERMISSION_CN in "$@"; do
|
||||
ipa privilege-add-permission "$LDAP_PRIVILEGE_CN" --permissions="$LDAP_PRIVILEGE_PERMISSION_CN" || true
|
||||
done
|
||||
}
|
||||
|
||||
role_privileges() {
|
||||
local LDAP_ROLE_CN=$1 LDAP_ROLE_PRIVILEGE_CN
|
||||
shift 1
|
||||
|
||||
echo "updating cn=$LDAP_ROLE_CN,$LDAP_DNSUFFIX_ROLE ..." >&2
|
||||
for LDAP_ROLE_PRIVILEGE_CN in "$@"; do
|
||||
ipa role-add-privilege "$LDAP_ROLE_CN" --privileges="$LDAP_ROLE_PRIVILEGE_CN" || true
|
||||
done
|
||||
}
|
||||
|
||||
role_members() {
|
||||
local LDAP_ROLE_CN=$1 LDAP_ROLE_MEMBER_DN LDAP_ROLE_MEMBER_CN LDAP_ROLE_MEMBER_TYPE
|
||||
shift 1
|
||||
|
||||
echo "updating cn=$LDAP_ROLE_CN,$LDAP_DNSUFFIX_ROLE ..." >&2
|
||||
for LDAP_ROLE_MEMBER_DN in "$@"; do
|
||||
case $LDAP_ROLE_MEMBER_DN in
|
||||
uid=*",$LDAP_DNSUFFIX_USER"*)
|
||||
LDAP_ROLE_MEMBER_TYPE=users
|
||||
;;
|
||||
cn=*",$LDAP_DNSUFFIX_GROUP"*)
|
||||
LDAP_ROLE_MEMBER_TYPE=groups
|
||||
;;
|
||||
fqdn=*",$LDAP_DNSUFFIX_HOST"*)
|
||||
LDAP_ROLE_MEMBER_TYPE=hosts
|
||||
;;
|
||||
cn=*",$LDAP_DNSUFFIX_HOSTGROUP"*)
|
||||
LDAP_ROLE_MEMBER_TYPE=hostgroups
|
||||
;;
|
||||
krbprincipalname=*",$LDAP_DNSUFFIX_SERVICE"*)
|
||||
LDAP_ROLE_MEMBER_TYPE=services
|
||||
;;
|
||||
*)
|
||||
echo "WARN: unknown role member type for $LDAP_ROLE_MEMBER_DN" >&2
|
||||
ipa role-modify "$LDAP_ROLE_CN" --addattr=member="$LDAP_ROLE_MEMBER_DN" || true
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
LDAP_ROLE_MEMBER_CN=${LDAP_ROLE_MEMBER_DN%%,*}
|
||||
LDAP_ROLE_MEMBER_CN=${LDAP_ROLE_MEMBER_CN#*=}
|
||||
ipa role-add-member "$LDAP_ROLE_CN" --${LDAP_ROLE_MEMBER_TYPE}="$LDAP_ROLE_MEMBER_CN" || true
|
||||
done
|
||||
}
|
||||
|
||||
smbsync_group() {
|
||||
local LDAP_GROUP_CN=$1 SMB_GROUP_DATA SMB_GROUP_SID
|
||||
shift 1
|
||||
|
|
|
|||
|
|
@ -10,10 +10,18 @@
|
|||
inherit (lib.modules) mkIf mkMerge mkOptionDefault;
|
||||
inherit (lib.attrsets) attrValues;
|
||||
inherit (lib.lists) filter;
|
||||
inherit (lib.strings) concatStringsSep concatMapStringsSep escapeShellArgs;
|
||||
inherit (lib.strings) concatStringsSep concatMapStringsSep;
|
||||
inherit (config.users) ldap;
|
||||
cfg = config.users.ldap.management;
|
||||
ldap'lib = config.lib.ldap;
|
||||
enabledObjects = filter (object: object.enable) (attrValues cfg.objects);
|
||||
sysAccounts = filter (acc: acc.enable) (attrValues cfg.sysAccounts);
|
||||
sysAccountPasswordFiles = concatMapStringsSep "," (acc: "${acc.uid}=${toString acc.passwordFile}") sysAccounts;
|
||||
privileges = filter (priv: priv.enable) (attrValues cfg.privileges);
|
||||
privilegePermissions = concatMapStringsSep "," (priv: "${priv.cn}=${concatStringsSep "." priv.permissions}") privileges;
|
||||
roles = filter (role: role.enable) (attrValues cfg.roles);
|
||||
rolePrivileges = concatMapStringsSep "," (role: "${role.cn}=${concatStringsSep "." role.privileges}") roles;
|
||||
roleMembers = concatMapStringsSep "+" (role: "${role.cn}=${concatMapStringsSep "%" ldap'lib.withBaseDn role.members}") roles;
|
||||
smbSyncUsers = filter (user: user.samba.sync.enable) (attrValues cfg.users);
|
||||
smbSyncGroups = filter (group: group.samba.sync.enable) (attrValues cfg.groups);
|
||||
modifyObjects = filter (object: object.changeType == "modify") enabledObjects;
|
||||
|
|
@ -42,6 +50,56 @@
|
|||
|
||||
ldapmodify -f "$MAN_LDAP_DELETE"
|
||||
'';
|
||||
sysaccountScript = pkgs.writeShellScript "ldap-management-sysaccounts.sh" ''
|
||||
set -eu
|
||||
|
||||
source ${./ldap-common.sh}
|
||||
source ${./ldap-sync.sh}
|
||||
|
||||
IFS=',' declare -a 'SYSACCOUNT_PASSWORD_FILES=($SYSACCOUNT_PASSWORD_FILES)'
|
||||
for SYSACCOUNT_PASSWORD_FILE in "''${SYSACCOUNT_PASSWORD_FILES[@]}"; do
|
||||
SYSACCOUNT_UID=''${SYSACCOUNT_PASSWORD_FILE%%=*}
|
||||
SYSACCOUNT_PASSWORD_PATH=''${SYSACCOUNT_PASSWORD_FILE#*=}
|
||||
if [[ -n $SYSACCOUNT_PASSWORD_PATH ]]; then
|
||||
sysaccount_password "$SYSACCOUNT_UID" "$SYSACCOUNT_PASSWORD_PATH"
|
||||
fi
|
||||
done
|
||||
'';
|
||||
privilegeScript = pkgs.writeShellScript "ldap-management-privileges.sh" ''
|
||||
set -eu
|
||||
|
||||
source ${./ldap-common.sh}
|
||||
source ${./ldap-sync.sh}
|
||||
|
||||
IFS=',' declare -a 'PRIVILEGE_PERMISSIONS=($PRIVILEGE_PERMISSIONS)'
|
||||
for PRIVILEGE_PERMISSION in "''${PRIVILEGE_PERMISSIONS[@]}"; do
|
||||
PRIVILEGE_CN=''${PRIVILEGE_PERMISSION%%=*}
|
||||
PRIVILEGE_PERMS=''${PRIVILEGE_PERMISSION#*=}
|
||||
IFS='.' declare -a 'PRIVILEGE_PERMS=($PRIVILEGE_PERMS)'
|
||||
privilege_permissions "$PRIVILEGE_CN" "''${PRIVILEGE_PERMS[@]}"
|
||||
done
|
||||
'';
|
||||
roleScript = pkgs.writeShellScript "ldap-management-rols.sh" ''
|
||||
set -eu
|
||||
|
||||
source ${./ldap-common.sh}
|
||||
source ${./ldap-sync.sh}
|
||||
|
||||
IFS=',' declare -a 'ROLE_PRIVILEGES=($ROLE_PRIVILEGES)'
|
||||
for ROLE_PRIVILEGE in "''${ROLE_PRIVILEGES[@]}"; do
|
||||
ROLE_CN=''${ROLE_PRIVILEGE%%=*}
|
||||
ROLE_PRIVS=''${ROLE_PRIVILEGE#*=}
|
||||
IFS='.' declare -a 'ROLE_PRIVS=($ROLE_PRIVS)'
|
||||
role_privileges "$ROLE_CN" "''${ROLE_PRIVS[@]}"
|
||||
done
|
||||
IFS='+' declare -a 'ROLE_MEMBERS=($ROLE_MEMBERS)'
|
||||
for ROLE_MEMBER in "''${ROLE_MEMBERS[@]}"; do
|
||||
ROLE_CN=''${ROLE_MEMBER%%=*}
|
||||
ROLE_MEMS=''${ROLE_MEMBER#*=}
|
||||
IFS='%' declare -a 'ROLE_MEMS=($ROLE_MEMS)'
|
||||
role_members "$ROLE_CN" "''${ROLE_MEMS[@]}"
|
||||
done
|
||||
'';
|
||||
syncScript = pkgs.writeShellScript "ldap-management-sync.sh" ''
|
||||
set -eu
|
||||
|
||||
|
|
@ -106,7 +164,9 @@ in {
|
|||
];
|
||||
serviceConfig = {
|
||||
Type = mkOptionDefault "oneshot";
|
||||
ExecStart = [ "${managementScript}" ];
|
||||
ExecStart = [
|
||||
"${managementScript}"
|
||||
];
|
||||
RemainAfterExit = mkOptionDefault true;
|
||||
};
|
||||
};
|
||||
|
|
@ -117,10 +177,15 @@ in {
|
|||
path = mkMerge [
|
||||
path
|
||||
[ pkgs.xxd ]
|
||||
(mkIf config.security.ipa.enable [ pkgs.freeipa ])
|
||||
];
|
||||
restartTriggers = [
|
||||
smbSyncGroupNames
|
||||
smbSyncUserNames
|
||||
sysAccountPasswordFiles
|
||||
privilegePermissions
|
||||
rolePrivileges
|
||||
roleMembers
|
||||
];
|
||||
environment = mkMerge [
|
||||
ldapEnv
|
||||
|
|
@ -128,13 +193,29 @@ in {
|
|||
(mapOptionDefaults {
|
||||
LDAP_DNSUFFIX_USER = ldap.userDnSuffix;
|
||||
LDAP_DNSUFFIX_GROUP = ldap.groupDnSuffix;
|
||||
LDAP_DNSUFFIX_SYSACCOUNT = ldap.sysAccountDnSuffix;
|
||||
LDAP_DNSUFFIX_PERMISSION = ldap.permissionDnSuffix;
|
||||
LDAP_DNSUFFIX_PRIVILEGE = ldap.privilegeDnSuffix;
|
||||
LDAP_DNSUFFIX_ROLE = ldap.roleDnSuffix;
|
||||
LDAP_DNSUFFIX_HOST = ldap.hostDnSuffix;
|
||||
LDAP_DNSUFFIX_HOSTGROUP = ldap.hostGroupDnSuffix;
|
||||
LDAP_DNSUFFIX_SERVICE = ldap.serviceDnSuffix;
|
||||
SMB_SYNC_GROUPS = concatStringsSep "," smbSyncGroupNames;
|
||||
SMB_SYNC_USERS = concatStringsSep "," smbSyncUserNames;
|
||||
SYSACCOUNT_PASSWORD_FILES = sysAccountPasswordFiles;
|
||||
PRIVILEGE_PERMISSIONS = privilegePermissions;
|
||||
ROLE_PRIVILEGES = rolePrivileges;
|
||||
ROLE_MEMBERS = roleMembers;
|
||||
})
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = mkOptionDefault "oneshot";
|
||||
ExecStart = [ "${syncScript}" ];
|
||||
ExecStart = mkMerge [
|
||||
(mkIf (privileges != [ ]) [ "${privilegeScript}" ])
|
||||
(mkIf (roles != [ ]) [ "${roleScript}" ])
|
||||
[ "${syncScript}" ]
|
||||
(mkIf (sysAccounts != [ ]) [ "${sysaccountScript}" ])
|
||||
];
|
||||
};
|
||||
};
|
||||
timers.ldap-management-sync = {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@
|
|||
'';
|
||||
in {
|
||||
modify = object: let
|
||||
enabledSettings' = filterAttrs (_: setting: setting.enable) object.settings;
|
||||
enabledSettings' = filterAttrs (_: setting: setting.enable && !setting.initial) object.settings;
|
||||
enabledSettings = ldap'lib.mkLdapModifyObjectSettings enabledSettings';
|
||||
replaceSettings' = filterAttrs (_: setting: setting.modifyType == "replace") enabledSettings';
|
||||
replaceSettings = ldap'lib.mkLdapModifyObjectSettings replaceSettings';
|
||||
|
|
@ -114,6 +114,10 @@
|
|||
value = mkOption {
|
||||
type = ldapValueType;
|
||||
};
|
||||
initial = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
modifyType = mkOption {
|
||||
type = enum [ "replace" "add" "delete" ];
|
||||
default = "replace";
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
...
|
||||
}: let
|
||||
inherit (inputs.self.lib.lib) mkAlmostOptionDefault mapOptionDefaults mapListToAttrs;
|
||||
inherit (lib.options) mkOption;
|
||||
inherit (lib.options) mkOption mkEnableOption;
|
||||
inherit (lib.modules) mkIf mkMerge mkOptionDefault;
|
||||
inherit (lib.attrsets) attrNames mapAttrs mapAttrsToList;
|
||||
inherit (lib.lists) filter;
|
||||
|
|
@ -55,8 +55,7 @@
|
|||
};
|
||||
sysaccount = {
|
||||
location = ldap.sysAccountDnSuffix;
|
||||
# TODO: targetFilter
|
||||
target = "uid=*";
|
||||
targetFilter = "(objectclass=account)";
|
||||
};
|
||||
};
|
||||
in {
|
||||
|
|
@ -95,13 +94,13 @@
|
|||
};
|
||||
members = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
};
|
||||
object = mkOption {
|
||||
type = ldap.lib.objectSettingsType;
|
||||
};
|
||||
};
|
||||
config = let
|
||||
conf.members = mkIf (config.bindType != "permission") (mkOptionDefault [ ]);
|
||||
conf.targetFilter = mkIf (config.target != null) (mkOptionDefault null);
|
||||
conf.object = {
|
||||
dn = mkOptionDefault (ldap.lib.withBaseDn "cn=${config.cn},${ldap.permissionDnSuffix}");
|
||||
|
|
@ -129,6 +128,73 @@
|
|||
};
|
||||
in mkMerge [ conf target ];
|
||||
};
|
||||
privilegeModule = {config, name, ldap, ...}: {
|
||||
options = with lib.types; {
|
||||
enable = mkEnableOption "privilege" // {
|
||||
default = true;
|
||||
};
|
||||
cn = mkOption {
|
||||
type = str;
|
||||
default = name;
|
||||
};
|
||||
permissions = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
};
|
||||
object = mkOption {
|
||||
type = ldap.lib.objectSettingsType;
|
||||
};
|
||||
};
|
||||
config = {
|
||||
object = {
|
||||
enable = mkAlmostOptionDefault config.enable;
|
||||
dn = mkOptionDefault (ldap.lib.withBaseDn "cn=${config.cn},${ldap.privilegeDnSuffix}");
|
||||
settings = {
|
||||
changeType = mkAlmostOptionDefault "add";
|
||||
settings = mapOptionDefaults {
|
||||
cn = config.cn;
|
||||
objectClass = [ "top" "nestedgroup" "groupofnames" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
roleModule = {config, name, ldap, ...}: {
|
||||
options = with lib.types; {
|
||||
enable = mkEnableOption "role" // {
|
||||
default = true;
|
||||
};
|
||||
cn = mkOption {
|
||||
type = str;
|
||||
default = name;
|
||||
};
|
||||
privileges = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
};
|
||||
members = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
};
|
||||
object = mkOption {
|
||||
type = ldap.lib.objectSettingsType;
|
||||
};
|
||||
};
|
||||
config = {
|
||||
object = {
|
||||
enable = mkAlmostOptionDefault config.enable;
|
||||
dn = mkOptionDefault (ldap.lib.withBaseDn "cn=${config.cn},${ldap.roleDnSuffix}");
|
||||
settings = {
|
||||
changeType = mkAlmostOptionDefault "add";
|
||||
settings = mapOptionDefaults {
|
||||
cn = config.cn;
|
||||
objectClass = [ "top" "nestedgroup" "groupofnames" ];
|
||||
member = mkIf (config.members != [ ]) (mkOptionDefault (map ldap.lib.withBaseDn config.members));
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
in {
|
||||
options.users.ldap = with lib.types; {
|
||||
management = {
|
||||
|
|
@ -139,6 +205,20 @@ in {
|
|||
});
|
||||
default = { };
|
||||
};
|
||||
privileges = mkOption {
|
||||
type = attrsOf (submoduleWith {
|
||||
modules = [ privilegeModule ];
|
||||
inherit (config.lib.ldap) specialArgs;
|
||||
});
|
||||
default = { };
|
||||
};
|
||||
roles = mkOption {
|
||||
type = attrsOf (submoduleWith {
|
||||
modules = [ roleModule ];
|
||||
inherit (config.lib.ldap) specialArgs;
|
||||
});
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
permissionDnSuffix = mkOption {
|
||||
type = str;
|
||||
|
|
@ -152,8 +232,9 @@ in {
|
|||
};
|
||||
config.users.ldap = {
|
||||
management.objects = let
|
||||
permissionObjects = mapAttrsToList (_: user: user.object) cfg.management.permissions;
|
||||
enabledObjects = filter (object: object.enable) (permissionObjects);
|
||||
permissionObjects = mapAttrsToList (_: perm: perm.object) cfg.management.permissions;
|
||||
privilegeObjects = mapAttrsToList (_: priv: priv.object) cfg.management.privileges;
|
||||
enabledObjects = filter (object: object.enable) (permissionObjects ++ privilegeObjects);
|
||||
in mapListToAttrs ldap'lib.mapObjectSettingsToPair enabledObjects;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue