orders-to-bi
1. Descripción general
Según el pom.xml, el proyecto se describe como "Send orders and refunds to BI". Es un servicio ligero de Spring Boot, sin servidor web ni base de datos, que mediante tareas programadas (@Scheduled) descarga ficheros XML de pedidos, devoluciones, clientes e inventario desde servidores SFTP (Hawkers producción/staging, proveedor GFK) y los sube al datalake de BI en Google Cloud Storage.
Nótese que tanto el groupId (com.hawkerco) como el paquete Java raíz (com.hawkerco.orderstobi) tienen una errata (falta la "s" de "hawkersco"), consistente en todo el proyecto.
2. Información técnica
| Campo | Valor |
|---|---|
artifactId | orders-to-bi |
groupId | com.hawkerco (nótese la errata, sin la "s" de "hawkersco") |
version | 1.0.25 |
| Java | 25 |
| Spring Boot | 4.0.6 |
| Tipo de artefacto | jar (ejecutable, servicio de larga duración con tareas programadas) |
| Módulos | No aplica (proyecto de módulo único) |
3. Arquitectura y diseño
No es una API REST ni un CommandLineRunner: es un servicio de larga duración con 5 tareas @Scheduled activas y 2 deshabilitadas, todas en component/OrdersToBiSchedule.
| Tarea | Programación | Origen → Destino |
|---|---|---|
ordersToBiProduction | Cada 5 min | SFTP producción Hawkers → GCS (pedidos XML) |
refundsToBiProduction | Cada 5 min | SFTP producción Hawkers → GCS (devoluciones XML) |
customersToBiProduction | Cada 5 min | SFTP producción Hawkers → GCS (clientes XML) |
cleanInventoryFiles | Diaria a medianoche | Borra ficheros de inventario ya procesados en SFTP producción |
microStrategyMoveFile | Lunes 10:50 (Europe/Madrid) | SFTP staging → renombra y sube CSV a SFTP del proveedor GFK |
ordersToBiStaging | Deshabilitada (@Scheduled comentado) | SFTP staging → GCS (pedidos XML) |
refundsToBiStaging | Deshabilitada (@Scheduled comentado) | SFTP staging → GCS (devoluciones XML) |
.utils—OrdersToBiUtils(filtrado por regex, extracción de prefijo de sitio del nombre de fichero, lógica de transferencia SFTP→GCS).
flowchart TD
A["@Scheduled cada 5 min"] -->|descarga XML| B[SFTP producción Hawkers]
A -->|filtra por regex, extrae prefijo de sitio| C[OrdersToBiUtils]
C -->|sube| D["GCS ingestion/sfcc/{site}/{type}/output/timestamp={fecha}/"]
A -->|"@Scheduled lunes 10:50"| E[SFTP staging]
E -->|renombra CSV| F[SFTP GFK]
4. Dependencias principales
| Dependencia | Propósito |
|---|---|
spring-boot-starter | Núcleo de Spring Boot (@Scheduled) |
com.hawkersco:pi-function-commons | SftpUtils, StorageUtils, DateUtils, DirectoryUtils |
com.hawkersco:sfcc-commons | Modelos compartidos |
5. API / Endpoints
No aplica a este proyecto. No expone capa REST; opera exclusivamente mediante tareas programadas.
6. Integraciones externas
| Sistema | Protocolo | Dirección | Detalle |
|---|---|---|---|
Servidor SFTP sftp.hawkersco.com (producción y staging, usuarios distintos) | SFTP | Entrante | Descarga de XML de pedidos/devoluciones/clientes/inventario |
Servidor SFTP GFK (gimftp.gfk.com) | SFTP | Saliente | Subida del fichero CSV semanal para MicroStrategy |
Google Cloud Storage (proyecto bi-saldum) | API de GCS, autenticación por clave de cuenta de servicio | Saliente | Ingesta de ficheros al datalake de BI |
7. Configuración
En producción, las credenciales SFTP llegan por variables de entorno inyectadas como Secret de Kubernetes; en local (application.properties) el repositorio contiene actualmente valores reales hardcodeados (ver alerta de seguridad crítica).
| Clave | Descripción |
|---|---|
gcs.bucket.name / .name.pro | Buckets de destino en GCS (dev/producción) |
orderstobi.ftp.staging.* / .production.* | Credenciales SFTP de Hawkers (staging y producción) |
gfk.ftp.* | Credenciales SFTP del proveedor GFK |
orderstobi.ftp.regex.* | Patrones de nombre de fichero por tipo (pedidos, devoluciones, inventario, clientes) |
🛑 Alerta de seguridad crítica — clave privada de cuenta de servicio de GCP comprometida en el repositorio
El fichero certificates/bi-saldum-519f49efa11b.json, presente físicamente en este repositorio (no en .gitignore como afirma el CLAUDE.md existente: "GCP auth: certificates/bi-saldum-519f49efa11b.json (service account key, not committed)"), es una clave privada completa de una cuenta de servicio de Google Cloud (type: service_account, proyecto bi-saldum, cuenta pi-kafka-gcs@bi-saldum.iam.gserviceaccount.com). El propio pom.xml la incluye explícitamente en el plugin Jib (extraDirectories, copiando certificates/ a /certificates dentro de la imagen Docker) para que la aplicación la use en tiempo de ejecución (OrdersToBiSchedule.initStorage() la carga directamente desde disco).
Esto es una clave criptográfica real, no una simple contraseña: cualquiera con acceso a este repositorio (incluyendo su historial de control de versiones) puede autenticarse como esa cuenta de servicio y actuar con los permisos de GCP que tenga asignados en el proyecto bi-saldum (previsiblemente, al menos, escritura en el datalake de BI). No se ha reproducido ningún fragmento de la clave privada en este documento.
Se recomienda con prioridad máxima:
- Revocar/rotar inmediatamente la clave de la cuenta de servicio
pi-kafka-gcs@bi-saldum.iam.gserviceaccount.comdesde la consola de IAM de GCP (proyectobi-saldum), generando una nueva clave. - Eliminar el fichero
certificates/bi-saldum-519f49efa11b.jsondel repositorio y de su historial de Git. - Sustituir la autenticación por fichero de clave por un mecanismo gestionado (Workload Identity en GKE, o montaje de la clave como
Secretde Kubernetes en tiempo de despliegue, nunca versionado en el repositorio de código). - Auditar los logs de acceso de esa cuenta de servicio en GCP para descartar uso no autorizado, dado que la fecha del fichero (2020, según metadatos) sugiere una exposición prolongada.
Además, application.properties contiene las contraseñas SFTP reales de Hawkers (staging y producción) y del proveedor GFK, no reproducidas en este documento. Se recomienda rotarlas también.
8. Persistencia
No aplica a este proyecto. No usa base de datos: el estado se traspasa íntegramente vía ficheros en SFTP/GCS.
9. Procesos programados y mensajería
Descritos en su totalidad en la tabla de la sección 3; no hay CommandLineRunner ni CronJob de Kubernetes — el servicio se despliega como Deployment de una réplica, de larga duración, con las tareas programadas gestionadas internamente por Spring (@Scheduled).
10. Ejecución en local
Requisitos previos: JDK 25, Maven, credenciales SFTP válidas y una clave de cuenta de servicio de GCP (idealmente no la comprometida del repositorio, ver alerta de seguridad).
# Compilar sin tests
./mvnw -B -DskipTests clean install
# Ejecutar tests
./mvnw test
# Build Docker
docker build -t orders-to-bi .
Al no ser una API REST, no hay endpoint de health check: la verificación se hace revisando el log de consola o los ficheros reflejados en GCS.
11. Despliegue
- Imagen: construida con
jib-maven-plugin(baseeclipse-temurin:25-jre,containerizingMode=packaged, incluye el directoriocertificates/completo —con la clave de cuenta de servicio— dentro de la imagen), publicada eneurope-west3-docker.pkg.dev/pi-saldum/pi-repo/orders-to-bi:<tag>. - Orquestación: Kubernetes
Deployment(una réplica) en el clúster GKEpi-cluster-hw, namespacepi, contenedor no privilegiado. - CI/CD (Jenkins): pipeline real de 3 etapas —
Checkout→Build & Push→Deploy to GKE.
Job de Jenkins: https://jenkins-pi.hawkersco.net/job/orders-to-bi/
12. Manejo de errores y logging
No hay una estrategia de excepciones centralizada. Cada tarea programada captura sus propias excepciones (IllegalAccessException, JSchException, IOException, SftpException, ParseException) y registra el mensaje sin propagar el error, de modo que un fallo en una ejecución no impide que la tarea vuelva a ejecutarse en el siguiente ciclo programado. Logging mediante java.util.logging.Logger estándar (consola).
13. Notas y consideraciones
🛑 Ver alerta de seguridad crítica en la sección 7
Es, con diferencia, el hallazgo más grave de todo este lote de documentación: una clave privada de cuenta de servicio de GCP comprometida y activamente empaquetada en la imagen de producción.
Otros hallazgos
- Errata en
groupIdy paquete Java:com.hawkercoen lugar decom.hawkersco, consistente en todo el proyecto (Maven y paquete Java) — no afecta a la funcionalidad, pero es una inconsistencia notable frente al resto de proyectos de este ecosistema. CLAUDE.mdverificado y consistente en el resto de aspectos: las 5 tareas activas y las 2 deshabilitadas, sus horarios exactos, el patrón de convención de rutas en GCS, y el flujo GFK/MicroStrategy coinciden con el código real, verificado directamente enOrdersToBiSchedule— la única afirmación incorrecta es la relativa a que la clave de GCP "no está comprometida en el repositorio".