Се­год­ня погово­рим о том, как повысить безопас­ность сер­вера на при­мере пароль­ного менед­жера Пас­сворк. Я покажу, как сок­ратить повер­хность ата­ки, а так­же напишем скрипт, который отсту­чит тебе в ЛС об ата­ке на менед­жер паролей.

Я сто­рон­ник идеи, что не быва­ет абсо­лют­но защищен­ных сис­тем: ата­кующие про­дол­жают находить всё более изощ­ренные уяз­вимос­ти. Добавь к это­му челове­чес­кий фак­тор. Прог­раммис­ты, девоп­сы, любые спе­циалис­ты могут совер­шать ошиб­ки. Поэто­му с точ­ки зре­ния защиты, единс­твен­ное что ты можешь делать — повышать зат­раты на взлом тво­их ресур­сов.

Пас­сворк — это быс­трый спо­соб силь­но уве­личить зат­раты на взлом тво­ей сис­темы. При этом, управляя сей­фами, дирек­тори­ями и пароля­ми, ты в пару кли­ков можешь решать серь­езные задачи. Нап­ример, пре­дос­тавить вре­мен­ный дос­туп сто­рон­ней коман­де раз­работ­ки, а ког­да они закон­чат про­ект, отклю­чить им дос­туп и заново сге­нери­ровать пароли.

 

Подготовка Пассворка

Ес­ли у тво­ей кон­торы нет лицен­зии Пас­сворк, пер­вый воп­рос — где его взять? Топай на passwork.ru и регай­ся на три­ал. Учи­тывай, что перед тем как отпра­вить дан­ные для дос­тупа, раз­работ­чики хотят убе­дить­ся, что ты нас­тоящий покупа­тель. По телефо­ну зво­нить не будут, а вот поч­товый домен точ­но пос­мотрят. При зап­росе проб­ной вер­сии нуж­но ука­зать кор­поратив­ную поч­ту, то есть не на Gmail, Outlook или Mail.Ru, а на сво­ем домене.

Те­бе дадут тес­товый стенд и дан­ные для логина.

Зай­ди в раз­дел «Аутен­тифика­ция». Про­мотай в самый низ к бло­ку «API-дос­туп». Cге­нери­руй API-токены.

Сис­тема соз­даст три токена, с помощью которых твой сер­вер смо­жет получать дан­ные из Пас­свор­ка.

Сис­тема пос­тро­ена по прин­ципу API first — вся работа с Пас­свор­ком — это, по сути, работа с API раз­ными спо­соба­ми. Есть ути­лита passwork-cli, есть кон­тей­нер Docker с пре­дус­танов­ленной ути­литой, есть пакет Python для раз­работ­ки собс­твен­ных скрип­тов. Но можешь писать скрип­ты на любом язы­ке, глав­ное — это воз­можность выпол­нять GET- и POST-зап­росы.

 

База API Пассворк

Ус­тановим пакет passwork-python для Python, это офи­циаль­ный кли­ент Passwork:

pip install passwork-python

Те­перь можем соз­дать кли­ента и вза­имо­дей­ство­вать с API:

from passwork_client import PassworkClient
# Используй данные из шага с генерацией токенов
client = PassworkClient(host="https://passwork.example.com")
client.set_tokens("ACCESS_TOKEN", "REFRESH_TOKEN")
client.set_master_key("MASTER_KEY")

Даль­нейшая работа — прос­то обра­щение к методам client. Нап­ример, client.create_vault() для соз­дания нового сей­фа.

info

Сейф — это груп­па сек­ретных дан­ных, которая име­ет собс­твен­ные нас­трой­ки при­ват­ности. Соз­даешь сейф, ука­зыва­ешь пра­ва на него, накиды­ваешь в него сек­ретные дан­ные.

Нап­ример, у тебя может быть две коман­ды DevOps, и им нуж­ны раз­ные наборы паролей и токенов. Соз­дай нес­коль­ко сей­фов, пре­дос­тавь каж­дой из команд дос­туп к нуж­ному сей­фу и получишь прек­расную изо­ляцию дан­ных.

В при­мерах кода, мож­но уви­деть что create_vault() при­нима­ет два парамет­ра: наз­вание vault_name и тип хра­нили­ща type_id. Наз­вание — это обыч­ная стро­ка, а вот с типом воз­ника­ют нюан­сы. Типы сей­фов — это еще один спо­соб груп­пиров­ки с задани­ем прав. Но пос­мотреть иден­тифика­торы мож­но толь­ко через API.

В тех­ничес­кой докумен­тации ты най­дешь опи­сание API, но давай сами заг­лянем внутрь passwork_client.py. Меня заин­тересо­вал этот импорт:

from .modules.vault_type import VaultType

В фай­ле есть под­ходящая фун­кция: get_vault_types(). Про­буем извлечь дан­ные:

from passwork_client import PassworkClient
client = PassworkClient(host="https://ruxakep.passwork-demo.space/")
client.set_tokens("1KqoGku9GYYYlsxj3BcLAvUqxa5ej/9M50/akAUuRvU=", "mXjYIaJUSTCzFa+RwHowNbguv2TF3OofnW7q8Hbb9AU=")
client.set_master_key("vznRsji3NiIjkuekQchhcpswkJxJNC2hmEwuEb4hFLphh1Xmxc545XO+mGCrbAlgSYJ9w1qp3ltQyuXqF91pVw==")
print(client.get_vault_types())

Вот. что приш­ло в ответ:

{'items':
[
{
'id': '685cfa5a3d0ba75d2f041972',
'name': 'Пользовательские сейфы',
'code': 'privateShared',
'isBuiltIn': True,
'creatorAccess': 'admin',
'administratorIds': [],
'allUsersCanCreate': True,
'userGroupCanCreateIds': [],
'userCanCreateIds': [],
'userRoleCanCreateIds': [],
'administrators': [],
'administratorsCount': 0,
'usersAllowedToCreate': None,
'creatorAccessName': 'Администрирование',
'isUsed': True
},
{
'id': '685cfa5a3d0ba75d2f041973',
'name': 'Корпоративные сейфы',
'code': 'company',
'isBuiltIn': True,
'creatorAccess': 'admin',
'administratorIds': ['68598c0a132196f6470ed522'],
'allUsersCanCreate': True,
'userGroupCanCreateIds': [],
'userCanCreateIds': [],
'userRoleCanCreateIds': [],
'administrators': [
{
'id': '68598c0a132196f6470ed522',
'login': 'admin',
'fullName': 'admin',
'hasAvatar': False,
'isDeleted': False
}
],
'administratorsCount': 1,
'usersAllowedToCreate': None,
'creatorAccessName': 'Администрирование',
'isUsed': False
}
],
'totalCount': 2
}

Те­перь не сос­тавит проб­лем, под­ста­вить в код нуж­ный vault_id и получить пол­ноцен­ный скрипт добав­ления сек­рета в Пас­сворк.

from passwork_client import PassworkClient
client = PassworkClient(host="https://ruxakep.passwork-demo.space/")
client.set_tokens("1KqoGku9GYYYlsxj3BcLAvUqxa5ej/9M50/akAUuRvU=", "mXjYIaJUSTCzFa+RwHowNbguv2TF3OofnW7q8Hbb9AU=")
client.set_master_key("vznRsji3NiIjkuekQchhcpswkJxJNC2hmEwuEb4hFLphh1Xmxc545XO+mGCrbAlgSYJ9w1qp3ltQyuXqF91pVw==")
vault_types = client.get_vault_types()
private_shared = next(
(vt for vt in vault_types['items'] if vt['code'] == 'privateShared'),
None
)
if not private_shared:
raise ValueError("Vault type with code 'privateShared' not found")
print(private_shared['id'])
vault_id = client.create_vault(vault_name="Cool Vault", type_id=private_shared['id'])
Успешно созданный сейф
Ус­пешно соз­данный сейф

Те­перь у нас есть пол­ноцен­ный механизм для ана­лиза API Пас­сворк. При­чем, боль­шая часть кода хорошо про­ком­менти­рова­на, а методы наз­ваны инту­итив­но понят­но.

Описание кода в комментариях
Опи­сание кода в ком­мента­риях

До­бавим в сейф новый пароль. В докумен­тации есть при­мер объ­екта для соз­дания пароля:

password = {
"name": "Service Name",
"login": "username",
"password": "secure-password",
"vaultId": vault_id,
"folderId": folder_id,
"description": "Описание",
"url": "https://service-url.com",
"tags": ["tag1", "tag2"],
"customs": [
{
"name": "Дополнительный логин",
"value": "second-username",
"type": "text"
},
{
"name": "Код восстановления",
"value": "recovery-code-value",
"type": "password"
},
{
"name": "TOTP",
"value": "JBSWY3DPEHPK3PXP",
"type": "totp"
}
],
"attachments": [
{
"path": "path/to/file.png",
"name": "file.png"
}
]
}
password_id = client.create_password(password)

Из JSON понят­но, что пароль пред­став­ляет собой серь­езную струк­туру с боль­шим количес­твом дан­ных. Сло­во «пароль» здесь не очень под­ходит, гораз­до удоб­нее под­ходит «сек­рет». Нап­ример, что меша­ет заг­рузить ключ дос­тупа по SSH или TLS-сер­тификат? Заг­рузка фай­лов есть, соз­дание кас­томных полей под­держи­вает­ся. В сек­рет мож­но положить поч­ти любые дан­ные, которые не сто­ит хра­нить на сер­вере.

Соз­дадим минималь­ный сек­рет, ука­зав толь­ко обя­затель­ные дан­ные:

password_data = {
"name": "Super Secret",
"vaultId": vault_id,
"password": "secure-password",
}
password_id = client.create_item(password_data)
Пароль успешно добавлен
Па­роль успешно добав­лен

Что­бы получить пароль, исполь­зуй:

secret = client.get_item(password_id)

Те­перь у нас в арсе­нале все, что нуж­но для написа­ния мощ­ных скрип­тов и интегра­ции Пас­сворк в CI/CD.

 

Идеи для DevOps

В ре­пози­тории Пас­свор­ка лежит мно­го хороших при­меров скрип­тов. На их осно­ве лег­ко накидать ротатор паролей или какой‑то дру­гой полез­ный про­ект. Но скрипт‑ротатор — шту­ка заез­женная, и мне даже стыд­но его упо­минать. Думаю, будет куда инте­рес­нее отправ­лять уве­дом­ления Пас­сворк в Telegram. Так ты будешь знать о всех событи­ях в тво­ем Пас­свор­ке.

В биб­лиоте­ке Пас­свор­ка я не нашел под­ходящей фун­кции для нотифи­каций. При­дет­ся исполь­зовать метод call, который выпол­няет зап­рос к ука­зан­ному эндпо­инту. Это поможет прой­ти все про­цес­сы шиф­рования и дешиф­рования. Можешь юзать и requests, но тог­да при­дет­ся написать мно­го лиш­него кода.

Что­бы най­ти эндпо­инт, я запус­тил прок­сирова­ние тра­фика через Burp. Ока­залось, что это /api/v1/notifications.

Ал­горитм работы скрип­та:

  1. По­лучить все уве­дом­ления из Пас­свор­ка.
  2. Срав­нить ID уве­дом­лений с теми, которые уже отправ­лены в телегу.
  3. Ес­ли есть новый, отправ­ляем уве­дом­ление.
  4. До­бав­ляем ID в спи­сок отправ­ленных и сох­раня­ем в файл.

Соз­дай бота, который будет нашим информа­тором. Затем соз­дай файл passwork-notify.py.

Им­порты:

import json
import sys
import asyncio
from datetime import datetime
from passwork_client import PassworkClient
from telegram import Bot

Блок кон­стант для работы с Пас­свор­ком и ботом телеги:

ACCESS_TOKEN = "..."
REFRESH_TOKEN = "..."
MASTER_KEY = "..."
HOST = "https://ruxakep.passwork-demo.space/"
TELEGRAM_TOKEN = "..."
TELEGRAM_CHAT_ID = "..."
KNOWN_IDS_FILE = "known_notification_ids.json"

Соз­дай кли­ентов:

passwork = PassworkClient(HOST)
passwork.set_tokens(ACCESS_TOKEN, REFRESH_TOKEN)
passwork.set_master_key(MASTER_KEY)
bot = Bot(token=TELEGRAM_TOKEN)

Те­бе пот­ребу­ется нес­коль­ко сер­висных фун­кций, что­бы код выг­лядел кра­сиво и был под­держи­ваемым:

# Загрузка JSON с уже известными ID уведомлений
def load_known_ids():
try:
with open(KNOWN_IDS_FILE, encoding="utf-8") as f:
return set(json.load(f))
except (FileNotFoundError, json.JSONDecodeError):
return set()
# Сохранение обновленного списка с уведомлениями
def save_known_ids(ids_set):
with open(KNOWN_IDS_FILE, "w", encoding="utf-8") as f:
json.dump(list(ids_set), f, ensure_ascii=False)
# Сервисная функция отправки сообщений
async def send_notification(chat_id, message):
await bot.send_message(
chat_id=chat_id,
text=message
)

Но все осталь­ное, как пач­ку спа­гет­ти, закинул в одну фун­кцию:

async def main():
known = load_known_ids()
updated = known.copy()
try:
# Здесь будет магия
except Exception as e:
print(f"Ошибка: {e}", file=sys.stderr)
sys.exit(1)

Ког­да кар­кас фун­кции готов, накинь мяса в виде вызова метода call:

raw = passwork.call("GET", "/api/v1/notifications")
if not raw or "items" not in raw:
print("Нет items в ответе", file=sys.stderr)
return

Ес­ли ите­мов нет, выходим из фун­кции и завер­шаем работу скрип­та. Если ите­мы есть, запус­каем скуч­ный цикл. Задача цик­ла — отсе­ить уве­дом­ления уже прос­мотрен­ные и отправ­ленные в бот. Осталь­ные шлем, добав­ляем в спи­сок отправ­ленных и сох­раня­ем в файл:

sent = 0
for item in raw["items"]:
nid = item.get("id")
if not nid or nid in known:
continue
# Избавься от этого if, if тебе нужны все уведомления
if item.get("isViewed", False):
updated.add(nid)
continue
# Формируем простое сообщение
text = item.get("text", "")
placeholders = item.get("placeholders", {})
for k, v in placeholders.items():
text = text.replace(f"{{{k}}}", str(v))
actor = item.get("creator", {}).get("fullName", "")
event = item.get("activityLogEvent", "")
ts = item.get("createdAt")
time_str = "" if not ts else f" ({datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')})"
message = f"Новое уведомление\nID: {nid}\nСобытие: {event}\nОт: {actor}\nТекст: {text}{time_str}"
# Вызов новой функции
await send_notification(TELEGRAM_CHAT_ID, message)
sent += 1
updated.add(nid)
# Чтобы работа скрипта не была совсем скучной
if sent > 0:
print(f"Отправлено {sent} новых уведомлений")
save_known_ids(updated)
else:
print("Новых непрочитанных уведомлений нет")
Результат работы скрипта уведомлений
Ре­зуль­тат работы скрип­та уве­дом­лений

Про­пиши скрипт в cron, уста­нови адек­ватный тай­минг для запус­ка и радуй­ся пол­ному кон­тро­лю над Пас­свор­ком!

Не инте­ресу­ют все уве­дом­ления, а толь­ко изме­нения? Пас­сворк регис­три­рует всю исто­рию изме­нений паролей. В скрип­тах, можешь получить информа­цию о кон­крет­ном изме­нении легитим­ным методом кли­ента:

snapshot = passwork.get_snapshot(ITEM_ID, SNAPSHOT_ID)

Но проб­лема в том, что тебе нуж­но знать кон­крет­ный иден­тифика­тор пароля и снэп­шота. Фун­кция удоб­на, что­бы отпра­вить тебе в сооб­щении кон­крет­ное изме­нение, которое было выпол­нено. А вот что­бы получить спи­сок снэп­шотов, при­дет­ся исполь­зовать метод call и покопать­ся в зап­росах с помощью Burp.

По­лучить спи­сок снэп­шотов по паролю, можешь через эндпо­инт /api/v1/items/<ITEM_ID>/snapshots.

Получение снэпшотов запросом
По­луче­ние снэп­шотов зап­росом

Ите­мы получишь из /api/v1/items?vaultId=<VAULT_ID>. Цепоч­ка поч­ти зам­кну­лась. Оста­лось получить спи­сок сей­фов и цик­лом обой­ти их.

Для получе­ния спис­ка сей­фов, исполь­зуй эндпо­инт с такими парамет­рами:

/api/v1/vaults?includeAccessInfo=true&includeFoldersCount=true&includeIsPrivate=true&includePermissions=true

Этот зап­рос я вытащил из Burp. Он удо­бен: не нуж­но переби­рать типы сей­фов, если твоя задача это­го не тре­бует.

Ито­говый цикл выг­лядит при­мер­но так:

# ... прочий код ...
vaults_raw = passwork.call("GET", "/api/v1/vaults", payload={
"includeAccessInfo": "true",
"includeFoldersCount": "true",
"includeIsPrivate": "true",
"includePermissions": "true"
})
vaults = vaults_raw.get("items", []) if isinstance(vaults_raw, dict) else vaults_raw
for vault in vaults:
vault_id = vault.get("id")
items_raw = passwork.call("GET", f"/api/v1/items", payload={
"vaultId":vault_id
})
items = items_raw.get("items", []) if isinstance(items_raw, dict) else items_raw
for item in items:
snaps_raw = passwork.call("GET", f"/api/v1/items/{item_id}/snapshots")
# ... код обработки снапшотов ...

По ана­логии с пре­дыду­щим при­мером ты лег­ко допишешь код что­бы всег­да знать о появ­лении новых снэп­шотов.

 

CLI

Каж­дый раз писать скрипт, что­бы про­тес­тировать тот или иной метод API, неудоб­но. Для этих целей есть ути­лита passwork-cli. Она пред­назна­чена для задач DevOps при авто­мати­зации CI/CD. Но и для зна­комс­тва со струк­турой API под­ходит хорошо.

Ког­да ты ста­вил пакет passwork-python, CLI тоже уста­нови­лась. Но в докумен­тации Пас­свор­ка пред­лага­ют ста­вить из репози­тория Git Verse:

pip install git+ssh://git@gitverse.ru:2222/passwork-ru/passwork-python.git

Или через HTTPS:

pip install git+https://gitverse.ru/passwork-ru/passwork-python.git

info

В Windows, не забудь про­писать путь к passwork-cli. Путь к тул­зе узна­ешь коман­дой: pip show passwork-python.

Ско­рее все­го, в PyPL и в Git Verse вер­сии выкаты­вают­ся одновре­мен­но. Я раз­ницы не заметил и каких‑то сооб­щений по это­му поводу не нашел.

Эк­спор­тируй в перемен­ные хост и токены. Это нуж­но, что­бы ты не вво­дил каж­дый раз их при запус­ке passwork-cli:

export PASSWORK_HOST="https://ruxakep.passwork-demo.space/"
export PASSWORK_TOKEN="..."
export PASSWORK_MASTER_KEY="..."

В Windows:

$env:PASSWORK_HOST="https://ruxakep.passwork-demo.space/"
$env:PASSWORK_TOKEN="..."
$env:PASSWORK_MASTER_KEY="..."

Ес­ли не нра­вит­ся хра­нение дан­ных в окру­жении или у тебя спе­цифи­чес­кая авто­мати­зация, ука­зывай зна­чения при запус­ке:

passwork-cli api --host <HOST> --token <TOKEN> --refresh-token <REFRESH_TOKEN> --master-key <MASTER_KEY> ...другие параметры...

Най­ди в исходни­ках мар­шрут вро­де /api/v1/users. Для кли­ента исполь­зуй мар­шрут без /api/:

passwork-cli api --method GET --endpoint "v1/users"
Результат работы клиента
Ре­зуль­тат работы кли­ента

Иног­да нуж­но добавить парамет­ры. Исполь­зуй опцию --params и опи­сание парамет­ров в JSON. Нап­ример, мож­но получить все пароли для опре­делен­ного вида сей­фов:

passwork-cli api --method GET --endpoint "v1/items/search" --params '{"vaultIds":["69aa963c1195f2c8420a4b52"]}'

Кро­ме режима api, у passwork-cli есть еще режимы: get, update и exec. Пос­ледний — режим работы наибо­лее инте­рес­ный. В нем Пас­сворк при­нима­ет иден­тифика­тор пароля (или нес­коль­ко иден­тифика­торов через запятую) и коман­ду для запус­ка в сис­теме. Сна­чала тул­за вытащит ука­зан­ные пароли и выг­рузит их в окру­жение, а затем запус­тит коман­ду.

Рас­паковать пароли и вывес­ти перемен­ные окру­жения:

passwork-cli exec --password-id "..." printenv

В окру­жении, перемен­ные будут называть­ся так, как пароль называ­ется в Пас­свор­ке. Если пароль наз­ван SECRET_LOGIN_ADMIN_DATABASE, пос­ле работы тул­зы в окру­жении появит­ся перемен­ная SECRET_LOGIN_ADMIN_DATABASE. В зна­чение перемен­ной помеща­ется пароль! В режиме exec Пас­сворк не уви­дит дру­гих зна­чений, кро­ме наз­вания и зна­чения поля password.

По­лучить нес­коль­ко перемен­ных под­ряд можешь не толь­ко перечис­лив их, но и ука­зав --folder или --tag. Дирек­тории и теги тоже мож­но перечис­лять через запятую.

 

Сокращаем поверхность атаки

Что­бы поп­ракти­ковать­ся, давай уста­новим Broken Crystals. Это спе­циали­зиро­ван­ное уяз­вимое веб‑при­ложе­ние для обу­чения и про­вер­ки инс­тру­мен­тов пен­теста. Нам инте­рес­на уяз­вимость Local File Inclusion.

Ус­танов­ка и запуск:

git clone https://github.com/NeuraLegion/brokencrystals
docker compose --file=compose.local.yml up -d

Ха­кер без проб­лем может получить сек­реты из .env. Веб‑при­ложе­ние уяз­вимо к Local File Inclusion по эндпо­инту http://localhost:3000/api/file/raw?path=.

Поп­робуй такой зап­рос:

curl.exe "http://localhost:3000/api/file/raw?path=.env"

В ответ при­летит файл с кучей дан­ных. Нап­ример: DATABASE_PASSWORD, JWT_SECRET_KEY, KEYCLOAK_ADMIN_CLIENT_SECRET, KEYCLOAK_PUBLIC_CLIENT_SECRET и так далее. Непоря­док! С такими дан­ными хакер име­ет прак­тичес­ки пол­ный кон­троль.

По­высить секь­юрность мож­но раз­ными спо­соба­ми, но мы будем делать это в рам­ках Пас­свор­ка. В качес­тве при­мера будет база дан­ных, осталь­ные сек­реты можешь спря­тать по ана­логии. Сек­ция базы в кон­фиге выг­лядит так:

services:
db:
image: 'postgres:17-alpine'
restart: always
healthcheck:
interval: 10s
retries: 10
test: ['CMD-SHELL', 'pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}']
timeout: 45s
environment:
POSTGRES_DB: ${DATABASE_SCHEMA}
POSTGRES_USER: ${DATABASE_USER}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
ports:
- '5432:5432'
volumes:
- './pg.sql:/docker-entrypoint-initdb.d/pg.sql'

От­редак­тируй файл .env, уда­ли из него DATABASE_SCHEMA, DATABASE_USER и DATABASE_PASSWORD. Эти дан­ные перене­си в Пас­сворк. Соз­дай сейф. В сей­фе соз­дай пап­ку, нап­ример, bc. В пап­ке соз­дай три сек­рета. В наз­вание помес­ти имя перемен­ной, зна­чение помес­ти в пароль.

Папка с паролями в сейфе
Пап­ка с пароля­ми в сей­фе

Убе­дись, что дан­ные для под­клю­чения к API Пас­сворк есть в перемен­ных окру­жения, потом выпол­ни:

passwork-cli exec --folder-id "69adfb16a7750e0b940be8f4" sh -c 'docker compose -f compose.local.yml up -d'

Пос­ле запус­ка, убе­дись, что кон­тей­нер с базой под­нялся:

docker inspect --format='{{.State.Health.Status}}' brokencrystals-db-1

Про­верь, что база дан­ных дос­тупна:

psql -h localhost -U bc -d bc -c "SELECT 1;"
Сервис четко запустился
Сер­вис чет­ко запус­тился
 

Выводы

Пас­сворк — это один из инс­тру­мен­тов, при помощи которых ты можешь повысить не толь­ко безопас­ность, но и ком­форт. Пароли надеж­но защище­ны и мак­сималь­но уда­лены от ата­кующе­го. А широкие воз­можнос­ти API поз­воля­ют бес­конеч­но совер­шенс­тво­вать свои инс­тру­мен­ты управле­ния.

В статье мы сде­лали все­го лишь опо­веще­ния, но нич­то не меша­ет сде­лать пол­ноцен­ную панель управле­ния, через которую в один клик мож­но будет поменять все пароли, пре­дос­тавить или заб­рать дос­туп.

Еще ты можешь при­нуди­тель­но поменять пароли тем, у кого они слиш­ком сла­бые для его уров­ня дос­тупа. Пос­мотри инте­рес­ный эндпо­инт /api/v1/items/security-analysis. К нему нуж­но два обра­щения: пер­вым запус­каешь про­вер­ку, через вре­мя этим же зап­росом уви­дишь у кого сла­бые пароли. Все что тебе нуж­но, в зависи­мос­ти от ско­рин­га запус­кать регене­рацию пароля.

На­деюсь матери­ал был полез­ным для тебя и ты обре­тешь еще один кру­той инс­тру­мент для сво­ей ком­пании.

Erid: Реклама. ООО «Пассворк». ИНН 2901311774. Erid: 2SDnjdeaXkW

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии