#!/usr/bin/python3 # Date update: 14.11.2023 # Email: aleksandr.egai@red-soft.ru # (c) RED SOFT import sys,re,socket,subprocess,os from PyQt5.QtWidgets import QApplication, QLabel, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QWidget, QCheckBox, QTabWidget, QMessageBox from PyQt5.QtCore import Qt class DomainForm(QWidget): def __init__(self, width, height, show_parameters_tab): QWidget.__init__(self) self.width = width self.height = height self.show_parameters_tab = show_parameters_tab self.initUI() def initUI(self): self.setFixedSize(self.width, self.height) layout = QVBoxLayout() tab_widget = QTabWidget(self) # Вкладка для основных данных tab1 = QWidget() tab_widget.addTab(tab1, "Основные данные") # Определяем имя домена domain = None with open("/etc/resolv.conf", "r") as resolv_file: for line in resolv_file: if line.strip().startswith("search"): domain = line.split()[1] break self.label_domain = QLabel("Имя домена:") self.entry_domain = QLineEdit(self) self.entry_domain.setText(domain) self.label_name_pc = QLabel("Имя компьютера:") self.entry_name_pc = QLineEdit(self) self.entry_name_pc.setMaxLength(15) self.entry_name_pc.setText(socket.gethostname().split(".")[0]) self.label_admin = QLabel("Имя администратора домена:") self.entry_admin = QLineEdit(self) self.label_password = QLabel("Пароль администратора домена:") self.entry_password = QLineEdit(self) self.entry_password.setEchoMode(QLineEdit.Password) # Скрыть ввод пароля звёздочками tab_layout1 = QVBoxLayout() tab_layout1.addWidget(self.label_domain) tab_layout1.addWidget(self.entry_domain) tab_layout1.addWidget(self.label_name_pc) tab_layout1.addWidget(self.entry_name_pc) tab_layout1.addWidget(self.label_admin) tab_layout1.addWidget(self.entry_admin) tab_layout1.addWidget(self.label_password) tab_layout1.addWidget(self.entry_password) tab1.setLayout(tab_layout1) if self.show_parameters_tab: # Вкладка для параметров, если show_parameters_tab == True tab2 = QWidget() tab_widget.addTab(tab2, "Параметры") self.checkbox1 = QCheckBox("Параметр 1") self.checkbox1.setChecked(True) # Активировать параметр self.checkbox2 = QCheckBox("Параметр 2") self.checkbox3 = QCheckBox("Параметр 3") tab_layout2 = QVBoxLayout() tab_layout2.addWidget(self.checkbox1) tab_layout2.addWidget(self.checkbox2) tab_layout2.addWidget(self.checkbox3) tab2.setLayout(tab_layout2) layout.addWidget(tab_widget) button_layout = QHBoxLayout() button_layout.setAlignment(Qt.AlignHCenter) self.close_button = QPushButton("Закрыть") self.submit_button = QPushButton("ОК") self.close_button.setFixedWidth(100) self.close_button.setFixedHeight(40) self.close_button.clicked.connect(self.close) self.submit_button.setFixedWidth(100) self.submit_button.setFixedHeight(40) self.submit_button.clicked.connect(self.on_submit) button_layout.addWidget(self.close_button) button_layout.addWidget(self.submit_button) layout.addLayout(button_layout) self.setLayout(layout) def is_valid_name_pc(self, name_pc): pattern = r'^(?:[a-zA-Z0-9](?:(?:[a-zA-Z0-9\-]){0,14}[a-zA-Z0-9\-])+[a-zA-Z0-9])$' if re.match(pattern, name_pc) and len(name_pc) <= 15: return True else: return False def check_domain_name(self, admin, domain, name_pc, password): has_errors = False # Флаг для отслеживания ошибок try: check_command = f"adcli show-computer -U {admin} --domain={domain} {name_pc} --stdin-password" # Открываем файлы здесь with open("/tmp/join_check.txt", "w") as output_file, \ open("/tmp/join_check.txt", "r") as check_file, \ open("/var/log/join-to-domain.log", "a") as log_file: process = subprocess.Popen(check_command, shell=True, stdin=subprocess.PIPE, stdout=output_file, stderr=subprocess.STDOUT, text=True) process.communicate(input=password) # Считываем содержимое /tmp/join_check.txt v_check = check_file.read() log_file.write("Проверка аутентификации в домене:\n") log_file.write(v_check) log_file.flush() # Очистить буфер вывода if "sAMAccountName" in v_check: message = f"Ошибка! В домене уже существует компьютер {name_pc}\n" log_message = f"Ошибка! В домене уже существует компьютер {name_pc}" log_file.write(log_message) log_file.write("\n") QMessageBox.critical(self, "Ошибка!", message) has_errors = True if "Couldn't authenticate" in v_check: message = "Неверное имя администратора домена или пароль!" log_message = "Ошибка! Неверное имя администратора домена или пароль!" log_file.write(log_message) QMessageBox.critical(self, "Ошибка!", message) has_errors = True except Exception as e: print(f"Error: {e}") has_errors = True return has_errors # Возвращаем флаг ошибок def on_submit(self): log_file_path = '/var/log/join-to-domain.log' domain = self.entry_domain.text() name_pc = self.entry_name_pc.text() admin = self.entry_admin.text().split('@')[0] password = self.entry_password.text() param1 = self.checkbox1.isChecked() if self.show_parameters_tab else None param2 = self.checkbox2.isChecked() if self.show_parameters_tab else None param3 = self.checkbox3.isChecked() if self.show_parameters_tab else None if not self.is_valid_name_pc(name_pc): QMessageBox.critical(self, "Ошибка!", f"{name_pc} - это недопустимое имя компьютера.", QMessageBox.Ok) with open(log_file_path, 'a') as log_file: log_file.write(f"Ошибка! {name_pc} - это недопустимое имя компьютера." + '\n') return if domain and name_pc and admin and password: # Проверка доступности домена try: socket.gethostbyname(domain) except socket.gaierror: QMessageBox.critical(self, "Ошибка!", f"Домен {domain} недоступен! Проверьте настройки сети.") with open(log_file_path, 'a') as log_file: log_file.write(f"Ошибка! Домен {domain} недоступен! Проверьте настройки сети." + '\n') return # Получаем имя контроллера домена из adcli def get_domain_controller(domain_name): try: result = subprocess.check_output(["adcli", "info", domain], stderr=subprocess.STDOUT, text=True) return result except subprocess.CalledProcessError as e: return str(e) controller_info = get_domain_controller(domain) # Парсинг информации о контроллере домена controller_lines = [line.strip() for line in controller_info.split("\n")] controller_name = None for line in controller_lines: if line.startswith("domain-controller = "): controller_name = line.split(" = ")[1] break if controller_name: # Короткое имя домена v_short_dc = controller_name.split(".")[0] else: QMessageBox.critical(self, "Ошибка!", "Информация о контроллере домена не найдена.") with open(log_file_path, 'a') as log_file: log_file.write(f"Ошибка! Информация о контроллере домена не найдена." + '\n') return if v_short_dc == name_pc: QMessageBox.critical(self, "Ошибка!", f"Имя компьютера {name_pc} не должно совпадать с именем контроллера домена!") with open(log_file_path, 'a') as log_file: log_file.write(f"Ошибка! Имя компьютера {name_pc} не должно совпадать с именем контроллера домена!" + '\n') return if self.check_domain_name(admin, domain, name_pc, password): return result = f"{domain},{name_pc},{admin},{password},{param1},{param2},{param3}" print(result) # Вывести результат в стандартный вывод (stdout) sys.stdout.flush() self.close() else: QMessageBox.critical(self, "Ошибка!", "Заполните все поля, включая пароль!", QMessageBox.Ok) return def main(): app = QApplication(sys.argv) # Параметры окна width = 420 height = 380 file_name = '/usr/bin/join-to-domain.sh' # Поиск версии join-to-domain version = None if os.path.exists(file_name): with open(file_name, 'r', encoding='utf-8') as file: for line in file: if "Версия:" in line: version = line.split("Версия:", 1)[1].strip() break if version is None: version="" show_parameters_tab = False # True или False, чтобы показать/скрыть вкладку "Параметры" form = DomainForm(width, height, show_parameters_tab) form.setWindowTitle(f"Ввод в домен {version}") form.show() sys.exit(app.exec_()) if __name__ == '__main__': main()