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

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