feat(db_connector): Create a PostgreSQL connector for Prowler (#1171)

* chore(db providers): db providers first version

* chore(db provider): added db provider setup into Readme

* fix(csv_line): csv_line out of conditional

* fix(README): text instead of varchar in table

* fix(help): help message extended

Co-authored-by: Sergio Garcia <38561120+sergargar@users.noreply.github.com>

* fix(typo): Update README.md

Co-authored-by: Pepe Fagoaga <pepe@verica.io>

* fix(table): add if not exists

Co-authored-by: Pepe Fagoaga <pepe@verica.io>

* fix(typo): Readme postgreSQL

Co-authored-by: Pepe Fagoaga <pepe@verica.io>

* fix(db_connector): details to add a new provider

* fix(typo): Uppercase Prowler

Co-authored-by: Toni de la Fuente <toni@blyx.com>

* fix(prowler): deleted unused variable

* chore(checks): test db connector previous to send data

* chore(input tests): input tests moved to main

* fix(typo): Readme typos

* chore(table): table name from pgpass file

* fix(grep test): Added missing -E flag

* chore(table): check of table name and Readme

* chore(error colors): Added error colors

* fix(tablename): table name in readme

* fix(typo)

* fix(db_provider): Exact match

* fix(error): One line message

* chore(pgpass check): Check added for pgpass file

* fix(pgpass): pgpass file and permissions test

* fix(unused vars): Deleted unused vars

* fix(TOP_PID): Deleted TOP_PID unused var and comment

* chore(db tests): Credentials, database and table tests added

* fix(empty pgpass): Look for empty fields at pgpass file

Co-authored-by: Sergio Garcia <38561120+sergargar@users.noreply.github.com>
Co-authored-by: Pepe Fagoaga <pepe@verica.io>
Co-authored-by: Toni de la Fuente <toni@blyx.com>
This commit is contained in:
Nacho Rivera
2022-06-02 13:15:14 +02:00
committed by GitHub
parent ba727391db
commit 2e134ed947
4 changed files with 176 additions and 10 deletions
+45 -1
View File
@@ -330,6 +330,51 @@ Prowler has two parameters related to regions: `-r` that is used query AWS servi
```
./prowler -h
```
## Database providers connector
You can send the Prowler's output to different databases (right now only PostgreSQL is supported).
Jump into the section for the database provider you want to use and follow the required steps to configure it.
### PostgreSQL
- Install psql
- Mac -> `brew install libpq`
- Ubuntu -> `sudo apt-get install postgresql-client `
- RHEL/Centos -> `sudo yum install postgresql10`
- Configure a `~/.pgpass` file into the root folder of the user that is going to launch Prowler ([pgpass file doc](https://www.postgresql.org/docs/current/libpq-pgpass.html)), including an extra field at the end of the line, separated by `:`, to name the table, for instance:
`hostname:port:database:username:password:prowler_findings`
- Create a table in your PostgreSQL database to store the Prowler's data. You can use the following SQL statement to create the table:
```
CREATE TABLE IF NOT EXISTS prowler_findings (
profile TEXT,
account_number TEXT,
region TEXT,
check_id TEXT,
result TEXT,
item_scored TEXT,
item_level TEXT,
check_title TEXT,
result_extended TEXT,
check_asff_compliance_type TEXT,
severity TEXT,
service_name TEXT,
check_asff_resource_type TEXT,
check_asff_type TEXT,
risk TEXT,
remediation TEXT,
documentation TEXT,
check_caf_epic TEXT,
resource_id TEXT,
prowler_start_time TEXT,
account_details_email TEXT,
account_details_name TEXT,
account_details_arn TEXT,
account_details_org TEXT,
account_details_tags TEXT
);
```
- Execute Prowler with `-d` flag, for example:
`./prowler -M csv -d postgres`
> *Note*: This command creates a `csv` output file and stores the Prowler output in the configured PostgreSQL DB. It's an example, `-d` flag **does not** require `-M` to run.
## Advanced Usage
@@ -490,7 +535,6 @@ Either to run Prowler once or based on a schedule this template makes it pretty
The Cloud Formation template that helps you doing that is [here](https://github.com/prowler-cloud/prowler/blob/master/util/codebuild/codebuild-prowler-audit-account-cfn.yaml).
> This is a simple solution to monitor one account. For multiples accounts see [Multi Account and Continuous Monitoring](util/org-multi-account/README.md).
## Allowlist or remove a fail from resources
Sometimes you may find resources that are intentionally configured in a certain way that may be a bad practice but it is all right with it, for example an S3 bucket open to the internet hosting a web site, or a security group with an open port needed in your use case. Now you can use `-w allowlist_sample.txt` and add your resources as `checkID:resourcename` as in this command:
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
# DB connectors
# Supported connectors list is stored in SUPPORTED_DB_PROVIDERS
# Once the logic of the connector is added it is needed to add it to the list also
# Example: adding oracle to the list
# SUPPORTED_DB_PROVIDERS="postgresql|oracle"
# oracle_connector() { ... }
SUPPORTED_DB_PROVIDERS="postgresql"
export SUPPORTED_DB_PROVIDERS
# Connectors for different databases
#POSTGRESQL connector
postgresql_connector () {
CSV_REGISTRY="${1}"
psql -q -U "${PSQL_USER}" -h "${PSQL_HOSTNAME}" -c "copy ${PSQL_TABLE} from stdin with null as E'\'\'' delimiter ','" <<< "${CSV_REGISTRY}"
}
db_exit_abnormally() {
DB_PROVIDER="${1}"
MESSAGE=${2}
echo "${OPTRED}ERROR!$OPTNORMAL Database connector for '${DB_PROVIDER}' failed. ${MESSAGE}"
exit 2
}
+31 -3
View File
@@ -44,6 +44,7 @@ HTML_LOGO_IMG="https://github.com/prowler-cloud/prowler/raw/master/util/html/pro
TIMESTAMP=$(get_iso8601_timestamp)
PROWLER_PARAMETERS=$@
# Available parameters for outputs formats (implemented this in CSV from v2.4):
# $PROFILE profile used to run Prowler (--profile in AWS CLI)
@@ -70,6 +71,8 @@ PROWLER_PARAMETERS=$@
# $ACCOUNT_DETAILS_ORG
# $ACCOUNT_DETAILS_TAGS
# Ensure that output directory always exists when -M is used
if [[ $MODE ]];then
mkdir -p "${OUTPUT_DIR}"
@@ -107,9 +110,11 @@ textPass(){
REPREGION=$REGION
fi
CSV_LINE="${PROFILE/,/--}${SEP}${ACCOUNT_NUM/,/--}${SEP}${REPREGION/,/--}${SEP}${TITLE_ID/,/--}${SEP}${CHECK_RESULT/,/--}${SEP}${ITEM_SCORED/,/--}${SEP}${ITEM_CIS_LEVEL/,/--}${SEP}${TITLE_TEXT/,/--}${SEP}${CHECK_RESULT_EXTENDED/,/--}${SEP}${CHECK_ASFF_COMPLIANCE_TYPE/,/--}${SEP}${CHECK_SEVERITY/,/--}${SEP}${CHECK_SERVICENAME/,/--}${SEP}${CHECK_ASFF_RESOURCE_TYPE/,/--}${SEP}${CHECK_ASFF_TYPE/,/--}${SEP}${CHECK_RISK/,/--}${SEP}${CHECK_REMEDIATION/,/--}${SEP}${CHECK_DOC/,/--}${SEP}${CHECK_CAF_EPIC/,/--}${SEP}${CHECK_RESOURCE_ID/,/--}${SEP}${PROWLER_START_TIME/,/--}${SEP}${ACCOUNT_DETAILS_EMAIL/,/--}${SEP}${ACCOUNT_DETAILS_NAME/,/--}${SEP}${ACCOUNT_DETAILS_ARN/,/--}${SEP}${ACCOUNT_DETAILS_ORG/,/--}${SEP}${ACCOUNT_DETAILS_TAGS/,/--}"
if [[ "${MODES[@]}" =~ "csv" ]]; then
# Writting csv file replacing commas
echo "${PROFILE/,/--}${SEP}${ACCOUNT_NUM/,/--}${SEP}${REPREGION/,/--}${SEP}${TITLE_ID/,/--}${SEP}${CHECK_RESULT/,/--}${SEP}${ITEM_SCORED/,/--}${SEP}${ITEM_CIS_LEVEL/,/--}${SEP}${TITLE_TEXT/,/--}${SEP}${CHECK_RESULT_EXTENDED/,/--}${SEP}${CHECK_ASFF_COMPLIANCE_TYPE/,/--}${SEP}${CHECK_SEVERITY/,/--}${SEP}${CHECK_SERVICENAME/,/--}${SEP}${CHECK_ASFF_RESOURCE_TYPE/,/--}${SEP}${CHECK_ASFF_TYPE/,/--}${SEP}${CHECK_RISK/,/--}${SEP}${CHECK_REMEDIATION/,/--}${SEP}${CHECK_DOC/,/--}${SEP}${CHECK_CAF_EPIC/,/--}${SEP}${CHECK_RESOURCE_ID/,/--}${SEP}${PROWLER_START_TIME/,/--}${SEP}${ACCOUNT_DETAILS_EMAIL/,/--}${SEP}${ACCOUNT_DETAILS_NAME/,/--}${SEP}${ACCOUNT_DETAILS_ARN/,/--}${SEP}${ACCOUNT_DETAILS_ORG/,/--}${SEP}${ACCOUNT_DETAILS_TAGS/,/--}" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
echo "${CSV_LINE}" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
fi
if [[ "${MODES[@]}" =~ "json" ]]; then
generateJsonOutput "$1" "Pass" "$CHECK_RESOURCE_ID" >> ${OUTPUT_FILE_NAME}.$EXTENSION_JSON
@@ -134,6 +139,13 @@ textPass(){
if [[ "${MODES[@]}" =~ "html" ]]; then
generateHtmlOutput "$1" "PASS"
fi
#checking database provider
if [[ ${DATABASE_PROVIDER} == 'postgresql' ]]
then
postgresql_connector "${CSV_LINE}"
fi
}
textInfo(){
@@ -151,9 +163,11 @@ textInfo(){
REPREGION=$REGION
fi
CSV_LINE="${PROFILE/,/--}${SEP}${ACCOUNT_NUM/,/--}${SEP}${REPREGION/,/--}${SEP}${TITLE_ID/,/--}${SEP}${CHECK_RESULT/,/--}${SEP}${ITEM_SCORED/,/--}${SEP}${ITEM_CIS_LEVEL/,/--}${SEP}${TITLE_TEXT/,/--}${SEP}${CHECK_RESULT_EXTENDED/,/--}${SEP}${CHECK_ASFF_COMPLIANCE_TYPE/,/--}${SEP}${CHECK_SEVERITY/,/--}${SEP}${CHECK_SERVICENAME/,/--}${SEP}${CHECK_ASFF_RESOURCE_TYPE/,/--}${SEP}${CHECK_ASFF_TYPE/,/--}${SEP}${CHECK_RISK/,/--}${SEP}${CHECK_REMEDIATION/,/--}${SEP}${CHECK_DOC/,/--}${SEP}${CHECK_CAF_EPIC/,/--}${SEP}${CHECK_RESOURCE_ID/,/--}${SEP}${PROWLER_START_TIME/,/--}${SEP}${ACCOUNT_DETAILS_EMAIL/,/--}${SEP}${ACCOUNT_DETAILS_NAME/,/--}${SEP}${ACCOUNT_DETAILS_ARN/,/--}${SEP}${ACCOUNT_DETAILS_ORG/,/--}${SEP}${ACCOUNT_DETAILS_TAGS/,/--}"
if [[ "${MODES[@]}" =~ "csv" ]]; then
# Writing csv file replacing commas
echo "${PROFILE/,/--}${SEP}${ACCOUNT_NUM/,/--}${SEP}${REPREGION/,/--}${SEP}${TITLE_ID/,/--}${SEP}${CHECK_RESULT/,/--}${SEP}${ITEM_SCORED/,/--}${SEP}${ITEM_CIS_LEVEL/,/--}${SEP}${TITLE_TEXT/,/--}${SEP}${CHECK_RESULT_EXTENDED/,/--}${SEP}${CHECK_ASFF_COMPLIANCE_TYPE/,/--}${SEP}${CHECK_SEVERITY/,/--}${SEP}${CHECK_SERVICENAME/,/--}${SEP}${CHECK_ASFF_RESOURCE_TYPE/,/--}${SEP}${CHECK_ASFF_TYPE/,/--}${SEP}${CHECK_RISK/,/--}${SEP}${CHECK_REMEDIATION/,/--}${SEP}${CHECK_DOC/,/--}${SEP}${CHECK_CAF_EPIC/,/--}${SEP}${CHECK_RESOURCE_ID/,/--}${SEP}${PROWLER_START_TIME/,/--}${SEP}${ACCOUNT_DETAILS_EMAIL/,/--}${SEP}${ACCOUNT_DETAILS_NAME/,/--}${SEP}${ACCOUNT_DETAILS_ARN/,/--}${SEP}${ACCOUNT_DETAILS_ORG/,/--}${SEP}${ACCOUNT_DETAILS_TAGS/,/--}" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
echo "${CSV_LINE}" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
fi
if [[ "${MODES[@]}" =~ "json" ]]; then
generateJsonOutput "$1" "Info" "$CHECK_RESOURCE_ID" >> ${OUTPUT_FILE_NAME}.${EXTENSION_JSON}
@@ -170,6 +184,12 @@ textInfo(){
if [[ "${MODES[@]}" =~ "html" ]]; then
generateHtmlOutput "$1" "INFO" "$CHECK_RESOURCE_ID"
fi
#checking database provider
if [[ ${DATABASE_PROVIDER} == 'postgresql' ]]
then
postgresql_connector "${CSV_LINE}"
fi
}
textFail(){
@@ -217,9 +237,11 @@ textFail(){
REPREGION=$REGION
fi
CSV_LINE="${PROFILE/,/--}${SEP}${ACCOUNT_NUM/,/--}${SEP}${REPREGION/,/--}${SEP}${TITLE_ID/,/--}${SEP}${CHECK_RESULT/,/--}${SEP}${ITEM_SCORED/,/--}${SEP}${ITEM_CIS_LEVEL/,/--}${SEP}${TITLE_TEXT/,/--}${SEP}${CHECK_RESULT_EXTENDED/,/--}${SEP}${CHECK_ASFF_COMPLIANCE_TYPE/,/--}${SEP}${CHECK_SEVERITY/,/--}${SEP}${CHECK_SERVICENAME/,/--}${SEP}${CHECK_ASFF_RESOURCE_TYPE/,/--}${SEP}${CHECK_ASFF_TYPE/,/--}${SEP}${CHECK_RISK/,/--}${SEP}${CHECK_REMEDIATION/,/--}${SEP}${CHECK_DOC/,/--}${SEP}${CHECK_CAF_EPIC/,/--}${SEP}${CHECK_RESOURCE_ID/,/--}${SEP}${PROWLER_START_TIME/,/--}${SEP}${ACCOUNT_DETAILS_EMAIL/,/--}${SEP}${ACCOUNT_DETAILS_NAME/,/--}${SEP}${ACCOUNT_DETAILS_ARN/,/--}${SEP}${ACCOUNT_DETAILS_ORG/,/--}${SEP}${ACCOUNT_DETAILS_TAGS/,/--}"
if [[ "${MODES[@]}" =~ "csv" ]]; then
# Writing csv file replacing commas
echo "${PROFILE/,/--}${SEP}${ACCOUNT_NUM/,/--}${SEP}${REPREGION/,/--}${SEP}${TITLE_ID/,/--}${SEP}${CHECK_RESULT/,/--}${SEP}${ITEM_SCORED/,/--}${SEP}${ITEM_CIS_LEVEL/,/--}${SEP}${TITLE_TEXT/,/--}${SEP}${CHECK_RESULT_EXTENDED/,/--}${SEP}${CHECK_ASFF_COMPLIANCE_TYPE/,/--}${SEP}${CHECK_SEVERITY/,/--}${SEP}${CHECK_SERVICENAME/,/--}${SEP}${CHECK_ASFF_RESOURCE_TYPE/,/--}${SEP}${CHECK_ASFF_TYPE/,/--}${SEP}${CHECK_RISK/,/--}${SEP}${CHECK_REMEDIATION/,/--}${SEP}${CHECK_DOC/,/--}${SEP}${CHECK_CAF_EPIC/,/--}${SEP}${CHECK_RESOURCE_ID/,/--}${SEP}${PROWLER_START_TIME/,/--}${SEP}${ACCOUNT_DETAILS_EMAIL/,/--}${SEP}${ACCOUNT_DETAILS_NAME/,/--}${SEP}${ACCOUNT_DETAILS_ARN/,/--}${SEP}${ACCOUNT_DETAILS_ORG/,/--}${SEP}${ACCOUNT_DETAILS_TAGS/,/--}" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
echo "${CSV_LINE}" >> ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
fi
if [[ "${MODES[@]}" =~ "json" ]]; then
generateJsonOutput "$1" "${level}" "$CHECK_RESOURCE_ID">> ${OUTPUT_FILE_NAME}.${EXTENSION_JSON}
@@ -247,6 +269,12 @@ textFail(){
if [[ "${MODES[@]}" =~ "html" ]]; then
generateHtmlOutput "$1" "${level}" "$CHECK_RESOURCE_ID"
fi
#checking database provider
if [[ ${DATABASE_PROVIDER} == 'postgresql' ]]
then
postgresql_connector "${CSV_LINE}"
fi
}
textTitle(){
+60 -6
View File
@@ -46,6 +46,7 @@ TITLE_TEXT="CALLER ERROR - UNSET TITLE"
ALLOWLIST_FILE=""
TOTAL_CHECKS=()
# Ensures command output will always be set to JSON.
# If the default value is already set, ORIGINAL_OUTPUT will be used to store it and reset it at cleanup
if [[ -z "${AWS_DEFAULT_OUTPUT}" ]]; then
@@ -82,11 +83,11 @@ USAGE:
-l List all available checks only (does not perform any check). Add -g <group_id> to only list checks within the specified group.
-L List all groups (does not perform any check).
-e Exclude group extras.
-E Execute all tests except a list of specified checks separated by comma.
-E Execute all tests except a list of specified checks separated by comma.
(i.e. check21,check31)
-b Do not print Prowler banner.
-s Show scoring report (it is included by default in the html report).
-S Send check output to AWS Security Hub. Only valid when the output mode is json-asff
-S Send check output to AWS Security Hub. Only valid when the output mode is json-asff
(i.e. "-M json-asff -S").
-x Specify external directory with custom checks. S3 URI is supported.
(i.e. /my/own/checks or s3://bucket/prefix/checks, files must start by "check").
@@ -112,16 +113,17 @@ USAGE:
(i.e.: "-Z check11,check12" will cause check11 and/or check12 to trigger exit code 3)
-O <mgmnt acct ID> Specify AWS Organizations management account ID. Used to get account details, requires -R.
(requires organizations:ListAccounts* and organizations:ListTagsForResource)
-a <aws_cli_cmd> Build your own on-the-fly custom check by specifying the AWS CLI command to execute. Requires "-c extra9999". Omit the "aws" command and only use its parameters within quotes.
-a <aws_cli_cmd> Build your own on-the-fly custom check by specifying the AWS CLI command to execute. Requires "-c extra9999". Omit the "aws" command and only use its parameters within quotes.
Do not nest quotes in the aws parameter. Note that --output text is already included in the check.
i,e. -a 'ec2 describe-security-groups --filters Name=ip-permission.to-port,Values=80 --query SecurityGroups[*].GroupId[]]'
i,e. -a 'ec2 describe-security-groups --filters Name=ip-permission.to-port,Values=80 --query SecurityGroups[*].GroupId[]]'
-V Show version number & exit.
-h This help.
-d Send output to database through database connectors supported, currently only PostgreSQL. Prowler will get the credentials and table name from your ~/.pgpass file.
"
exit
}
while getopts ":hlLkqp:r:c:C:g:f:m:M:E:x:enbVsSI:A:R:T:w:N:o:B:D:F:zZ:O:a:" OPTION; do
while getopts ":hlLkqp:r:c:C:g:f:m:M:E:x:enbVsSI:A:R:T:w:N:o:B:D:F:zZ:O:a:d:" OPTION; do
case $OPTION in
h )
usage
@@ -234,6 +236,9 @@ while getopts ":hlLkqp:r:c:C:g:f:m:M:E:x:enbVsSI:A:R:T:w:N:o:B:D:F:zZ:O:a:" OPTI
a )
CUSTOM_CMD=$OPTARG
;;
d )
DATABASE_PROVIDER=$OPTARG
;;
: )
echo ""
echo "$OPTRED ERROR!$OPTNORMAL -$OPTARG requires an argument"
@@ -258,7 +263,7 @@ clean_up() {
addHtmlFooter >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
fi
# puts the AWS_DEFAULT_OUTPUT back to what it was at the start
if [ -z "$ORIGINAL_OUTPUT"]; then
if [ -z "$ORIGINAL_OUTPUT" ]; then
export AWS_DEFAULT_OUTPUT="$ORIGINAL_OUTPUT"
else
unset AWS_DEFAULT_OUTPUT
@@ -301,6 +306,10 @@ unset AWS_DEFAULT_OUTPUT
. $PROWLER_DIR/include/organizations_metadata
. $PROWLER_DIR/include/custom_checks
. $PROWLER_DIR/include/allowlist
. $PROWLER_DIR/include/db_connector
# Parses the check file into CHECK_ID's.
if [[ -n "$CHECK_FILE" ]]; then
@@ -315,6 +324,51 @@ if [[ -n "$CHECK_FILE" ]]; then
fi
fi
# Check database providers
if [[ ${DATABASE_PROVIDER} ]]
then
# Check if input provider is supported
if ! grep -w -q -E "${DATABASE_PROVIDER}" <<< "${SUPPORTED_DB_PROVIDERS}"
then
db_exit_abnormally "${DATABASE_PROVIDER}" "DB provider not supported, providers supported: ${SUPPORTED_DB_PROVIDERS} - EXITING!"
elif ! command -v "psql" > /dev/null 2>&1
then
db_exit_abnormally "postgresql" "psql tool not installed or not found- EXITING!"
elif [[ $(find "${HOME}/.pgpass" -perm 600 2>/dev/null) != "$HOME/.pgpass" ]]
then
db_exit_abnormally "postgresql" ".pgpass file not found at $HOME/.pgpass or .pgpass file permissions not matching 600 - EXITING!"
else
IFS=':' read -r PSQL_HOSTNAME PSQL_PORT PSQL_DATABASE PSQL_USER PSQL_PASSWORD PSQL_TABLE < "$HOME/.pgpass"
if [[ ! ${PSQL_HOSTNAME} ]] || [[ ! ${PSQL_PORT} ]] || [[ ! ${PSQL_DATABASE} ]] || [[ ! ${PSQL_USER} ]] || [[ ! ${PSQL_PASSWORD} ]] || [[ ! ${PSQL_TABLE} ]]
then
db_exit_abnormally "postgresql" "Empty field into ${HOME}/.pgpass file, all fields must be filled. Please check Prowler README about .pgpass file format - EXITING!"
fi
export PSQL_USER
export PSQL_HOSTNAME
export PSQL_TABLE
# Once all the variables are defined and exported test if database instance is reachable
if ! pg_isready -q -U "${PSQL_USER}" -h "${PSQL_HOSTNAME}" -p "${PSQL_PORT}"
then
db_exit_abnormally "postgresql" "Database listening on host ${PSQL_HOSTNAME} on port ${PSQL_PORT} connected as user ${PSQL_USER} is unreachable - EXITING!"
# If database instance is ready time to check credentials
elif ! PGPASSWORD="${PSQL_PASSWORD}" psql -U "${PSQL_USER}" -h "${PSQL_HOSTNAME}" -c "\q" > /dev/null 2>&1
then
db_exit_abnormally "postgresql" "User ${PSQL_USER} invalid or invalid credentials, please check ${HOME}/.pgpass file - EXITING!"
# If credentials are ok -> database exists?
elif ! PGPASSWORD="${PSQL_PASSWORD}" psql -U "${PSQL_USER}" -h "${PSQL_HOSTNAME}" "${PSQL_DATABASE}" -c "\q" > /dev/null 2>&1
then
db_exit_abnormally "postgresql" "Database not exists, please check ${HOME}/.pgpass file - EXITING!"
# and finally, if database exists -> table exists ?
elif ! PGPASSWORD="${PSQL_PASSWORD}" psql -U "${PSQL_USER}" -h "${PSQL_HOSTNAME}" "${PSQL_DATABASE}" -c "SELECT * FROM ${PSQL_TABLE};" > /dev/null 2>&1
then
db_exit_abnormally "postgresql" "Table ${PSQL_TABLE} not exists, please check ${HOME}/.pgpass file - EXITING!"
fi
fi
fi
# Pre-process allowlist file if supplied
if [[ -n "$ALLOWLIST_FILE" ]]; then
allowlist