mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-25 16:33:15 +00:00
nixos/kanidm: run nixfmt-rfc-style
This commit is contained in:
parent
391d05ce95
commit
aa6cbcbf09
@ -1,4 +1,10 @@
|
|||||||
{ config, lib, options, pkgs, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
options,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
cfg = config.services.kanidm;
|
cfg = config.services.kanidm;
|
||||||
settingsFormat = pkgs.formats.toml { };
|
settingsFormat = pkgs.formats.toml { };
|
||||||
@ -7,18 +13,29 @@ let
|
|||||||
serverConfigFile = settingsFormat.generate "server.toml" (filterConfig cfg.serverSettings);
|
serverConfigFile = settingsFormat.generate "server.toml" (filterConfig cfg.serverSettings);
|
||||||
clientConfigFile = settingsFormat.generate "kanidm-config.toml" (filterConfig cfg.clientSettings);
|
clientConfigFile = settingsFormat.generate "kanidm-config.toml" (filterConfig cfg.clientSettings);
|
||||||
unixConfigFile = settingsFormat.generate "kanidm-unixd.toml" (filterConfig cfg.unixSettings);
|
unixConfigFile = settingsFormat.generate "kanidm-unixd.toml" (filterConfig cfg.unixSettings);
|
||||||
certPaths = builtins.map builtins.dirOf [ cfg.serverSettings.tls_chain cfg.serverSettings.tls_key ];
|
certPaths = builtins.map builtins.dirOf [
|
||||||
|
cfg.serverSettings.tls_chain
|
||||||
|
cfg.serverSettings.tls_key
|
||||||
|
];
|
||||||
|
|
||||||
# Merge bind mount paths and remove paths where a prefix is already mounted.
|
# Merge bind mount paths and remove paths where a prefix is already mounted.
|
||||||
# This makes sure that if e.g. the tls_chain is in the nix store and /nix/store is already in the mount
|
# This makes sure that if e.g. the tls_chain is in the nix store and /nix/store is already in the mount
|
||||||
# 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 = list: newPath: lib.any (path: lib.hasPrefix (builtins.toString path) (builtins.toString newPath)) list;
|
hasPrefixInList =
|
||||||
mergePaths = lib.foldl' (merged: newPath: let
|
list: newPath:
|
||||||
|
lib.any (path: lib.hasPrefix (builtins.toString path) (builtins.toString newPath)) list;
|
||||||
|
mergePaths = lib.foldl' (
|
||||||
|
merged: newPath:
|
||||||
|
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
|
||||||
filteredPaths = lib.filter (p: !lib.hasPrefix (builtins.toString newPath) (builtins.toString p)) merged;
|
filteredPaths = lib.filter (
|
||||||
|
p: !lib.hasPrefix (builtins.toString newPath) (builtins.toString p)
|
||||||
|
) merged;
|
||||||
# If a prefix of the new path is already in the list, do not add it
|
# If a prefix of the new path is already in the list, do not add it
|
||||||
filteredNew = lib.optional (!hasPrefixInList filteredPaths newPath) newPath;
|
filteredNew = lib.optional (!hasPrefixInList filteredPaths newPath) newPath;
|
||||||
in filteredPaths ++ filteredNew) [];
|
in
|
||||||
|
filteredPaths ++ filteredNew
|
||||||
|
) [ ];
|
||||||
|
|
||||||
defaultServiceConfig = {
|
defaultServiceConfig = {
|
||||||
BindReadOnlyPaths = [
|
BindReadOnlyPaths = [
|
||||||
@ -28,7 +45,7 @@ let
|
|||||||
"-/etc/hosts"
|
"-/etc/hosts"
|
||||||
"-/etc/localtime"
|
"-/etc/localtime"
|
||||||
];
|
];
|
||||||
CapabilityBoundingSet = [];
|
CapabilityBoundingSet = [ ];
|
||||||
# ProtectClock= adds DeviceAllow=char-rtc r
|
# ProtectClock= adds DeviceAllow=char-rtc r
|
||||||
DeviceAllow = "";
|
DeviceAllow = "";
|
||||||
# Implies ProtectSystem=strict, which re-mounts all paths
|
# Implies ProtectSystem=strict, which re-mounts all paths
|
||||||
@ -57,12 +74,16 @@ let
|
|||||||
RestrictRealtime = true;
|
RestrictRealtime = true;
|
||||||
RestrictSUIDSGID = true;
|
RestrictSUIDSGID = true;
|
||||||
SystemCallArchitectures = "native";
|
SystemCallArchitectures = "native";
|
||||||
SystemCallFilter = [ "@system-service" "~@privileged @resources @setuid @keyring" ];
|
SystemCallFilter = [
|
||||||
|
"@system-service"
|
||||||
|
"~@privileged @resources @setuid @keyring"
|
||||||
|
];
|
||||||
# Does not work well with the temporary root
|
# Does not work well with the temporary root
|
||||||
#UMask = "0066";
|
#UMask = "0066";
|
||||||
};
|
};
|
||||||
|
|
||||||
mkPresentOption = what:
|
mkPresentOption =
|
||||||
|
what:
|
||||||
lib.mkOption {
|
lib.mkOption {
|
||||||
description = "Whether to ensure that this ${what} is present or absent.";
|
description = "Whether to ensure that this ${what} is present or absent.";
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
@ -71,9 +92,9 @@ let
|
|||||||
|
|
||||||
filterPresent = lib.filterAttrs (_: v: v.present);
|
filterPresent = lib.filterAttrs (_: v: v.present);
|
||||||
|
|
||||||
provisionStateJson = pkgs.writeText "provision-state.json" (builtins.toJSON {
|
provisionStateJson = pkgs.writeText "provision-state.json" (
|
||||||
inherit (cfg.provision) groups persons systems;
|
builtins.toJSON { inherit (cfg.provision) groups persons systems; }
|
||||||
});
|
);
|
||||||
|
|
||||||
# Only recover the admin account if a password should explicitly be provisioned
|
# Only recover the admin account if a password should explicitly be provisioned
|
||||||
# for the account. Otherwise it is not needed for provisioning.
|
# for the account. Otherwise it is not needed for provisioning.
|
||||||
@ -89,28 +110,30 @@ let
|
|||||||
# Recover the idm_admin account. If a password should explicitly be provisioned
|
# Recover the idm_admin account. If a password should explicitly be provisioned
|
||||||
# for the account we set it, otherwise we generate a new one because it is required
|
# for the account we set it, otherwise we generate a new one because it is required
|
||||||
# for provisioning.
|
# for provisioning.
|
||||||
recoverIdmAdmin = if cfg.provision.idmAdminPasswordFile != null
|
recoverIdmAdmin =
|
||||||
then ''
|
if cfg.provision.idmAdminPasswordFile != null then
|
||||||
KANIDM_IDM_ADMIN_PASSWORD=$(< ${cfg.provision.idmAdminPasswordFile})
|
''
|
||||||
# We always reset the idm_admin account password if a desired password was specified.
|
KANIDM_IDM_ADMIN_PASSWORD=$(< ${cfg.provision.idmAdminPasswordFile})
|
||||||
if ! KANIDM_RECOVER_ACCOUNT_PASSWORD=$KANIDM_IDM_ADMIN_PASSWORD ${cfg.package}/bin/kanidmd recover-account -c ${serverConfigFile} idm_admin --from-environment >/dev/null; then
|
# We always reset the idm_admin account password if a desired password was specified.
|
||||||
echo "Failed to recover idm_admin account" >&2
|
if ! KANIDM_RECOVER_ACCOUNT_PASSWORD=$KANIDM_IDM_ADMIN_PASSWORD ${cfg.package}/bin/kanidmd recover-account -c ${serverConfigFile} idm_admin --from-environment >/dev/null; then
|
||||||
exit 1
|
echo "Failed to recover idm_admin account" >&2
|
||||||
fi
|
exit 1
|
||||||
''
|
fi
|
||||||
else ''
|
''
|
||||||
# Recover idm_admin account
|
else
|
||||||
if ! recover_out=$(${cfg.package}/bin/kanidmd recover-account -c ${serverConfigFile} idm_admin -o json); then
|
''
|
||||||
echo "$recover_out" >&2
|
# Recover idm_admin account
|
||||||
echo "kanidm provision: Failed to recover admin account" >&2
|
if ! recover_out=$(${cfg.package}/bin/kanidmd recover-account -c ${serverConfigFile} idm_admin -o json); then
|
||||||
exit 1
|
echo "$recover_out" >&2
|
||||||
fi
|
echo "kanidm provision: Failed to recover admin account" >&2
|
||||||
if ! KANIDM_IDM_ADMIN_PASSWORD=$(grep '{"password' <<< "$recover_out" | ${lib.getExe pkgs.jq} -r .password); then
|
exit 1
|
||||||
echo "$recover_out" >&2
|
fi
|
||||||
echo "kanidm provision: Failed to parse password for idm_admin account" >&2
|
if ! KANIDM_IDM_ADMIN_PASSWORD=$(grep '{"password' <<< "$recover_out" | ${lib.getExe pkgs.jq} -r .password); then
|
||||||
exit 1
|
echo "$recover_out" >&2
|
||||||
fi
|
echo "kanidm provision: Failed to parse password for idm_admin account" >&2
|
||||||
'';
|
exit 1
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
postStartScript = pkgs.writeShellScript "post-start" ''
|
postStartScript = pkgs.writeShellScript "post-start" ''
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
@ -142,14 +165,15 @@ let
|
|||||||
|
|
||||||
serverPort =
|
serverPort =
|
||||||
# ipv6:
|
# ipv6:
|
||||||
if lib.hasInfix "]:" cfg.serverSettings.bindaddress
|
if lib.hasInfix "]:" cfg.serverSettings.bindaddress then
|
||||||
then lib.last (lib.splitString "]:" cfg.serverSettings.bindaddress)
|
lib.last (lib.splitString "]:" cfg.serverSettings.bindaddress)
|
||||||
else
|
else
|
||||||
# ipv4:
|
# ipv4:
|
||||||
if lib.hasInfix "." cfg.serverSettings.bindaddress
|
if lib.hasInfix "." cfg.serverSettings.bindaddress then
|
||||||
then lib.last (lib.splitString ":" cfg.serverSettings.bindaddress)
|
lib.last (lib.splitString ":" cfg.serverSettings.bindaddress)
|
||||||
# default is 8443
|
# default is 8443
|
||||||
else "8443";
|
else
|
||||||
|
"8443";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.kanidm = {
|
options.services.kanidm = {
|
||||||
@ -157,7 +181,7 @@ in
|
|||||||
enableServer = lib.mkEnableOption "the Kanidm server";
|
enableServer = lib.mkEnableOption "the Kanidm server";
|
||||||
enablePam = lib.mkEnableOption "the Kanidm PAM and NSS integration";
|
enablePam = lib.mkEnableOption "the Kanidm PAM and NSS integration";
|
||||||
|
|
||||||
package = lib.mkPackageOption pkgs "kanidm" {};
|
package = lib.mkPackageOption pkgs "kanidm" { };
|
||||||
|
|
||||||
serverSettings = lib.mkOption {
|
serverSettings = lib.mkOption {
|
||||||
type = lib.types.submodule {
|
type = lib.types.submodule {
|
||||||
@ -213,12 +237,20 @@ in
|
|||||||
log_level = lib.mkOption {
|
log_level = lib.mkOption {
|
||||||
description = "Log level of the server.";
|
description = "Log level of the server.";
|
||||||
default = "info";
|
default = "info";
|
||||||
type = lib.types.enum [ "info" "debug" "trace" ];
|
type = lib.types.enum [
|
||||||
|
"info"
|
||||||
|
"debug"
|
||||||
|
"trace"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
role = lib.mkOption {
|
role = lib.mkOption {
|
||||||
description = "The role of this server. This affects the replication relationship and thereby available features.";
|
description = "The role of this server. This affects the replication relationship and thereby available features.";
|
||||||
default = "WriteReplica";
|
default = "WriteReplica";
|
||||||
type = lib.types.enum [ "WriteReplica" "WriteReplicaNoUI" "ReadOnlyReplica" ];
|
type = lib.types.enum [
|
||||||
|
"WriteReplica"
|
||||||
|
"WriteReplicaNoUI"
|
||||||
|
"ReadOnlyReplica"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
online_backup = {
|
online_backup = {
|
||||||
path = lib.mkOption {
|
path = lib.mkOption {
|
||||||
@ -347,221 +379,248 @@ in
|
|||||||
|
|
||||||
groups = lib.mkOption {
|
groups = lib.mkOption {
|
||||||
description = "Provisioning of kanidm groups";
|
description = "Provisioning of kanidm groups";
|
||||||
default = {};
|
default = { };
|
||||||
type = lib.types.attrsOf (lib.types.submodule (groupSubmod: {
|
type = lib.types.attrsOf (
|
||||||
options = {
|
lib.types.submodule (groupSubmod: {
|
||||||
present = mkPresentOption "group";
|
options = {
|
||||||
|
present = mkPresentOption "group";
|
||||||
|
|
||||||
members = lib.mkOption {
|
members = lib.mkOption {
|
||||||
description = "List of kanidm entities (persons, groups, ...) which are part of this group.";
|
description = "List of kanidm entities (persons, groups, ...) which are part of this group.";
|
||||||
type = lib.types.listOf lib.types.str;
|
type = lib.types.listOf lib.types.str;
|
||||||
apply = lib.unique;
|
apply = lib.unique;
|
||||||
default = [];
|
default = [ ];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
config.members = lib.concatLists (
|
||||||
config.members = lib.concatLists (lib.flip lib.mapAttrsToList cfg.provision.persons (person: personCfg:
|
lib.flip lib.mapAttrsToList cfg.provision.persons (
|
||||||
lib.optional (personCfg.present && builtins.elem groupSubmod.config._module.args.name personCfg.groups) person
|
person: personCfg:
|
||||||
));
|
lib.optional (
|
||||||
}));
|
personCfg.present && builtins.elem groupSubmod.config._module.args.name personCfg.groups
|
||||||
|
) person
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
persons = lib.mkOption {
|
persons = lib.mkOption {
|
||||||
description = "Provisioning of kanidm persons";
|
description = "Provisioning of kanidm persons";
|
||||||
default = {};
|
default = { };
|
||||||
type = lib.types.attrsOf (lib.types.submodule {
|
type = lib.types.attrsOf (
|
||||||
options = {
|
lib.types.submodule {
|
||||||
present = mkPresentOption "person";
|
options = {
|
||||||
|
present = mkPresentOption "person";
|
||||||
|
|
||||||
displayName = lib.mkOption {
|
displayName = lib.mkOption {
|
||||||
description = "Display name";
|
description = "Display name";
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
example = "My User";
|
example = "My User";
|
||||||
};
|
};
|
||||||
|
|
||||||
legalName = lib.mkOption {
|
legalName = lib.mkOption {
|
||||||
description = "Full legal name";
|
description = "Full legal name";
|
||||||
type = lib.types.nullOr lib.types.str;
|
type = lib.types.nullOr lib.types.str;
|
||||||
example = "Jane Doe";
|
example = "Jane Doe";
|
||||||
default = null;
|
default = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
mailAddresses = lib.mkOption {
|
mailAddresses = lib.mkOption {
|
||||||
description = "Mail addresses. First given address is considered the primary address.";
|
description = "Mail addresses. First given address is considered the primary address.";
|
||||||
type = lib.types.listOf lib.types.str;
|
type = lib.types.listOf lib.types.str;
|
||||||
example = ["jane.doe@example.com"];
|
example = [ "jane.doe@example.com" ];
|
||||||
default = [];
|
default = [ ];
|
||||||
};
|
};
|
||||||
|
|
||||||
groups = lib.mkOption {
|
groups = lib.mkOption {
|
||||||
description = "List of groups this person should belong to.";
|
description = "List of groups this person should belong to.";
|
||||||
type = lib.types.listOf lib.types.str;
|
type = lib.types.listOf lib.types.str;
|
||||||
apply = lib.unique;
|
apply = lib.unique;
|
||||||
default = [];
|
default = [ ];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
});
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
systems.oauth2 = lib.mkOption {
|
systems.oauth2 = lib.mkOption {
|
||||||
description = "Provisioning of oauth2 resource servers";
|
description = "Provisioning of oauth2 resource servers";
|
||||||
default = {};
|
default = { };
|
||||||
type = lib.types.attrsOf (lib.types.submodule {
|
type = lib.types.attrsOf (
|
||||||
options = {
|
lib.types.submodule {
|
||||||
present = mkPresentOption "oauth2 resource server";
|
options = {
|
||||||
|
present = mkPresentOption "oauth2 resource server";
|
||||||
|
|
||||||
public = lib.mkOption {
|
public = lib.mkOption {
|
||||||
description = "Whether this is a public client (enforces PKCE, doesn't use a basic secret)";
|
description = "Whether this is a public client (enforces PKCE, doesn't use a basic secret)";
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
displayName = lib.mkOption {
|
||||||
|
description = "Display name";
|
||||||
|
type = lib.types.str;
|
||||||
|
example = "Some Service";
|
||||||
|
};
|
||||||
|
|
||||||
|
originUrl = lib.mkOption {
|
||||||
|
description = "The origin URL of the service. OAuth2 redirects will only be allowed to sites under this origin. Must end with a slash.";
|
||||||
|
type =
|
||||||
|
let
|
||||||
|
originStrType = lib.types.strMatching ".*://.*/$";
|
||||||
|
in
|
||||||
|
lib.types.either originStrType (lib.types.nonEmptyListOf originStrType);
|
||||||
|
example = "https://someservice.example.com/";
|
||||||
|
};
|
||||||
|
|
||||||
|
originLanding = lib.mkOption {
|
||||||
|
description = "When redirecting from the Kanidm Apps Listing page, some linked applications may need to land on a specific page to trigger oauth2/oidc interactions.";
|
||||||
|
type = lib.types.str;
|
||||||
|
example = "https://someservice.example.com/home";
|
||||||
|
};
|
||||||
|
|
||||||
|
basicSecretFile = lib.mkOption {
|
||||||
|
description = ''
|
||||||
|
The basic secret to use for this service. If null, the random secret generated
|
||||||
|
by kanidm will not be touched. Do NOT use a path from the nix store here!
|
||||||
|
'';
|
||||||
|
type = lib.types.nullOr lib.types.path;
|
||||||
|
example = "/run/secrets/some-oauth2-basic-secret";
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
enableLocalhostRedirects = lib.mkOption {
|
||||||
|
description = "Allow localhost redirects. Only for public clients.";
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
enableLegacyCrypto = lib.mkOption {
|
||||||
|
description = "Enable legacy crypto on this client. Allows JWT signing algorthms like RS256.";
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
allowInsecureClientDisablePkce = lib.mkOption {
|
||||||
|
description = ''
|
||||||
|
Disable PKCE on this oauth2 resource server to work around insecure clients
|
||||||
|
that may not support it. You should request the client to enable PKCE!
|
||||||
|
Only for non-public clients.
|
||||||
|
'';
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
preferShortUsername = lib.mkOption {
|
||||||
|
description = "Use 'name' instead of 'spn' in the preferred_username claim";
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
scopeMaps = lib.mkOption {
|
||||||
|
description = ''
|
||||||
|
Maps kanidm groups to returned oauth scopes.
|
||||||
|
See [Scope Relations](https://kanidm.github.io/kanidm/stable/integrations/oauth2.html#scope-relationships) for more information.
|
||||||
|
'';
|
||||||
|
type = lib.types.attrsOf (lib.types.listOf lib.types.str);
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
supplementaryScopeMaps = lib.mkOption {
|
||||||
|
description = ''
|
||||||
|
Maps kanidm groups to additionally returned oauth scopes.
|
||||||
|
See [Scope Relations](https://kanidm.github.io/kanidm/stable/integrations/oauth2.html#scope-relationships) for more information.
|
||||||
|
'';
|
||||||
|
type = lib.types.attrsOf (lib.types.listOf lib.types.str);
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
removeOrphanedClaimMaps = lib.mkOption {
|
||||||
|
description = "Whether claim maps not specified here but present in kanidm should be removed from kanidm.";
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
claimMaps = lib.mkOption {
|
||||||
|
description = ''
|
||||||
|
Adds additional claims (and values) based on which kanidm groups an authenticating party belongs to.
|
||||||
|
See [Claim Maps](https://kanidm.github.io/kanidm/master/integrations/oauth2.html#custom-claim-maps) for more information.
|
||||||
|
'';
|
||||||
|
default = { };
|
||||||
|
type = lib.types.attrsOf (
|
||||||
|
lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
joinType = lib.mkOption {
|
||||||
|
description = ''
|
||||||
|
Determines how multiple values are joined to create the claim value.
|
||||||
|
See [Claim Maps](https://kanidm.github.io/kanidm/master/integrations/oauth2.html#custom-claim-maps) for more information.
|
||||||
|
'';
|
||||||
|
type = lib.types.enum [
|
||||||
|
"array"
|
||||||
|
"csv"
|
||||||
|
"ssv"
|
||||||
|
];
|
||||||
|
default = "array";
|
||||||
|
};
|
||||||
|
|
||||||
|
valuesByGroup = lib.mkOption {
|
||||||
|
description = "Maps kanidm groups to values for the claim.";
|
||||||
|
default = { };
|
||||||
|
type = lib.types.attrsOf (lib.types.listOf lib.types.str);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
}
|
||||||
displayName = lib.mkOption {
|
);
|
||||||
description = "Display name";
|
|
||||||
type = lib.types.str;
|
|
||||||
example = "Some Service";
|
|
||||||
};
|
|
||||||
|
|
||||||
originUrl = lib.mkOption {
|
|
||||||
description = "The origin URL of the service. OAuth2 redirects will only be allowed to sites under this origin. Must end with a slash.";
|
|
||||||
type = let
|
|
||||||
originStrType = lib.types.strMatching ".*://.*/$";
|
|
||||||
in
|
|
||||||
lib.types.either originStrType (lib.types.nonEmptyListOf originStrType);
|
|
||||||
example = "https://someservice.example.com/";
|
|
||||||
};
|
|
||||||
|
|
||||||
originLanding = lib.mkOption {
|
|
||||||
description = "When redirecting from the Kanidm Apps Listing page, some linked applications may need to land on a specific page to trigger oauth2/oidc interactions.";
|
|
||||||
type = lib.types.str;
|
|
||||||
example = "https://someservice.example.com/home";
|
|
||||||
};
|
|
||||||
|
|
||||||
basicSecretFile = lib.mkOption {
|
|
||||||
description = ''
|
|
||||||
The basic secret to use for this service. If null, the random secret generated
|
|
||||||
by kanidm will not be touched. Do NOT use a path from the nix store here!
|
|
||||||
'';
|
|
||||||
type = lib.types.nullOr lib.types.path;
|
|
||||||
example = "/run/secrets/some-oauth2-basic-secret";
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
enableLocalhostRedirects = lib.mkOption {
|
|
||||||
description = "Allow localhost redirects. Only for public clients.";
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
enableLegacyCrypto = lib.mkOption {
|
|
||||||
description = "Enable legacy crypto on this client. Allows JWT signing algorthms like RS256.";
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
allowInsecureClientDisablePkce = lib.mkOption {
|
|
||||||
description = ''
|
|
||||||
Disable PKCE on this oauth2 resource server to work around insecure clients
|
|
||||||
that may not support it. You should request the client to enable PKCE!
|
|
||||||
Only for non-public clients.
|
|
||||||
'';
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
preferShortUsername = lib.mkOption {
|
|
||||||
description = "Use 'name' instead of 'spn' in the preferred_username claim";
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
scopeMaps = lib.mkOption {
|
|
||||||
description = ''
|
|
||||||
Maps kanidm groups to returned oauth scopes.
|
|
||||||
See [Scope Relations](https://kanidm.github.io/kanidm/stable/integrations/oauth2.html#scope-relationships) for more information.
|
|
||||||
'';
|
|
||||||
type = lib.types.attrsOf (lib.types.listOf lib.types.str);
|
|
||||||
default = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
supplementaryScopeMaps = lib.mkOption {
|
|
||||||
description = ''
|
|
||||||
Maps kanidm groups to additionally returned oauth scopes.
|
|
||||||
See [Scope Relations](https://kanidm.github.io/kanidm/stable/integrations/oauth2.html#scope-relationships) for more information.
|
|
||||||
'';
|
|
||||||
type = lib.types.attrsOf (lib.types.listOf lib.types.str);
|
|
||||||
default = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
removeOrphanedClaimMaps = lib.mkOption {
|
|
||||||
description = "Whether claim maps not specified here but present in kanidm should be removed from kanidm.";
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
claimMaps = lib.mkOption {
|
|
||||||
description = ''
|
|
||||||
Adds additional claims (and values) based on which kanidm groups an authenticating party belongs to.
|
|
||||||
See [Claim Maps](https://kanidm.github.io/kanidm/master/integrations/oauth2.html#custom-claim-maps) for more information.
|
|
||||||
'';
|
|
||||||
default = {};
|
|
||||||
type = lib.types.attrsOf (lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
joinType = lib.mkOption {
|
|
||||||
description = ''
|
|
||||||
Determines how multiple values are joined to create the claim value.
|
|
||||||
See [Claim Maps](https://kanidm.github.io/kanidm/master/integrations/oauth2.html#custom-claim-maps) for more information.
|
|
||||||
'';
|
|
||||||
type = lib.types.enum ["array" "csv" "ssv"];
|
|
||||||
default = "array";
|
|
||||||
};
|
|
||||||
|
|
||||||
valuesByGroup = lib.mkOption {
|
|
||||||
description = "Maps kanidm groups to values for the claim.";
|
|
||||||
default = {};
|
|
||||||
type = lib.types.attrsOf (lib.types.listOf lib.types.str);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf (cfg.enableClient || cfg.enableServer || cfg.enablePam) {
|
config = lib.mkIf (cfg.enableClient || cfg.enableServer || cfg.enablePam) {
|
||||||
assertions = let
|
assertions =
|
||||||
entityList = type: attrs: lib.flip lib.mapAttrsToList (filterPresent attrs) (name: _: { inherit type name; });
|
let
|
||||||
entities =
|
entityList =
|
||||||
entityList "group" cfg.provision.groups
|
type: attrs: lib.flip lib.mapAttrsToList (filterPresent attrs) (name: _: { inherit type name; });
|
||||||
++ entityList "person" cfg.provision.persons
|
entities =
|
||||||
++ entityList "oauth2" cfg.provision.systems.oauth2;
|
entityList "group" cfg.provision.groups
|
||||||
|
++ entityList "person" cfg.provision.persons
|
||||||
|
++ 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 = lib.foldl' (acc: { type, name }:
|
entitiesByName = lib.foldl' (
|
||||||
acc // {
|
acc: { type, name }: acc // { ${name} = (acc.${name} or [ ]) ++ [ type ]; }
|
||||||
${name} = (acc.${name} or []) ++ [type];
|
) { } entities;
|
||||||
}
|
|
||||||
) {} entities;
|
|
||||||
|
|
||||||
assertGroupsKnown = opt: groups: let
|
assertGroupsKnown =
|
||||||
knownGroups = lib.attrNames (filterPresent cfg.provision.groups);
|
opt: groups:
|
||||||
unknownGroups = lib.subtractLists knownGroups groups;
|
let
|
||||||
in {
|
knownGroups = lib.attrNames (filterPresent cfg.provision.groups);
|
||||||
assertion = (cfg.enableServer && cfg.provision.enable) -> unknownGroups == [];
|
unknownGroups = lib.subtractLists knownGroups groups;
|
||||||
message = "${opt} refers to unknown groups: ${toString unknownGroups}";
|
in
|
||||||
};
|
{
|
||||||
|
assertion = (cfg.enableServer && cfg.provision.enable) -> unknownGroups == [ ];
|
||||||
|
message = "${opt} refers to unknown groups: ${toString unknownGroups}";
|
||||||
|
};
|
||||||
|
|
||||||
assertEntitiesKnown = opt: entities: let
|
assertEntitiesKnown =
|
||||||
unknownEntities = lib.subtractLists (lib.attrNames entitiesByName) entities;
|
opt: entities:
|
||||||
in {
|
let
|
||||||
assertion = (cfg.enableServer && cfg.provision.enable) -> unknownEntities == [];
|
unknownEntities = lib.subtractLists (lib.attrNames entitiesByName) entities;
|
||||||
message = "${opt} refers to unknown entities: ${toString unknownEntities}";
|
in
|
||||||
};
|
{
|
||||||
in
|
assertion = (cfg.enableServer && cfg.provision.enable) -> unknownEntities == [ ];
|
||||||
|
message = "${opt} refers to unknown entities: ${toString unknownEntities}";
|
||||||
|
};
|
||||||
|
in
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
assertion = !cfg.enableServer || ((cfg.serverSettings.tls_chain or null) == null) || (!lib.isStorePath cfg.serverSettings.tls_chain);
|
assertion =
|
||||||
|
!cfg.enableServer
|
||||||
|
|| ((cfg.serverSettings.tls_chain or null) == null)
|
||||||
|
|| (!lib.isStorePath cfg.serverSettings.tls_chain);
|
||||||
message = ''
|
message = ''
|
||||||
<option>services.kanidm.serverSettings.tls_chain</option> points to
|
<option>services.kanidm.serverSettings.tls_chain</option> points to
|
||||||
a file in the Nix store. You should use a quoted absolute path to
|
a file in the Nix store. You should use a quoted absolute path to
|
||||||
@ -569,7 +628,10 @@ in
|
|||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
assertion = !cfg.enableServer || ((cfg.serverSettings.tls_key or null) == null) || (!lib.isStorePath cfg.serverSettings.tls_key);
|
assertion =
|
||||||
|
!cfg.enableServer
|
||||||
|
|| ((cfg.serverSettings.tls_key or null) == null)
|
||||||
|
|| (!lib.isStorePath cfg.serverSettings.tls_key);
|
||||||
message = ''
|
message = ''
|
||||||
<option>services.kanidm.serverSettings.tls_key</option> points to
|
<option>services.kanidm.serverSettings.tls_key</option> points to
|
||||||
a file in the Nix store. You should use a quoted absolute path to
|
a file in the Nix store. You should use a quoted absolute path to
|
||||||
@ -591,8 +653,12 @@ in
|
|||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
assertion = !cfg.enableServer || (cfg.serverSettings.domain == null
|
assertion =
|
||||||
-> cfg.serverSettings.role == "WriteReplica" || cfg.serverSettings.role == "WriteReplicaNoUI");
|
!cfg.enableServer
|
||||||
|
|| (
|
||||||
|
cfg.serverSettings.domain == null
|
||||||
|
-> cfg.serverSettings.role == "WriteReplica" || cfg.serverSettings.role == "WriteReplicaNoUI"
|
||||||
|
);
|
||||||
message = ''
|
message = ''
|
||||||
<option>services.kanidm.serverSettings.domain</option> can only be set if this instance
|
<option>services.kanidm.serverSettings.domain</option> can only be set if this instance
|
||||||
is not a ReadOnlyReplica. Otherwise the db would inherit it from
|
is not a ReadOnlyReplica. Otherwise the db would inherit it from
|
||||||
@ -605,63 +671,96 @@ in
|
|||||||
}
|
}
|
||||||
# If any secret is provisioned, the kanidm package must have some required patches applied to it
|
# If any secret is provisioned, the kanidm package must have some required patches applied to it
|
||||||
{
|
{
|
||||||
assertion = (cfg.provision.enable &&
|
assertion =
|
||||||
(cfg.provision.adminPasswordFile != null
|
(
|
||||||
|| cfg.provision.idmAdminPasswordFile != null
|
cfg.provision.enable
|
||||||
|| lib.any (x: x.basicSecretFile != null) (lib.attrValues (filterPresent cfg.provision.systems.oauth2))
|
&& (
|
||||||
)) -> cfg.package.enableSecretProvisioning;
|
cfg.provision.adminPasswordFile != null
|
||||||
|
|| cfg.provision.idmAdminPasswordFile != null
|
||||||
|
|| lib.any (x: x.basicSecretFile != null) (
|
||||||
|
lib.attrValues (filterPresent cfg.provision.systems.oauth2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
-> cfg.package.enableSecretProvisioning;
|
||||||
message = ''
|
message = ''
|
||||||
Specifying an admin account password or oauth2 basicSecretFile requires kanidm to be built with the secret provisioning patches.
|
Specifying an admin account password or oauth2 basicSecretFile requires kanidm to be built with the secret provisioning patches.
|
||||||
You may want to set `services.kanidm.package = pkgs.kanidm.withSecretProvisioning;`.
|
You may want to set `services.kanidm.package = pkgs.kanidm.withSecretProvisioning;`.
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
# Entity names must be globally unique:
|
# Entity names must be globally unique:
|
||||||
(let
|
(
|
||||||
# Filter all names that occurred in more than one entity type.
|
let
|
||||||
duplicateNames = lib.filterAttrs (_: v: builtins.length v > 1) entitiesByName;
|
# Filter all names that occurred in more than one entity type.
|
||||||
in {
|
duplicateNames = lib.filterAttrs (_: v: builtins.length v > 1) entitiesByName;
|
||||||
assertion = cfg.provision.enable -> duplicateNames == {};
|
in
|
||||||
message = ''
|
{
|
||||||
services.kanidm.provision requires all entity names (group, person, oauth2, ...) to be unique!
|
assertion = cfg.provision.enable -> duplicateNames == { };
|
||||||
${lib.concatLines (lib.mapAttrsToList (name: xs: " - '${name}' used as: ${toString xs}") duplicateNames)}'';
|
message = ''
|
||||||
})
|
services.kanidm.provision requires all entity names (group, person, oauth2, ...) to be unique!
|
||||||
|
${lib.concatLines (
|
||||||
|
lib.mapAttrsToList (name: xs: " - '${name}' used as: ${toString xs}") duplicateNames
|
||||||
|
)}'';
|
||||||
|
}
|
||||||
|
)
|
||||||
]
|
]
|
||||||
++ lib.flip lib.mapAttrsToList (filterPresent cfg.provision.persons) (person: personCfg:
|
++ lib.flip lib.mapAttrsToList (filterPresent cfg.provision.persons) (
|
||||||
|
person: personCfg:
|
||||||
assertGroupsKnown "services.kanidm.provision.persons.${person}.groups" personCfg.groups
|
assertGroupsKnown "services.kanidm.provision.persons.${person}.groups" personCfg.groups
|
||||||
)
|
)
|
||||||
++ lib.flip lib.mapAttrsToList (filterPresent cfg.provision.groups) (group: groupCfg:
|
++ lib.flip lib.mapAttrsToList (filterPresent cfg.provision.groups) (
|
||||||
|
group: groupCfg:
|
||||||
assertEntitiesKnown "services.kanidm.provision.groups.${group}.members" groupCfg.members
|
assertEntitiesKnown "services.kanidm.provision.groups.${group}.members" groupCfg.members
|
||||||
)
|
)
|
||||||
++ lib.concatLists (lib.flip lib.mapAttrsToList (filterPresent cfg.provision.systems.oauth2) (
|
++ lib.concatLists (
|
||||||
oauth2: oauth2Cfg:
|
lib.flip lib.mapAttrsToList (filterPresent cfg.provision.systems.oauth2) (
|
||||||
|
oauth2: oauth2Cfg:
|
||||||
[
|
[
|
||||||
(assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.scopeMaps" (lib.attrNames oauth2Cfg.scopeMaps))
|
(assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.scopeMaps" (
|
||||||
(assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.supplementaryScopeMaps" (lib.attrNames oauth2Cfg.supplementaryScopeMaps))
|
lib.attrNames oauth2Cfg.scopeMaps
|
||||||
|
))
|
||||||
|
(assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.supplementaryScopeMaps" (
|
||||||
|
lib.attrNames oauth2Cfg.supplementaryScopeMaps
|
||||||
|
))
|
||||||
]
|
]
|
||||||
++ lib.concatLists (lib.flip lib.mapAttrsToList oauth2Cfg.claimMaps (claim: claimCfg: [
|
++ lib.concatLists (
|
||||||
(assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.claimMaps.${claim}.valuesByGroup" (lib.attrNames claimCfg.valuesByGroup))
|
lib.flip lib.mapAttrsToList oauth2Cfg.claimMaps (
|
||||||
# At least one group must map to a value in each claim map
|
claim: claimCfg: [
|
||||||
{
|
(assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.claimMaps.${claim}.valuesByGroup" (
|
||||||
assertion = (cfg.provision.enable && cfg.enableServer) -> lib.any (xs: xs != []) (lib.attrValues claimCfg.valuesByGroup);
|
lib.attrNames claimCfg.valuesByGroup
|
||||||
message = "services.kanidm.provision.systems.oauth2.${oauth2}.claimMaps.${claim} does not specify any values for any group";
|
))
|
||||||
}
|
# At least one group must map to a value in each claim map
|
||||||
# Public clients cannot define a basic secret
|
{
|
||||||
{
|
assertion =
|
||||||
assertion = (cfg.provision.enable && cfg.enableServer && oauth2Cfg.public) -> oauth2Cfg.basicSecretFile == null;
|
(cfg.provision.enable && cfg.enableServer)
|
||||||
message = "services.kanidm.provision.systems.oauth2.${oauth2} is a public client and thus cannot specify a basic secret";
|
-> lib.any (xs: xs != [ ]) (lib.attrValues claimCfg.valuesByGroup);
|
||||||
}
|
message = "services.kanidm.provision.systems.oauth2.${oauth2}.claimMaps.${claim} does not specify any values for any group";
|
||||||
# Public clients cannot disable PKCE
|
}
|
||||||
{
|
# Public clients cannot define a basic secret
|
||||||
assertion = (cfg.provision.enable && cfg.enableServer && oauth2Cfg.public) -> !oauth2Cfg.allowInsecureClientDisablePkce;
|
{
|
||||||
message = "services.kanidm.provision.systems.oauth2.${oauth2} is a public client and thus cannot disable PKCE";
|
assertion =
|
||||||
}
|
(cfg.provision.enable && cfg.enableServer && oauth2Cfg.public) -> oauth2Cfg.basicSecretFile == null;
|
||||||
# Non-public clients cannot enable localhost redirects
|
message = "services.kanidm.provision.systems.oauth2.${oauth2} is a public client and thus cannot specify a basic secret";
|
||||||
{
|
}
|
||||||
assertion = (cfg.provision.enable && cfg.enableServer && !oauth2Cfg.public) -> !oauth2Cfg.enableLocalhostRedirects;
|
# Public clients cannot disable PKCE
|
||||||
message = "services.kanidm.provision.systems.oauth2.${oauth2} is a non-public client and thus cannot enable localhost redirects";
|
{
|
||||||
}
|
assertion =
|
||||||
]))
|
(cfg.provision.enable && cfg.enableServer && oauth2Cfg.public)
|
||||||
));
|
-> !oauth2Cfg.allowInsecureClientDisablePkce;
|
||||||
|
message = "services.kanidm.provision.systems.oauth2.${oauth2} is a public client and thus cannot disable PKCE";
|
||||||
|
}
|
||||||
|
# Non-public clients cannot enable localhost redirects
|
||||||
|
{
|
||||||
|
assertion =
|
||||||
|
(cfg.provision.enable && cfg.enableServer && !oauth2Cfg.public)
|
||||||
|
-> !oauth2Cfg.enableLocalhostRedirects;
|
||||||
|
message = "services.kanidm.provision.systems.oauth2.${oauth2} is a non-public client and thus cannot enable localhost redirects";
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
environment.systemPackages = lib.mkIf cfg.enableClient [ cfg.package ];
|
environment.systemPackages = lib.mkIf cfg.enableClient [ cfg.package ];
|
||||||
|
|
||||||
@ -679,9 +778,12 @@ in
|
|||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
serviceConfig = lib.mkMerge [
|
serviceConfig = lib.mkMerge [
|
||||||
# Merge paths and ignore existing prefixes needs to sidestep mkMerge
|
# Merge paths and ignore existing prefixes needs to sidestep mkMerge
|
||||||
(defaultServiceConfig // {
|
(
|
||||||
BindReadOnlyPaths = mergePaths (defaultServiceConfig.BindReadOnlyPaths ++ certPaths);
|
defaultServiceConfig
|
||||||
})
|
// {
|
||||||
|
BindReadOnlyPaths = mergePaths (defaultServiceConfig.BindReadOnlyPaths ++ certPaths);
|
||||||
|
}
|
||||||
|
)
|
||||||
{
|
{
|
||||||
StateDirectory = "kanidm";
|
StateDirectory = "kanidm";
|
||||||
StateDirectoryMode = "0700";
|
StateDirectoryMode = "0700";
|
||||||
@ -704,7 +806,11 @@ in
|
|||||||
PrivateUsers = lib.mkForce false;
|
PrivateUsers = lib.mkForce false;
|
||||||
# Port needs to be exposed to the host network
|
# Port needs to be exposed to the host network
|
||||||
PrivateNetwork = lib.mkForce false;
|
PrivateNetwork = lib.mkForce false;
|
||||||
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
|
RestrictAddressFamilies = [
|
||||||
|
"AF_INET"
|
||||||
|
"AF_INET6"
|
||||||
|
"AF_UNIX"
|
||||||
|
];
|
||||||
TemporaryFileSystem = "/:ro";
|
TemporaryFileSystem = "/:ro";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@ -715,7 +821,10 @@ in
|
|||||||
description = "Kanidm PAM daemon";
|
description = "Kanidm PAM daemon";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
restartTriggers = [ unixConfigFile clientConfigFile ];
|
restartTriggers = [
|
||||||
|
unixConfigFile
|
||||||
|
clientConfigFile
|
||||||
|
];
|
||||||
serviceConfig = lib.mkMerge [
|
serviceConfig = lib.mkMerge [
|
||||||
defaultServiceConfig
|
defaultServiceConfig
|
||||||
{
|
{
|
||||||
@ -740,7 +849,11 @@ in
|
|||||||
];
|
];
|
||||||
# Needs to connect to kanidmd
|
# Needs to connect to kanidmd
|
||||||
PrivateNetwork = lib.mkForce false;
|
PrivateNetwork = lib.mkForce false;
|
||||||
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
|
RestrictAddressFamilies = [
|
||||||
|
"AF_INET"
|
||||||
|
"AF_INET6"
|
||||||
|
"AF_UNIX"
|
||||||
|
];
|
||||||
TemporaryFileSystem = "/:ro";
|
TemporaryFileSystem = "/:ro";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@ -750,9 +863,15 @@ in
|
|||||||
systemd.services.kanidm-unixd-tasks = lib.mkIf cfg.enablePam {
|
systemd.services.kanidm-unixd-tasks = lib.mkIf cfg.enablePam {
|
||||||
description = "Kanidm PAM home management daemon";
|
description = "Kanidm PAM home management daemon";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "network.target" "kanidm-unixd.service" ];
|
after = [
|
||||||
|
"network.target"
|
||||||
|
"kanidm-unixd.service"
|
||||||
|
];
|
||||||
partOf = [ "kanidm-unixd.service" ];
|
partOf = [ "kanidm-unixd.service" ];
|
||||||
restartTriggers = [ unixConfigFile clientConfigFile ];
|
restartTriggers = [
|
||||||
|
unixConfigFile
|
||||||
|
clientConfigFile
|
||||||
|
];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${cfg.package}/bin/kanidm_unixd_tasks";
|
ExecStart = "${cfg.package}/bin/kanidm_unixd_tasks";
|
||||||
|
|
||||||
@ -772,7 +891,12 @@ in
|
|||||||
"/run/kanidm-unixd:/var/run/kanidm-unixd"
|
"/run/kanidm-unixd:/var/run/kanidm-unixd"
|
||||||
];
|
];
|
||||||
# CAP_DAC_OVERRIDE is needed to ignore ownership of unixd socket
|
# CAP_DAC_OVERRIDE is needed to ignore ownership of unixd socket
|
||||||
CapabilityBoundingSet = [ "CAP_CHOWN" "CAP_FOWNER" "CAP_DAC_OVERRIDE" "CAP_DAC_READ_SEARCH" ];
|
CapabilityBoundingSet = [
|
||||||
|
"CAP_CHOWN"
|
||||||
|
"CAP_FOWNER"
|
||||||
|
"CAP_DAC_OVERRIDE"
|
||||||
|
"CAP_DAC_READ_SEARCH"
|
||||||
|
];
|
||||||
IPAddressDeny = "any";
|
IPAddressDeny = "any";
|
||||||
# Need access to users
|
# Need access to users
|
||||||
PrivateUsers = false;
|
PrivateUsers = false;
|
||||||
@ -787,15 +911,11 @@ in
|
|||||||
|
|
||||||
# These paths are hardcoded
|
# These paths are hardcoded
|
||||||
environment.etc = lib.mkMerge [
|
environment.etc = lib.mkMerge [
|
||||||
(lib.mkIf cfg.enableServer {
|
(lib.mkIf cfg.enableServer { "kanidm/server.toml".source = serverConfigFile; })
|
||||||
"kanidm/server.toml".source = serverConfigFile;
|
|
||||||
})
|
|
||||||
(lib.mkIf options.services.kanidm.clientSettings.isDefined {
|
(lib.mkIf options.services.kanidm.clientSettings.isDefined {
|
||||||
"kanidm/config".source = clientConfigFile;
|
"kanidm/config".source = clientConfigFile;
|
||||||
})
|
})
|
||||||
(lib.mkIf cfg.enablePam {
|
(lib.mkIf cfg.enablePam { "kanidm/unixd".source = unixConfigFile; })
|
||||||
"kanidm/unixd".source = unixConfigFile;
|
|
||||||
})
|
|
||||||
];
|
];
|
||||||
|
|
||||||
system.nssModules = lib.mkIf cfg.enablePam [ cfg.package ];
|
system.nssModules = lib.mkIf cfg.enablePam [ cfg.package ];
|
||||||
@ -804,12 +924,8 @@ in
|
|||||||
system.nssDatabases.passwd = lib.optional cfg.enablePam "kanidm";
|
system.nssDatabases.passwd = lib.optional cfg.enablePam "kanidm";
|
||||||
|
|
||||||
users.groups = lib.mkMerge [
|
users.groups = lib.mkMerge [
|
||||||
(lib.mkIf cfg.enableServer {
|
(lib.mkIf cfg.enableServer { kanidm = { }; })
|
||||||
kanidm = { };
|
(lib.mkIf cfg.enablePam { kanidm-unixd = { }; })
|
||||||
})
|
|
||||||
(lib.mkIf cfg.enablePam {
|
|
||||||
kanidm-unixd = { };
|
|
||||||
})
|
|
||||||
];
|
];
|
||||||
users.users = lib.mkMerge [
|
users.users = lib.mkMerge [
|
||||||
(lib.mkIf cfg.enableServer {
|
(lib.mkIf cfg.enableServer {
|
||||||
@ -830,6 +946,10 @@ in
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
meta.maintainers = with lib.maintainers; [ erictapen Flakebi oddlama ];
|
meta.maintainers = with lib.maintainers; [
|
||||||
|
erictapen
|
||||||
|
Flakebi
|
||||||
|
oddlama
|
||||||
|
];
|
||||||
meta.buildDocsInSandbox = false;
|
meta.buildDocsInSandbox = false;
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ import ./make-test-python.nix (
|
|||||||
groups.service1-admin = { };
|
groups.service1-admin = { };
|
||||||
systems.oauth2.service1 = {
|
systems.oauth2.service1 = {
|
||||||
displayName = "Service One (changed)";
|
displayName = "Service One (changed)";
|
||||||
# multiple origin urls
|
# multiple origin urls
|
||||||
originUrl = [
|
originUrl = [
|
||||||
"https://changed-one.example.com/"
|
"https://changed-one.example.com/"
|
||||||
"https://changed-one.example.org/"
|
"https://changed-one.example.org/"
|
||||||
|
Loading…
Reference in New Issue
Block a user