def test_fauxapi_not_installed(mock_requests_get):

    fauxapi = PfsenseFauxapi(host=None, apikey=None, apisecret=None)
    mock_requests_get.return_value.status_code = 404
    with pytest.raises(Exception) as exception_info:
        fauxapi.config_get()

    assert 'Unable to find FauxAPI on target host' in str(exception_info.value)
Beispiel #2
0
    def update(self):
        """Check the current state of the rule in pfSense"""
        import pprint, sys
        from PfsenseFauxapi.PfsenseFauxapi import PfsenseFauxapi

        _LOGGER.debug("Getting pfSense current rule state for %s",
                      self._rule_name)
        try:
            # Setup connection with devices/cloud
            FauxapiLib = PfsenseFauxapi(self._host,
                                        self._api_key,
                                        self._access_token,
                                        debug=True)

            # Get the current set of filters
            filters = FauxapiLib.config_get('filter')

            for rule in filters['rule']:
                if (rule.get('tracker') == self._tracker_id):
                    _LOGGER.debug(
                        "Found rule with tracker %s, updating state.",
                        self._tracker_id)
                    if ('disabled' in rule):
                        self._state = False
                    else:
                        self._state = True
        except:
            _LOGGER.error(
                "Problem retrieving rule set from pfSense host: %s.  Likely due to API key or secret.",
                self._host)
def test_config_get(mock_requests_get):

    fauxapi = PfsenseFauxapi(host=None, apikey=None, apisecret=None)
    mock_requests_get.return_value.status_code = 200
    mock_requests_get.return_value.text = '{"callid": "b905cb4ef8db8", "action": "config_get", "message": "ok", "data": { "config": {"version": "18.9", "lastchange": "", "system": {}} }}'

    response = fauxapi.config_get()
    assert response['version'] == '18.9'
Beispiel #4
0
def setup_platform(hass, config, add_entities, discovery_info=None):
    """Initialize the platform"""
    """Setup the pfSense Rules platform."""
    import pprint, sys
    from PfsenseFauxapi.PfsenseFauxapi import PfsenseFauxapi

    # Assign configuration variables. The configuration check takes care they are
    # present.
    host = config.get(CONF_HOST)
    api_key = config.get(CONF_API_KEY)
    access_token = config.get(CONF_ACCESS_TOKEN)
    rule_prefix = config.get(CONF_RULE_FILTER)

    _LOGGER.debug(
        "Connecting to pfSense firewall to collect rules to add as switches.")

    try:
        FauxapiLib = PfsenseFauxapi(host, api_key, access_token, debug=True)

        # Get the current set of filters
        filters = FauxapiLib.config_get('filter')

        _LOGGER.debug("Found %s rules in pfSense", len(filters['rule']))

        if rule_prefix:
            _LOGGER.debug("Filter for rules starting with %s being applied",
                          rule_prefix)

        rules = []
        # Iterate through and find rules
        i = 0
        for rule in filters['rule']:
            tracker = rule.get('tracker')
            if tracker == None:
                _LOGGER.warning("Skipping rule (no tracker_id): " +
                                rule['descr'])
            else:
                if rule_prefix:
                    if (rule['descr'].startswith(rule_prefix)):
                        _LOGGER.debug("Found rule %s", rule['descr'])
                        new_rule = pfSense('pfsense_' + rule['descr'],
                                           rule['descr'], tracker, host,
                                           api_key, access_token)
                        rules.append(new_rule)
                else:
                    _LOGGER.debug("Found rule %s", rule['descr'])
                    new_rule = pfSense('pfsense_' + rule['descr'],
                                       rule['descr'], tracker, host, api_key,
                                       access_token)
                    rules.append(new_rule)
            i = i + 1

        # Add devices
        add_entities(rules)
    except Exception as e:
        _LOGGER.error(
            "Problem getting rule set from pfSense host: %s.  Likely due to API key or secret. More Info:"
            + str(e), host)
Beispiel #5
0
    def set_rule_state(self, action):
        """Setup the pfSense Rules platform."""
        import pprint, sys
        from PfsenseFauxapi.PfsenseFauxapi import PfsenseFauxapi

        _LOGGER.debug("Connecting to pfSense firewall to change rule states.")
        try:
            # Setup connection with devices/cloud
            FauxapiLib = PfsenseFauxapi(self._host,
                                        self._api_key,
                                        self._access_token,
                                        debug=True)

            # Get the current set of filters
            filters = FauxapiLib.config_get('filter')
        except:
            _LOGGER.error(
                "Problem retrieving rule set from pfSense host: %s.  Likely due to API key or secret.",
                self._host)

        i = 0
        for rule in filters['rule']:
            if (rule.get('tracker') == self._tracker_id):
                _LOGGER.info("Found rule changing state rule: %s",
                             self._rule_name)
                if (action == True):
                    if ('disabled' in rule):
                        del filters['rule'][i]['disabled']
                        _LOGGER.debug(
                            "Rule %s enabled in config (this has not been pushed back to firewall yet!)",
                            self._rule_name)
                elif (action == False):
                    filters['rule'][i]['disabled'] = ""
                    _LOGGER.debug(
                        "Rule %s disabled in config (this has not been pushed back to firewall yet!)",
                        self._rule_name)
            i = i + 1

        try:
            _LOGGER.debug("Sending updated rule set to pfSense firewall")
            # Push the config back to pfSense
            filters = FauxapiLib.config_set(filters, 'filter')

            _LOGGER.debug(
                "Reloading the config on pfSense firewall to accept rule changes"
            )
            # Reload the config
            FauxapiLib.send_event("filter reload")
        except:
            _LOGGER.error(
                "Problem sending & reloading rule set from pfSense host: %s.  Likely due to API key or secret.",
                self._host)
Beispiel #6
0
class UpdateAwsAliasesFauxapi():

    fauxapi_host = None
    fauxapi_apikey = None
    fauxapi_apisecret = None

    system_config = None
    aws_ipranges_uri = 'https://ip-ranges.amazonaws.com/ip-ranges.json'

    FauxapiLib = None

    def __init__(self,
                 fauxapi_host,
                 fauxapi_apikey,
                 fauxapi_apisecret,
                 debug=False):
        self.FauxapiLib = PfsenseFauxapi(fauxapi_host, fauxapi_apikey,
                                         fauxapi_apisecret, debug)

    def update(self,
               regions_match='*',
               services_match='*',
               ipv4=True,
               ipv6=True):

        # Use FauxapiLib to load the remote system config into memory
        self.system_config = self.FauxapiLib.config_get()

        # download ip-ranges.json parse and iterate
        for name, data in sorted(self.get_aws_ipranges().items()):
            if regions_match == '*' or regions_match.replace('*', '').replace(
                    '-', '').lower() in name:
                if services_match == '*' or services_match.replace(
                        '*', '').replace('_', '').lower() in name:
                    addresses = []
                    if ipv4 is True and len(data['ipv4']) > 0:
                        addresses += data['ipv4']
                    if ipv6 is True and len(data['ipv6']) > 0:
                        addresses += data['ipv6']
                    self.update_alias_in_config(
                        name=name,
                        description=data['description'],
                        addresses=addresses,
                        aws_create_date=data['aws_create_date'])

        # Use FauxapiLib to save to the remote system the new edited config
        result = self.FauxapiLib.config_set(self.system_config)
        print(json.dumps(result))

    def update_alias_in_config(self, name, description, addresses,
                               aws_create_date):

        addresses.sort()

        # candidate alias to apply
        alias_data = {
            'name':
            name,
            'type':
            'network',
            'address':
            ' '.join(addresses),
            'descr':
            description,
            'detail':
            '||'.join(
                ['ip-ranges.json createDate: {}'.format(aws_create_date)] *
                len(addresses))
        }

        if 'aliases' not in self.system_config or type(
                self.system_config['aliases']) is not dict:
            self.system_config['aliases'] = {}

        if 'alias' not in self.system_config['aliases'] or type(
                self.system_config['aliases']['alias']) is not list:
            self.system_config['aliases']['alias'] = []

        alias_found = False
        for index, alias in enumerate(self.system_config['aliases']['alias']):
            if alias['name'] == name:
                alias_found = True
                if alias['address'] != alias_data['address']:
                    self.system_config['aliases']['alias'][index] = alias_data

        if alias_found is False:
            self.system_config['aliases']['alias'].append(alias_data)

    def get_aws_ipranges(self):

        with urllib.request.urlopen(self.aws_ipranges_uri) as response:
            aws_ipranges_data = json.loads(response.read())

        ipranges = {}
        for prefix in aws_ipranges_data['prefixes'] + aws_ipranges_data[
                'ipv6_prefixes']:

            name = 'aws_{}_{}'.format(
                prefix['region'].replace('-', '').lower(),
                prefix['service'].replace('_', '').lower())[:32]

            if name not in ipranges:
                ipranges[name] = {
                    'ipv4': [],
                    'ipv6': [],
                    'description':
                    'AWS {region} {service}'.format(region=prefix['region'],
                                                    service=prefix['service']),
                    'aws_create_date':
                    aws_ipranges_data['createDate']
                }

            if 'ip_prefix' in prefix and len(prefix['ip_prefix']) > 0:
                ipranges[name]['ipv4'].append(prefix['ip_prefix'])

            if 'ipv6_prefix' in prefix and len(prefix['ipv6_prefix']) > 0:
                ipranges[name]['ipv6'].append(prefix['ipv6_prefix'])

        return ipranges
Beispiel #7
0
# check args and env exist
if(len(sys.argv) != 2) or not os.getenv('FAUXAPI_APIKEY') or not os.getenv('FAUXAPI_APISECRET'):
    usage()

# config
fauxapi_host=sys.argv[1]
fauxapi_apikey=os.getenv('FAUXAPI_APIKEY')
fauxapi_apisecret=os.getenv('FAUXAPI_APISECRET')


FauxapiLib = PfsenseFauxapi(fauxapi_host, fauxapi_apikey, fauxapi_apisecret, debug=False)


# config get the full configuration and simply print to console
# =============================================================================
config = FauxapiLib.config_get()
print(json.dumps(
    config
))

# config set the full configuration
# =============================================================================
# NB: nothing amazing is happening here, we are simply writing back the same (full) configuration again, the developer
# most likely wants to make changes to `config` before calling the config_set function again here
print(json.dumps(
    FauxapiLib.config_set(config)
))

# config_get, config_set by section
# =============================================================================
# perform a second config_get > config_set this time within the 'aliases' section only
Beispiel #8
0
class PfSense:
    """
    PfSense Thingy...
    ...
    Methods
    -------
    get_openvpn_settings(self) -> dict:
    set_pfsense_config(self, data: dict, vpnid: list, refresh: bool = None) -> dict:
    get_pf_openvpn_clients(self) -> dict:
    get_pf_openvpn_locations(self, vpn_clients: dict) -> set:
    """
    def __init__(self):
        self.host = getenv("HOST_ADDRESS")
        self.port = 443
        self.key = getenv("FAUXAPI_KEY")
        self.secret = getenv("FAUXAPI_SECRET")
        try:
            PfsenseFauxapi(f"{self.host}:{self.port}", self.key, self.secret)
        except PfsenseFauxapiException as e:
            print(f"error: {str(e)}")
        else:
            self.pfapi = PfsenseFauxapi(f"{self.host}:{self.port}", self.key,
                                        self.secret)

    def get_openvpn_settings(self) -> dict:
        try:
            pf_openvpn_settings = self.pfapi.config_get('openvpn')
        except PfsenseFauxapiException as e:
            return {"error": str(e)}
        else:
            return pf_openvpn_settings

    def set_pfsense_config(self,
                           data: dict,
                           vpnid: list,
                           refresh: bool = None) -> dict:
        """
        Parameters
        ----------
        data : dict
            .
        vpnid : list
            .
        refresh : bool
            .
        """
        try:
            resp = self.pfapi.config_set(data, 'openvpn')
        except PfsenseFauxapiException as e:
            return {"error": str(e)}
        else:
            if refresh:
                self.pfapi.config_reload()
            if len(vpnid):
                for vid in vpnid:
                    data = self.pfapi.function_call({
                        "function":
                        "openvpn_restart_by_vpnid",
                        "args": ["client", f"{vid}"]
                    })
            return resp

    def get_pf_openvpn_clients(self) -> dict:
        clients: list = []
        vpn_clients = self.get_openvpn_settings()
        if "error" in vpn_clients.keys():
            return vpn_clients

        locations: set = self.get_pf_openvpn_locations(vpn_clients)
        for vpnclient in vpn_clients["openvpn-client"]:
            clients.append(vpnclient["server_addr"])

        return {"clients": clients, "locations": list(locations)}

    def get_pf_openvpn_locations(self, vpn_clients: dict) -> set:
        """
        Parameters
        ----------
        vpn_clients : dict
            .
        """
        locations = set()
        for client in vpn_clients["openvpn-client"]:
            loc = is_vpn_address(client["server_addr"])
            if loc is not None:
                locations.add(loc[1].lower())
        return locations
Beispiel #9
0
class UserGroupManagementFauxapi():

    fauxapi_host = None
    fauxapi_apikey = None
    fauxapi_apisecret = None

    system_config = None

    FauxapiLib = None

    def __init__(self,
                 fauxapi_host,
                 fauxapi_apikey,
                 fauxapi_apisecret,
                 debug=False):
        self.FauxapiLib = PfsenseFauxapi(fauxapi_host, fauxapi_apikey,
                                         fauxapi_apisecret, debug)

    # user functions
    # =========================================================================

    def get_users(self):
        self._reload_system_config()

        response_data = {}
        for user in self.system_config['system']['user']:
            response_data[user['name']] = user
            del (response_data[user['name']]['name'])
        return response_data

    def add_user(self, username):
        self._reload_system_config()

        user_index, user = self._get_entity('user', username)
        if user_index is not None:
            raise UserGroupManagementFauxapiException('user already exists',
                                                      username)

        user = {
            'scope': 'user',
            'bcrypt-hash': 'no-password-set',
            'descr': '',
            'name': username,
            'expires': '',
            'dashboardcolumns': '2',
            'authorizedkeys': '',
            'ipsecpsk': '',
            'webguicss': 'pfSense.css',
            'uid': self._get_next_id('uid'),
        }

        patch_system_user = {
            'system': {
                'user': self.system_config['system']['user']
            }
        }
        patch_system_user['system']['user'].append(user)

        response = self.FauxapiLib.config_patch(patch_system_user)
        if response['message'] != 'ok':
            raise UserGroupManagementFauxapiException('unable to add user',
                                                      response['message'])

        self._increment_next_id('uid')

        return user

    def manage_user(self, username, attributes):
        self._reload_system_config()

        valid_attributes = [
            'password', 'descr', 'expires', 'dashboardcolumns',
            'authorizedkeys', 'ipsecpsk', 'webguicss', 'disabled', 'priv'
        ]

        user_index, user = self._get_entity('user', username)
        if user_index is None:
            raise UserGroupManagementFauxapiException('user does not exist',
                                                      username)

        if type(attributes) != dict:
            raise UserGroupManagementFauxapiException(
                'attributes is incorrect type')

        for attribute, value in attributes.items():
            if attribute not in valid_attributes:
                raise UserGroupManagementFauxapiException(
                    'unsupported attribute type', attribute)

            if attribute == 'disabled':
                if value is True:
                    user[attribute] = ''
                else:
                    if attribute in user:
                        del (user[attribute])
            elif attribute == 'password':
                user['bcrypt-hash'] = bcrypt.hashpw(
                    value.encode('utf8'), bcrypt.gensalt()).decode('utf8')
            else:
                if len(value) == 0 and attribute in user:
                    del (user[attribute])
                elif len(value) > 0:
                    user[attribute] = value

        patch_system_user = {
            'system': {
                'user': self.system_config['system']['user']
            }
        }
        patch_system_user['system']['user'][user_index] = user

        response = self.FauxapiLib.config_patch(patch_system_user)
        if response['message'] != 'ok':
            raise UserGroupManagementFauxapiException('unable to manage user',
                                                      response['message'])

        return user

    def remove_user(self, username):
        self._reload_system_config()

        user_index, user = self._get_entity('user', username)
        if user_index is None:
            raise UserGroupManagementFauxapiException('user does not exist',
                                                      username)

        patch_system_user = {
            'system': {
                'user': self.system_config['system']['user']
            }
        }
        del (patch_system_user['system']['user'][user_index])

        response = self.FauxapiLib.config_patch(patch_system_user)
        if response['message'] != 'ok':
            raise UserGroupManagementFauxapiException('unable to remove user',
                                                      response['message'])

        return user

    # group functions
    # =========================================================================

    def get_groups(self):
        self._reload_system_config()

        response_data = {}
        for group in self.system_config['system']['group']:
            response_data[group['name']] = group
            del (response_data[group['name']]['name'])
        return response_data

    def add_group(self, groupname):
        self._reload_system_config()

        group_index, group = self._get_entity('group', groupname)
        if group_index is not None:
            raise UserGroupManagementFauxapiException('group already exists',
                                                      groupname)

        group = {
            'scope': 'local',
            'description': '',
            'name': groupname,
            'gid': self._get_next_id('gid'),
        }

        patch_system_group = {
            'system': {
                'group': self.system_config['system']['group']
            }
        }
        patch_system_group['system']['group'].append(group)

        response = self.FauxapiLib.config_patch(patch_system_group)
        if response['message'] != 'ok':
            raise UserGroupManagementFauxapiException('unable to add group',
                                                      response['message'])

        self._increment_next_id('gid')

        return group

    def manage_group(self, groupname, attributes):
        self._reload_system_config()

        valid_attributes = ['description', 'member', 'priv']

        group_index, group = self._get_entity('group', groupname)
        if group_index is None:
            raise UserGroupManagementFauxapiException('group does not exist',
                                                      groupname)

        if type(attributes) != dict:
            raise UserGroupManagementFauxapiException(
                'attributes is incorrect type')

        for attribute, value in attributes.items():
            if attribute not in valid_attributes:
                raise UserGroupManagementFauxapiException(
                    'unsupported attribute type', attribute)

            if attribute == 'member':
                if type(value) != list:
                    raise UserGroupManagementFauxapiException(
                        'member attribute is incorrect type')
            elif attribute == 'priv':
                if type(value) != list:
                    raise UserGroupManagementFauxapiException(
                        'priv attribute is incorrect type')

            if len(value) == 0 and attribute in group:
                del (group[attribute])
            elif len(value) > 0:
                group[attribute] = value

        patch_system_group = {
            'system': {
                'group': self.system_config['system']['group']
            }
        }
        patch_system_group['system']['group'][group_index] = group

        response = self.FauxapiLib.config_patch(patch_system_group)
        if response['message'] != 'ok':
            raise UserGroupManagementFauxapiException('unable to manage group',
                                                      response['message'])

        return group

    def remove_group(self, groupname):
        self._reload_system_config()

        group_index, group = self._get_entity('group', groupname)
        if group_index is None:
            raise UserGroupManagementFauxapiException('group does not exist',
                                                      groupname)

        patch_system_group = {
            'system': {
                'group': self.system_config['system']['group']
            }
        }
        del (patch_system_group['system']['group'][group_index])

        response = self.FauxapiLib.config_patch(patch_system_group)
        if response['message'] != 'ok':
            raise UserGroupManagementFauxapiException('unable to remove group',
                                                      response['message'])

        return group

    # internal helper functions
    # =========================================================================

    def _get_entity(self, entity_type, entity_name):

        entity = None
        entity_index = 0
        for entity_data in self.system_config['system'][entity_type]:
            if entity_data['name'] == entity_name:
                entity = entity_data
                break
            entity_index += 1

        if entity is None:
            return None, None

        return entity_index, entity

    def _get_next_id(self, id_type):
        id_name = 'next{}'.format(id_type)
        return self.system_config['system'][id_name]

    def _increment_next_id(self, id_type):
        id_name = 'next{}'.format(id_type)
        next_id = int(self._get_next_id(id_type)) + 1
        patch_system_nextid = {'system': {id_name: str(next_id)}}
        response = self.FauxapiLib.config_patch(patch_system_nextid)
        if response['message'] != 'ok':
            raise UserGroupManagementFauxapiException(
                'unable to increment the nextid', id_type)
        return next_id

    def _reload_system_config(self):
        self.system_config = self.FauxapiLib.config_get()
class pfSenseInfluxCollector:
	def __init__(self, config_file):
		"""Program to send pfSense information collected from FauxAPI to InfluxDB"""
		self.config = configparser.ConfigParser()
		self.config.read(config_file)
		self.fauxapi = PfsenseFauxapi(self.config['FAUXAPI']['APIHost'], self.config['FAUXAPI']['APIKey'], self.config['FAUXAPI']['APISecret'])
		self.influx_client = InfluxDBClient(host=self.config['INFLUXDB']['InfluxDBHost'], port=self.config['INFLUXDB']['Port'],
			username=self.config['INFLUXDB']['Username'], password=self.config['INFLUXDB']['Password'], database=self.config['INFLUXDB']['Database'])
		self.pfSense_config = self.fauxapi.config_get()
		self.pfSense_host = self.pfSense_config['system']['hostname'] + "." + self.pfSense_config['system']['domain']

	def run(self):
		"""Run enabled modules wuth delay as defined in config file"""
		threading.Timer(int(self.config['GENERAL']['Delay']), self.run).start()
		for function in self.module_dictionary:
			if self.config['MODULES'].getboolean(function):
				self.module_dictionary[function](self)

	def fauxapi_function_call(self, functionName):
		"""Call fauxapi function_call without function arguments"""
		data = {
			"function": functionName
		}
		return self.fauxapi.function_call(data)['data']['return']

	def fauxapi_function_call_args(self, functionName, args):
		"""Call fauxapi function_call function with arguments"""
		data = {
			"function": functionName,
			"args": args
		}
		return self.fauxapi.function_call(data)['data']['return']

	def write_influxdb_data(self, data):
		"""Write set of data to InfluxDB."""
		self.influx_client.write_points(data)

	def gateway_status(self):
		"""Get and save information about statuses of gateways."""
		gateways = self.fauxapi_function_call_args("return_gateways_status", "true")
		for gateway in gateways:
			gateway_status = 0 if gateways[gateway]['status'] == "down" else 1
			gateway_data = [
				{
					"measurement": "gateway_status",
					"fields": {
						"name": gateways[gateway]['name'],
						"rtt": gateways[gateway]['delay'],
						"rttsd": gateways[gateway]['stddev'],
						"status": gateway_status
					},
					"tags": {
						"host": self.pfSense_host
					}
				}
			]
			self.write_influxdb_data(gateway_data)

	def interface_statistics(self):
		"""Get and save information about interfaces statistics."""
		interface_descriptions = self.fauxapi_function_call("get_configured_interface_with_descr")
		for interface in interface_descriptions:
			interface_info = self.fauxapi_function_call_args("get_interface_info", interface)
			interface_data = [
				{
					"measurement": "interface_statistics",
					"fields": {
						"bytes_in": interface_info['inbytes'],
						"bytes_out": interface_info['outbytes'],
						"collisions": interface_info['collisions'],
						"errors_in": interface_info['inerrs'],
						"errors_out": interface_info['outerrs'],
						"name": interface_descriptions[interface],
						"packets_in": interface_info['inpkts'],
						"packets_out": interface_info['outpkts']
					},
					"tags": {
						"host": self.pfSense_host,
						"interface": interface_info['if']
					}
				}
			]
			self.write_influxdb_data(interface_data)

	def interface_status(self):
		"""Get and save information about statuses of interfaces."""
		interface_descriptions = self.fauxapi_function_call("get_configured_interface_with_descr")
		for interface in interface_descriptions:
			interface_info = self.fauxapi_function_call_args("get_interface_info", interface)
			interface_data = [
				{
					"measurement": "interface_status",
					"fields": {
						"ip_address": interface_info['ipaddr'],
						"name": interface_descriptions[interface],
						"status": 1 if interface_info['status'] == 'up' else 0
					},
					"tags": {
						"host": self.pfSense_host,
						"interface": interface_info['if']
					}
				}
			]
			self.write_influxdb_data(interface_data)

	def openvpn_client_status(self):
		"""Get and save information about OpenVPN clients."""
		for client in self.fauxapi_function_call("openvpn_get_active_clients"):
			client_data = [
				{
					"measurement": "openvpn_client_status",
					"fields": {
						"remote_host": client['remote_host'],
						"status": 1 if client['status'] == "up" else 0,
						"virtual_address": client['virtual_addr']
					},
					"tags": {
						"host": self.pfSense_host,
						"vpnid": int(client['vpnid']),
					}
				}
			]
			self.write_influxdb_data(client_data)

	def openvpn_connected_clients(self):
		"""Get and save information about connected clients to OpenVPN server."""
		for server in self.fauxapi_function_call("openvpn_get_active_servers"):
			server_name = server['name']
			for connection in server['conns']:
				connection_data = [
					{
						"measurement": "openvpn_connected_clients",
						"fields": {
							"client_id": int(connection['client_id']),
							"common_name": connection['common_name'],
							"remote_host": connection['remote_host'],
							"virtual_address": connection['virtual_addr']
						},
						"tags": {
							"host": self.pfSense_host,
							"server": server_name
						}
					}
				]
				self.write_influxdb_data(connection_data)
			connected_clients_data = [
				{
					"measurement": "openvpn_connected_clients",
					"fields": {
						"connected_clients": len(server['conns'])
					},
					"tags": {
						"host": self.pfSense_host,
						"server": server_name
					}
				}
			]
			self.write_influxdb_data(connected_clients_data)

	def services_status(self):
		"""Get and save information about statuses of services."""
		for service in self.fauxapi_function_call("get_services")[1:]:
			service_status = self.fauxapi_function_call_args("get_service_status", [service])
			service_data = [
				{
					"measurement": "services_status",
					"fields": {
						"description": service['description'],
						"status": 1 if service_status else 0
					},
					"tags": {
						"host": self.pfSense_host,
						"service": service['name']
					}
				}
			]
			self.write_influxdb_data(service_data)

	# Module Dictionary to allow dynamic calling of functions depending on config file
	module_dictionary = {"Gateway_Status": gateway_status, "Interface_Statistics": interface_statistics,
		"Interface_Status": interface_status, "OpenVPN_Client_Status": openvpn_client_status, "OpenVPN_Connected_Clients": openvpn_connected_clients,
		"Services_Status": services_status}