You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
join-to-domain/SOURCES/form-join-to-domain.py

246 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/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()