#!/usr/bin/env python3
# -*- coding:utf-8 -*-
#############################################################################
# Copyright (c) 2024 Huawei Technologies Co.,Ltd.
#
# openGauss is licensed under Mulan PSL v2.
# You can use this software according to the terms
# and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#
#          http://license.coscl.org.cn/MulanPSL2
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# ----------------------------------------------------------------------------
# Description : LocalCheckSE.py is a utility to check security configurations info on local node.
#############################################################################
import os
import sys
import getopt
import subprocess
import re

localDirPath = os.path.dirname(os.path.realpath(__file__))

sys.path.append(sys.path[0] + "/../")
from gspylib.common.ParameterParsecheck import Parameter
from gspylib.common.GaussLog import GaussLog
from gspylib.common.DbClusterInfo import dbClusterInfo
from gspylib.common.Common import DefaultValue
from gspylib.common.ErrorCode import ErrorCode
from domain_utils.cluster_file.version_info import VersionInfo
from base_utils.os.net_util import NetUtil
from domain_utils.domain_common.cluster_constants import ClusterConstants
from datetime import datetime, timedelta

sys.path.insert(0, localDirPath + "/../../lib")
import pwd
import grp

ACTION_CHECK_Connection_configuration = "Check_Connection_configuration"
ACTION_CHECK_File_directory_security = "Check_File_directory_security"
ACTION_CHECK_Security_authentication_configuration = "Check_Security_authentication_configuration"
ACTION_CHECK_Account_password_management = "Check_Account_password_management"
ACTION_CHECK_Permission_management = "Check_Permission_management"
ACTION_CHECK_Database_auditing = "Check_Database_auditing"
ACTION_CHECK_Error_reporting_and_logging_configuration = "Check_Error_reporting_and_logging_configuration"
ACTION_CHECK_Backup_configuration = "Check_Backup_configuration"
ACTION_CHECK_Runtime_environment_configuration = "Check_Runtime_environment_configuration"
ACTION_CHECK_Other_configurations = "Check_Other_configurations"

ACTION_SET_Connection_configuration = "Set_Connection_configuration"
ACTION_SET_File_directory_security = "Set_File_directory_security"
ACTION_SET_Security_authentication_configuration = "Set_Security_authentication_configuration"
ACTION_SET_Account_password_management = "Set_Account_password_management"
ACTION_SET_Permission_management = "Set_Permission_management"
ACTION_SET_Database_auditing = "Set_Database_auditing"
ACTION_SET_Error_reporting_and_logging_configuration = "Set_Error_reporting_and_logging_configuration"
ACTION_SET_Backup_configuration = "Set_Backup_configuration"
ACTION_SET_Runtime_environment_configuration = "Set_Runtime_environment_configuration"
ACTION_SET_Other_configurations = "Set_Other_configurations"

#############################################################################
# Global variables
#############################################################################
netWorkLevel = 10000
expectMTUValue = 8192
expectRXValue = 4096
expectTXValue = 4096
MASTER_INSTANCE = 0
STANDBY_INSTANCE = 1

g_logger = None
g_opts = None
g_clusterInfo = None
netWorkBondInfo = None
g_readlist = None


#############################################################################
def getValueFromFile(key):
    """
    function : Get value from file
    input  : String
    output : String
    """
    file_path = os.path.join(os.environ['PGDATA'], 'postgresql.conf')
    with open(file_path, 'r') as file:
        for line in file:
            if line.startswith(key) or line.startswith('#' + key):
                return line.split('=')[1].split('#')[0].strip()
    return None


###########################################################################
# User Info:
###########################################################################
class UserInfo:
    """
    Class: userInfo
    """

    def __init__(self):
        """
        function : Init class userInfo
        input  : NA
        output : NA
        """
        self.username = None
        self.groupname = None


def getUserInfo():
    """
    function : Get user info
    input  : NA
    output : Instantion
    """
    data = UserInfo()
    user_id = os.getuid()

    user_info = pwd.getpwuid(user_id)
    data.username = user_info.pw_name
    group_info = grp.getgrgid(user_info.pw_gid)
    data.groupname = group_info.gr_name
    return data


#############################################################################
def extractRowsCount(s):
    """
    function : extract rows count
    input  : String
    output : String
    """
    import re
    match = re.search(r'\((\d+) row[s]*\)$', s)
    if match:
        return int(match.group(1))
    else:
        return None


def extractValues(s):
    """
    function : extract values
    input  : String
    output : String
    """
    lines = s.strip().splitlines()[2:-1]
    return lines


#############################################################################
def getDatabaseInfo(data, sql_query):
    """
    function : Get database info
    input  : Instantion, String
    output : Instantion
    """
    port = int(getValueFromFile('port'))
    cmd = f"gsql -d postgres -p '{port}' -r -c \"{sql_query}\""
    status, output = subprocess.getstatusoutput(cmd)
    if status != 0:
        raise Exception((ErrorCode.GAUSS_505["GAUSS_50502"] % "ConnectionConfiguration") +
                        ("The cmd is : %s" % cmd))
    value = extractRowsCount(output)
    if not value is None:
        data.output = value
        if data.output > 0:
            data.db.extend(extractValues(output))
        else:
            data.db.append("")
    return data


#############################################################################
# monitor IP
#############################################################################
class MonitorIP:
    """
    Class: monitorIP
    """

    def __init__(self):
        """
        function : Init class monitorIP
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectMonitorIP():
    """
    function : Collector monitorIP
    input  : NA
    output : Instantion
    """
    data = MonitorIP()
    data.db = []
    sql_query = """SELECT name,setting FROM pg_settings WHERE name = 'listen_addresses' AND (position('*' in setting) OR position('0.0.0.0' in setting) OR position('::' in setting));"""
    data = getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# ports for Services
#############################################################################
class PortsforServices:
    """
    Class: portsforServices
    """

    def __init__(self):
        """
        function : Init class portsforServices
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectPortsforServices():
    """
    function : Collector PortsforServices
    input  : NA
    output : Instantion
    """
    data = PortsforServices()
    value = getValueFromFile('port')
    data.output = int(value)
    return data


#############################################################################
# connection Configuration
#############################################################################
class ConnectionConfiguration:
    """
    Class: connectionConfiguration
    """

    def __init__(self):
        """
        function : Init class connectionConfiguration
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectConnectionConfiguration():
    """
    function : Collector ConnectionConfiguration
    input  : NA
    output : Instantion
    """
    data = ConnectionConfiguration()
    data.db = []
    sql_query = """show max_connections;"""
    getDatabaseInfo(data, sql_query)
    data.output = int(data.db[0])
    return data


#############################################################################
# DataBase Connection
#############################################################################
class DBConnection:
    """
    Class: DBConnection
    """

    def __init__(self):
        """
        function : Init class DBConnection
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectDBConnection():
    """
    function : Collector Database Configuration
    input  : NA
    output : Instantion
    """
    data = DBConnection()
    data.db = []
    sql_query = """SELECT datname FROM pg_database WHERE datistemplate = false AND datconnlimit = -1;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Admin Connection
#############################################################################
class AdminConnection:
    """
    Class: AdminConnection
    """

    def __init__(self):
        """
        function : Init class AdminConnection
        input  : NA
        output : NA
        """
        self.output = None
        self.maxValue = None
        self.errormsg = None


def collectAdminConnection():
    """
    function : Collector AdminConnection
    input  : NA
    output : Instantion
    """
    data = AdminConnection()
    value = getValueFromFile('sysadmin_reserved_connections')
    maxValue = getValueFromFile('max_connections')
    data.output = int(value)
    data.maxValue = int(maxValue)
    return data


#############################################################################
# User Connection
#############################################################################
class UserConnection:
    """
    Class: UserConnection
    """

    def __init__(self):
        """
        function : Init class UserConnection
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectUserConnection():
    """
    function : Collector UserConnection
    input  : NA
    output : Instantion
    """
    data = UserConnection()
    data.db = []
    sql_query = """SELECT rolname, rolconnlimit FROM pg_roles WHERE rolname NOT LIKE 'gs_role%' AND rolconnlimit = -1;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# unix socket
#############################################################################
class Unixsocket:
    """
    Class: unixsocket
    """

    def __init__(self):
        """
        function : Init class unixsocket
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectUnixsocket():
    """
    function : Collector Unixsocket
    input  : NA
    output : Instantion
    """
    data = Unixsocket()
    value = getValueFromFile('unix_socket_permissions')
    data.output = value
    return data


#############################################################################
# md5 Host
#############################################################################
class Md5Host:
    """
    Class: md5Host
    """

    def __init__(self):
        """
        function : Init class md5Host
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectMD5Host():
    """
    function : Collector md5Host
    input  : NA
    output : Instantion
    """
    data = Md5Host()
    cmd = f"grep -P '^[^#]*host(ssl|nossl)?\\s+.+(?:MD5|md5)\\s*$' {os.getenv('PGDATA')}/pg_hba.conf"
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# host no ssl
#############################################################################
class Hostnossl:
    """
    Class: hostnossl
    """

    def __init__(self):
        """
        function : Init class hostnossl
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectHostnossl():
    """
    function : Collector Hostnossl
    input  : NA
    output : Instantion
    """
    data = Hostnossl()
    cmd = "grep -P '^[^#]*hostnossl' ${PGDATA}/pg_hba.conf"
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# host no all
#############################################################################
class Hostnoall:
    """
    Class: hostnossl
    """

    def __init__(self):
        """
        function : Init class hostnoall
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectHostnoall():
    """
    function : Collector Hostnoall
    input  : NA
    output : Instantion
    """
    data = Hostnoall()
    cmd = "grep -P '^[^#]*host(ssl|nossl)?\s+[Aa][Ll][Ll]' ${PGDATA}/pg_hba.conf"
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# host Address no 0.0.0.0/0
#############################################################################
class HostAddressno0:
    """
    Class: hostAddressno0
    """

    def __init__(self):
        """
        function : Init class hostAddressno0
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectHostAddressno0():
    """
    function : Collector Hostnoall
    input  : NA
    output : Instantion
    """
    data = HostAddressno0()
    cmd = "grep '0.0.0.0/0' ${PGDATA}/pg_hba.conf"
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# ssl Connection
#############################################################################
class SslConnection:
    """
    Class: sslConnection
    """

    def __init__(self):
        """
        function : Init class sslConnection
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectSSLConnection():
    """
    function : Collector SSLConnection
    input  : NA
    output : Instantion
    """
    data = SslConnection()
    value = getValueFromFile('ssl')
    data.output = value
    return data


#############################################################################
# I/O min Home
#############################################################################
class MinHome:
    """
    Class: minHome
    """

    def __init__(self):
        """
        function : Init class minHome
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectMinHome():
    """
    function : Collector minHome
    input  : NA
    output : Instantion
    """
    data = MinHome()
    user = getUserInfo()
    GAUSSUSER = user.username
    GAUSSGROUP = user.groupname
    cmd = f"find -L {os.getenv('GAUSSHOME')} -prune \( ! -user {GAUSSUSER} -o ! -group {GAUSSGROUP} -o -perm /g=rwx,o=rwx \)"
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# min Share
#############################################################################
class MinShare:
    """
    Class: minShare
    """

    def __init__(self):
        """
        function : Init class minShare
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectMinShare():
    """
    function : Collector MinShare
    input  : NA
    output : Instantion
    """
    data = MinShare()
    cmd = "find ${GAUSSHOME}/share -prune -type d \( -perm -g=w -o -perm -o=w \) -exec ls -ld {} \;"
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# min Bin
#############################################################################
class MinBin:
    """
    Class: minBin
    """

    def __init__(self):
        """
        function : Init class minBin
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectMinBin():
    """
    function : Collector MinBin
    input  : NA
    output : Instantion
    """
    data = MinBin()
    cmd = "find ${GAUSSHOME}/bin -prune -perm /g=rwx,o=rwx"
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# min Data
#############################################################################
class MinData:
    """
    Class: minData
    """

    def __init__(self):
        """
        function : Init class minData
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectMinData():
    """
    function : Collector MinData
    input  : NA
    output : Instantion
    """
    data = MinData()
    user = getUserInfo()
    GAUSSUSER = user.username
    GAUSSGROUP = user.groupname
    cmd = f"find {os.getenv('PGDATA')} -prune \( ! -user {GAUSSUSER} -o ! -group {GAUSSGROUP} -o -perm /g=rwx,o=rwx \)"
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# min Archive
#############################################################################
class MinArchive:
    """
    Class: minArchive
    """

    def __init__(self):
        """
        function : Init class minArchive
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectMinArchive():
    """
    function : Collector MinArchive
    input  : NA
    output : Instantion
    """
    data = MinArchive()
    user = getUserInfo()
    GAUSSUSER = user.username
    GAUSSGROUP = user.groupname
    cmd = f"find {os.getenv('GAUSSHOME')}/archive -prune \( ! -user {GAUSSUSER} -o ! -group {GAUSSGROUP} -o -perm /g=rwx,o=rwx \)"
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# min postgres configuration
#############################################################################
class MinPGConf:
    """
    Class: minPGConf
    """

    def __init__(self):
        """
        function : Init class minPGConf
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectMinPGConf():
    """
    function : Collector MinPGConf
    input  : NA
    output : Instantion
    """
    data = MinPGConf()
    user = getUserInfo()
    GAUSSUSER = user.username
    GAUSSGROUP = user.groupname
    cmd = f"find {os.getenv('PGDATA')}/postgresql.conf \( ! -user {GAUSSUSER} -o ! -group {GAUSSGROUP} -o -perm /u=x,g=rwx,o=rwx \)"
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# min pg_hba configuration
#############################################################################
class MinPGHbaConf:
    """
    Class: minPGHbaConf
    """

    def __init__(self):
        """
        function : Init class minPGHbaConf
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectMinPGHbaConf():
    """
    function : Collector MinPGHbaConf
    input  : NA
    output : Instantion
    """
    data = MinPGHbaConf()
    user = getUserInfo()
    GAUSSUSER = user.username
    GAUSSGROUP = user.groupname
    cmd = f"find {os.getenv('PGDATA')}/pg_hba.conf \( ! -user {GAUSSUSER} -o ! -group {GAUSSGROUP} -o -perm /u=x,g=rwx,o=rwx \)"
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# min pg log
#############################################################################
class MinPGLog:
    """
    Class: minPGLog
    """

    def __init__(self):
        """
        function : Init class minPGLog
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectMinPGLog():
    """
    function : Collector MinPGLog
    input  : NA
    output : Instantion
    """
    data = MinPGLog()
    user = getUserInfo()
    GAUSSUSER = user.username
    GAUSSGROUP = user.groupname
    cmd = f"find {os.getenv('GAUSSHOME')}/log/{GAUSSUSER} -prune \( ! -user {GAUSSUSER} -o ! -group {GAUSSGROUP} -o -perm /g=rwx,o=rwx \)"
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# min Client AuthTime
#############################################################################
class ClientAuthTime:
    """
    Class: ClientAuthTime
    """

    def __init__(self):
        """
        function : Init class ClientAuthTime
        input  : NA
        output : NA
        """
        self.output = None
        self.errormsg = None


def collectClientAuthTime():
    """
    function : Collector ClientAuthTime
    input  : NA
    output : Instantion
    """
    data = ClientAuthTime()
    value = getValueFromFile('authentication_timeout')
    data.output = value
    return data


#############################################################################
# min Auth Encription Count
#############################################################################
class AuthEncriptionCount:
    """
    Class: AuthEncriptionCount
    """

    def __init__(self):
        """
        function : Init class AuthEncriptionCount
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAuthEncriptionCount():
    """
    function : Collector AuthEncriptionCount
    input  : NA
    output : Instantion
    """
    data = AuthEncriptionCount()
    data.db = []
    sql_query = """show auth_iteration_count;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# min Failed Login Count
#############################################################################
class FailedLoginCount:
    """
    Class: FailedLoginCount
    """

    def __init__(self):
        """
        function : Init class FailedLoginCount
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectFailedLoginCount():
    """
    function : Collector FailedLoginCount
    input  : NA
    output : Instantion
    """
    data = FailedLoginCount()
    data.db = []
    sql_query = """show failed_login_attempts;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Password Complexity Validation
#############################################################################
class PasswordComplexityValidation:
    """
    Class: PasswordComplexityValidation
    """

    def __init__(self):
        """
        function : Init class PasswordComplexityValidation
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectPasswordComplexityValidation():
    """
    function : Collector PasswordComplexityValidation
    input  : NA
    output : Instantion
    """
    data = PasswordComplexityValidation()
    data.db = []
    sql_query = """show password_policy;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Password Encryption Type
#############################################################################
class PasswordEncryptionType:
    """
    Class: PasswordEncryptionType
    """

    def __init__(self):
        """
        function : Init class PasswordEncryptionType
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectPasswordEncryptionType():
    """
    function : Collector PasswordEncryptionType
    input  : NA
    output : Instantion
    """
    data = PasswordEncryptionType()
    data.db = []
    sql_query = """show password_encryption_type;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Password Reuse Time
#############################################################################
class PasswordReuseTime:
    """
    Class: PasswordReuseTime
    """

    def __init__(self):
        """
        function : Init class PasswordReuseTime
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectPasswordReuseTime():
    """
    function : Collector PasswordReuseTime
    input  : NA
    output : Instantion
    """
    data = PasswordReuseTime()
    data.db = []
    sql_query = """show password_reuse_time;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Password Lock Time
#############################################################################
class PasswordLockTime:
    """
    Class: PasswordLockTime
    """

    def __init__(self):
        """
        function : Init class PasswordLockTime
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectPasswordLockTime():
    """
    function : Collector PasswordLockTime
    input  : NA
    output : Instantion
    """
    data = PasswordLockTime()
    data.db = []
    sql_query = """show password_lock_time;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Rol Password
#############################################################################
class RolPassword:
    """
    Class: RolPassword
    """

    def __init__(self):
        """
        function : Init class RolPassword
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectRolPassword():
    """
    function : Collector RolPassword
    input  : NA
    output : Instantion
    """
    data = RolPassword()
    data.db = []
    sql_query = """SELECT rolpassword FROM pg_authid WHERE rolsuper=true;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Rol valid
#############################################################################
class RolValid:
    """
    Class: RolValid
    """

    def __init__(self):
        """
        function : Init class RolValid
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectRolValid():
    """
    function : Collector RolValid
    input  : NA
    output : Instantion
    """
    data = RolValid()
    data.db = []
    sql_query = """SELECT rolname, rolvalidbegin, rolvaliduntil FROM pg_roles WHERE rolsuper=false AND rolname NOT LIKE 'gs_role%' AND (rolvalidbegin IS NULL OR rolvaliduntil IS NULL);"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Password Effect Time
#############################################################################
class PasswordEffectTime:
    """
    Class: PasswordEffectTime
    """

    def __init__(self):
        """
        function : Init class PasswordEffectTime
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectPasswordEffectTime():
    """
    function : Collector PasswordEffectTime
    input  : NA
    output : Instantion
    """
    data = PasswordEffectTime()
    data.db = []
    sql_query = """show password_effect_time;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Public Rol PG Authid
#############################################################################
class PublicRolPGAuthid:
    """
    Class: PublicRolPGAuthid
    """

    def __init__(self):
        """
        function : Init class PublicRolPGAuthid
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectPublicRolPGAuthid():
    """
    function : Collector PublicRolPGAuthid
    input  : NA
    output : Instantion
    """
    data = PublicRolPGAuthid()
    data.db = []
    sql_query = """SELECT relname,relacl FROM pg_class WHERE relname = 'pg_authid' AND CAST(relacl AS TEXT) LIKE '%,=%}';"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Public Rol Create Perm
#############################################################################
class PublicRolCreatePerm:
    """
    Class: PublicRolCreatePerm
    """

    def __init__(self):
        """
        function : Init class PublicRolCreatePerm
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectPublicRolCreatePerm():
    """
    function : Collector PublicRolCreatePerm
    input  : NA
    output : Instantion
    """
    data = PublicRolCreatePerm()
    data.db = []
    sql_query = """SELECT CAST(has_schema_privilege('public','public','CREATE') AS TEXT);"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Public Rol All Perm
#############################################################################
class PublicRolAllPerm:
    """
    Class: PublicRolAllPerm
    """

    def __init__(self):
        """
        function : Init class PublicRolAllPerm
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectPublicRolAllPerm():
    """
    function : Collector PublicRolAllPerm
    input  : NA
    output : Instantion
    """
    data = []
    data_table = PublicRolAllPerm()
    data_table.db = []
    sql_query_table = """SELECT relname,relacl FROM pg_class WHERE (CAST(relacl AS TEXT) LIKE '%,=arwdDxt/%}' OR CAST(relacl AS TEXT) LIKE '{=arwdDxt/%}') AND (CAST(relacl AS TEXT) LIKE '%,=APmiv/%}' OR CAST(relacl AS TEXT) LIKE '{=APmiv/%}');"""
    getDatabaseInfo(data_table, sql_query_table)
    data.append(data_table)
    data_schema = PublicRolAllPerm()
    data_schema.db = []
    sql_query_schema = """SELECT nspname,nspacl FROM pg_namespace WHERE (CAST(nspacl AS TEXT) LIKE '%,=UC/%}' OR CAST(nspacl AS TEXT) LIKE '{=UC/%}') AND (CAST(nspacl AS TEXT) LIKE '%,=APm/%}' OR CAST(nspacl AS TEXT) LIKE '{=APm/%}');"""
    getDatabaseInfo(data_schema, sql_query_schema)
    data.append(data_schema)
    data_function = PublicRolAllPerm()
    data_function.db = []
    sql_query_function = """SELECT proname,proacl FROM pg_proc WHERE (CAST(proacl AS TEXT) LIKE '%,=X/%}' OR CAST(proacl AS TEXT) LIKE '{=X/%}') AND (CAST(proacl AS TEXT) LIKE '%,=APm/%}' OR CAST(proacl AS TEXT) LIKE '{=APm/%}');"""
    getDatabaseInfo(data_function, sql_query_function)
    data.append(data_function)
    return data


#############################################################################
# Admin Privileges
#############################################################################
class AdminPrivileges:
    """
    Class: AdminPrivileges
    """

    def __init__(self):
        """
        function : Init class AdminPrivileges
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAdminPrivileges():
    """
    function : Collector AdminPrivileges
    input  : NA
    output : Instantion
    """
    data = []
    data_createrole = AdminPrivileges()
    data_createrole.db = []
    sql_query_createrole = """SELECT rolname FROM pg_roles WHERE rolcreaterole = true AND rolsuper = false;"""
    getDatabaseInfo(data_createrole, sql_query_createrole)
    data.append(data_createrole)
    data_createdb = AdminPrivileges()
    data_createdb.db = []
    sql_query_createdb = """SELECT rolname FROM pg_roles WHERE rolcreatedb = true AND rolsuper = false;"""
    getDatabaseInfo(data_createdb, sql_query_createdb)
    data.append(data_createdb)
    data_auditadmin = AdminPrivileges()
    data_auditadmin.db = []
    sql_query_auditadmin = """SELECT rolname FROM pg_roles WHERE rolauditadmin = true AND rolsuper = false;"""
    getDatabaseInfo(data_auditadmin, sql_query_auditadmin)
    data.append(data_auditadmin)
    data_monitoradmin = AdminPrivileges()
    data_monitoradmin.db = []
    sql_query_monitoradmin = """SELECT rolname FROM pg_roles WHERE rolmonitoradmin = true AND rolsuper = false;"""
    getDatabaseInfo(data_monitoradmin, sql_query_monitoradmin)
    data.append(data_monitoradmin)
    data_peratoradmin = AdminPrivileges()
    data_peratoradmin.db = []
    sql_query_peratoradmin = """SELECT rolname FROM pg_roles WHERE roloperatoradmin = true AND rolsuper = false;"""
    getDatabaseInfo(data_peratoradmin, sql_query_peratoradmin)
    data.append(data_peratoradmin)
    data_policyadmin = AdminPrivileges()
    data_policyadmin.db = []
    sql_query_policyadmin = """SELECT rolname FROM pg_roles WHERE rolpolicyadmin = true AND rolsuper = false;"""
    getDatabaseInfo(data_policyadmin, sql_query_policyadmin)
    data.append(data_policyadmin)
    return data


#############################################################################
# Enable Separation Of Duty
#############################################################################
class EnableSeparationOfDuty:
    """
    Class: EnableSeparationOfDuty
    """

    def __init__(self):
        """
        function : Init class EnableSeparationOfDuty
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectEnableSeparationOfDuty():
    """
    function : Collector EnableSeparationOfDuty
    input  : NA
    output : Instantion
    """
    data = EnableSeparationOfDuty()
    data.db = []
    sql_query = """show enableSeparationOfDuty;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Enable Copy Server Files
#############################################################################
class EnableCopyServerFiles:
    """
    Class: EnableCopyServerFiles
    """

    def __init__(self):
        """
        function : Init class EnableCopyServerFiles
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectEnableCopyServerFiles():
    """
    function : Collector EnableCopyServerFiles
    input  : NA
    output : Instantion
    """
    data = EnableCopyServerFiles()
    data.db = []
    sql_query = """show enable_copy_server_files;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Audit Enabled
#############################################################################
class AuditEnabled:
    """
    Class: AuditEnabled
    """

    def __init__(self):
        """
        function : Init class AuditEnabled
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAuditEnabled():
    """
    function : Collector AuditEnabled
    input  : NA
    output : Instantion
    """
    data = AuditEnabled()
    data.db = []
    sql_query = """show audit_enabled;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Audit Login Logout
#############################################################################
class AuditLoginLogout:
    """
    Class: AuditLoginLogout
    """

    def __init__(self):
        """
        function : Init class AuditLoginLogout
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAuditLoginLogout():
    """
    function : Collector AuditLoginLogout
    input  : NA
    output : Instantion
    """
    data = AuditLoginLogout()
    data.db = []
    sql_query = """show audit_login_logout;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Audit Database Process
#############################################################################
class AuditDatabaseProcess:
    """
    Class: AuditDatabaseProcess
    """

    def __init__(self):
        """
        function : Init class AuditDatabaseProcess
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAuditDatabaseProcess():
    """
    function : Collector AuditDatabaseProcess
    input  : NA
    output : Instantion
    """
    data = AuditDatabaseProcess()
    data.db = []
    sql_query = """show audit_database_process;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Audit User Locked
#############################################################################
class AuditUserLocked:
    """
    Class: AuditUserLocked
    """

    def __init__(self):
        """
        function : Init class AuditUserLocked
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAuditUserLocked():
    """
    function : Collector AuditUserLocked
    input  : NA
    output : Instantion
    """
    data = AuditUserLocked()
    data.db = []
    sql_query = """show audit_user_locked;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Audit Grant Revoke
#############################################################################
class AuditGrantRevoke:
    """
    Class: AuditGrantRevoke
    """

    def __init__(self):
        """
        function : Init class AuditGrantRevoke
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAuditGrantRevoke():
    """
    function : Collector AuditGrantRevoke
    input  : NA
    output : Instantion
    """
    data = AuditGrantRevoke()
    data.db = []
    sql_query = """show audit_grant_revoke;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Audit System Object
#############################################################################
class AuditSystemObject:
    """
    Class: AuditSystemObject
    """

    def __init__(self):
        """
        function : Init class AuditSystemObject
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAuditSystemObject():
    """
    function : Collector AuditSystemObject
    input  : NA
    output : Instantion
    """
    data = AuditSystemObject()
    data.db = []
    sql_query = """show audit_system_object;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Audit Dml State Select
#############################################################################
class AuditDmlStateSelect:
    """
    Class: AuditDmlStateSelect
    """

    def __init__(self):
        """
        function : Init class AuditDmlStateSelect
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAuditDmlStateSelect():
    """
    function : Collector AuditDmlStateSelect
    input  : NA
    output : Instantion
    """
    data = AuditDmlStateSelect()
    data.db = []
    sql_query = """show audit_dml_state_select;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Audit Resource Policy
#############################################################################
class AuditResourcePolicy:
    """
    Class: AuditResourcePolicy
    """

    def __init__(self):
        """
        function : Init class AuditResourcePolicy
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAuditResourcePolicy():
    """
    function : Collector AuditResourcePolicy
    input  : NA
    output : Instantion
    """
    data = AuditResourcePolicy()
    data.db = []
    sql_query = """show audit_resource_policy;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Audit Rotation Interval
#############################################################################
class AuditRotationInterval:
    """
    Class: AuditRotationInterval
    """

    def __init__(self):
        """
        function : Init class AuditRotationInterval
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAuditRotationInterval():
    """
    function : Collector AuditRotationInterval
    input  : NA
    output : Instantion
    """
    data = AuditRotationInterval()
    data.db = []
    sql_query = """show audit_rotation_interval;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Audit Rotation Size
#############################################################################
class AuditRotationSize:
    """
    Class: AuditRotationSize
    """

    def __init__(self):
        """
        function : Init class AuditRotationSize
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAuditRotationSize():
    """
    function : Collector AuditRotationSize
    input  : NA
    output : Instantion
    """
    data = AuditRotationSize()
    data.db = []
    sql_query = """show audit_rotation_size;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Audit Space Limit
#############################################################################
class AuditSpaceLimit:
    """
    Class: AuditSpaceLimit
    """

    def __init__(self):
        """
        function : Init class AuditSpaceLimit
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAuditSpaceLimit():
    """
    function : Collector AuditSpaceLimit
    input  : NA
    output : Instantion
    """
    data = AuditSpaceLimit()
    data.db = []
    sql_query = """show audit_space_limit;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Audit File Remain Threshold
#############################################################################
class AuditFileRemainThreshold:
    """
    Class: AuditFileRemainThreshold
    """

    def __init__(self):
        """
        function : Init class AuditFileRemainThreshold
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAuditFileRemainThreshold():
    """
    function : Collector AuditFileRemainThreshold
    input  : NA
    output : Instantion
    """
    data = AuditFileRemainThreshold()
    data.db = []
    sql_query = """show audit_file_remain_threshold;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Logging Collector
#############################################################################
class LoggingCollector:
    """
    Class: LoggingCollector
    """

    def __init__(self):
        """
        function : Init class LoggingCollector
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectLoggingCollector():
    """
    function : Collector LoggingCollector
    input  : NA
    output : Instantion
    """
    data = LoggingCollector()
    data.db = []
    sql_query = """show logging_collector;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Log Filename
#############################################################################
class LogFilename:
    """
    Class: LogFilename
    """

    def __init__(self):
        """
        function : Init class LogFilename
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectLogFilename():
    """
    function : Collector LogFilename
    input  : NA
    output : Instantion
    """
    data = LogFilename()
    data.db = []
    sql_query = """show log_filename;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Log Filename
#############################################################################
class LogFileMode:
    """
    Class: LogFileMode
    """

    def __init__(self):
        """
        function : Init class LogFileMode
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectLogFileMode():
    """
    function : Collector LogFileMode
    input  : NA
    output : Instantion
    """
    data = LogFileMode()
    data.db = []
    sql_query = """show log_file_mode;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Log Truncate On Rotation
#############################################################################
class LogTruncateOnRotation:
    """
    Class: LogTruncateOnRotation
    """

    def __init__(self):
        """
        function : Init class LogTruncateOnRotation
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectLogTruncateOnRotation():
    """
    function : Collector LogTruncateOnRotation
    input  : NA
    output : Instantion
    """
    data = LogTruncateOnRotation()
    data.db = []
    sql_query = """show log_truncate_on_rotation;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Log Rotation Age
#############################################################################
class LogRotationAge:
    """
    Class: LogRotationAge
    """

    def __init__(self):
        """
        function : Init class LogRotationAge
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectLogRotationAge():
    """
    function : Collector LogRotationAge
    input  : NA
    output : Instantion
    """
    data = LogRotationAge()
    data.db = []
    sql_query = """show log_rotation_age;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Log Rotation Size
#############################################################################
class LogRotationSize:
    """
    Class: LogRotationSize
    """

    def __init__(self):
        """
        function : Init class LogRotationSize
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectLogRotationSize():
    """
    function : Collector LogRotationSize
    input  : NA
    output : Instantion
    """
    data = LogRotationSize()
    data.db = []
    sql_query = """show log_rotation_size;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Client Min Messages
#############################################################################
class ClientMinMessages:
    """
    Class: ClientMinMessages
    """

    def __init__(self):
        """
        function : Init class ClientMinMessages
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectClientMinMessages():
    """
    function : Collector ClientMinMessages
    input  : NA
    output : Instantion
    """
    data = ClientMinMessages()
    data.db = []
    sql_query = """show client_min_messages;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Log Min Messages
#############################################################################
class LogMinMessages:
    """
    Class: LogMinMessages
    """

    def __init__(self):
        """
        function : Init class LogMinMessages
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectLogMinMessages():
    """
    function : Collector LogMinMessages
    input  : NA
    output : Instantion
    """
    data = LogMinMessages()
    data.db = []
    sql_query = """show log_min_messages;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Log Min ErrorStatement
#############################################################################
class LogMinErrorStatement:
    """
    Class: LogMinErrorStatement
    """

    def __init__(self):
        """
        function : Init class LogMinErrorStatement
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectLogMinErrorStatement():
    """
    function : Collector LogMinErrorStatement
    input  : NA
    output : Instantion
    """
    data = LogMinErrorStatement()
    data.db = []
    sql_query = """show log_min_error_statement;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Log Connections
#############################################################################
class LogConnections:
    """
    Class: LogConnections
    """

    def __init__(self):
        """
        function : Init class LogConnections
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectLogConnections():
    """
    function : Collector LogConnections
    input  : NA
    output : Instantion
    """
    data = LogConnections()
    data.db = []
    sql_query = """show log_connections;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Log Disconnections
#############################################################################
class LogDisconnections:
    """
    Class: LogDisconnections
    """

    def __init__(self):
        """
        function : Init class LogDisconnections
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectLogDisconnections():
    """
    function : Collector LogDisconnections
    input  : NA
    output : Instantion
    """
    data = LogDisconnections()
    data.db = []
    sql_query = """show log_disconnections;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Log Error Verbosity
#############################################################################
class LogErrorVerbosity:
    """
    Class: LogErrorVerbosity
    """

    def __init__(self):
        """
        function : Init class LogErrorVerbosity
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectLogErrorVerbosity():
    """
    function : Collector LogErrorVerbosity
    input  : NA
    output : Instantion
    """
    data = LogErrorVerbosity()
    data.db = []
    sql_query = """show log_error_verbosity;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Log Hostname
#############################################################################
class LogHostname:
    """
    Class: LogHostname
    """

    def __init__(self):
        """
        function : Init class LogHostname
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectLogHostname():
    """
    function : Collector LogHostname
    input  : NA
    output : Instantion
    """
    data = LogHostname()
    data.db = []
    sql_query = """show log_hostname;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Debug PrintParse
#############################################################################
class DebugPrintParse:
    """
    Class: DebugPrintParse
    """

    def __init__(self):
        """
        function : Init class DebugPrintParse
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectDebugPrintParse():
    """
    function : Collector DebugPrintParse
    input  : NA
    output : Instantion
    """
    data = DebugPrintParse()
    data.db = []
    sql_query = """show debug_print_parse;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Debug PrintPlan
#############################################################################
class DebugPrintPlan:
    """
    Class: DebugPrintPlan
    """

    def __init__(self):
        """
        function : Init class DebugPrintPlan
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectDebugPrintPlan():
    """
    function : Collector DebugPrintPlan
    input  : NA
    output : Instantion
    """
    data = DebugPrintPlan()
    data.db = []
    sql_query = """show debug_print_plan;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Debug Print Rewritten
#############################################################################
class DebugPrintRewritten:
    """
    Class: DebugPrintRewritten
    """

    def __init__(self):
        """
        function : Init class DebugPrintRewritten
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectDebugPrintRewritten():
    """
    function : Collector DebugPrintRewritten
    input  : NA
    output : Instantion
    """
    data = DebugPrintRewritten()
    data.db = []
    sql_query = """show debug_print_rewritten;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# WalLevel
#############################################################################
class WalLevel:
    """
    Class: WalLevel
    """

    def __init__(self):
        """
        function : Init class WalLevel
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectWalLevel():
    """
    function : Collector WalLevel
    input  : NA
    output : Instantion
    """
    data = WalLevel()
    data.db = []
    sql_query = """show wal_level;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# ArchiveMode
#############################################################################
class ArchiveMode:
    """
    Class: ArchiveMode
    """

    def __init__(self):
        """
        function : Init class ArchiveMode
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectArchiveMode():
    """
    function : Collector ArchiveMode
    input  : NA
    output : Instantion
    """
    data = ArchiveMode()
    data.db = []
    sql_query_wal = """show wal_level;"""
    getDatabaseInfo(data, sql_query_wal)
    sql_query_archive = """show archive_mode;"""
    getDatabaseInfo(data, sql_query_archive)
    return data


#############################################################################
# Umask
#############################################################################
class Umask:
    """
    Class: Umask
    """

    def __init__(self):
        """
        function : Init class Umask
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectUmask():
    """
    function : Collector Umask
    input  : NA
    output : Instantion
    """
    data = Umask()
    cmd = "umask"
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# Hidepid
#############################################################################
class Hidepid:
    """
    Class: Hidepid
    """

    def __init__(self):
        """
        function : Init class Hidepid
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectHidepid():
    """
    function : Collector Hidepid
    input  : NA
    output : Instantion
    """
    data = Hidepid()
    cmd = 'mount | grep "proc on /proc" | grep hidepid'
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# Ntpd
#############################################################################
class Ntpd:
    """
    Class: Ntpd
    """

    def __init__(self):
        """
        function : Init class Ntpd
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectNtpd():
    """
    function : Collector Ntpd
    input  : NA
    output : Instantion
    """
    data = Ntpd()
    cmd = 'service ntpd status 2>&1 | grep Active'
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if result.returncode == 0:
        data.output = result.stdout
    else:
        data.errormsg = result.stderr
    return data


#############################################################################
# Backslash Quote
#############################################################################
class BackslashQuote:
    """
    Class: BackslashQuote
    """

    def __init__(self):
        """
        function : Init class BackslashQuote
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectBackslashQuote():
    """
    function : Collector BackslashQuote
    input  : NA
    output : Instantion
    """
    data = BackslashQuote()
    data.db = []
    sql_query = """show backslash_quote;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
# Allow System Table Mods
#############################################################################
class AllowSystemTableMods:
    """
    Class: AllowSystemTableMods
    """

    def __init__(self):
        """
        function : Init class AllowSystemTableMods
        input  : NA
        output : NA
        """
        self.output = None
        self.db = None
        self.errormsg = None


def collectAllowSystemTableMods():
    """
    function : Collector AllowSystemTableMods
    input  : NA
    output : Instantion
    """
    data = AllowSystemTableMods()
    data.db = []
    sql_query = """show allow_system_table_mods;"""
    getDatabaseInfo(data, sql_query)
    return data


#############################################################################
def checkConnection(isSetting=False):
    """
    function : Check Connection
    input  : Bool
    output : NA
    """
    checkMonitorIP(isSetting)
    checkPortsforServices()
    checkConnectionConfiguration(isSetting)
    checkDBConnection(isSetting)
    checkAdminConnection(isSetting)
    checkUserConnection(isSetting)
    checkUnixsocket(isSetting)
    checkMD5Host()
    checkHostnossl()
    checkHostnoall()
    checkHostAddressno0()
    checkSSLConnection(isSetting)


def checkMonitorIP(isSetting):
    """
    function : Check MonitorIP
    input  : NA
    output : NA
    """
    data = collectMonitorIP()
    if not (data.output == 0):
        if not isSetting:
            g_logger.log(
                "        Warning reason:Prohibit listening on all IP addresses on the host.Listening to all IP addresses will not achieve network isolation. By prohibiting listening to all IP addresses on the host, malicious connection requests from other networks can be blocked.You should set the parameter listen_addresses to \"localhost\" or the IP address of the network card that needs to receive business requests. Multiple addresses are separated by commas, and then restart the database.")
        else:
            setMonitorIP(data)

def checkPortsforServices():
    """
    function : Check collectPortsforServices
    input  : NA
    output : NA
    """
    data = collectPortsforServices()
    if data.output == 5432:
        g_logger.log("        Warning reason:Ensure external service ports use non-default port numbers.Using default port numbers makes it easy for malicious attackers to access and attack the system. It is necessary to configure the external service port number to a non-default port number.You can specify the port numbers for each instance either through the configuration file during database installation or in the configuration files located in the database data directory.")

def checkConnectionConfiguration(isSetting):
    """
    function : Check connection Configuration
    input  : Bool
    output : NA
    """
    expectedConnection = 5000
    data = collectConnectionConfiguration()
    if (data.output != expectedConnection):
        if not isSetting:
            g_logger.log("        Warning reason:Ensure correct configuration of maximum connection settings for the database instance.Setting parameters too high may cause the database to request more System V shared memory or semaphores, exceeding the values allowed by the operating system's default configuration. Users need to determine the size of parameter values based on business specifications or consult technical support.You can modify the value of the parameter max_connections and then restart the database.")
        else:
            setConnectionConfiguration(data)

def checkDBConnection(isSetting):
    """
    function : Check DataBase connection
    input  : Bool
    output : NA
    """
    data = collectDBConnection()
    if (data.output > 0):
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure the maximum connection settings for the database are configured correctly.Setting the parameter datconnlimit too low will affect the maximum number of concurrent connections to the database. Setting it too high or without any limit may lead to exceeding the system's load capacity due to the number of sessions, thereby impacting the database's availability.")
        else:
            setDBConnection(data)

def checkAdminConnection(isSetting):
    """
    function : Check Admin connection
    input  : Bool
    output : NA
    """
    data = collectAdminConnection()
    if not (data.output < data.maxValue):
        if not isSetting:
            g_logger.log("        Warning reason:Ensure the connection settings used by system administrators are configured correctly.The parameter sysadmin_reserved_connections represents the minimum number of connections reserved for the database system administrator. This ensures that there are dedicated connection channels for the system administrator, preventing connections from being occupied by regular users or malicious users, which could otherwise prevent the administrator from connecting. The value of this parameter must be less than the value of max_connections.")
        else:
            setAdminConnection(data)

def checkUserConnection(isSetting):
    """
    function : Check User connection
    input  : Bool
    output : NA
    """
    data = collectUserConnection()
    if not (data.output == 1):
        if not isSetting:
            g_logger.log("        Warning reason:Ensure the maximum connection settings for users are configured correctly.When the actual number of connections for the current user exceeds the user's maximum connection limit, no new connections can be established.Limiting the maximum number of connections for different users based on business requirements can prevent a single user from monopolizing all connections.")
        else:
            setUserConnection(data)

def checkUnixsocket(isSetting):
    """
    function : Check Unixsocket
    input  : Bool
    output : NA
    """
    data = collectUnixsocket()
    if not (data.output == '0700'):
        if not isSetting:
            g_logger.log("        Warning reason:Ensure correct access permissions are configured for UNIX domain sockets.The recommended configuration is 0700 (only the user currently connected to the database can access it, neither members of the same group nor others have permission), which meets the requirement for minimal file permissions. This prevents files from being accessed or altered by other users, thus safeguarding socket communication functionality.")
        else:
            setUnixsocket(data)

def checkMD5Host():
    """
    function : Check MD5Host
    input  : NA
    output : NA
    """
    data = collectMD5Host()
    if data.output:
        g_logger.log("        Warning reason:Ensure there are no 'host' entries using MD5 authentication.The MD5 authentication method poses security risks and may lead to password cracking. It is advisable to use a more secure authentication method such as SHA256 or certificate-based authentication.")

def checkHostnossl():
    """
    function : Check Hostnossl
    input  : NA
    output : NA
    """
    data = collectHostnossl()
    if data.output:
        g_logger.log("        Warning reason:Ensure there are no 'hostnossl' entries.The 'hostnossl' entry specifies connections that do not use SSL encryption, while the 'host' entry allows both SSL and non-SSL connections. The 'hostssl' entry is restricted to using only SSL connections. From a security standpoint, it is recommended to use SSL encryption for data transmission to prevent information leakage.")

def checkHostnoall():
    """
    function : Check Hostnoall
    input  : NA
    output : NA
    """
    data = collectHostnoall()
    if data.output:
        g_logger.log("        Warning reason:Ensure there are no 'host' entries specifying 'all' for the database.Under the premise of meeting business requirements, it isUnder the premise of meeting business requirements, it isate specific databases for different it is advisable to designate specific databases for different users or client IP addresses to avoid mutual interference between various services.")

def checkHostAddressno0():
    """
    function : Check HostAddressno0
    input  : NA
    output : NA
    """
    data = collectHostAddressno0()
    if data.output:
        g_logger.log(
            "        Warning reason:Ensure there are no 'host' entries specifying the source address as 0.0.0.0/0.Allowing any IP to connect to the database can lead to malicious users launching network attacks, compromising the database's security. It is recommended that the source addresses configured in the 'host' entry should only include the IPs that need to connect to the database.")

def checkSSLConnection(isSetting):
    """
    function : Check SSLConnection
    input  : NA
    output : NA
    """
    data = collectSSLConnection()
    if (data.output == 'off'):
        if not isSetting:
            g_logger.log("        Warning reason:Ensure SSL connections are enabled on the server side.Enabling this parameter also requires ensuring that the ssl_cert_file, ssl_key_file, and ssl_ca_file parameters are correctly configured, and that the SSL certificate permissions are set to 0600. Incorrect configurations may prevent the database from starting normally. Additionally, enabling SSL connections will have some impact on performance.")
        else:
            setSSLConnection(data)


#############################################################################
def setConnection(isSetting=True):
    """
    function : Set Connection
    input  : Boolean
    output : NA
    """
    checkMonitorIP(isSetting)
    checkConnectionConfiguration(isSetting)
    checkDBConnection(isSetting)
    checkAdminConnection(isSetting)
    checkUserConnection(isSetting)
    checkUnixsocket(isSetting)
    checkSSLConnection(isSetting)


def setMonitorIP(data):
    """
    function : Set Monitor IP
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc set -D %s -c \"listen_addresses='localhost'\"" %(os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!',result.stdout):
            g_logger.log("Failed to set Monitor IP")
        cmd_restart = "gs_ctl restart -D %s" %(os.getenv('PGDATA'))
        subprocess.run(cmd_restart, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        data.errormsg = e.__str__()

def setConnectionConfiguration(data):
    """
    function : Set Connection Configuration
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc set -D %s -c \"max_connections=5000\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Connection Configuration.")
        cmd_restart = "gs_ctl restart -D %s" % (os.getenv('PGDATA'))
        subprocess.run(cmd_restart, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        data.errormsg = e.__str__()

def setDBConnection(data):
    """
    function : Set DataBase Connection
    input  : Instantion
    output : NA
    """
    result = collectDBConnection()
    result.db = []
    try:
        for item in data.db:
            sql_query = """UPDATE pg_database SET datconnlimit=1024 WHERE datname='%s';""" %(item.strip())
            getDatabaseInfo(result, sql_query)
    except Exception as e:
        data.errormsg = e.__str__()

def setAdminConnection(data):
    """
    function : Set Admin Connection
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc set -D %s -c \"sysadmin_reserved_connections=3\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Admin Connection")
        cmd_restart = "gs_ctl restart -D %s" % (os.getenv('PGDATA'))
        subprocess.run(cmd_restart, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        data.errormsg = e.__str__()

def setUserConnection(data):
    """
    function : Set User Connection
    input  : Instantion
    output : NA
    """
    result = collectUserConnection()
    result.db = []
    try:
        for item in data.db:
            sql_query = """ALTER ROLE %s CONNECTION LIMIT 1024;""" %(item.split("|")[0].strip())
            getDatabaseInfo(result, sql_query)
    except Exception as e:
        data.errormsg = e.__str__()

def setUnixsocket(data):
    """
    function : Set Unix socket
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc set -D %s -c \"unix_socket_permissions=0700\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Unix socket")
        cmd_restart = "gs_ctl restart -D %s" % (os.getenv('PGDATA'))
        subprocess.run(cmd_restart, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        data.errormsg = e.__str__()

def setSSLConnection(data):
    """
    function : Set SSL Connection
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc set -D %s -c \"ssl=on\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set SSL Connection")
        cmd_restart = "gs_ctl restart -D %s" % (os.getenv('PGDATA'))
        subprocess.run(cmd_restart, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        data.errormsg = e.__str__()


#############################################################################
def checkFileSecurity(isSetting=False):
    """
    function : Check File Security
    input  : Bool
    output : NA
    """
    checkMinHome(isSetting)
    checkMinShare(isSetting)
    checkMinBin(isSetting)
    checkMinData(isSetting)
    checkMinArchive(isSetting)
    checkMinPGConf(isSetting)
    checkMinPGHbaConf(isSetting)
    checkMinPGLog(isSetting)


def checkMinHome(isSetting):
    """
    function : Check MinData
    input  : Bool
    output : NA
    """
    data = collectMinHome()
    if data.output:
        if not isSetting:
            g_logger.log("        Warning reason:Ensure minimal permissions for the database installation directory.To prevent files in the installation directory from being maliciously tampered with or destroyed, this directory should be protected and access should not be allowed for non-database installation users. Proper permission settings can ensure the security of the database system.")
        else:
            setMinHome(data)

def checkMinShare(isSetting):
    """
    function : Check MinShare
    input  : Bool
    output : NA
    """
    data = collectMinShare()
    if data.output:
        if not isSetting:
            g_logger.log("        Warning reason:Ensure minimal permissions for shared directories.To prevent shared components from being maliciously tampered with or destroyed, this directory should be protected and access should not be allowed for non-database installation users.")
        else:
            setMinShare(data)

def checkMinBin(isSetting):
    """
    function : Check MinBin
    input  : Bool
    output : NA
    """
    data = collectMinBin()
    if data.output:
        if not isSetting:
            g_logger.log("        Warning reason:Ensure minimal permissions for binary file directories.To prevent binary files from being maliciously tampered with or destroyed, thereby threatening the security of client information, this directory should be protected and access should not be allowed for non-database installation users.")
        else:
            setMinBin(data)

def checkMinData(isSetting):
    """
    function : Check MinData
    input  : Bool
    output : NA
    """
    data = collectMinData()
    if data.output:
        if not isSetting:
            g_logger.log("        Warning reason:Ensure minimal permissions for data directories.The data directory contains user data files. To prevent these data files from being maliciously tampered with or destroyed, which could threaten the security of client data, this directory should be protected and access should not be allowed for non-database installation users.")
        else:
            setMinData(data)

def checkMinArchive(isSetting):
    """
    function : Check MinArchive
    input  : Bool
    output : NA
    """
    data = collectMinArchive()
    if data.output:
        if not isSetting:
            g_logger.log("        Warning reason:Ensure minimal permissions for log archive directories.When the wal_level parameter is set to 'archive', the directory permissions should be configured to 0700 to ensure that only the database installation user has access.")
        else:
            setMinArchive(data)

def checkMinPGConf(isSetting):
    """
    function : Check MinPGConf
    input  : Bool
    output : NA
    """
    data = collectMinPGConf()
    if data.output:
        if not isSetting:
            g_logger.log("        Warning reason:Ensure minimal permissions for the postgresql.conf file.The configuration file postgresql.conf contains the operational parameters for the database. To prevent malicious tampering with the configuration file, it should be protected and access should not be allowed for non-database installation users.")
        else:
            setMinPGConf(data)

def checkMinPGHbaConf(isSetting):
    """
    function : Check MinPGHbaConf
    input  : Bool
    output : NA
    """
    data = collectMinPGHbaConf()
    if data.output:
        if not isSetting:
            g_logger.log("        Warning reason:Ensure minimal permissions for the pg_hba.conf file.The configuration file pg_hba.conf contains connection information for the database, such as client authentication methods. To prevent malicious tampering with the configuration file, it should be protected and access should only be allowed for the database installation user.")
        else:
            setMinPGHbaConf(data)

def checkMinPGLog(isSetting):
    """
    function : Check MinPGLog
    input  : Bool
    output : NA
    """
    data = collectMinPGLog()
    if data.output:
        if not isSetting:
            g_logger.log("        Warning reason:Ensure minimal permissions for the log directory.The database log directory contains many operational logs, and to prevent these log files from being maliciously tampered with or destroyed, thereby threatening the security of client data, this directory should be protected and access should not be allowed for non-database installation users.")
        else:
            setMinPGLog(data)


#############################################################################
def setFileSecurity(isSetting=True):
    """
    function : Set File Security
    input  : Bool
    output : NA
    """
    checkMinHome(isSetting)
    checkMinShare(isSetting)
    checkMinBin(isSetting)
    checkMinData(isSetting)
    checkMinArchive(isSetting)
    checkMinPGConf(isSetting)
    checkMinPGHbaConf(isSetting)
    checkMinPGLog(isSetting)


def setMinHome(data):
    """
    function : Set Min Home
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "chmod 0700 %s" % (os.getenv('GAUSSHOME'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        g_logger.log("Failed to set Min Home")
        data.errormsg = e.__str__()

def setMinShare(data):
    """
    function : Set Min Share
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "chmod 0700 %s/share" % (os.getenv('GAUSSHOME'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        g_logger.log("Failed to set Min Share")
        data.errormsg = e.__str__()

def setMinBin(data):
    """
    function : Set Min Bin
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "chmod 0700 %s/bin" % (os.getenv('GAUSSHOME'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        g_logger.log("Failed to set Min Bin")
        data.errormsg = e.__str__()

def setMinData(data):
    """
    function : Set Min Data
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "chmod 0700 %s" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        g_logger.log("Failed to set Min Data")
        data.errormsg = e.__str__()

def setMinArchive(data):
    """
    function : Set Min Archive
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "chmod 0700 %s/archive" % (os.getenv('GAUSSHOME'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        g_logger.log("Failed to set Min Archive")
        data.errormsg = e.__str__()

def setMinPGConf(data):
    """
    function : Set Min PGConf
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "chmod 0600 %s/postgresql.conf" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        g_logger.log("Failed to set Min Data")
        data.errormsg = e.__str__()

def setMinPGHbaConf(data):
    """
    function : Set Min PGHbaConf
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "chmod 0600 %s/pg_hba.conf" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        g_logger.log("Failed to set Min Data")
        data.errormsg = e.__str__()

def setMinPGLog(data):
    """
    function : Set Min PGLog
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "chmod 0700 %s/pg_log" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        g_logger.log("Failed to set Min Data")
        data.errormsg = e.__str__()


#############################################################################
def checkSecurityAuthConf(isSetting=False):
    """
    function : Check Security Auth Conf
    input  : Bool
    output : NA
    """
    checkClientAuthTime(isSetting)
    checkAuthEncriptionCount(isSetting)
    checkFailedLoginCount(isSetting)


def checkClientAuthTime(isSetting):
    """
    function : Check ClientAuthTime
    input  : Bool
    output : NA
    """
    data = collectClientAuthTime()
    if not data.output == '1min':
        if not isSetting:
            g_logger.log("        Warning reason: Ensure correct client authentication timeout configuration.The default timeout is recommended to be set to 1 minute. If a client does not complete authentication with the server within the parameter-set time, the server automatically disconnects from the client. This prevents problematic clients from indefinitely occupying connection slots.Setting the parameter value too low may lead to authentication failures due to timeouts.")
        else:
            setClientAuthTime(data)

def checkAuthEncriptionCount(isSetting):
    """
    function : Check AuthEncriptionCount
    input  : Bool
    output : NA
    """
    data = collectAuthEncriptionCount()
    if not int(data.db[0]) == 10000:
        if not isSetting:
            g_logger.log("        Warning reason: Ensure correct configuration of authentication encryption iteration counts.Setting the number of iterations too low will reduce the security of password storage, while setting it too high can degrade performance in scenarios involving password encryption, such as user creation and authentication. Please set the number of iterations reasonably according to actual hardware conditions, with a minimum of 10,000 iterations.")
        else:
            setAuthEncriptionCount(data)

def checkFailedLoginCount(isSetting):
    """
    function : Check FailedLoginCount
    input  : Bool
    output : NA
    """
    data = collectFailedLoginCount()
    if not int(data.db[0]) == 10:
        if not isSetting:
            g_logger.log("        Warning reason: Ensure correct configuration of account login failure attempt counts.Configuring the number of failed login attempts through the parameter 'failed_login_attempts' can prevent passwords from being cracked by brute force.When the number of consecutive authentication failures exceeds this parameter value, the account will be automatically locked.")
        else:
            setFailedLoginCount(data)


#############################################################################
def setSecurityAuthenticationConfiguration(isSetting=True):
    """
    function : Set Security Authentication Configuration
    input  : Bool
    output : NA
    """
    checkClientAuthTime(isSetting)
    checkAuthEncriptionCount(isSetting)
    checkFailedLoginCount(isSetting)


def setClientAuthTime(data):
    """
    function : Set Client AuthTime
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"authentication_timeout=1min\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Client AuthTime")
    except Exception as e:
        data.errormsg = e.__str__()

def setAuthEncriptionCount(data):
    """
    function : Set AuthEncription Count
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"auth_iteration_count=10000\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set AuthEncription Count")
    except Exception as e:
        data.errormsg = e.__str__()

def setFailedLoginCount(data):
    """
    function : Set FailedLogin Count
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"failed_login_attempts=10\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set FailedLogin Count")
    except Exception as e:
        data.errormsg = e.__str__()


#############################################################################
def checkAccountPasswordManagement(isSetting=False):
    """
    function : Check Account Password Management
    input  : Bool
    output : NA
    """
    checkPasswordComplexityValidation(isSetting)
    checkPasswordEncryptionType(isSetting)
    checkPasswordReuseTime(isSetting)
    checkPasswordLockTime(isSetting)
    checkRolPassword()
    checkRolValid(isSetting)
    checkPasswordEffectTime(isSetting)


def checkPasswordComplexityValidation(isSetting):
    """
    function : Check PasswordComplexityValidation
    input  : Bool
    output : NA
    """
    data = collectPasswordComplexityValidation()
    if not int(data.db[0]) == 1:
        if not isSetting:
            g_logger.log("        Warning reason: Ensure password complexity checking is enabled.Passwords with low complexity are easily guessed or cracked by brute force. For the sake of password security, please enable password complexity checks.")
        else:
            setPasswordComplexityValidation(data)

def checkPasswordEncryptionType(isSetting):
    """
    function : Check PasswordEncryptionType
    input  : Bool
    output : NA
    """
    data = collectPasswordEncryptionType()
    if int(data.db[0]) == 0 or int(data.db[0]) == 1:
        if not isSetting:
            g_logger.log("        Warning reason: Ensure password encryption method is configured correctly.The MD5 method has been proven to be insecure and should not be configured, it is retained only for compatibility with open-source third-party tools. It should be configured to use the SHA256 method (default configuration).")
        else:
            setPasswordEncryptionType(data)

def checkPasswordReuseTime(isSetting):
    """
    function : Check PasswordReuseTime
    input  : Bool
    output : NA
    """
    data = collectPasswordReuseTime()
    if int(data.db[0]) == 0:
        if not isSetting:
            g_logger.log("        Warning reason: Ensure correct configuration of password reuse days.Avoid users repeatedly using the same password, as it may lead to the password being cracked.")
        else:
            setPasswordReuseTime(data)

def checkPasswordLockTime(isSetting):
    """
    function : Check PasswordLockTime
    input  : Bool
    output : NA
    """
    data = collectPasswordLockTime()
    if data.db[0].strip() == "0":
        if not isSetting:
            g_logger.log("        Warning reason: Ensure correct configuration of account automatic unlock time.To prevent passwords from being attempted to be cracked by brute force, this parameter must be set to a non-zero value.")
        else:
            setPasswordLockTime(data)

def checkRolPassword():
    """
    function : Check RolPassword
    input  : NA
    output : NA
    """
    data = collectRolPassword()
    if not data.db[0].strip():
        g_logger.log("        Warning reason: Ensure initial user password change at first login.If the initial user password is empty and not promptly modified, it can easily lead to low-cost attack incidents and also raise external doubts, posing security risks.")

def checkRolValid(isSetting):
    """
    function : Check RolValid
    input  : Bool
    output : NA
    """
    data = collectRolValid()
    if data.db[0].strip():
        if not isSetting:
            g_logger.log("        Warning reason: Ensure configuration of user expiration periods.If this configuration is ignored, there may be a risk of inconsistent expiration times for login accounts across nodes. Therefore, it is recommended to reasonably configure the validity period of users or roles according to business needs, and timely clean up unused expired users or roles.")
        else:
            setRolValid(data)

def checkPasswordEffectTime(isSetting):
    """
    function : Check PasswordEffectTime
    input  : Bool
    output : NA
    """
    data = collectPasswordEffectTime()
    if data.db[0].strip() == "0":
        if not isSetting:
            g_logger.log("        Warning reason: Ensure configuration of password expiration periods.Once the password reaches its expiration reminder time, the system will prompt the user to change the password when logging into the database. It is recommended that users regularly update their passwords to enhance the security of password usage.")
        else:
            setPasswordEffectTime(data)


#############################################################################
def setAccountPasswordManagement(isSetting=True):
    """
    function : Set Account Password Management
    input  : Bool
    output : NA
    """
    checkPasswordComplexityValidation(isSetting)
    checkPasswordEncryptionType(isSetting)
    checkPasswordReuseTime(isSetting)
    checkPasswordLockTime(isSetting)
    checkRolValid(isSetting)
    checkPasswordEffectTime(isSetting)


def setPasswordComplexityValidation(data):
    """
    function : Set Password Complexity Validation
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"password_policy=1\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Password Complexity Validation")
    except Exception as e:
        data.errormsg = e.__str__()

def setPasswordEncryptionType(data):
    """
    function : Set Password Encryption Type
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"password_encryption_type=2\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Password Encryption Type")
    except Exception as e:
        data.errormsg = e.__str__()

def setPasswordReuseTime(data):
    """
    function : Set Password ReuseTime
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"password_reuse_time=60\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Password Encryption Type")
    except Exception as e:
        data.errormsg = e.__str__()

def setPasswordLockTime(data):
    """
    function : Set Password Lock Time
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"password_lock_time=1\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Password Lock Time")
    except Exception as e:
        data.errormsg = e.__str__()

def setRolValid(data):
    """
    function : Set Rol Valid
    input  : Instantion
    output : NA
    """
    result = collectRolValid()
    result.db = []
    try:
        now = datetime.now()
        one_year_later = now + timedelta(days=365)
        start_date_str = now.strftime('%Y-%m-%d')
        end_date_str = one_year_later.strftime('%Y-%m-%d')
        for item in data.db:
            sql_query = """ALTER ROLE %s VALID BEGIN '%s' VALID UNTIL '%s';""" %(item.split("|")[0].strip(), start_date_str, end_date_str)
            getDatabaseInfo(result, sql_query)
    except Exception as e:
        data.errormsg = e.__str__()

def setPasswordEffectTime(data):
    """
    function : Set Password Effect Time
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"password_effect_time=90\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Password Effect Time")
    except Exception as e:
        data.errormsg = e.__str__()


#############################################################################
def checkPermissionManagement(isSetting=False):
    """
    function : Check Permission Management
    input  : Bool
    output : NA
    """
    checkPublicRolPGAuthid(isSetting)
    checkPublicRolCreatePerm(isSetting)
    checkPublicRolAllPerm(isSetting)
    checkAdminPrivileges(isSetting)
    checkEnableSeparationOfDuty(isSetting)
    checkEnableCopyServerFiles(isSetting)


def checkPublicRolPGAuthid(isSetting):
    """
    function : Check PublicRolPGAuthid
    input  : Bool
    output : NA
    """
    data = collectPublicRolPGAuthid()
    if data.db[0].strip():
        if not isSetting:
            g_logger.log(
                "        Warning reason: Prohibit the PUBLIC role from having permissions on the pg_authid system table.Since all users inherit the permissions of the PUBLIC role, to prevent sensitive information from being leaked or altered, the PUBLIC role is not allowed to have any permissions on the pg_authid system table.")
        else:
            setPublicRolPGAuthid(data)

def checkPublicRolCreatePerm(isSetting):
    """
    function : Check PublicRolCreatePerm
    input  : Bool
    output : NA
    """
    data = collectPublicRolCreatePerm()
    if data.db[0].strip() != "false":
        if not isSetting:
            g_logger.log(
                "        Warning reason: Disallow the PUBLIC role from having CREATE permissions in the public schema.If the PUBLIC role has CREATE permissions in the public schema, any user can create tables or other database objects in the public schema, which may lead to security risks as other users can also view and modify these tables and database objects.")
        else:
            setPublicRolCreatePerm(data)

def checkPublicRolAllPerm(isSetting):
    """
    function : Check PublicRolAllPerm
    input  : Bool
    output : NA
    """
    data = collectPublicRolAllPerm()
    if data[0].db[0].strip() or data[1].db[0].strip() or data[2].db[0].strip():
        if not isSetting:
            g_logger.log("        Warning reason:Disallow granting all privileges on objects to the PUBLIC role.The PUBLIC role belongs to any user, and if all permissions of an object are granted to the PUBLIC role, then any user will inherit all permissions of this object, which violates the principle of least privilege. To ensure the security of database data, this role should have as few permissions as possible, and it is prohibited to grant all permissions of an object to the PUBLIC role.")
        else:
            setPublicRolAllPerm(data)

def checkAdminPrivileges(isSetting):
    """
    function : Check AdminPrivileges
    input  : Bool
    output : NA
    """
    data = collectAdminPrivileges()
    if data[0].db[0].strip() or data[1].db[0].strip() or data[2].db[0].strip() or data[3].db[0].strip() or data[4].db[
        0].strip() or data[5].db[0].strip():
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure revocation of unnecessary administrative privileges from regular users.As a regular user, they should not possess administrative permissions beyond their normal scope. To ensure that the permissions of regular users are minimized while meeting normal business needs, unnecessary administrative permissions for regular users should be revoked.")
        else:
            setAdminPrivileges(data)

def checkEnableSeparationOfDuty(isSetting):
    """
    function : Check EnableSeparationOfDuty
    input  : Bool
    output : NA
    """
    data = collectEnableSeparationOfDuty()
    if data.db[0].strip() == "off":
        if not isSetting:
            g_logger.log("        Warning reason:Ensure separation of powers configuration is enabled.If a three-tier separation of powers permission management model needs to be used, it should be specified during the database initialization phase, and it is not recommended to switch back and forth between permission management models. Specifically, if switching from a non-three-tier separation of powers to a three-tier separation of powers permission management model is required, it is necessary to re-evaluate whether the existing user permission sets are reasonable.")
        else:
            setEnableSeparationOfDuty(data)

def checkEnableCopyServerFiles(isSetting):
    """
    function : Check EnableCopyServerFiles
    input  : Bool
    output : NA
    """
    data = collectEnableCopyServerFiles()
    if data.db[0].strip() != "off":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure removal of server-side file COPY permissions from system administrators.After canceling the server-side file COPY permissions for system administrators, system administrators will no longer be able to perform server-side file COPY operations. This configuration does not affect initial users.")
        else:
            setEnableCopyServerFiles(data)


#############################################################################
def setPermissionManagement(isSetting=True):
    """
    function : Set Permission Management
    input  : Bool
    output : NA
    """
    checkPublicRolPGAuthid(isSetting)
    checkPublicRolCreatePerm(isSetting)
    checkPublicRolAllPerm(isSetting)
    checkAdminPrivileges(isSetting)
    checkEnableSeparationOfDuty(isSetting)
    checkEnableCopyServerFiles(isSetting)


def setPublicRolPGAuthid(data):
    """
    function : Set Public Rol PG Authid
    input  : Instantion
    output : NA
    """
    result = PublicRolPGAuthid()
    result.db = []
    try:
        sql_query = """REVOKE ALL ON pg_authid FROM PUBLIC;"""
        getDatabaseInfo(result, sql_query)
    except Exception as e:
        data.errormsg = e.__str__()

def setPublicRolCreatePerm(data):
    """
    function : Set Public Rol Create Perm
    input  : Instantion
    output : NA
    """
    result = PublicRolCreatePerm()
    result.db = []
    try:
        sql_query = """REVOKE CREATE ON SCHEMA public FROM PUBLIC;"""
        getDatabaseInfo(result, sql_query)
    except Exception as e:
        data.errormsg = e.__str__()

def setPublicRolAllPerm(data):
    """
    function : Set Public Rol Create Perm
    input  : Instantion
    output : NA
    """
    result = PublicRolAllPerm()
    result.db = []
    try:
        for item in data[0].db:
            sql_query = """REVOKE ALL ON %s FROM PUBLIC;""" %(item.split("|")[0].strip())
            getDatabaseInfo(result, sql_query)
        for item in data[1].db:
            sql_query = """REVOKE ALL ON SCHEMA %s FROM PUBLIC;""" %(item.split("|")[0].strip())
            getDatabaseInfo(result, sql_query)
        for item in data[2].db:
            sql_query = """REVOKE ALL ON FUNCTION %s() FROM PUBLIC;""" %(item.split("|")[0].strip())
            getDatabaseInfo(result, sql_query)
    except Exception as e:
        data.errormsg = e.__str__()

def setAdminPrivileges(data):
    """
    function : Set Admin Privileges
    input  : Instantion
    output : NA
    """
    result = AdminPrivileges()
    result.db = []
    try:
        for item in data[0].db:
            sql_query = """ALTER ROLE %s NOCREATEROLE;""" %(item.split("|")[0].strip())
            getDatabaseInfo(result, sql_query)
        for item in data[1].db:
            sql_query = """ALTER ROLE %s NOCREATEDB;""" %(item.split("|")[0].strip())
            getDatabaseInfo(result, sql_query)
        for item in data[2].db:
            sql_query = """ALTER ROLE %s NOAUDITADMIN;""" %(item.split("|")[0].strip())
            getDatabaseInfo(result, sql_query)
        for item in data[3].db:
            sql_query = """ALTER ROLE %s NOMONADMIN;""" %(item.split("|")[0].strip())
            getDatabaseInfo(result, sql_query)
        for item in data[4].db:
            sql_query = """ALTER ROLE %s NOOPRADMIN;""" %(item.split("|")[0].strip())
            getDatabaseInfo(result, sql_query)
        for item in data[5].db:
            sql_query = """ALTER ROLE %s NOPOLADMIN;""" %(item.split("|")[0].strip())
            getDatabaseInfo(result, sql_query)
    except Exception as e:
        data.errormsg = e.__str__()

def setEnableSeparationOfDuty(data):
    """
    function : Set Enable Separation Of Duty
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc set -D %s -c \"enableSeparationOfDuty = on\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Enable Separation Of Duty")
        cmd_restart = "gs_ctl restart -D %s" % (os.getenv('PGDATA'))
        subprocess.run(cmd_restart, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        data.errormsg = e.__str__()

def setEnableCopyServerFiles(data):
    """
    function : Set Enable Copy Server Files
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"enable_copy_server_files=off\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Enable Copy Server Files")
    except Exception as e:
        data.errormsg = e.__str__()


#############################################################################
def checkDatabaseAuditing(isSetting=False):
    """
    function : Check Database Auditing
    input  : Bool
    output : NA
    """
    checkAuditEnabled(isSetting)
    checkAuditLoginLogout(isSetting)
    checkAuditDatabaseProcess(isSetting)
    checkAuditUserLocked(isSetting)
    checkAuditGrantRevoke(isSetting)
    checkAuditSystemObject(isSetting)
    checkAuditDmlStateSelect(isSetting)
    checkAuditResourcePolicy(isSetting)
    checkAuditRotationInterval(isSetting)
    checkAuditRotationSize(isSetting)
    checkAuditSpaceLimit(isSetting)
    checkAuditFileRemainThreshold(isSetting)


def checkAuditEnabled(isSetting):
    """
    function : Check AuditEnabled
    input  : Bool
    output : NA
    """
    data = collectAuditEnabled()
    if data.db[0].strip() != "on":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure database auditing functionality is enabled.Audit logs are stored in binary form in the pg_audit directory. Enabling auditing will increase disk space usage and have a certain impact on performance.")
        else:
            setAuditEnabled(data)

def checkAuditLoginLogout(isSetting):
    """
    function : Check AuditLoginLogout
    input  : Bool
    output : NA
    """
    data = collectAuditLoginLogout()
    if data.db[0].strip() != "7":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure user login and logout auditing is enabled.Enabling this option allows for tracking which users have logged into the database and when they logged out; otherwise, it is not possible to audit user login and logout activities.")
        else:
            setAuditLoginLogout(data)

def checkAuditDatabaseProcess(isSetting):
    """
    function : Check AuditDatabaseProcess
    input  : Bool
    output : NA
    """
    data = collectAuditDatabaseProcess()
    if data.db[0].strip() != "1":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure database startup, shutdown, recovery, and switchover auditing is enabled.Enabling this option allows for tracing changes in the database's operational status.")
        else:
            setAuditDatabaseProcess(data)

def checkAuditUserLocked(isSetting):
    """
    function : Check AuditUserLocked
    input  : Bool
    output : NA
    """
    data = collectAuditUserLocked()
    if data.db[0].strip() != "1":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure user lock and unlock auditing is enabled.Enabling this option allows for recording audit logs of locking and unlocking operations on database users.")
        else:
            setAuditUserLocked(data)

def checkAuditGrantRevoke(isSetting):
    """
    function : Check AuditGrantRevoke
    input  : Bool
    output : NA
    """
    data = collectAuditGrantRevoke()
    if data.db[0].strip() != "1":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure permission grant and revoke auditing is enabled.Enabling this option allows for recording audit logs of operations that grant and revoke database user permissions.")
        else:
            setAuditGrantRevoke(data)

def checkAuditSystemObject(isSetting):
    """
    function : Check AuditSystemObject
    input  : Bool
    output : NA
    """
    data = collectAuditSystemObject()
    if int(data.db[0].strip()) < 67121195:
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure auditing of database object creation, deletion, and modification is enabled.The parameter 'audit_system_object' determines whether to record audit logs for CREATE, DROP, and ALTER operations on database objects.")
        else:
            setAuditSystemObject(data)

def checkAuditDmlStateSelect(isSetting):
    """
    function : Check AuditDmlStateSelect
    input  : Bool
    output : NA
    """
    data = collectAuditDmlStateSelect()
    if data.db[0].strip() != "1":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure auditing of database object querying is enabled.Enabling this option allows for tracing user queries on the database, but usually, database query operations are relatively frequent. Enabling this option will affect query performance and result in increased audit log records, occupying more disk space. Users can decide whether to enable it based on business needs.")
        else:
            setAuditDmlStateSelect(data)

def checkAuditResourcePolicy(isSetting):
    """
    function : Check AuditResourcePolicy
    input  : Bool
    output : NA
    """
    data = collectAuditResourcePolicy()
    if data.db[0].strip() != "on":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure audit priority strategy configuration is correct.The space policy can ensure the upper limit of audit log disk usage, but it does not guarantee the retention of historical audit logs; the time limit policy ensures the retention of audit logs for a specific period, which may result in increased log space usage.")
        else:
            setAuditResourcePolicy(data)

def checkAuditRotationInterval(isSetting):
    """
    function : Check AuditRotationInterval
    input  : Bool
    output : NA
    """
    data = collectAuditRotationInterval()
    if data.db[0].strip() != "1d":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure correct configuration of maximum retention period for individual audit files.Setting the parameter value too low will result in frequent generation of audit log files.Setting it too high will lead to a single file recording too many logs and occupying a large amount of space, which is not conducive to the management of audit log files.Do not adjust this parameter at will, otherwise it may cause the 'audit_resource_policy' parameter to become ineffective.")
        else:
            setAuditRotationInterval(data)

def checkAuditRotationSize(isSetting):
    """
    function : Check AuditRotationSize
    input  : Bool
    output : NA
    """
    data = collectAuditRotationSize()
    if data.db[0].strip() != "10MB":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure correct configuration of maximum size for individual audit log files.Setting the parameter value too low will result in frequent generation of audit log files. Setting it too high will lead to a single file recording too many logs and occupying a large amount of space, which is not conducive to the management of audit log files. Please do not adjust this parameter at will, as it may cause the 'audit_resource_policy' parameter to become ineffective.")
        else:
            setAuditRotationSize(data)

def checkAuditSpaceLimit(isSetting):
    """
    function : Check AuditSpaceLimit
    input  : Bool
    output : NA
    """
    data = collectAuditSpaceLimit()
    if data.db[0].strip() != "1GB":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure correct configuration of maximum disk space usage for all audit log files.Setting the parameter value too high will increase disk space usage. Setting it too low will result in a shorter retention time for audit logs, which may lead to the loss of important log information.")
        else:
            setAuditSpaceLimit(data)

def checkAuditFileRemainThreshold(isSetting):
    """
    function : Check AuditFileRemainThreshold
    input  : Bool
    output : NA
    """
    data = collectAuditFileRemainThreshold()
    if data.db[0].strip() != "1048576":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure correct configuration of maximum number of audit log files.Setting the parameter value too high will increase disk space usage. Setting it too low will result in a shorter recordable period for audit logs, which may lead to the loss of important log information. Arbitrarily adjusting this parameter may affect the effectiveness of the 'audit_resource_policy' parameter.")
        else:
            setAuditFileRemainThreshold(data)


#############################################################################
def setDatabaseAuditing(isSetting=True):
    """
    function : Set Database Auditing
    input  : Bool
    output : NA
    """
    checkAuditEnabled(isSetting)
    checkAuditLoginLogout(isSetting)
    checkAuditDatabaseProcess(isSetting)
    checkAuditUserLocked(isSetting)
    checkAuditGrantRevoke(isSetting)
    checkAuditSystemObject(isSetting)
    checkAuditDmlStateSelect(isSetting)
    checkAuditResourcePolicy(isSetting)
    checkAuditRotationInterval(isSetting)
    checkAuditRotationSize(isSetting)
    checkAuditSpaceLimit(isSetting)
    checkAuditFileRemainThreshold(isSetting)

def setAuditEnabled(data):
    """
    function : Set Audit Enabled
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"audit_enabled = on\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Audit Enabled")
    except Exception as e:
        data.errormsg = e.__str__()

def setAuditLoginLogout(data):
    """
    function : Set Audit Login Logout
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"audit_login_logout = 7\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Audit Login Logout")
    except Exception as e:
        data.errormsg = e.__str__()

def setAuditDatabaseProcess(data):
    """
    function : Set Audit Database Process
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"audit_database_process = 1\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Audit Database Process")
    except Exception as e:
        data.errormsg = e.__str__()

def setAuditUserLocked(data):
    """
    function : Set Audit User Locked
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"audit_user_locked = 1\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Audit User Locked")
    except Exception as e:
        data.errormsg = e.__str__()

def setAuditGrantRevoke(data):
    """
    function : Set Audit Grant Revoke
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"audit_grant_revoke = 1\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Audit Grant Revoke")
    except Exception as e:
        data.errormsg = e.__str__()

def setAuditSystemObject(data):
    """
    function : Set Audit System Object
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"audit_system_object = 67121195\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Audit System Object")
    except Exception as e:
        data.errormsg = e.__str__()

def setAuditDmlStateSelect(data):
    """
    function : Set Audit Dml State Select
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"audit_dml_state_select = 1\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Audit Dml State Select")
    except Exception as e:
        data.errormsg = e.__str__()

def setAuditResourcePolicy(data):
    """
    function : Set Audit Resource Policy
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"audit_resource_policy = on\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Audit Resource Policy")
    except Exception as e:
        data.errormsg = e.__str__()

def setAuditRotationInterval(data):
    """
    function : Set Audit Rotation Interval
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"audit_rotation_interval = 1440\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Audit Rotation Interval")
    except Exception as e:
        data.errormsg = e.__str__()

def setAuditRotationSize(data):
    """
    function : Set Audit Rotation Size
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"audit_rotation_size = 10MB\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Audit Rotation Size")
    except Exception as e:
        data.errormsg = e.__str__()

def setAuditSpaceLimit(data):
    """
    function : Set Audit Space Limit
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"audit_space_limit = 1GB\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Audit Space Limit")
    except Exception as e:
        data.errormsg = e.__str__()

def setAuditFileRemainThreshold(data):
    """
    function : Set Audit File Remain Threshold
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"audit_file_remain_threshold = 1048576\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Audit File Remain Threshold")
    except Exception as e:
        data.errormsg = e.__str__()


#############################################################################
def checkErrorReportingAndLoggingConfiguration(isSetting=False):
    """
    function : Check Error Reporting And Logging Configuration
    input  : Bool
    output : NA
    """
    checkLoggingCollector(isSetting)
    checkLogFilename(isSetting)
    checkLogFileMode(isSetting)
    checkLogTruncateOnRotation(isSetting)
    checkLogRotationAge(isSetting)
    checkLogRotationSize(isSetting)
    checkClientMinMessages(isSetting)
    checkLogMinMessages(isSetting)
    checkLogMinErrorStatement(isSetting)
    checkLogConnections(isSetting)
    checkLogDisconnections(isSetting)
    checkLogErrorVerbosity(isSetting)
    checkLogHostname(isSetting)
    checkDebugPrintParse(isSetting)
    checkDebugPrintPlan(isSetting)
    checkDebugPrintRewritten(isSetting)


def checkLoggingCollector(isSetting):
    """
    function : Check LoggingCollector
    input  : Bool
    output : NA
    """
    data = collectLoggingCollector()
    if data.db[0].strip() != "on":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure the log collector is enabled.When sending server logs to stderr, the 'logging_collector' parameter can be omitted, and the log messages will be sent to the space pointed to by the server's stderr. The disadvantage of this method is that it is difficult to roll back logs and is only suitable for smaller log volumes.")
        else:
            setLoggingCollector(data)

def checkLogFilename(isSetting):
    """
    function : Check LogFilename
    input  : Bool
    output : NA
    """
    data = collectLogFilename()
    if data.db[0].strip() != "postgresql-%Y-%m-%d_%H%M%S.log":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure correct log name configuration.It is recommended to use the % escape character to define log file names, so that they can automatically include date and time information, thereby facilitating effective management of log files.")
        else:
            setLogFilename(data)

def checkLogFileMode(isSetting):
    """
    function : Check LogFileMode
    input  : Bool
    output : NA
    """
    data = collectLogFileMode()
    if data.db[0].strip() != "0600":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure correct log file permissions configuration.Log files may contain user data, so access to log files must be restricted to prevent the disclosure or tampering of log information.")
        else:
            setLogFileMode(data)

def checkLogTruncateOnRotation(isSetting):
    """
    function : Check LogTruncateOnRotation
    input  : Bool
    output : NA
    """
    data = collectLogTruncateOnRotation()
    if data.db[0].strip() != "off":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Prohibit overwriting of identically named log files.When set to 'on', the database will write server log messages in an overwrite mode, which means that when the log file is rotated, new log messages will overwrite old ones. When set to 'off', new log messages will be appended to the existing log file with the same name without overwriting the old ones. To ensure longer retention of logs, it is necessary to set this parameter to 'off', prohibiting the overwriting of log files with the same name.")
        else:
            setLogTruncateOnRotation(data)

def checkLogRotationAge(isSetting):
    """
    function : Check LogRotationAge
    input  : Bool
    output : NA
    """
    data = collectLogRotationAge()
    if data.db[0].strip() != "1d":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure correct configuration of maximum retention time for individual log files.When the log recording time exceeds the maximum value set by this parameter, the server will automatically create a new log file. Proper configuration helps avoid the excessively frequent creation of log files while preventing individual log files from becoming too large and difficult to manage.")
        else:
            setLogRotationAge(data)

def checkLogRotationSize(isSetting):
    """
    function : Check LogRotationSize
    input  : Bool
    output : NA
    """
    data = collectLogRotationSize()
    if data.db[0].strip() != "20MB":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure correct configuration of maximum size for individual log files.If the value of the 'log_rotation_size' parameter is set too low, it will result in frequent generation of log files, increasing management difficulty. If the parameter value is set too high, a single log file will record too many logs, which may lead to excessive disk space usage and is not conducive to log file management.")
        else:
            setLogRotationSize(data)

def checkClientMinMessages(isSetting):
    """
    function : Check ClientMinMessages
    input  : Bool
    output : NA
    """
    data = collectClientMinMessages()
    if data.db[0].strip().startswith("debug"):
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure correct client log level configuration.Log levels debug1 to debug5 are primarily used for debugging and are not recommended for use in production environments, as they can increase the amount of logs sent to clients. It is advised to keep the default value of 'notice'.")
        else:
            setClientMinMessages(data)

def checkLogMinMessages(isSetting):
    """
    function : Check LogMinMessages
    input  : Bool
    output : NA
    """
    data = collectLogMinMessages()
    if data.db[0].strip().startswith("debug"):
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure server log level configuration is correct.Log levels debug1 to debug5 are primarily used for debugging and are not recommended for use in production environments, as they can increase the amount of logs written to the server. It is advised to keep the default value of 'warning'.")
        else:
            setLogMinMessages(data)

def checkLogMinErrorStatement(isSetting):
    """
    function : Check LogMinErrorStatement
    input  : Bool
    output : NA
    """
    data = collectLogMinErrorStatement()
    if data.db[0].strip() != "error":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure correct logging configuration for SQL statements that generate errors.Since some SQL statements contain personal user information, ifSince some SQL statements contain personal user information, if record the erroneous SQL if there is no need to record the erroneous SQL statements, the parameter can be set to 'panic'.")
        else:
            setLogMinErrorStatement(data)

def checkLogConnections(isSetting):
    """
    function : Check LogConnections
    input  : Bool
    output : NA
    """
    data = collectLogConnections()
    if data.db[0].strip() != "on":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure logging of user login events is enabled.Enabling 'log_connections' allows for logging all user login attempts, aiding administrators in analyzing potential malicious connections or connection issues. However, as it records all connection attempts, it may lead to rapid growth of log files, increasing disk storage pressure.")
        else:
            setLogConnections(data)

def checkLogDisconnections(isSetting):
    """
    function : Check LogDisconnections
    input  : Bool
    output : NA
    """
    data = collectLogDisconnections()
    if data.db[0].strip() != "on":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure logging of user logout events is enabled.Enabling the 'log_disconnections' parameter helps analyze client connection disconnections, including the reasons for disconnection and session duration. At the same time, enabling this parameter may increase the volume of log records, and the costs of disk storage and log management need to be considered.")
        else:
            setLogDisconnections(data)

def checkLogErrorVerbosity(isSetting):
    """
    function : Check LogErrorVerbosity
    input  : Bool
    output : NA
    """
    data = collectLogErrorVerbosity()
    if data.db[0].strip() != "default":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure correct configuration of logging verbosity for server logs.Valid values include TERSE, DEFAULT, and VERBOSE.")
        else:
            setLogErrorVerbosity(data)

def checkLogHostname(isSeting):
    """
    function : Check LogHostname
    input  : Bool
    output : NA
    """
    data = collectLogHostname()
    if data.db[0].strip() != "off":
        if not isSeting:
            g_logger.log(
                "        Warning reason:Ensure logs do not record hostnames.Since resolving hostnames takes some time, it may result in additional performance overhead. Therefore, it is recommended to set 'log_hostname' to 'off', so that only the IP address is recorded in the connection log without logging the hostname.")
        else:
            setLogHostname(data)

def checkDebugPrintParse(isSetting):
    """
    function : Check DebugPrintParse
    input  : Bool
    output : NA
    """
    data = collectDebugPrintParse()
    if data.db[0].strip() != "off":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure debug printing switch for parse tree is turned off.When this parameter is set to 'on', the parse tree results of queries will be printed in the log, which may occupy a significant amount of log space and negatively impact query performance. In production environments, it is recommended to set the 'debug_print_parse' parameter to 'off' to prevent the printing of query parse tree results in the log.")
        else:
            setDebugPrintParse(data)

def checkDebugPrintPlan(isSetting):
    """
    function : Check DebugPrintPlan
    input  : Bool
    output : NA
    """
    data = collectDebugPrintPlan()
    if data.db[0].strip() != "off":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure debug printing switch for execution plans is turned off.By default, this parameter is set to 'off', indicating that the execution plan will not be printed. However, if it is set to 'on', the execution plan of queries will be printed in the log, which may occupy a large amount of log space and negatively impact query performance. Therefore, in production environments, it is recommended to set the 'debug_print_plan' parameter to 'off' to prevent the printing of the execution plan in the log.")
        else:
            setDebugPrintPlan(data)

def checkDebugPrintRewritten(isSetting):
    """
    function : Check DebugPrintRewritten
    input  : Bool
    output : NA
    """
    data = collectDebugPrintRewritten()
    if data.db[0].strip() != "off":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure debug printing switch for query rewriting is turned off.By default, this parameter is set to 'off', indicating that the query rewrite results will not be printed. However, if it is set to 'on', the results of query rewriting will be printed in the log, which may occupy a large amount of log space and negatively impact query performance. Therefore, in production environments, it is recommended to set the 'debug_print_rewritten' parameter to 'off' to prevent the printing of query rewrite results in the log.")
        else:
            setDebugPrintRewritten(data)


#############################################################################
def setErrorReportingAndLoggingConfiguration(isSetting=True):
    """
    function : Set Error Reporting And Logging Configuration
    input  : Bool
    output : NA
    """
    checkLoggingCollector(isSetting)
    checkLogFilename(isSetting)
    checkLogFileMode(isSetting)
    checkLogTruncateOnRotation(isSetting)
    checkLogRotationAge(isSetting)
    checkLogRotationSize(isSetting)
    checkClientMinMessages(isSetting)
    checkLogMinMessages(isSetting)
    checkLogMinErrorStatement(isSetting)
    checkLogConnections(isSetting)
    checkLogDisconnections(isSetting)
    checkLogErrorVerbosity(isSetting)
    checkLogHostname(isSetting)
    checkDebugPrintParse(isSetting)
    checkDebugPrintPlan(isSetting)
    checkDebugPrintRewritten(isSetting)


def setLoggingCollector(data):
    """
    function : Set Logging Collector
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc set -D %s -c \"logging_collector=on\"" %(os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!',result.stdout):
            g_logger.log("Failed to set Logging Collector")
        cmd_restart = "gs_ctl restart -D %s" %(os.getenv('PGDATA'))
        subprocess.run(cmd_restart, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        data.errormsg = e.__str__()

def setLogFilename(data):
    """
    function : Set Log Filename
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Log Filename")
    except Exception as e:
        data.errormsg = e.__str__()

def setLogFileMode(data):
    """
    function : Set Log File Mode
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"log_file_mode=0600\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Log File Mode")
    except Exception as e:
        data.errormsg = e.__str__()

def setLogTruncateOnRotation(data):
    """
    function : Set Log Truncate On Rotation
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"log_truncate_on_rotation=off\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Log Truncate On Rotation")
    except Exception as e:
        data.errormsg = e.__str__()

def setLogRotationAge(data):
    """
    function : Set Log Rotation Age
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"log_rotation_age=1d\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Log Rotation Age")
    except Exception as e:
        data.errormsg = e.__str__()

def setLogRotationSize(data):
    """
    function : Set Log Rotation Size
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"log_rotation_size=20MB\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Log Rotation Size")
    except Exception as e:
        data.errormsg = e.__str__()

def setClientMinMessages(data):
    """
    function : Set Client Min Messages
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"client_min_messages=notice\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Client Min Messages")
    except Exception as e:
        data.errormsg = e.__str__()

def setLogMinMessages(data):
    """
    function : Set Log Min Messages
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"log_min_messages=warning\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Log Min Messages")
    except Exception as e:
        data.errormsg = e.__str__()

def setLogMinErrorStatement(data):
    """
    function : Set Log Min Error Statement
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"log_min_error_statement=error\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Log Min Error Statement")
    except Exception as e:
        data.errormsg = e.__str__()

def setLogConnections(data):
    """
    function : Set Log Connections
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"log_connections=on\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Log Connections")
    except Exception as e:
        data.errormsg = e.__str__()

def setLogDisconnections(data):
    """
    function : Set Log Disconnections
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"log_disconnections=on\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Log Disconnections")
    except Exception as e:
        data.errormsg = e.__str__()

def setLogErrorVerbosity(data):
    """
    function : Set Log Error Verbosity
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"log_error_verbosity=default\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Log Error Verbosity")
    except Exception as e:
        data.errormsg = e.__str__()

def setLogHostname(data):
    """
    function : Set Log Hostname
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"log_hostname=off\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Log Hostname")
    except Exception as e:
        data.errormsg = e.__str__()

def setDebugPrintParse(data):
    """
    function : Set Debug Print Parse
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"debug_print_parse=off\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Debug Print Parse")
    except Exception as e:
        data.errormsg = e.__str__()

def setDebugPrintPlan(data):
    """
    function : Set Debug Print Plan
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"debug_print_plan=off\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Debug Print Plan")
    except Exception as e:
        data.errormsg = e.__str__()

def setDebugPrintRewritten(data):
    """
    function : Set Debug Print Rewritten
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"debug_print_rewritten=off\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Debug Print Rewritten")
    except Exception as e:
        data.errormsg = e.__str__()


#############################################################################
def checkBackupConfiguration(isSetting=False):
    """
    function : Check Backup Configuration
    input  : Bool
    output : NA
    """
    checkWalLevel(isSetting)
    checkArchiveMode(isSetting)


def checkWalLevel(isSetting):
    """
    function : Check WalLevel
    input  : Bool
    output : NA
    """
    data = collectWalLevel()
    if data.db[0].strip() != "hot_standby":
        if not isSetting:
            g_logger.log(
                "         Warning reason:Ensure correct configuration of WAL (Write-Ahead Logging) information recording level.The 'wal_level' determines the amount of information written to WAL. To enable read-only queries on a standby server, 'wal_level' must be set to 'hot_standby' on the primary server, and the 'hot_standby' parameter must be set to 'on' on the standby server.")
        else:
            setWalLevel(data)

def checkArchiveMode(isSetting):
    """
    function : Check ArchiveMode
    input  : Bool
    output : NA
    """
    data = collectArchiveMode()
    if not (data.db[0].strip() == "hot_standby" or (data.db[0].strip() == "archive" and data.db[1].strip() == "on")):
        if not isSetting:
            g_logger.log(
                "         Warning reason:Ensure archiving mode is enabled.After enabling archive mode, it is necessary to plan the disk space occupied by archived logs. The log archiving process may impact database performance.")
        else:
            setArchiveMode(data)


#############################################################################
def setBackupConfiguration(isSetting=True):
    """
    function : Set Backup Configuration
    input  : Bool
    output : NA
    """
    checkWalLevel(isSetting)
    checkArchiveMode(isSetting)


def setWalLevel(data):
    """
    function : Set Wal Level
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc set -D %s -c \"wal_level=hot_standby\"" %(os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!',result.stdout):
            g_logger.log("Failed to set Wal Level")
        cmd_restart = "gs_ctl restart -D %s" %(os.getenv('PGDATA'))
        subprocess.run(cmd_restart, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        data.errormsg = e.__str__()

def setArchiveMode(data):
    """
    function : Set Archive Mode
    input  : Instantion
    output : NA
    """
    try:
        cmd_set_archive_mode = "gs_guc reload -D %s -c \"archive_mode=on\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set_archive_mode, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Archive Mode")
        cmd_set_archive_command = "gs_guc reload -D %s -c \"archive_command='cp --remove-destination %p /mnt/server/archive/%f'\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set_archive_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Archive Mode")
    except Exception as e:
        data.errormsg = e.__str__()


#############################################################################
def checkRuntimeEnvironmentConfiguration(isSetting=False):
    """
    function : Check Runtime Environment Configuration
    input  : Bool
    output : NA
    """
    checkUmask(isSetting)
    checkHidepid()
    checkNtpd()


def checkUmask(isSetting):
    """
    function : Check Umask
    input  : Bool
    output : NA
    """
    data = collectUmask()
    if not data.output.strip() == "0077":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure correct file permission mask configuration.If the umask is set improperly, it may lead to overly restrictive or excessive permissions for newly created files, thereby affecting normal business operations or posing security risks.")
        else:
            setUmask()

def checkHidepid():
    """
    function : Check Hidepid
    input  : NA
    output : NA
    """
    data = collectHidepid()
    pattern = r'hidepid=2'
    if not (data.output and re.search(pattern, data.output)):
        g_logger.log(
            "        Warning reason:Ensure process information is hidden from other users.This ensures that only the root user can view all processes, while regular users can only see their own processes. This helps prevent the leakage of user process information and enhances the security of the database operating environment.")


def checkNtpd():
    """
    function : Check Ntpd
    input  : NA
    output : NA
    """
    data = collectNtpd()
    pattern = r'running'
    if not (data.output and re.search(pattern, data.output)):
        g_logger.log(
            "        Warning reason:Ensure NTP clock synchronization is enabled.Ensure that the system time is synchronized across all hosts on the database server. A lack of synchronization or significant differences in system time may prevent the database from operating normally.")


#############################################################################
def setRuntimeEnvironmentConfiguration(isSetting=True):
    """
    function : Set Runtime Environment Configuration
    input  : Bool
    output : NA
    """
    checkUmask(isSetting)

def setUmask():
    """
    function : Set Umask
    input  : NA
    output : NA
    """
    umask_value = '0077'
    home_dir = os.path.expanduser('~')
    bashrc_path = os.path.join(home_dir, '.bashrc')

    with open(bashrc_path, 'r', encoding='utf-8') as file:
        lines = file.readlines()

    new_lines = []
    umask_found = False
    for line in lines:
        if line.strip().startswith('umask'):
            new_lines.append(f'umask {umask_value}\n')
            umask_found = True
        else:
            new_lines.append(line)

    if not umask_found:
        new_lines.append(f'umask {umask_value}\n')
    with open(bashrc_path, 'w', encoding='utf-8') as file:
        file.writelines(new_lines)

    os.system("source ~/.bashrc")


#############################################################################
def checkOtherConfigurations(isSetting=False):
    """
    function : Check Other Configurations
    input  : Bool
    output : NA
    """
    checkBackslashQuote(isSetting)
    checkAllowSystemTableMods(isSetting)


def checkBackslashQuote(isSetting):
    """
    function : Check BackslashQuote
    input  : Bool
    output : NA
    """
    data = collectBackslashQuote()
    if data.db[0].strip() not in ['safe_encoding', 'off']:
        if not isSetting:
            g_logger.log(
                "        Warning reason:Ensure correct configuration of the backslash_quote parameter.The use of backslash-escaped quotation marks can pose security risks, such as SQL injection attacks. To avoid this risk, it is recommended to configure the server to reject queries with backslash-escaped quotation marks. It is advisable to use the SQL standard method, which involves writing a single quotation mark twice ('').")
        else:
            setBackslashQuote(data)

def checkAllowSystemTableMods(isSetting):
    """
    function : Check AllowSystemTableMods
    input  : Bool
    output : NA
    """
    data = collectAllowSystemTableMods()
    if data.db[0].strip() != "off":
        if not isSetting:
            g_logger.log(
                "        Warning reason:Prohibit modification of system table structures.Although in some extreme cases, this parameter can help recover a damaged database, modifying the system table structure in a production environment may pose serious security risks, including data loss and system instability. Therefore, in a production environment, the 'allow_system_table_mods' parameter should be set to 'off'.")
        else:
            setAllowSystemTableMods(data)


#############################################################################
def setOtherConfigurations(isSetting=True):
    """
    function : Set Other Configurations
    input  : Bool
    output : NA
    """
    checkBackslashQuote(isSetting)
    checkAllowSystemTableMods(isSetting)


def setBackslashQuote(data):
    """
    function : Set Backslash Quote
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc reload -D %s -c \"backslash_quote=safe_encoding\"" % (os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!', result.stdout):
            g_logger.log("Failed to set Backslash Quote")
    except Exception as e:
        data.errormsg = e.__str__()

def setAllowSystemTableMods(data):
    """
    function : Set Allow System Table Mods
    input  : Instantion
    output : NA
    """
    try:
        cmd_set = "gs_guc set -D %s -c \"allow_system_table_mods=off\"" %(os.getenv('PGDATA'))
        result = subprocess.run(cmd_set, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if not re.search(r'Success to perform gs_guc!',result.stdout):
            g_logger.log("Failed to set Allow System Table Mods")
        cmd_restart = "gs_ctl restart -D %s" %(os.getenv('PGDATA'))
        subprocess.run(cmd_restart, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    except Exception as e:
        data.errormsg = e.__str__()


#############################################################################
class CmdOptions():
    """
    Class: CmdOptions
    """

    def __init__(self):
        """
        function : Init class CmdOptions
        input  : NA
        output : NA
        """
        self.action = ""
        self.user = ""
        self.extrachecklist = []
        self.logFile = ""
        self.confFile = ""
        self.mtuValue = ""
        self.hostname = ""
        self.mppdbfile = ""


#########################################################
# Init global log
#########################################################
def initGlobals():
    """
    function : init Globals
    input  : NA
    output : NA
    """
    global g_logger
    global g_clusterInfo
    global g_readlist
    g_readlist = []

    g_logger = GaussLog(g_opts.logFile, "LocalCheckSE")

    g_clusterInfo = dbClusterInfo()
    if (g_opts.confFile != "" and g_opts.confFile is not None):
        g_clusterInfo.initFromXml(g_opts.confFile)


###########################################################################
# network card parameter:
###########################################################################
class netWork:
    """
    Class: netWork
    """

    def __init__(self):
        """
        function : Init class netWork
        input  : NA
        output : NA
        """
        self.netLevel = ""
        self.netNum = ""
        self.variables = dict()
        self.modeType = False
        self.nums = 0


def usage():
    """
Usage:
 python3 --help | -?
 python3 LocalCheckSE -t action [-l logfile] [-X xmlfile] [-V]
Common options:
 -t                                The type of action.
 -s                                the path of MPPDB file
 -l --log-file=logfile             The path of log file.
 -? --help                         Show this help screen.
 -X --xmlfile = xmlfile            Cluster config file
    --ntp-server                   NTP server node's IP.
 -V --version
    """
    print(usage.__doc__)


def parseCommandLine():
    """
    function : Parse command line and save to global variables
    input  : NA
    output : NA
    """
    try:
        opts, args = getopt.getopt(sys.argv[1:], "t:s:l:X:V?",
                                   ["help", "log-file=", "xmlfile=",
                                    "MTUvalue=", "hostname=",
                                    "ntp-server=", "version"])
    except Exception as e:
        usage()
        GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50000"]
                               % str(e))

    if (len(args) > 0):
        GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50000"]
                               % str(args[0]))

    global g_opts
    g_opts = CmdOptions()

    for (key, value) in opts:
        if (key == "-?" or key == "--help"):
            usage()
            sys.exit(0)
        elif (key == "-V" or key == "--version"):
            print("%s %s" % (sys.argv[0].split("/")[-1],
                             VersionInfo.COMMON_VERSION))
            sys.exit(0)
        elif (key == "-t"):
            g_opts.action = value
        elif (key == "-s"):
            g_opts.mppdbfile = value
        elif (key == "-X" or key == "--xmlfile"):
            g_opts.confFile = value
        elif (key == "-l" or key == "--log-file"):
            g_opts.logFile = os.path.realpath(value)
        elif (key == "--MTUvalue"):
            g_opts.mtuValue = value
        elif (key == "--hostname"):
            g_opts.hostname = value
        Parameter.checkParaVaild(key, value)


def checkParameter():
    """
    function : check parameter
    input  : NA
    output : NA
    """
    if (g_opts.action == ""):
        GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50001"] % 't' + '.')
    if (g_opts.action != ACTION_CHECK_Connection_configuration
            and g_opts.action != ACTION_CHECK_File_directory_security
            and g_opts.action != ACTION_CHECK_Security_authentication_configuration
            and g_opts.action != ACTION_CHECK_Account_password_management
            and g_opts.action != ACTION_CHECK_Permission_management
            and g_opts.action != ACTION_CHECK_Database_auditing
            and g_opts.action != ACTION_CHECK_Error_reporting_and_logging_configuration
            and g_opts.action != ACTION_CHECK_Backup_configuration
            and g_opts.action != ACTION_CHECK_Runtime_environment_configuration
            and g_opts.action != ACTION_CHECK_Other_configurations
            and g_opts.action != ACTION_SET_Connection_configuration
            and g_opts.action != ACTION_SET_File_directory_security
            and g_opts.action != ACTION_SET_Security_authentication_configuration
            and g_opts.action != ACTION_SET_Account_password_management
            and g_opts.action != ACTION_SET_Permission_management
            and g_opts.action != ACTION_SET_Database_auditing
            and g_opts.action != ACTION_SET_Error_reporting_and_logging_configuration
            and g_opts.action != ACTION_SET_Backup_configuration
            and g_opts.action != ACTION_SET_Runtime_environment_configuration
            and g_opts.action != ACTION_SET_Other_configurations):
        GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50004"] % "t")

    if (g_opts.logFile == ""):
        dirName = os.path.dirname(os.path.realpath(__file__))
        g_opts.logFile = os.path.join(dirName, ClusterConstants.LOCAL_LOG_FILE)


def getLocalIPAddr():
    """
    function: get local ip
    input : NA
    output: Ips
    """
    Ips = []

    if g_opts.confFile == "":
        Ips.append(DefaultValue.getIpByHostName())
        return Ips

    for node in g_clusterInfo.dbNodes:
        if (node.name == NetUtil.GetHostIpOrName()):
            Ips.append(node.backIps[0])

    return Ips


def doLocalCheck():
    """
    function: check SE item on local node
    input : NA
    output: NA
    """

    global netWorkBondInfo
    netWorkBondInfo = netWork()

    function_dict_false = {ACTION_CHECK_Connection_configuration: checkConnection,
                           ACTION_CHECK_File_directory_security: checkFileSecurity,
                           ACTION_CHECK_Security_authentication_configuration: checkSecurityAuthConf,
                           ACTION_CHECK_Account_password_management: checkAccountPasswordManagement,
                           ACTION_CHECK_Permission_management: checkPermissionManagement,
                           ACTION_CHECK_Database_auditing: checkDatabaseAuditing,
                           ACTION_CHECK_Error_reporting_and_logging_configuration: checkErrorReportingAndLoggingConfiguration,
                           ACTION_CHECK_Backup_configuration: checkBackupConfiguration,
                           ACTION_CHECK_Runtime_environment_configuration: checkRuntimeEnvironmentConfiguration,
                           ACTION_CHECK_Other_configurations: checkOtherConfigurations}
    function_keys_false = list(function_dict_false.keys())

    function_dict_true = {ACTION_SET_Connection_configuration: setConnection,
                          ACTION_SET_File_directory_security: setFileSecurity,
                          ACTION_SET_Security_authentication_configuration: setSecurityAuthenticationConfiguration,
                          ACTION_SET_Account_password_management: setAccountPasswordManagement,
                          ACTION_SET_Permission_management: setPermissionManagement,
                          ACTION_SET_Database_auditing: setDatabaseAuditing,
                          ACTION_SET_Error_reporting_and_logging_configuration: setErrorReportingAndLoggingConfiguration,
                          ACTION_SET_Backup_configuration: setBackupConfiguration,
                          ACTION_SET_Runtime_environment_configuration: setRuntimeEnvironmentConfiguration,
                          ACTION_SET_Other_configurations: setOtherConfigurations}
    function_keys_true = list(function_dict_true.keys())

    if (g_opts.action in function_keys_false):
        function_dict_false[g_opts.action](False)
    elif (g_opts.action in function_keys_true):
        function_dict_true[g_opts.action](True)
    else:
        g_logger.logExit(ErrorCode.GAUSS_500["GAUSS_50004"] % 't' +
                         " Value: %s." % g_opts.action)


if __name__ == '__main__':
    """
    main function
    """
    try:
        parseCommandLine()
        checkParameter()
        initGlobals()
    except Exception as e:
        GaussLog.exitWithError(str(e))

    try:
        nodeIps = []
        nodeIps = getLocalIPAddr()
        doLocalCheck()
        g_logger.closeLog()
    except Exception as e:
        g_logger.logExit(str(e))

    sys.exit(0)
