Внесены незначительные изменения

main
Dmitry Kovtun 2024-05-23 17:10:25 +03:00
parent 7d23c372c4
commit 8184dee91d
3 changed files with 201 additions and 70 deletions

View File

@ -219,7 +219,7 @@ if __name__ == "__main__":
MS_AD_ADRESS = 'ldap://cp-vm-dc01.energo.ru' MS_AD_ADRESS = 'ldap://cp-vm-dc01.energo.ru'
SEARCH_FREE_MS = "dc=energo,dc=ru" SEARCH_FREE_MS = "dc=energo,dc=ru"
MS_USER = 'energo\\administrator' MS_USER = 'energo\\administrator'
PASSWORD = "" PASSWORD = "P@sww0rd"
PATH_SCV = "List_groups.csv" PATH_SCV = "List_groups.csv"
SEARCH_FREE_SAMBA = "dc=lenenergo,dc=ru" SEARCH_FREE_SAMBA = "dc=lenenergo,dc=ru"

View File

@ -1,3 +1,4 @@
#!/usr/bin/python3
from ldap3 import Server, Connection, ALL, NTLM, SUBTREE, SAFE_SYNC, BASE from ldap3 import Server, Connection, ALL, NTLM, SUBTREE, SAFE_SYNC, BASE
from samba.samdb import SamDB from samba.samdb import SamDB
from samba.auth import system_session from samba.auth import system_session
@ -7,9 +8,11 @@ import samba.param
import logging import logging
from pprint import pprint from pprint import pprint
import json import json
import subprocess
import csv import csv
import subprocess
import sched
import time
import datetime
@ -25,20 +28,15 @@ class AD_provaider():
logging.warning("status connect AD.........error") logging.warning("status connect AD.........error")
def search_ms_ad(self,search_filter ,filter:list = ["*"], dn = None)->dict: def search_ms_ad(self, search_filter ,filter:list = ["*"])->dict:
logging.info("search >>>>>>>>>>>>>> AD") logging.info("search >>>>>>>>>>>>>> AD")
if dn is not None: self.__connect.search(self.__ad_serch_tree, search_filter, SUBTREE, attributes=filter)
self.__connect.search(dn, search_filter, SUBTREE, attributes=filter)
else:
self.__connect.search(self.__ad_serch_tree, search_filter, SUBTREE, attributes=filter)
response = self.__connect.response_to_json() response = self.__connect.response_to_json()
response = json.loads(response) response = json.loads(response)
response = json.dumps(response, ensure_ascii="utf-8") response = json.dumps(response, ensure_ascii="utf-8")
return json.loads(response) return json.loads(response)
class Samba_provaider(): class Samba_provaider():
def __init__(self, path) -> None: def __init__(self, path) -> None:
self.__lp = samba.param.LoadParm() self.__lp = samba.param.LoadParm()
@ -66,81 +64,214 @@ class Samba_provaider():
return False return False
class Manager: class Manager():
def __init__(self, samba_ad:Samba_provaider, ad:AD_provaider) -> None: def __init__(self, samba_prov:Samba_provaider, ad:AD_provaider) -> None:
self._smb = samba_ad self._smb = samba_prov
self.__ad = ad self.__ad = ad
def creat_branch_ou(self, data_path_list:list): def find_user_by_groups(self, name:str, ou:str, base_ou:str)->dict:
for item in data_path_list: str_base_ou = self.__get_str_base_ou(base_ou)
i = item.split(",") return self.__ad.search_ms_ad(f"(memberOf=CN={name},{ou},{str_base_ou})")
date = [m.split("=") for m in i]
date_list = list(reversed(date))
self.__seach_path_ou_and_add(date_list) def find_group(self, name, ou, base):
base_ou = self.__get_str_base_ou(base)
return self.__ad.search_ms_ad(f"(&(objectCategory=group)(name={name})(distinguishedName=CN={name},{ou},{base_ou}))")
def __seach_path_ou_and_add(self, ou_list:list): def __get_str_base_ou(self, base:str)->str:
path = "" ou_list = []
try: for i in base.split(","):
for i in ou_list: dn = i.split("=")[0]
if str(i[0]).replace('"', '') == "OU": v = i.split("=")[1]
if len(path) == 0: out = "{}={}".format( dn.upper(), v)
path = path + i[0].replace('"', '') +"="+i[1] ou_list.append(out)
str_add = "add ou -> {} <- status ....ok".format(path) return ",".join(ou_list)
print("***************************************")
logging.info(str_add)
print("***************************************")
self._smb.add_ou(path)
else:
path = i[0].replace('"', '') +"="+i[1]+","+ path
str_add = "add ou -> {} <- status ....ok".format(path)
print("***************************************")
logging.info(str_add)
print("***************************************")
self._smb.add_ou(path)
except Exception as ex:
logging.warning(ex)
def open_csv_file(self, path)->list: def open_file_list_groups(self, path:str)->dict:
out_list = [] list_grups = []
try: with open(path, encoding="utf-8") as sv:
with open(path, encoding="utf-8") as f: render = csv.DictReader(sv)
reader = csv.reader(f, delimiter="\t" ) for i in render:
next(reader) list_grups.append(i)
next(reader) return list_grups
for row in reader:
out_list.append(row[0].split(";"))
return out_list def find_smb_groups(self, name:str, ou:str, base:str):
except Exception as ex: group = self._smb.search_samba_ad(f"(&(objectCategory=group)(name={name})(distinguishedName=CN={name},{ou},{self.__get_str_base_ou(base)}))")
logging.error(ex) for i in group:
print("при открытии файла произошла ошибка необходимо проверить кодировку файла, а также путь до файла") return dict(i)
return None
def create_group_for_samba(self, name:str, ou:str, data_group:dict, base:str )->bool:
cmd = self._smb.add_group(name, ou)
if cmd:
self.__create_attrs(data_group, ou, base)
return True
return False
def __create_attrs(self, data_group:dict, ou, base_ou:str)->int:
logging.info("-> add attr <-")
attr_list = []
base_ou = self.__get_str_base_ou(base_ou)
l = []
for i in data_group.get("entries")[0].get("dn").split(","):
if i.split("=")[0] != "DC":
l.append(i)
l.append(base_ou)
dn = ",".join(l)
attr_list.append("dn: {}".format(dn))
attr_list.append("changetype: modify")
data = data_group.get("entries")[0].get("attributes")
if data.get("description"):
attr_list.append("add:description")
attr_list.append("description: {}".format(",".join(data.get("description"))))
if data.get("mail"):
attr_list.append("add:mail")
attr_list.append("mail: {}".format(data.get("mail")))
if data.get("info"):
attr_list.append("add:info")
attr_list.append("info: {}".format(data.get("info")))
if data.get("groupType"):
attr_list.append("replace:groupType")
attr_list.append("groupType: {}".format(data.get("groupType")))
cmd = ["ldbmodify", "-H", "/var/lib/samba/private/sam.ldb", "/tmp/group.ldif"]
with open("/tmp/group.ldif", "w") as file:
file.write("\n".join(attr_list))
out = subprocess.call(cmd,restore_signals=True, shell=False)
return out
def find_user_by_groups_samba(self, name, ou, base_ou):
str_base_ou = self.__get_str_base_ou(base_ou)
return self._smb.search_samba_ad(f"(memberOf=CN={name},{ou},{str_base_ou})")
def compare_entry_by_group(self, ms:list, name_group:str, samba_data, base):
if len(samba_data) == 0:
for items in ms:
if "person" in items.get("attributes").get("objectClass"):
if self.__is_user_samba(items.get("attributes").get("sAMAccountName")):
self.__add_entry_for_group_samba(name_group, items.get("attributes").get("sAMAccountName"))
if "group" in items.get("attributes").get("objectClass"):
add_name = self.__is_group_samba(items.get("dn"), base)
if add_name is not None:
self.__add_entry_for_group_samba(name_group, add_name)
else:
smb_list_name = []
ms_list_name = []
for i in samba_data:
smb_list_name.append(str(dict(i).get("sAMAccountName")))
for ms_i in ms:
if "person" in ms_i.get("attributes").get("objectClass"):
if ms_i.get("attributes").get("sAMAccountName") not in smb_list_name and self.__is_user_samba(ms_i.get("attributes").get("sAMAccountName")):
self.__add_entry_for_group_samba(name_group, ms_i.get("attributes").get("sAMAccountName"))
logging.info("-> add in group <-")
if "group" in ms_i.get("attributes").get("objectClass"):
if ms_i.get("attributes").get("sAMAccountName") not in smb_list_name:
add_name = self.__is_group_samba(ms_i.get("dn"), base)
if add_name is not None:
self.__add_entry_for_group_samba(name_group, add_name)
logging.info("-> add in group <-")
ms_list_name.append(ms_i.get("attributes").get("sAMAccountName"))
self.__delet_entry(ms_list_name, smb_list_name, name_group)
def __delet_entry(self, buf_ms:list, samba_buf:list, name_group:str):
for i in samba_buf:
if i not in buf_ms:
cmd = ["samba-tool", "group", "removemembers", name_group, i]
out = subprocess.call(cmd, restore_signals=True)
def __is_user_samba(self, name)->bool:
user = self._smb.search_samba_ad(f"(&(objectCategory=person)(objectClass=user)(sAMAccountName={name}))")
if len(user) !=0:
return True
return False
def __is_group_samba(self, ou, base):
path = []
for i in ou.split(","):
if i.split("=")[0] != "DC":
path.append(i)
p = ",".join(path)
group = self._smb.search_samba_ad(f"(&(objectCategory=group)(distinguishedName={p},{self.__get_str_base_ou(base)}))")
for i in group:
if dict(i).get("sAMAccountName"): return str(dict(i).get("sAMAccountName"))
return None
def __add_entry_for_group_samba(self, name_group, name_user)->int:
cmd = ["samba-tool", "group", "addmembers", name_group, name_user]
out = subprocess.call(cmd,restore_signals=True)
if out == 0:
logging.info("Added members to group {} account {}".format(name_group, name_user))
return out
if __name__ == "__main__": if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s")
MS_AD_ADRESS = 'ldap://cp-vm-dc01.energo.ru' MS_AD_ADRESS = 'ldap://cp-vm-dc01.energo.ru'
SEARCH_FREE_MS = "dc=energo,dc=ru" SEARCH_FREE_MS = "dc=energo,dc=ru"
MS_USER = 'energo\\administrator' MS_USER = 'energo\\administrator'
PASSWORD = "" PASSWORD = "P@sww0rd"
PATH_CSV = "MigrBatch1.csv" PATH_SCV = "List_groups.csv"
SEARCH_FREE_SAMBA = "dc=lenenergo,dc=ru" SEARCH_FREE_SAMBA = "dc=lenenergo,dc=ru"
TIME_RUN = "13:43"
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s")
logging.info("> Run script <")
ad = AD_provaider(MS_AD_ADRESS, SEARCH_FREE_MS, MS_USER, PASSWORD)
smb = Samba_provaider(SEARCH_FREE_SAMBA)
manager = Manager(smb, ad)
date_file = manager.open_csv_file(PATH_CSV)
if date_file is not None:
ou_add_list = [ i[5] for i in date_file]
logging.info("run create ou")
manager.creat_branch_ou(ou_add_list)# Создаст структуру OU
logging.info("> END <")
def run_script():
logging.info("> Run script <")
ad = AD_provaider(MS_AD_ADRESS, SEARCH_FREE_MS, MS_USER, PASSWORD)
smb = Samba_provaider(SEARCH_FREE_SAMBA)
manager = Manager(smb, ad)
try:
flag_out = True
count = 0
while flag_out:
data = manager.open_file_list_groups(PATH_SCV)
for items in data:
group_data_ms = manager.find_group(items.get("SamAccountName"), items.get("OU"), SEARCH_FREE_MS)
samba_groups = manager.find_smb_groups(items.get("SamAccountName"), items.get("OU"),SEARCH_FREE_SAMBA)
if samba_groups is None:
logging.info("-> Create group <-")
manager.create_group_for_samba(items.get("SamAccountName"), items.get("OU"), group_data_ms, SEARCH_FREE_SAMBA)
else:
ms_group = manager.find_user_by_groups(items.get("SamAccountName"), items.get("OU"), SEARCH_FREE_MS)
samba_group = manager.find_user_by_groups_samba(items.get("SamAccountName"), items.get("OU"), SEARCH_FREE_SAMBA)
manager.compare_entry_by_group(ms_group.get("entries"), items.get("SamAccountName"), samba_group, SEARCH_FREE_SAMBA)
logging.info("> End script <-")
time.sleep(2)
count += 1
if count > 1: break
except KeyboardInterrupt as kb:
print("ctr+c")
except Exception as ex:
logging.error(ex)
def time_run(hour:int, minuts:int):
if isinstance(hour, int) and isinstance(minuts, int) is False:
raise "Type error hour and minute is not int !!!!!"
try:
logging.info(f" -> The launch will be every day in {hour}:{minuts} <-")
while True:
time.sleep(1)
z = time.localtime()
if z.tm_hour == hour and z.tm_min == minuts and z.tm_sec == 0:
logging.info(f"-> Run time {hour}:{minuts}")
run_script()
logging.info(f" -> The launch will be every day in {hour}:{minuts} <-")
except KeyboardInterrupt:
logging.warning("ctr+c")
exit()
time_data = TIME_RUN.split(":")
time_run(int(time_data[0]), int(time_data[1]))

View File

@ -226,7 +226,7 @@ if __name__ == "__main__":
MS_AD_ADRESS = 'ldap://cp-vm-dc01.energo.ru' MS_AD_ADRESS = 'ldap://cp-vm-dc01.energo.ru'
SEARCH_FREE_MS = "dc=energo,dc=ru" SEARCH_FREE_MS = "dc=energo,dc=ru"
MS_USER = 'energo\\administrator' MS_USER = 'energo\\administrator'
PASSWORD = "" PASSWORD = "P@sww0rd"
PATH_CSV = "MigrBatch1.csv" PATH_CSV = "MigrBatch1.csv"
SEARCH_FREE_SAMBA = "dc=lenenergo,dc=ru" SEARCH_FREE_SAMBA = "dc=lenenergo,dc=ru"