feat(auth,roundcube): members of sp.admins group become admins
This commit is contained in:
@@ -1,9 +1,8 @@
|
|||||||
{
|
{ config
|
||||||
config,
|
, lib
|
||||||
lib,
|
, options
|
||||||
options,
|
, pkgs
|
||||||
pkgs,
|
, ...
|
||||||
...
|
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
@@ -55,7 +54,8 @@ let
|
|||||||
# paths, no new bind mount is added. Adding subpaths caused problems on ofborg.
|
# paths, no new bind mount is added. Adding subpaths caused problems on ofborg.
|
||||||
hasPrefixInList =
|
hasPrefixInList =
|
||||||
list: newPath: any (path: hasPrefix (builtins.toString path) (builtins.toString newPath)) list;
|
list: newPath: any (path: hasPrefix (builtins.toString path) (builtins.toString newPath)) list;
|
||||||
mergePaths = foldl' (
|
mergePaths = foldl'
|
||||||
|
(
|
||||||
merged: newPath:
|
merged: newPath:
|
||||||
let
|
let
|
||||||
# If the new path is a prefix to some existing path, we need to filter it out
|
# If the new path is a prefix to some existing path, we need to filter it out
|
||||||
@@ -126,13 +126,16 @@ let
|
|||||||
|
|
||||||
filterPresent = filterAttrs (_: v: v.present);
|
filterPresent = filterAttrs (_: v: v.present);
|
||||||
|
|
||||||
isGroupEmpty = g: ! g ? members || g ? members && g.members == [ ];
|
isGroupNonOverwritable = g: false
|
||||||
|
|| ! g ? members
|
||||||
|
|| g ? members && g.members == [ ]
|
||||||
|
|| g ? members && g.members == [ "sp.admins" ];
|
||||||
|
|
||||||
provisionStateJson = pkgs.writeText "provision-state.json" (
|
provisionStateJson = pkgs.writeText "provision-state.json" (
|
||||||
builtins.toJSON {
|
builtins.toJSON {
|
||||||
inherit (cfg.provision) persons systems;
|
inherit (cfg.provision) persons systems;
|
||||||
groups =
|
groups =
|
||||||
lib.attrsets.filterAttrs (_n: v: ! isGroupEmpty v) cfg.provision.groups;
|
lib.attrsets.filterAttrs (_n: v: ! isGroupNonOverwritable v) cfg.provision.groups;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -175,21 +178,27 @@ let
|
|||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
|
|
||||||
emptyGroupsNames =
|
groupsToCreateAndPopulate =
|
||||||
builtins.attrNames
|
lib.attrsets.filterAttrs (_n: isGroupNonOverwritable) cfg.provision.groups;
|
||||||
(lib.attrsets.filterAttrs (_n: isGroupEmpty) cfg.provision.groups);
|
|
||||||
|
|
||||||
createEmptyGroups = ''
|
createGroups = ''
|
||||||
readonly CLIENT_HOME=$RUNTIME_DIRECTORY/client_home
|
for group_name in ${lib.strings.concatStringsSep " " (builtins.attrNames groupsToCreateAndPopulate)}
|
||||||
mkdir -p $CLIENT_HOME
|
|
||||||
HOME=$CLIENT_HOME KANIDM_PASSWORD="$KANIDM_IDM_ADMIN_PASSWORD" ${cfg.package}/bin/kanidm login --name idm_admin --url "${cfg.provision.instanceUrl}" --skip-hostname-verification
|
|
||||||
for group_name in ${lib.strings.concatLines emptyGroupsNames}
|
|
||||||
do
|
do
|
||||||
HOME=$CLIENT_HOME ${cfg.package}/bin/kanidm group create "$group_name" --name idm_admin --url "${cfg.provision.instanceUrl}" --skip-hostname-verification
|
${cfg.package}/bin/kanidm group create "$group_name"
|
||||||
done
|
done
|
||||||
# rm -r $CLIENT_HOME
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
populateGroup = group_name: group: ''
|
||||||
|
for member_name in ${lib.strings.concatStringsSep " " group.members}
|
||||||
|
do
|
||||||
|
${cfg.package}/bin/kanidm group add-members "${group_name}" "$member_name"
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
|
||||||
|
createAndPopulateGroups =
|
||||||
|
lib.concatLines ([ createGroups ]
|
||||||
|
++ (lib.mapAttrsToList populateGroup groupsToCreateAndPopulate));
|
||||||
|
|
||||||
postStartScript = pkgs.writeShellScript "post-start" ''
|
postStartScript = pkgs.writeShellScript "post-start" ''
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
@@ -209,7 +218,19 @@ let
|
|||||||
|
|
||||||
${recoverIdmAdmin}
|
${recoverIdmAdmin}
|
||||||
${maybeRecoverAdmin}
|
${maybeRecoverAdmin}
|
||||||
${createEmptyGroups}
|
|
||||||
|
readonly CLIENT_HOME=$RUNTIME_DIRECTORY/client_home
|
||||||
|
mkdir -p "$CLIENT_HOME"
|
||||||
|
export HOME="$CLIENT_HOME"
|
||||||
|
export KANIDM_NAME=idm_admin
|
||||||
|
export KANIDM_URL="${cfg.provision.instanceUrl}"
|
||||||
|
export KANIDM_SKIP_HOSTNAME_VERIFICATION="true"
|
||||||
|
KANIDM_PASSWORD="$KANIDM_IDM_ADMIN_PASSWORD" ${cfg.package}/bin/kanidm login
|
||||||
|
${createAndPopulateGroups}
|
||||||
|
unset HOME
|
||||||
|
unset KANIDM_NAME
|
||||||
|
unset KANIDM_URL
|
||||||
|
unset KANIDM_SKIP_HOSTNAME_VERIFICATION
|
||||||
|
|
||||||
KANIDM_PROVISION_IDM_ADMIN_TOKEN=$KANIDM_IDM_ADMIN_PASSWORD \
|
KANIDM_PROVISION_IDM_ADMIN_TOKEN=$KANIDM_IDM_ADMIN_PASSWORD \
|
||||||
${getExe pkgs.kanidm-provision} \
|
${getExe pkgs.kanidm-provision} \
|
||||||
@@ -451,9 +472,11 @@ in
|
|||||||
config.members = concatLists (
|
config.members = concatLists (
|
||||||
flip mapAttrsToList cfg.provision.persons (
|
flip mapAttrsToList cfg.provision.persons (
|
||||||
person: personCfg:
|
person: personCfg:
|
||||||
optional (
|
optional
|
||||||
|
(
|
||||||
personCfg.present && builtins.elem groupSubmod.config._module.args.name personCfg.groups
|
personCfg.present && builtins.elem groupSubmod.config._module.args.name personCfg.groups
|
||||||
) person
|
)
|
||||||
|
person
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@@ -646,9 +669,12 @@ in
|
|||||||
++ entityList "oauth2" cfg.provision.systems.oauth2;
|
++ entityList "oauth2" cfg.provision.systems.oauth2;
|
||||||
|
|
||||||
# Accumulate entities by name. Track corresponding entity types for later duplicate check.
|
# Accumulate entities by name. Track corresponding entity types for later duplicate check.
|
||||||
entitiesByName = foldl' (
|
entitiesByName = foldl'
|
||||||
|
(
|
||||||
acc: { type, name }: acc // { ${name} = (acc.${name} or [ ]) ++ [ type ]; }
|
acc: { type, name }: acc // { ${name} = (acc.${name} or [ ]) ++ [ type ]; }
|
||||||
) { } entities;
|
)
|
||||||
|
{ }
|
||||||
|
entities;
|
||||||
|
|
||||||
assertGroupsKnown =
|
assertGroupsKnown =
|
||||||
opt: groups:
|
opt: groups:
|
||||||
|
@@ -67,7 +67,8 @@ in
|
|||||||
};
|
};
|
||||||
provision = {
|
provision = {
|
||||||
enable = true;
|
enable = true;
|
||||||
autoRemove = false;
|
autoRemove = true; # if false, obsolete oauth2 scopeMaps remain
|
||||||
|
groups."sp.admins".present = true;
|
||||||
};
|
};
|
||||||
enableClient = true;
|
enableClient = true;
|
||||||
clientSettings = {
|
clientSettings = {
|
||||||
|
@@ -71,33 +71,34 @@ in
|
|||||||
systemd.slices.roundcube.description = "Roundcube service slice";
|
systemd.slices.roundcube.description = "Roundcube service slice";
|
||||||
|
|
||||||
services.kanidm.provision = lib.mkIf is-auth-enabled {
|
services.kanidm.provision = lib.mkIf is-auth-enabled {
|
||||||
groups.roundcube_users.present = true;
|
groups = {
|
||||||
|
"sp.roundcube.admins".members = [ "sp.admins" ];
|
||||||
|
"sp.roundcube.users".present = true;
|
||||||
|
};
|
||||||
systems.oauth2.roundcube = {
|
systems.oauth2.roundcube = {
|
||||||
displayName = "Roundcube";
|
displayName = "Roundcube";
|
||||||
originUrl = "https://${cfg.subdomain}.${domain}/index.php/login/oauth";
|
originUrl = "https://${cfg.subdomain}.${domain}/index.php/login/oauth";
|
||||||
originLanding = "https://${cfg.subdomain}.${domain}/";
|
originLanding = "https://${cfg.subdomain}.${domain}/";
|
||||||
basicSecretFile = pkgs.writeText "bs-roundcube" "VERYSTRONGSECRETFORROUNDCUBE";
|
basicSecretFile = pkgs.writeText "bs-roundcube" "VERYSTRONGSECRETFORROUNDCUBE"; # FIXME
|
||||||
# when true, name is passed to a service instead of name@domain
|
# when true, name is passed to a service instead of name@domain
|
||||||
preferShortUsername = false;
|
preferShortUsername = false;
|
||||||
allowInsecureClientDisablePkce = true; # FIXME is it needed?
|
allowInsecureClientDisablePkce = true; # FIXME is it needed?
|
||||||
scopeMaps.roundcube_users = [
|
scopeMaps = {
|
||||||
|
"sp.roundcube.users" = [
|
||||||
"email"
|
"email"
|
||||||
"profile"
|
|
||||||
"openid"
|
"openid"
|
||||||
|
"profile"
|
||||||
];
|
];
|
||||||
# scopeMaps."sp.roundcube.users" = [
|
};
|
||||||
# "email"
|
removeOrphanedClaimMaps = true;
|
||||||
# "openid"
|
|
||||||
# "dovecotprofile"
|
|
||||||
# ];
|
|
||||||
|
|
||||||
# add more scopes when a user is a member of specific group
|
# add more scopes when a user is a member of specific group
|
||||||
# claimMaps.groups = {
|
supplementaryScopeMaps."sp.roundcube.admins" = [ "admin" ];
|
||||||
# joinType = "array";
|
claimMaps.groups = {
|
||||||
# valuesByGroup = {
|
joinType = "array";
|
||||||
# "sp.roundcube.admins" = [ "admin" ];
|
valuesByGroup = {
|
||||||
# };
|
"sp.roundcube.admins" = [ "admin" "test" ];
|
||||||
# };
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user