|
|
|
#!/usr/bin/perl
|
|
|
|
#
|
|
|
|
# This checks the state of the database server and, if necessary, sets up the database.
|
|
|
|
#
|
|
|
|
# Exit codes;
|
|
|
|
# 0 = Normal exit.
|
|
|
|
# 1 = Failed to initialize postgres
|
|
|
|
# 2 = Failed to start postgres
|
|
|
|
# 3 = ScanCore user not set in the local ID in striker.conf
|
|
|
|
# 4 = Failed to create the database user.
|
|
|
|
# 5 =
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
use Data::Dumper;
|
|
|
|
use AN::Tools;
|
|
|
|
|
|
|
|
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
|
|
|
|
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
|
|
|
|
if (($running_directory =~ /^\./) && ($ENV{PWD}))
|
|
|
|
{
|
|
|
|
$running_directory =~ s/^\./$ENV{PWD}/;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete.
|
|
|
|
$| = 1;
|
|
|
|
|
|
|
|
my $an = AN::Tools->new();
|
|
|
|
$an->Log->level({set => 2});
|
|
|
|
$an->Log->secure({set => 1});
|
|
|
|
|
|
|
|
# Paths
|
|
|
|
$an->data->{path}{tools}{'scancore-database'} = "/usr/sbin/striker/scancore-database";
|
|
|
|
$an->data->{path}{tools}{'scancore-update-states'} = "/usr/sbin/striker/scancore-update-states";
|
|
|
|
$an->data->{path}{config}{'striker.conf'} = "/etc/striker/striker.conf";
|
|
|
|
|
|
|
|
$an->Storage->read_config({file => $an->data->{path}{config}{'striker.conf'}});
|
|
|
|
|
|
|
|
my $local_id = $an->Database->get_local_id;
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { local_id => $local_id }});
|
|
|
|
if ($local_id)
|
|
|
|
{
|
|
|
|
# Start checks
|
|
|
|
my $running = $an->System->check_daemon({daemon => "postgresql"});
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { running => $running }});
|
|
|
|
if (not $running)
|
|
|
|
{
|
|
|
|
# Do we need to initialize the databae?
|
|
|
|
if (not -e $an->data->{path}{configs}{'pg_hba.conf'})
|
|
|
|
{
|
|
|
|
# Initialize.
|
|
|
|
my $output = $an->System->call({shell_call => $an->data->{path}{exe}{'postgresql-setup'}." initdb", source => $THIS_FILE, line => __LINE__});
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output }});
|
|
|
|
|
|
|
|
# Did it succeed?
|
|
|
|
if (not -e $an->data->{path}{configs}{'pg_hba.conf'})
|
|
|
|
{
|
|
|
|
# Failed...
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0001"});
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
# Initialized!
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0001"});
|
|
|
|
}
|
|
|
|
|
|
|
|
# Setup postgresql.conf
|
|
|
|
my $postgresql_backup = $an->data->{path}{directories}{backups}."/pgsql/postgresql.conf";
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { postgresql_backup => $postgresql_backup }});
|
|
|
|
$an->Storage->copy_file({source => $an->data->{path}{configs}{'postgresql.conf'}, target => $postgresql_backup});
|
|
|
|
|
|
|
|
my $postgresql_conf = $an->Storage->read_file({file => $an->data->{path}{configs}{'postgresql.conf'}});
|
|
|
|
my $update_file = 1;
|
|
|
|
my $new_postgresql_conf = "";
|
|
|
|
foreach my $line (split/\n/, $postgresql_conf)
|
|
|
|
{
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { line => $line }});
|
|
|
|
if ($line =~ /^listen_addresses = '\*'/)
|
|
|
|
{
|
|
|
|
# No need to update.
|
|
|
|
$update_file = 0;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
elsif ($line =~ /^#listen_addresses = 'localhost'/)
|
|
|
|
{
|
|
|
|
# Inject the new listen_addresses
|
|
|
|
$new_postgresql_conf .= "listen_addresses = '*'\n";
|
|
|
|
}
|
|
|
|
$new_postgresql_conf .= $line."\n";
|
|
|
|
}
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_file => $update_file }});
|
|
|
|
if ($update_file)
|
|
|
|
{
|
|
|
|
$an->Storage->write_file({
|
|
|
|
file => $an->data->{path}{configs}{'postgresql.conf'},
|
|
|
|
body => $new_postgresql_conf,
|
|
|
|
user => "postgres",
|
|
|
|
group => "postgres",
|
|
|
|
mode => "0600",
|
|
|
|
overwrite => 1,
|
|
|
|
});
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0002", variables => { file => $an->data->{path}{configs}{'postgresql.conf'} }});
|
|
|
|
}
|
|
|
|
|
|
|
|
# Setup pg_hba.conf now
|
|
|
|
my $pg_hba_backup = $an->data->{path}{directories}{backups}."/pgsql/pg_hba.conf";
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { pg_hba_backup => $pg_hba_backup }});
|
|
|
|
|
|
|
|
$an->Storage->copy_file({source => $an->data->{path}{configs}{'pg_hba.conf'}, target => $pg_hba_backup});
|
|
|
|
my $pg_hba_conf = $an->Storage->read_file({file => $an->data->{path}{configs}{'pg_hba.conf'}});
|
|
|
|
$update_file = 1;
|
|
|
|
my $new_pg_hba_conf = "";
|
|
|
|
foreach my $line (split/\n/, $pg_hba_conf)
|
|
|
|
{
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { line => $line }});
|
|
|
|
if ($line =~ /^host\s+all\s+all\s+\all\s+md5$/)
|
|
|
|
{
|
|
|
|
# No need to update.
|
|
|
|
$update_file = 0;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
elsif ($line =~ /^# TYPE\s+DATABASE/)
|
|
|
|
{
|
|
|
|
# Inject the new listen_addresses
|
|
|
|
$new_pg_hba_conf .= $line."\n";
|
|
|
|
$new_pg_hba_conf .= "host\tall\t\tall\t\t*\t\t\tmd5\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$new_pg_hba_conf .= $line."\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_file => $update_file }});
|
|
|
|
if ($update_file)
|
|
|
|
{
|
|
|
|
$an->Storage->write_file({
|
|
|
|
file => $an->data->{path}{configs}{'pg_hba.conf'},
|
|
|
|
body => $new_pg_hba_conf,
|
|
|
|
user => "postgres",
|
|
|
|
group => "postgres",
|
|
|
|
mode => "0600",
|
|
|
|
overwrite => 1,
|
|
|
|
});
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0003", variables => { file => $an->data->{path}{configs}{'postgresql.conf'} }});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Start the daemon. It might fail if it has never been initialized.
|
|
|
|
my $started = $an->System->start_daemon({daemon => "postgresql"});
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { started => $started }});
|
|
|
|
if ($started)
|
|
|
|
{
|
|
|
|
# Started the daemon.
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0004"});
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
# Failed to start
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0002"});
|
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Create the .pgpass file, if needed.
|
|
|
|
my $created_pgpass = 0;
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => {
|
|
|
|
'path::secure::postgres_pgpass' => $an->data->{path}{secure}{postgres_pgpass},
|
|
|
|
"database::${local_id}::password" => $an->data->{database}{$local_id}{password},
|
|
|
|
}});
|
|
|
|
if ((not -e $an->data->{path}{secure}{postgres_pgpass}) && ($an->data->{database}{$local_id}{password}))
|
|
|
|
{
|
|
|
|
my $body = "*:*:*:postgres:".$an->data->{database}{$local_id}{password}."\n";
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { body => $body }});
|
|
|
|
$an->Storage->write_file({
|
|
|
|
file => $an->data->{path}{secure}{postgres_pgpass},
|
|
|
|
body => $body,
|
|
|
|
user => "postgres",
|
|
|
|
group => "postgres",
|
|
|
|
mode => "0600",
|
|
|
|
overwrite => 1,
|
|
|
|
secure => 1,
|
|
|
|
});
|
|
|
|
if (-e $an->data->{path}{secure}{postgres_pgpass})
|
|
|
|
{
|
|
|
|
$created_pgpass = 1;
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { created_pgpass => $created_pgpass }});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Does the database user exist?
|
|
|
|
my $create_user = 1;
|
|
|
|
my $scancore_user = $an->data->{database}{$local_id}{user};
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scancore_user => $scancore_user }});
|
|
|
|
if (not $scancore_user)
|
|
|
|
{
|
|
|
|
# No database user defined
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0003", variables => { id => $local_id }});
|
|
|
|
exit(3);
|
|
|
|
}
|
|
|
|
my $user_list = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{psql}." template1 -c 'SELECT usename, usesysid FROM pg_catalog.pg_user;'\"", source => $THIS_FILE, line => __LINE__});
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { user_list => $user_list }});
|
|
|
|
foreach my $line (split/\n/, $user_list)
|
|
|
|
{
|
|
|
|
if ($line =~ /^ $scancore_user\s+\|\s+(\d+)/)
|
|
|
|
{
|
|
|
|
# User exists already
|
|
|
|
my $id = $1;
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0005", variables => { user => $scancore_user, id => $id }});
|
|
|
|
$create_user = 0;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { create_user => $create_user }});
|
|
|
|
if ($create_user)
|
|
|
|
{
|
|
|
|
# Create the user
|
|
|
|
my $create_output = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{createuser}." --no-superuser --createdb --no-createrole $scancore_user\"", source => $THIS_FILE, line => __LINE__});
|
|
|
|
my $user_list = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{psql}." template1 -c 'SELECT usename, usesysid FROM pg_catalog.pg_user;'\"", source => $THIS_FILE, line => __LINE__});
|
|
|
|
my $user_exists = 0;
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { create_output => $create_output, user_list => $user_list }});
|
|
|
|
foreach my $line (split/\n/, $user_list)
|
|
|
|
{
|
|
|
|
if ($line =~ /^ $scancore_user\s+\|\s+(\d+)/)
|
|
|
|
{
|
|
|
|
# Success!
|
|
|
|
my $id = $1;
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0006", variables => { user => $scancore_user, id => $id }});
|
|
|
|
$user_exists = 1;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (not $user_exists)
|
|
|
|
{
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0004", variables => { user => $scancore_user }});
|
|
|
|
exit(4);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Update/set the passwords.
|
|
|
|
if ($an->data->{database}{$local_id}{password})
|
|
|
|
{
|
|
|
|
foreach my $user ("postgres", $scancore_user)
|
|
|
|
{
|
|
|
|
my $update_output = $an->System->call({secure => 1, shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{psql}." template1 -c \\\"ALTER ROLE $user WITH PASSWORD '".$an->data->{database}{$local_id}{password}."';\\\"\"", source => $THIS_FILE, line => __LINE__});
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { update_output => $update_output }});
|
|
|
|
foreach my $line (split/\n/, $user_list)
|
|
|
|
{
|
|
|
|
if ($line =~ /ALTER ROLE/)
|
|
|
|
{
|
|
|
|
# Password set
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0007", variables => { user => $user }});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Create the database, if needed.
|
|
|
|
my $create_database = 1;
|
|
|
|
my $scancore_database = $an->data->{database}{$local_id}{name};
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "database::${local_id}::name" => $an->data->{database}{$local_id}{name} }});
|
|
|
|
|
|
|
|
my $database_list = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{psql}." template1 -c 'SELECT datname FROM pg_catalog.pg_database;'\"", source => $THIS_FILE, line => __LINE__});
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { database_list => $database_list }});
|
|
|
|
foreach my $line (split/\n/, $database_list)
|
|
|
|
{
|
|
|
|
if ($line =~ /^ $scancore_database$/)
|
|
|
|
{
|
|
|
|
# Database already exists.
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0008", variables => { database => $scancore_database }});
|
|
|
|
$create_database = 0;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { create_database => $create_database }});
|
|
|
|
if ($create_database)
|
|
|
|
{
|
|
|
|
my $create_output = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{createdb}." --owner $scancore_user $scancore_database\"", source => $THIS_FILE, line => __LINE__});
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { create_output => $create_output }});
|
|
|
|
|
|
|
|
my $database_exists = 0;
|
|
|
|
my $database_list = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{psql}." template1 -c 'SELECT datname FROM pg_catalog.pg_database;'\"", source => $THIS_FILE, line => __LINE__});
|
|
|
|
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { database_list => $database_list }});
|
|
|
|
foreach my $line (split/\n/, $database_list)
|
|
|
|
{
|
|
|
|
if ($line =~ /^ $scancore_database$/)
|
|
|
|
{
|
|
|
|
# Database created
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0008", variables => { database => $scancore_database }});
|
|
|
|
$database_exists = 1;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (not $database_exists)
|
|
|
|
{
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0005", variables => { database => $scancore_database }});
|
|
|
|
exit(5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Remove the temporary password file.
|
|
|
|
if (($created_pgpass) && (-e $an->data->{path}{secure}{postgres_pgpass}))
|
|
|
|
{
|
|
|
|
unlink $an->data->{path}{secure}{postgres_pgpass};
|
|
|
|
if (-e $an->data->{path}{secure}{postgres_pgpass})
|
|
|
|
{
|
|
|
|
# Failed to unlink the file.
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "warning_0001"});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
# Didn't find an entry for this machine.
|
|
|
|
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0010"});
|
|
|
|
}
|
|
|
|
|
|
|
|
exit(0);
|
|
|
|
|
|
|
|
|
|
|
|
#############################################################################################################
|
|
|
|
# Functions #
|
|
|
|
#############################################################################################################
|