first commit
This commit is contained in:
@@ -0,0 +1,356 @@
|
||||
# Seguridad
|
||||
|
||||
## Principios de Seguridad
|
||||
|
||||
DataTransferV2 maneja datos sensibles y requiere medidas de seguridad apropiadas para entornos de producción.
|
||||
|
||||
## Gestión de Credenciales
|
||||
|
||||
### Problema Actual
|
||||
|
||||
**Las credenciales están hardcodeadas en archivos de configuración:**
|
||||
|
||||
```python
|
||||
# App/Config/GeneralConfig.py
|
||||
USERNAME = "usuario_db"
|
||||
PASSWORD = "password_db"
|
||||
SHAREPOINT_CLIENT_ID = "client_id"
|
||||
```
|
||||
|
||||
### Soluciones Recomendadas
|
||||
|
||||
#### 1. Variables de Entorno
|
||||
|
||||
```bash
|
||||
# Archivo .env
|
||||
DB_USER=usuario_seguro
|
||||
DB_PASSWORD=password_seguro
|
||||
SHAREPOINT_CLIENT_ID=client_id_seguro
|
||||
FTP_PASSWORD=password_ftp_seguro
|
||||
```
|
||||
|
||||
```python
|
||||
# En GeneralConfig.py
|
||||
import os
|
||||
|
||||
USERNAME = os.getenv("DB_USER")
|
||||
PASSWORD = os.getenv("DB_PASSWORD")
|
||||
SHAREPOINT_CLIENT_ID = os.getenv("SHAREPOINT_CLIENT_ID")
|
||||
```
|
||||
|
||||
#### 2. Secrets Management
|
||||
|
||||
##### Azure Key Vault
|
||||
|
||||
```python
|
||||
from azure.keyvault.secrets import SecretClient
|
||||
from azure.identity import DefaultAzureCredential
|
||||
|
||||
credential = DefaultAzureCredential()
|
||||
client = SecretClient(vault_url="https://myvault.vault.azure.net/", credential=credential)
|
||||
|
||||
DB_PASSWORD = client.get_secret("db-password").value
|
||||
```
|
||||
|
||||
##### AWS Secrets Manager
|
||||
|
||||
```python
|
||||
import boto3
|
||||
|
||||
client = boto3.client('secretsmanager')
|
||||
response = client.get_secret_value(SecretId='prod/datatransfer/db')
|
||||
credentials = json.loads(response['SecretString'])
|
||||
DB_USER = credentials['username']
|
||||
DB_PASSWORD = credentials['password']
|
||||
```
|
||||
|
||||
##### HashiCorp Vault
|
||||
|
||||
```python
|
||||
import hvac
|
||||
|
||||
client = hvac.Client(url='https://vault.example.com:8200')
|
||||
client.auth.approle.login(role_id='role_id', secret_id='secret_id')
|
||||
|
||||
DB_PASSWORD = client.read('secret/datatransfer/db')['data']['password']
|
||||
```
|
||||
|
||||
## Autenticación y Autorización
|
||||
|
||||
### API Security
|
||||
|
||||
#### Implementar API Keys
|
||||
|
||||
```python
|
||||
from flask import request, abort
|
||||
|
||||
API_KEYS = os.getenv("API_KEYS", "").split(",")
|
||||
|
||||
def require_api_key(func):
|
||||
@wraps(func)
|
||||
def decorated(*args, **kwargs):
|
||||
api_key = request.headers.get('X-API-Key')
|
||||
if api_key not in API_KEYS:
|
||||
abort(401, "Invalid API key")
|
||||
return func(*args, **kwargs)
|
||||
return decorated
|
||||
|
||||
@app.route('/api/download')
|
||||
@require_api_key
|
||||
def download_data():
|
||||
# Endpoint protegido
|
||||
```
|
||||
|
||||
#### JWT Tokens
|
||||
|
||||
```python
|
||||
from flask_jwt_extended import JWTManager, jwt_required
|
||||
|
||||
app.config['JWT_SECRET_KEY'] = os.getenv('JWT_SECRET_KEY')
|
||||
jwt = JWTManager(app)
|
||||
|
||||
@app.route('/api/download')
|
||||
@jwt_required()
|
||||
def download_data():
|
||||
# Requiere token JWT válido
|
||||
```
|
||||
|
||||
### UI Web Security
|
||||
|
||||
#### Autenticación de Usuario
|
||||
|
||||
```python
|
||||
from flask_login import LoginManager, login_required
|
||||
|
||||
login_manager = LoginManager()
|
||||
login_manager.init_app(app)
|
||||
|
||||
@app.route('/etl')
|
||||
@login_required
|
||||
def etl_interface():
|
||||
# Solo usuarios autenticados
|
||||
```
|
||||
|
||||
#### Rate Limiting
|
||||
|
||||
```python
|
||||
from flask_limiter import Limiter
|
||||
|
||||
limiter = Limiter(app, key_func=lambda: request.remote_addr)
|
||||
|
||||
@app.route('/api/download')
|
||||
@limiter.limit("10 per minute")
|
||||
def download_data():
|
||||
# Máximo 10 requests por minuto por IP
|
||||
```
|
||||
|
||||
## Encriptación de Datos
|
||||
|
||||
### En Tránsito
|
||||
|
||||
#### HTTPS para API
|
||||
|
||||
```python
|
||||
from flask_sslify import SSLify
|
||||
|
||||
sslify = SSLify(app) # Fuerza HTTPS
|
||||
```
|
||||
|
||||
#### Conexiones Encriptadas
|
||||
|
||||
- **Base de Datos:** Usar `encrypt=yes` en connection string
|
||||
- **FTP:** Considerar FTPS (FTP over SSL)
|
||||
- **SFTP:** Ya encriptado por defecto
|
||||
- **SharePoint:** HTTPS obligatorio
|
||||
|
||||
### En Reposo
|
||||
|
||||
#### Encriptar Archivos Excel
|
||||
|
||||
```python
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.styles import Protection
|
||||
|
||||
wb = Workbook()
|
||||
ws = Protection.set_password('password_seguro')
|
||||
wb.security = Protection(workbookPassword='password_seguro')
|
||||
```
|
||||
|
||||
#### Encriptar Base de Datos
|
||||
|
||||
Configurar SQL Server con Transparent Data Encryption (TDE).
|
||||
|
||||
## Control de Acceso
|
||||
|
||||
### Principio de Menor Privilegio
|
||||
|
||||
#### Usuario de Base de Datos
|
||||
|
||||
```sql
|
||||
-- Crear usuario con permisos mínimos
|
||||
CREATE USER datatransfer_user WITH PASSWORD = 'password';
|
||||
GRANT SELECT ON Cobertura TO datatransfer_user;
|
||||
GRANT SELECT ON Checkout TO datatransfer_user;
|
||||
-- Solo permisos de lectura
|
||||
```
|
||||
|
||||
#### Usuario FTP
|
||||
|
||||
- Solo permisos de escritura en directorio específico
|
||||
- No permisos de lectura/eliminación
|
||||
|
||||
#### Usuario SharePoint
|
||||
|
||||
- Acceso solo a document libraries específicas
|
||||
- Permisos de Contributor (no Owner)
|
||||
|
||||
### Network Security
|
||||
|
||||
#### Firewall Rules
|
||||
|
||||
```bash
|
||||
# Solo permitir conexiones desde IPs específicas
|
||||
ufw allow from 192.168.1.0/24 to any port 5000
|
||||
ufw allow from 10.0.0.0/8 to any port 5000
|
||||
ufw deny from 0.0.0.0/0 to any port 5000
|
||||
```
|
||||
|
||||
#### VPC/Subnets
|
||||
|
||||
- Desplegar en red privada
|
||||
- Usar NAT Gateway para acceso outbound
|
||||
- Security Groups restrictivos
|
||||
|
||||
## Auditoría y Monitoreo
|
||||
|
||||
### Logging Seguro
|
||||
|
||||
```python
|
||||
# No loggear credenciales
|
||||
logger.info(f"Connected to database: {db_config['server']}")
|
||||
# ❌ MAL: logger.info(f"Connected with user: {USERNAME}")
|
||||
|
||||
# Sanitizar datos sensibles en logs
|
||||
def sanitize_log(message):
|
||||
# Remover passwords, tokens, etc.
|
||||
return re.sub(r'password=\w+', 'password=***', message)
|
||||
```
|
||||
|
||||
### Monitoreo de Seguridad
|
||||
|
||||
#### Detección de Intrusiones
|
||||
|
||||
- Monitorear logs para patrones sospechosos
|
||||
- Alertas en accesos desde IPs desconocidas
|
||||
- Rate limiting para prevenir ataques de fuerza bruta
|
||||
|
||||
#### Vulnerability Scanning
|
||||
|
||||
```bash
|
||||
# Escanear dependencias
|
||||
safety check
|
||||
pip-audit
|
||||
|
||||
# Escanear imagen Docker
|
||||
docker scan datatransfer:latest
|
||||
```
|
||||
|
||||
## Backup y Recuperación
|
||||
|
||||
### Estrategia de Backup
|
||||
|
||||
#### Configuración
|
||||
|
||||
```bash
|
||||
# Backup de configs
|
||||
tar -czf config_backup_$(date +%Y%m%d).tar.gz App/Config/
|
||||
|
||||
# Versionado en Git (sin secrets)
|
||||
git add App/Config/
|
||||
git commit -m "Config update"
|
||||
```
|
||||
|
||||
#### Datos
|
||||
|
||||
- **Reportes:** Backup automático en storage redundante
|
||||
- **Logs:** Rotación y compresión semanal
|
||||
- **Base de Datos:** Backup SQL Server programado
|
||||
|
||||
### Plan de Recuperación
|
||||
|
||||
#### Disaster Recovery
|
||||
|
||||
1. **Restaurar desde backup**
|
||||
2. **Reconfigurar credenciales**
|
||||
3. **Verificar integridad**
|
||||
4. **Reanudar operaciones**
|
||||
|
||||
#### Business Continuity
|
||||
|
||||
- **RTO (Recovery Time Objective):** 4 horas
|
||||
- **RPO (Recovery Point Objective):** 1 hora
|
||||
- **Multi-region:** Despliegue en múltiples zonas
|
||||
|
||||
## Cumplimiento
|
||||
|
||||
### GDPR (Europa)
|
||||
|
||||
- **Derecho al olvido:** Capacidad de eliminar datos
|
||||
- **Consentimiento:** Documentar uso de datos
|
||||
- **Auditoría:** Logs de acceso a datos personales
|
||||
|
||||
### SOX (EEUU)
|
||||
|
||||
- **Controles internos:** Validación de procesos ETL
|
||||
- **Auditoría financiera:** Traceability de datos
|
||||
- **Integridad:** Checks de validación de datos
|
||||
|
||||
### ISO 27001
|
||||
|
||||
- **Asset Management:** Inventario de datos sensibles
|
||||
- **Access Control:** Autenticación multifactor
|
||||
- **Incident Management:** Procedimientos de respuesta
|
||||
|
||||
## Mejores Prácticas
|
||||
|
||||
### Desarrollo Seguro
|
||||
|
||||
1. **Code Reviews:** Revisar código por seguridad
|
||||
2. **Dependency Scanning:** Verificar vulnerabilidades en paquetes
|
||||
3. **Input Validation:** Sanitizar todas las entradas
|
||||
4. **Error Handling:** No exponer información sensible en errores
|
||||
|
||||
### Despliegue Seguro
|
||||
|
||||
1. **Imágenes Base:** Usar imágenes oficiales y actualizadas
|
||||
2. **Secrets:** Nunca en código o imágenes
|
||||
3. **Network:** Principio de zero trust
|
||||
4. **Monitoring:** Alertas en tiempo real
|
||||
|
||||
### Operaciones Seguras
|
||||
|
||||
1. **Access Management:** Rotación regular de credenciales
|
||||
2. **Backup Testing:** Verificar restauración periódicamente
|
||||
3. **Incident Response:** Plan documentado y probado
|
||||
4. **Training:** Capacitación en seguridad para equipo
|
||||
|
||||
## Checklist de Seguridad
|
||||
|
||||
### Antes de Producción
|
||||
|
||||
- [ ] Credenciales en variables de entorno
|
||||
- [ ] HTTPS configurado
|
||||
- [ ] Autenticación implementada
|
||||
- [ ] Rate limiting activo
|
||||
- [ ] Logs sanitizados
|
||||
- [ ] Backup funcionando
|
||||
- [ ] Firewall configurado
|
||||
- [ ] Dependencias actualizadas
|
||||
|
||||
### Monitoreo Continuo
|
||||
|
||||
- [ ] Alertas de seguridad activas
|
||||
- [ ] Logs revisados regularmente
|
||||
- [ ] Vulnerabilidades escaneadas
|
||||
- [ ] Accesos auditados
|
||||
- [ ] Backups verificados
|
||||
Reference in New Issue
Block a user