Initial commit: Terraform infrastructure, pipelines, docs and scripts
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
# 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)*
|
||||
Reference in New Issue
Block a user