# encoding: utf-8 # copyright: 2015, Vulcano Security GmbH module Inspec::Resources class Postgres < Inspec.resource(1) name 'postgres' supports platform: 'unix' desc 'The \'postgres\' resource is a helper for the \'postgres_conf\', \'postgres_hba_conf\', \'postgres_ident_conf\' & \'postgres_session\' resources. Please use those instead.' attr_reader :service, :data_dir, :conf_dir, :conf_path, :version, :cluster def initialize # determine dirs and service based on versions determine_dirs determine_service # print warnings if the dirs do not exist verify_dirs if !@version.nil? && !@conf_dir.empty? @conf_path = File.join @conf_dir, 'postgresql.conf' else @conf_path = nil return skip_resource 'Seems like PostgreSQL is not installed on your system' end end def to_s 'PostgreSQL' end private def determine_dirs if inspec.os.debian? # # https://wiki.debian.org/PostgreSql # # Debian allows multiple versions of postgresql to be # installed as well as multiple "clusters" to be configured. # @version = version_from_psql || version_from_dir('/etc/postgresql') @cluster = cluster_from_dir("/etc/postgresql/#{@version}") @conf_dir = "/etc/postgresql/#{@version}/#{@cluster}" @data_dir = "/var/lib/postgresql/#{@version}/#{@cluster}" else @version = version_from_psql if @version.nil? if inspec.directory('/var/lib/pgsql/data').exist? warn 'Unable to determine PostgreSQL version: psql did not return a version number and unversioned data directories were found.' nil else @version = version_from_dir('/var/lib/pgsql') end end @data_dir = locate_data_dir_location_by_version(@version) end @conf_dir ||= @data_dir end def determine_service @service = 'postgresql' if @version.to_i >= 10 @service += "-#{@version.to_i}" elsif @version.to_f >= 9.4 @service += "-#{@version}" end end def verify_dirs warn "Default postgresql configuration directory: #{@conf_dir} does not exist. " \ "Postgresql may not be installed or we've misidentified the configuration " \ 'directory.' unless inspec.directory(@conf_dir).exist? warn "Default postgresql data directory: #{@data_dir} does not exist. " \ "Postgresql may not be installed or we've misidentified the data " \ 'directory.' unless inspec.directory(@data_dir).exist? end def version_from_psql return unless inspec.command('psql').exist? inspec.command("psql --version | awk '{ print $NF }' | awk -F. '{ print $1\".\"$2 }'").stdout.strip end def locate_data_dir_location_by_version(ver = @version) dir_list = [ "/var/lib/pgsql/#{ver}/data", # for 10, the versions are just stored in `10` although their version `10.7` "/var/lib/pgsql/#{ver.to_i}/data", '/var/lib/pgsql/data', '/var/lib/postgres/data', '/var/lib/postgresql/data', ] data_dir_loc = dir_list.detect { |i| inspec.directory(i).exist? } if data_dir_loc.nil? warn 'Unable to find the PostgreSQL data_dir in expected location(s), please execute "psql -t -A -p -h -c "show hba_file";" as the PostgreSQL DBA to find the non-standard data_dir location.' end data_dir_loc end def version_from_dir(dir) dirs = inspec.command("ls -d #{dir}/*/").stdout entries = dirs.lines.count case entries when 0 warn "Could not determine version of installed postgresql by inspecting #{dir}" nil when 1 warn "Using #{dirs}: #{dir_to_version(dirs)}" dir_to_version(dirs) else warn "Multiple versions of postgresql installed or incorrect base dir #{dir}" first = dir_to_version(dirs.lines.first) warn "Using the first version found: #{first}" first end end def dir_to_version(dir) dir.chomp.split('/').last end def cluster_from_dir(dir) # Main is the default cluster name on debian use it if it # exists. if inspec.directory("#{dir}/main").exist? 'main' else dirs = inspec.command("ls -d #{dir}/*/").stdout.lines first = dirs.first.chomp.split('/').last if dirs.count > 1 warn "Multiple postgresql clusters configured or incorrect base dir #{dir}" warn "Using the first directory found: #{first}" end first end end end end