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"; default = "/etc/git";
}; };
repos = mkOption { 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 = { 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 { desc = mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
@ -82,48 +148,69 @@ let
# TODO allow every configured user to fetch the repository via SSH. # TODO allow every configured user to fetch the repository via SSH.
}; };
}; };
})); });
rule = types.submodule ({ config, ... }: {
default = {}; options = {
user = mkOption {
example = literalExample '' type = types.listOf types.user;
{
testing = {
name = "testing";
hooks.post-update = '''
#! /bin/sh
set -euf
echo post-update hook: $* >&2
''';
};
testing2 = { name = "testing2"; };
}
'';
description = '' 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; type = types.nullOr types.str;
default = null; default = null;
description = '' description = ''
Text printed below the heading on the repository index page. Ref that can receive objects.
Default value: "a fast webinterface for the git dscm". Checked by authorize-push.
''; '';
}; };
root-title = mkOption { allow-receive-modes = mkOption {
type = types.nullOr types.str; type = types.listOf (types.enum (with git; [
default = null; fast-forward
non-fast-forward
create
delete
merge
]));
default = [];
description = '' description = ''
Text printed as heading on the repository index page. List of allowed receive modes.
Default value: "Git Repository Browser". Checked by pre-receive hook.
''; '';
}; };
rules = mkOption {
type = types.unspecified;
}; };
}; };
description = ''
Permissions granted.
'';
};
};
});
};
git-imp = { git-imp = {
system.activationScripts.git-init = "${init-script}"; system.activationScripts.git-init = "${init-script}";
@ -131,18 +218,18 @@ let
# TODO maybe put all scripts here and then use PATH? # TODO maybe put all scripts here and then use PATH?
environment.etc."${etc-base}".source = environment.etc."${etc-base}".source =
scriptFarm "git-ssh-authorizers" { scriptFarm "git-ssh-authorizers" {
authorize-command = makeAuthorizeScript (map ({ repo, user, perm }: [ authorize-command = makeAuthorizeScript (map (rule: [
(map getName (ensureList user)) (map getName (ensureList rule.user))
(map getName (ensureList repo)) (map getName (ensureList rule.repo))
(map getName perm.allow-commands) (map getName rule.perm.allow-commands)
]) cfg.rules); ]) cfg.rules);
authorize-push = makeAuthorizeScript (map ({ repo, user, perm }: [ authorize-push = makeAuthorizeScript (map (rule: [
(map getName (ensureList user)) (map getName (ensureList rule.user))
(map getName (ensureList repo)) (map getName (ensureList rule.repo))
(ensureList perm.allow-receive-ref) (ensureList rule.perm.allow-receive-ref)
(map getName perm.allow-receive-modes) (map getName rule.perm.allow-receive-modes)
]) (filter (x: hasAttr "allow-receive-ref" x.perm) cfg.rules)); ]) (filter (rule: rule.perm.allow-receive-ref != null) cfg.rules));
}; };
users.extraUsers = singleton rec { users.extraUsers = singleton rec {

View File

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