forked from the-distro/infra
70 lines
2.3 KiB
Nix
70 lines
2.3 KiB
Nix
|
{ lib, config, ... }:
|
||
|
let
|
||
|
keys = import ./ssh-keys.nix;
|
||
|
inherit (lib) mkOption types length concatMap listToAttrs catAttrs attrValues;
|
||
|
cfgAdmins = config.bagel.admins;
|
||
|
cfgGroups = config.bagel.groups;
|
||
|
cfgUsers = config.bagel.users;
|
||
|
|
||
|
userOpts = { name, ... }: {
|
||
|
options = {
|
||
|
sshKeys = mkOption {
|
||
|
type = types.listOf types.str;
|
||
|
description = "List of SSH keys associated to this user, defaults to `ssh-keys.nix` entries.";
|
||
|
default = keys.users.${name} or [ ];
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
groupOpts = { name, ... }: {
|
||
|
options = {
|
||
|
members = mkOption {
|
||
|
type = types.listOf types.str;
|
||
|
description = "List of users member of this group";
|
||
|
example = [ "raito" ];
|
||
|
default = [ ];
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
# There might be duplicate in that list. We will turn it into an attribute set.
|
||
|
allowedMembers = listToAttrs (
|
||
|
map (member: {
|
||
|
name = member;
|
||
|
value = cfgUsers.${member};
|
||
|
}) (concatMap (allowedGroup: cfgGroups.${allowedGroup}.members) cfgAdmins.allowedGroups));
|
||
|
|
||
|
rootKeys = concatMap ({ sshKeys, ... }: sshKeys) (attrValues allowedMembers);
|
||
|
in
|
||
|
{
|
||
|
options.bagel.users = mkOption {
|
||
|
type = types.attrsOf (types.submodule userOpts);
|
||
|
description = "User configuration for server ACLs";
|
||
|
};
|
||
|
|
||
|
options.bagel.groups = mkOption {
|
||
|
type = types.attrsOf (types.submodule groupOpts);
|
||
|
description = "Group configuration for server ACLs";
|
||
|
};
|
||
|
|
||
|
options.bagel.admins = {
|
||
|
allowedGroups = mkOption {
|
||
|
type = types.listOf types.str;
|
||
|
default = [ "catch-all" ];
|
||
|
description = "List of groups which are allowed to admin this machine.";
|
||
|
example = [ "lix" "build-infra" ];
|
||
|
};
|
||
|
};
|
||
|
|
||
|
config = {
|
||
|
assertions = [
|
||
|
{ assertion = length config.users.users.root.openssh.authorizedKeys.keys > 0;
|
||
|
# TODO: you can add printing of `concatStringsSep ", " cfg.allowedGroups` to diagnose
|
||
|
# which are the allowed groups and existing admins.
|
||
|
message = "root@${config.networking.fqdnOrHostName} has no SSH key attached, this machine will lose its access if you deploy it successfully! Set a valid `bagel.admins.allowedGroups` or ensure you have at least one administrator of the relevant group registered";
|
||
|
}
|
||
|
];
|
||
|
|
||
|
users.users.root.openssh.authorizedKeys.keys = rootKeys;
|
||
|
};
|
||
|
}
|