From a9aab71d128aa60e35bace01d924d1cfb825a222 Mon Sep 17 00:00:00 2001 From: absurdo Date: Sun, 3 Dec 2023 01:17:30 +0100 Subject: [PATCH] Added proxy support --- scripts/webapps/flask/install_flask_site.py | 2 +- scripts/webapps/proxy/install_proxy_site.py | 145 +++++++++++++++++ tasks/apache/scripts/proxy.py | 165 ++++++++++++++++++++ 3 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 scripts/webapps/proxy/install_proxy_site.py create mode 100644 tasks/apache/scripts/proxy.py diff --git a/scripts/webapps/flask/install_flask_site.py b/scripts/webapps/flask/install_flask_site.py index dc53c94..41bfd4d 100644 --- a/scripts/webapps/flask/install_flask_site.py +++ b/scripts/webapps/flask/install_flask_site.py @@ -178,7 +178,7 @@ with open(name_file, 'w') as f: f.write("\n") -print('Updating apache configuration for wordpress outside of htdocs...') +print('Updating apache configuration for flask outside of htdocs...') if subprocess.call('sudo mv {} /etc/{}/vhosts.d/extra && sudo chown root:root /etc/{}/vhosts.d/extra/{}'.format(name_file, apache_cmd, apache_cmd, base_name_file), shell=True) > 0: print('Error') sys.exit(1) diff --git a/scripts/webapps/proxy/install_proxy_site.py b/scripts/webapps/proxy/install_proxy_site.py new file mode 100644 index 0000000..c6eb241 --- /dev/null +++ b/scripts/webapps/proxy/install_proxy_site.py @@ -0,0 +1,145 @@ +#!/usr/bin/python3 -u + +import sys, os +import subprocess +import argparse +import platform +import shutil +import pathlib +import distro +import pwd +import getpass +import re + +#import pymysql.cursors +#pymysql.install_as_MySQLdb + +pyv=platform.python_version_tuple() + +if pyv[0]!='3': + print('Need python 3 for execute this script') + sys.exit(1) + +parser = argparse.ArgumentParser(description='Script for create a flask site.') + +parser.add_argument('--domain', help='The domain where is the site', required=True) +parser.add_argument('--home_user', help='The name of the new user', required=True) +parser.add_argument('--url', help='Url for the http service to proxy', required=True) +parser.add_argument('--user', help='The name of the domain user', required=True) +parser.add_argument('--path', help='The path of the flask install') + +args = parser.parse_args() + +linux_distro=distro.id() + +home_user=args.home_user + +if home_user.find('/', -1)==-1: + print("Error: you need backslash in home_user option") + exit(1) + +user=args.user + +apache_cmd='apache2' +apachectl='apache2ctl' + +if linux_distro!='debian' and linux_distro!='ubuntu': + + apache_cmd='httpd' + apachectl='apachectl' + + if linux_distro=='rocky' or linux_distro=='fedora' or linux_distro=='almalinux': + apache_group='apache' + + if linux_distro=='arch': + apache_group='http' + +system_user=getpass.getuser() + +name=os.path.basename(home_user[:-1]).strip() + +path='/' + +if args.path: + + if args.path.find('/', -1)==-1: + print("Error: you need backslash in path option") + exit(1) + + path=args.path[:-1] + + if path=='': + path='/' + +if path=='/': + + base_name_file='{}-001-{}.conf'.format(args.domain, name) + + name_file='/home/{}/{}-001-{}.conf'.format(system_user, args.domain, name) + +else: + + base_name_file='{}-000-{}.conf'.format(args.domain, name) + + name_file='/home/{}/{}-000-{}.conf'.format(system_user, args.domain, name) + +with open(name_file, 'w') as f: + + f.write("ProxyPreserveHost On\n") + f.write("ProxyRequests Off\n") + f.write("AllowEncodedSlashes NoDecode\n") + + f.write("\n" % path) + #ProxyPass unix:/home/root/flask_rest/flaskrest.sock|http://127.0.0.1/ + f.write("ProxyPass {} nocanon\n".format(args.url)) + #f.write("ProxyPassReverse {}\n" .format(args.url)) + + if path!='/': + f.write("RequestHeader set SCRIPT_NAME %s\n" % path) + + f.write("RequestHeader set X-Forwarded-Proto http\n") + f.write("RequestHeader set X-Forwarded-Prefix %s\n" % path) + + f.write("\n") + + if path=='/': + f.write("\n") + f.write("ProxyPass !\n") + f.write("\n") + + """ + if path=='/': + f.write("ProxyPreserveHost On\n") + f.write("ProxyRequests off\n") + f.write("AllowEncodedSlashes NoDecode\n") + f.write("ProxyPass %s.well-known/acme-challenge/ !\n" % path) + f.write("ProxyPass / {}/ nocanon\n".format(args.url)) + + + else: + + f.write("AllowEncodedSlashes NoDecode\n") + f.write("ProxyPass {} {} nocanon\n".format(path, args.url)) + """ + +print('Updating apache configuration for application outside of htdocs...') + +if subprocess.call('sudo mv {} /etc/{}/vhosts.d/extra && sudo chown root:root /etc/{}/vhosts.d/extra/{}'.format(name_file, apache_cmd, apache_cmd, base_name_file), shell=True) > 0: + print('Error') + sys.exit(1) + +print("Preparing apache for use proxy http...") + +if linux_distro=='debian' or linux_distro=='ubuntu': + if subprocess.call('sudo a2enmod proxy_http', shell=True) > 0: + print("Error: cannot enable proxy_http in apache in debian/ubuntu distro") + sys.exit(1) + +service=args.domain+'-'+name + +if subprocess.call("sudo systemctl restart %s" % (apache_cmd), shell=True) > 0: + print("Error: cannot update and restart apache") + sys.exit(1) + +print("Proxy app install successfully!") + diff --git a/tasks/apache/scripts/proxy.py b/tasks/apache/scripts/proxy.py new file mode 100644 index 0000000..aec498d --- /dev/null +++ b/tasks/apache/scripts/proxy.py @@ -0,0 +1,165 @@ +#/usr/bin/env python3 + +from collections import OrderedDict +import os +#from modules.pastafari2.models.servers import Server +from modules.webservers.models.webservers import WebServer, VirtualHost +import json + +from modules.pastafari2.libraries.task import Task +from modules.pastafari2.models.pastafari2 import ServerDbTask +from paramecio2.libraries.db import coreforms +from paramecio2.libraries.i18n import I18n +from paramecio2.libraries.formsutils import show_form +from paramecio2.libraries.db.extrafields.usernamefield import UserNameField +from paramecio2.libraries.db.extrafields.emailfield import EmailField +from paramecio2.libraries.db.extrafields.urlfield import DomainField, UrlField +from modules.webservers.libraries.webapptask import WebAppTask +from flask import url_for, request +import re + +class ServerTask(WebAppTask): + + def __init__(self, server, conn, remote_user='root', remote_password='', private_key='./ssh/id_rsa', password_key='', remote_path='pastafari2', task_id=0, data={}, port=22): + + super().__init__(server, conn, remote_user, remote_password, private_key, password_key, remote_path, task_id, data, port) + + self.name_task='Install Proxy App in an Apache Httpd Server' + + self.description_task='Install Proxy app in an Apache Httpd Server.' + + self.codename_task='apache_webserver_proxy' + + self.files=[['modules/apache/scripts/webapps/proxy/install_proxy_site.py', 0o700]] + + #THe files to delete + + self.delete_files=[] + + self.delete_directories=['modules/apache/scripts'] + + self.arr_form=OrderedDict() + + self.arr_form['path']=coreforms.BaseForm('path', '/') + + self.arr_form['path'].required=True + + self.arr_form['path'].label='The path of proxy application' + self.arr_form['path'].help='The path of proxy application.

For example, if you have a domain called http://example.com, if you install in / path, you access to proxy app, directly in http://example.com.
If you add path to /webapp/, the proxy webapp site will be accesible using http://example.com/webapp' + + self.arr_form['url']=coreforms.BaseForm('url', '') + + self.arr_form['url'].required=True + + self.arr_form['url'].label='The url used for proxy the app' + self.arr_form['url'].help='The url used for proxy the app. Example, if you want install an gitea server that use 3000 port, you can use this url http://localhost:3000' + + + def pre_task(self): + + if not super().pre_task(): + return False + + ##python3 install_flask_site.py --domain red.cuchulu.com --home_user /home/absurdo/sites/red.cuchulu.com/superapp/ --git_url https://webtsys@bitbucket.org/paramecio/flasktest.git --user=absurdo --dependencies=paramiko,pymysql --app_flask=app:app --path /superapp/ + + install_proxy='--domain %s --home_user %s --url %s --user %s --path %s' % (self.data['domain'], self.data['home_user'], self.data['url'], self.data['username'], self.data['path']) + + self.commands_to_execute.append(['modules/apache/scripts/webapps/proxy/install_proxy_site.py', install_proxy]) + + + + return True + + def form(self, t, yes_error=False, pass_values=False, values={}): + + #Here load the form for it task + + return '

'+I18n.lang('apache', 'add_proxy_site', 'Add site by proxy')+'

'+show_form(values, self.arr_form, t, yes_error, pass_values) + + def check_form(self, post): + + return_val=True + + usernamefield=UserNameField('user') + + urlfield=UrlField('url') + + path=post['path'].strip() + + if 'path' in post: + if path=='': + + self.arr_form['path'].error=True + self.arr_form['path'].txt_error='Empty value.' + + return_val=False + + url=urlfield.check(request.form.get('url', '')) + + if url=='': + self.arr_form['url'].error=True + self.arr_form['url'].txt_error='Wrong value for http proxy url.' + + return_val=False + + virtualhost_id=self.data.get('virtualhost_id', '0') + # ImmutableMultiDict([('send_task', '1'), ('amp;virtualhost_id', '42')]) + + #print(virtualhost_id) + + domain='' + home='' + app_name='' + + with self.connection.query('select domain, home, username from virtualhost where id=%s', [virtualhost_id]) as cursor: + arr_virtualhost=cursor.fetchone() + + if arr_virtualhost: + domain=arr_virtualhost['domain'] + + home=arr_virtualhost['home'] + + app_name='proxy' + + home=arr_virtualhost['home']+path + + if path!='/': + app_name=os.path.basename(os.path.dirname(home)) + + username=arr_virtualhost['username'] + + if domain=='': + return_val=False + + if return_val: + + # (self.data['user_wp'], self.data['password_wp'], self.data['mysql_user'], self.data['mysql_password'], self.data['mysql_db'], self.data['email_wp'], self.data['domain_wp'], self.data['title_wp'], self.data['mysql_host'], 3306) + + self.data['domain']=domain + self.data['path']=path + + self.data['virtualhost_id']=virtualhost_id + + self.data['home_user']=home + self.data['username']=username + self.data['webapp']=app_name + + self.data['url']=url + + return return_val + + def post_task(self): + + #virtualhost=VirtualHost(self.connection) + + #virtualhost.safe_query() + + #if not virtualhost.insert({'virtualhost_id': int(self.data['virtualhost_id']), 'app_name': 'wordpress', 'path': self.data['path']}): + # return False + #print(virtualhost.show_errors()) + + #virtua + self.connection.query('insert into webapp (`virtualhost_id`, `app_name`, `app_type`, `path`, `data`) VALUES (%s, %s, %s, %s, %s)', [int(self.data['virtualhost_id']), self.data['webapp'], 'proxy', self.data['path'], json.dumps(self.data)]) + + + return True