mirror of
https://github.com/NixOS/hydra.git
synced 2024-10-22 22:59:17 +02:00
Create eval-jobset role and guard /api/push route
(cherry picked from commit f730433789
)
This commit is contained in:
parent
88d9898588
commit
bc6f08d233
|
@ -208,7 +208,8 @@ Example configuration:
|
||||||
<role_mapping>
|
<role_mapping>
|
||||||
# Make all users in the hydra_admin group Hydra admins
|
# Make all users in the hydra_admin group Hydra admins
|
||||||
hydra_admin = admin
|
hydra_admin = admin
|
||||||
# Allow all users in the dev group to restart jobs and cancel builds
|
# Allow all users in the dev group to eval jobsets, restart jobs and cancel builds
|
||||||
|
dev = eval-jobset
|
||||||
dev = restart-jobs
|
dev = restart-jobs
|
||||||
dev = cancel-build
|
dev = cancel-build
|
||||||
</role_mapping>
|
</role_mapping>
|
||||||
|
|
|
@ -95,6 +95,7 @@ sub get_legacy_ldap_config {
|
||||||
"hydra_bump-to-front" => [ "bump-to-front" ],
|
"hydra_bump-to-front" => [ "bump-to-front" ],
|
||||||
"hydra_cancel-build" => [ "cancel-build" ],
|
"hydra_cancel-build" => [ "cancel-build" ],
|
||||||
"hydra_create-projects" => [ "create-projects" ],
|
"hydra_create-projects" => [ "create-projects" ],
|
||||||
|
"hydra_eval-jobset" => [ "eval-jobset" ],
|
||||||
"hydra_restart-jobs" => [ "restart-jobs" ],
|
"hydra_restart-jobs" => [ "restart-jobs" ],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -159,6 +160,7 @@ sub valid_roles {
|
||||||
"bump-to-front",
|
"bump-to-front",
|
||||||
"cancel-build",
|
"cancel-build",
|
||||||
"create-projects",
|
"create-projects",
|
||||||
|
"eval-jobset",
|
||||||
"restart-jobs",
|
"restart-jobs",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -248,19 +248,24 @@ sub push : Chained('api') PathPart('push') Args(0) {
|
||||||
foreach my $s (@jobsets) {
|
foreach my $s (@jobsets) {
|
||||||
my ($p, $j) = parseJobsetName($s);
|
my ($p, $j) = parseJobsetName($s);
|
||||||
my $jobset = $c->model('DB::Jobsets')->find($p, $j);
|
my $jobset = $c->model('DB::Jobsets')->find($p, $j);
|
||||||
|
requireEvalJobsetPrivileges($c, $jobset->project);
|
||||||
next unless defined $jobset && ($force || ($jobset->project->enabled && $jobset->enabled));
|
next unless defined $jobset && ($force || ($jobset->project->enabled && $jobset->enabled));
|
||||||
triggerJobset($self, $c, $jobset, $force);
|
triggerJobset($self, $c, $jobset, $force);
|
||||||
}
|
}
|
||||||
|
|
||||||
my @repos = split /,/, ($c->request->query_params->{repos} // "");
|
my @repos = split /,/, ($c->request->query_params->{repos} // "");
|
||||||
foreach my $r (@repos) {
|
foreach my $r (@repos) {
|
||||||
triggerJobset($self, $c, $_, $force) foreach $c->model('DB::Jobsets')->search(
|
my @jobsets = $c->model('DB::Jobsets')->search(
|
||||||
{ 'project.enabled' => 1, 'me.enabled' => 1 },
|
{ 'project.enabled' => 1, 'me.enabled' => 1 },
|
||||||
{
|
{
|
||||||
join => 'project',
|
join => 'project',
|
||||||
where => \ [ 'exists (select 1 from JobsetInputAlts where project = me.project and jobset = me.name and value = ?)', [ 'value', $r ] ],
|
where => \ [ 'exists (select 1 from JobsetInputAlts where project = me.project and jobset = me.name and value = ?)', [ 'value', $r ] ],
|
||||||
order_by => 'me.id DESC'
|
order_by => 'me.id DESC'
|
||||||
});
|
});
|
||||||
|
foreach my $jobset (@jobsets) {
|
||||||
|
requireEvalJobsetPrivileges($c, $jobset->project);
|
||||||
|
triggerJobset($self, $c, $jobset, $force)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->status_ok(
|
$self->status_ok(
|
||||||
|
|
|
@ -15,6 +15,7 @@ our @EXPORT = qw(
|
||||||
forceLogin requireUser requireProjectOwner requireRestartPrivileges requireAdmin requirePost isAdmin isProjectOwner
|
forceLogin requireUser requireProjectOwner requireRestartPrivileges requireAdmin requirePost isAdmin isProjectOwner
|
||||||
requireBumpPrivileges
|
requireBumpPrivileges
|
||||||
requireCancelBuildPrivileges
|
requireCancelBuildPrivileges
|
||||||
|
requireEvalJobsetPrivileges
|
||||||
trim
|
trim
|
||||||
getLatestFinishedEval getFirstEval
|
getLatestFinishedEval getFirstEval
|
||||||
paramToList
|
paramToList
|
||||||
|
@ -186,6 +187,27 @@ sub isProjectOwner {
|
||||||
defined $c->model('DB::ProjectMembers')->find({ project => $project, userName => $c->user->username }));
|
defined $c->model('DB::ProjectMembers')->find({ project => $project, userName => $c->user->username }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub hasEvalJobsetRole {
|
||||||
|
my ($c) = @_;
|
||||||
|
return $c->user_exists && $c->check_user_roles("eval-jobset");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub mayEvalJobset {
|
||||||
|
my ($c, $project) = @_;
|
||||||
|
return
|
||||||
|
$c->user_exists &&
|
||||||
|
(isAdmin($c) ||
|
||||||
|
hasEvalJobsetRole($c) ||
|
||||||
|
isProjectOwner($c, $project));
|
||||||
|
}
|
||||||
|
|
||||||
|
sub requireEvalJobsetPrivileges {
|
||||||
|
my ($c, $project) = @_;
|
||||||
|
requireUser($c);
|
||||||
|
accessDenied($c, "Only the project members, administrators, and accounts with eval-jobset privileges can perform this operation.")
|
||||||
|
unless mayEvalJobset($c, $project);
|
||||||
|
}
|
||||||
|
|
||||||
sub hasCancelBuildRole {
|
sub hasCancelBuildRole {
|
||||||
my ($c) = @_;
|
my ($c) = @_;
|
||||||
return $c->user_exists && $c->check_user_roles('cancel-build');
|
return $c->user_exists && $c->check_user_roles('cancel-build');
|
||||||
|
|
|
@ -91,6 +91,7 @@
|
||||||
[% INCLUDE roleoption mutable=mutable role="restart-jobs" %]
|
[% INCLUDE roleoption mutable=mutable role="restart-jobs" %]
|
||||||
[% INCLUDE roleoption mutable=mutable role="bump-to-front" %]
|
[% INCLUDE roleoption mutable=mutable role="bump-to-front" %]
|
||||||
[% INCLUDE roleoption mutable=mutable role="cancel-build" %]
|
[% INCLUDE roleoption mutable=mutable role="cancel-build" %]
|
||||||
|
[% INCLUDE roleoption mutable=mutable role="eval-jobset" %]
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -57,6 +57,7 @@ subtest "getLDAPConfig" => sub {
|
||||||
"hydra_cancel-build" => [ "cancel-build" ],
|
"hydra_cancel-build" => [ "cancel-build" ],
|
||||||
"hydra_create-projects" => [ "create-projects" ],
|
"hydra_create-projects" => [ "create-projects" ],
|
||||||
"hydra_restart-jobs" => [ "restart-jobs" ],
|
"hydra_restart-jobs" => [ "restart-jobs" ],
|
||||||
|
"hydra_eval-jobset" => [ "eval-jobset" ],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"The empty file and set env var make legacy mode active."
|
"The empty file and set env var make legacy mode active."
|
||||||
|
@ -177,6 +178,7 @@ subtest "get_legacy_ldap_config" => sub {
|
||||||
"hydra_cancel-build" => [ "cancel-build" ],
|
"hydra_cancel-build" => [ "cancel-build" ],
|
||||||
"hydra_create-projects" => [ "create-projects" ],
|
"hydra_create-projects" => [ "create-projects" ],
|
||||||
"hydra_restart-jobs" => [ "restart-jobs" ],
|
"hydra_restart-jobs" => [ "restart-jobs" ],
|
||||||
|
"hydra_eval-jobset" => [ "eval-jobset" ],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Legacy, default role maps are applied."
|
"Legacy, default role maps are applied."
|
||||||
|
|
|
@ -22,9 +22,24 @@ sub is_json {
|
||||||
}
|
}
|
||||||
|
|
||||||
my $ctx = test_context();
|
my $ctx = test_context();
|
||||||
|
|
||||||
Catalyst::Test->import('Hydra');
|
Catalyst::Test->import('Hydra');
|
||||||
|
|
||||||
|
# Create a user to log in to
|
||||||
|
my $user = $ctx->db->resultset('Users')->create({ username => 'alice', emailaddress => 'alice@example.com', password => '!' });
|
||||||
|
$user->setPassword('foobar');
|
||||||
|
$user->userroles->update_or_create({ role => 'admin' });
|
||||||
|
|
||||||
|
# Login and save cookie for future requests
|
||||||
|
my $req = request(POST '/login',
|
||||||
|
Referer => 'http://localhost/',
|
||||||
|
Content => {
|
||||||
|
username => 'alice',
|
||||||
|
password => 'foobar'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
is($req->code, 302, "The login redirects");
|
||||||
|
my $cookie = $req->header("set-cookie");
|
||||||
|
|
||||||
my $finishedBuilds = $ctx->makeAndEvaluateJobset(
|
my $finishedBuilds = $ctx->makeAndEvaluateJobset(
|
||||||
expression => "one-job.nix",
|
expression => "one-job.nix",
|
||||||
build => 1
|
build => 1
|
||||||
|
@ -109,7 +124,10 @@ subtest "/api/push" => sub {
|
||||||
my $jobsetName = $jobset->name;
|
my $jobsetName = $jobset->name;
|
||||||
is($jobset->forceeval, undef, "The existing jobset is not set to be forced to eval");
|
is($jobset->forceeval, undef, "The existing jobset is not set to be forced to eval");
|
||||||
|
|
||||||
my $response = request(POST "/api/push?jobsets=$projectName:$jobsetName&force=1");
|
my $response = request(POST "/api/push?jobsets=$projectName:$jobsetName&force=1",
|
||||||
|
Cookie => $cookie,
|
||||||
|
Referer => 'http://localhost/',
|
||||||
|
);
|
||||||
ok($response->is_success, "The API enpdoint for triggering jobsets returns 200.");
|
ok($response->is_success, "The API enpdoint for triggering jobsets returns 200.");
|
||||||
|
|
||||||
my $data = is_json($response);
|
my $data = is_json($response);
|
||||||
|
@ -128,7 +146,10 @@ subtest "/api/push" => sub {
|
||||||
|
|
||||||
print STDERR $repo;
|
print STDERR $repo;
|
||||||
|
|
||||||
my $response = request(POST "/api/push?repos=$repo&force=1");
|
my $response = request(POST "/api/push?repos=$repo&force=1",
|
||||||
|
Cookie => $cookie,
|
||||||
|
Referer => 'http://localhost/',
|
||||||
|
);
|
||||||
ok($response->is_success, "The API enpdoint for triggering jobsets returns 200.");
|
ok($response->is_success, "The API enpdoint for triggering jobsets returns 200.");
|
||||||
|
|
||||||
my $data = is_json($response);
|
my $data = is_json($response);
|
||||||
|
|
|
@ -24,6 +24,7 @@ $ldap->add_group("hydra_create-projects", $users->{"many_roles"}->{"username"});
|
||||||
$ldap->add_group("hydra_restart-jobs", $users->{"many_roles"}->{"username"});
|
$ldap->add_group("hydra_restart-jobs", $users->{"many_roles"}->{"username"});
|
||||||
$ldap->add_group("hydra_bump-to-front", $users->{"many_roles"}->{"username"});
|
$ldap->add_group("hydra_bump-to-front", $users->{"many_roles"}->{"username"});
|
||||||
$ldap->add_group("hydra_cancel-build", $users->{"many_roles"}->{"username"});
|
$ldap->add_group("hydra_cancel-build", $users->{"many_roles"}->{"username"});
|
||||||
|
$ldap->add_group("hydra_eval-jobset", $users->{"many_roles"}->{"username"});
|
||||||
|
|
||||||
my $hydra_ldap_config = "${\$ldap->tmpdir()}/hydra_ldap_config.yaml";
|
my $hydra_ldap_config = "${\$ldap->tmpdir()}/hydra_ldap_config.yaml";
|
||||||
LDAPContext::write_file($hydra_ldap_config, <<YAML);
|
LDAPContext::write_file($hydra_ldap_config, <<YAML);
|
||||||
|
@ -68,7 +69,7 @@ subtest "Valid login attempts" => sub {
|
||||||
unrelated => [],
|
unrelated => [],
|
||||||
admin => ["admin"],
|
admin => ["admin"],
|
||||||
not_admin => [],
|
not_admin => [],
|
||||||
many_roles => [ "create-projects", "restart-jobs", "bump-to-front", "cancel-build" ],
|
many_roles => [ "create-projects", "restart-jobs", "bump-to-front", "cancel-build", "eval-jobset" ],
|
||||||
);
|
);
|
||||||
for my $username (keys %users_to_roles) {
|
for my $username (keys %users_to_roles) {
|
||||||
my $user = $users->{$username};
|
my $user = $users->{$username};
|
||||||
|
|
|
@ -24,6 +24,7 @@ $ldap->add_group("hydra_create-projects", $users->{"many_roles"}->{"username"});
|
||||||
$ldap->add_group("hydra_restart-jobs", $users->{"many_roles"}->{"username"});
|
$ldap->add_group("hydra_restart-jobs", $users->{"many_roles"}->{"username"});
|
||||||
$ldap->add_group("hydra_bump-to-front", $users->{"many_roles"}->{"username"});
|
$ldap->add_group("hydra_bump-to-front", $users->{"many_roles"}->{"username"});
|
||||||
$ldap->add_group("hydra_cancel-build", $users->{"many_roles"}->{"username"});
|
$ldap->add_group("hydra_cancel-build", $users->{"many_roles"}->{"username"});
|
||||||
|
$ldap->add_group("hydra_eval-jobset", $users->{"many_roles"}->{"username"});
|
||||||
|
|
||||||
|
|
||||||
my $ctx = test_context(
|
my $ctx = test_context(
|
||||||
|
@ -76,10 +77,12 @@ my $ctx = test_context(
|
||||||
hydra_cancel-build = cancel-build
|
hydra_cancel-build = cancel-build
|
||||||
hydra_bump-to-front = bump-to-front
|
hydra_bump-to-front = bump-to-front
|
||||||
hydra_restart-jobs = restart-jobs
|
hydra_restart-jobs = restart-jobs
|
||||||
|
hydra_eval-jobset = eval-jobset
|
||||||
|
|
||||||
hydra_one_group_many_roles = create-projects
|
hydra_one_group_many_roles = create-projects
|
||||||
hydra_one_group_many_roles = cancel-build
|
hydra_one_group_many_roles = cancel-build
|
||||||
hydra_one_group_many_roles = bump-to-front
|
hydra_one_group_many_roles = bump-to-front
|
||||||
|
hydra_one_group_many-roles = eval-jobset
|
||||||
</role_mapping>
|
</role_mapping>
|
||||||
</ldap>
|
</ldap>
|
||||||
CFG
|
CFG
|
||||||
|
@ -92,7 +95,7 @@ subtest "Valid login attempts" => sub {
|
||||||
unrelated => [],
|
unrelated => [],
|
||||||
admin => ["admin"],
|
admin => ["admin"],
|
||||||
not_admin => [],
|
not_admin => [],
|
||||||
many_roles => [ "create-projects", "restart-jobs", "bump-to-front", "cancel-build" ],
|
many_roles => [ "create-projects", "restart-jobs", "bump-to-front", "cancel-build", "eval-jobset" ],
|
||||||
many_roles_one_group => [ "create-projects", "bump-to-front", "cancel-build" ],
|
many_roles_one_group => [ "create-projects", "bump-to-front", "cancel-build" ],
|
||||||
);
|
);
|
||||||
for my $username (keys %users_to_roles) {
|
for my $username (keys %users_to_roles) {
|
||||||
|
|
Loading…
Reference in a new issue