206 lines
6.4 KiB
Markdown
206 lines
6.4 KiB
Markdown
# 08 - Seguridad y Secretos
|
|
|
|
> Cómo protegemos las contraseñas, llaves y datos sensibles de `proyectosacc`.
|
|
|
|
---
|
|
|
|
## 1. ¿Qué es un "secreto"?
|
|
|
|
Un **secreto** es cualquier información que no debe ser pública. En `proyectosacc`, los secrets incluyen:
|
|
|
|
- Contraseñas de bases de datos.
|
|
- Llaves SSH privadas.
|
|
- Tokens de Telegram.
|
|
- Credenciales de AWS (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`).
|
|
|
|
> 💡 **Regla de oro**: si perder esa información causaría un problema de seguridad, es un secreto.
|
|
|
|
---
|
|
|
|
## 2. ¿Dónde viven los secrets?
|
|
|
|
### Opción 1: Bitbucket Repository Variables (la más usada)
|
|
|
|
En Bitbucket Pipelines podemos guardar variables de entorno que los scripts usan sin exponer su valor.
|
|
|
|
**Cómo configurarlas:**
|
|
1. Ve al repositorio en Bitbucket.
|
|
2. Entra a **Repository settings > Pipelines > Repository variables**.
|
|
3. Agrega el nombre y el valor.
|
|
4. **Marca la casilla "Secured"** 🔒.
|
|
|
|
**Ventaja**: cuando el pipeline corre, las variables secured aparecen como `***` en los logs. Nadie puede leerlas.
|
|
|
|
### Opción 2: AWS Secrets Manager
|
|
|
|
AWS tiene un servicio llamado **Secrets Manager** que guarda secrets de forma segura y permite rotarlos automáticamente.
|
|
|
|
**Ejemplo de uso en un pipeline de CodeBuild:**
|
|
```yaml
|
|
env:
|
|
secrets-manager:
|
|
DB_PASSWORD: "prod/database/password"
|
|
```
|
|
|
|
### Opción 3: AWS Systems Manager Parameter Store
|
|
|
|
Similar a Secrets Manager, pero más simple y económico. Se usa para guardar configuraciones sensibles.
|
|
|
|
```yaml
|
|
env:
|
|
parameter-store:
|
|
DATABASE_URL: "/app/database/url"
|
|
```
|
|
|
|
### Opción 4: Archivo `.env` (solo local)
|
|
|
|
En tu computadora personal puedes tener un archivo `.env` con variables locales. **Este archivo NUNCA debe subirse al repositorio.**
|
|
|
|
El archivo `.gitignore` del proyecto ya debería incluir `.env` para evitar accidentes.
|
|
|
|
---
|
|
|
|
## 3. ¿Qué NUNCA poner en el repositorio?
|
|
|
|
### ❌ NUNCA hagas esto
|
|
|
|
```yaml
|
|
# Mal ejemplo en bitbucket-pipelines.yml
|
|
- step:
|
|
script:
|
|
- export DB_PASSWORD="supersecreta123"
|
|
- export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
|
|
```
|
|
|
|
```hcl
|
|
# Mal ejemplo en Terraform
|
|
resource "aws_db_instance" "example" {
|
|
password = "mi-contrasena-123"
|
|
}
|
|
```
|
|
|
|
```bash
|
|
# Mal ejemplo en un script
|
|
API_KEY="sk-1234567890abcdef"
|
|
```
|
|
|
|
### ✅ SIEMPRE haz esto
|
|
|
|
```yaml
|
|
# Bien: usa variables de entorno
|
|
- step:
|
|
script:
|
|
- export DB_PASSWORD="$DB_PASSWORD"
|
|
```
|
|
|
|
```hcl
|
|
# Bien: usa variables de Terraform
|
|
resource "aws_db_instance" "example" {
|
|
password = var.db_password
|
|
}
|
|
```
|
|
|
|
```bash
|
|
# Bien: lee desde una variable de entorno
|
|
API_KEY="$API_KEY"
|
|
```
|
|
|
|
---
|
|
|
|
## 4. ¿Cómo rotar las llaves SSH?
|
|
|
|
**Rotar** una llave significa crear una nueva y dejar de usar la anterior. Es una buena práctica de seguridad, especialmente si alguien con acceso a la llave privada deja la empresa.
|
|
|
|
### Paso 1: Generar un nuevo par de llaves
|
|
```bash
|
|
ssh-keygen -t ed25519 -b 4096 \
|
|
-C "bitbucket.pipeline.ci.cd.proyectosacc.thoth.develop@computocontable.com" \
|
|
-f bitbucket_pipeline_ci_cd_TO_proyectosacc_server_thoth_develop
|
|
```
|
|
|
|
### Paso 2: Codificar la llave privada en base64
|
|
```bash
|
|
base64 -i bitbucket_pipeline_ci_cd_TO_proyectosacc_server_thoth_develop | tr -d '\n' > nueva_llave.b64
|
|
```
|
|
|
|
### Paso 3: Actualizar la variable en Bitbucket
|
|
1. Copia el contenido de `nueva_llave.b64`.
|
|
2. Ve a **Repository settings > Pipelines > Repository variables**.
|
|
3. Actualiza la variable `PROYECTOSACC_SSH_KEY` con el nuevo valor.
|
|
|
|
### Paso 4: Colocar la llave pública en el servidor
|
|
```bash
|
|
# Copia el contenido del archivo .pub
|
|
cat bitbucket_pipeline_ci_cd_TO_proyectosacc_server_thoth_develop.pub
|
|
|
|
# Conéctate al servidor y agrégala a authorized_keys
|
|
ssh ubuntu@<IP_DE_LA_EC2>
|
|
sudo su - thoth
|
|
nano ~/.ssh/authorized_keys
|
|
# Pega la nueva llave pública al final del archivo
|
|
|
|
> 💡 **Tip**: en un despliegue automatizado con Terraform, esta llave pública se inyecta directamente desde el archivo `user_data`. No hace falta editar `authorized_keys` a mano.
|
|
|
|
### Paso 5: Probar la conexión
|
|
Ejecuta un pipeline de prueba o conéctate manualmente con la nueva llave privada para confirmar que funciona.
|
|
|
|
### Paso 6: Eliminar la llave anterior
|
|
Una vez confirmado que la nueva llave funciona:
|
|
1. Borra la llave pública antigua de `~/.ssh/authorized_keys`.
|
|
2. Borra la llave privada antigua de tu computadora.
|
|
3. Actualiza cualquier otra copia que exista.
|
|
|
|
---
|
|
|
|
## 5. Seguridad del frontend en S3 + CloudFront
|
|
|
|
### Bucket policy para CloudFront (OAI)
|
|
El bucket S3 del frontend NO debe ser público. Solo CloudFront puede leer los objetos:
|
|
|
|
```json
|
|
{
|
|
"Version": "2012-10-17",
|
|
"Statement": [{
|
|
"Sid": "AllowCloudFrontOAI",
|
|
"Effect": "Allow",
|
|
"Principal": {
|
|
"CanonicalUser": "<OAI-canonical-user-id>"
|
|
},
|
|
"Action": "s3:GetObject",
|
|
"Resource": "arn:aws:s3:::ccsoft-proyectosacc-frontend/*"
|
|
}]
|
|
}
|
|
```
|
|
|
|
### CORS en S3 (si el frontend llama a la API)
|
|
Como el frontend React y la API backend comparten el mismo dominio `https://sacc.ccsoft.mx` (gracias al behavior `/api/*` de CloudFront), **no hay problema de CORS**. Si en el futuro decides mover la API a un subdominio diferente (por ejemplo, `api.sacc.ccsoft.mx`), ahí sí necesitarás configurar CORS en el backend.
|
|
|
|
### Versionamiento de objetos en S3
|
|
Habilita el versionamiento en el bucket del frontend. Así puedes restaurar una versión anterior del sitio si un deploy falla:
|
|
```bash
|
|
aws s3api put-bucket-versioning \
|
|
--bucket ccsoft-proyectosacc-frontend \
|
|
--versioning-configuration Status=Enabled
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Checklist de seguridad básica
|
|
|
|
- [ ] El archivo `.env` está en `.gitignore`.
|
|
- [ ] Ningún archivo del repositorio contiene contraseñas escritas directamente.
|
|
- [ ] Las variables de Bitbucket están marcadas como **Secured**.
|
|
- [ ] La llave privada SSH dedicada para `proyectosacc` está en formato **base64** en Bitbucket.
|
|
- [ ] No se usa acceso SSH por contraseña ni herramientas como `sshpass`.
|
|
- [ ] El puerto SSH (22) de la EC2 solo está abierto a IPs conocidas.
|
|
- [ ] La base de datos RDS no es accesible desde internet (solo desde la VPC).
|
|
- [ ] Los certificados SSL están configurados correctamente en **CloudFront** (HTTPS obligatorio).
|
|
- [ ] El bucket S3 del frontend NO es público; solo CloudFront tiene acceso mediante OAI/OAC.
|
|
- [ ] El versionamiento de objetos está habilitado en el bucket S3 del frontend.
|
|
- [ ] Se ha programado una rotación de llaves SSH al menos una vez al año.
|
|
|
|
---
|
|
|
|
*Anterior: [`07-terraform-iac.md`](07-terraform-iac.md)*
|
|
*Siguiente: [`09-runbook-deploy.md`](09-runbook-deploy.md)*
|