Skip to content

ChubbyIsaak/CI-CDMongoDB-API

Repository files navigation

CICD Safe Changes API v4

API Express + TypeScript para aplicar cambios de esquema en MongoDB de forma segura, auditable y trazable, con integraciones opcionales hacia Artifactory y Jira.


Tabla de contenidos


Resumen rápido

  • Autenticación JWT HS256 y verificación HMAC opcional en operaciones de escritura.
  • Middleware de seguridad: Helmet, CORS configurable, allowlist de IP y rate limiting.
  • Ventana de cambios configurable con posibilidad de bypass controlado.
  • Operaciones idempotentes createCollection y createIndex, con auditoría, revert y rollback en lotes.
  • Documentación OpenAPI disponible en /docs (Swagger UI) y /redoc.
  • Integraciones opcionales:
    • Artifactory: genera un artefacto JSON por operación.
    • Jira: crea o actualiza issues con comentarios operativos.

Requisitos previos

  • Node.js 18 o superior.
  • Acceso a una instancia de MongoDB.
  • (Opcional) Credenciales válidas para Artifactory y/o Jira si las integraciones se habilitan.

Primeros pasos

  1. Clona el repositorio y entra en la carpeta del proyecto.
  2. Copia .env.example a .env y completa los valores necesarios.
  3. Instala las dependencias:
    npm install
  4. Ejecuta el proyecto en modo desarrollo:
    npm run dev
  5. Abre http://localhost:8080/docs para navegar la especificación interactiva.

Variables de entorno

Parámetros generales

Variable Descripción
PORT Puerto HTTP de la API (por defecto 8080).
AUDIT_DB Base de datos donde se guardan los registros de auditoría.
JWT_SECRET Secreto HS256 para validar JWT (obligatorio si JWT_REQUIRED=true).
HMAC_SECRET Clave para validar la firma HMAC de los cuerpos en escrituras.
RATE_LIMIT_WINDOW_MS, RATE_LIMIT_MAX Configuración del limitador global.
IP_ALLOWLIST Lista (coma) de IP/CIDR permitidos. Vacío = sin restricción.
CORS_ORIGINS Orígenes permitidos para CORS. Vacío = *.
OPLOG_ENABLE, OPLOG_DIR Control de logs operativos (NDJSON diario).
CHANGE_ALLOW_WINDOW Cadena que define ventana de cambios permitidos.
CHANGE_FREEZE_MESSAGE Mensaje devuelto cuando la ventana bloquea la acción.
CHANGE_BYPASS_TOKEN Token opcional para saltar la ventana de cambios.
ALLOW_TARGET_URI_REGEX Regex opcional para validar URIs de destino.

Integración con Artifactory

Variable Descripción
ARTIFACTORY_ENABLED Activa la publicación (true/false).
ARTIFACTORY_BASE_URL URL base (ej. https://artifactory.miempresa.com/artifactory).
ARTIFACTORY_REPOSITORY Repositorio por defecto para los artefactos.
ARTIFACTORY_PATH_TEMPLATE Plantilla de ruta (changes/{changeId}/{action}-{timestamp}.json).
ARTIFACTORY_USERNAME, ARTIFACTORY_PASSWORD Credenciales básicas (alternativa al token).
ARTIFACTORY_TOKEN Token API (X-JFrog-Art-Api).
ARTIFACTORY_TIMEOUT_MS Timeout de la solicitud HTTP.

Integración con Jira

Variable Descripción
JIRA_ENABLED Activa la sincronización (true/false).
JIRA_BASE_URL URL base de Jira (ej. https://miempresa.atlassian.net).
JIRA_EMAIL Cuenta usada para autenticarse.
JIRA_API_TOKEN Token API asociado a JIRA_EMAIL.
JIRA_PROJECT_KEY Proyecto por defecto al crear issues.
JIRA_ISSUE_TYPE Tipo de issue (por defecto Task).
JIRA_DEFAULT_LABELS Etiquetas por defecto separadas por comas.
JIRA_TIMEOUT_MS Timeout de la solicitud HTTP.

Consejo: reutiliza el bloque completo de .env.example para evitar errores tipográficos.


Scripts disponibles

Comando Descripción
npm run dev Inicia el servidor con recarga en caliente (ts-node-dev).
npm run build Compila TypeScript a JavaScript en dist/.
npm start Ejecuta la versión compilada desde dist/.

Consumir la API

  1. Genera un JWT firmado con JWT_SECRET. Puedes usar jsonwebtoken:
    npm i jsonwebtoken
    node -e "const jwt=require('jsonwebtoken');console.log(jwt.sign({sub:'user-1',email:'dev@local'}, process.env.JWT_SECRET,{algorithm:'HS256',expiresIn:'1h'}));"
  2. Para aplicar un cambio individual:
    curl -X POST "http://localhost:8080/changes/apply" \
      -H "Authorization: Bearer <TOKEN>" \
      -H "Content-Type: application/json" \
      -d '{
        "target": {
          "uri": "mongodb://user:pass@127.0.0.1:27017/admin",
          "database": "MyDB"
        },
        "operation": {
          "type": "createIndex",
          "collection": "users",
          "spec": { "email": 1 },
          "options": { "name": "ix_email_unique", "unique": true }
        }
      }'
  3. Usa /changes?uri=<URI codificada> para consultar auditoría. Añade status=applied,failed,skipped,reverted si necesitas incluir revertidos.

Cuando dryRun=true, la API valida y genera plan, pero no toca MongoDB ni dispara integraciones.


Integrando Artifactory

Configurar el servidor

  1. Establece ARTIFACTORY_ENABLED=true en .env.
  2. Define ARTIFACTORY_BASE_URL y ARTIFACTORY_REPOSITORY.
  3. Configura autenticación: usuario/contraseña o token API.
  4. Reinicia el servicio para aplicar los cambios.

Para cada operación se genera un JSON con:

  • Información del cambio original (incluyendo metadatos).
  • Resultado (status, message, durationMs, revertPlan).
  • Contexto operativo (action, timestamp, requestId, información de lote, actor`).

La respuesta HTTP incluye integrations.artifactory con el resultado de la publicación (enabled, success, details, error, skippedReason).

Personalizar por petición

Dentro del payload, usa metadata.artifactory:

"metadata": {
  "artifactory": {
    "repository": "db-changes",
    "path": "changes/{changeId}/{action}-{timestamp}.json",
    "properties": {
      "environment": "prod",
      "service": "payments-api"
    },
    "skip": false
  }
}
  • La plantilla acepta {changeId}, {action}, {timestamp}, {collection} y {operation}.
  • properties genera parámetros de matriz (;clave=valor).
  • Usa skip: true si quieres omitir la publicación en un caso concreto.

Integrando Jira

Configurar el servidor

  1. Establece JIRA_ENABLED=true.
  2. Define JIRA_BASE_URL, JIRA_PROJECT_KEY, JIRA_EMAIL y JIRA_API_TOKEN.
  3. Ajusta JIRA_ISSUE_TYPE y JIRA_DEFAULT_LABELS si lo necesitas.
  4. Reinicia el servicio.

Comportamiento por defecto:

  • Si no se envía metadata.jira.issueKey, la API crea un nuevo issue usando los valores derivados del cambio.
  • Cada ejecución agrega un comentario con action, status, message y timestamp.
  • La respuesta incluye integrations.jira con issueKey, created, commentId, url, o en su defecto, error / skippedReason.

Personalizar por petición

"metadata": {
  "jira": {
    "issueKey": "OPS-1234",
    "summary": "Crear índice único para pagos",
    "description": "Detalles extendidos...",
    "labels": ["db-change", "payments"],
    "components": ["Payments"],
    "assignee": "db.automation",
    "skip": false
  }
}
  • issueKey reutiliza un ticket existente.
  • summary y description sobreescriben los generados.
  • labels, components y assignee complementan o sustituyen la configuración global.
  • skip: true evita que esa petición dispare Jira.
  • linkIssues está reservado para futuras funciones.

Ejemplo completo de payload

{
  "target": {
    "uri": "mongodb://user:pass@cluster/?replicaSet=rs0&authSource=admin",
    "database": "Billing"
  },
  "operation": {
    "type": "createIndex",
    "collection": "payments",
    "spec": { "invoiceId": 1 },
    "options": { "name": "idx_invoice_unique", "unique": true }
  },
  "metadata": {
    "artifactory": {
      "repository": "db-changes",
      "path": "changes/{changeId}/{action}-{timestamp}.json",
      "properties": {
        "environment": "prod",
        "service": "payments-api"
      }
    },
    "jira": {
      "summary": "Crear índice único para pagos",
      "labels": ["db-change", "payments"],
      "components": ["Payments"],
      "assignee": "db.automation"
    }
  }
}

Trazabilidad y monitoreo

  • Logs operativos: si OPLOG_ENABLE=true, se generan archivos NDJSON diarios en logs/ops-YYYYMMDD.log.
  • Auditoría en MongoDB: colección cicd_changes_audit con detalle de cada cambio y su revertPlan.
  • Respuesta del API: el bloque integrations confirma qué ocurrió en Artifactory y Jira.

Solución de problemas

Problema Acción sugerida
401 Unauthorized Verifica el JWT (firmado con el secreto correcto y sin expirar).
403 en /changes/* IP fuera del allowlist, ventana de cambios cerrada o firma HMAC inválida.
integrations.artifactory.skippedReason = "missing_credentials" Falta token/API key o usuario/contraseña en .env.
Errores _failed_4xx/5xx en Jira Revisa permisos, datos obligatorios y proyecto configurado.
Integraciones omitidas en dryRun Comportamiento esperado: no se contacta Artifactory/Jira durante simulaciones.

Manual operativo: Artifactory + Jira + Postman

1. Preparativos

  1. Recursos necesarios
    • Cuenta con privilegios administrativos en Artifactory (Cloud o self-hosted).
    • Cuenta Atlassian con permiso para crear proyectos en Jira Software.
    • Acceso a una instancia MongoDB y al servidor donde se ejecutará esta API.
    • Postman instalado (o Postman Web + agente local).
  2. Repositorio local: clona este proyecto y asegúrate de instalar dependencias (npm install).

2. Aprovisionar Artifactory

  1. Crear instancia
  2. Crear repositorio genérico
    • Ingresa a Administration → Repositories → Create Repository → Generic (Local).
    • Asigna un nombre (ej. db-changes) y guarda la configuración por defecto.
  3. Crear usuario técnico o token
    • Opciones:
      • Usuario dedicado con permiso deploy sobre el repo recién creado.
      • Token API (administración → User ManagementAccess Tokens).
    • Anota username/password o el token, la base URL de Artifactory (https://<host>/artifactory) y el nombre del repositorio.

3. Aprovisionar Jira

  1. Crear proyecto
    • Entra a admin.atlassian.comJira SoftwareProjectsCreate project → Plantilla Kanban/Scrum clásica.
    • Define la clave del proyecto (ej. OPS).
  2. Generar API Token

4. Vincular integraciones con la API

  1. Configurar .env
    ARTIFACTORY_ENABLED=true
    ARTIFACTORY_BASE_URL=https://<tu-host>/artifactory
    ARTIFACTORY_REPOSITORY=db-changes
    ARTIFACTORY_USERNAME=<usuario>        # O usa ARTIFACTORY_TOKEN
    ARTIFACTORY_PASSWORD=<contraseña>
    ARTIFACTORY_TIMEOUT_MS=20000
    
    JIRA_ENABLED=true
    JIRA_BASE_URL=https://<tu-org>.atlassian.net
    JIRA_EMAIL=<correo@tuorg.com>
    JIRA_API_TOKEN=<token_api>
    JIRA_PROJECT_KEY=OPS
    JIRA_ISSUE_TYPE=Task
    JIRA_DEFAULT_LABELS=db-change,automation
    JIRA_TIMEOUT_MS=20000
  2. Levantar la API
    npm run dev
    • Verifica en consola que no existan errores de conexión.
  3. Preparar collection en Postman
    • Crea un Environment con variables:
      • baseUrl: http://localhost:8080
      • jwt: token válido (puedes generarlo con el snippet de este README).
      • mongoUri: URI del cluster de pruebas.
      • database: nombre de la base (ej. Billing).
      • artifactoryRepo: db-changes (opcional).
      • jiraIssueKey: deja vacío; se completará automáticamente.

5. Ejecutar una prueba con Postman (buenas prácticas)

  1. Request: POST ${{baseUrl}}/changes/apply
    • Headers:
      • Authorization: Bearer {{jwt}}
      • Content-Type: application/json
      • (Opcional) X-Request-Id: {{uuid}} para trazabilidad.
    • Body (raw JSON):
      {
        "target": {
          "uri": "{{mongoUri}}",
          "database": "{{database}}"
        },
        "operation": {
          "type": "createIndex",
          "collection": "payments",
          "spec": { "invoiceId": 1 },
          "options": { "name": "idx_invoice_unique", "unique": true }
        },
        "metadata": {
          "artifactory": {
            "repository": "{{artifactoryRepo}}",
            "path": "changes/{changeId}/{action}-{timestamp}.json",
            "properties": {
              "environment": "dev",
              "service": "payments-api"
            }
          },
          "jira": {
            "summary": "Crear índice unique para invoices",
            "labels": ["db-change", "payments"],
            "components": ["Payments"]
          }
        }
      }
  2. Enviar petición y revisar respuesta:
    • status debe ser 200.
    • integrations.artifactory.successtrue y details.url apuntando al JSON en Artifactory.
    • integrations.jira.details.issueKey → clave del issue creado.
    • Guarda changeId como variable Postman para pruebas posteriores (ej. revert).
  3. Validaciones manuales
    • Artifactory: descarga el artefacto y confirma que incluye change, result y context.
    • Jira: abre el issue (details.url) y verifica el comentario con Action, Status, Message y Timestamp.
  4. Prueba de re-ejecución
    • Reenvía la misma petición; Artifactory debe registrar un segundo artefacto y Jira debe añadir un nuevo comentario (la integración no crea issue nuevo).
  5. Rollback opcional
    • POST ${{baseUrl}}/changes/revert con body { "changeId": "<id>", "uri": "{{mongoUri}}" }.
    • Verifica que Artifactory reciba el artefacto de tipo revert y que Jira sume otro comentario con action: revert.

Buenas prácticas: usa entornos de ensayo, activa dryRun=true antes de ejecutar contra producción, documenta los issueKey resultantes y automatiza limpieza (drop index/colección) al finalizar las pruebas.


¿Planeas integrarlo en un pipeline? Orquesta los JSON desde tu CI/CD y usa el resumen de integraciones para alimentar tableros operativos, reportes o alertas automáticas.

About

Repositorio para la creacion de una API que permita un flujo CI/CD en MongoDB

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published