commit db4dbc2e14af1d9c075973ea442c67bab1cfd754 Author: Sergey Filimonov Date: Fri Dec 20 18:17:50 2024 +0700 Init project diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7e58dfb --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +config.py +__pycache__** +res.xml +.venv** \ No newline at end of file diff --git a/MANUAL. Get token.pdf b/MANUAL. Get token.pdf new file mode 100644 index 0000000..16fd4cb Binary files /dev/null and b/MANUAL. Get token.pdf differ diff --git a/app.py b/app.py new file mode 100644 index 0000000..928f5d1 --- /dev/null +++ b/app.py @@ -0,0 +1,19 @@ +import config +import cloud +import cloudad + +c = cloud.cloud(config.API_TOKEN) +a = cloudad.AD() +#r = a.getUserInfo("M-kab4", "sAMAccountName", ['sAMAccountName', "cn", "mail", "Enabled"]) +#print(a.isDisabled("Esina.Svetlana1", "sAMAccountName")) + +for r in c.getUserList(): + print(r["name"], a.isDisabled(r["name"], "sAMAccountName"), a.isEnabled(r["name"], "sAMAccountName")) + + +# print(c.getVMList()) + +# print(c.getUserList()) + + + \ No newline at end of file diff --git a/cloud.py b/cloud.py new file mode 100644 index 0000000..04a8d23 --- /dev/null +++ b/cloud.py @@ -0,0 +1,69 @@ +import config +import requests +import xml.dom.minidom + +class cloud: + def __init__(self, API_KEY: str): + ''' + Запрос списка машин с перечнем атрибутов: Имя, ОС, IP-адрес, Состояние + На входе нужен Access Token получить который можно при помощи функции getAccessToken(API Token) + ''' + + url = "https://" + config.SITE + "/oauth/tenant/" + config.TENANT + "/token" + headers = { + "Accept": "application/json", + "Content-Type": "application/x-www-form-urlencoded", + "Content-Length": "71" + } + data = "grant_type=refresh_token&refresh_token=" + config.API_TOKEN + + try: + token = requests.post(url=url, headers=headers, data=data).json()['access_token'] + self.__access_token = token + except: + raise SystemError("Ошибка иницализации Access Token.") + + def getVMList(self) -> list: + ''' + Запрос списка машин с перечнем атрибутов: Имя, ОС, IP-адрес, Состояние + ''' + url = "https://" + config.SITE + "/api/query/?type=vm&fields=name,detectedGuestOs,ipAddress,status&filter=isVAppTemplate==false" + + headers = { + "Accept": "application/*;version=" + config.API_VERSION, + "Authorization": "Bearer " + self.__access_token + } + + res = requests.get(url=url, headers=headers) + dom = xml.dom.minidom.parseString(res.text) + + return [{ + "name": e.attributes['name'].value, + "detectedGuestOs": e.attributes['detectedGuestOs'].value, + "ipAddress": e.attributes['ipAddress'].value, + "status": e.attributes['status'].value} + for e in dom.getElementsByTagName("VMRecord")] + + def getUserList(self) -> list: + ''' + Запрос списка пользователей + На выходе имеем список словарей: + [{ + "name": "str('name')", + "fullName": "str('fullName)", + "isEnabled": bool('isEnabled') + }, { + ..... + }] + ''' + url = "https://" + config.SITE + "/api/query?type=user&fields=name,fullName,isEnabled" + + headers = { + "Accept": "application/*;version=" + config.API_VERSION, + "Authorization": "Bearer " + self.__access_token + } + + res = requests.get(url=url, headers=headers) + dom = xml.dom.minidom.parseString(res.text) + + return [{"name": e.attributes['name'].value, "fullName": e.attributes['fullName'].value, "isEnabled": bool(e.attributes['isEnabled'].value)} for e in dom.getElementsByTagName("UserRecord")] diff --git a/cloudad.py b/cloudad.py new file mode 100644 index 0000000..abd4819 --- /dev/null +++ b/cloudad.py @@ -0,0 +1,32 @@ +import ldap3 +import ldap3.abstract +import ldap3.abstract.entry +import config + +class AD: + def __init__(self): + server = ldap3.Server(config.AD_SERVER) + try: + server = ldap3.Server(config.AD_SERVER) + self.__conn = ldap3.Connection(server, user=config.AD_USERNAME, password=config.AD_PASSWORD, auto_bind=True) + except: + raise "Ошибка подключения к LDAP" + + def getUserInfo(self, searchValue: str, searchField: str, searchAttr: list) -> list: + search_filter = "(&(objectClass=User)("+ searchField +"="+ searchValue +"))" + self.__conn.search(config.AD_BASE_DN, search_filter, search_scope="LEVEL", attributes=searchAttr) + + d = {} + l = [] + for entry in self.__conn.entries: + l.append(entry.entry_attributes_as_dict) + return l + + def isDisabled(self, searchValue: str, searchField: str) -> bool: + ldap_filder = "(&(objectClass=User)(" + searchField + "="+searchValue+")(userAccountControl:1.2.840.113556.1.4.803:=2))" + self.__conn.search(config.AD_BASE_DN, ldap_filder, "SUBTREE" ) + return bool(len(self.__conn.entries)) + + def isEnabled(self, searchValue: str, searchField: str) -> bool: + return not self.isDisabled(searchValue, searchField) + \ No newline at end of file diff --git a/config.py-example b/config.py-example new file mode 100644 index 0000000..eb76667 --- /dev/null +++ b/config.py-example @@ -0,0 +1,9 @@ +API_TOKEN = "YOU TOKEN" +API_VERSION = "38.1" +SITE = "SITE NAME" +TENANT = "TENANT NAME" + +AD_SERVER = "x.x.x.x" +AD_USERNAME = "UserLogin@domain.name" +AD_PASSWORD = "VeeeeryStrongPassword" +AD_BASE_DN = "OU=Super,OU=Users,dc=consto,dc=com" \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..795d3d3 --- /dev/null +++ b/readme.md @@ -0,0 +1,22 @@ +# getCloud +Набор инструментов дял получения данных из cloud.ru + +## Что нужно для запуска +1. Установить библиотеку ldap3 +2. Для запуска необхдоимо получить API-токен на cloud.ru (инструкция находится в pdf-файле) +3. Переименовать файл config.py-example в config.py +4. Заполнить содержимое config.py актуальными данными. + + +## Структура +#### ./app.py +Основной файл приложения с примерами использования + +#### ./cloud.py +Описание класса для взаимодействия с cloud.ru + +#### ./cloud.py +Описание класса для взаимодействия с ActiveDirectory + +#### ./config.py +Конфигурационный файл с описанием глобальных переменных.