Microsegment.ru
  • Главная страница
  • О проекте
  • Портфолио
  • Блог
Системы

Анализ правил доступа в Tessa

Анализ правил доступа в Tessa
Системы

Согласно общей концепции анализа модели предоставления прав в информационной системе квадрига «роль — условия — разрешения — объект» в Tessa является квантом модели предоставления прав, и правило доступа должно быть логичным кластером подобных квантовых объектов в общей модели предоставления прав в системе. Далее предпринята попытка анализа подобных кластеров-правил доступа.

Выгрузка данных из БД Tessa¶

Далее представлен код MS SQL, предназначенный для выгрузки данных из базы данных (далее БД) Tessa, которые требуются для кластерного анализа модели предоставления прав в Tessa. Однако, в целях обеспечения безопасности эксплуатационных данных для разработки кластерного анализа предлагается использовать тестовые данные, сгенерированные с помощью генератора датафреймов, разработанного в Microsegment.ru.

-- Все правила доступа с русским переводом параметров
SELECT  kp.ID AS [ID правила доступа],
        kp.Caption AS [Название правила доступа],
        CASE WHEN kp.IsDisabled ='1' THEN 'True' ELSE 'False' END AS [Правило отключено],
        CASE WHEN kp.IsRequired ='1' THEN 'True' ELSE 'False' END AS [Всегда проверять правило],
        CASE WHEN kp.IsExtended ='1' THEN 'True'ELSE 'False' END AS [РПД],
        CASE WHEN kp.Conditions LIKE '%ConditionTypeID%' THEN 'True' ELSE 'False' END AS [Типы условий],
        -- Разрешения из правил доступа
        CASE WHEN kp.CanCreateCard ='1' THEN 'True' ELSE 'False' END AS [Создание карточки],
        CASE WHEN kp.CanReadCard ='1' THEN 'True' ELSE 'False' END AS [Чтение карточки],
        CASE WHEN kp.CanEditCard ='1' THEN 'True' ELSE 'False' END AS [Редактирование карточки],
        CASE WHEN kp.CanEditFiles ='1' THEN 'True' ELSE 'False' END AS [Редактирование файлов],
        CASE WHEN kp.CanAddFiles ='1' THEN 'True' ELSE 'False' END AS [Добавление файлов],
        CASE WHEN kp.CanEditRoute ='1' THEN 'True' ELSE 'False' END AS [Редактирование маршрута],
        CASE WHEN kp.CanDeleteCard ='1' THEN 'True' ELSE 'False' END AS [Удаление карточки],
        CASE WHEN kp.CanStartProcess ='1' THEN 'True' ELSE 'False' END AS [Инициация типового процесса отправки задач],
        CASE WHEN kp.CanEditNumber ='1' THEN 'True' ELSE 'False' END AS [Ручное редактирование номера],
        CASE WHEN kp.CanCreateResolutions ='1' THEN 'True' ELSE 'False' END AS [Создание резолюций],
        CASE WHEN kp.CanDeleteFiles ='1' THEN 'True' ELSE 'False' END AS [Удаление всех файлов],
        CASE WHEN kp.CanEditOwnFiles ='1' THEN 'True' ELSE 'False' END AS [Редактирование собственных файлов].
        CASE WHEN kp.CanDeleteownFiles ='1' THEN 'True'ELSE 'False' END AS [Удаление собственных файлов],
        CASE WHEN kp.CansignFiles ='1' THEN 'True' ELSE 'False' END AS [Подписание файлов],
        CASE WHEN kp.CanAddTopics ='1' THEN 'True'ELSE 'False'END AS [Создание обсуждений].
        CASE WHEN kp.CanSuperModeratorMode ='1' THEN 'True'ELSE 'False' END AS [Права супермодератора],
        CASE WHEN kp.CanSubscribeForNotifications = '1' THEN 'True' ELSE 'False' END AS [Подписка на уведомления],
        CASE WHEN kp.CanCreateTemplateAndCopy ='1' THEN 'True' ELSE 'False' END AS [Создание шаблона и копирование],
        CASE WHEN kp.CanSkipStages ='1' THEN 'True' ELSE 'False' END AS [Пропуск этапов],
        CASE WHEN kp.CanFullRecalcRoute ='1' THEN 'True' ELSE 'False' END AS [Полный пересчет маршрута].
        CASE WHEN kp.CanEditMyMessages ='1' THEN 'True' ELSE 'False' END AS [Редактирование своих сообщений],
        CASE WHEN kp.CanEditAllMessages ='1' THEN 'True' ELSE 'False' END AS [Редактирование всех сообщений],
        CASE WHEN kp.CanReadAllTopics ='1' THEN 'True' ELSE 'False' END AS [Чтение обсуждений],
        CASE WHEN kp.CanReadAndSendMessageInAllTopics ='1' THEN 'True' ELSE 'False' END AS [Чтение и отправка сообщений]
FROM KrPermissions (NOLOCK) kp;

-- Обогащение правил доступа дополнительными данными о ролях
SELECT DISTINCT
    -- Правила доступа
    kpr.ID AS [ID правила доступа],
    -- Роли
    kpr.RoleID AS [ID роли],
    kpr.RoleName AS [Название роли]
FROM krPermissionRoles (NOLOCK) kpr;

-- Обогащение правил доступа дополнительными данными о типах документов
SELECT DISTINCT
    -- Правила доступа
    kpt.ID AS [ID правила доступа],
    -- Тип карточки
    kpt.TypeCaption AS [ID ЛФО типа карточки]
    dbo.Localize(kpt.TypeCaption, 25) AS [Тип карточки]
FROM KrPermissionTypes (NOLOCK) kpt;

-- Обогащение правил доступа дополнительными данными о состояниях документов
SELECT DISTINCT
    -- Правила доступа
    kpt.ID AS [ID правила доступа],
    -- Состояние карточки
    kps.StateName AS [ID ЛФО состояния карточки]
    dbo.Localize(kps.StateName, 25) AS [Состояние карточки]
FROM KrPermissionStates (NOLOCK) kps

-- Расширенные правила доступа (РПД)
SELECT
DISTINCT
    -- Правила доступа
    kp.ID AS [ID правила доступа],
    -- Параметры РПД
    kpecr.SectionName AS [РПД. Секция карточки].
    kpecrf.FieldName AS [РПД. Поле карточки],
    kpecr.AccessSettingName AS [РПД. Разрешение],
    dbo.Localize(kpecr.AccesssettingName, 25) AS [РПД. Разрешение (рус)]
FROM KrPermissions AS kp
LEFT JOIN KrPermissionExtendedcardRules (NOLOCK) kpecr ON kpecr.ID = kp. ID
LEFT JOIN KrPermissionExtendedcardRulefields (NOLOCK) kpecrf ON kpecrf. ID = kp.ID;

-- Вхождение PersonalRoles в любые Roles, кроме ContextRoles
SELECT  pr.ID AS [ID пользователя],
        pr.Name AS [Имя пользователя],
        pr.Position AS [Должность пользователя], 
        pr.AccessLevelID AS [Уровень доступа пользователя], 
        pr.LoginTypeID AS [Тип учетной записи пользователя], 
        pr.Login AS [Логин пользователя],
        CASE WHEN pr.Blocked ='1' THEN 'True' END AS [Блокировка учетной записи пользователя], 
        r.ID AS [ID роли], 
        r.Name AS [Название роли], 
        r.TypeID AS [Тип роли]
FROM Roles (NOLOCK)r
LEFT JOIN RoleUsers (NOLOCK) ru ON ru.ID = r.ID
LEFT JOIN PersonalRoles (NOLOCK) pr ON pr.ID - ru.UserID
WHERE (ru. IsDeputy = O OR ru.IsDeputy IS NULL)
ORDER BY pr.Name, r.Name;

-- ContextRoles
SELECT cr.ID AS [ID роли],
        cr.SqlText AS [Код SQL]
FROM ContextRoles (NOLOCK) cr;
-- Для выявления вхождения идентификаторов ролей в коды контекстных ролей
-- (очень долгая операция, лучше реализовать локально на Python)
--LEFT JOIN Roles (NOLOCK) r ON cr.SqlText LIKE '%'+CONVERT(VARCHAR(50), .ID)+'%'

Загрузка библиотек¶

In [8]:
import pandas as pd
import numpy as np

Загрузка данных¶

In [10]:
# Данные из таблицы KrPermissions, предварительно выгруженные из БД Tessa
KrPermissions = pd.read_csv('files/KrPermissions.csv').drop('Unnamed: 0', axis=1)#, sep=';', encoding='utf-8-sig')

print(KrPermissions.info())
KrPermissions.head(5)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 187 entries, 0 to 186
Data columns (total 30 columns):
 #   Column                                      Non-Null Count  Dtype 
---  ------                                      --------------  ----- 
 0   ID правила доступа                          187 non-null    object
 1   Название правила доступа                    187 non-null    object
 2   Правило отключено                           187 non-null    bool  
 3   Всегда проверять правило                    187 non-null    bool  
 4   РПД                                         187 non-null    bool  
 5   Типы условий                                187 non-null    bool  
 6   Создание карточки                           187 non-null    bool  
 7   Чтение карточки                             187 non-null    bool  
 8   Редактирование карточки                     187 non-null    bool  
 9   Удаление карточки                           187 non-null    bool  
 10  Добавление файлов                           187 non-null    bool  
 11  Редактирование собственных файлов           187 non-null    bool  
 12  Редактирование файлов                       187 non-null    bool  
 13  Удаление собственных файлов                 187 non-null    bool  
 14  Удаление всех файлов                        187 non-null    bool  
 15  Инициация типового процесса отправки задач  187 non-null    bool  
 16  Редактирование маршрута                     187 non-null    bool  
 17  Пропуск этапов                              187 non-null    bool  
 18  Полный пересчет маршрута                    187 non-null    bool  
 19  Ручное редактирование номера                187 non-null    bool  
 20  Создание резолюций                          187 non-null    bool  
 21  Подписание файлов                           187 non-null    bool  
 22  Создание обсуждений                         187 non-null    bool  
 23  Права супермодератора                       187 non-null    bool  
 24  Подписка на уведомления                     187 non-null    bool  
 25  Создание шаблона и копирование              187 non-null    bool  
 26  Редактирование своих сообщений              187 non-null    bool  
 27  Редактирование всех сообщений               187 non-null    bool  
 28  Чтение обсуждений                           187 non-null    bool  
 29  Чтение и отправка сообщений                 187 non-null    bool  
dtypes: bool(28), object(2)
memory usage: 8.2+ KB
None
Out[10]:
ID правила доступа Название правила доступа Правило отключено Всегда проверять правило РПД Типы условий Создание карточки Чтение карточки Редактирование карточки Удаление карточки … Создание резолюций Подписание файлов Создание обсуждений Права супермодератора Подписка на уведомления Создание шаблона и копирование Редактирование своих сообщений Редактирование всех сообщений Чтение обсуждений Чтение и отправка сообщений
0 5b5a54df-f4c3-429b-9b90-afcbfc94d904 Правило 0 False True False False True True False False … True False False False False False False False False False
1 18841597-7fd1-4dd9-a48e-ed7287cb7ca9 Правило 1 False False False False True True False False … False False False False False False False False False False
2 49097422-ab5d-43db-8d58-1c2fd2e7b951 Правило 2 False False False False True False True False … False False False False False False False False False False
3 f3c8942f-da63-456d-8d4f-c9edd97d9568 Правило 3 False True False False True True True False … False False False False False False False False False False
4 5286e47f-9078-49a9-b53d-7a832f1d4c36 Правило 4 False False False False False False True True … True False False False False False False False False False

5 rows × 30 columns

In [11]:
# Данные из таблицы KrPermissionRoles, предварительно выгруженные из БД Tessa
KrPermissionRoles = pd.read_csv('files/KrPermissionRoles.csv').drop('Unnamed: 0', axis=1)#, sep=';', encoding='utf-8-sig')

print(KrPermissionRoles.info())
KrPermissionRoles.head(5)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 403 entries, 0 to 402
Data columns (total 3 columns):
 #   Column              Non-Null Count  Dtype 
---  ------              --------------  ----- 
 0   ID правила доступа  403 non-null    object
 1   ID роли             403 non-null    object
 2   Название роли       403 non-null    object
dtypes: object(3)
memory usage: 9.6+ KB
None
Out[11]:
ID правила доступа ID роли Название роли
0 20336af0-1547-4441-b701-abb37eb7e80a 80e5677f-e1d6-4ae1-ad2f-3d56ac543394 Беляева В.Д.
1 17c8a168-87ff-42ab-a499-a8af288649cf 6de6127b-f01b-4f2e-a9d8-1b8f53092e91 Григорьев Б.Д.
2 ed9ab1be-8faa-4f18-8fc8-1efc5402342b e96d002f-ee0f-461a-b831-561ff8b457e3 Юридический отдел
3 5286e47f-9078-49a9-b53d-7a832f1d4c36 fb2f72a0-002b-41f4-b61f-2a9a8660f24b Согласующий финансовых документов
4 5286e47f-9078-49a9-b53d-7a832f1d4c36 fb2f72a0-002b-41f4-b61f-2a9a8660f24b Согласующий финансовых документов
In [12]:
# Данные из таблицы KrPermissionTypes, предварительно выгруженные из БД Tessa
KrPermissionTypes = pd.read_csv('files/KrPermissionTypes.csv').drop('Unnamed: 0', axis=1)#, sep=';', encoding='utf-8-sig')

print(KrPermissionTypes.info())
KrPermissionTypes.head(5)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 174 entries, 0 to 173
Data columns (total 3 columns):
 #   Column              Non-Null Count  Dtype 
---  ------              --------------  ----- 
 0   ID правила доступа  174 non-null    object
 1   ID типа карточки    135 non-null    object
 2   Тип карточки        135 non-null    object
dtypes: object(3)
memory usage: 4.2+ KB
None
Out[12]:
ID правила доступа ID типа карточки Тип карточки
0 de03f571-e211-432c-9c8a-e863d673ebf6 c86fb70e-7352-480f-a710-e6b75e5cbac2 Дополнительное соглашение
1 d94cda5c-6434-4215-8245-a3ed951d652a 1293034c-e069-482c-a710-8738f6145b72 Входящий
2 bf756289-8092-477b-a03c-afb2c49fa6ae 97ed6f19-5201-441b-acee-8474be8a44db МЧД
3 9fdefb43-5469-4322-8a3d-c9229d89cb72 c86fb70e-7352-480f-a710-e6b75e5cbac2 Дополнительное соглашение
4 efe9a617-b5cc-432f-be74-620c4f57de40 NaN NaN
In [13]:
# Данные из таблицы KrPermissionStates, предварительно выгруженные из БД Tessa
KrPermissionStates = pd.read_csv('files/KrPermissionStates.csv').drop('Unnamed: 0', axis=1)#, sep=';', encoding='utf-8-sig')

print(KrPermissionStates.info())
KrPermissionStates.head(5)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 178 entries, 0 to 177
Data columns (total 3 columns):
 #   Column                 Non-Null Count  Dtype 
---  ------                 --------------  ----- 
 0   ID правила доступа     178 non-null    object
 1   ID состояния карточки  134 non-null    object
 2   Состояние карточки     134 non-null    object
dtypes: object(3)
memory usage: 4.3+ KB
None
Out[13]:
ID правила доступа ID состояния карточки Состояние карточки
0 5549c392-541d-4667-ac61-91596128d1a6 17215e76-92fa-4586-934e-92bc85e7f91b Проект
1 36a36459-e020-4900-80a5-468ebcaf3ca6 cbae96bd-0d35-4a38-aa01-b6fd2b4b208d Зарегистрирован
2 3d74a414-af74-4d28-a331-2d8ee29312e5 d3f85efe-2808-416f-93c0-f1589f150e47 На согласовании
3 9ed92537-fb02-4cd5-bf60-bb5ec8b690ce fdffb12d-be8d-49e2-999e-b5a661dfb955 На обработке
4 14104765-d331-467f-a9ea-639e0f7d49d2 cbae96bd-0d35-4a38-aa01-b6fd2b4b208d Зарегистрирован
In [14]:
# Данные из таблицы KrPermissionExtendedcard, предварительно выгруженные из БД Tessa
KrPermissionCardRules = pd.read_csv('files/KrPermissionExtendedcard.csv').drop('Unnamed: 0', axis=1)#, sep=';', encoding='utf-8-sig')

print(KrPermissionCardRules.info())
KrPermissionCardRules.head(5)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 5 columns):
 #   Column                 Non-Null Count  Dtype 
---  ------                 --------------  ----- 
 0   ID правила доступа     5 non-null      object
 1   РПД. Секция карточки   5 non-null      object
 2   РПД. Поле карточки     5 non-null      object
 3   РПД. Разрешение        5 non-null      object
 4   РПД. Разрешение (рус)  5 non-null      object
dtypes: object(5)
memory usage: 332.0+ bytes
None
Out[14]:
ID правила доступа РПД. Секция карточки РПД. Поле карточки РПД. Разрешение РПД. Разрешение (рус)
0 5b5a54df-f4c3-429b-9b90-afcbfc94d904 Document DocumentText Write Редактирование
1 18841597-7fd1-4dd9-a48e-ed7287cb7ca9 GeneralInformation CreationDate DenyWrite Запрещено редактировать
2 49097422-ab5d-43db-8d58-1c2fd2e7b951 EmployeeCard Salary Read Чтение
3 f3c8942f-da63-456d-8d4f-c9edd97d9568 ApprovalStage Comments Append Добавление комментариев
4 5286e47f-9078-49a9-b53d-7a832f1d4c36 BasicData Subject DenyDelete Запрещено удалять
In [15]:
# Данные из таблицы RoleUsers, предварительно выгруженные из БД Tessa
RoleUsers = pd.read_csv('files/RoleUsers.csv').drop('Unnamed: 0', axis=1)#, sep=';', encoding='utf-8-sig')

print(RoleUsers.info())
RoleUsers.head(5)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 483 entries, 0 to 482
Data columns (total 10 columns):
 #   Column                                  Non-Null Count  Dtype  
---  ------                                  --------------  -----  
 0   ID пользователя                         483 non-null    object 
 1   Имя пользователя                        483 non-null    object 
 2   Должность пользователя                  483 non-null    object 
 3   Уровень доступа пользователя            472 non-null    float64
 4   Тип учетной записи пользователя         461 non-null    float64
 5   Логин пользователя                      483 non-null    object 
 6   Блокировка учетной записи пользователя  353 non-null    object 
 7   ID роли                                 483 non-null    object 
 8   Название роли                           483 non-null    object 
 9   Тип роли                                483 non-null    int64  
dtypes: float64(2), int64(1), object(7)
memory usage: 37.9+ KB
None
Out[15]:
ID пользователя Имя пользователя Должность пользователя Уровень доступа пользователя Тип учетной записи пользователя Логин пользователя Блокировка учетной записи пользователя ID роли Название роли Тип роли
0 b554a73d-e711-404c-a92f-6b532d590f73 Комаров Р.Т. Начальник отдела 1.0 0.0 komarovrt False 0ebe84b4-137e-4020-b29e-3749d2a6310b IT-отдел 2
1 8da6a188-ec22-4d89-832a-ebbfaba2eebf Ильин О.К. Начальник отдела 0.0 0.0 ilinok NaN 3a7ba0fd-8929-438a-9b24-26a7bd547ec2 Отдел продаж 2
2 628d7ee9-3f74-4d66-bfc6-5ab086c5c903 Соколов Р.Е. Начальник отдела 1.0 1.0 sokolovre False daf6589d-885b-49ed-a347-2ea54076ea56 Отдел кадров 2
3 d12eb580-8dac-4371-bb7d-66261719caef Комаров И.А. Старший специалист 1.0 1.0 komarovia False 66d273c8-d957-4bb3-9623-3e790daa54d9 Отдел продаж 2
4 b42fa3ea-2482-460f-abd2-4a0e3531738c Смирнова О.Б. Менеджер проекта 0.0 0.0 smirnovaob True 581bcaa7-d3fe-4483-8cc2-6446e1ea33b4 Отдел продаж 2
In [16]:
# Данные из таблицы ContextRoles, предварительно выгруженные из БД Tessa
ContextRoles = pd.read_csv('files/ContextRoles.csv').drop('Unnamed: 0', axis=1)#, sep=';', encoding='utf-8-sig')

print(ContextRoles.info())
ContextRoles.head(5)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 2 columns):
 #   Column   Non-Null Count  Dtype 
---  ------   --------------  ----- 
 0   ID роли  5 non-null      object
 1   Код SQL  5 non-null      object
dtypes: object(2)
memory usage: 212.0+ bytes
None
Out[16]:
ID роли Код SQL
0 3a39dcf7-49d7-4a5c-a765-4aa3c16a081c \nSELECT u.UserID, u.Name\nFROM Users u\nJOIN …
1 48307771-7cf8-43a1-ae95-92fbf4e0d263 \nSELECT u.UserID, u.Name\nFROM Users u\nJOIN …
2 899889c8-9be5-49fc-bde1-9cdf1a65e8eb \nSELECT u.UserID, u.Name\nFROM Users u\nJOIN …
3 cc4461f1-02ed-465e-a4c0-ef6b13845bd4 \nSELECT u.UserID, u.Name\nFROM Users u\nJOIN …
4 4a39f1d5-a3ab-4aa4-b748-1fd725321b6d \nSELECT u.UserID, u.Name\nFROM Users u\nJOIN …

Предобработка данных¶

Перемещение дополнительной информации из датафреймов с правилами в отдельные датафреймы¶

In [19]:
# Перемещение данных о правилах доступа в отдельный датафрейм 
rules_data = KrPermissions[['ID правила доступа', 'Название правила доступа', 
                            'Правило отключено', 'Всегда проверять правило', 
                            'РПД', 'Типы условий']]\
.groupby(['ID правила доступа', 'Название правила доступа', 
          'Правило отключено', 'Всегда проверять правило', 
          'РПД', 'Типы условий']).count().reset_index()
KrPermissions = KrPermissions.drop(['Название правила доступа', 
                                    'Правило отключено', 'Всегда проверять правило', 
                                    'РПД', 'Типы условий'], axis=1)

print(rules_data.info())
rules_data.head(5)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 187 entries, 0 to 186
Data columns (total 6 columns):
 #   Column                    Non-Null Count  Dtype 
---  ------                    --------------  ----- 
 0   ID правила доступа        187 non-null    object
 1   Название правила доступа  187 non-null    object
 2   Правило отключено         187 non-null    bool  
 3   Всегда проверять правило  187 non-null    bool  
 4   РПД                       187 non-null    bool  
 5   Типы условий              187 non-null    bool  
dtypes: bool(4), object(2)
memory usage: 3.8+ KB
None
Out[19]:
ID правила доступа Название правила доступа Правило отключено Всегда проверять правило РПД Типы условий
0 0156312e-890f-49e3-8c5d-d8df16376bd4 Правило 38 False True True False
1 0359fea5-f9d6-4911-acbe-70f82c858418 Правило 143 True False False False
2 051b8ae8-cefe-4327-9511-777515747775 Правило 47 False False False False
3 05bd596d-c6ad-474b-80db-fdbecab66f21 Правило 124 True False False False
4 07cc452b-48c4-4176-b13d-ab576ae7afdc Правило 67 False False False False
In [20]:
# Перемещение названий ролей из правил доступа в отдельный датафрейм 
roles_name = KrPermissionRoles[['ID роли', 'Название роли']]\
.groupby(['ID роли', 'Название роли']).count().reset_index()
KrPermissionRoles = KrPermissionRoles.drop(['Название роли'], axis=1)

print(rules_data.info())
rules_data.head(5)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 187 entries, 0 to 186
Data columns (total 6 columns):
 #   Column                    Non-Null Count  Dtype 
---  ------                    --------------  ----- 
 0   ID правила доступа        187 non-null    object
 1   Название правила доступа  187 non-null    object
 2   Правило отключено         187 non-null    bool  
 3   Всегда проверять правило  187 non-null    bool  
 4   РПД                       187 non-null    bool  
 5   Типы условий              187 non-null    bool  
dtypes: bool(4), object(2)
memory usage: 3.8+ KB
None
Out[20]:
ID правила доступа Название правила доступа Правило отключено Всегда проверять правило РПД Типы условий
0 0156312e-890f-49e3-8c5d-d8df16376bd4 Правило 38 False True True False
1 0359fea5-f9d6-4911-acbe-70f82c858418 Правило 143 True False False False
2 051b8ae8-cefe-4327-9511-777515747775 Правило 47 False False False False
3 05bd596d-c6ad-474b-80db-fdbecab66f21 Правило 124 True False False False
4 07cc452b-48c4-4176-b13d-ab576ae7afdc Правило 67 False False False False

Перемещение дополнительной информации из датафреймов с ролями в отдельные датафреймы¶

In [22]:
# Перемещение данных о правилах доступа в отдельный датафрейм 
user_data = RoleUsers[['ID пользователя', 
                       'Имя пользователя', 
                       'Логин пользователя', 
                       'Должность пользователя', 
                       'Уровень доступа пользователя', 
                       'Тип учетной записи пользователя', 
                       'Блокировка учетной записи пользователя']]\
.groupby(['ID пользователя', 
          'Имя пользователя', 
          'Логин пользователя', 
          'Должность пользователя', 
          'Уровень доступа пользователя', 
          'Тип учетной записи пользователя', 
          'Блокировка учетной записи пользователя'], 
         # Не удалять строки с пропусками
         dropna=False)\
.count().reset_index()
user_data = user_data[~user_data['ID пользователя'].isnull()]
RoleUsers = RoleUsers.drop(['Имя пользователя', 
                            'Логин пользователя', 
                            'Должность пользователя', 
                            'Уровень доступа пользователя', 
                            'Тип учетной записи пользователя', 
                            'Блокировка учетной записи пользователя'], axis=1)

print(user_data.info())
user_data.head(5)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 216 entries, 0 to 215
Data columns (total 7 columns):
 #   Column                                  Non-Null Count  Dtype  
---  ------                                  --------------  -----  
 0   ID пользователя                         216 non-null    object 
 1   Имя пользователя                        216 non-null    object 
 2   Логин пользователя                      216 non-null    object 
 3   Должность пользователя                  216 non-null    object 
 4   Уровень доступа пользователя            211 non-null    float64
 5   Тип учетной записи пользователя         206 non-null    float64
 6   Блокировка учетной записи пользователя  159 non-null    object 
dtypes: float64(2), object(5)
memory usage: 11.9+ KB
None
Out[22]:
ID пользователя Имя пользователя Логин пользователя Должность пользователя Уровень доступа пользователя Тип учетной записи пользователя Блокировка учетной записи пользователя
0 00000000-0000-0000-0000-000000000002 Бухгалтерские сервисы accounting_services Сервис 0.0 2.0 False
1 00000000-0000-0000-0000-000000000003 ИТ-сервисы it_services Сервис 0.0 2.0 False
2 00000000-0000-0000-0000-000000000004 Сайт компании company_website Сервис 0.0 2.0 False
3 00000000-0000-0000-0000-000000000005 Робот службы безопасности security_service_robot Робот 1.0 2.0 False
4 00000000-0000-0000-0000-000000000006 Робот финансовой службы financial_service_robot Робот 0.0 2.0 False
In [23]:
# Перемещение данных о правилах доступа в отдельный датафрейм 
role_name = RoleUsers[['ID роли', 'Название роли']]\
.groupby(['ID роли', 'Название роли']).count().reset_index()
RoleUsers = RoleUsers.drop(['Название роли'], axis=1)

print(role_name.info())
role_name.head(5)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 429 entries, 0 to 428
Data columns (total 2 columns):
 #   Column         Non-Null Count  Dtype 
---  ------         --------------  ----- 
 0   ID роли        429 non-null    object
 1   Название роли  429 non-null    object
dtypes: object(2)
memory usage: 6.8+ KB
None
Out[23]:
ID роли Название роли
0 00000000-0000-0000-0000-000000000002 Бухгалтерские сервисы
1 00000000-0000-0000-0000-000000000003 ИТ-сервисы
2 00000000-0000-0000-0000-000000000004 Сайт компании
3 00000000-0000-0000-0000-000000000005 Робот службы безопасности
4 00000000-0000-0000-0000-000000000006 Робот финансовой службы
In [24]:
# Перемещение данных од известных ролях в отдельный датафрейм
roles = RoleUsers[RoleUsers['ID роли'] != 'Unknown'].drop_duplicates()

print(roles.info())
roles.head(5)
<class 'pandas.core.frame.DataFrame'>
Index: 476 entries, 0 to 482
Data columns (total 3 columns):
 #   Column           Non-Null Count  Dtype 
---  ------           --------------  ----- 
 0   ID пользователя  476 non-null    object
 1   ID роли          476 non-null    object
 2   Тип роли         476 non-null    int64 
dtypes: int64(1), object(2)
memory usage: 14.9+ KB
None
Out[24]:
ID пользователя ID роли Тип роли
0 b554a73d-e711-404c-a92f-6b532d590f73 0ebe84b4-137e-4020-b29e-3749d2a6310b 2
1 8da6a188-ec22-4d89-832a-ebbfaba2eebf 3a7ba0fd-8929-438a-9b24-26a7bd547ec2 2
2 628d7ee9-3f74-4d66-bfc6-5ab086c5c903 daf6589d-885b-49ed-a347-2ea54076ea56 2
3 d12eb580-8dac-4371-bb7d-66261719caef 66d273c8-d957-4bb3-9623-3e790daa54d9 2
4 b42fa3ea-2482-460f-abd2-4a0e3531738c 581bcaa7-d3fe-4483-8cc2-6446e1ea33b4 2

Кластеризация правил и ролей¶

Правила и роли не дающие прав пользователям¶

In [27]:
# Связка полной информации о ролях с идентификаторами правил,
# в которых роли используются
rules_roles = pd.merge(KrPermissionRoles, 
                       roles, 
                       on='ID роли', how='left')

rules_roles = pd.merge(rules_roles, 
                       rules_data[['ID правила доступа', 'Правило отключено']], 
                       on='ID правила доступа', how='left')

print(rules_roles.info())
rules_roles.head(5)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3655 entries, 0 to 3654
Data columns (total 5 columns):
 #   Column              Non-Null Count  Dtype 
---  ------              --------------  ----- 
 0   ID правила доступа  3655 non-null   object
 1   ID роли             3655 non-null   object
 2   ID пользователя     3655 non-null   object
 3   Тип роли            3655 non-null   int64 
 4   Правило отключено   3655 non-null   bool  
dtypes: bool(1), int64(1), object(3)
memory usage: 117.9+ KB
None
Out[27]:
ID правила доступа ID роли ID пользователя Тип роли Правило отключено
0 20336af0-1547-4441-b701-abb37eb7e80a 80e5677f-e1d6-4ae1-ad2f-3d56ac543394 80e5677f-e1d6-4ae1-ad2f-3d56ac543394 1 False
1 17c8a168-87ff-42ab-a499-a8af288649cf 6de6127b-f01b-4f2e-a9d8-1b8f53092e91 6de6127b-f01b-4f2e-a9d8-1b8f53092e91 1 False
2 ed9ab1be-8faa-4f18-8fc8-1efc5402342b e96d002f-ee0f-461a-b831-561ff8b457e3 8d0dc4c3-be5b-4294-82cf-9422c7c00eae 2 True
3 5286e47f-9078-49a9-b53d-7a832f1d4c36 fb2f72a0-002b-41f4-b61f-2a9a8660f24b 776d348c-5e78-45f6-b87d-6f1fbe205bbe 0 False
4 5286e47f-9078-49a9-b53d-7a832f1d4c36 fb2f72a0-002b-41f4-b61f-2a9a8660f24b e932ad1c-5331-4dfd-82b0-b5f45ca45c21 0 False
In [28]:
# Правила с групповыми ролями, но не контекстными, по которым практически
# не возможно отследить, кому они предоставляют права
rules_not_contextual_roles = rules_roles[rules_roles['Тип роли'] != 4]

print('-'*5, 'Правила без контекстных ролей', '-'*5)
print(rules_roles.info())
rules_roles.head(5)
----- Правила без контекстных ролей -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3655 entries, 0 to 3654
Data columns (total 5 columns):
 #   Column              Non-Null Count  Dtype 
---  ------              --------------  ----- 
 0   ID правила доступа  3655 non-null   object
 1   ID роли             3655 non-null   object
 2   ID пользователя     3655 non-null   object
 3   Тип роли            3655 non-null   int64 
 4   Правило отключено   3655 non-null   bool  
dtypes: bool(1), int64(1), object(3)
memory usage: 117.9+ KB
None
Out[28]:
ID правила доступа ID роли ID пользователя Тип роли Правило отключено
0 20336af0-1547-4441-b701-abb37eb7e80a 80e5677f-e1d6-4ae1-ad2f-3d56ac543394 80e5677f-e1d6-4ae1-ad2f-3d56ac543394 1 False
1 17c8a168-87ff-42ab-a499-a8af288649cf 6de6127b-f01b-4f2e-a9d8-1b8f53092e91 6de6127b-f01b-4f2e-a9d8-1b8f53092e91 1 False
2 ed9ab1be-8faa-4f18-8fc8-1efc5402342b e96d002f-ee0f-461a-b831-561ff8b457e3 8d0dc4c3-be5b-4294-82cf-9422c7c00eae 2 True
3 5286e47f-9078-49a9-b53d-7a832f1d4c36 fb2f72a0-002b-41f4-b61f-2a9a8660f24b 776d348c-5e78-45f6-b87d-6f1fbe205bbe 0 False
4 5286e47f-9078-49a9-b53d-7a832f1d4c36 fb2f72a0-002b-41f4-b61f-2a9a8660f24b e932ad1c-5331-4dfd-82b0-b5f45ca45c21 0 False
In [29]:
# Предварительный список правил с ролями без пользователей
'''
_rules_without_users = rules_not_contextual_roles[rules_not_contextual_roles['ID пользователя'].isnull()]\
.sort_values(['ID правила доступа', 'ID роли'])\
.drop(['ID пользователя', 'Должность пользователя', 
       'Уровень доступа пользователя', 'Тип учетной записи пользователя', 
       'Блокировка учетной записи пользователя'], axis=1).drop_duplicates()
'''
_rules_without_users = rules_not_contextual_roles[rules_not_contextual_roles['ID пользователя'].isnull()]\
.sort_values(['ID правила доступа', 'ID роли'])\
.drop(['ID пользователя'], axis=1).drop_duplicates()

# Правила с ролями без пользователей
rules_without_users = pd.merge(_rules_without_users['ID правила доступа'].drop_duplicates(), 
                               rules_data[['ID правила доступа', 'Название правила доступа', 'Правило отключено']], 
                               on='ID правила доступа', how='inner')
rules_without_users.to_csv('clusters/rules_without_users.csv')

print('-'*5, 'Правила с ролями без пользователей', '-'*5)
print(rules_without_users.info())
rules_without_users.head(5)
----- Правила с ролями без пользователей -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 0 entries
Data columns (total 3 columns):
 #   Column                    Non-Null Count  Dtype 
---  ------                    --------------  ----- 
 0   ID правила доступа        0 non-null      object
 1   Название правила доступа  0 non-null      object
 2   Правило отключено         0 non-null      bool  
dtypes: bool(1), object(2)
memory usage: 132.0+ bytes
None
Out[29]:
ID правила доступа Название правила доступа Правило отключено
In [30]:
# Роли без пользователей в правилах
'''
roles_without_users = pd.merge(_rules_without_users[['ID роли', 'Тип роли']].drop_duplicates(), 
    rules_data[['ID роли', 'Название роли']], 
    on='ID роли', how='left')[['ID роли', 'Название роли', 'Тип роли']]
roles_without_users.to_csv('clusters/rules_without_users.csv')
'''
roles_without_users = pd.merge(_rules_without_users[['ID роли', 'Тип роли']].drop_duplicates(), 
    role_name[['ID роли', 'Название роли']], 
    on='ID роли', how='left')[['ID роли', 'Название роли', 'Тип роли']]
roles_without_users.to_csv('clusters/rules_without_users.csv')

print('-'*5, 'Роли без пользователей (в правилах)', '-'*5)
print(roles_without_users.info())
roles_without_users.head(5)
----- Роли без пользователей (в правилах) -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 0 entries
Data columns (total 3 columns):
 #   Column         Non-Null Count  Dtype 
---  ------         --------------  ----- 
 0   ID роли        0 non-null      object
 1   Название роли  0 non-null      object
 2   Тип роли       0 non-null      int64 
dtypes: int64(1), object(2)
memory usage: 132.0+ bytes
None
Out[30]:
ID роли Название роли Тип роли
In [31]:
# Предварительный список правил с ролями с пользователями
_rules_with_users = rules_not_contextual_roles[~rules_not_contextual_roles['ID пользователя'].isnull()]\
.sort_values(['ID правила доступа', 'ID роли'])\
.drop(['ID пользователя'], axis=1).drop_duplicates()

# Правила с ролями с пользователями
rules_with_users = pd.merge(_rules_with_users['ID правила доступа'].drop_duplicates(), 
                               rules_data[['ID правила доступа', 'Название правила доступа', 'Правило отключено']], 
                               on='ID правила доступа', how='inner')
rules_with_users.to_csv('clusters/rules_with_users.csv')

print('-'*5, 'Правила с ролями с пользователями', '-'*5)
print(rules_with_users.info())
rules_with_users.head(5)
----- Правила с ролями с пользователями -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 102 entries, 0 to 101
Data columns (total 3 columns):
 #   Column                    Non-Null Count  Dtype 
---  ------                    --------------  ----- 
 0   ID правила доступа        102 non-null    object
 1   Название правила доступа  102 non-null    object
 2   Правило отключено         102 non-null    bool  
dtypes: bool(1), object(2)
memory usage: 1.8+ KB
None
Out[31]:
ID правила доступа Название правила доступа Правило отключено
0 0156312e-890f-49e3-8c5d-d8df16376bd4 Правило 38 False
1 051b8ae8-cefe-4327-9511-777515747775 Правило 47 False
2 09c45d7d-ee39-4e35-b47b-5b40edfa20bf Правило 184 False
3 131ea06e-e001-4cec-a0f8-b31d29bd57d6 Правило 20 False
4 13d02e38-aa00-4782-9770-bca53a6838b2 Правило 22 False
In [32]:
# Роли с пользователями в правилах
'''
roles_with_users = pd.merge(_rules_with_users[['ID роли', 'Тип роли']].drop_duplicates(), 
rules_data[['ID роли', 'Название роли']], 
on='ID роли', how='left')[['ID роли', 'Название роли', 'Тип роли']]
'''
roles_with_users = pd.merge(_rules_with_users[['ID роли', 'Тип роли']].drop_duplicates(), 
role_name[['ID роли', 'Название роли']], 
on='ID роли', how='left')[['ID роли', 'Название роли', 'Тип роли']]

roles_with_users.to_csv('clusters/roles_with_users.csv')

print('-'*5, 'Роли с пользователями (в правилах)', '-'*5)
print(roles_with_users.info())
roles_with_users.head(5)
----- Роли с пользователями (в правилах) -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 125 entries, 0 to 124
Data columns (total 3 columns):
 #   Column         Non-Null Count  Dtype 
---  ------         --------------  ----- 
 0   ID роли        125 non-null    object
 1   Название роли  125 non-null    object
 2   Тип роли       125 non-null    int64 
dtypes: int64(1), object(2)
memory usage: 3.1+ KB
None
Out[32]:
ID роли Название роли Тип роли
0 49d7a40b-b8a2-4e51-ab99-febf59a885b6 Юридический отдел 2
1 27a6ba8d-4cc5-464e-a1d9-d30daf643391 Отдел продаж 2
2 71a48819-fca5-4d4d-a9b9-0ca13e41b63f Михайлов Д.Г. 1
3 8d0dc4c3-be5b-4294-82cf-9422c7c00eae Титов Д.Д. 1
4 d1c293a6-21aa-4c45-8e77-ceb8f6fc726a Руководство 2

Правила с заблокированными пользователями¶

In [34]:
# Карточки заблокирванных пользователей
blocked_users = user_data[
    (user_data['Логин пользователя'].isna()) 
    | (user_data['Блокировка учетной записи пользователя'] == 1)
    & ~(user_data['ID пользователя'] == '11111111-1111-1111-1111-111111111111')
][['ID пользователя', 'Имя пользователя']]

# Карточки не заблокированных пользователей
non_blocked_users = user_data[
    ~(user_data['Логин пользователя'].isna()) 
    | ~(user_data['Блокировка учетной записи пользователя'] == 1)
][['ID пользователя', 'Имя пользователя']]

print('-'*5, 'Заблокированные пользователи', '-'*5)
print(blocked_users.info())
display(blocked_users.head(5))

print('-'*5, 'Не заблокированные пользователи', '-'*5)
print(non_blocked_users.info())
display(non_blocked_users.head(5))
----- Заблокированные пользователи -----
<class 'pandas.core.frame.DataFrame'>
Index: 14 entries, 13 to 196
Data columns (total 2 columns):
 #   Column            Non-Null Count  Dtype 
---  ------            --------------  ----- 
 0   ID пользователя   14 non-null     object
 1   Имя пользователя  14 non-null     object
dtypes: object(2)
memory usage: 336.0+ bytes
None
ID пользователя Имя пользователя
13 0b9ec6fd-10d5-4436-8748-3bfe58677e89 Степанова О.Г.
52 3f7cd252-a4db-4774-ad74-6026668d4b07 Куликова Р.М.
54 421d676f-9536-4046-83aa-9b39cf666e30 Морозов А.А.
55 42e0089a-6687-4c36-b291-e50814cd15ed Смирнова Л.Д.
65 4842d040-4327-4245-b837-34561fb30273 Сорокин М.С.
----- Не заблокированные пользователи -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 216 entries, 0 to 215
Data columns (total 2 columns):
 #   Column            Non-Null Count  Dtype 
---  ------            --------------  ----- 
 0   ID пользователя   216 non-null    object
 1   Имя пользователя  216 non-null    object
dtypes: object(2)
memory usage: 3.5+ KB
None
ID пользователя Имя пользователя
0 00000000-0000-0000-0000-000000000002 Бухгалтерские сервисы
1 00000000-0000-0000-0000-000000000003 ИТ-сервисы
2 00000000-0000-0000-0000-000000000004 Сайт компании
3 00000000-0000-0000-0000-000000000005 Робот службы безопасности
4 00000000-0000-0000-0000-000000000006 Робот финансовой службы
In [35]:
# Правила с заблокированными пользователями
_rules_with_blocked_users = rules_not_contextual_roles[
    rules_not_contextual_roles['ID пользователя'].isin(blocked_users['ID пользователя'])
]['ID правила доступа'].drop_duplicates()
rules_with_blocked_users = rules_with_users[rules_with_users['ID правила доступа'].isin(_rules_with_blocked_users)].drop_duplicates()
rules_with_blocked_users.to_csv('clusters/rules_with_blocked_users.csv')

# Правила с не заблокированными пользователями
_rules_with_non_blocked_users = rules_not_contextual_roles[
    rules_not_contextual_roles['ID пользователя'].isin(non_blocked_users['ID пользователя'])
]['ID правила доступа'].drop_duplicates()
rules_with_non_blocked_users = rules_with_users[rules_with_users['ID правила доступа'].isin(_rules_with_non_blocked_users)].drop_duplicates()
rules_with_non_blocked_users.to_csv('clusters/rules_with_non_blocked_users.csv')

print('-'*5, 'Правила с заблокированными пользователями', '-'*5)
print(rules_with_blocked_users.info())
display(rules_with_blocked_users.head(5))
print()

print('-'*5, 'Правила с не заблокированными пользователями', '-'*5)
print(rules_with_non_blocked_users.info())
display(rules_with_non_blocked_users.head(5))
----- Правила с заблокированными пользователями -----
<class 'pandas.core.frame.DataFrame'>
Index: 29 entries, 7 to 99
Data columns (total 3 columns):
 #   Column                    Non-Null Count  Dtype 
---  ------                    --------------  ----- 
 0   ID правила доступа        29 non-null     object
 1   Название правила доступа  29 non-null     object
 2   Правило отключено         29 non-null     bool  
dtypes: bool(1), object(2)
memory usage: 725.0+ bytes
None
ID правила доступа Название правила доступа Правило отключено
7 20336af0-1547-4441-b701-abb37eb7e80a Правило 26 False
9 2882e956-a847-4425-91eb-2a22860a766e Правило 86 False
10 2927ff14-1eb4-4c8d-8541-822547b8aa18 Правило 7 False
14 30b2b26e-1a46-4a60-addb-451eca6ce528 Правило 6 True
16 35d0ca67-430d-4101-866c-1425472896b1 Правило 54 False
----- Правила с не заблокированными пользователями -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 102 entries, 0 to 101
Data columns (total 3 columns):
 #   Column                    Non-Null Count  Dtype 
---  ------                    --------------  ----- 
 0   ID правила доступа        102 non-null    object
 1   Название правила доступа  102 non-null    object
 2   Правило отключено         102 non-null    bool  
dtypes: bool(1), object(2)
memory usage: 1.8+ KB
None
ID правила доступа Название правила доступа Правило отключено
0 0156312e-890f-49e3-8c5d-d8df16376bd4 Правило 38 False
1 051b8ae8-cefe-4327-9511-777515747775 Правило 47 False
2 09c45d7d-ee39-4e35-b47b-5b40edfa20bf Правило 184 False
3 131ea06e-e001-4cec-a0f8-b31d29bd57d6 Правило 20 False
4 13d02e38-aa00-4782-9770-bca53a6838b2 Правило 22 False

Правила с сотрудниками без групповых ролей¶

In [37]:
# Предварительный список правил с сотрудниками без групповых ролей
_rules_with_users_without_roles = rules_not_contextual_roles[
    rules_not_contextual_roles['Тип роли'] == 1 # Тип роли Сотрудник
].sort_values(['ID правила доступа', 'ID роли']).drop(['ID пользователя'], axis=1).drop_duplicates()

# Правила с сотрудниками без групповых ролей
rules_with_users_without_roles = pd.merge(_rules_with_users_without_roles['ID правила доступа'].drop_duplicates(), 
                                          rules_data[['ID правила доступа', 'Название правила доступа', 'Правило отключено']], 
                                          on='ID правила доступа', how='inner')
rules_with_users_without_roles.to_csv('clusters/rules_with_users_without_roles.csv')

# Пользователи без групповых ролей в правилах
roles_with_users_without_roles = pd.merge(_rules_with_users_without_roles[['ID роли', 'Тип роли']].drop_duplicates(), 
                                          roles_name[['ID роли', 'Название роли']], 
                                          on='ID роли', how='left')[['ID роли', 'Название роли', 'Тип роли']]
roles_with_users_without_roles.to_csv('clusters/roles_with_users_without_roles.csv')

print('-'*5, 'Правила с сотрудниками без групповых ролей', '-'*5)
print(rules_with_users_without_roles.info())
display(rules_with_users_without_roles.head(5))
print()

print('-'*5, 'Пользователи без групповых ролей в правилах', '-'*5)
print(roles_with_users_without_roles.info())
display(roles_with_users_without_roles.head(5))
----- Правила с сотрудниками без групповых ролей -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 63 entries, 0 to 62
Data columns (total 3 columns):
 #   Column                    Non-Null Count  Dtype 
---  ------                    --------------  ----- 
 0   ID правила доступа        63 non-null     object
 1   Название правила доступа  63 non-null     object
 2   Правило отключено         63 non-null     bool  
dtypes: bool(1), object(2)
memory usage: 1.2+ KB
None
ID правила доступа Название правила доступа Правило отключено
0 09c45d7d-ee39-4e35-b47b-5b40edfa20bf Правило 184 False
1 131ea06e-e001-4cec-a0f8-b31d29bd57d6 Правило 20 False
2 13d02e38-aa00-4782-9770-bca53a6838b2 Правило 22 False
3 17b1b391-9abc-4f8c-9fd3-9e62bee4790d Правило 103 False
4 17c8a168-87ff-42ab-a499-a8af288649cf Правило 142 False
----- Пользователи без групповых ролей в правилах -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 65 entries, 0 to 64
Data columns (total 3 columns):
 #   Column         Non-Null Count  Dtype 
---  ------         --------------  ----- 
 0   ID роли        65 non-null     object
 1   Название роли  65 non-null     object
 2   Тип роли       65 non-null     int64 
dtypes: int64(1), object(2)
memory usage: 1.7+ KB
None
ID роли Название роли Тип роли
0 71a48819-fca5-4d4d-a9b9-0ca13e41b63f Михайлов Д.Г. 1
1 8d0dc4c3-be5b-4294-82cf-9422c7c00eae Титов Д.Д. 1
2 eb532d6a-5ffa-4d26-83c6-af0912b79e27 Соловьёва Р.Д. 1
3 f1e9bbca-03a2-4d2e-939f-4573d680d245 Морозов А.А. 1
4 57ee420c-1548-42b3-b8b6-f3cbc9b65ce1 Комарова Т.В. 1

Правила с пользователем System¶

In [39]:
# Предварительный список правил с пользователем System
_rules_with_system = rules_not_contextual_roles[
    rules_not_contextual_roles['ID пользователя'] == '11111111-1111-1111-1111-111111111111' # Пользователь System
].sort_values(['ID правила доступа', 'ID роли']).drop(['ID пользователя'], axis=1).drop_duplicates()

# Правила с пользователем System
rules_with_system = pd.merge(_rules_with_system['ID правила доступа'].drop_duplicates(), 
                             rules_data[['ID правила доступа', 'Название правила доступа', 'Правило отключено']], 
                             on='ID правила доступа', how='inner')
rules_with_system.to_csv('clusters/rules_with_system.csv')

# Роли с пользователем System
roles_with_system = pd.merge(_rules_with_system[['ID роли', 'Тип роли']].drop_duplicates(), 
                             roles_name[['ID роли', 'Название роли']], 
                             on='ID роли', how='left')[['ID роли', 'Название роли', 'Тип роли']]
roles_with_system.to_csv('clusters/roles_with_users_without_roles.csv')

print('-'*5, 'Правила с пользователем System', '-'*5)
print(rules_with_system.info())
display(rules_with_system.head(5))
print()

print('-'*5, 'Роли с пользователем System', '-'*5)
print(roles_with_system.info())
display(roles_with_system.head(5))
----- Правила с пользователем System -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 0 entries
Data columns (total 3 columns):
 #   Column                    Non-Null Count  Dtype 
---  ------                    --------------  ----- 
 0   ID правила доступа        0 non-null      object
 1   Название правила доступа  0 non-null      object
 2   Правило отключено         0 non-null      bool  
dtypes: bool(1), object(2)
memory usage: 132.0+ bytes
None
ID правила доступа Название правила доступа Правило отключено
----- Роли с пользователем System -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 0 entries
Data columns (total 3 columns):
 #   Column         Non-Null Count  Dtype 
---  ------         --------------  ----- 
 0   ID роли        0 non-null      object
 1   Название роли  0 non-null      object
 2   Тип роли       0 non-null      int64 
dtypes: int64(1), object(2)
memory usage: 132.0+ bytes
None
ID роли Название роли Тип роли

Правила с системными ролями¶

In [41]:
rules_not_contextual_roles
Out[41]:
ID правила доступа ID роли ID пользователя Тип роли Правило отключено
0 20336af0-1547-4441-b701-abb37eb7e80a 80e5677f-e1d6-4ae1-ad2f-3d56ac543394 80e5677f-e1d6-4ae1-ad2f-3d56ac543394 1 False
1 17c8a168-87ff-42ab-a499-a8af288649cf 6de6127b-f01b-4f2e-a9d8-1b8f53092e91 6de6127b-f01b-4f2e-a9d8-1b8f53092e91 1 False
2 ed9ab1be-8faa-4f18-8fc8-1efc5402342b e96d002f-ee0f-461a-b831-561ff8b457e3 8d0dc4c3-be5b-4294-82cf-9422c7c00eae 2 True
3 5286e47f-9078-49a9-b53d-7a832f1d4c36 fb2f72a0-002b-41f4-b61f-2a9a8660f24b 776d348c-5e78-45f6-b87d-6f1fbe205bbe 0 False
4 5286e47f-9078-49a9-b53d-7a832f1d4c36 fb2f72a0-002b-41f4-b61f-2a9a8660f24b e932ad1c-5331-4dfd-82b0-b5f45ca45c21 0 False
… … … … … …
3650 35d0ca67-430d-4101-866c-1425472896b1 0eda49ad-18db-4d8f-bbfc-5239b3f39252 290b018c-cfc2-4bca-aad0-0b117b3a2a19 0 False
3651 6e7ba467-4b8f-4628-a007-cfdb2b18c17a c4ddb00f-7aae-4a49-b468-9af017ed1100 eaa562e4-bdf3-4355-aa74-54060f2a8ec5 2 False
3652 83bd2279-20e7-440a-ab8a-f6b26cede17c 6f9f1412-d3a6-4be8-8789-5d542b896fa8 6f9f1412-d3a6-4be8-8789-5d542b896fa8 1 False
3653 56fb5b4b-8bcc-4287-84ac-26af690185c3 2bddbdfa-b91b-4ca5-8726-92e6a253f504 2bddbdfa-b91b-4ca5-8726-92e6a253f504 1 False
3654 862822e0-164e-426e-83fc-07f3af78f110 39c44b9b-46bf-4d0a-ba81-6b8084a396ce 39c44b9b-46bf-4d0a-ba81-6b8084a396ce 1 False

3655 rows × 5 columns

In [42]:
# Предварительный список правил с системными пользователями
'''
_rules_with_systems_roles = rules_not_contextual_roles[rules_not_contextual_roles['ID пользователя'].isin([
    #'11111111-1111-1111-1111-111111111111', #'System'
    '00000000-0000-0000-0000-000000000002', # 'Бухгалтерские сервисы'
    '00000000-0000-0000-0000-000000000003', # 'ИТ-сервисы'
    '00000000-0000-0000-0000-000000000004', # 'Сайт компании'
    '00000000-0000-0000-0000-000000000005', # 'Робот службы безопасности'
    '00000000-0000-0000-0000-000000000006', # 'Робот финансовой службы'
    '00000000-0000-0000-0000-000000000007'  # 'Юридические сервисы'
])].sort_values([
    'ID правила доступа',
    'ID роли'
]).drop(['ID пользователя', 
         'Должность пользователя', 
         'Уровень доступа пользователя', 
         'Тип учетной записи  пользователя', 
         'Блокировка учетной записи пользователя'
], axis=1).drop_duplicates()
'''
_rules_with_systems_roles = rules_not_contextual_roles[rules_not_contextual_roles['ID пользователя'].isin([
    #'11111111-1111-1111-1111-111111111111', #'System'
    '00000000-0000-0000-0000-000000000002', # 'Бухгалтерские сервисы'
    '00000000-0000-0000-0000-000000000003', # 'ИТ-сервисы'
    '00000000-0000-0000-0000-000000000004', # 'Сайт компании'
    '00000000-0000-0000-0000-000000000005', # 'Робот службы безопасности'
    '00000000-0000-0000-0000-000000000006', # 'Робот финансовой службы'
    '00000000-0000-0000-0000-000000000007'  # 'Юридические сервисы'
])].sort_values([
    'ID правила доступа',
    'ID роли'
]).drop(['ID пользователя'
], axis=1).drop_duplicates()

# Правила с системными пользователями
rules_with_systems_roles = pd.merge(
    _rules_with_systems_roles['ID правила доступа'].drop_duplicates(), 
    rules_data[['ID правила доступа','Название правила доступа','Правило отключено']],
    on='ID правила доступа', how='inner')
rules_with_systems_roles.to_csv('clusters/rules_with_system.csv')

# Роли с системными пользователями в правилах
roles_with_systems_roles = pd.merge(
    _rules_with_systems_roles[['ID роли','Тип роли']].drop_duplicates(), 
    role_name[['ID роли','Название роли']], 
    on='ID роли', how='left'
)[['ID роли','Название роли','Тип роли']]
roles_with_systems_roles.to_csv('clusters/roles_with_system.csv')

print('-'*5, 'Правила с системными пользователями', '-'*5)
print(rules_with_systems_roles.info())
display(rules_with_systems_roles.head(5))
print()

print('-'*5, 'Роли с системными пользователями в правилах','-'*5)
print(roles_with_systems_roles.info())
display(roles_with_systems_roles.head(5))
----- Правила с системными пользователями -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4 entries, 0 to 3
Data columns (total 3 columns):
 #   Column                    Non-Null Count  Dtype 
---  ------                    --------------  ----- 
 0   ID правила доступа        4 non-null      object
 1   Название правила доступа  4 non-null      object
 2   Правило отключено         4 non-null      bool  
dtypes: bool(1), object(2)
memory usage: 200.0+ bytes
None
ID правила доступа Название правила доступа Правило отключено
0 5f00b5e3-060e-4f76-923b-9c5cee5fb1a2 Правило 30 False
1 62efd89f-4495-4042-bc08-5ba4fc608d05 Правило 12 False
2 635e701d-f2bd-4616-8994-db1206c5f882 Правило 160 False
3 b2322015-2883-460c-be26-99803aa581e3 Правило 53 False
----- Роли с системными пользователями в правилах -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3 entries, 0 to 2
Data columns (total 3 columns):
 #   Column         Non-Null Count  Dtype 
---  ------         --------------  ----- 
 0   ID роли        3 non-null      object
 1   Название роли  3 non-null      object
 2   Тип роли       3 non-null      int64 
dtypes: int64(1), object(2)
memory usage: 204.0+ bytes
None
ID роли Название роли Тип роли
0 00000000-0000-0000-0000-000000000002 Бухгалтерские сервисы 1
1 00000000-0000-0000-0000-000000000004 Сайт компании 1
2 00000000-0000-0000-0000-000000000005 Робот службы безопасности 1

Правила с администраторами¶

In [44]:
# Предварительный список правил с администраторами
'''
_rules_with_admins = rules_not_contextual_roles[
    (rules_not_contextual_roles['ID пользователя'].isin(['00000000-0000-0000-0000-000000000008'])) # Статическая роль 'Сотрудники с правами Администратора
    | (rules_not_contextual_roles['Уровень доступа пользователя']== 1) # Административный уровень доступа
].sort_values(['ID правила доступа','ID роли']).drop([
    'ID пользователя', 'Доложность пользователя', 
    'Уровень доступа пользователя', 'Тип учетной записи пользователя', 
    'Блокировка учетной записи пользователя'
], axis=1).drop_duplicates
'''
_rules_with_admins = rules_not_contextual_roles[
    (rules_not_contextual_roles['ID пользователя'] == '00000000-0000-0000-0000-000000000008') # Статическая роль 'Сотрудники с правами Администратора
    | (
        rules_not_contextual_roles['ID пользователя'].isin(
            user_data[user_data['Уровень доступа пользователя'] == 1]['ID пользователя']
        )
    ) # Административный уровень доступа
].sort_values(['ID правила доступа','ID роли']).drop([
    'ID пользователя'], axis=1).drop_duplicates()

# Правила с администраторами
rules_with_admins = pd.merge(_rules_with_admins['ID правила доступа'].drop_duplicates(), 
                             rules_data[['ID правила доступа', 
                                         'Название правила доступа', 
                                         'Правило отключено']], on='ID правила доступа', how='inner')
rules_with_admins.to_csv('clusters/rules_with_admins.csv')

# Роли с администраторами
roles_with_admins = pd.merge(_rules_with_admins[['ID роли','Тип роли']].drop_duplicates(), 
                             role_name[['ID роли','Название роли']], 
                             on='ID роли', how='left')[['ID роли','Название роли','Тип роли']]
roles_with_admins.to_csv('clusters/roles_with_admins.csv')

print('-'*5, 'Правила с администраторами', '-'*5)
print(rules_with_admins.info())
display(rules_with_admins.head(5))
print()

print('-'*5, 'Роли с администраторами в правилах', '-'*5)
print(roles_with_admins.info())
display(roles_with_admins.head(5))
----- Правила с администраторами -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 69 entries, 0 to 68
Data columns (total 3 columns):
 #   Column                    Non-Null Count  Dtype 
---  ------                    --------------  ----- 
 0   ID правила доступа        69 non-null     object
 1   Название правила доступа  69 non-null     object
 2   Правило отключено         69 non-null     bool  
dtypes: bool(1), object(2)
memory usage: 1.3+ KB
None
ID правила доступа Название правила доступа Правило отключено
0 0156312e-890f-49e3-8c5d-d8df16376bd4 Правило 38 False
1 051b8ae8-cefe-4327-9511-777515747775 Правило 47 False
2 09c45d7d-ee39-4e35-b47b-5b40edfa20bf Правило 184 False
3 131ea06e-e001-4cec-a0f8-b31d29bd57d6 Правило 20 False
4 13d02e38-aa00-4782-9770-bca53a6838b2 Правило 22 False
----- Роли с администраторами в правилах -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 64 entries, 0 to 63
Data columns (total 3 columns):
 #   Column         Non-Null Count  Dtype 
---  ------         --------------  ----- 
 0   ID роли        64 non-null     object
 1   Название роли  64 non-null     object
 2   Тип роли       64 non-null     int64 
dtypes: int64(1), object(2)
memory usage: 1.6+ KB
None
ID роли Название роли Тип роли
0 49d7a40b-b8a2-4e51-ab99-febf59a885b6 Юридический отдел 2
1 27a6ba8d-4cc5-464e-a1d9-d30daf643391 Отдел продаж 2
2 71a48819-fca5-4d4d-a9b9-0ca13e41b63f Михайлов Д.Г. 1
3 8d0dc4c3-be5b-4294-82cf-9422c7c00eae Титов Д.Д. 1
4 d1c293a6-21aa-4c45-8e77-ceb8f6fc726a Руководство 2

Объединение данных о результатах анализа правил¶

In [46]:
# Данные о правилах
result_rules = rules_data[['ID правила доступа','Название правила доступа','Правило отключено']].drop_duplicates()
result_rules['РПД'] = np.where(result_rules['ID правила доступа'].isin(rules_data[rules_data['РПД'] == True]['ID правила доступа']), True, False)
result_rules['Типы условий'] = np.where(result_rules['ID правила доступа'].isin(rules_data[rules_data['Типы условий'] == True]['ID правила доступа']), True, False)
# Данные о ролях в правилах
result_rules['Контекстные роли'] = np.where(result_rules['ID правила доступа'].isin(rules_roles[rules_roles['Тип роли'] == 4]['ID правила доступа']), True, False)
result_rules['Роли с пользователями'] = np.where(result_rules['ID правила доступа'].isin(rules_with_users['ID правила доступа']), True, False)
result_rules['Роли без пользователей'] = np.where(result_rules['ID правила доступа'].isin(rules_without_users['ID правила доступа']), True, False)
result_rules['Роли с не заблокированными пользователями'] = np.where(result_rules['ID правила доступа'].isin(rules_with_non_blocked_users['ID правила доступа']), True, False)
result_rules['Роли с заблокированными пользователями'] = np.where(result_rules['ID правила доступа'].isin(rules_with_blocked_users['ID правила доступа']), True, False)
result_rules['Пользователи без групповых ролей'] = np.where(result_rules['ID правила доступа'].isin(rules_with_users_without_roles['ID правила доступа']), True, False)
result_rules['Роли с System'] = np.where(result_rules['ID правила доступа'].isin(rules_with_system['ID правила доступа']), True, False)
result_rules['Роли с системными пользователям'] = np.where(result_rules['ID правила доступа'].isin(rules_with_systems_roles['ID правила доступа']), True, False)
result_rules['Роли с администраторами'] = np.where(result_rules['ID правила доступа'].isin(rules_with_admins['ID правила доступа']), True, False)
# Данные о разрешениях
result_rules['Чтение карточки'] = np.where(result_rules['ID правила доступа'].isin(KrPermissions[KrPermissions['Чтение карточки'] == True]['ID правила доступа']), True, False)
result_rules['Создание карточки'] = np.where(result_rules['ID правила доступа'].isin(KrPermissions[KrPermissions['Создание карточки'] == True]['ID правила доступа']), True, False)
result_rules['Редактирование карточки'] = np.where(result_rules['ID правила доступа'].isin(KrPermissions[KrPermissions['Редактирование карточки'] == True]['ID правила доступа']), True, False)
result_rules['Удаление карточки'] = np.where(result_rules['ID правила доступа'].isin(KrPermissions[KrPermissions['Удаление карточки'] == True]['ID правила доступа']), True, False)
result_rules['Добавление файлов'] = np.where(result_rules['ID правила доступа'].isin(KrPermissions[KrPermissions['Добавление файлов'] == True]['ID правила доступа']), True, False)
result_rules['Редактирование файлов'] = np.where(result_rules['ID правила доступа'].isin(KrPermissions[KrPermissions['Редактирование файлов'] == True]['ID правила доступа']), True, False)
result_rules['Удаление всех файлов'] = np.where(result_rules['ID правила доступа'].isin(KrPermissions[KrPermissions['Удаление всех файлов'] == True]['ID правила доступа']), True, False)

print('-'*5,'Результаты анализа правил','-'*5)
print(result_rules.info())
display(result_rules.head(5))
----- Результаты анализа правил -----
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 187 entries, 0 to 186
Data columns (total 21 columns):
 #   Column                                     Non-Null Count  Dtype 
---  ------                                     --------------  ----- 
 0   ID правила доступа                         187 non-null    object
 1   Название правила доступа                   187 non-null    object
 2   Правило отключено                          187 non-null    bool  
 3   РПД                                        187 non-null    bool  
 4   Типы условий                               187 non-null    bool  
 5   Контекстные роли                           187 non-null    bool  
 6   Роли с пользователями                      187 non-null    bool  
 7   Роли без пользователей                     187 non-null    bool  
 8   Роли с не заблокированными пользователями  187 non-null    bool  
 9   Роли с заблокированными пользователями     187 non-null    bool  
 10  Пользователи без групповых ролей           187 non-null    bool  
 11  Роли с System                              187 non-null    bool  
 12  Роли с системными пользователям            187 non-null    bool  
 13  Роли с администраторами                    187 non-null    bool  
 14  Чтение карточки                            187 non-null    bool  
 15  Создание карточки                          187 non-null    bool  
 16  Редактирование карточки                    187 non-null    bool  
 17  Удаление карточки                          187 non-null    bool  
 18  Добавление файлов                          187 non-null    bool  
 19  Редактирование файлов                      187 non-null    bool  
 20  Удаление всех файлов                       187 non-null    bool  
dtypes: bool(19), object(2)
memory usage: 6.5+ KB
None
ID правила доступа Название правила доступа Правило отключено РПД Типы условий Контекстные роли Роли с пользователями Роли без пользователей Роли с не заблокированными пользователями Роли с заблокированными пользователями … Роли с System Роли с системными пользователям Роли с администраторами Чтение карточки Создание карточки Редактирование карточки Удаление карточки Добавление файлов Редактирование файлов Удаление всех файлов
0 0156312e-890f-49e3-8c5d-d8df16376bd4 Правило 38 False True False False True False True False … False False True True True False False True True False
1 0359fea5-f9d6-4911-acbe-70f82c858418 Правило 143 True False False False False False False False … False False False True False False True False False False
2 051b8ae8-cefe-4327-9511-777515747775 Правило 47 False False False False True False True False … False False True True True True True True False False
3 05bd596d-c6ad-474b-80db-fdbecab66f21 Правило 124 True False False False False False False False … False False False False True True True True False False
4 07cc452b-48c4-4176-b13d-ab576ae7afdc Правило 67 False False False False False False False False … False False False True False True False False False False

5 rows × 21 columns

Кластеризация правил¶

In [48]:
# Кластеры правил и рекомендации
result_rules['Кластеры'] = ''
result_rules['Рекомендации'] = ''

# Все роли пустые
mask = ((result_rules['Роли с пользователями'] == False)
    & (result_rules['Роли без пользователей'] == True)
    | ( (result_rules['Роли с не заблокированными пользователями'] == False)
    & (result_rules['Роли с заблокированными пользователями'] == True))
    & (result_rules['Кластеры'] == ''))
result_rules.loc[mask, 'Кластеры'] = 'Все роли пустые. '
result_rules.loc[mask, 'Рекомендации'] = 'Удалить правила и роли внутри них. '

# Есть пустые роли
mask = ((result_rules['Роли с пользователями'] == True)
    & (result_rules['Роли без пользователей'] == True)
    | ( (result_rules['Роли с не заблокированными пользователями'] == True)
    & (result_rules['Роли с заблокированными пользователями'] == True)))
result_rules.loc[mask, 'Кластеры'] = 'Пустые роли. '
result_rules.loc[mask, 'Рекомендации'] = 'Проверить правила и роли внутри них. '

# Иднивидуальные роли
mask = (result_rules['Пользователи без групповых ролей'] == True)
result_rules.loc[mask, 'Кластеры'] += 'Индивидуальные роли. '
result_rules.loc[mask, 'Рекомендации'] += 'Использовать групповые роли вместо иднивидуальных'

# Контекстные роли
mask = (result_rules['Контекстные роли'] == True)
result_rules.loc[mask, 'Кластеры'] += 'Контекстные роли. '
result_rules.loc[mask, 'Рекомендации'] += 'Контекстные роли заменить на групповые роли и типы условий. '

# Системные роли
mask = ((result_rules['Роли с системными пользователям'] == True))
result_rules.loc[mask, 'Кластеры'] += 'Системные роли. '
result_rules.loc[mask, 'Рекомендации'] += 'Сверить права системных ролей с их ТЗ. '

# Административные права
mask = ((result_rules['Роли с System'] == True)
    | (result_rules['Роли с администраторами'] == True))
result_rules.loc[mask, 'Кластеры'] += 'Административные права. '
result_rules.loc[mask, 'Рекомендации'] += 'Особое внимание на список администраторов. '

# Полные права на модификацию документов
mask = ((result_rules['Редактирование карточки'] == True)
    & (result_rules['Удаление карточки'] == True)
    & (result_rules['Добавление файлов'] == True)
    & (result_rules['Редактирование файлов'] == True)
    & (result_rules['Удаление всех файлов'] == True))
result_rules.loc[mask, 'Кластеры'] += 'Полные права на модификацию документов. '
result_rules.loc[mask, 'Рекомендации'] += 'Проверить риск возможности подлога документов. '

# Права на чтение
mask = ((result_rules['Чтение карточки'] == True))
result_rules.loc[mask, 'Кластеры'] += 'Права на чтение. '
result_rules.loc[mask, 'Рекомендации'] += 'Сверить права с бизнес-требованиями на доступ к документам. '

# Права на создание
mask = ((result_rules['Создание карточки'] == True))
result_rules.loc[mask, 'Кластеры'] += 'Права на создание. '
result_rules.loc[mask, 'Рекомендации'] += ''

result_rules.to_csv('clusters/result_rules.csv', sep=';', encoding='utf-8-sig')
result_rules.head()
Out[48]:
ID правила доступа Название правила доступа Правило отключено РПД Типы условий Контекстные роли Роли с пользователями Роли без пользователей Роли с не заблокированными пользователями Роли с заблокированными пользователями … Роли с администраторами Чтение карточки Создание карточки Редактирование карточки Удаление карточки Добавление файлов Редактирование файлов Удаление всех файлов Кластеры Рекомендации
0 0156312e-890f-49e3-8c5d-d8df16376bd4 Правило 38 False True False False True False True False … True True True False False True True False Административные права. Права на чтение. Права… Особое внимание на список администраторов. Све…
1 0359fea5-f9d6-4911-acbe-70f82c858418 Правило 143 True False False False False False False False … False True False False True False False False Права на чтение. Сверить права с бизнес-требованиями на доступ …
2 051b8ae8-cefe-4327-9511-777515747775 Правило 47 False False False False True False True False … True True True True True True False False Административные права. Права на чтение. Права… Особое внимание на список администраторов. Све…
3 05bd596d-c6ad-474b-80db-fdbecab66f21 Правило 124 True False False False False False False False … False False True True True True False False Права на создание.
4 07cc452b-48c4-4176-b13d-ab576ae7afdc Правило 67 False False False False False False False False … False True False True False False False False Права на чтение. Сверить права с бизнес-требованиями на доступ …

5 rows × 23 columns

Python sql анализ информационная система информация корпоративная информационная система модель предоставления прав практика

Предыдущая статьяИнтерпретация кластерного анализа модели предоставления разрешений в TessaСледующая статья Общая концепция анализа модели предоставления прав в информационной системе

Рубрики

Метки

abc abcd AI-Ready платформа Bash Data Lakehouse ELT excel ms sql n8n PostgreSQL PowerShell Python RAG RAW sql STG tessa VBA xyz ИИ-агент анализ виртуальный помощник гибридное хранилище данных данные знания информационная система информация искусственный интеллект кластерный анализ компетенции корпоративная информационная система математика модель предоставления прав мудрость о проекте оптимизация практика программное обеспечение ролевая модель сеть; теория теория вероятностей тесса юмор языки программирования

Политика конфиденциальности

Продолжая использовать данный сайт вы подтверждаете свое согласие с условиями его политики конфиденциальности. Подробнее…




Администрация и владельцы данного информационного ресурса не несут ответственности за возможные последствия, связанные с использованием информации, размещенной на нем.


Все права защищены. При копировании материалов сайта обязательно указывать ссылку на © Microsegment.ru (2020-2026)