Практика ротации секретов
Зачем нужна ротация
Регулярная смена секретов снижает риски:
| Риск | Как ротация помогает |
|---|---|
| Утечка пароля | Скомпрометированный пароль быстро становится недействительным |
| Долгоживущие токены | Ограничение времени жизни уменьшает окно атаки |
| Инсайдерские угрозы | Бывшие сотрудники теряют доступ после ротации |
| Compliance-требования | PCI DSS, SOC 2 требуют регулярной смены паролей |
Принцип ротации
┌─────────────────────────────────────────────────────────────┐
│ 1. Генерация 2. Целевая система 3. Пассворк │
│ нового пароля (обновление) (сохранение) │
│ │
│ openssl rand ──► ALTER ROLE ... ──────► passwork-cli update│
└─────────────────────────────────────────────────────────────┘
Важно: порядок действий
Сначала обновите пароль в целевой системе (БД, сервис), затем в Пассворке. Иначе возникнет рассинхрон: Пассворк содержит новый пароль, а система ещё использует старый.
Ротация через CLI
PostgreSQL
#!/bin/bash
set -e
ITEM_ID="<item-id>"
DB_ROLE="app_user"
# 1. Генерируем новый пароль
NEW_PASS=$(openssl rand -base64 32)
# 2. Обновляем в PostgreSQL
psql -h db.example.com -U admin -d postgres -c \
"ALTER ROLE ${DB_ROLE} WITH PASSWORD '${NEW_PASS}';"
# 3. Сохраняем в Пассворк
passwork-cli update --password-id "${ITEM_ID}" --password "${NEW_PASS}"
echo "Password rotated for ${DB_ROLE}"
MySQL
#!/bin/bash
set -e
ITEM_ID="<item-id>"
DB_USER="app"
NEW_PASS=$(openssl rand -base64 32)
mysql -h db.example.com -u root -p"${MYSQL_ROOT_PASSWORD}" -e \
"ALTER USER '${DB_USER}'@'%' IDENTIFIED BY '${NEW_PASS}';"
passwork-cli update --password-id "${ITEM_ID}" --password "${NEW_PASS}"
echo "Password rotated for ${DB_USER}"
API-ключ
#!/bin/bash
set -e
ITEM_ID="<item-id>"
# 1. Запрашиваем новый ключ у внешнего сервиса
NEW_KEY=$(curl -s -X POST https://api.service.com/keys/rotate \
-H "Authorization: Bearer ${OLD_KEY}" | jq -r '.new_key')
# 2. Сохраняем в Пассворк
passwork-cli update --password-id "${ITEM_ID}" --password "${NEW_KEY}"
echo "API key rotated"
Ротация через Python SDK
Полный пример с обработкой ошибок:
#!/usr/bin/env python3
"""Скрипт ротации пароля PostgreSQL."""
import os
import secrets
import sys
import psycopg2
from passwork import Client
def rotate_password(item_id: str, db_role: str) -> bool:
"""
Ротация пароля для роли PostgreSQL.
Returns:
True при успехе, False при ошибке.
"""
# Инициализация
client = Client(
url=os.environ["PASSWORK_HOST"],
token=os.environ["PASSWORK_TOKEN"],
)
# Получаем admin credentials из Пассворка
admin_item = client.get_password(
item_id=os.environ["DB_ADMIN_ITEM_ID"]
)
# Генерируем новый пароль
new_password = secrets.token_urlsafe(32)
try:
# Подключаемся к PostgreSQL
conn = psycopg2.connect(
host=admin_item.fields["DB_HOST"],
dbname="postgres",
user=admin_item.login,
password=admin_item.password,
)
conn.autocommit = True
# Обновляем пароль в БД
with conn.cursor() as cur:
cur.execute(
"ALTER ROLE %s WITH PASSWORD %s",
(db_role, new_password)
)
conn.close()
# Сохраняем в Пассворк
item = client.get_password(item_id=item_id)
item.password = new_password
client.update_password(item)
print(f"Password rotated for {db_role}")
return True
except psycopg2.Error as e:
print(f"Database error: {e}", file=sys.stderr)
return False
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
return False
if __name__ == "__main__":
success = rotate_password(
item_id=os.environ["TARGET_ITEM_ID"],
db_role=os.environ["DB_ROLE"],
)
sys.exit(0 if success else 1)