← Назад к вопросам
Где лучше хранить Credentials?
2.0 Middle🔥 231 комментариев
#DevOps и инфраструктура#Безопасность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Хранение Credentials в приложениях
Credentials (пароли, токены, API ключи, секреты БД) — это критические данные, которые требуют наивысшего уровня защиты. Неправильное хранение может привести к компрометации всей системы.
Где НЕ нужно хранить Credentials
❌ Жёсткий код в исходном коде
# НИКОГДА так не делать!
DB_PASSWORD = "super_secret_123"
API_KEY = "sk_live_4eC39HqLyjWDarhtT20Oy7z"
TOKEN = "ghp_abc123xyz456"
Проблемы:
- Видно всем с доступом к репозиторию
- Попадает в историю Git
- Скомпрометировано при утечке репо
- Одно значение для всех окружений
❌ Комментарии и примеры
# Example: token = "real_token_123"
# Default password: admin/password
❌ Файлы в репозитории
config.py ← содержит passwords
secrets.json ← содержит API keys
.env ← закоммичен в Git
credentials.txt ← в исходном коде
Где нужно хранить Credentials
1. Environment Variables (Переменные окружения)
Лучший выбор для большинства приложений.
import os
from dotenv import load_dotenv
# Локально: из .env файла (НЕ коммичится в Git)
load_dotenv() # Читает из .env, которого НЕТ в репо
# В продакшене: из переменных окружения системы
db_password = os.getenv("DB_PASSWORD")
api_key = os.getenv("API_KEY")
if not db_password:
raise ValueError("DB_PASSWORD not set in environment")
.env.example — коммичится в Git (без значений):
DB_PASSWORD=
API_KEY=
SECRET_KEY=
.env — в .gitignore (содержит реальные значения):
DB_PASSWORD=production_super_secret_123
API_KEY=sk_live_real_token_here
SECRET_KEY=django_secret_123abc
2. .gitignore правила
Обязательно добавить в .gitignore:
# Credentials
.env
.env.local
.env.*.local
secrets.json
credentials.json
*.key
*.pem
# IDE
.vscode/
.idea/
# Python
__pycache__/
*.pyc
.venv/
3. Хранилище секретов (Secrets Manager)
Для крупных приложений и микросервисов.
AWS Secrets Manager
import boto3
client = boto3.client("secretsmanager", region_name="us-east-1")
try:
response = client.get_secret_value(SecretId="prod/db/password")
db_password = response["SecretString"]
except Exception as e:
print(f"Error retrieving secret: {e}")
HashiCorp Vault
import hvac
client = hvac.Client(url="https://vault.example.com:8200")
client.auth.approle.login(role_id="...", secret_id="...")
secret = client.secrets.kv.v2.read_secret_version(
path="prod/database"
)
db_password = secret["data"]["data"]["password"]
Google Secret Manager
from google.cloud import secretmanager
client = secretmanager.SecretManagerServiceClient()
name = f"projects/my-project/secrets/db-password/versions/latest"
response = client.access_secret_version(request={"name": name})
db_password = response.payload.data.decode("UTF-8")
4. Конфигурационные сервисы (для микросервисной архитектуры)
Spring Cloud Config / Consul
import requests
# Запрос конфига у централизованного сервиса
response = requests.get(
"https://config-server.company.com/api/config/database",
headers={"Authorization": "Bearer token"}
)
config = response.json()
db_password = config["password"]
5. Docker Secrets (для Swarm/Kubernetes)
Docker Swarm
# Создать secret
docker secret create db_password -
# Использовать в сервисе
docker service create --secret db_password myapp
# В контейнере
with open("/run/secrets/db_password") as f:
db_password = f.read().strip()
Kubernetes Secrets
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
stringData:
password: super_secret_123
username: postgres
import os
# K8s автоматически монтирует как env переменные
db_password = os.getenv("DB_PASSWORD")
6. Локальное хранилище ОС
macOS / Linux — использование keyring
import keyring
# Сохранить в системное хранилище
keyring.set_password("myapp", "db_password", "secret_value")
# Получить из системного хранилища
db_password = keyring.get_password("myapp", "db_password")
Windows — использование DPAPI
import keyring
# Работает автоматически на Windows через DPAPI
keyring.set_password("myapp", "api_key", "sk_live_token")
api_key = keyring.get_password("myapp", "api_key")
Лучшие практики
✅ Разные секреты для разных окружений
import os
from enum import Enum
class Environment(Enum):
DEVELOPMENT = "development"
STAGING = "staging"
PRODUCTION = "production"
env = os.getenv("ENVIRONMENT", "development")
# Загрузить специфичные для окружения секреты
if env == "production":
# Использовать AWS Secrets Manager
pass
else:
# Использовать локальный .env файл
from dotenv import load_dotenv
load_dotenv()
✅ Ротация секретов
# AWS Secrets Manager автоматически ротирует
# Приложение должно регулярно вызывать get_secret_value
# для получения свежего значения
def get_db_password():
# Не кэшируй на долгое время!
response = secretsmanager.get_secret_value(SecretId="db_password")
return response["SecretString"]
✅ Минимальные права доступа
# IAM политика — только необходимые секреты
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:*:*:secret:db_password"
}
]
}
✅ Логирование без раскрытия секретов
def connect_to_database(host, password):
logger.info(f"Connecting to {host}") # OK
# logger.info(f"Password: {password}") # НИКОГДА!
logger.debug(f"DB credentials: {host}:***") # OK для debug
Сравнительная таблица
| Место хранения | Простота | Безопасность | Масштабируемость | Рекомендация |
|---|---|---|---|---|
| .env локально | ⭐⭐⭐⭐⭐ | ⭐ | ⭐ | Только разработка |
| Env переменные | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ | Production |
| AWS Secrets Manager | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | Enterprise AWS |
| Vault | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | Enterprise |
| Kubernetes Secrets | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | K8s |
| Keyring OS | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐ | Локальная разработка |
Вывод
Для большинства случаев: Environment переменные + Secrets Manager в production. Никогда не коммичь реальные креденшалы, используй .env.example как шаблон, и забудь о жёсткого кода в исходнике.