add myoffice scripts
This commit is contained in:
12
myoffice_projects/co_scripts/pgs_group_sync/Dockerfile
Normal file
12
myoffice_projects/co_scripts/pgs_group_sync/Dockerfile
Normal file
@@ -0,0 +1,12 @@
|
||||
FROM python:3.10-alpine
|
||||
|
||||
WORKDIR /srv/hyperus_apps/pgs_sync
|
||||
COPY group_sync_pgs.py ./
|
||||
|
||||
RUN python3 -m venv venv && \
|
||||
source venv/bin/activate && \
|
||||
pip install \
|
||||
python-freeipa==1.0.6 \
|
||||
requests
|
||||
|
||||
CMD ["/bin/sh", "-c", "source venv/bin/activate; python ./group_sync_pgs.py"]
|
||||
30
myoffice_projects/co_scripts/pgs_group_sync/README.md
Normal file
30
myoffice_projects/co_scripts/pgs_group_sync/README.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# PGS_GROUP_SYNC
|
||||
|
||||
- Скрипт синхронизирует группы в PGS из IPA
|
||||
- Актуализирует состав групп пользователей
|
||||
|
||||
## Переменные окружения
|
||||
| Название | Значение по умолчанию | Описание |
|
||||
| --------------------- | ------------------------------------- | ---------------------------------------------- |
|
||||
| IPA_ADDRESS | "ipa01.hyperus.team" | Адрес сервера IPA |
|
||||
| IPA_GROUP_ATTR | "description" | Атрибут используемый в качестве имени группы |
|
||||
| IPA_USERNAME | "automated.carbon" | Учетная запись подключения к IPA |
|
||||
| IPA_PASSWORD | | Пароль учетной записи подключения к IPA |
|
||||
| PGS_ADMINAPI_URL | "https://admin.hyperus.team/adminapi" | Адрес AdminAPI PGS |
|
||||
| PGS_ADMINAPI_PASSWORD | | Пароль учетной записи с правами администратора |
|
||||
| PGS_ADMINAPI_TENANT | "default" | Тенант к которому принадлежит домен |
|
||||
| PGS_ADMINAPI_USERNAME | "admin@hyperus.team" | Учетная запись с правами администратора |
|
||||
|
||||
## Установка
|
||||
|
||||
1. Собрать образ и запустить контейнер.
|
||||
После аргумента `-e` указать переменные окружения и их значения
|
||||
|
||||
```bash
|
||||
docker build . --tag pgs_group_sync:0.0.1
|
||||
docker run -d -e IPA_PASSWORD="securepassword" -e PGS_ADMINAPI_PASSWORD="securepassword" --name pgs_group_sync pgs_group_sync:0.0.1
|
||||
```
|
||||
2. Добавить в cron задачу по запуску контейнера с необходимым интервалом.
|
||||
```
|
||||
*/5 * * * * docker start pgs_group_sync 2>%1 1>/dev/null
|
||||
```
|
||||
@@ -0,0 +1,29 @@
|
||||
apiVersion: "batch/v1"
|
||||
kind: "CronJob"
|
||||
metadata:
|
||||
name: "groupsync-cronjob"
|
||||
spec:
|
||||
concurrencyPolicy: "Forbid"
|
||||
failedJobsHistoryLimit: 1
|
||||
jobTemplate:
|
||||
spec:
|
||||
backoffLimit: 0
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: "group_sync_pgs"
|
||||
image: "nexus.hyperus.team/groupsync:latest"
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
env:
|
||||
- name: "PGS_ADMINAPI_PASSWORD"
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: "infrastructure/pgs"
|
||||
key: "ADMIN_PASSWORD"
|
||||
- name: "IPA_PASSWORD"
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: "infrastructure/service_accounts/carbon"
|
||||
key: "password"
|
||||
restartPolicy: "Never"
|
||||
schedule: "*/5 * * * *"
|
||||
147
myoffice_projects/co_scripts/pgs_group_sync/group_sync_pgs.py
Normal file
147
myoffice_projects/co_scripts/pgs_group_sync/group_sync_pgs.py
Normal file
@@ -0,0 +1,147 @@
|
||||
import os
|
||||
import requests
|
||||
import python_freeipa as freeipa
|
||||
import warnings
|
||||
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
class GroupSyncPGS:
|
||||
"""
|
||||
Реализует:
|
||||
- Получение списка групп с участниками из FreeIPA
|
||||
- Получение списка групп с участниками из PGS
|
||||
- Получение списка пользователей из PGS
|
||||
- Сравнение групп и членства участников
|
||||
- Добавление групп и участников в PGS
|
||||
- Удаление групп и участников в PGS
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.ipa_address = os.environ.get("IPA_ADDRESS", "ipa01.hyperus.team")
|
||||
self.ipa_group_attr = os.environ.get("IPA_GROUP_ATTR", "description")
|
||||
self.ipa_password = os.environ.get("IPA_PASSWORD")
|
||||
self.ipa_username = os.environ.get("IPA_USERNAME", "automated.carbon")
|
||||
self.pgs_adminapi_address = os.environ.get("PGS_ADMINAPI_URL", "https://admin.hyperus.team/adminapi")
|
||||
self.pgs_adminapi_password = os.environ.get("PGS_ADMINAPI_PASSWORD")
|
||||
self.pgs_adminapi_tenant = os.environ.get("PGS_ADMINAPI_TENANT", "default")
|
||||
self.pgs_adminapi_username = os.environ.get("PGS_ADMINAPI_USERNAME", "admin@hyperus.team")
|
||||
|
||||
def pgs_auth(self) -> None:
|
||||
pgs_credentials = {"username": self.pgs_adminapi_username, "password": self.pgs_adminapi_password}
|
||||
result = requests.post(url=f"{self.pgs_adminapi_address}/auth", data=pgs_credentials, verify=False)
|
||||
if result.status_code == 200:
|
||||
self.pgs_adminapi_token = result.json()["token"]
|
||||
else:
|
||||
raise ConnectionRefusedError("Authentication failed")
|
||||
self.__pgs_adminapi_header = {"Authorization": self.pgs_adminapi_token}
|
||||
|
||||
def get_ipa_groups(self) -> dict:
|
||||
ipa_groups_formated = {}
|
||||
ipa_client = freeipa.ClientMeta(host=self.ipa_address, verify_ssl=False)
|
||||
ipa_client.login(self.ipa_username, self.ipa_password)
|
||||
ipa_groups_find = ipa_client.group_find()
|
||||
ipa_client.logout()
|
||||
ipa_groups_find = list(filter( lambda ipa_group: "member_user" in ipa_group.keys(), ipa_groups_find["result"] ))
|
||||
for ipa_group in ipa_groups_find:
|
||||
ipa_group_name = "".join(ipa_group[self.ipa_group_attr])
|
||||
ipa_groups_formated[ipa_group_name] = ["{}@hyperus.team".format(user) for user in ipa_group["member_user"]]
|
||||
return ipa_groups_formated
|
||||
|
||||
def get_pgs_groups(self) -> dict:
|
||||
pgs_groups_formated = {}
|
||||
response = requests.get(url=f"{self.pgs_adminapi_address}/tenants/{self.pgs_adminapi_tenant}/groups", headers=self.__pgs_adminapi_header, verify=False)
|
||||
if response.status_code == 200:
|
||||
pgs_groups_finded = response.json()["groups"]
|
||||
else:
|
||||
raise Exception("PGS API: can't get groups list")
|
||||
for pgs_group in pgs_groups_finded:
|
||||
pgs_groups_formated[pgs_group["name"]] = {}
|
||||
pgs_groups_formated[pgs_group["name"]]["id"] = pgs_group["id"]
|
||||
pgs_groups_formated[pgs_group["name"]]["members"] = ["{}".format(user["username"]) for user in pgs_group["users"]]
|
||||
return pgs_groups_formated
|
||||
|
||||
def get_pgs_users(self) -> dict:
|
||||
pgs_users_formated = {}
|
||||
response = requests.get(url=f"{self.pgs_adminapi_address}/tenants/{self.pgs_adminapi_tenant}/users", headers=self.__pgs_adminapi_header, verify=False)
|
||||
if response.status_code == 200:
|
||||
pgs_users_finded = response.json()["users"]
|
||||
else:
|
||||
raise Exception("PGS API: can't get users list")
|
||||
for pgs_user in pgs_users_finded:
|
||||
pgs_users_formated[pgs_user["username"]] = pgs_user["id"]
|
||||
return pgs_users_formated
|
||||
|
||||
def compare_groups(self, source={}, destination={}, pgs_users={}) -> None:
|
||||
if not source:
|
||||
source = self.get_ipa_groups()
|
||||
if not destination:
|
||||
destination = self.get_pgs_groups()
|
||||
if not pgs_users:
|
||||
pgs_users = self.get_pgs_users()
|
||||
|
||||
to_create_groups = list(filter(lambda group: group not in destination, source))
|
||||
to_delete_groups = list(filter(lambda group: group not in source, destination))
|
||||
for group in to_create_groups:
|
||||
group_members = [pgs_users[username] for username in source[group]]
|
||||
self.create_pgs_group(group, group_members)
|
||||
for group in to_delete_groups:
|
||||
self.delete_pgs_group(destination[group]["id"])
|
||||
|
||||
def compare_members(self, source={}, destination={}, pgs_users={}) -> None:
|
||||
if not source:
|
||||
source = self.get_ipa_groups()
|
||||
if not destination:
|
||||
destination = self.get_pgs_groups()
|
||||
if not pgs_users:
|
||||
pgs_users = self.get_pgs_users()
|
||||
|
||||
for group in source:
|
||||
to_create_membership = list(filter( lambda member: member not in destination[group]["members"], source[group] ))
|
||||
to_remove_membership = list(filter( lambda member: member not in source[group], destination[group]["members"] ))
|
||||
if len(to_create_membership) > 0:
|
||||
group_members = [pgs_users[username] for username in to_create_membership]
|
||||
response = self.set_pgs_group_members("POST", destination[group]["id"], group_members)
|
||||
if response.status_code == 200:
|
||||
print("Users has been added to group <{}>".format(group))
|
||||
else:
|
||||
raise Exception("Error during adding members to group <{}>".format(group))
|
||||
if len(to_remove_membership) > 0:
|
||||
group_members = [pgs_users[username] for username in to_remove_membership]
|
||||
response = self.set_pgs_group_members("DELETE", destination[group]["id"], group_members)
|
||||
if response.status_code == 200:
|
||||
print("Users has been removed from group <{}>".format(group))
|
||||
else:
|
||||
raise Exception("Error during removing members from group <{}>".format(group))
|
||||
|
||||
def create_pgs_group(self, pgs_group_name, pgs_users={}):
|
||||
pgs_group_data = {"name": pgs_group_name, "users": pgs_users}
|
||||
response = requests.post(url=f"{self.pgs_adminapi_address}/tenants/{self.pgs_adminapi_tenant}/groups", headers=self.__pgs_adminapi_header, data=pgs_group_data, verify=False)
|
||||
if response.status_code == 200:
|
||||
print("Group <{}> was created".format(pgs_group_name))
|
||||
else:
|
||||
raise Exception("Error during creation group <{}>".format(pgs_group_name))
|
||||
return response
|
||||
|
||||
def delete_pgs_group(self, pgs_group_name):
|
||||
response = requests.delete(url=f"{self.pgs_adminapi_address}/tenants/{self.pgs_adminapi_tenant}/groups/{pgs_group_name}", headers=self.__pgs_adminapi_header, verify=False)
|
||||
if response.status_code == 200:
|
||||
print("Group <{}> was deleted".format(pgs_group_name))
|
||||
else:
|
||||
raise Exception("Error during removing group <{}>".format(pgs_group_name))
|
||||
return response
|
||||
|
||||
def set_pgs_group_members(self, method, pgs_group_id, pgs_users={}):
|
||||
pgs_data = {"users": pgs_users}
|
||||
response = requests.request(method, f"{self.pgs_adminapi_address}/tenants/{self.pgs_adminapi_tenant}/groups/{pgs_group_id}/users", headers=self.__pgs_adminapi_header, data=pgs_data, verify=False)
|
||||
return response
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sync_manager = GroupSyncPGS()
|
||||
sync_manager.pgs_auth()
|
||||
pgs_users = sync_manager.get_pgs_users()
|
||||
ipa_groups = sync_manager.get_ipa_groups()
|
||||
pgs_groups = sync_manager.get_pgs_groups()
|
||||
sync_manager.compare_groups(ipa_groups, pgs_groups, pgs_users)
|
||||
sync_manager.compare_members(ipa_groups, pgs_users=pgs_users)
|
||||
Reference in New Issue
Block a user