def __init__(self, logger, settings=None, globalSettings=None, env=None, poolSize=35, maxOverflow=5, poolRecycle=1800): """Constructor for the database client connection. Arguments: logger : handler for the database log settings (json) : database connection parameters globalSettings (json) : global settings env : module containing the env paths poolSize (int) : pool_size param for sqlalchemy.create_engine() maxOverflow (int) : max_overflow param for sqlalchemy.create_engine() poolRecycle (int) : pool_recycle param for sqlalchemy.create_engine() """ try: self.session = None self.settings = settings if self.settings is None: self.settings = {} ## Load an external database library for the wrapped connection; ## the provided library must contain a 'createEngine' function that ## takes a previously created dictionary with the database ## settings (if empty, it will be filled), the globalSettings which ## contains named references to modules in the external directory, ## and parameters to use in the call for sqlalchemy.create_engine(). externalLibrary = utils.loadExternalLibrary('externalDatabaseLibrary', env, globalSettings) self.engine = externalLibrary.createEngine(self.settings, globalSettings, poolSize, maxOverflow, poolRecycle) ## Validate we are actually talking to the DB engineInspector = sqlalchemy_inspect(self.engine) schemas = engineInspector.get_schema_names() if schemas is None or len(schemas) <= 0: raise EnvironmentError('Could not connect to database') logger.debug('Schemas found from connection pool inspection: {}'.format(str(schemas))) self.createScopedSession(logger) except exc.OperationalError: ## Intentionally catch database connection errors logger.error('Exception in DatabaseClient: {}'.format(str(sys.exc_info()[1]))) raise except: stacktrace = traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]) logger.error('Exception in DatabaseClient: {}'.format(str(stacktrace))) raise
.. hidden:: Author: Chris Satterthwaite (CS) Contributors: Version info: 1.0 : (CS) Created Jan 3, 2018 """ ## Using pythoncom since WMI is COM-based, and when using ## in a thread, it needs it's own COM threading model import pythoncom ## Using an externally provided library defined in globalSettings and located ## in '<install_path>/external'. import utils externalProtocolLibrary = utils.loadExternalLibrary('externalProtocolWmi') ## PyMI is used in the external library: ## import wmi ## To call this function for a remote connection: ## wmi.WMI(moniker, computer, user, password) class Wmi: """Wrapper class for WMI.""" def __init__(self, runtime, logger, endpoint, reference, protocol, **kwargs): self.runtime = runtime self.logger = logger self.endpoint = endpoint self.connection = None
import sys import traceback import json ## Using sqlalchemy for the wrapper around postgresql: ## http://docs.sqlalchemy.org/en/latest/index.html from sqlalchemy import create_engine ## Get relative paths based on install location import env env.addLibPath() import utils globalSettings = utils.loadSettings( os.path.join(env.configPath, 'globalSettings.json')) ## Import an externally-provided library for encoding/encrypting/hashing/etc externalEncryptionLibrary = utils.loadExternalLibrary( 'externalEncryptionLibrary', env, globalSettings) requiredParameters = [ 'databaseServer', 'databasePort', 'databaseName', 'databaseUser' ] def encode(sensitiveData): ## Use an externally library for sensitive data (defined and imported above) return externalEncryptionLibrary.encode(sensitiveData) def decode(encodedData): ## Use an externally library for sensitive data (defined and imported above) return externalEncryptionLibrary.decode(encodedData)
def powerShell(): import sys import traceback import os import re try: ## Add openContentPlatform directories onto the sys path thisPath = os.path.dirname(os.path.abspath(__file__)) basePath = os.path.abspath(os.path.join(thisPath, '..')) if basePath not in sys.path: sys.path.append(basePath) import env env.addLibPath() env.addDatabasePath() env.addExternalPath() ## Setup requested log handlers globalSettings = utils.loadSettings( os.path.join(env.configPath, 'globalSettings.json')) logEntity = 'Protocols' logger = utils.setupLogger(logEntity, env, 'logSettingsCore.json') logger.info('Starting protocolWrapperPowershell...') import twisted.logger logFiles = utils.setupLogFile( 'JobDetail', env, globalSettings['fileContainingContentGatheringLogSettings'], directoryName='client') logObserver = utils.setupObservers( logFiles, 'JobDetail', env, globalSettings['fileContainingContentGatheringLogSettings']) logger = twisted.logger.Logger(observer=logObserver, namespace='JobDetail') from remoteRuntime import Runtime runtime = Runtime(logger, env, 'TestPkg', 'TestJob', 'endpoint', {}, None, {}, None, {}, None) ## Manual creation of a protocol via protocolHandler externalProtocolHandler = utils.loadExternalLibrary( 'externalProtocolHandler', env, globalSettings) protocolHandler = externalProtocolHandler.ProtocolHandler( None, globalSettings, env, logger) protocolType = 'ProtocolPowerShell' protocolData = {'user': '******', 'password': '******'} protocolHandler.createManual(runtime, protocolType, protocolData) protocol = externalProtocolHandler.getProtocolObject(runtime, 1) print('protocol to use: {}'.format(protocol)) print('protocols: {}'.format( externalProtocolHandler.getProtocolObjects(runtime))) endpoint = '192.168.1.100' client = PowerShell(runtime, logger, endpoint, 1, protocol) client.open() osAttrDict = {} queryOperatingSystem(client, logger, osAttrDict) logger.debug('osAttrDict: {osAttrDict!r}', osAttrDict=osAttrDict) client.close() except: stacktrace = traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]) msg = str(sys.exc_info()[1]) ## Cleanup message when we know what it is: ## "<x_wmi: The RPC server is unavailable. (-2147023174, 'The RPC server is unavailable. ', (0, None, 'The RPC server is unavailable. ', None, None, -2147023174), None)>" if re.search( 'The client cannot connect to the destination specified in the request', msg, re.I): ## Remove the rest of the fluff msg = 'The client cannot connect to the destination specified in the request. Verify that the service on the destination is running and is accepting requests.' logger.debug('Main Exception: {exception!r}', exception=msg) else: logger.debug('Main Exception: {exception!r}', exception=stacktrace)
Author: Chris Satterthwaite (CS) Contributors: Version info: 1.0 : (CS) Created Jan 3, 2018 """ from contextlib import suppress import sys import os import subprocess import utils from protocolWrapperShell import Shell, NonBlockingStreamReader ## Using an externally provided library defined in globalSettings and located ## in '<install_path>/external'. externalProtocolLibrary = utils.loadExternalLibrary( 'externalProtocolPowerShell') class PowerShell(Shell): """Wrapper class for PowerShell.""" def __init__(self, runtime, logger, endpoint, reference, protocol, **kwargs): if ('shellExecutable' not in kwargs or kwargs['shellExecutable'] is None): ## Static v1.0 path still valid on v5.1, however relative paths work ## best with different environments setup through user preferences #kwargs['shellExecutable'] = 'C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' kwargs['shellExecutable'] = 'powershell.exe' self.exitStatusPassRegEx = '^True$' self.exitStatusFailRegEx = '^False$' super().__init__(runtime, logger, endpoint, protocol, **kwargs)
"""External utility to work with WMI connections. Externally referenced function: | connection : called by protocolWrapperWmi to make a WMI connection The intention with an external wrapper, is to move responsibility of protecting sensitive data away from the open-source platform. From a modular perspective, this module would be best coded as a single Python class. However, doing that provides easier access to internals and so we intentionally avoid encapsulation with individual functions. """ import wmi import utils externalProtocolHandler = utils.loadExternalLibrary('externalProtocolHandler') def connection(runtime, protocol, endpoint, namespace="root/cimv2"): """Extract user & password from protocol, and call wmi.WMI().""" protocol = externalProtocolHandler.extractProtocol(runtime, protocol) user = protocol['user'] password = protocol['password'] return wmi.WMI(moniker=namespace, computer=endpoint, user=user, password=password)
## Add openContentPlatform directories onto the sys path thisPath = os.path.dirname(os.path.abspath(__file__)) basePath = os.path.abspath(os.path.join(thisPath, '..')) if basePath not in sys.path: sys.path.append(basePath) import env env.addLibPath() ## From openContentPlatform import utils from database.connectionPool import DatabaseClient from database.schema.platformSchema import ProtocolSnmp, ProtocolWmi from database.schema.platformSchema import ProtocolSsh, ProtocolPowerShell from database.schema.platformSchema import ProtocolRestApi, Realm externalEncryptionLibrary = utils.loadExternalLibrary('externalEncryptionLibrary', env) def getPassInput(column): """Simple validation and transformation of a password.""" prettyEncoding = None pprompt = lambda: (getpass.getpass(' {}: '.format(column)), getpass.getpass(' retype {}: '.format(column))) while 1: pass1, pass2 = pprompt() if pass1 != pass2: print('Entries do not match; try again...') continue break prettyEncoding = externalEncryptionLibrary.encode(pass1) ## end getPassInput return prettyEncoding
Classes: | Snmp : wrapper class for SNMP .. hidden:: Author: Chris Satterthwaite (CS) Contributors: Version info: 1.0 : (CS) Created Jan 1, 2018 2.0 : (CS) Migrated to using external library, Apr 28, 2020 """ ## Using an externally provided library defined in globalSettings and located ## in '<install_path>/external'. import utils externalProtocolLibrary = utils.loadExternalLibrary('externalProtocolSnmp') ## Pysnmp is used in the external library: ## from pysnmp.hlapi import * ## To call these functions: ## getCmd(SnmpEngine(), CommunityData(communityString), ## UdpTransportTarget((endpoint, port)), ContextData(), ## ObjectType(ObjectIdentity(oid))) ## nextCmd(SnmpEngine(), CommunityData(communityString), ## UdpTransportTarget((endpoint, port)), ContextData(), ## ObjectType(ObjectIdentity(oid)), lexicographicMode=False) class Snmp: """Wrapper class for SNMP.""" def __init__(self, runtime, logger, endpoint, reference, protocol):
def main(): """Entry point for the database configuration utility. Usage:: $ python configureDatabase.py """ try: ## Setup requested log handlers logEntity = 'Database' logger = utils.setupLogger(logEntity, env, 'logSettingsCore.json') logger.info('Starting configureDatabase utility.') ## Using an externally provided library to create and/or update a local ## config file for database parameters; defined in globalSettings and ## located in '<install_path>/external/'. globalSettings = utils.loadSettings( os.path.join(env.configPath, 'globalSettings.json')) externalLibrary = utils.loadExternalLibrary('externalDatabaseLibrary', env) dbClient = None while dbClient is None: try: ## Get settings from user (new or updated) and save to file externalLibrary.updateSettingsFile(globalSettings, logger) ## Attempt connection with the new or updated settings dbClient = DatabaseClient(logger) ## In case we fall through the cracks without an exception... if dbClient is None: ## The settings didn't work; request a new set print( 'Failed to connect to database with provided settings; try again...' ) logger.debug( 'Failed to connect to database with provided settings; try again...' ) except exc.OperationalError: ## Intentionally catch database connection errors print('\nException in configureDatabase: {}'.format( str(sys.exc_info()[1]))) logger.error('Exception in configureDatabase: {}'.format( str(sys.exc_info()[1]))) ## The settings didn't work; request a new set print( '\nFailed to connect to database with provided settings; try again...' ) logger.debug( 'Failed to connect to database with provided settings; try again...' ) print('\nDatabase connection successful\n') logger.debug('Database connection successful') ## Close the connection dbClient.close() logger.info('Exiting configureDatabase utility.') except: stacktrace = traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]) print('Failure in configureDatabase.main: {}'.format(stacktrace)) with suppress(Exception): logger.debug('Failure in configureDatabase: {}'.format(stacktrace)) ## end main return
.. hidden:: Author: Chris Satterthwaite (CS) Contributors: Version info: 1.0 : (CS) Created Nov 24, 2020 """ import sys import traceback import socket ## Using an externally provided library defined in globalSettings and located ## in '<install_path>/external'. import utils externalProtocolLibrary = utils.loadExternalLibrary( 'externalProtocolSqlPostgres') ## Fabric is used by the external library: ## from fabric import Connection ## To call this function for a remote connection: ## Connection(host, user, connect_timeout, connect_kwargs) class SqlPostgres(): """Wrapper class for SQL connections.""" def __init__(self, runtime, logger, endpoint, reference, protocol,