mirror of https://github.com/Aidaho12/haproxy-wi
397 lines
14 KiB
Python
397 lines
14 KiB
Python
import ast
|
|
from typing import Union
|
|
|
|
from flask.views import MethodView
|
|
from flask_pydantic import validate
|
|
from flask import jsonify
|
|
from flask_jwt_extended import jwt_required
|
|
from playhouse.shortcuts import model_to_dict
|
|
|
|
import app.modules.db.sql as sql
|
|
import app.modules.db.le as le_sql
|
|
import app.modules.db.server as server_sql
|
|
import app.modules.common.common as common
|
|
import app.modules.roxywi.common as roxywi_common
|
|
import app.modules.service.installation as service_mod
|
|
from app.modules.db.db_model import LetsEncrypt
|
|
from app.modules.server.ssh import return_ssh_keys_path
|
|
from app.middleware import get_user_params, page_for_admin, check_group
|
|
from app.modules.roxywi.class_models import LetsEncryptRequest, LetsEncryptDeleteRequest, IdResponse, GroupQuery, BaseResponse
|
|
from app.modules.common.common_classes import SupportClass
|
|
|
|
|
|
class LetsEncryptView(MethodView):
|
|
methods = ['GET', 'POST', 'PUT', 'DELETE']
|
|
decorators = [jwt_required(), get_user_params(), page_for_admin(level=3), check_group()]
|
|
|
|
@validate(query=GroupQuery)
|
|
def get(self, le_id: int, query: GroupQuery):
|
|
"""
|
|
Get Let's Encrypt details.
|
|
---
|
|
tags:
|
|
- Let's Encrypt
|
|
parameters:
|
|
- name: le_id
|
|
in: path
|
|
type: integer
|
|
required: true
|
|
description: ID of the Let's Encrypt configuration
|
|
- name: group_id
|
|
in: query
|
|
type: integer
|
|
required: false
|
|
description: ID of the group (only for role superAdmin)
|
|
responses:
|
|
200:
|
|
description: Let's Encrypt details retrieved successfully
|
|
schema:
|
|
type: object
|
|
properties:
|
|
api_key:
|
|
type: string
|
|
description: API key
|
|
api_token:
|
|
type: string
|
|
description: API token
|
|
description:
|
|
type: string
|
|
description: Description of the Let's Encrypt configuration
|
|
domains:
|
|
type: array
|
|
description: List of domains associated with the Let's Encrypt configuration
|
|
email:
|
|
type: string
|
|
description: Email associated with the Let's Encrypt account
|
|
id:
|
|
type: integer
|
|
description: ID of the Let's Encrypt configuration
|
|
server_id:
|
|
type: integer
|
|
description: ID of the server
|
|
type:
|
|
type: string
|
|
description: Type of the Let's Encrypt configuration
|
|
enum: ['standalone', 'route53', 'cloudflare', 'digitalocean', 'linode']
|
|
"""
|
|
group_id = SupportClass.return_group_id(query)
|
|
try:
|
|
le = le_sql.get_le_with_group(le_id, group_id)
|
|
le_dict = model_to_dict(le, recurse=False)
|
|
le_dict['domains'] = ast.literal_eval(le_dict['domains'])
|
|
return jsonify(le_dict)
|
|
except Exception as e:
|
|
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot get Let\'s Encrypt')
|
|
|
|
@validate(body=LetsEncryptRequest)
|
|
def post(self, body: LetsEncryptRequest):
|
|
"""
|
|
Create a Let's Encrypt configuration.
|
|
---
|
|
tags:
|
|
- Let's Encrypt
|
|
parameters:
|
|
- name: group_id
|
|
in: query
|
|
type: integer
|
|
required: false
|
|
description: ID of the group (only for role superAdmin)
|
|
- name: body
|
|
in: body
|
|
required: true
|
|
schema:
|
|
type: object
|
|
properties:
|
|
api_key:
|
|
type: string
|
|
description: API key
|
|
api_token:
|
|
type: string
|
|
description: API token
|
|
description:
|
|
type: string
|
|
description: Description of the Let's Encrypt configuration
|
|
domains:
|
|
type: array
|
|
description: List of domains associated with the Let's Encrypt configuration
|
|
email:
|
|
type: string
|
|
description: Email associated with the Let's Encrypt account
|
|
id:
|
|
type: integer
|
|
description: ID of the Let's Encrypt configuration
|
|
server_id:
|
|
type: integer
|
|
description: ID of the server
|
|
type:
|
|
type: string
|
|
description: Type of the Let's Encrypt configuration
|
|
enum: ['standalone', 'route53', 'cloudflare', 'digitalocean', 'linode']
|
|
responses:
|
|
201:
|
|
description: Let's Encrypt configuration created successfully
|
|
"""
|
|
try:
|
|
self._create_env(body, 'install')
|
|
last_id = le_sql.insert_le(**body.model_dump(mode='json'))
|
|
return IdResponse(id=last_id).model_dump(), 201
|
|
except Exception as e:
|
|
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot create Let\'s Encrypt')
|
|
|
|
@validate(body=LetsEncryptRequest, query=GroupQuery)
|
|
def put(self, le_id: int, body: LetsEncryptRequest, query: GroupQuery):
|
|
"""
|
|
Update a Let's Encrypt configuration.
|
|
---
|
|
tags:
|
|
- Let's Encrypt
|
|
parameters:
|
|
- name: le_id
|
|
in: path
|
|
type: integer
|
|
required: true
|
|
description: ID of the Let's Encrypt configuration
|
|
- name: group_id
|
|
in: query
|
|
type: integer
|
|
required: false
|
|
description: ID of the group (only for role superAdmin)
|
|
- name: body
|
|
in: body
|
|
required: true
|
|
schema:
|
|
type: object
|
|
properties:
|
|
api_key:
|
|
type: string
|
|
description: API key
|
|
api_token:
|
|
type: string
|
|
description: API token
|
|
description:
|
|
type: string
|
|
description: Description of the Let's Encrypt configuration
|
|
domains:
|
|
type: array
|
|
description: List of domains associated with the Let's Encrypt configuration
|
|
email:
|
|
type: string
|
|
description: Email associated with the Let's Encrypt account
|
|
id:
|
|
type: integer
|
|
description: ID of the Let's Encrypt configuration
|
|
server_id:
|
|
type: integer
|
|
description: ID of the server
|
|
type:
|
|
type: string
|
|
description: Type of the Let's Encrypt configuration
|
|
enum: ['standalone', 'route53', 'cloudflare', 'digitalocean', 'linode']
|
|
responses:
|
|
201:
|
|
description: Let's Encrypt configuration updated successfully
|
|
"""
|
|
group_id = SupportClass.return_group_id(query)
|
|
try:
|
|
le = le_sql.get_le_with_group(le_id, group_id)
|
|
except Exception as e:
|
|
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot find Let\'s Encrypt')
|
|
|
|
try:
|
|
le_dict = _return_domains_list(le)
|
|
data = LetsEncryptRequest(**le_dict)
|
|
self._create_env(data, 'delete')
|
|
except Exception as e:
|
|
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot update Let\'s Encrypt on server')
|
|
|
|
try:
|
|
le_sql.update_le(le_id, **body.model_dump(mode='json'))
|
|
self._create_env(body, 'install')
|
|
return IdResponse(id=le_id).model_dump(), 201
|
|
except Exception as e:
|
|
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot update Let\'s Encrypt')
|
|
|
|
@validate(query=GroupQuery)
|
|
def delete(self, le_id: int, query: GroupQuery):
|
|
"""
|
|
Delete Let's Encrypt details.
|
|
---
|
|
tags:
|
|
- Let's Encrypt
|
|
parameters:
|
|
- name: le_id
|
|
in: path
|
|
type: integer
|
|
required: true
|
|
description: ID of the Let's Encrypt configuration
|
|
- name: group_id
|
|
in: query
|
|
type: integer
|
|
required: false
|
|
description: ID of the group (only for role superAdmin)
|
|
responses:
|
|
204:
|
|
description: Let's Encrypt deleted successfully
|
|
"""
|
|
group_id = SupportClass.return_group_id(query)
|
|
try:
|
|
le = le_sql.get_le_with_group(le_id, group_id)
|
|
except Exception as e:
|
|
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot find Let\'s Encrypt')
|
|
|
|
try:
|
|
le_dict = _return_domains_list(le)
|
|
le_dict['emails'] = None
|
|
data = LetsEncryptDeleteRequest(**le_dict)
|
|
self._create_env(data, action='delete')
|
|
except Exception as e:
|
|
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot delete Let\'s Encrypt from server')
|
|
|
|
try:
|
|
le_sql.delete_le(le_id)
|
|
return BaseResponse().model_dump(mode='json'), 204
|
|
except Exception as e:
|
|
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot delete Let\'s Encrypt')
|
|
|
|
@staticmethod
|
|
def _create_env(data: Union[LetsEncryptRequest, LetsEncryptDeleteRequest], action: str = 'install'):
|
|
server_ips = []
|
|
server_ip = 'localhost'
|
|
domains_command = ''
|
|
servers = {}
|
|
main_domain = data.domains[0]
|
|
inv = {"server": {"hosts": {}}}
|
|
masters = server_sql.is_master(server_ip)
|
|
ssl_path = common.return_nice_path(sql.get_setting('cert_path'), is_service=0)
|
|
haproxy_dir = sql.get_setting('haproxy_dir')
|
|
|
|
if data.type == 'standalone':
|
|
server_ip = server_sql.get_server(data.server_id).ip
|
|
ssh_settings = return_ssh_keys_path(server_ip)
|
|
servers[server_ip] = f"{ssh_settings['user']}@{ssh_settings['key']}"
|
|
ansible_role = 'letsencrypt_standalone'
|
|
else:
|
|
master_ip = server_sql.get_server(data.server_id).ip
|
|
ssh_settings = return_ssh_keys_path(master_ip)
|
|
servers[master_ip] = f"{ssh_settings['user']}@{ssh_settings['key']}"
|
|
ansible_role = 'letsencrypt'
|
|
|
|
for domain in data.domains:
|
|
domains_command += f' -d {domain}'
|
|
|
|
for master in masters:
|
|
if master[0] is not None:
|
|
ssh_settings = return_ssh_keys_path(master[0])
|
|
servers[master[0]] = f"{ssh_settings['user']}@{ssh_settings['key']}"
|
|
|
|
inv['server']['hosts'][master[0]] = {
|
|
'token': data.api_token,
|
|
'secret_key': data.api_key,
|
|
'email': data.email,
|
|
'ssl_path': ssl_path,
|
|
'domains_command': domains_command,
|
|
'main_domain': main_domain,
|
|
'servers': servers,
|
|
'action': action,
|
|
'cert_type': data.type,
|
|
'haproxy_dir': haproxy_dir
|
|
}
|
|
server_ips.append(master[0])
|
|
|
|
inv['server']['hosts'][server_ip] = {
|
|
'token': data.api_token,
|
|
'secret_key': data.api_key,
|
|
'email': data.email,
|
|
'ssl_path': ssl_path,
|
|
'domains_command': domains_command,
|
|
'main_domain': main_domain,
|
|
'servers': servers,
|
|
'action': action,
|
|
'cert_type': data.type,
|
|
'haproxy_dir': haproxy_dir
|
|
}
|
|
|
|
server_ips.append(server_ip)
|
|
if data.type != 'standalone':
|
|
try:
|
|
output = service_mod.run_ansible_locally(inv, ansible_role)
|
|
except Exception as e:
|
|
raise e
|
|
else:
|
|
try:
|
|
output = service_mod.run_ansible(inv, server_ips, ansible_role)
|
|
except Exception as e:
|
|
raise e
|
|
|
|
if len(output['failures']) > 0 or len(output['dark']) > 0:
|
|
raise Exception('Cannot create certificate. Check Apache error log')
|
|
|
|
|
|
class LetsEncryptsView(MethodView):
|
|
methods = ['GET']
|
|
decorators = [jwt_required(), get_user_params(), page_for_admin(level=3), check_group()]
|
|
|
|
@validate(query=GroupQuery)
|
|
def get(self, query: GroupQuery):
|
|
"""
|
|
Get all Let's Encrypt configurations.
|
|
---
|
|
tags:
|
|
- Let's Encrypt
|
|
parameters:
|
|
- name: group_id
|
|
in: query
|
|
type: integer
|
|
required: false
|
|
description: ID of the group (only for role superAdmin)
|
|
responses:
|
|
200:
|
|
description: List of Let's Encrypt configurations retrieved successfully
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
api_key:
|
|
type: string
|
|
description: API key
|
|
api_token:
|
|
type: string
|
|
description: API token
|
|
description:
|
|
type: string
|
|
description: Description of the Let's Encrypt configuration
|
|
domains:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Domains associated with the Let's Encrypt configuration
|
|
email:
|
|
type: string
|
|
description: Email associated with the Let's Encrypt account
|
|
id:
|
|
type: integer
|
|
description: ID of the Let's Encrypt configuration
|
|
server_id:
|
|
type: integer
|
|
description: ID of the server
|
|
type:
|
|
type: string
|
|
description: Type of the Let's Encrypt configuration
|
|
"""
|
|
group_id = SupportClass.return_group_id(query)
|
|
le_list = []
|
|
try:
|
|
les = le_sql.select_le_with_group(group_id)
|
|
for le in les:
|
|
le_list.append(_return_domains_list(le, query.recurse))
|
|
return jsonify(le_list)
|
|
except Exception as e:
|
|
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot get Let\'s Encrypts')
|
|
|
|
|
|
def _return_domains_list(le: LetsEncrypt, recurse: bool = False) -> dict:
|
|
le_dict = model_to_dict(le, recurse=recurse)
|
|
le_dict['domains'] = ast.literal_eval(le_dict['domains'])
|
|
return le_dict
|