Перейти к содержимому

7. Secrets и безопасность

Иллюстрация к уроку

Secrets management — систематический подход к хранению, ротации и контролю доступа к чувствительным данным: API ключам, паролям, сертификатам.

Секреты — это данные, которые:
✅ Нельзя коммитить в git
✅ Нельзя логировать
✅ Нужно ротировать
✅ Доступ должен быть ограничен
Примеры:
- Пароли к базам данных
- API ключи (Stripe, SendGrid, AWS)
- JWT секреты
- SSL сертификаты и приватные ключи
- OAuth client secrets
- SSH ключи

Главное правило: git никогда не видит секреты

Заголовок раздела «Главное правило: git никогда не видит секреты»
Окно терминала
# ❌ НИКОГДА так
git add .env
git commit -m "add env file" # Всё, утекло навсегда
# Даже если удалишь потом — история git хранит всё
git rm .env # Файл удалён, но был в коммите
# git log --all -p -- .env # Любой может достать

Если секрет попал в git:

  1. Немедленно ротируй (создай новый)
  2. Считай старый скомпрометированным
  3. Используй git filter-repo для очистки истории
  4. Force push — крайний случай

Самый простой вариант для GitHub проектов:

# Settings → Secrets and variables → Actions
# Repository secrets, Environment secrets, Organization secrets
# Использование в workflow
jobs:
deploy:
steps:
- name: Deploy
env:
STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: npm run deploy
# Secrets в actions (без явного env)
- uses: some/action@v1
with:
token: ${{ secrets.GITHUB_TOKEN }} # встроенный secret

Особенности GitHub Secrets:

  • Автоматически маскируются в логах
  • Нельзя прочитать после сохранения
  • Organization level — для всех репозиториев организации
  • Environment secrets — отдельные для staging/production
/home/deploy/myapp/.env.production
# На сервере (не в git!)
# Создание с правильными правами
touch .env.production
chmod 600 .env.production # только владелец читает/пишет
chown deploy:deploy .env.production
# Редактирование
nano .env.production
# Проверка прав
ls -la .env.production
# -rw------- 1 deploy deploy 512 Mar 8 01:30 .env.production
Окно терминала
# Установка
curl -fsSL https://apt.releases.hashicorp.com/gpg | gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/hashicorp.list
apt update && apt install vault
# Запись секрета
vault kv put secret/myapp/production \
database_url="postgresql://..." \
jwt_secret="supersecret"
# Чтение
vault kv get -field=database_url secret/myapp/production
# Использование в приложении
import vault from 'node-vault';
const client = vault({ endpoint: 'http://vault:8200' });
await client.userpassLogin({ username: 'myapp', password: process.env.VAULT_PASSWORD });
const { data } = await client.read('secret/data/myapp/production');
const DATABASE_URL = data.data.database_url;
import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';
const client = new SecretsManagerClient({ region: 'eu-west-1' });
async function getSecret(secretName) {
const command = new GetSecretValueCommand({ SecretId: secretName });
const response = await client.send(command);
return JSON.parse(response.SecretString);
}
// Использование
const secrets = await getSecret('myapp/production');
const db = createPool({ connectionString: secrets.DATABASE_URL });
Окно терминала
# Создание секрета через AWS CLI
aws secretsmanager create-secret \
--name "myapp/production" \
--secret-string '{"DATABASE_URL":"postgresql://...","JWT_SECRET":"..."}'
# Обновление
aws secretsmanager put-secret-value \
--secret-id "myapp/production" \
--secret-string '{"DATABASE_URL":"postgresql://...new..."}'
Окно терминала
# Установка
brew install dopplerhq/cli/doppler # macOS
# или
curl -Ls https://cli.doppler.com/install.sh | sh # Linux
# Логин
doppler login
# Создание проекта
doppler setup
# Добавление секретов
doppler secrets set DATABASE_URL="postgresql://..."
doppler secrets set JWT_SECRET="supersecret"
# Запуск с секретами
doppler run -- node server.js
doppler run -- npm start
# В GitHub Actions
- name: Fetch secrets from Doppler
uses: dopplerhq/secrets-fetch-action@v1
id: doppler
with:
doppler-token: ${{ secrets.DOPPLER_TOKEN }}
- name: Use secret
run: echo "DB URL: ${{ steps.doppler.outputs.DATABASE_URL }}"
Окно терминала
# git-secrets — проверка перед коммитом
brew install git-secrets
git secrets --install # в репозитории
git secrets --register-aws
git secrets --scan
# truffleHog — поиск секретов в истории
pip install trufflehog
trufflehog git https://github.com/myorg/myrepo
# gitleaks — популярный сканер
brew install gitleaks
gitleaks detect --source . -v # проверить текущее состояние
gitleaks git -v # проверить всю историю
.github/workflows/security.yml
name: Security Scan
on: [push, pull_request]
jobs:
gitleaks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
.git/hooks/pre-commit
#!/bin/bash
# Проверяем что .env файлы не добавлены
if git diff --cached --name-only | grep -E '^\.env(\..+)?$' | grep -v '\.example$'; then
echo "❌ ERROR: Attempting to commit .env file!"
echo "Remove it: git reset HEAD <file>"
exit 1
fi
# Проверяем на паттерны секретов
if git diff --cached | grep -E '(api_key|secret|password)\s*=\s*["\'][^"\']{8,}'; then
echo "⚠️ WARNING: Possible secret detected in commit!"
echo "Review the diff before proceeding"
exit 1
fi
echo "✅ Security checks passed"
Окно терминала
chmod +x .git/hooks/pre-commit
scripts/rotate-secret.sh
#!/bin/bash
SECRET_NAME=$1
OLD_VALUE=$(doppler secrets get $SECRET_NAME --plain)
# Генерация нового секрета
NEW_VALUE=$(openssl rand -base64 32)
echo "Rotating $SECRET_NAME..."
# Обновляем в Doppler (или Vault, или AWS SM)
doppler secrets set $SECRET_NAME="$NEW_VALUE"
# Деплоим новую конфигурацию
./scripts/deploy.sh
# Проверяем что всё работает
curl -f https://myapp.com/health || {
echo "❌ Health check failed, rolling back!"
doppler secrets set $SECRET_NAME="$OLD_VALUE"
./scripts/deploy.sh
exit 1
}
echo "✅ Secret rotated successfully"
  • Секреты никогда не попадают в git
  • .env в .gitignore, .env.example в git
  • GitHub Secrets — для CI/CD, достаточно для большинства проектов
  • Vault / AWS SM / Doppler — для серьёзных production систем
  • gitleaks — сканируй код на предмет случайно попавших секретов
  • pre-commit хуки — первая линия защиты
  • Ротируй секреты регулярно и сразу при подозрении на компрометацию

Как работает хранение секретов — vault vs .env: