def configure(self): """ Configures supervisord after manual installation :return: """ self.config.vpnauth_enc_password = util.random_password(16) self.config.vpnauth_db_password = util.random_password(16) self.audit.add_secrets(self.config.vpnauth_enc_password) self.audit.add_secrets(self.config.vpnauth_db_password) self.config.vpnauth_db = self.ejbca.MYSQL_DB self.mysql.create_user(self.DB_USER, self.config.vpnauth_db_password, self.config.vpnauth_db) # Create stats dir if does not exist if not os.path.exists(self.webroot): os.makedirs(self.webroot, mode=0o755) # Create VPN-dir based configuration for vpnauth notifier. # It is started under VPN server user so it has to be able to read the configuration with the API key. if os.path.exists(self.VPN_CONFIG_FILE): os.remove(self.VPN_CONFIG_FILE) with util.safe_open(self.VPN_CONFIG_FILE, mode='w', chmod=0o600) as fh: js = { 'config': { 'vpnauth_enc_password': self.config.vpnauth_enc_password } } json.dump(js, fh, indent=2) self.sysconfig.exec_shell('chown %s %s' % (self.ovpn.get_user(), self.VPN_CONFIG_FILE))
def _sql_command(self, sql, root_password=None): """ Executes sql command as root, returns return code, stdout, stderr. Uses configuration files not to leak credentials and query via arguments. Used internally. :param sql: :param root_password: optional root password - another from the one set in the self :return: res, out, err """ self._prepare_files(root_password=root_password) self.secure_query = os.path.join( '/tmp', 'ebstall-sql.query.%s' % random.randint(0, 65535)) with util.safe_open(self.secure_query, 'w', chmod=0o600) as fh: fh.write(sql) cmd = 'mysql --defaults-file="%s" < "%s"' % (self.secure_config, self.secure_query) res, out, err = self.sysconfig.cli_cmd_sync(cmd, write_dots=self.write_dots) self.audit.audit_sql(sql=sql, user='******', res_code=res, result=out, sensitive=True) util.safely_remove(self.secure_query) util.safely_remove(self.secure_config) return res, out, err
def store_server_cert(self, ca, cert, key): """ Stores CA, Cert, Key to the storage and fixes permissions :return: """ shutil.copy(ca, self.get_config_dir_subfile('ca.crt')) shutil.copy(cert, self.get_config_dir_subfile('server.crt')) # Key is tricky - do not expose the raw key key_file = self.get_config_dir_subfile('server.key') if os.path.exists(key_file): os.remove(key_file) # just UX remove, not security sensitive # Create file with correct permissions set fh = util.safe_open(key_file, 'w', chmod=0o600) fh.close() ret = self.sysconfig.exec_shell('sudo chown root:root \'%s\'' % key_file, shell=True, write_dots=self.write_dost) if ret != 0: return ret cmd_exec = 'sudo cat \'%s\' >> \'%s\'' % (key, key_file) return self.sysconfig.exec_shell(cmd_exec, write_dots=self.write_dost)
def configure(self): """ Configures Nginx :return: """ cfg_dir = self.nginx.http_include path = os.path.join(cfg_dir, 'nextcloud.conf') util.safely_remove(path) with util.safe_open(path, mode='w', chmod=0o644) as fh: fh.write(self._get_nginx_cfg() + '\n')
def _create_cert_files(self): """ Creates certificate for the XMPP server - using the certificate object, global letsencrypt certificate. :return: """ self._find_dirs_if_needed() cert_path, key_path = self._get_tls_paths() cert_data = open(cert_path).read().strip() key_data = open(key_path).read().strip() util.safely_remove(self._server_cert_path) with util.safe_open(self._server_cert_path, 'w', 0o600) as fh: fh.write('%s\n%s\n' % (cert_data, key_data)) if self._user is None: raise errors.InvalidState('Unknown user / group') os.chown(self._server_cert_path, self._user, self._group)
def _prepare_files(self, root_password=None): """ Prepares mysql configuration file for SQL command execution under root. Password & query do not leak via command arguments as it is quite sensitive (e.g., changing passwords) :return: """ self.secure_config = os.path.join( '/tmp', 'ebstall-sql.cnf.%s' % random.randint(0, 65535)) util.safely_remove(self.secure_config) if root_password is None: root_password = self.root_passwd self.audit.add_secrets(root_password) with util.safe_open(self.secure_config, 'w', chmod=0o600) as fh: fh.write('# mysql_secure_installation config file\n') fh.write('[mysql]\n') fh.write('user=root\n') fh.write('password=\'%s\'\n' % self._escape_single_quote(root_password))
def _trusted_domains(self): """ Trusted domains configuration - modifies config.php and adds current domain to the trusted_domains config key :return: """ cfg_path = os.path.join(self.webroot, 'config', 'config.php') if not os.path.exists(cfg_path): logger.warning('NextCloud config file not found: %s' % cfg_path) raise errors.SetupError('NextCloud config file not found') tpl_file = self._get_php_trusted_domains_template() tpl_file = tpl_file.replace('{{ CONFIG_FILE }}', cfg_path) tpl_file = re.sub(r'\{\{\s*[a-zA-Z0-9_\-]+\s*\}\}', '', tpl_file) php_file = os.path.join(self.webroot, 'ebstall-config.php') util.safely_remove(php_file) with util.safe_open(php_file, 'w', 0o755) as fw: fw.write(tpl_file) domains_list = ' '.join(self.get_domains() + [self.hostname]) cmd = 'sudo -u %s php %s %s ' \ % (self.user, php_file, domains_list) ret, out, err = self.sysconfig.cli_cmd_sync(cmd, cwd=self.webroot) if ret != 0: raise errors.SetupError( 'Owner change failed for private space web') if isinstance(out, types.ListType): out = ''.join(out) new_cfg = '<?php\n $CONFIG = %s; \n' % out with open(cfg_path, 'w') as fw: fw.write(new_cfg) util.safely_remove(php_file)