# Безопасность LogBoard+

**Автор:** Сергей Антропов  
**Сайт:** https://devops.org.ru

## Содержание

1. [Обзор безопасности](#обзор-безопасности)
2. [Генерация ключей](#генерация-ключей)
3. [Аутентификация](#аутентификация)
4. [Настройка HTTPS](#настройка-https)
5. [Доступ к Docker](#доступ-к-docker)
6. [Сетевая безопасность](#сетевая-безопасность)
7. [Мониторинг безопасности](#мониторинг-безопасности)
8. [Рекомендации для продакшена](#рекомендации-для-продакшена)

## Обзор безопасности

LogBoard+ включает в себя несколько уровней безопасности для защиты доступа к логам и системной информации. Правильная настройка безопасности критически важна для продакшена.

### Уровни безопасности

1. **Аутентификация** - JWT токены для доступа к API
2. **Шифрование** - Защита чувствительных данных
3. **Сетевая безопасность** - HTTPS, файрвол, ограничение доступа
4. **Docker безопасность** - Ограничение прав доступа к Docker socket
5. **Мониторинг** - Логирование событий безопасности

## Генерация ключей

### SECRET_KEY

SECRET_KEY используется для подписи JWT токенов. Это критически важный ключ для безопасности аутентификации.

#### Генерация SECRET_KEY

**Метод 1: OpenSSL (рекомендуется)**

```bash
# Генерация 32-байтового ключа в hex формате
openssl rand -hex 32
# Пример вывода: 8a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6

# Генерация 64-байтового ключа (для максимальной безопасности)
openssl rand -hex 64
# Пример вывода: 8a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6...
```

**Метод 2: Python**

```bash
# Использование Python для генерации
python3 -c "import secrets; print(secrets.token_hex(32))"
# Пример вывода: 8a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6

# Генерация через Python скрипт
python3 -c "
import secrets
import base64
key = secrets.token_bytes(32)
print('Hex:', key.hex())
print('Base64:', base64.b64encode(key).decode())
"
```

**Метод 3: Node.js**

```bash
# Использование Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# Пример вывода: 8a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6
```

#### Требования к SECRET_KEY

- **Длина:** Минимум 32 байта (64 символа в hex)
- **Энтропия:** Используйте криптографически стойкий генератор случайных чисел
- **Уникальность:** Каждая установка должна иметь уникальный ключ
- **Хранение:** Храните в безопасном месте, не в коде

### ENCRYPTION_KEY

ENCRYPTION_KEY используется для шифрования чувствительных данных в приложении.

#### Генерация ENCRYPTION_KEY

**Метод 1: OpenSSL (рекомендуется)**

```bash
# Генерация 32-байтового ключа шифрования
openssl rand -hex 32
# Пример вывода: 1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t1u2v3w4x5y6z7

# Генерация ключа для AES-256
openssl rand -base64 32
# Пример вывода: 1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t1u2v3w4x5y6z7
```

**Метод 2: Python с Fernet**

```bash
# Генерация ключа для Fernet (Base64)
python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
# Пример вывода: 1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t1u2v3w4x5y6z7

# Генерация через Python скрипт
python3 -c "
import secrets
import base64
key = secrets.token_bytes(32)
print('Hex:', key.hex())
print('Base64:', base64.b64encode(key).decode())
print('Fernet:', base64.urlsafe_b64encode(key).decode())
"
```

**Метод 3: Скрипт генерации ключей**

Создайте файл `generate_keys.sh`:

```bash
#!/bin/bash
# Скрипт генерации ключей безопасности для LogBoard+
# Автор: Сергей Антропов
# Сайт: https://devops.org.ru

echo "=== Генерация ключей безопасности для LogBoard+ ==="
echo ""

# Проверка наличия OpenSSL
if ! command -v openssl &> /dev/null; then
    echo "❌ OpenSSL не найден. Установите OpenSSL для генерации ключей."
    exit 1
fi

echo "🔐 Генерация SECRET_KEY..."
SECRET_KEY=$(openssl rand -hex 32)
echo "SECRET_KEY=$SECRET_KEY"
echo ""

echo "🔐 Генерация ENCRYPTION_KEY..."
ENCRYPTION_KEY=$(openssl rand -hex 32)
echo "ENCRYPTION_KEY=$ENCRYPTION_KEY"
echo ""

echo "🔐 Генерация пароля пользователя..."
USER_PASSWORD=$(openssl rand -base64 16 | tr -d "=+/" | cut -c1-16)
echo "LOGBOARD_PASS=$USER_PASSWORD"
echo ""

echo "📝 Обновление .env файла..."
if [ -f .env ]; then
    # Создание резервной копии
    cp .env .env.backup.$(date +%Y%m%d_%H%M%S)
    echo "✅ Создана резервная копия .env"
    
    # Обновление ключей
    sed -i "s/^SECRET_KEY=.*/SECRET_KEY=$SECRET_KEY/" .env
    sed -i "s/^ENCRYPTION_KEY=.*/ENCRYPTION_KEY=$ENCRYPTION_KEY/" .env
    sed -i "s/^LOGBOARD_PASS=.*/LOGBOARD_PASS=$USER_PASSWORD/" .env
    
    echo "✅ Ключи обновлены в .env"
else
    echo "⚠️  Файл .env не найден. Создайте его из env.example"
fi

echo ""
echo "=== Рекомендации по безопасности ==="
echo "1. Сохраните ключи в безопасном месте"
echo "2. Не передавайте ключи через незащищенные каналы"
echo "3. Регулярно обновляйте ключи"
echo "4. Используйте разные ключи для разных окружений"
echo ""
echo "✅ Генерация ключей завершена!"
```

```bash
# Установка прав на выполнение
chmod +x generate_keys.sh

# Запуск генерации
./generate_keys.sh
```

#### Требования к ENCRYPTION_KEY

- **Длина:** 32 байта для AES-256
- **Формат:** Hex или Base64
- **Энтропия:** Криптографически стойкий генератор
- **Уникальность:** Уникальный для каждой установки

### Проверка качества ключей

```bash
# Проверка энтропии ключа
python3 -c "
import secrets
import base64

def check_entropy(key_hex):
    # Преобразование hex в байты
    key_bytes = bytes.fromhex(key_hex)
    
    # Подсчет уникальных байтов
    unique_bytes = len(set(key_bytes))
    total_bytes = len(key_bytes)
    
    # Вычисление энтропии
    entropy = unique_bytes / total_bytes
    
    print(f'Длина ключа: {total_bytes} байт')
    print(f'Уникальных байтов: {unique_bytes}')
    print(f'Энтропия: {entropy:.2%}')
    
    if entropy > 0.8:
        print('✅ Ключ имеет хорошую энтропию')
    else:
        print('⚠️  Ключ может иметь низкую энтропию')

# Проверка вашего ключа
key = '8a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6'
check_entropy(key)
"
```

## Аутентификация

### JWT токены

LogBoard+ использует JWT (JSON Web Tokens) для аутентификации.

#### Структура JWT токена

```json
{
  "header": {
    "alg": "HS256",
    "typ": "JWT"
  },
  "payload": {
    "sub": "admin",
    "exp": 1642234567,
    "iat": 1642230967
  },
  "signature": "HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), SECRET_KEY)"
}
```

#### Настройка JWT

```bash
# В .env файле
SECRET_KEY=your-secret-key-here
SESSION_TIMEOUT=3600  # Время жизни токена в секундах
```

#### Безопасность JWT

1. **Используйте сильный SECRET_KEY**
2. **Установите разумное время жизни токена**
3. **Используйте HTTPS для передачи токенов**
4. **Регулярно обновляйте токены**

### Пароли пользователей

#### Генерация безопасного пароля

```bash
# Генерация пароля с OpenSSL
openssl rand -base64 16 | tr -d "=+/" | cut -c1-16
# Пример вывода: aB3cD4eF5gH6iJ7k

# Генерация пароля с Python
python3 -c "
import secrets
import string

def generate_password(length=16):
    alphabet = string.ascii_letters + string.digits + '!@#$%^&*'
    return ''.join(secrets.choice(alphabet) for _ in range(length))

print('Пароль:', generate_password(16))
"

# Генерация пароля с pwgen
pwgen -s 16 1
```

#### Требования к паролям

- **Длина:** Минимум 12 символов
- **Сложность:** Буквы, цифры, специальные символы
- **Уникальность:** Не используйте пароли по умолчанию
- **Хранение:** Храните в безопасном месте

## Настройка HTTPS

### Самоподписанные сертификаты (для тестирования)

```bash
# Генерация приватного ключа
openssl genrsa -out private.key 2048

# Генерация сертификата
openssl req -x509 -new -nodes -key private.key -sha256 -days 365 -out certificate.crt

# Или одной командой
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout private.key -out certificate.crt \
  -subj "/C=RU/ST=Moscow/L=Moscow/O=Company/CN=localhost"
```

### Let's Encrypt сертификаты (для продакшена)

```bash
# Установка certbot
sudo apt install certbot python3-certbot-nginx

# Получение сертификата
sudo certbot --nginx -d your-domain.com

# Автоматическое обновление
sudo crontab -e
# Добавить строку:
# 0 12 * * * /usr/bin/certbot renew --quiet
```

### Nginx конфигурация с HTTPS

```nginx
server {
    listen 80;
    server_name your-domain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name your-domain.com;

    # SSL сертификаты
    ssl_certificate /path/to/certificate.crt;
    ssl_certificate_key /path/to/private.key;

    # SSL настройки
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # Безопасные заголовки
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options DENY always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    location / {
        proxy_pass http://localhost:9001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # WebSocket поддержка
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        
        # Таймауты
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}
```

## Доступ к Docker

### Ограничение прав доступа

```bash
# Создание группы docker
sudo groupadd docker

# Добавление пользователя в группу
sudo usermod -aG docker $USER

# Проверка прав
ls -la /var/run/docker.sock
# Должно быть: srw-rw-rw- 1 root docker 0 Jan 15 10:00 /var/run/docker.sock

# Перезагрузка группы
newgrp docker
```

### Альтернативные методы

#### Метод 1: Docker API с TLS

```bash
# Генерация CA ключа
openssl genrsa -aes256 -out ca-key.pem 4096

# Генерация CA сертификата
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem

# Генерация серверного ключа
openssl genrsa -out server-key.pem 4096

# Генерация серверного сертификата
openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr

# Подпись серверного сертификата
openssl x509 -req -days 365 -sha256 \
  -in server.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out server-cert.pem

# Настройка Docker daemon
sudo mkdir -p /etc/docker
sudo cp ca.pem server-cert.pem server-key.pem /etc/docker/

# Конфигурация Docker daemon
sudo tee /etc/docker/daemon.json <<EOF
{
  "tls": true,
  "tlscacert": "/etc/docker/ca.pem",
  "tlscert": "/etc/docker/server-cert.pem",
  "tlskey": "/etc/docker/server-key.pem",
  "hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"]
}
EOF

# Перезапуск Docker
sudo systemctl restart docker
```

#### Метод 2: Docker API с аутентификацией

```bash
# Создание пользователя для API
sudo useradd -r -s /bin/false docker-api

# Настройка прав
sudo usermod -aG docker docker-api

# Конфигурация в .env
DOCKER_HOST=tcp://localhost:2375
DOCKER_TLS_VERIFY=1
DOCKER_CERT_PATH=/path/to/certs
```

## Сетевая безопасность

### Настройка файрвола

```bash
# Установка UFW
sudo apt install ufw

# Базовые правила
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Разрешение SSH
sudo ufw allow ssh

# Разрешение HTTPS
sudo ufw allow 443/tcp

# Разрешение LogBoard+ только для локальной сети
sudo ufw allow from 192.168.1.0/24 to any port 9001

# Включение файрвола
sudo ufw enable

# Проверка статуса
sudo ufw status verbose
```

### iptables правила

```bash
# Очистка правил
sudo iptables -F
sudo iptables -X

# Установка политик по умолчанию
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT

# Разрешение локального трафика
sudo iptables -A INPUT -i lo -j ACCEPT

# Разрешение установленных соединений
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Разрешение SSH
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# Разрешение HTTPS
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# Разрешение LogBoard+ для локальной сети
sudo iptables -A INPUT -p tcp --dport 9001 -s 192.168.1.0/24 -j ACCEPT

# Сохранение правил
sudo iptables-save > /etc/iptables/rules.v4
```

### Настройка Docker сетей

```yaml
# В docker-compose.yml
networks:
  logboard_network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16
    driver_opts:
      com.docker.network.bridge.name: logboard_br0

services:
  logboard:
    networks:
      - logboard_network
    # Ограничение доступа к Docker socket
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
```

## Мониторинг безопасности

### Логирование событий безопасности

```bash
# Настройка логирования в .env
LOG_LEVEL=INFO
LOG_FORMAT=json

# Создание директории для логов
sudo mkdir -p /var/log/logboard
sudo chown $USER:$USER /var/log/logboard

# Настройка ротации логов
sudo tee /etc/logrotate.d/logboard <<EOF
/var/log/logboard/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 644 $USER $USER
    postrotate
        docker compose -f /path/to/logboard/docker-compose.yml restart logboard
    endscript
}
EOF
```

### Мониторинг доступа

```bash
# Скрипт мониторинга доступа
cat > monitor_access.sh <<'EOF'
#!/bin/bash
# Мониторинг доступа к LogBoard+
# Автор: Сергей Антропов

LOG_FILE="/var/log/logboard/access.log"
ALERT_FILE="/var/log/logboard/security_alerts.log"

# Функция логирования
log_alert() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$ALERT_FILE"
}

# Мониторинг неудачных попыток входа
failed_logins=$(grep -c "authentication failed" "$LOG_FILE" 2>/dev/null || echo "0")

if [ "$failed_logins" -gt 10 ]; then
    log_alert "Обнаружено $failed_logins неудачных попыток входа"
fi

# Мониторинг подозрительных IP
suspicious_ips=$(grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" "$LOG_FILE" | sort | uniq -c | awk '$1 > 100 {print $2}')

if [ -n "$suspicious_ips" ]; then
    log_alert "Подозрительная активность с IP: $suspicious_ips"
fi

echo "Мониторинг завершен: $(date)"
EOF

chmod +x monitor_access.sh

# Добавление в cron
crontab -e
# Добавить строку:
# */5 * * * * /path/to/logboard/monitor_access.sh
```

### Алерты безопасности

```bash
# Скрипт отправки алертов
cat > security_alerts.sh <<'EOF'
#!/bin/bash
# Отправка алертов безопасности
# Автор: Сергей Антропов

ALERT_FILE="/var/log/logboard/security_alerts.log"
EMAIL="admin@company.com"

# Проверка новых алертов
if [ -f "$ALERT_FILE" ]; then
    new_alerts=$(tail -n 10 "$ALERT_FILE")
    
    if [ -n "$new_alerts" ]; then
        echo "$new_alerts" | mail -s "LogBoard+ Security Alert" "$EMAIL"
    fi
fi
EOF

chmod +x security_alerts.sh

# Добавление в cron
crontab -e
# Добавить строку:
# 0 */1 * * * /path/to/logboard/security_alerts.sh
```

## Рекомендации для продакшена

### Обязательные настройки

1. **Измените все пароли по умолчанию**
2. **Используйте сильные секретные ключи**
3. **Настройте HTTPS**
4. **Ограничьте доступ к Docker socket**
5. **Настройте файрвол**
6. **Включите мониторинг безопасности**

### Регулярные проверки

```bash
# Скрипт проверки безопасности
cat > security_check.sh <<'EOF'
#!/bin/bash
# Проверка безопасности LogBoard+
# Автор: Сергей Антропов

echo "=== Проверка безопасности LogBoard+ ==="
echo "Дата: $(date)"
echo ""

# Проверка паролей по умолчанию
if grep -q "LOGBOARD_PASS=admin" .env; then
    echo "❌ Пароль по умолчанию не изменен!"
else
    echo "✅ Пароль изменен"
fi

# Проверка секретных ключей
if grep -q "SECRET_KEY=your-secret-key-here" .env; then
    echo "❌ SECRET_KEY не изменен!"
else
    echo "✅ SECRET_KEY изменен"
fi

if grep -q "ENCRYPTION_KEY=your-encryption-key-here" .env; then
    echo "❌ ENCRYPTION_KEY не изменен!"
else
    echo "✅ ENCRYPTION_KEY изменен"
fi

# Проверка HTTPS
if curl -s -I https://localhost:9001 > /dev/null 2>&1; then
    echo "✅ HTTPS доступен"
else
    echo "⚠️  HTTPS недоступен"
fi

# Проверка прав Docker
if ls -la /var/run/docker.sock | grep -q "srw-rw-rw-"; then
    echo "✅ Docker socket доступен"
else
    echo "❌ Проблемы с доступом к Docker socket"
fi

# Проверка файрвола
if command -v ufw > /dev/null && sudo ufw status | grep -q "Status: active"; then
    echo "✅ Файрвол активен"
else
    echo "⚠️  Файрвол не настроен"
fi

echo ""
echo "=== Рекомендации ==="
echo "1. Регулярно обновляйте ключи"
echo "2. Мониторьте логи доступа"
echo "3. Обновляйте зависимости"
echo "4. Проверяйте права доступа"
echo "5. Тестируйте резервные копии"
EOF

chmod +x security_check.sh

# Запуск проверки
./security_check.sh
```

### План реагирования на инциденты

1. **Немедленные действия**
   - Отключение подозрительных IP
   - Блокировка скомпрометированных учетных записей
   - Анализ логов

2. **Расследование**
   - Определение источника атаки
   - Оценка ущерба
   - Документирование инцидента

3. **Восстановление**
   - Обновление ключей
   - Патчинг уязвимостей
   - Восстановление из резервных копий

4. **Профилактика**
   - Усиление безопасности
   - Обновление процедур
   - Обучение персонала

### Контрольный список безопасности

- [ ] Изменены пароли по умолчанию
- [ ] Сгенерированы сильные секретные ключи
- [ ] Настроен HTTPS
- [ ] Ограничен доступ к Docker
- [ ] Настроен файрвол
- [ ] Включено логирование
- [ ] Настроен мониторинг
- [ ] Созданы резервные копии
- [ ] Документированы процедуры
- [ ] Проведено тестирование безопасности
