dodanie podstawowego panelu administracyjnego w wersji testowej

This commit is contained in:
Mateusz779 2023-04-19 09:34:40 +02:00
parent 6bc3ba9ad7
commit 8b444a8bf5
4 changed files with 195 additions and 36 deletions

66
app.py
View File

@ -1,6 +1,6 @@
import datetime import datetime
from time import sleep from time import sleep
from flask import Flask, flash, make_response, redirect, send_file, jsonify, request, render_template, url_for from flask import Flask, make_response, redirect, send_file, jsonify, request, render_template, url_for
import db import db
import os import os
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
@ -8,20 +8,24 @@ import subprocess
import utils import utils
import shutil import shutil
import config import config
import machines
app = Flask(__name__) app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = "squash" app.config['UPLOAD_FOLDER'] = "squash"
app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 512 #512MB app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 512 # 512MB
utils.init_threads() utils.init_threads()
@app.route('/') @app.route('/')
def main(): def main():
auth_token = request.cookies.get('auth_token') auth_token = request.cookies.get('auth_token')
if auth_token != "" or auth_token is not None: if auth_token != "" or auth_token is not None:
if db.get_user_bytoken(auth_token) is None: if db.get_user_bytoken(auth_token) is None:
return redirect("/login") return redirect("/login")
return render_template('index.html') machines_all = db.get_machines()
return render_template('index.html', ssh_port=config.webssh_port, table=machines_all.to_html_table())
@app.route('/login') @app.route('/login')
def login(): def login():
@ -31,6 +35,7 @@ def login():
return render_template('index.html') return render_template('index.html')
return render_template('login.html') return render_template('login.html')
@app.route('/create/conf') @app.route('/create/conf')
def create_conf(): def create_conf():
auth_token = request.cookies.get('auth_token') auth_token = request.cookies.get('auth_token')
@ -39,6 +44,7 @@ def create_conf():
return redirect("/login") return redirect("/login")
return render_template("create.html") return render_template("create.html")
@app.route('/api/createconf', methods=['POST']) @app.route('/api/createconf', methods=['POST'])
def create_conf_post(): def create_conf_post():
config_name = request.form['config_name'] config_name = request.form['config_name']
@ -46,44 +52,47 @@ def create_conf_post():
key_length = request.form['key_length'] key_length = request.form['key_length']
folder = utils.generate_random_string(5) folder = utils.generate_random_string(5)
try: try:
os.mkdir(os.path.join(os.getcwd(), 'configs',folder)) os.mkdir(os.path.join(os.getcwd(), 'configs', folder))
authorized_keys_config = request.form['authorized_keys_config'] authorized_keys_config = request.form['authorized_keys_config']
authorized_keys_file = open(folder+"/authorized_keys","w") authorized_keys_file = open(folder+"/authorized_keys", "w")
authorized_keys_file.write(authorized_keys_config) authorized_keys_file.write(authorized_keys_config)
authorized_keys_file.close() authorized_keys_file.close()
except: except:
shutil.copy('./configs/authorized_keys', './configs/'+ folder+"/authorized_keys") shutil.copy('./configs/authorized_keys',
'./configs/' + folder+"/authorized_keys")
script_path = os.path.join(os.getcwd(), 'configs', "create.sh") script_path = os.path.join(os.getcwd(), 'configs', "create.sh")
ini_path = os.path.join(os.getcwd(), 'configs', "uVPN.ini") ini_path = os.path.join(os.getcwd(), 'configs', "uVPN.ini")
conf_path = os.path.join(os.getcwd(), 'configs', "uVPN.conf") conf_path = os.path.join(os.getcwd(), 'configs', "uVPN.conf")
pub_path = os.path.join(os.getcwd(), 'configs', "server.pub") pub_path = os.path.join(os.getcwd(), 'configs', "server.pub")
scripts_path = os.path.join(os.getcwd(), 'configs', "scripts/") scripts_path = os.path.join(os.getcwd(), 'configs', "scripts/")
authorized_keys_path = os.path.join(os.getcwd(), 'configs',folder ,"authorized_keys") authorized_keys_path = os.path.join(
os.getcwd(), 'configs', folder, "authorized_keys")
sshd_config_path = os.path.join(os.getcwd(), 'configs', "sshd_config") sshd_config_path = os.path.join(os.getcwd(), 'configs', "sshd_config")
sendmail_path = os.path.join(os.getcwd(), 'configs', "sendmail.sh") sendmail_path = os.path.join(os.getcwd(), 'configs', "sendmail.sh")
subprocess.run([script_path,"-i "+ini_path, "-c "+conf_path, "-k "+pub_path, "-l "+key_length, "-n"+config_name, "-s "+scripts_path, "-a "+authorized_keys_path, "-d "+sshd_config_path, "-m "+sendmail_path, " > /dev/null 2>&1 "]) subprocess.run([script_path, "-i "+ini_path, "-c "+conf_path, "-k "+pub_path, "-l "+key_length, "-n"+config_name,
"-s "+scripts_path, "-a "+authorized_keys_path, "-d "+sshd_config_path, "-m "+sendmail_path, " > /dev/null 2>&1 "])
if os.path.exists(folder): if os.path.exists(folder):
shutil.rmtree(folder) shutil.rmtree(folder)
db.add_conf_image(config_name+".squashfs", token_name) db.add_conf_image(config_name+".squashfs", token_name)
return send_file(os.path.join(app.config['UPLOAD_FOLDER'], config_name+".pub")) return send_file(os.path.join(app.config['UPLOAD_FOLDER'], config_name+".pub"))
@app.route('/api/login', methods=['POST']) @app.route('/api/login', methods=['POST'])
def login_api(): def login_api():
username = request.form['username'] username = request.form['username']
password = request.form['password'] password = request.form['password']
#register # register
#db.add_user(username, password) # db.add_user(username, password)
#register # register
auth_token = db.login(username, password) auth_token = db.login(username, password)
if auth_token is None: if auth_token is None:
return render_template('login.html', incorrect="Incorrect username or password!") return render_template('login.html', incorrect="Incorrect username or password!")
response = make_response(redirect('/')) response = make_response(redirect('/'))
response.set_cookie('auth_token', auth_token) response.set_cookie('auth_token', auth_token)
return response return response
@ -99,7 +108,7 @@ def add_image():
return jsonify(message="nofile") return jsonify(message="nofile")
except Exception as e: except Exception as e:
return jsonify(message="nofile") return jsonify(message="nofile")
try: try:
token = request.form['token'] token = request.form['token']
if token is None or token == "": if token is None or token == "":
@ -107,7 +116,7 @@ def add_image():
except: except:
if token is None: if token is None:
return jsonify(message="notoken") return jsonify(message="notoken")
incorrect = True incorrect = True
while incorrect: while incorrect:
if db.GetVPNImage(token) is not None: if db.GetVPNImage(token) is not None:
@ -128,7 +137,7 @@ def add_image():
db.add_conf_image(filename, token) db.add_conf_image(filename, token)
return jsonify(message="ok") return jsonify(message="ok")
@app.route("/api/getconf") @app.route("/api/getconf")
def get_image(): def get_image():
@ -140,20 +149,22 @@ def get_image():
date = db.get_image_allocation_time(request.headers['token']) date = db.get_image_allocation_time(request.headers['token'])
if date is not None: if date is not None:
delta = datetime.datetime.now() - date delta = datetime.datetime.now() - date
if delta.total_seconds() > 30: if delta.total_seconds() > 30:
db.del_image_allocation_token(request.headers['token']) db.del_image_allocation_token(request.headers['token'])
else: else:
filename = None filename = None
else: else:
db.set_image_allocation(request.headers['token'], request.remote_addr) db.set_image_allocation(
request.headers['token'], request.remote_addr)
except: except:
pass pass
if filename is None or filename == "": if filename is None or filename == "":
filename = config.default_file filename = config.default_file
return send_file(os.path.join(app.config['UPLOAD_FOLDER'], filename)) return send_file(os.path.join(app.config['UPLOAD_FOLDER'], filename))
@app.route("/api/release_allocation", methods=['POST']) @app.route("/api/release_allocation", methods=['POST'])
def release_allocation(): def release_allocation():
try: try:
@ -166,9 +177,10 @@ def release_allocation():
db.del_image_allocation_id_image(id_allocation) db.del_image_allocation_id_image(id_allocation)
else: else:
return jsonify(message="404") return jsonify(message="404")
return jsonify(message="200") return jsonify(message="200")
@app.route("/api/addip", methods=['POST']) @app.route("/api/addip", methods=['POST'])
def add_ip(): def add_ip():
try: try:
@ -178,5 +190,7 @@ def add_ip():
pass pass
print(token, ip) print(token, ip)
return "" return ""
if __name__ == '__main__': if __name__ == '__main__':
app.run(host="0.0.0.0") app.run(host="0.0.0.0")

33
db.py
View File

@ -1,7 +1,7 @@
import psycopg2 import psycopg2
import config import config
import utils import utils
import machines
def connect(): def connect():
global cur, conn global cur, conn
@ -139,8 +139,23 @@ def login(username, password):
else: else:
return None return None
def get_machines():
connect()
with get_cur() as cur:
cur.execute("""
SELECT image_id, allocation_time, client_ip FROM image_allocation""")
try:
machinesall = machines.MachineManager()
for row in cur.fetchall():
token = get_one("SELECT token FROM image WHERE id = %s", row[0])
image_name = get_one("SELECT image_name FROM image WHERE id = %s", row[0])
machine = machines.Machine(token, image_name, start_time=row[1], ip=row[2], username="root", password="")
machinesall.add_machine(machine)
return machinesall
except:
return None
def get_image_allocation_all(): def get_image_allocation_all_id():
connect() connect()
with get_cur() as cur: with get_cur() as cur:
cur.execute(""" cur.execute("""
@ -152,6 +167,18 @@ def get_image_allocation_all():
return None return None
def get_image_allocation_all():
connect()
with get_cur() as cur:
cur.execute("""
SELECT * FROM image_allocation""")
try:
results = [list(row) for row in cur.fetchall()]
return results
except:
return None
def get_image_allocation(sql, value): def get_image_allocation(sql, value):
connect() connect()
with get_cur() as cur: with get_cur() as cur:
@ -237,4 +264,4 @@ def update_image_allocation_time(id):
conn.commit() conn.commit()
return True return True
except: except:
return None return None

51
machines.py Normal file
View File

@ -0,0 +1,51 @@
class Machine:
def __init__(self, name, image_name, start_time, ip, username, password):
self.name = name
self.image_name = image_name
self.start_time = start_time
self.ip = ip
self.username = username
self.password = password
def __str__(self):
return f"Name: {self.name}\nImage name: {self.image_name}\nStart time: {self.start_time}\nIP: {self.ip}\nUsername: {self.username}\nPassword: {self.password}"
class MachineManager:
def __init__(self):
self.machines = []
def add_machine(self, machine):
self.machines.append(machine)
def remove_machine(self, machine):
self.machines.remove(machine)
def get_machine_by_name(self, name):
for machine in self.machines:
if machine.name == name:
return machine
return None
def __str__(self):
result = ""
for machine in self.machines:
result += str(machine) + "\n\n"
return result
def to_html_table(self):
html = "<table>"
html += """<th>Nazwa maszyny</th>
<th>Obraz</th>
<th>Czas uruchomienia</th>
<th>IP uVPN</th>
<th></th>"""
for machine in self.machines:
html += f"""<tr>
<td>{ machine.name }</td>
<td>{ machine.image_name }</td>
<td>{ machine.start_time }</td>
<td>{ machine.ip }</td>
<td><button onclick="ssh('{ machine.ip, machine.username, machine.password }')">SSH</button></td>
</tr>"""
html += "</table>"
return html

View File

@ -1,12 +1,79 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html>
<head> <head>
<meta charset="UTF-8"> <title>Panel administracyjny</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <style>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> body {
<title>Document</title> font-family: Arial, sans-serif;
background-color: #f5f5f5;
margin: 0;
padding: 0;
}
h1 {
font-size: 32px;
font-weight: bold;
color: #333;
margin: 20px 0;
}
table {
border-collapse: collapse;
margin: 20px 0;
width: 100%;
}
table th, table td {
padding: 10px;
text-align: left;
vertical-align: middle;
border: 1px solid #ccc;
}
table th {
background-color: #eee;
font-weight: bold;
}
table tr:hover {
background-color: #f0f0f0;
}
button {
background-color: #4CAF50;
border: none;
color: white;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 10px 0;
cursor: pointer;
}
button:hover {
background-color: #3e8e41;
}
</style>
</head> </head>
<body> <body>
<h1>Lista maszyn</h1>
{{table}}
</table>
<script>
function ssh(ipvpn, username, password) {
const currentLocation = window.location;
// budowanie nowego URL
const newUrl = currentLocation.protocol + '//' + currentLocation.hostname + ':' + ssh_port + "/?hostname="+ipvpn+"&username="+username+"&password="+btoa(password);
// przekierowanie na nowy URL
window.location.replace(newUrl);
}
</script>
</body> </body>
</html> </html>