2021-04-20 19:26:42 +08:00
require 'msfdb_helpers/db_interface'
2021-04-16 20:52:55 +08:00
2021-04-30 21:24:56 +08:00
module MsfdbHelpers
class PgCtl < DbInterface
def initialize ( db_path : , options : , localconf : , db_conf : )
@db = db_path
@options = options
@localconf = localconf
@db_conf = db_conf
2022-06-23 19:20:23 +08:00
@socket_directory = db_path
2021-04-30 21:24:56 +08:00
super ( options )
2021-04-26 09:24:11 +08:00
end
2021-04-30 21:24:56 +08:00
def init ( msf_pass , msftest_pass )
puts " Creating database at #{ @db } "
Dir . mkdir ( @db )
2021-05-13 23:44:17 +08:00
run_cmd ( " initdb --auth-host=trust --auth-local=trust -E UTF8 #{ @db . shellescape } " )
2022-01-25 22:54:14 +08:00
2022-01-25 22:41:57 +08:00
File . open ( " #{ @db } /postgresql.conf " , 'a' ) do | f |
f . puts " port = #{ @options [ :db_port ] } "
2022-06-23 19:20:23 +08:00
end
# Try creating a test file at {Dir.tmpdir}
begin
test_executable_file ( " #{ Dir . tmpdir } " )
rescue
begin
# Fallback to creation at {@db}
test_executable_file ( " #{ @db } " )
rescue
print_error ( " Attempt to create DB socket file at Temporary Directory and `~/.msf4/db` failed. Possibly because they are mounted with NOEXEC Flags. Database Initialization Failed. " )
2022-02-21 21:47:36 +08:00
end
2021-04-30 21:24:56 +08:00
end
2021-04-26 09:24:11 +08:00
2021-04-30 21:24:56 +08:00
start
2021-04-26 09:24:11 +08:00
2021-04-30 21:24:56 +08:00
create_db_users ( msf_pass , msftest_pass )
2021-04-16 20:52:55 +08:00
2021-04-30 21:24:56 +08:00
write_db_client_auth_config
restart
end
2021-04-16 20:52:55 +08:00
2022-06-23 19:20:23 +08:00
# Creates and attempts to execute a testfile in the specified directory,
# to determine if it is mounted with NOEXEC flags.
def test_executable_file ( path )
File . open ( " #{ path } /msfdb_testfile " , 'w' ) do | f |
f . puts " # !/bin/bash \n echo exec "
end
File . chmod ( 0744 , " #{ path } /msfdb_testfile " )
if run_cmd ( " #{ path } /msfdb_testfile " )
File . open ( " #{ @db } /postgresql.conf " , 'a' ) do | f |
f . puts " unix_socket_directories = \' #{ path } \' "
end
@socket_directory = path
puts " Creating db socket file at #{ path } "
end
end
2021-04-30 21:24:56 +08:00
def delete
2021-06-18 04:27:33 +08:00
if exists?
2021-04-30 21:24:56 +08:00
stop
2021-04-16 20:52:55 +08:00
2021-04-30 21:24:56 +08:00
if @options [ :delete_existing_data ]
puts " Deleting all data at #{ @db } "
FileUtils . rm_rf ( @db )
end
if @options [ :delete_existing_data ]
2021-06-18 04:27:33 +08:00
FileUtils . rm_r ( @db_conf , force : true )
2021-04-30 21:24:56 +08:00
end
else
puts " No data at #{ @db } , doing nothing "
2021-04-16 20:52:55 +08:00
end
end
2021-04-30 21:24:56 +08:00
def start
2021-06-18 04:27:33 +08:00
if status == DatabaseStatus :: RUNNING
2021-04-30 21:24:56 +08:00
puts " Database already started at #{ @db } "
return true
end
print " Starting database at #{ @db } ... "
2021-05-13 23:44:17 +08:00
run_cmd ( " pg_ctl -o \" -p #{ @options [ :db_port ] } \" -D #{ @db . shellescape } -l #{ @db . shellescape } /log start " )
2021-04-30 21:24:56 +08:00
sleep ( 2 )
2021-05-13 23:44:17 +08:00
if run_cmd ( " pg_ctl -o \" -p #{ @options [ :db_port ] } \" -D #{ @db . shellescape } status " ) != 0
2021-04-30 21:24:56 +08:00
puts 'failed' . red . bold . to_s
false
else
puts 'success' . green . bold . to_s
true
end
2021-04-16 20:52:55 +08:00
end
2021-04-30 21:24:56 +08:00
def stop
2021-06-18 04:27:33 +08:00
if status == DatabaseStatus :: RUNNING
2021-04-30 21:24:56 +08:00
puts " Stopping database at #{ @db } "
2021-05-13 23:44:17 +08:00
run_cmd ( " pg_ctl -o \" -p #{ @options [ :db_port ] } \" -D #{ @db . shellescape } stop " )
2021-04-30 21:24:56 +08:00
else
puts " Database is no longer running at #{ @db } "
end
2021-04-16 20:52:55 +08:00
end
2021-04-30 21:24:56 +08:00
def restart
stop
start
end
2021-04-16 20:52:55 +08:00
2021-06-18 04:27:33 +08:00
def exists?
Dir . exist? ( @db )
end
2021-04-30 21:24:56 +08:00
def status
2021-06-18 04:27:33 +08:00
if exists?
2021-05-13 23:44:17 +08:00
if run_cmd ( " pg_ctl -o \" -p #{ @options [ :db_port ] } \" -D #{ @db . shellescape } status " ) == 0
2021-06-18 04:27:33 +08:00
DatabaseStatus :: RUNNING
2021-04-30 21:24:56 +08:00
else
2021-06-18 04:27:33 +08:00
DatabaseStatus :: INACTIVE
2021-04-30 21:24:56 +08:00
end
2021-04-16 20:52:55 +08:00
else
2021-06-18 04:27:33 +08:00
DatabaseStatus :: NOT_FOUND
2021-04-16 20:52:55 +08:00
end
end
2021-04-30 21:24:56 +08:00
def create_db_users ( msf_pass , msftest_pass )
puts 'Creating database users'
2022-06-23 19:20:23 +08:00
run_psql ( " create user #{ @options [ :msf_db_user ] . shellescape } with password ' #{ msf_pass } ' " , @socket_directory )
run_psql ( " create user #{ @options [ :msftest_db_user ] . shellescape } with password ' #{ msftest_pass } ' " , @socket_directory )
run_psql ( " alter role #{ @options [ :msf_db_user ] . shellescape } createdb " , @socket_directory )
run_psql ( " alter role #{ @options [ :msftest_db_user ] . shellescape } createdb " , @socket_directory )
run_psql ( " alter role #{ @options [ :msf_db_user ] . shellescape } with password ' #{ msf_pass } ' " , @socket_directory )
run_psql ( " alter role #{ @options [ :msftest_db_user ] . shellescape } with password ' #{ msftest_pass } ' " , @socket_directory )
2021-04-30 21:24:56 +08:00
conn = PG . connect ( host : @options [ :db_host ] , dbname : 'postgres' , port : @options [ :db_port ] , user : @options [ :msf_db_user ] , password : msf_pass )
conn . exec ( " CREATE DATABASE #{ @options [ :msf_db_name ] } " )
conn . exec ( " CREATE DATABASE #{ @options [ :msftest_db_name ] } " )
conn . finish
end
2021-04-26 09:24:11 +08:00
2021-04-30 21:24:56 +08:00
def write_db_client_auth_config
client_auth_config = " #{ @db } /pg_hba.conf "
super ( client_auth_config )
end
2021-04-20 20:47:47 +08:00
2021-04-30 21:24:56 +08:00
def self . requirements
%w[ psql pg_ctl initdb createdb ]
end
2021-04-20 20:47:47 +08:00
end
2021-04-16 20:52:55 +08:00
end