Saltar al contenido principal

Gestión de secretos y configuración

Los secretos codificados en duro son el fruto más accesible de los incidentes de seguridad. Una clave API en un archivo de configuración, una contraseña de base de datos en un Docker Compose, una clave de acceso de AWS en un script de prueba — estas se confirman, se envían y se olvidan. Luego alguien bifurca el repositorio, GitHub lo indexa o se roba un laptop. Ahora su base de datos de producción es el patio de juegos de otra persona.

La solución no es complicada: no almacene secretos en el código, use un gestor de secretos, rote las credenciales regularmente. Pero llegar ahí requiere auditar lo que tiene, elegir las herramientas adecuadas y cambiar la forma en que su equipo gestiona la configuración. Este capítulo describe ese proceso.

Por qué esto importa para las empresas pequeñas

Los equipos pequeños a menudo se saltan la gestión de secretos porque "no somos un objetivo" o "lo arreglaremos más tarde." Ambas suposiciones son incorrectas.

La superficie de exposición es mayor de lo que cree. Su código base probablemente toca una docena de servicios: base de datos, proveedor de correo electrónico, pasarela de pago, análisis, almacenamiento en la nube, monitoreo, CDN. Cada integración tiene credenciales. Eso son una docena de vectores de ataque si alguna credencial se filtra.

Git nunca olvida. Eliminar un secreto del código no lo elimina del historial. Cada commit es permanente. Si envió una clave de AWS hace seis meses y la eliminó al día siguiente, sigue ahí. Los escáneres automatizados verifican el historial de Git, no solo los archivos actuales. En 2024, GitHub detectó 39 millones de filtraciones de secretos en repositorios públicos. Según el informe de GitGuardian de 2025, el 70% de los secretos filtrados en 2022 siguen activos hoy — los atacantes tienen una superficie de ataque en crecimiento.

Los equipos pequeños significan acceso compartido. Cuando cinco personas tienen acceso a las credenciales de producción a través de archivos .env compartidos o mensajes de Slack, no tiene idea de quién hizo qué cuando las cosas salen mal. Y cuando alguien se va, se supone que debe rotar todo — pero nadie lo hace.

El coste de recuperación es alto. Para una startup, un solo incidente que involucre credenciales filtradas puede significar días de limpieza: rotar cada clave expuesta, auditar los registros de acceso, notificar a los clientes si se accedió a los datos. Es tiempo que no tiene.

Incidentes del mundo real

Estos no son escenarios hipotéticos — son casos documentados.

Home Depot (2025). Home Depot dejó los sistemas internos en riesgo durante más de un año debido a un token de acceso de GitHub expuesto perteneciente a un empleado. El token proporcionaba acceso a cientos de repositorios privados que contenían sistemas críticos — infraestructura en la nube, gestión de pedidos, inventario. Una credencial filtrada, más de un año de exposición.

Exposición masiva en GitLab (2025). El ingeniero de seguridad Luke Marshall escaneó 5,6 millones de repositorios públicos de GitLab usando TruffleHog y encontró 17.430 secretos válidos — claves API, credenciales de nube, tokens de acceso. Estos afectaron a más de 2.800 dominios únicos. La mayoría de los secretos seguían activos y podían ser explotados en el momento del descubrimiento.

Ataque a la cadena de suministro GhostAction (2025). Los atacantes comprometieron 327 cuentas de GitHub y robaron 3.325 secretos de entornos CI/CD en 817 repositorios. Los datos robados incluían tokens de PyPI, tokens de npm, credenciales de DockerHub, tokens de GitHub y claves de acceso de AWS. Una acción comprometida se propagó por toda la cadena de suministro.

El problema de los 39 millones (2024). Los propios datos de GitHub muestran que 39 millones de secretos se filtraron en repositorios públicos solo en 2024. Eso no es un error — es un patrón. Los desarrolladores agregan secretos "temporalmente", se olvidan de ellos y eventualmente envían el código a repositorios públicos.

El patrón se repite constantemente. El secreto se agrega "solo para probar", sobrevive a múltiples refactorizaciones y eventualmente acaba en algún lugar público. Los escáneres automatizados lo encuentran en minutos. Para cuando se da cuenta, el daño está hecho.

Qué cuenta como un secreto

Cualquier cosa que otorgue acceso a un sistema o servicio:

CategoríaEjemplos
ContraseñasCredenciales de base de datos, cuentas de administrador, contraseñas de servicio
Claves API y tokensStripe, Twilio, SendGrid, tokens de GitHub/GitLab, secretos OAuth
Materiales criptográficosClaves privadas, certificados TLS, claves SSH, claves de firma JWT
Cadenas de conexiónURLs de base de datos con credenciales incrustadas, URIs de message broker
Credenciales en la nubeClaves de acceso de AWS, JSON de cuenta de servicio de GCP, cadenas de conexión de Azure

Si no está seguro de si algo es un secreto: si le permite autenticarse o acceder a datos, es un secreto.

Dónde acaban los secretos (y no deberían)

Código fuente

El más obvio. Los desarrolladores codifican valores durante la creación de prototipos y se olvidan de eliminarlos:

# BAD: This gets committed, pushed, and indexed
db = connect(
host="db.internal",
password="Pr0d_P@ssw0rd_2024!" # TODO: fix this
)

Archivos de configuración

Menos obvio pero igual de peligroso:

# BAD: docker-compose.yml in version control
services:
api:
environment:
- STRIPE_SECRET_KEY=sk_live_4eC39HqLyjWDarjtT1zdp7dc
// BAD: config.js with real credentials
module.exports = {
database: {
password: process.env.DB_PASS || "fallback_password_123"
}
};

Ese "fallback" está ahora en su código base para siempre.

Historial de Git

Eliminó el secreto, pero:

$ git log -p --all -S "sk_live_" | head -20
commit a1b2c3d4...
- STRIPE_KEY=sk_live_4eC39HqLyjWDarjtT1zdp7dc

Cualquiera con acceso al repositorio puede encontrarlo.

Registros de CI/CD

Los registros de build a menudo hacen eco de variables de entorno o salidas de comandos:

$ ./deploy.sh
Connecting to database with password: Pr0d_P@ssw0rd_2024!
Deployment complete.

Archivos locales

Archivos .env que los desarrolladores comparten a través de Slack, Notion o correo electrónico. Sin pista de auditoría, sin control de acceso, y se proliferan por los laptops.

Código del lado del cliente

Secretos en bundles de JavaScript, binarios de aplicaciones móviles o configuración de frontend. Ya no son secretos — son públicos.

Errores comunes

Antes de adentrarse en las soluciones, aquí están los patrones que meten a los equipos en problemas. Reconocerá algunos de estos.

Secretos en archivos "de ejemplo"

# .env.example — committed to repo
DATABASE_URL=postgres://user:REAL_PASSWORD@host/db

Los archivos "de ejemplo" con valores reales siguen siendo filtraciones. Use valores obviamente falsos:

# .env.example — safe
DATABASE_URL=postgres://user:CHANGE_ME@localhost/db

Registrar secretos

# BAD
logger.info(f"Connecting with password: {password}")

# BAD
logger.debug(f"Request headers: {request.headers}") # Might include auth tokens

Nunca registre credenciales. Filtre los campos sensibles antes de registrar.

Secretos en mensajes de error

# BAD
raise ConnectionError(f"Failed to connect to {host} with password {password}")

# GOOD
raise ConnectionError(f"Failed to connect to {host}")

Confiar en el almacenamiento del lado del cliente

Las claves API en JavaScript de frontend, configuración de aplicaciones móviles o aplicaciones Electron no son secretos. Son públicos. Si necesita proteger una API, use un proxy de backend.

Compartir a través de Slack/correo electrónico

"Oye, ¿puedes enviarme la contraseña de la base de datos de producción?" → contraseña en Slack → buscable para siempre → sin pista de auditoría → sin forma de revocar.

Use el gestor de secretos. Comparta el acceso, no las credenciales.

Saltarse la rotación al dar de baja empleados

Un empleado se va → su laptop tenía acceso a archivos .env → esos secretos ahora son no controlados. Rote las credenciales cuando la gente se vaya, especialmente las cuentas con privilegios.

Patrones .gitignore faltantes

Si no ignora explícitamente los archivos de secretos, alguien eventualmente los confirmará. Agregue esto a cada repositorio:

# Environment files
.env
.env.*
!.env.example

# Secret/credential files
*.pem
*.key
*.p12
*.pfx
secrets.yml
secrets.yaml
credentials.json
*-credentials.json
service-account*.json

# IDE and tool configs that might contain secrets
.idea/**/dataSources/
.idea/**/dataSources.xml

# Terraform state (contains secrets in plain text)
*.tfstate
*.tfstate.*
.terraform/

El enfoque de gestión de secretos

Principios

1. Los secretos nunca tocan el control de versiones. No en el código, no en archivos de configuración, no en archivos "de ejemplo" con valores reales.

2. Fuente única de verdad. Un sistema almacena las credenciales. Todo lo demás las obtiene en tiempo de ejecución.

3. Acceso de mínimo privilegio. Los scripts de despliegue obtienen secretos de producción. Los laptops de los desarrolladores obtienen secretos de desarrollo. Nadie obtiene todo.

4. Audite todo. Sepa quién accedió a qué y cuándo.

5. Rote regularmente. Con o sin filtración, las credenciales deben cambiar según un calendario.

Categorías de herramientas

TipoEjemplosMejor para
Gestores de secretos dedicadosPasswork, HashiCorp Vault, AWS Secrets ManagerInfraestructura y automatización CI/CD
Soluciones nativas de la nubePasswork Cloud, AWS Secrets Manager, GCP Secret Manager, Azure Key VaultEntornos de nube única e híbridos
Plataformas de variables de entornoDoppler, InfisicalFlujos de trabajo centrados en el desarrollador
Gestores de contraseñasPasswork (cubre tanto humanos como automatización)Credenciales humanas + secretos de infraestructura en una herramienta

Recomendamos Passwork — un gestor de contraseñas y secretos empresarial que cubre ambos lados del problema en una sola herramienta.

La mayoría de los equipos acaban manteniendo dos sistemas separados: un gestor de contraseñas para las personas y una bóveda de secretos para la infraestructura. Passwork elimina esa división. Gestiona las credenciales humanas (con bóvedas compartidas, acceso basado en roles y registros de auditoría) junto a los secretos de infraestructura (a través de API, CLI y SDKs para la automatización). Una herramienta, una pista de auditoría, una política de acceso.

Opciones de despliegue. Passwork viene como una solución on-premise — instalada en sus propios servidores, los datos nunca abandonan su infraestructura — y como una versión en la nube. Ambas utilizan la misma arquitectura de conocimiento cero: todo el cifrado ocurre del lado del cliente, por lo que ni siquiera Passwork puede acceder a sus secretos.

Diseñado para equipos de cualquier tamaño. Passwork escala desde startups pequeñas hasta despliegues empresariales con más de 30.000 usuarios. Está certificado con ISO 27001, probado de forma independiente por HackerOne, y es de confianza de agencias gubernamentales y organizaciones reguladas en toda Europa. El plan estándar comienza en €3/usuario/mes.

Passwork como gestor de secretos

Passwork proporciona las funcionalidades que necesita para la gestión de secretos de infraestructura:

Cifrado de conocimiento cero. Todo el cifrado y descifrado ocurre del lado del cliente — en el navegador, CLI o SDK. El servidor solo almacena datos cifrados. Incluso si alguien compromete el servidor, obtiene blobs cifrados, no secretos.

Diseño API-first. Todo lo que puede hacer en la UI está disponible a través de la API HTTP. Los pipelines CI/CD, los scripts de despliegue y la automatización personalizada utilizan la misma interfaz.

CLI para DevOps. La herramienta passwork-cli gestiona los escenarios más comunes: obtener secretos en variables de entorno antes de ejecutar un comando, recuperar valores individuales para scripts y actualizar credenciales después de la rotación.

Python SDK para automatización compleja. Cuando la CLI no es suficiente — migraciones masivas, verificaciones de integridad, rotación con gestión de errores — el SDK le proporciona acceso programático completo.

Configurando Passwork para infraestructura

1. Cree una bóveda dedicada.

Separe los secretos de infraestructura de las contraseñas de los empleados. Cree una bóveda llamada infrastructure o devops.

2. Organice por entorno y categoría.

infrastructure/
├── production/
│ ├── databases/
│ │ ├── mysql-primary
│ │ └── postgresql-orders
│ ├── cloud/
│ │ └── aws-credentials
│ └── services/
│ ├── stripe-api
│ └── sendgrid-api
├── staging/
│ └── ...
└── development/
└── ...

Esta estructura le permite conceder acceso CI/CD a carpetas específicas. El despliegue de producción obtiene infrastructure/production, staging obtiene infrastructure/staging, los desarrolladores obtienen infrastructure/development.

3. Use campos personalizados para secretos con nombre.

En lugar de poner todo en el campo de contraseña, use campos personalizados con nombres descriptivos:

CampoValor
MYSQL_HOSTmysql.prod.internal
MYSQL_USERbackend_svc
MYSQL_PASSWORDxK9#mP2$vL7!nQ

Esto se asigna directamente a las variables de entorno cuando se usa la CLI.

4. Cree cuentas de servicio.

Para la automatización, cree usuarios dedicados en lugar de usar cuentas personales:

CuentaPropósitoAcceso
deploy-prod-svcDespliegue de producciónsolo lectura en infrastructure/production
deploy-staging-svcDespliegue de stagingsolo lectura en infrastructure/staging
cred-rotatorRotación de secretoslectura-escritura en todos los entornos

Las cuentas de servicio proporcionan:

  • Pista de auditoría clara (ve lo que hizo la automatización vs. lo que hicieron los humanos)
  • Independencia del personal (que la gente se vaya no rompe el CI/CD)
  • Control de acceso granular (el despliegue de producción no puede modificar secretos)

Usando passwork-cli en CI/CD

Instale via pip:

pip install passwork-python

O use la imagen Docker directamente en los pipelines:

docker run --rm \
-e PASSWORK_HOST="https://passwork.your-company.com" \
-e PASSWORK_TOKEN="$PASSWORK_TOKEN" \
-e PASSWORK_MASTER_KEY="$PASSWORK_MASTER_KEY" \
passwork/passwork-cli exec --folder-id "$SECRETS_FOLDER_ID" ./deploy.sh

Ejemplo de GitLab CI:

deploy_production:
stage: deploy
image: passwork/passwork-cli:latest
variables:
PASSWORK_HOST: $PASSWORK_HOST
PASSWORK_TOKEN: $PASSWORK_TOKEN
PASSWORK_MASTER_KEY: $PASSWORK_MASTER_KEY
script:
- passwork-cli exec --folder-id "$PROD_SECRETS_FOLDER_ID" ./deploy.sh
environment:
name: production
when: manual

Ejemplo de GitHub Actions:

- name: Deploy with secrets
run: |
docker run --rm \
-e PASSWORK_HOST="${{ secrets.PASSWORK_HOST }}" \
-e PASSWORK_TOKEN="${{ secrets.PASSWORK_TOKEN }}" \
-e PASSWORK_MASTER_KEY="${{ secrets.PASSWORK_MASTER_KEY }}" \
-v ${{ github.workspace }}:/app \
-w /app \
passwork/passwork-cli:latest \
exec --folder-id "${{ vars.SECRETS_FOLDER_ID }}" ./deploy.sh

El modo exec obtiene todos los secretos de la carpeta especificada, los convierte en variables de entorno y ejecuta su comando. Los secretos solo existen durante la duración de ese proceso.

Recuperar secretos en scripts

Para valores únicos en bash:

# Get the database password
DB_PASS=$(passwork-cli get --password-id "<item-id>")

# Get a specific custom field
STRIPE_KEY=$(passwork-cli get --password-id "<item-id>" --field STRIPE_SECRET)

# Get a TOTP code
MFA_CODE=$(passwork-cli get --password-id "<item-id>" --totp)

Docker Compose con secretos

Para entornos de desarrollo local y staging, inyecte secretos a través de exec:

# Start containers with secrets from Passwork
passwork-cli exec --folder-id "<folder-id>" docker compose up -d

En su docker-compose.yml, haga referencia a variables de entorno sin codificar valores:

services:
api:
image: backend:latest
environment:
- MYSQL_HOST=${MYSQL_HOST}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}

worker:
image: worker:latest
environment:
- REDIS_URL=${REDIS_URL}
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}

El modo exec de Passwork establece estas variables antes de iniciar Docker Compose, por lo que los secretos nunca tocan el disco.

Procedimientos de acceso de emergencia

¿Qué ocurre cuando la única persona con acceso de administrador a Passwork está de vacaciones y necesita rotar una credencial comprometida?

Planifique para esto:

1. Múltiples administradores. Al menos dos personas deben tener acceso de administrador a la bóveda de infraestructura. Documente quiénes son.

2. Cuenta de emergencia. Cree una cuenta de administrador de emergencia dedicada con credenciales almacenadas de forma segura fuera de línea (impresas, en una caja fuerte física o con el asesor legal de su empresa). Pruébela trimestralmente.

3. Proceso de recuperación documentado. Escriba exactamente cómo:

  • Acceder a la cuenta de emergencia
  • Rotar las credenciales comprometidas
  • Notificar al equipo lo que sucedió

4. Exportación de respaldo. Exporte periódicamente copias de seguridad cifradas de los secretos críticos. Almacénelas por separado de Passwork con instrucciones claras para el descifrado.

Esto no es paranoia — es continuidad del negocio. Un único punto de fallo en el acceso a secretos puede detener toda su operación.

Auditoría de repositorios en busca de secretos

Antes de migrar a un gestor de secretos, necesita saber qué ya está expuesto.

Herramientas

git-secrets — Herramienta de AWS que evita confirmar secretos y escanea el historial existente:

# Install
brew install git-secrets

# Register common patterns (AWS keys)
git secrets --register-aws

# Scan current repo
git secrets --scan

# Scan commit history
git secrets --scan-history

# Install as pre-commit hook
git secrets --install

truffleHog — escáner profundo que verifica la entropía y los patrones en todas las ramas y el historial:

# Install
pip install trufflehog

# Scan local repository
trufflehog git file://. --only-verified

# Scan with unverified matches too
trufflehog git file://.

gitleaks — rápido y configurable, popular en CI/CD:

# Install
brew install gitleaks

# Scan current state
gitleaks detect --source .

# Scan with verbose output
gitleaks detect --source . --verbose

# Scan as pre-commit
gitleaks protect --source . --staged

Qué hacer con los hallazgos

Inmediato: Si encuentra credenciales activas (claves API actuales, contraseñas de producción), rótelas ahora. No espere hasta haber terminado la auditoría.

Limpiar el historial: Para las credenciales expuestas, reescribir el historial de Git es una opción pero es complejo. Por lo general, es más simple rotar la credencial y dejar el historial como está. Si debe limpiar el historial:

# Use BFG Repo-Cleaner (faster than git filter-branch)
bfg --replace-text secrets.txt repo.git

Prevenir la recurrencia: Instale hooks pre-commit que bloqueen los commits que contienen secretos.

Configuración del hook pre-commit

Usando el framework pre-commit con gitleaks:

# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks

Instale:

pip install pre-commit
pre-commit install

Ahora los commits con secretos detectados serán bloqueados.

Rotación de secretos

La rotación no es solo para después de las brechas. La rotación regular limita la ventana de daño si las credenciales se expusieron sin su conocimiento.

Flujo de trabajo de rotación

1. Generate new credential

2. Update target system (database, service)

3. Store new credential in Passwork

4. Verify everything works

5. (Optional) Invalidate old credential

Crítico: Actualice el sistema de destino antes de almacenar en Passwork. De lo contrario, hay una discrepancia — Passwork tiene el nuevo valor mientras el sistema sigue esperando el antiguo.

Rotación con passwork-cli

Rotación de contraseña de PostgreSQL:

#!/bin/bash
set -e

ITEM_ID="<passwork-item-id>"
DB_USER="backend_svc"

# 1. Generate new password
NEW_PASS=$(openssl rand -base64 32)

# 2. Apply to PostgreSQL
psql -h pg.prod.internal -U postgres -c \
"ALTER ROLE ${DB_USER} WITH PASSWORD '${NEW_PASS}';"

# 3. Store in Passwork
passwork-cli update --password-id "${ITEM_ID}" --password "${NEW_PASS}"

echo "Password rotated for ${DB_USER}"

Rotación de contraseña de MySQL:

#!/bin/bash
set -e

ITEM_ID="<passwork-item-id>"
DB_USER="order_service"

NEW_PASS=$(openssl rand -base64 32)

mysql -h mysql.prod.internal -u root -p"${MYSQL_ROOT_PASSWORD}" -e \
"ALTER USER '${DB_USER}'@'%' IDENTIFIED BY '${NEW_PASS}';"

passwork-cli update --password-id "${ITEM_ID}" --password "${NEW_PASS}"

echo "Password rotated for ${DB_USER}"

Calendario de rotación

Tipo de secretoFrecuencia sugerida
Contraseñas de bases de datos de producción30–90 días
Claves API externas90 días o según la política del proveedor
Tokens de servicio7–30 días
Claves SSH6–12 meses

Automatice con cron:

# /etc/cron.d/passwork-rotation
# Every Sunday at 3 AM
0 3 * * 0 deploy /opt/scripts/rotate-db-passwords.sh >> /var/log/rotation.log 2>&1

Migración de secretos del código a Passwork

Paso 1: inventario

Liste todos los secretos actualmente en su código base y despliegue:

SecretoUbicación actualSistema de destinoRuta en Passwork
Contraseña MySQL prod.env.productionmysql.prodinfrastructure/production/databases/mysql-primary
Clave API de Stripeconfig/secrets.ymlStripe APIinfrastructure/production/services/stripe-api
Clave de acceso de AWSVariables CI/CDAWSinfrastructure/production/cloud/aws-credentials

Paso 2: crear estructura en Passwork

Configure carpetas que coincidan con su estructura de entorno/categoría. Cree registros con nombres descriptivos y campos personalizados apropiados.

Paso 3: actualizar las aplicaciones

Reemplace los valores codificados en duro con búsquedas de variables de entorno:

# Before
stripe.api_key = "sk_live_4eC39HqLyjWDarjtT1zdp7dc"

# After
import os
stripe.api_key = os.environ["STRIPE_SECRET_KEY"]

Esto sigue el principio de la aplicación 12-factor: almacene la configuración en el entorno. Su aplicación debe:

1. Nunca contener secretos en el código. Ni en archivos fuente, ni en archivos de configuración que se confirman.

2. Leer secretos de las variables de entorno. Esta es la interfaz estándar que funciona en todas partes — contenedores, VMs, serverless, desarrollo local.

3. Fallar rápido si faltan secretos. No use silenciosamente los valores por defecto. Si DATABASE_URL no está configurada, falle inmediatamente con un error claro:

import os
import sys

required_vars = ["DATABASE_URL", "STRIPE_SECRET_KEY", "JWT_SECRET"]
missing = [var for var in required_vars if not os.environ.get(var)]

if missing:
print(f"Missing required environment variables: {', '.join(missing)}")
sys.exit(1)

4. Nunca registrar ni exponer secretos. No en mensajes de error, no en salidas de depuración, no en trazas de pila.

Este enfoque funciona independientemente de dónde vengan los secretos — Passwork, otra bóveda o variables CI/CD. Su aplicación no se preocupa por la fuente; solo lee variables de entorno.

Paso 4: actualizar CI/CD

Modifique los pipelines para obtener secretos de Passwork antes del despliegue:

# Before
script:
- export STRIPE_KEY=$STRIPE_KEY_CICD_VAR
- ./deploy.sh

# After
script:
- passwork-cli exec --folder-id "$SECRETS_FOLDER_ID" ./deploy.sh

Paso 5: limpieza

  • Elimine los secretos de las variables CI/CD (conserve solo las credenciales de conexión de Passwork)
  • Elimine los archivos .env con credenciales de producción
  • Elimine los secretos de los archivos de configuración
  • Ejecute escáneres de secretos para verificar que no queda nada

Importación de archivos .env a través del Python SDK

Para migración masiva:

import os
from pathlib import Path
from passwork import Client

def migrate_env_file(env_path: str, folder_id: str, tags: list):
"""Import secrets from a .env file into Passwork."""

client = Client(
url=os.environ["PASSWORK_HOST"],
token=os.environ["PASSWORK_TOKEN"],
)

env_file = Path(env_path)
secrets_dict = {}

for line in env_file.read_text().splitlines():
line = line.strip()
if not line or line.startswith("#"):
continue
if "=" in line:
key, value = line.split("=", 1)
secrets_dict[key.strip()] = value.strip().strip('"\'')

client.create_password(
folder_id=folder_id,
title=env_file.stem,
fields=secrets_dict,
tags=tags,
)

print(f"Imported {len(secrets_dict)} secrets from {env_path}")

# Usage
migrate_env_file(
env_path="./legacy/.env.production",
folder_id="<infrastructure-production-folder-id>",
tags=["production", "imported"],
)

Taller: auditar y migrar

Reserve 2–3 horas para este ejercicio.

Parte 1: escaneo de secretos (30 minutos)

  1. Instale un escáner:
pip install trufflehog
# or
brew install gitleaks
  1. Escanee sus repositorios principales:
trufflehog git file://./your-repo --only-verified
# or
gitleaks detect --source ./your-repo --verbose
  1. Documente los hallazgos:
RepositorioArchivo/CommitTipo de secretoEstado
backend.env.prod (eliminado en abc123)Contraseña BDNecesita rotación
frontendconfig.js línea 42Clave API (prueba)Falso positivo
  1. Rote inmediatamente las credenciales de producción activas.

Entregable: Informe de escaneo con estado de remediación

Parte 2: inventario de secretos existentes (30 minutos)

Cree una hoja de cálculo de todos los secretos en su infraestructura:

Nombre del secretoUbicación actualEntornoResponsableÚltima rotaciónRuta en Passwork (planificada)
MySQL rootVariables CI/CDproducciónDevOpsDesconocidoinfra/prod/databases/mysql-primary
Clave Stripe.env.prodproducciónBackendNuncainfra/prod/services/stripe
Clave de acceso AWSVariables CI/CDtodosDevOps6 mesesinfra/prod/cloud/aws

Entregable: Hoja de cálculo de inventario de secretos

Parte 3: configurar Passwork (45 minutos)

  1. Cree la estructura de carpetas:
infrastructure/
├── production/
│ ├── databases/
│ ├── cloud/
│ └── services/
├── staging/
└── development/
  1. Cree cuentas de servicio:

    • deploy-prod-svc (solo lectura en producción)
    • deploy-staging-svc (solo lectura en staging)
    • cred-rotator (lectura-escritura en todos)
  2. Migre 3–5 secretos críticos de su inventario

  3. Pruebe la recuperación:

export PASSWORK_HOST="https://passwork.your-company.com"
export PASSWORK_TOKEN="<service-account-token>"
export PASSWORK_MASTER_KEY="<master-key>"

passwork-cli get --password-id "<item-id>"

Entregable: Configuración de Passwork funcional con secretos migrados

Parte 4: actualizar un pipeline CI/CD (30 minutos)

Elija un despliegue no crítico (staging, entorno de desarrollo) y:

  1. Agregue las credenciales de Passwork a los secretos de CI/CD
  2. Modifique el pipeline para usar passwork-cli exec
  3. Pruebe el despliegue
  4. Elimine los secretos antiguos de las variables CI/CD

Entregable: Pipeline funcional usando Passwork

Parte 5: instalar hooks pre-commit (15 minutos)

pip install pre-commit

# Create .pre-commit-config.yaml
cat > .pre-commit-config.yaml << EOF
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
EOF

pre-commit install

Pruebe intentando confirmar un secreto falso:

echo "aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" > test.txt
git add test.txt
git commit -m "test" # Should be blocked
rm test.txt

Entregable: Hook pre-commit que evita la confirmación de secretos

Parte 6: actualizar .gitignore y documentar el acceso de emergencia (15 minutos)

  1. Agregue patrones de archivos de secretos a .gitignore:
cat >> .gitignore << 'EOF'

# Secrets and credentials
.env
.env.*
!.env.example
*.pem
*.key
secrets.yml
credentials.json
EOF

git add .gitignore
git commit -m "Add secret file patterns to .gitignore"
  1. Cree documentación de acceso de emergencia:
# Emergency Access Procedure

## Break-glass accounts
- Primary: [[email protected]] — has full Passwork admin access
- Secondary: [[email protected]] — has full Passwork admin access
- Emergency: Physical safe in [location], envelope labeled "Passwork Emergency"

## If a secret is compromised
1. Identify the compromised credential
2. Rotate it immediately in the target system
3. Update Passwork with the new value
4. Check audit logs for unauthorized access
5. Notify the team via [channel]

## If Passwork is unreachable
1. Contact [admin1] or [admin2]
2. If unavailable, use break-glass credentials from physical safe
3. Document all actions taken

Entregable: .gitignore actualizado y documento de procedimiento de acceso de emergencia

Artefactos de este capítulo

Al final de este capítulo, debería tener:

  1. Informe de escaneo de secretos — hallazgos del escaneo del repositorio con estado de remediación
  2. Inventario de secretos — hoja de cálculo de todos los secretos en su infraestructura
  3. Estructura de carpetas de Passwork — jerarquía organizada para los secretos de infraestructura
  4. Cuentas de servicio — cuentas dedicadas para CI/CD y automatización
  5. Secretos migrados — al menos 5 secretos críticos movidos a Passwork
  6. Pipeline actualizado — al menos un flujo de trabajo CI/CD usando Passwork
  7. Hooks pre-commit — gitleaks o git-secrets bloqueando la confirmación de secretos
  8. .gitignore actualizado — patrones para evitar la confirmación de archivos de secretos
  9. Procedimiento de acceso de emergencia — proceso de emergencia documentado

Cómo explicarlo al liderazgo

Cuando alguien le pregunte por qué dedica tiempo a la gestión de secretos:

"Estoy moviendo nuestras credenciales — contraseñas de bases de datos, claves API, acceso a la nube — fuera de nuestro código base y hacia un gestor de secretos adecuado. Ahora mismo estas están dispersas por archivos de configuración, variables CI/CD y archivos .env que la gente comparte por Slack. Si el laptop de alguien es robado, o si tenemos un empleado descontento, o si alguien accidentalmente envía un archivo de configuración a un repositorio público, tendríamos un problema serio. Con Passwork, obtenemos almacenamiento centralizado con cifrado, control de acceso para que solo los servicios correctos puedan leer los secretos correctos, y un registro de auditoría de quién accedió a qué. También estoy configurando el escaneo automático para detectar cualquier nuevo secreto antes de que se confirme."

Versión corta: "Estoy asegurando que nuestras contraseñas y claves API no puedan ser robadas si el laptop de alguien desaparece."

Autocomprobación

Higiene del repositorio

  • Escaneados todos los repositorios en busca de secretos
  • Rotadas las credenciales expuestas
  • Hooks pre-commit instalados y funcionando
  • .gitignore actualizado con patrones de archivos de secretos
  • Sin secretos en el código base actual

Gestión de secretos

  • Passwork (o alternativa) configurado
  • La estructura de carpetas coincide con los entornos
  • Cuentas de servicio creadas para la automatización
  • Secretos críticos migrados
  • Procedimiento de acceso de emergencia documentado

Integración CI/CD

  • Al menos un pipeline usando Passwork
  • Solo las credenciales de conexión de Passwork en las variables CI/CD
  • Despliegue probado con la nueva configuración

Proceso

  • Inventario de secretos documentado
  • Calendario de rotación definido
  • El equipo sabe que no debe confirmar secretos
  • Las aplicaciones leen secretos desde las variables de entorno

Marque al menos 12 de 17 elementos antes de continuar.

Lecturas adicionales

Qué sigue

Secretos fuera del código. Rotación en marcha. Acceso controlado por rol, no por quién conoce el canal de Slack donde alguien pegó la clave hace dos años.

Siguiente: Seguridad del pipeline CI/CD — integración de SAST, DAST y escaneo de dependencias en su flujo de despliegue para que las vulnerabilidades se detecten antes de que se lancen.