def get_value_from_sample(key, sample_path=None): """Get suggestion from sample config.""" fallback_path = None fallback_defaults = None if sample_path is None: container = _helper.sanitize_path( os.path.dirname(os.path.realpath(__file__))) sample_path = container + '/sovpn.json' fallback_path = sample_path override = container + 'local/' if not os.path.isdir(override): override = None if override and os.path.isfile(override + '/sovpn.json'): sample_path = override + '/sovpn.json' sample = _helper.read_file_as_value(sample_path) defaults = json.loads(sample) if fallback_path: fallback = _helper.read_file_as_value(fallback_path) fallback_defaults = json.loads(fallback) if key in defaults['server']: return defaults['server'][key] if fallback_defaults: if key in fallback_defaults['server']: return fallback_defaults['server'][key] return None
def ipv4(self): """Returns value of IPv4 property.""" ipv4 = self.settings['server']['ipv4'] if ipv4 is None: value = _helper.fetch_external_ipv4() if _helper.is_valid_ipv4(value): ipv4 = value return ipv4
def clients_dir(sample_path=None): # pylint: disable=E0602 """Getting suggestion for clients_dir.""" suggestion = __class__.get_value_from_sample(_helper.current_method(), sample_path) if suggestion is None: suggestion = _helper.sanitize_path( os.path.expanduser('~')) + 'openvpn-clients' return suggestion
def hostname(sample_path=None): # pylint: disable=E0602 """Returns suggestion for hostname.""" suggestion = __class__.get_value_from_sample(_helper.current_method(), sample_path) if suggestion is None: suggestion = _helper.fetch_hostname_by_system() if suggestion is None: suggestion = _helper.fetch_hostname_by_reverse_dns() return suggestion
def needs_setup(): """Check if the script needs to run initial setup.""" container = _helper.sanitize_path( os.path.dirname(os.path.realpath(__file__))) sovpn_config_pointer = container + 'sovpn_config_pointer.txt' if not os.path.isfile(sovpn_config_pointer): return True sovpn_config_file = _helper.read_file_as_value(sovpn_config_pointer) if os.path.isfile(sovpn_config_file): return False return True
def client_page(share_hash): """Display all flavours of client's config files to user.""" slug = DB.find_client_slug_by_share_hash(share_hash) if slug is None: abort(404) if ALLOWED_SLUGS is not None: if slug not in ALLOWED_SLUGS: abort(403) data = dict() data['css'] = SHARE.css data['slug'] = slug data['client_name'] = slug data['list_items'] = '' files = os.listdir(PATH + slug) for config_file in files: if config_file == 'pretty-name.txt': data['client_name'] = _helper.read_file_as_value(PATH + slug + '/' + config_file) continue anchor = '<a href="' + share_hash + '/' + config_file + '">' + config_file + '</a>' data['list_items'] += '<li>' + anchor + '</li>' renderer = pystache.Renderer() return renderer.render_path(SHARE.template_path, data)
def rotate_share_hashes(self): """Generates share hashes for clients who can be found in database.""" sovpn_data = SimplifiedOpenvpnData() slugs = sovpn_data.get_all_client_slugs() for slug in slugs: share_hash = _helper.generate_share_hash( slug, self._config.sovpn_share_salt) sovpn_data.rotate_share_hash(slug, share_hash)
def __init__(self): """Initialises SimplifiedOpenvpnShare class.""" self.container = _helper.sanitize_path( os.path.dirname(os.path.realpath(__file__))) self.override = self.container + 'local/' if not os.path.isdir(self.override): self.override = None
def generate_config_files(self, verbose=True): """Generates different flavours of config files.""" ca_path = self._config.client_dir + 'ca.crt' cert_path = self._config.client_dir + self._config.slug + '.crt' key_path = self._config.client_dir + self._config.slug + '.key' ta_path = self._config.client_dir + 'ta.key' options = self.create_config() # Plain Windows flavour. self.write_config(options) # Plain Debian flavour. options['deb'] = True self.write_config(options, 'deb') options['deb'] = False # Plain RedHat flavour. options['rhel'] = True self.write_config(options, 'rhel') options['rhel'] = False # Inline Windows flavour. options['inline'] = True options['ca'] = _helper.read_file_as_value(ca_path) options['cert'] = _helper.read_file_as_value(cert_path) options['key'] = _helper.read_file_as_value(key_path) options['ta'] = _helper.read_file_as_value(ta_path) self.write_config(options, 'inline') # Inline Debian flavour. options['deb'] = True self.write_config(options, 'inline-deb') options['deb'] = False # Inline RedHat flavour. options['rhel'] = True self.write_config(options, 'inline-rhel') options['rhel'] = False # Clean up. self.cleanup_client_certificates() if verbose: print('> Client "' + self._config.slug + '" was successfully created.')
def __init__(self): """Loads config if possible, else asks you to generate config.""" self.container = _helper.sanitize_path( os.path.dirname(os.path.realpath(__file__))) self._config = SimplifiedOpenvpnConfig() # EasyRSA 2 requires loading environment variables manually. if self._config.easy_rsa_ver == 2: self.load_env()
def sovpn_share_salt(sample_path=None): # pylint: disable=E0602 """Getting suggestion for sovpn_share_salt.""" suggestion = __class__.get_value_from_sample(_helper.current_method(), sample_path) if suggestion is None: chars = string.ascii_letters + string.digits length = random.randint(10, 16) suggestion = ''.join(random.choice(chars) for _ in range(length)) return suggestion
def mgmt_used(sample_path=None): # pylint: disable=E0602 """Getting suggestion for mgmt_used.""" suggestion = __class__.get_value_from_sample(_helper.current_method(), sample_path) if suggestion is True: suggestion = 'Y' elif suggestion is False: suggestion = 'N' return suggestion
def get_value_from_sample(key, sample_path=None): """Get suggestion from sample config.""" if sample_path is None: sample_path = os.path.dirname( os.path.realpath(__file__)) + '/sovpn.json' sample = _helper.read_file_as_value(sample_path) defaults = json.loads(sample) if key in defaults['server']: return defaults['server'][key] return None
def __init__(self, run_setup=True): """Loads config if possible, else asks you to generate config.""" self.container = _helper.sanitize_path( os.path.dirname(os.path.realpath(__file__))) self.override = self.container + 'local/' self.loaded = False self.needs_rotation = False if self.needs_setup(): if run_setup: self.setup() else: self.load()
def hostname(self, value): """Assigns new value to hostname property.""" if value is None: self.settings['server']['hostname'] = None return elif value is False or value == '-': self.settings['server']['hostname'] = False return if not _helper.is_valid_hostname(value): print('Value that you specified as Hostname is invalid: (' + value + ')') else: self.settings['server']['hostname'] = value
def load(self): """Populate properties with values if config file exists.""" if self.sovpn_config_file is None: self.sovpn_config_file = _helper.read_file_as_value( self.sovpn_config_pointer) if os.path.isfile(self.sovpn_config_file): with open(self.sovpn_config_file) as config_file: data = json.load(config_file) for pool in data: for key, value in data[pool].items(): if key in dir(self): setattr(self, key, value) self.loaded = True
def clients_dir(self, value): """Assigns new value to clients_dir property if possible.""" if value is None: self.settings['server']['clients_dir'] = None return if not os.path.isdir(value): _helper.create_directory(value) status = os.path.isdir(value) if not status: print( "Value that you specified as directory for clients is invalid: (" + value + ")") print( 'Make sure that the value you gave meets following requirements:' ) print('> Does the directory really exist in your filesystem?') print( '> The specified directory has write and execute permissions.') exit(1) self.settings['server']['clients_dir'] = _helper.sanitize_path(value)
def port(sample_path=None): # pylint: disable=E0602 """Getting suggestion for port.""" suggestion = __class__.get_value_from_sample(_helper.current_method(), sample_path) return suggestion
def read_sql_file(self, sql_file): """Reads sql from file and returns it.""" sql = _helper.read_file_as_value(self._config.container + 'sql/' + sql_file) return sql
def sovpn_share_address(sample_path=None): # pylint: disable=E0602 """Getting suggestion for sovpn_share_address.""" suggestion = __class__.get_value_from_sample(_helper.current_method(), sample_path) return suggestion
def setup(self): # pylint: disable=R0912 # pylint: disable=R0914 # pylint: disable=R0915 # pylint: disable=W0125 """Set up settings for Simplified OpenVPN on current system.""" config = dict() config['server'] = dict() # Ask value for server_dir property. suggestion_source = self.sovpn_config_file if self.loaded else None suggestion = self.get_suggestion('server_dir', suggestion_source) while self.server_dir is None: prompt = _prompt.get('server_dir', suggestion) server_dir = input(prompt) if server_dir.strip() == '': server_dir = suggestion self.server_dir = server_dir config['server']['server_dir'] = self.server_dir # Ask value for easy_rsa_dir property. suggestion = self.server_dir + 'easy-rsa' while self.easy_rsa_dir is None: prompt = _prompt.get('easy_rsa_dir', suggestion) easy_rsa_dir = input(prompt) if easy_rsa_dir.strip() == '': easy_rsa_dir = suggestion self.easy_rsa_dir = easy_rsa_dir config['server']['easy_rsa_dir'] = self.easy_rsa_dir # Ask value for easy_rsa_ver property. suggestion_source = self.sovpn_config_file if self.loaded else None suggestion = self.get_suggestion('easy_rsa_ver', suggestion_source) while self.easy_rsa_ver is None: prompt = _prompt.get('easy_rsa_ver', suggestion) easy_rsa_ver = input(prompt) if easy_rsa_ver.strip() == '': easy_rsa_ver = suggestion self.easy_rsa_ver = easy_rsa_ver config['server']['easy_rsa_ver'] = self.easy_rsa_ver # Ask value for clients_dir property. suggestion_source = self.sovpn_config_file if self.loaded else None suggestion = self.get_suggestion('clients_dir', suggestion_source) while self.clients_dir is None: prompt = _prompt.get('clients_dir', suggestion) clients_dir = input(prompt) if clients_dir.strip() == '': clients_dir = suggestion self.clients_dir = clients_dir config['server']['clients_dir'] = self.clients_dir # Ask value for hostname property. suggestion_source = self.sovpn_config_file if self.loaded else None suggestion = self.get_suggestion('hostname', suggestion_source) if not self.hostname and self.sovpn_share_url and not suggestion: suggestion = '-' while self.hostname is None: prompt = _prompt.get('hostname', suggestion) hostname = input(prompt).strip() if hostname == '' and suggestion and suggestion != '-': hostname = suggestion elif hostname == '-' or (hostname == '' and suggestion == '-'): hostname = False self.hostname = hostname # If hostname is changes then in most cases we also want to change sharing URL. if suggestion != self.hostname and self.sovpn_share_url: self.sovpn_share_url = None config['server']['hostname'] = self.hostname # Ask value for port property. suggestion_source = self.sovpn_config_file if self.loaded else None suggestion = self.get_suggestion('port', suggestion_source) while self.port is None: prompt = _prompt.get('port', suggestion) port = input(prompt) if port.strip() == '': port = suggestion self.port = port config['server']['port'] = self.port # Ask value for protocol property. suggestion_source = self.sovpn_config_file if self.loaded else None suggestion = self.get_suggestion('protocol', suggestion_source) while self.protocol is None: prompt = _prompt.get('protocol', suggestion) protocol = input(prompt) if protocol.strip() == '': protocol = suggestion self.protocol = protocol config['server']['protocol'] = self.protocol # Ask if management interface will be used. suggestion_source = self.sovpn_config_file if self.loaded else None suggestion = self.get_suggestion('mgmt_used', suggestion_source) while self.mgmt_used is None: prompt = _prompt.get('mgmt_used', suggestion) mgmt_used = input(prompt) if mgmt_used.strip() == '': mgmt_used = suggestion self.mgmt_used = mgmt_used config['server']['mgmt_used'] = self.mgmt_used if self.mgmt_used: # Ask value for mgmt_address property. suggestion_source = self.sovpn_config_file if self.loaded else None suggestion = self.get_suggestion('mgmt_address', suggestion_source) while self.mgmt_address is None: prompt = _prompt.get('mgmt_address', suggestion) mgmt_address = input(prompt) if mgmt_address.strip() == '': mgmt_address = suggestion self.mgmt_address = mgmt_address config['server']['mgmt_address'] = self.mgmt_address # Ask value for mgmt_port property. suggestion_source = self.sovpn_config_file if self.loaded else None suggestion = self.get_suggestion('mgmt_port', suggestion_source) while self.mgmt_port is None: prompt = _prompt.get('mgmt_port', suggestion) mgmt_port = input(prompt) if mgmt_port.strip() == '': mgmt_port = suggestion self.mgmt_port = mgmt_port config['server']['mgmt_port'] = self.mgmt_port # Ask value for sovpn_share_salt property. suggestion_source = self.sovpn_config_file if self.loaded else None suggestion = self.get_suggestion('sovpn_share_salt', suggestion_source) while self.sovpn_share_salt is None: prompt = _prompt.get('sovpn_share_salt', suggestion) sovpn_share_salt = input(prompt) if sovpn_share_salt.strip() == '': sovpn_share_salt = suggestion self.sovpn_share_salt = sovpn_share_salt config['server']['sovpn_share_salt'] = self.sovpn_share_salt # If you changed share salt, then you need to rotate hashes for everybody. if self.loaded and suggestion != self.sovpn_share_salt: self.needs_rotation = True # Ask value for sovpn_share_address property. suggestion_source = self.sovpn_config_file if self.loaded else None suggestion = self.get_suggestion('sovpn_share_address', suggestion_source) while self.sovpn_share_address is None: prompt = _prompt.get('sovpn_share_address', suggestion) sovpn_share_address = input(prompt) if sovpn_share_address.strip() == '': sovpn_share_address = suggestion self.sovpn_share_address = sovpn_share_address config['server']['sovpn_share_address'] = self.sovpn_share_address # Ask value for sovpn_share_port property. suggestion_source = self.sovpn_config_file if self.loaded else None suggestion = self.get_suggestion('sovpn_share_port', suggestion_source) while self.sovpn_share_port is None: prompt = _prompt.get('sovpn_share_port', suggestion) sovpn_share_port = input(prompt) if sovpn_share_port.strip() == '': sovpn_share_port = suggestion # Make sure server and sharing port are different. if self.protocol == 'tcp' and self.port == sovpn_share_port: print('> Port ' + str(sovpn_share_port) + '/TCP is already used by server.') sovpn_share_port = None self.sovpn_share_port = sovpn_share_port config['server']['sovpn_share_port'] = self.sovpn_share_port # Ask value for sovpn_share_url property. if self.hostname: if self.sovpn_share_url: suggestion = self.sovpn_share_url self.sovpn_share_url = None elif not self.hostname and self.hostname is False: suggestion = '-' else: if self.sovpn_share_port == 443: suggestion = 'https://' else: suggestion = 'http://' suggestion += self.hostname if self.sovpn_share_port != 443 and self.sovpn_share_port != 80: suggestion += ':' + str(self.sovpn_share_port) suggestion += '/' while self.sovpn_share_url is None: prompt = _prompt.get('sovpn_share_url', suggestion) sovpn_share_url = input(prompt) if sovpn_share_url.strip() == '': sovpn_share_url = suggestion self.sovpn_share_url = sovpn_share_url config['server']['sovpn_share_url'] = self.sovpn_share_url else: ipv4 = _helper.fetch_external_ipv4() if _helper.is_valid_ipv4(ipv4): self.sovpn_share_url = 'http://' + ipv4 + ':' + str( self.sovpn_share_port) + '/' config['server']['sovpn_share_url'] = self.sovpn_share_url # Ask value for sovpn_config_file property. suggestion = self.server_dir + 'sovpn.json' while self.sovpn_config_file is None: prompt = _prompt.get('sovpn_config_file', suggestion) sovpn_config_file = input(prompt) if sovpn_config_file.strip() == '': sovpn_config_file = suggestion self.sovpn_config_file = sovpn_config_file # Write sovpn's config file path to pointer file. with open(self.sovpn_config_pointer, 'w') as config_path_file: config_path_file.write(self.sovpn_config_file + "\n") # Write config values to file. with open(self.sovpn_config_file, 'w') as config_file: config_file.write(json.dumps(config) + "\n") # Copy client's template to server's directory. copyfile(self.client_template_path, self.server_dir + 'client.mustache')
def client_dir(self, create=True): """Assigns new value to client_dir property and creates directory for it if needed.""" value = self.clients_dir + self.slug if create: _helper.create_directory(value) self.settings['client']['client_dir'] = _helper.sanitize_path(value)
def share_hash(self): """Returns generated value of sovpn_hash.""" share_hash = _helper.generate_share_hash(self.slug, self.sovpn_share_salt) return share_hash
def css(self): """Method that return CSS content for sharing page.""" if self.css_path: return _helper.read_file_as_value(self.css_path) return None