mirror of
https://github.com/gensokyo-zone/infrastructure.git
synced 2026-02-09 12:29:19 -08:00
feat(idp): sync on a timer
This commit is contained in:
parent
3f7e25f5f5
commit
931af35f09
3 changed files with 196 additions and 101 deletions
42
modules/nixos/ldap/ldap-common.sh
Normal file
42
modules/nixos/ldap/ldap-common.sh
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
ldap_args_binddn() {
|
||||
if [[ -n ${LDAPBINDDN-} ]]; then
|
||||
LDAP_ARGS+=(
|
||||
-x
|
||||
-y "$LDAPBINDPW_FILE"
|
||||
)
|
||||
if [[ -n ${LDAPBINDPW-} ]]; then
|
||||
LDAP_ARGS+=(
|
||||
-w "$LDAPBINDPW"
|
||||
)
|
||||
else
|
||||
LDAP_ARGS+=(
|
||||
-y "$LDAPBINDPW_FILE"
|
||||
)
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
ldap_args_op() {
|
||||
ldap_args_binddn
|
||||
if [[ -z ${LDAPBINDDN-} ]]; then
|
||||
LDAP_ARGS+=(-Q)
|
||||
fi
|
||||
}
|
||||
|
||||
ldapwhoami() {
|
||||
local LDAP_ARGS=("$@")
|
||||
ldap_args_binddn
|
||||
command ldapwhoami "${LDAP_ARGS[@]}"
|
||||
}
|
||||
|
||||
ldapsearch() {
|
||||
local LDAP_ARGS=("$@")
|
||||
ldap_args_op
|
||||
command ldapsearch -LLL -o ldif_wrap=no "${LDAP_ARGS[@]}"
|
||||
}
|
||||
|
||||
ldapmodify() {
|
||||
local LDAP_ARGS=("$@")
|
||||
ldap_args_op
|
||||
command ldapmodify "${LDAP_ARGS[@]}"
|
||||
}
|
||||
69
modules/nixos/ldap/ldap-sync.sh
Normal file
69
modules/nixos/ldap/ldap-sync.sh
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
ldap_parse() {
|
||||
local LDAP_ATTR=$1 LDAP_LIMIT LDAP_LINE LDAP_COUNT=0
|
||||
shift 1
|
||||
local LDAP_LIMIT=${1-1}
|
||||
|
||||
while read -r LDAP_LINE; do
|
||||
if [[ $LDAP_LIMIT -eq 0 ]]; then
|
||||
break
|
||||
fi
|
||||
if [[ $LDAP_LINE = "$LDAP_ATTR:: "* ]]; then
|
||||
printf '%s\n' "$LDAP_LINE" | cut -d ' ' -f 2- | base64 -d
|
||||
elif [[ $LDAP_LINE = "$LDAP_ATTR: "* ]]; then
|
||||
printf '%s\n' "$LDAP_LINE" | cut -d ' ' -f 2-
|
||||
else
|
||||
continue
|
||||
fi
|
||||
LDAP_COUNT=$((LDAP_COUNT+1))
|
||||
LDAP_LIMIT=$((LDAP_LIMIT-1))
|
||||
done
|
||||
if [[ $LDAP_COUNT -eq 0 ]]; then
|
||||
echo "$LDAP_ATTR not found" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
smbsync_group() {
|
||||
local LDAP_GROUP_CN=$1 SMB_GROUP_DATA SMB_GROUP_SID
|
||||
shift 1
|
||||
|
||||
echo "updating cn=$LDAP_GROUP_CN,$LDAP_DNSUFFIX_GROUP ..." >&2
|
||||
SMB_GROUP_DATA=$(ldapsearch -z1 \
|
||||
-b "$LDAP_DNSUFFIX_GROUP$LDAPBASE" \
|
||||
"(&(cn=$LDAP_GROUP_CN)(objectClass=posixgroup))" \
|
||||
objectClass ipaNTSecurityIdentifier
|
||||
)
|
||||
SMB_GROUP_SID=$(ldap_parse ipaNTSecurityIdentifier <<< "$SMB_GROUP_DATA")
|
||||
ldapmodify <<EOF
|
||||
dn: cn=$LDAP_GROUP_CN,$LDAP_DNSUFFIX_GROUP$LDAPBASE
|
||||
changetype: modify
|
||||
replace: sambaSID
|
||||
sambaSID: $SMB_GROUP_SID
|
||||
-
|
||||
EOF
|
||||
}
|
||||
|
||||
smbsync_user() {
|
||||
local LDAP_USER_UID=$1 SMB_USER_DATA SMB_USER_SID SMB_USER_NTPASS
|
||||
shift 1
|
||||
|
||||
echo "updating uid=$LDAP_USER_UID,$LDAP_DNSUFFIX_USER ..." >&2
|
||||
SMB_USER_DATA=$(ldapsearch -z1 \
|
||||
-b "$LDAP_DNSUFFIX_USER$LDAPBASE" \
|
||||
"(&(uid=$LDAP_USER_UID)(objectClass=posixaccount))" \
|
||||
objectClass ipaNTSecurityIdentifier ipaNTHash ipaUserAuthType memberOf
|
||||
)
|
||||
SMB_USER_SID=$(ldap_parse ipaNTSecurityIdentifier <<< "$SMB_USER_DATA")
|
||||
SMB_USER_NTPASS=$(ldap_parse ipaNTHash <<< "$SMB_USER_DATA" | xxd -p)
|
||||
SMB_USER_NTPASS=${SMB_USER_NTPASS^^}
|
||||
ldapmodify <<EOF
|
||||
dn: uid=$LDAP_USER_UID,$LDAP_DNSUFFIX_USER$LDAPBASE
|
||||
changetype: modify
|
||||
replace: sambaSID
|
||||
sambaSID: $SMB_USER_SID
|
||||
-
|
||||
replace: sambaNTPassword
|
||||
sambaNTPassword: $SMB_USER_NTPASS
|
||||
-
|
||||
EOF
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
}: let
|
||||
inherit (inputs.self.lib.lib) mapOptionDefaults;
|
||||
inherit (lib.options) mkEnableOption;
|
||||
inherit (lib.modules) mkIf mkOptionDefault;
|
||||
inherit (lib.modules) mkIf mkMerge mkOptionDefault;
|
||||
inherit (lib.attrsets) attrValues;
|
||||
inherit (lib.lists) filter;
|
||||
inherit (lib.strings) concatStringsSep concatMapStringsSep escapeShellArgs;
|
||||
|
|
@ -29,92 +29,10 @@
|
|||
deletions = pkgs.writeText "ldap-management-delete.ldap" (
|
||||
concatMapStringsSep "\n" (object: object.changeText) deleteObjects
|
||||
);
|
||||
objectClassAttr = "objectClass";
|
||||
sidAttr = "ipaNTSecurityIdentifier";
|
||||
ntHashAttr = "ipaNTHash";
|
||||
authTypeAttr = "ipaUserAuthType";
|
||||
userSearchAttrs = [ objectClassAttr sidAttr authTypeAttr ntHashAttr ];
|
||||
groupSearchAttrs = [ objectClassAttr sidAttr ];
|
||||
managementScript = pkgs.writeShellScript "ldap-management.sh" ''
|
||||
managementScript = pkgs.writeShellScript "ldap-management-init.sh" ''
|
||||
set -eu
|
||||
|
||||
ldapsearch() {
|
||||
command ldapsearch -QLLL -o ldif_wrap=no "$@"
|
||||
}
|
||||
|
||||
ldapmodify() {
|
||||
command ldapmodify -Q "$@"
|
||||
}
|
||||
|
||||
ldap_parse() {
|
||||
local LDAP_ATTR=$1 LDAP_LIMIT LDAP_LINE LDAP_COUNT=0
|
||||
shift 1
|
||||
local LDAP_LIMIT=''${1-1}
|
||||
|
||||
while read -r LDAP_LINE; do
|
||||
if [[ $LDAP_LIMIT -eq 0 ]]; then
|
||||
break
|
||||
fi
|
||||
if [[ $LDAP_LINE = "$LDAP_ATTR:: "* ]]; then
|
||||
printf '%s\n' "$LDAP_LINE" | cut -d ' ' -f 2- | base64 -d
|
||||
elif [[ $LDAP_LINE = "$LDAP_ATTR: "* ]]; then
|
||||
printf '%s\n' "$LDAP_LINE" | cut -d ' ' -f 2-
|
||||
else
|
||||
continue
|
||||
fi
|
||||
LDAP_COUNT=$((LDAP_COUNT+1))
|
||||
LDAP_LIMIT=$((LDAP_LIMIT-1))
|
||||
done
|
||||
if [[ $LDAP_COUNT -eq 0 ]]; then
|
||||
echo "$LDAP_ATTR not found" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
smbsync_group() {
|
||||
local LDAP_GROUP_CN=$1 SMB_GROUP_DATA SMB_GROUP_SID
|
||||
shift 1
|
||||
|
||||
echo "updating cn=''${LDAP_GROUP_CN},${ldap.groupDnSuffix} ..." >&2
|
||||
SMB_GROUP_DATA=$(ldapsearch -z1 \
|
||||
-b "${ldap.groupDnSuffix}${ldap.base}" \
|
||||
"(&(cn=$LDAP_GROUP_CN)(${objectClassAttr}=posixgroup))" \
|
||||
${escapeShellArgs groupSearchAttrs}
|
||||
)
|
||||
SMB_GROUP_SID=$(ldap_parse ${sidAttr} <<< "$SMB_GROUP_DATA")
|
||||
ldapmodify <<EOF
|
||||
dn: cn=$LDAP_GROUP_CN,${ldap.groupDnSuffix}${ldap.base}
|
||||
changetype: modify
|
||||
replace: sambaSID
|
||||
sambaSID: $SMB_GROUP_SID
|
||||
-
|
||||
EOF
|
||||
}
|
||||
|
||||
smbsync_user() {
|
||||
local LDAP_USER_UID=$1 SMB_USER_DATA SMB_USER_SID SMB_USER_NTPASS
|
||||
shift 1
|
||||
|
||||
echo "updating uid=''${LDAP_USER_UID},${ldap.userDnSuffix} ..." >&2
|
||||
SMB_USER_DATA=$(ldapsearch -z1 \
|
||||
-b "${ldap.userDnSuffix}${ldap.base}" \
|
||||
"(&(uid=$LDAP_USER_UID)(${objectClassAttr}=posixaccount))" \
|
||||
${escapeShellArgs userSearchAttrs}
|
||||
)
|
||||
SMB_USER_SID=$(ldap_parse ${sidAttr} <<< "$SMB_USER_DATA")
|
||||
SMB_USER_NTPASS=$(ldap_parse ${ntHashAttr} <<< "$SMB_USER_DATA" | xxd -p)
|
||||
SMB_USER_NTPASS=''${SMB_USER_NTPASS^^}
|
||||
ldapmodify <<EOF
|
||||
dn: uid=$LDAP_USER_UID,${ldap.userDnSuffix}${ldap.base}
|
||||
changetype: modify
|
||||
replace: sambaSID
|
||||
sambaSID: $SMB_USER_SID
|
||||
-
|
||||
replace: sambaNTPassword
|
||||
sambaNTPassword: $SMB_USER_NTPASS
|
||||
-
|
||||
EOF
|
||||
}
|
||||
source ${./ldap-common.sh}
|
||||
|
||||
ldapwhoami
|
||||
|
||||
|
|
@ -123,6 +41,14 @@
|
|||
ldapmodify -c -f "$MAN_LDAP_MODIFY" || true
|
||||
|
||||
ldapmodify -f "$MAN_LDAP_DELETE"
|
||||
'';
|
||||
syncScript = pkgs.writeShellScript "ldap-management-sync.sh" ''
|
||||
set -eu
|
||||
|
||||
source ${./ldap-common.sh}
|
||||
source ${./ldap-sync.sh}
|
||||
|
||||
ldapwhoami
|
||||
|
||||
IFS=',' declare -a 'SMB_SYNC_GROUPS=($SMB_SYNC_GROUPS)'
|
||||
for SMB_GROUP_CN in "''${SMB_SYNC_GROUPS[@]}"; do
|
||||
|
|
@ -137,27 +63,85 @@ in {
|
|||
options.users.ldap.management = with lib.types; {
|
||||
enable = mkEnableOption "LDAP object management";
|
||||
};
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.ldap-management = rec {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
wants = [ "krb5-host.service" ];
|
||||
after = wants;
|
||||
path = [ config.services.openldap.package pkgs.coreutils pkgs.xxd ];
|
||||
environment = mapOptionDefaults {
|
||||
config.systemd = let
|
||||
path = [ config.services.openldap.package pkgs.coreutils ];
|
||||
krb5-host = "krb5-host.service";
|
||||
ldap-management-init = "ldap-management-init.service";
|
||||
ldapEnv = mapOptionDefaults {
|
||||
# man 5 ldap.conf
|
||||
LDAPBASE = ldap.base;
|
||||
LDAPURI = "ldaps://ldap.int.${config.networking.domain}";
|
||||
};
|
||||
ldapAuth = mkMerge [
|
||||
(mkIf config.security.krb5.enable (mapOptionDefaults {
|
||||
LDAPSASL_MECH = "GSSAPI";
|
||||
LDAPSASL_AUTHCID = "dn:fqdn=${config.networking.fqdn},${ldap.hostDnSuffix}${ldap.base}";
|
||||
# LDAPBINDDN?
|
||||
SMB_SYNC_GROUPS = concatStringsSep "," (map (group: group.name) smbSyncGroups);
|
||||
SMB_SYNC_USERS = concatStringsSep "," (map (user: user.uid) smbSyncUsers);
|
||||
}))
|
||||
(mkIf (config.users.ldap.bind.distinguishedName != "") (mapOptionDefaults {
|
||||
LDAPBINDDN = config.users.ldap.bind.distinguishedName;
|
||||
LDAPBINDPW_FILE = config.users.ldap.bind.passwordFile;
|
||||
}))
|
||||
];
|
||||
smbSyncGroupNames = map (group: group.name) smbSyncGroups;
|
||||
smbSyncUserNames = map (user: user.uid) smbSyncUsers;
|
||||
in mkIf cfg.enable {
|
||||
services.ldap-management-init = {
|
||||
inherit path;
|
||||
wants = [ krb5-host ];
|
||||
after = [ krb5-host ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
restartTriggers = [
|
||||
"${additions}"
|
||||
"${modifications}"
|
||||
"${deletions}"
|
||||
];
|
||||
environment = mkMerge [
|
||||
ldapEnv
|
||||
ldapAuth
|
||||
(mapOptionDefaults {
|
||||
MAN_LDAP_ADD = "${additions}";
|
||||
MAN_LDAP_MODIFY = "${modifications}";
|
||||
MAN_LDAP_DELETE = "${deletions}";
|
||||
};
|
||||
})
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = mkOptionDefault "oneshot";
|
||||
ExecStart = [ "${managementScript}" ];
|
||||
RemainAfterExit = mkOptionDefault true;
|
||||
};
|
||||
};
|
||||
services.ldap-management-sync = {
|
||||
wants = [ krb5-host ];
|
||||
requires = [ ldap-management-init ];
|
||||
after = [ krb5-host ldap-management-init ];
|
||||
path = mkMerge [
|
||||
path
|
||||
[ pkgs.xxd ]
|
||||
];
|
||||
restartTriggers = [
|
||||
smbSyncGroupNames
|
||||
smbSyncUserNames
|
||||
];
|
||||
environment = mkMerge [
|
||||
ldapEnv
|
||||
ldapAuth
|
||||
(mapOptionDefaults {
|
||||
LDAP_DNSUFFIX_USER = ldap.userDnSuffix;
|
||||
LDAP_DNSUFFIX_GROUP = ldap.groupDnSuffix;
|
||||
SMB_SYNC_GROUPS = concatStringsSep "," smbSyncGroupNames;
|
||||
SMB_SYNC_USERS = concatStringsSep "," smbSyncUserNames;
|
||||
})
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = mkOptionDefault "oneshot";
|
||||
ExecStart = [ "${syncScript}" ];
|
||||
};
|
||||
};
|
||||
timers.ldap-management-sync = {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = mapOptionDefaults {
|
||||
OnBootSec = "1m";
|
||||
OnUnitInactiveSec = "30m";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue