# 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)*
