krebs.git.rules: specify type

This commit is contained in:
tv 2016-02-03 13:36:54 +01:00
parent 68655d1ddf
commit cdb590be50
2 changed files with 142 additions and 55 deletions

View File

@ -44,8 +44,74 @@ let
default = "/etc/git";
};
repos = mkOption {
type = types.attrsOf (types.submodule ({
type = types.attrsOf subtypes.repo;
default = {};
example = literalExample ''
{
testing = {
name = "testing";
hooks.post-update = '''
#! /bin/sh
set -euf
echo post-update hook: $* >&2
''';
};
testing2 = { name = "testing2"; };
}
'';
description = ''
Repositories.
'';
};
root-desc = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Text printed below the heading on the repository index page.
Default value: "a fast webinterface for the git dscm".
'';
};
root-title = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Text printed as heading on the repository index page.
Default value: "Git Repository Browser".
'';
};
rules = mkOption {
type = types.listOf subtypes.rule;
default = [];
example = literalExample ''
singleton {
user = [ config.krebs.users.tv ];
repo = [ testing ]; # see literal example of repos
perm = push "refs/*" (with lib.git; [
non-fast-forward create delete merge
]);
}
'';
description = ''
Rules.
'';
};
};
# TODO put into krebs/4lib/types.nix?
subtypes = {
repo = types.submodule ({
options = {
collaborators = mkOption {
type = types.listOf types.user;
default = [];
description = ''
List of users that should be able to fetch from this repo.
This option is currently not used by krebs.git but instead can be
used to create rules. See e.g. <stockholm/tv/2configs/git.nix> for
an example.
'';
};
desc = mkOption {
type = types.nullOr types.str;
default = null;
@ -82,48 +148,69 @@ let
# TODO allow every configured user to fetch the repository via SSH.
};
};
}));
default = {};
example = literalExample ''
{
testing = {
name = "testing";
hooks.post-update = '''
#! /bin/sh
set -euf
echo post-update hook: $* >&2
''';
};
testing2 = { name = "testing2"; };
}
'';
});
rule = types.submodule ({ config, ... }: {
options = {
user = mkOption {
type = types.listOf types.user;
description = ''
Repositories.
List of users this rule should apply to.
Checked by authorize-command.
'';
};
root-desc = mkOption {
repo = mkOption {
type = types.listOf subtypes.repo;
description = ''
List of repos this rule should apply to.
Checked by authorize-command.
'';
};
perm = mkOption {
type = types.submodule {
# TODO generate enum argument from krebs/4lib/git.nix
options = {
allow-commands = mkOption {
type = types.listOf (types.enum (with git; [
git-receive-pack
git-upload-pack
]));
default = [];
description = ''
List of commands the rule's users are allowed to execute.
Checked by authorize-command.
'';
};
allow-receive-ref = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Text printed below the heading on the repository index page.
Default value: "a fast webinterface for the git dscm".
Ref that can receive objects.
Checked by authorize-push.
'';
};
root-title = mkOption {
type = types.nullOr types.str;
default = null;
allow-receive-modes = mkOption {
type = types.listOf (types.enum (with git; [
fast-forward
non-fast-forward
create
delete
merge
]));
default = [];
description = ''
Text printed as heading on the repository index page.
Default value: "Git Repository Browser".
List of allowed receive modes.
Checked by pre-receive hook.
'';
};
rules = mkOption {
type = types.unspecified;
};
};
description = ''
Permissions granted.
'';
};
};
});
};
git-imp = {
system.activationScripts.git-init = "${init-script}";
@ -131,18 +218,18 @@ let
# TODO maybe put all scripts here and then use PATH?
environment.etc."${etc-base}".source =
scriptFarm "git-ssh-authorizers" {
authorize-command = makeAuthorizeScript (map ({ repo, user, perm }: [
(map getName (ensureList user))
(map getName (ensureList repo))
(map getName perm.allow-commands)
authorize-command = makeAuthorizeScript (map (rule: [
(map getName (ensureList rule.user))
(map getName (ensureList rule.repo))
(map getName rule.perm.allow-commands)
]) cfg.rules);
authorize-push = makeAuthorizeScript (map ({ repo, user, perm }: [
(map getName (ensureList user))
(map getName (ensureList repo))
(ensureList perm.allow-receive-ref)
(map getName perm.allow-receive-modes)
]) (filter (x: hasAttr "allow-receive-ref" x.perm) cfg.rules));
authorize-push = makeAuthorizeScript (map (rule: [
(map getName (ensureList rule.user))
(map getName (ensureList rule.repo))
(ensureList rule.perm.allow-receive-ref)
(map getName rule.perm.allow-receive-modes)
]) (filter (rule: rule.perm.allow-receive-ref != null) cfg.rules));
};
users.extraUsers = singleton rec {

View File

@ -9,7 +9,7 @@ let
enable = true;
root-title = "public repositories at ${config.krebs.build.host.name}";
root-desc = "keep calm and engage";
repos = mapAttrs (_: s: removeAttrs s ["collaborators"]) repos;
repos = repos;
rules = rules;
};
};
@ -99,7 +99,7 @@ let
repo = [ repo ];
perm = fetch;
} ++
optional (length (repo.collaborators or []) > 0) {
optional (repo.collaborators or [] != []) {
user = repo.collaborators;
repo = [ repo ];
perm = fetch;