import json
import logging
from os import path
class ForticlientHelper:
data_path = '/Library/Application Support/Fortinet/FortiClient/data/'
vpn_data = '/Library/Application Support/Fortinet/FortiClient/conf/vpn.plist'
def __init__(self):
#
# Map file containing data to aggregator handhake key
#
self.data_files_map = {
'fct_uid.conf' : 'forticlient_serial',
'EMS_sn.conf' : 'ems_serial'
}
self.log = logging.getLogger()
def parse_address(self, url):
try:
import urllib.parse as urlparse
parsed = urlparse.urlparse(url)
if parsed.scheme == '':
parsed = urlparse.urlparse("http://" + url)
host = parsed.netloc
try:
idx = host.index(':')
host = host[0:idx]
except:
pass
host_parts = host.lower().split('.')
if len(host_parts) < 4:
return None
if host_parts[-1] == 'com' and host_parts[-2] == 'fortisase' and host_parts[-4] == 'edge':
return host_parts[-3]
return None
except:
return None
"""
To determine the environment for FortiSASE, we expect
to find a server address of the form:
<name0>.edge.<environment>.fortisase.com
where name0 is arbitrary, and environment is what
we will pass to the aggregator.
"""
def get_vpn_environment(self):
import plistlib
with open(self.vpn_data, 'rb') as f:
data = plistlib.load(f)
for profileInfo in data['Profiles'].values():
server_name = profileInfo.get('Server', None)
if server_name:
env = self.parse_address(server_name)
if env:
return env
raise Exception('No environment profile found')
def get_handshake_data(self):
if not path.isdir(self.data_path):
raise Exception('Missing forticlient data')
rv = {}
key_count = 0
for file, hs_key in self.data_files_map.items():
key_count += 1
with open(path.join(self.data_path, file), 'r') as df:
dv = df.readline().strip()
if len(dv) > 0:
rv[hs_key] = dv
if len(rv.keys()) != key_count:
raise Exception('Missing forticlient keys')
try:
rv['forticlient_environment'] = self.get_vpn_environment()
except:
raise Exception('Missing VPN data')
return rv