diff --git a/gorgone/gorgone/class/core.pm b/gorgone/gorgone/class/core.pm index 4320c6e026c..7b8408472f1 100644 --- a/gorgone/gorgone/class/core.pm +++ b/gorgone/gorgone/class/core.pm @@ -163,8 +163,14 @@ sub init { $self->{logger}->writeLogError("[core] can't find config file '$self->{config_file}'"); exit(1); } + # before loading the config, we need to load initialize vault. + # Gorgone don't know how to reload for now, but once it will be done, we will need to retry the vault connexion if it failed when starting, and read again the configuration + $self->{vault_file} = defined($self->{vault_file}) ? $self->{vault_file} : '/var/lib/centreon/vault/vault.json'; + $self->{vault} = centreon::common::vault->new(logger => $self->{logger}, 'config_file' => $self->{vault_file}); + $self->{config} = $self->yaml_load_config( - file => $self->{config_file}, + file => $self->{config_file}, + # the filter is used to remove anything from the configuration not related to gorgone or centreon filter => '!($ariane eq "configuration##" || $ariane =~ /^configuration##(?:gorgone|centreon)##/)' ); diff --git a/gorgone/gorgone/class/script.pm b/gorgone/gorgone/class/script.pm index 2dbd5bbf3f6..5e48dfac044 100644 --- a/gorgone/gorgone/class/script.pm +++ b/gorgone/gorgone/class/script.pm @@ -56,6 +56,7 @@ sub new { $self->{logger} = gorgone::class::logger->new(); $self->{options} = { 'config=s' => \$self->{config_file}, + 'vault=s' => \$self->{vault_config_file}, 'logfile=s' => \$self->{log_file}, 'severity=s' => \$self->{severity}, 'flushoutput' => \$self->{flushoutput}, @@ -184,7 +185,6 @@ sub yaml_get_include { # yaml_parse_config: recursive function to parse yaml content and honor the inclusion of other files and vault password decryption. # depending on the type of the yaml object, it will call itself recursively. # config: yaml object as perl reference (hash, array, scalar, hash of hash...). $YAML::XS::LoadBlessed should be set to 1 to transform !include in blessed reference. -# vault: vault object to decrypt password. # current_dir: current directory to resolve relative path of !include directive. # filter: a string to eval to filter the yaml content. you can for exemple return only children of a node. # ariane: Ariadne's thread to know where we are in the yaml content. It is used by the filter. example : 'configuration##gorgone##gorgonecore##' @@ -250,14 +250,23 @@ sub yaml_parse_config { } else { ${$options{config}} = 'false'; } + + } elsif (ref(${$options{config}}) eq '') { + # this is a scalar value, we check if this is a vault path to replace it. + if ($self->{vault} and $self->{vault}->can('get_secret')) { + ${$options{config}} = $self->{vault}->get_secret( ${$options{config}}); + } + } else { + $self->{logger}->writeLogError("config - unknown type of data: " . ref(${$options{config}})); } } # yaml_load_config: entry point for yaml parsing. # can be called by yaml_parse_config if there is !include in the yaml, and will call yaml_parse_config to parse the content of the file. # file: filename to parse. The file can contain !include directive to include other files. -# ariane: is a string to eval to filter the yaml content. you can for exemple return only children of a node named configuration with this filter : +# filter: is a string to eval to filter the yaml content. you can for exemple return only children of a node named configuration with this filter : # '$ariane eq "configuration##"' +# arianne: Ariadne's thread to know where we are in the yaml content. It is used by the filter. example : 'configuration##gorgone##gorgonecore##' sub yaml_load_config { my ($self, %options) = @_; diff --git a/gorgone/tests/unit/class/core.t b/gorgone/tests/unit/class/core.t index 7f12b2105e3..b4a3224c44b 100644 --- a/gorgone/tests/unit/class/core.t +++ b/gorgone/tests/unit/class/core.t @@ -10,6 +10,7 @@ use FindBin; use lib "$FindBin::Bin/../../../"; use gorgone::class::script; use gorgone::class::core; +use centreon::common::centreonvault; sub create_data_set { my $set = {}; @@ -17,6 +18,15 @@ sub create_data_set { chdir($FindBin::Bin); $set->{logger} = gorgone::class::logger->new(); $set->{logger}->severity('debug'); + $set->{vault} = mock 'centreon::common::centreonvault'; # is from Test2::Tools::Mock, included by Test2::V0 + $set->{vault}->override('get_secret' => sub { + if ($_[1] eq 'secret::hashicorp_vault::SecretPathArg::secretNameFromApiResponse') { + return 'VaultSentASecret'; + } + return $_[1]; + }, 'new' => sub { + return bless({}, 'centreon::common::centreonvault'); + }); return $set; } @@ -26,6 +36,7 @@ sub test_configuration_read { # let's make a simple object and try to industryalize the yaml read configuration. my $gorgone = gorgone::class::core->new(); $gorgone->{logger} = $set->{logger}; + $gorgone->{vault} = centreon::common::centreonvault->new(); my $tests_cases = [ { @@ -37,7 +48,7 @@ sub test_configuration_read { FalseVal => 'false', vault => { badFormat => 'secret::hashicorp::thereIsOnlyOneColon', - correctFormat => 'secret::hashicorp_vault::SecretPathArg::secretNameFromApiResponse'}, + correctFormat => 'VaultSentASecret'}, } } }, msg => 'simple configuration without recursion' @@ -71,6 +82,7 @@ sub test_yaml_get_include { my $set = shift; my $gorgone = gorgone::class::core->new(); $gorgone->{logger} = $set->{logger}; + #$gorgone->{vault} = centreon::common::centreonvault->new(); my @result = $gorgone->yaml_get_include('include' => '*.yaml', 'current_dir' => './config_examples/include_other_files', 'filter' => '!($ariane eq "configuration##" || $ariane =~ /^configuration##(?:gorgone|centreon)##/)'); @@ -84,7 +96,6 @@ sub test_yaml_get_include { } sub main { my $set = create_data_set(); - ok(1); test_yaml_get_include($set); test_configuration_read($set);