# 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@ 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": "" }, "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)*