chore(idp): sys accounts

This commit is contained in:
arcnmx 2024-04-02 13:52:06 -07:00
parent db2f7d27b3
commit 34d1b400e1
10 changed files with 561 additions and 81 deletions

View file

@ -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;
};
}

View file

@ -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

View file

@ -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

View file

@ -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 = {

View file

@ -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";

View file

@ -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;
};
}

View file

@ -31,6 +31,7 @@ in {
roleDnSuffix = mkDefault "cn=roles,cn=accounts,";
serviceDnSuffix = mkDefault "cn=services,cn=accounts,";
hostDnSuffix = mkDefault "cn=computers,cn=accounts,";
hostGroupDnSuffix = mkDefault "cn=hostgroups,cn=accounts,";
sysAccountDnSuffix = mkDefault "cn=sysaccounts,cn=etc,";
domainDnSuffix = mkDefault "cn=ad,cn=etc,";
};

View file

@ -2,7 +2,6 @@
inherit (lib.modules) mkDefault;
inherit (config.users) ldap;
inherit (ldap.management) permissions;
adminPriv = "cn=Custom Management Admin,${ldap.privilegeDnSuffix}";
in {
config.users.ldap.management = {
enable = mkDefault true;
@ -16,7 +15,6 @@ in {
location = ldap.permissionDnSuffix;
target = "cn=*";
rights = "all";
members = [ adminPriv ];
attrs = [
"member" "cn" "o" "ou" "owner" "description" "objectclass" "seealso" "businesscategory"
"ipapermtarget" "ipapermright" "ipapermincludedattr" "ipapermbindruletype" "ipapermexcludedattr" "ipapermtargetto" "ipapermissiontype" "ipapermlocation" "ipapermdefaultattr" "ipapermtargetfrom" "ipapermtargetfilter"
@ -26,7 +24,6 @@ in {
location = ldap.privilegeDnSuffix;
target = "cn=*";
rights = "all";
members = [ adminPriv ];
attrs = [
"member" "memberof" "cn" "o" "ou" "owner" "description" "objectclass" "seealso" "businesscategory"
];
@ -35,52 +32,82 @@ in {
location = ldap.roleDnSuffix;
target = "cn=*";
rights = "all";
members = [ adminPriv ];
attrs = [
"member" "memberof" "cn" "o" "ou" "owner" "description" "objectclass" "seealso" "businesscategory"
];
};
"Custom Role Modify" = {
targetType = "role";
rights = [ "write" ];
members = [ adminPriv ];
rights = [ "write" "add" ];
attrs = permissions."Custom Role Admin".attrs;
};
"Custom Host Permission" = {
targetType = "host";
rights = [ "write" ];
members = [ adminPriv ];
attrs = [
"memberof"
];
};
"Custom SysAccount Permission" = {
targetType = "sysaccount";
rights = [ "write" ];
members = [ adminPriv ];
rights = "all";
attrs = [
"memberof"
"member" "memberof" "uid" "o" "ou" "description" "objectclass" "seealso" "businesscategory"
"passwordExpirationTime" "nsIdleTimeout"
];
};
"Custom SysAccount Admin" = {
location = ldap.sysAccountDnSuffix;
target = "uid=*";
rights = [ "add" "write" "delete" ];
attrs = permissions."Custom SysAccount Permission".attrs ++ [
"userPassword"
];
};
"Custom Service Permission" = {
targetType = "service";
rights = [ "write" ];
members = [ adminPriv ];
attrs = [
"memberof"
];
};
};
objects = {
${adminPriv} = {
changeType = "add";
settings = {
objectClass = [ "top" "nestedgroup" "groupofnames" ];
member = map config.lib.ldap.withBaseDn [
"cn=Security Architect,${ldap.roleDnSuffix}"
privileges = {
"Custom Management Admin" = {
permissions = [
"Custom Permission Admin"
"Custom Privilege Admin"
"Custom Role Admin"
"Custom Role Modify"
"Custom Host Permission"
"Custom SysAccount Permission"
"Custom SysAccount Admin"
"Custom Service Permission"
];
};
};
roles = {
"Security Architect" = {
privileges = [
"Custom Management Admin"
# you can't manage roles if you can't see them .-.
"RBAC Readers"
];
# allow reimu to actually make these changes...
members = [
"fqdn=reimu.${config.networking.domain},${ldap.hostDnSuffix}"
];
};
};
sysAccounts = {
peep = {
passwordFile = config.sops.secrets.ldap-peep-password.path;
};
keycloak = {
passwordFile = config.sops.secrets.ldap-keycloak-password.path;
};
};
objects = {
# change default public access
"cn=System: Read User Compat Tree,${ldap.permissionDnSuffix}" = {
settings.ipaPermBindRuleType = "all";
@ -91,10 +118,16 @@ in {
"cn=System: Read User Standard Attributes,${ldap.permissionDnSuffix}" = {
settings.ipaPermBindRuleType = "all";
};
# allow reimu to actually make these changes...
"cn=Security Architect,${ldap.roleDnSuffix}" = {
settings.member = [ "fqdn=reimu.${config.networking.domain},${ldap.hostDnSuffix}${ldap.base}" ];
};
};
config.sops.secrets = let
sopsFile = mkDefault ../secrets/ldap.yaml;
in {
ldap-peep-password = {
inherit sopsFile;
};
ldap-keycloak-password = {
inherit sopsFile;
};
};
}

View file

@ -1,10 +1,6 @@
{config, lib, ...}: let
inherit (lib.modules) mkDefault;
inherit (config.users) ldap;
inherit (ldap.management) permissions;
adminPriv = "cn=Custom Management Admin,${ldap.privilegeDnSuffix}";
smbPriv = "cn=Samba smbd,${ldap.privilegeDnSuffix}";
smbRole = "cn=Samba smbd,${ldap.roleDnSuffix}";
smbAccountAttrs = [ "sambasid" "sambapwdlastset" "sambaacctflags" "sambapasswordhistory" "sambantpassword" ];
smbGroupAttrs = [ "sambasid" "sambagrouptype" ];
smbDomainAttrs = [ "sambasid" "sambaRefuseMachinePwdChange" "sambaMinPwdLength" "sambaAlgorithmicRidBase" "sambaPwdHistoryLength" "sambaDomainName" "sambaMinPwdAge" "sambaMaxPwdAge" "sambaLockoutThreshold" "sambaForceLogoff" "sambaLogonToChgPwd" "sambaLockoutObservationWindow" "sambaNextUserRid" "sambaLockoutDuration" ];
@ -15,70 +11,58 @@ in {
"Custom Samba User Read" = {
targetType = "user";
attrs = [ "ipanthash" "ipanthomedirectory" "ipanthomedirectorydrive" "ipantlogonscript" "ipantprofilepath" "ipantsecurityidentifier" ] ++ smbAccountAttrs;
members = [ smbPriv ];
};
"Custom Samba User Modify" = {
targetType = "user";
rights = [ "write" ];
attrs = smbAccountAttrs;
members = permissions."Custom Samba User Admin".members;
};
"Custom Samba User Admin" = {
targetType = "user";
rights = [ "write" "add" ];
attrs = [ "objectclass" ];
members = [ adminPriv ];
rights = [ "write" ];
attrs = smbAccountAttrs ++ [ "objectclass" ];
};
"Custom Samba Group Read" = {
targetType = "user-group";
attrs = [ "ipantsecurityidentifier" "gidnumber" ] ++ smbGroupAttrs;
members = [ smbPriv ];
};
"Custom Samba Group Modify" = {
targetType = "user-group";
rights = [ "write" ];
attrs = smbGroupAttrs;
members = permissions."Custom Samba Group Admin".members;
};
"Custom Samba Group Admin" = {
targetType = "user-group";
rights = [ "write" "add" ];
attrs = [ "objectclass" ];
members = [ adminPriv ];
rights = [ "write" ];
attrs = smbGroupAttrs ++ [ "objectclass" ];
};
"Custom Samba Domain Read" = {
targetType = "samba-domain";
attrs = [ "objectClass" ] ++ smbDomainAttrs;
members = [ smbPriv ];
};
"Custom Samba Domain Modify" = {
targetType = "samba-domain";
rights = [ "write" ];
rights = [ "write" "add" ];
attrs = smbDomainAttrs;
members = permissions."Custom Samba Domain Admin".members;
};
"Custom Samba Domain Admin" = {
targetType = "domain";
rights = [ "write" "add" ];
attrs = [ "objectclass" ];
members = [ adminPriv ];
rights = [ "write" ];
attrs = smbDomainAttrs ++ [ "objectclass" ];
};
"Custom Samba Realm Read" = {
targetType = "domain";
attrs = [ "objectClass" "ipaNTSecurityIdentifier" "ipaNTFlatName" "ipaNTDomainGUID" "ipaNTFallbackPrimaryGroup" ] ++ smbDomainAttrs;
members = [ smbPriv ];
};
"Custom Samba Realm Modify" = {
targetType = "domain";
rights = [ "write" ];
attrs = smbDomainAttrs;
members = permissions."Custom Samba Realm Admin".members;
};
"Custom Samba Realm Admin" = {
targetType = "user-group";
rights = [ "write" "add" ];
attrs = [ "objectclass" ];
members = [ adminPriv ];
targetType = "domain";
rights = [ "write" ];
attrs = smbDomainAttrs ++ [ "objectclass" ];
};
};
users = {
@ -149,27 +133,45 @@ in {
};
};
};
objects = {
${smbPriv} = {
changeType = "add";
settings = {
objectClass = [ "top" "nestedgroup" "groupofnames" ];
member = map config.lib.ldap.withBaseDn [
"cn=Security Architect,${ldap.roleDnSuffix}"
"uid=samba,${ldap.sysAccountDnSuffix}"
smbRole
sysAccounts = {
samba = {
passwordFile = config.sops.secrets.ldap-samba-password.path;
};
};
privileges = {
"Samba smbd" = {
permissions = [
"Custom Samba User Read"
"Custom Samba Group Read"
"Custom Samba Domain Read"
"Custom Samba Realm Read"
];
};
"Custom Management Admin" = {
permissions = [
"Custom Samba User Admin"
"Custom Samba Group Admin"
"Custom Samba Domain Admin"
"Custom Samba Realm Admin"
"Custom Samba User Modify"
"Custom Samba Group Modify"
"Custom Samba Domain Modify"
"Custom Samba Realm Modify"
];
};
};
${smbRole} = {
changeType = "add";
settings = {
objectClass = [ "top" "nestedgroup" "groupofnames" ];
member = map config.lib.ldap.withBaseDn [
roles = {
"Samba smbd" = {
privileges = [
"Samba smbd"
];
members = [
"krbprincipalname=cifs/hakurei.${config.networking.domain}@${config.security.ipa.realm},${ldap.serviceDnSuffix}"
ldap.management.sysAccounts.samba.object.dn
];
};
};
objects = {
"cn=${config.networking.domain},${ldap.domainDnSuffix}" = {
objectClasses = [ "sambaDomain" ];
settings = {
@ -179,4 +181,11 @@ in {
};
};
};
config.sops.secrets = let
sopsFile = mkDefault ../secrets/ldap.yaml;
in {
ldap-samba-password = {
inherit sopsFile;
};
};
}

122
nixos/secrets/ldap.yaml Normal file
View file

@ -0,0 +1,122 @@
ldap-samba-password: ENC[AES256_GCM,data:2EnURacB0d6VXikBM39XzHG0evJRaWEmPC6pFRwTuLQ=,iv:YuFq8+vgN5UKJNgYgZleYT8GbM5LVgUeyvWXWXNLq/M=,tag:pUiD6975QkBn8ceQbFuDuA==,type:str]
ldap-peep-password: ENC[AES256_GCM,data:RtEE7EbmS70jqRt8HeUSoYJoUfcWGvLNoNeSBGb6mwk=,iv:/4zlBSlhsPuE9isT3K1qchAL/cEKVgTVXSHzrOYF6Ag=,tag:NoP6XouQVwvL/FNuAbzCKA==,type:str]
ldap-keycloak-password: ENC[AES256_GCM,data:pt//mcGuc90gG6PSx81nBHpZ1b+0zOPMb8ffIVWF4ng=,iv:8jYaVf/R1Me5DApeaSDFzG21PGVLM4CJboEg8ZSb+mo=,tag:UDMBTSziG088eGvXQ0jUxg==,type:str]
sops:
shamir_threshold: 1
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age12ze362pu5mza6ef9akrptr7hfe4auaqul4rkta7kyy2tnrstqensgmujeq
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOZjZBbStJdU5VeGNXUG92
OE5udnNJVUh0cjJEUFBuRllLaCt0MnZpcm1RCkduQTc5QU5EVE5GdUFlNU5zdFJs
N3J6MTJweUQrbFZJdE9xbTh4REJvM00KLS0tIEhCWXBjQWJvYmFnb0trUTlhQk1o
bUhUOFRoanZacXBKOTJaempzelVwbzQK6tsNplwqkrjwiUwxxaMguD1q7SeKKKsa
yB7S3XMBNFdX5eJ2+aGw6+omivu2426QZIW98gc0KgbVptY272mX6w==
-----END AGE ENCRYPTED FILE-----
- recipient: age176uyyyk7veqnzmm8xzwfhf0u23m6hm02cldlfkldunqe6std0gcq6lg057
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyNC9rL0dHQUE5RU1tUFFX
dWphQzJSRS9zdWZLKzdlRFJEVXI4OGJzNWxFCkRRTzMyY1NWYm5vNUthUG53bzg3
U2loZzdYZWZ1TEVxR0xiNldUeXU5ZW8KLS0tIGFYWXlkaFhtdVpvajBhbjIvOE4x
UjBFcDEyeTIvekU5VG9VNnlXQXVzcWsKt00QmEPogo7/wWKhMEHfgkXnwfcb1V9+
YafYEH30j3Kk0gVBZDJiNypDZub+aeL7zosass/lURsmZwFdDOvKFQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age15hmlkd9p5rladsjzpmvrh6u34xvggu9mzdsdxdj3ms43tltxeuhq4g7g9k
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5N1B4c0srYVVNNFlPWkYz
QUNXdFBNUllJTTBvcjRJNGMyUGRuWWIzRzBrCndOS1pPMzA5Qk1rc29LS25QL2ZP
dkV0U0tJU0xOSzFBcjRvQUxmSVZJZjAKLS0tIE8wSGlPcHd3SHJCUHFKQkhpQ1Bv
WXNZNTcwK2toNDJiUWsyNDlPb1FhNUEKlbd6VF324AYaW6tFDo4WYgwRq3p3qex7
Hqa9QPSqgrbJFLKeONwBx/BlDqhKxuNKDTUQpCX1YyxEFhrbnLZ4zQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age10t6kc5069cyky929vvxk8aznqyxpkx3k5h5rmlyz83xtjmr22ahqe8mzes
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuQTZCOUl3cmVYYk1ueHA5
RlhpRlF2OFppc0c0NXgzY2k1NGMwWFRkSGpnCjEzQnR5TndVWVJFRW9ETzFJbFhK
R1hzTGlycWlzbEplc1ZVb2xiV1pMTGcKLS0tIGhyNlVKUHFqYm1QbDZ6TzJKekE2
TmtxM1dubG1mVFBzTHdHdGZiaGRFVWcKiUM/aB7G4dp/j/GGxkRVRUwE5FTo9Z0r
ukFy8RpFm3Ctvl1MIZ30M0NNMTppu/CTOmoSo0OSxKE9Vltw/WtFLA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1a2quf2ekkj94ygu7wgvhrvh44fwn32c0l2cwvgvjh23wst90s54szdsvgr
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjRit6SlJVVWR1TGZxZ3Ni
MGlINjZCVkZqVTdSNWhpZFNLNXFqVEZBd1JFCmtyR2lJQmJNNGM1djRZZk9aYnRC
a3hFMzcvV3Z2TnZ6clNRdU10MEJnam8KLS0tIGFobXUvNHFPN1pNNm9QMXZhR3ZK
M3ZvQXptWksrdVhHMjE0SXZNWW9hRW8KbMZ2iWMsV+rLfSgJHwyd7OW9Dvf6EFWf
ldeW837x2uZCCR7Es7HShjC8Q7rXOsPsbnyuybTvj4zvh0qPAl/Fpw==
-----END AGE ENCRYPTED FILE-----
- recipient: age16klpkaut5759dut8mdm3jn0rnp8w6kxyvs9n6ntqrdsayjtd7upqlvw489
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLaWhrdHhYaEhPN3MySWM2
MWhpUE5FZnEzRW54bEF2eWk1S3pYL2ppeWdVCnRUSWdMQys2aElQTDA3eFpueVVP
SG4vZlQzWE5XVWdRVUlhNWhNQTZUVXMKLS0tIFVnaXRsbTArM0pJZ1N6cndYbXJY
YTRNd2N2ajVGU3FJWTk1cVdvbmM1VWsKING/3HcLu3Yp3n4LtEPB677jdPMPC63r
MwnHsBJx5CBZEou1D91WUXOFy6tVGyoouUb7XDOKrKx9FEx8/qbTPQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age13qgddr326g5je0fpq2r3k940vsr3fh9nlvl9xtcxk3xg2x0k3vsq7pvzaj
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqWkVXMlNlc3BqSXh0eklK
TzZIQXN5am9scXFzc05GaTNQR1YwMXBBUWxjCm9XbHlvckhvbmxaKzBnVENwZHR4
a2wyVEFOZHB5TXhZQ1JvZ0crL21ZbTQKLS0tIHZlSVVycUFidVBWREhsVFVHUklH
Q3c1NWJTcnZJc3dvVldRdDRiblAydUEKZ1Mtn+PQxyCg8OZ2lAB+rEfVAPk14pH1
eub12LarVz5nqgW+XhMb6ztJ5ks9xle9reIeHhILFtpvW8wahXTYVQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1ktmx2szedfnpe5xumnzs8vkk0ffqgga6ved3drtksg9pye6ndsnsnqq488
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4bVVvSnoxUitRd3NGR0N0
Zlhvc00yNzNDMURDZlFwdm9mOWpGa1hCeVFvClZhYVdoM2lNUGRwK3hGTk83Rjhn
YkRsTTM1ODBrWXpSTWx6Y1RpdnBTNlUKLS0tIGlOVVpIaUlQbzk0azFqT2JOL2pE
WFdaN0lEWDRxVGErWFIyRFFTcDBqRHcKfnvyeArVg/pTTBRoX5buAMK0egwZfY5M
LAQmTRAddbycMiHYAk2S2PRPW+mE/Bwg3Khi3G+LqTAX/1XrrXENWg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-04-03T19:02:13Z"
mac: ENC[AES256_GCM,data:Cak6rkD3J3tU6ADwlnFiNVN9qAuAnywE0mzZMAiT5sXCgV7QPzD21D57kxwNMKon8dUaYVtIrQ/01xzruiYNGrk2mzMqZ6W7Mf0U9yjp3AkJ88K1RlZyGUby/4TdjgSg9bNDSg17rai8EpnMwe6mqpPcQbnLmUwg1iaN0gLhEj4=,iv:Fx3u7GvTaVp1cyBRkei2RL6IqPttTTZKNQOAM0CRaNM=,tag:LfewOWvxfdPC4ArN9ufLAw==,type:str]
pgp:
- created_at: "2024-04-02T17:59:55Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA82M54yws73UARAAuEh+cW6lgZ0jigOUDH1kkoVLNlUEch4GKMFafvFlk40h
feVlHi/wOFsaKsUynMDN6IkoFEdjevv1TJ7Eh5xY7S0Ua9OppyFetszxDVkaXxiv
XZNow/fFSiBnjMAMnPEz/jqs3OSoKkrH8C6CbIt0K2pWMxFz7EW64nH1ZkboTrde
JP9w1Kpl0GAGlOJrNI6cGiOyP4LxhoVJq494kBLkLNgP9KFWrd4kA2Qof9fNAo24
b5Wmnvfa1mNhQH5xzSQEHBH6gVTGtcq0Pt0UYROZuo/DwJTOh3oXmOWkLb9YIE0i
ctDoKNtBW3+jpJI7nKSxp3Ys0BcZmowcpaByp9nW3/EaveqeWDgWnn0NNwrcHloi
z5xURx59rT/rRm4vztYp9WUyyeXIA7SmoDJ1/JhqeMNhd0VcCrqsG8dmO6+kwx8w
MXHVcNnisM5Jx0Wg/6becT6p3Ej1dHAEKSNoUNrWcVo/hThT1HvvBY9HvnMDsBp4
at6bYIl+F3JT3bBIbVFNpNynPQGzKxdOp+GmCtTsauECgBNivqpGabo5CTR7Shih
KqgpUuBJsM2rPUQiOro/eZOLlTtSRwHFZ0l/q1Mwm4ZhKbiqC/urMcsfZZUZyNh0
8wgFUncvJDiAbOrlrSB3Zij92DDlZqYlFiO07tF3YxPL5s386S/qpTUOAscLlnPS
XAGW1p93RF0qwdScAA01nQnA2RMyYW8tMeBV96y0OW8QrJua8b2rozqCP6Uesyze
Xz0XVMNcw2S7hQAedQIF6BAPG4rnzgyDVjOMVGDNzcwuSzJnEaL2DiPK6JoE
=+wSd
-----END PGP MESSAGE-----
fp: CD8CE78CB0B3BDD4
- created_at: "2024-04-02T17:59:55Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQEMA2W9MER3HLb7AQf/e0yDYqiD6lYq5lRUKGX7ILpCIix1qrHzml3hLSoXvlsj
CbYyP/M18chVJ40LkJrD5fLKkTH/qOuBU5mKR2DY7mhmMYVTGp91KR8kJYExbszr
gveKzmHczrTbCzpuoVUCzoKu68HQ+s8Cvj/puxrwy8AiiRk0g4Visr9q9yhrDy50
KQtb8vZysLA90mquMu4QOodoTn5zQMuVCqChPj3xJnGfBg5B4DM7kd3A6lAWXxC4
vFsMDPvT/lSJbDIu8DIigRgYNYXygG2vW93NS0zgRvm0YdjmbJeWrjbpBy9kDqRm
/zLZHybVPKRhuu3rIAMXZjsfpfS8Ap/tBRPDvP29o9JcAQXecjL0ZSMdeNWZImj3
pIBAlVzUcgMX2U0NvSm8GZgd9cR+AAQSpF80jFdZEFGG3l/0c0UOOeBO7+WmMBtr
qezAj3MfzsOfFuydY4BM8IogcqQ4n46u+rf43ms=
=ld0s
-----END PGP MESSAGE-----
fp: 65BD3044771CB6FB
unencrypted_suffix: _unencrypted
version: 3.8.1