2021-07-26 03:43:09 +00:00
|
|
|
package Hydra::Config;
|
|
|
|
|
2021-08-19 16:36:43 -04:00
|
|
|
use strict;
|
|
|
|
use warnings;
|
2022-02-09 21:06:28 -05:00
|
|
|
use Config::General;
|
|
|
|
use List::SomeUtils qw(none);
|
|
|
|
use YAML qw(LoadFile);
|
|
|
|
|
|
|
|
our @ISA = qw(Exporter);
|
|
|
|
our @EXPORT = qw(
|
|
|
|
getHydraConfig
|
|
|
|
getLDAPConfig
|
|
|
|
getLDAPConfigAmbient
|
|
|
|
);
|
2021-08-19 16:36:43 -04:00
|
|
|
|
2021-07-26 17:11:21 +00:00
|
|
|
our %configGeneralOpts = (-UseApacheInclude => 1, -IncludeAgain => 1, -IncludeRelative => 1);
|
2021-07-26 03:43:09 +00:00
|
|
|
|
2022-02-09 21:06:28 -05:00
|
|
|
my $hydraConfigCache;
|
|
|
|
|
|
|
|
sub getHydraConfig {
|
|
|
|
return $hydraConfigCache if defined $hydraConfigCache;
|
|
|
|
|
|
|
|
my $conf;
|
|
|
|
|
|
|
|
if ($ENV{"HYDRA_CONFIG"}) {
|
|
|
|
$conf = $ENV{"HYDRA_CONFIG"};
|
|
|
|
} else {
|
|
|
|
require Hydra::Model::DB;
|
|
|
|
$conf = Hydra::Model::DB::getHydraPath() . "/hydra.conf"
|
|
|
|
};
|
|
|
|
|
|
|
|
if (-f $conf) {
|
|
|
|
$hydraConfigCache = loadConfig($conf);
|
|
|
|
} else {
|
|
|
|
$hydraConfigCache = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
return $hydraConfigCache;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub loadConfig {
|
|
|
|
my ($sourceFile) = @_;
|
|
|
|
|
|
|
|
my %opts = (%configGeneralOpts, -ConfigFile => $sourceFile);
|
|
|
|
|
|
|
|
return { Config::General->new(%opts)->getall };
|
|
|
|
}
|
|
|
|
|
|
|
|
sub is_ldap_in_legacy_mode {
|
|
|
|
my ($config, %env) = @_;
|
|
|
|
|
|
|
|
my $legacy_defined = defined $env{"HYDRA_LDAP_CONFIG"};
|
|
|
|
|
|
|
|
if (defined $config->{"ldap"}) {
|
|
|
|
if ($legacy_defined) {
|
|
|
|
die "The legacy environment variable HYDRA_LDAP_CONFIG is set, but config is also specified in hydra.conf. Please unset the environment variable.";
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
} elsif ($legacy_defined) {
|
|
|
|
warn "Hydra is configured to use LDAP via the HYDRA_LDAP_CONFIG, a deprecated method. Please see the docs about configuring LDAP in the hydra.conf.";
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub getLDAPConfigAmbient {
|
|
|
|
return getLDAPConfig(getHydraConfig(), %ENV);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub getLDAPConfig {
|
|
|
|
my ($config, %env) = @_;
|
|
|
|
|
|
|
|
my $ldap_config;
|
|
|
|
|
|
|
|
if (is_ldap_in_legacy_mode($config, %env)) {
|
|
|
|
$ldap_config = get_legacy_ldap_config($env{"HYDRA_LDAP_CONFIG"});
|
|
|
|
} else {
|
|
|
|
$ldap_config = $config->{"ldap"};
|
|
|
|
}
|
|
|
|
|
|
|
|
$ldap_config->{"role_mapping"} = normalize_ldap_role_mappings($ldap_config->{"role_mapping"});
|
|
|
|
|
|
|
|
return $ldap_config;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub get_legacy_ldap_config {
|
|
|
|
my ($ldap_yaml_file) = @_;
|
|
|
|
|
|
|
|
return {
|
|
|
|
config => LoadFile($ldap_yaml_file),
|
|
|
|
role_mapping => {
|
|
|
|
"hydra_admin" => [ "admin" ],
|
|
|
|
"hydra_bump-to-front" => [ "bump-to-front" ],
|
|
|
|
"hydra_cancel-build" => [ "cancel-build" ],
|
|
|
|
"hydra_create-projects" => [ "create-projects" ],
|
|
|
|
"hydra_restart-jobs" => [ "restart-jobs" ],
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
sub normalize_ldap_role_mappings {
|
|
|
|
my ($input_map) = @_;
|
|
|
|
|
|
|
|
my $mapping = {};
|
|
|
|
|
|
|
|
my @errors;
|
|
|
|
|
|
|
|
for my $group (keys %{$input_map}) {
|
|
|
|
my $input = $input_map->{$group};
|
|
|
|
|
|
|
|
if (ref $input eq "ARRAY") {
|
|
|
|
$mapping->{$group} = $input;
|
|
|
|
} elsif (ref $input eq "") {
|
|
|
|
$mapping->{$group} = [ $input ];
|
|
|
|
} else {
|
|
|
|
push @errors, "On group '$group': the value is of type ${\ref $input}. Only strings and lists are acceptable.";
|
|
|
|
$mapping->{$group} = [ ];
|
|
|
|
}
|
|
|
|
|
|
|
|
eval {
|
|
|
|
validate_roles($mapping->{$group});
|
|
|
|
};
|
|
|
|
if ($@) {
|
|
|
|
push @errors, "On group '$group': $@";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (@errors) {
|
|
|
|
die join "\n", @errors;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $mapping;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub validate_roles {
|
|
|
|
my ($roles) = @_;
|
|
|
|
|
|
|
|
my @invalid;
|
|
|
|
my $valid = valid_roles();
|
|
|
|
|
|
|
|
for my $role (@$roles) {
|
|
|
|
if (none { $_ eq $role } @$valid) {
|
|
|
|
push @invalid, "'$role'";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (@invalid) {
|
|
|
|
die "Invalid roles: ${\join ', ', @invalid}. Valid roles are: ${\join ', ', @$valid}.";
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub valid_roles {
|
|
|
|
return [
|
|
|
|
"admin",
|
|
|
|
"bump-to-front",
|
|
|
|
"cancel-build",
|
|
|
|
"create-projects",
|
|
|
|
"restart-jobs",
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2021-07-26 03:43:09 +00:00
|
|
|
1;
|