• Saltar a la navegación principal
  • Saltar al contenido principal
  • Saltar al pie de página
Bluetab

Bluetab

an IBM Company

  • Soluciones
    • DATA STRATEGY
    • DATA READINESS
    • DATA PRODUCTS AI
  • Assets
    • TRUEDAT
    • FASTCAPTURE
    • Spark Tune
  • Conócenos
  • Oficinas
    • España
    • Mexico
    • Perú
    • Colombia
  • talento
    • España
    • TALENT HUB BARCELONA
    • TALENT HUB BIZKAIA
    • TALENT HUB ALICANTE
    • TALENT HUB MÁLAGA
  • Blog
  • English

Blog

FinOps

mayo 20, 2024 by Bluetab

FinOps

La Ingeniería del Ahorro en la Era de la Nube y como aplicarlo funcional y técnicamente

Francis Josue De La Cruz

Big Data Architect

Wiener Morán

Data Engineer

En el mundo empresarial actual, la eficiencia en la gestión de costos en la nube se ha convertido en una prioridad. Aquí es donde entra en juego FinOps (Financial Operations), una práctica emergente que combina estratégicas presupuestales, la tecnología de la información (servicios en la nube), estrategias de negocios para maximizar el valor de la nube y sobretodo la inventiva y desarrollo para tratar de sacar provecho económico. En este artículo queremos compartir desde Bluetab, cómo nuestros clientes pueden implementar FinOps, con un enfoque particular en los servicios de Azure de Microsoft.

Estos servicios en la nube brindan una poderosa flexibilidad en la construcción de soluciones y hacen realidad la meta común de pasar del CAPEX al OPEX. Esto se enfrenta al nuevo desafío que las empresas ahora tienen, de monitorear cientos o miles de recursos a la vez para mantener las finanzas alineadas a los presupuestos tecnológicos definidos. Una buena (y necesaria) práctica para esto, es el monitoreo activo de los recursos y costos cloud, lo que permite identificar oportunidades de optimización de recursos no utilizados o infrautilizados, para aplicar los cambios de configuración, prendido y apagado oportuno que pueden conllevar a una significativa reducción de costos.

¿Qué es FinOps?

FinOps es un enfoque, paradigma cultural y operativo que permite a las organizaciones equilibrar y alinear mejor los costos con el valor en entornos de nube. Se trata de una práctica colaborativa, que involucra a equipos de finanzas, operaciones y desarrollo, para gestionar los costos de la nube de manera más efectiva y eficiente.

¿En qué etapa del proyecto se debe considerar el FinOps?

El FinOps, o la gestión financiera de la nube, se debe considerar desde las primeras etapas de un proyecto que involucra servicios en la nube, ya que ayuda a entender y optimizar los costos asociados.

No siempre demanda tener un equipo dedicado desde el inicio, especialmente en proyectos pequeños o medianos, pero sí requiere que alguien asuma la responsabilidad de monitorear y optimizar los costos. A medida que el proyecto crece y el gasto en la nube se incrementa, puede ser beneficioso establecer un equipo dedicado o función de FinOps para gestionar estos costos de manera más efectiva.

Pasos para Implementar FinOps en una empresa usando Servicios de Azure

1. Comprensión y adopción de la cultura FinOps

Educación y Conciencia: capacite a su equipo sobre los principios de FinOps. Esto incluye entender cómo el gasto en la nube afecta a la empresa y cómo pueden contribuir a una gestión más eficiente.

Combinando la Agilidad (Scrum-finOps) en la empresa

Es posible combinar el framework scrum con el enfoque FinOps agregando nuevas ceremonias enfocadas en el mismo, con la finalidad de implementar nuevas prácticas de comunicación y gestión. Por ejemplo, reuniones semanales donde se presentan como va el presupuesto del proyecto y reuniones diarias de cómo va el consumo de los servicios en los diferentes ambientes (development, quality assurance y production).

Colaboración interdepartamental: fomente la colaboración entre los equipos de finanzas, operaciones y desarrollo. La comunicación efectiva es clave para el éxito de FinOps.

2. Análisis del gasto actual en Azure

Auditoría de servicios: realice un inventario de todos los servicios de Azure utilizados. Comprenda cómo se están utilizando y si son esenciales para las operaciones comerciales.

Herramientas de gestión de costos: utilice herramientas como Azure Cost Management y Billing para obtener una visión clara del gasto.

3. Optimización de recursos y costos

Identificación de recursos subutilizados: busque instancias, almacenamiento o servicios que estén infrautilizados. Azure ofrece herramientas para identificar estos recursos.

Implementación de mejores prácticas: aplique prácticas recomendadas para la optimización de recursos, como el escalado automático, la elección de instancias reservadas o el apagado de recursos no utilizados.

3. Optimización de recursos y costos

Establecimiento de presupuestos: defina presupuestos claros para diferentes equipos o proyectos. Azure Cost Management puede ayudar en este proceso.

Pronósticos de gasto: antes de empezar el desarrollo de ahorro de costos en una empresa, se debe tener claro el uso y gasto actual, para estimar el ahorro proyectado. Imagínese cuanto ahorraría en una empresa con más de diez mil pipelines.

Ejemplo: estrategias de ahorro de costos de migración All-purpose hacia Job Clusters en 1 aplicación realtime (13,5 horas prendidas) ahorro de 44% aproximadamente.

Tipos Dbu/hora #DBU/hora Horas activas RT #Clusters Total diario Total mensual Total Anual
Job Cluster-REALTIME
$0,30
3,75
13,5
1
$15,19
$455,63
$5.467,50
All Purpose-REALTIME
$0,55
3,75
13,5
1
$27,84
$835,31
$10.023,75

5. Gobernanza y políticas de uso

Políticas de uso: establezca políticas claras para el uso de recursos en Azure. Esto incluye quién puede aprovisionar recursos y qué tipos de recursos están permitidos.

Automatización de la gobernanza: implemente políticas automatizadas para garantizar el cumplimiento y evitar gastos innecesarios.

Comparativa de características de servicios de gobernanza de costos:

Google Cost Management AWS Cost Management Microsoft Cost Management
Informes y paneles de control
Visualización de informes de costos, personalización mediante Looker Studio.
Proporciona informe de gastos y sus detalles (AWS Cost Explorer)
Reportes y análisis de la organización. Extensible el análisis con Power BI.
Control de Acceso
Uso de políticas para permisos granulares y nivel de jerarquía. Puede establecer quien visualiza los costos y quien realiza los pagos.
Permite establecer mecanismos de gobernanza y seguimiento de la información de facturación en la organización
Control de acceso basado en roles de Azure RBAC. Los usuarios con Azure Enterprise usan una combinación de permisos del Azure Portal y Enterprise (EA)
Presupuesto y alertas
Configuración de presupuestos que envíen alerta por correo si se supera el umbral.
Presupuestos con notificaciones de alerta automáticas (AWS Budgets)
Las vistas de presupuestos pueden estar limitadas por suscripción, grupos de recursos o colección de recursos. Soporta alertas.
Recomendaciones
Recomendaciones inteligentes para optimizar costos, las cuales son fácilmente aplicables.
Alinea el tamaño de los recursos asignados con la demanda real de la carga de trabajo (Rightsizing Recommendations)
Optimizaciones de costos según recomendaciones usando Azure Advisor.
Cuotas
Configuracion de limites de cuotas, que restringe la cantidad de recursos que se pueden utilizar.
Mediante el Service Quotas, limitan los servicios siendo los valores máximos para los recursos.
Dispone de diferentes clasificaciones de límites, algunos de ellos: generales, grupo de administración, suscripción, grupo de recursos, plantilla.

6. Desarrollo e innovación

Ahorro de Costos con el Despliegue de Job Clusters en Databricks

En el mundo de la ciencia de datos y el análisis de grandes volúmenes de datos, Databricks se ha establecido como una plataforma líder. Una de las características clave de Databricks es su capacidad para manejar diferentes tipos de clústeres, siendo los más comunes los «All-Purpose Clusters» y los «Job Clusters». En este artículo, nos centraremos en cómo el despliegue de Job Clusters puede ser una estrategia efectiva para ahorrar costos, especialmente en comparación con los All-Purpose Clusters.

Diferencia entre All-Purpose Clusters y Job Clusters

Antes de sumergirnos en las estrategias de ahorro de costos, es crucial entender la diferencia entre estos dos tipos de clústeres:

All-Purpose Clusters: están diseñados para ser utilizados de manera interactiva y pueden ser compartidos por varios usuarios. Son ideales para el desarrollo y la exploración de datos.

Job Clusters: se crean específicamente para ejecutar un trabajo y se cierran automáticamente una vez que el trabajo ha finalizado. Son ideales para trabajos programados y procesos automatizados. La desventaja en el entorno de Azure de este tipo de despliegue de cluster es que al ser más barato no tiene funciones de gestión de control de uso.

Ejemplo Despliegue Job Cluster

				
					# Configuración de Databricks API
DATABRICKS_INSTANCE = 'https://tu-instancia-databricks.com'
TOKEN = 'tu-token-de-acceso'
JOB_ID = 'tu-job-id'

# Headers para la autenticación
HEADERS = {
    'Authorization': f'Bearer {TOKEN}'
}

# Verificar el estado del job
def check_job_status(job_id):
    response = requests.get(f'{DATABRICKS_INSTANCE}/api/2.0/jobs/get?job_id={job_id}', headers=HEADERS)
    if response.status_code == 200:
        return response.json()['state']
    else:
        raise Exception("Error al obtener el estado del job")

# Cancelar el job si está en ejecución
def cancel_job(job_id):
    response = requests.post(f'{DATABRICKS_INSTANCE}/api/2.0/jobs/runs/cancel', json={"job_id": job_id}, headers=HEADERS)
    if response.status_code != 200:
        raise Exception("Error al cancelar el job")

# Desplegar el job
def deploy_job(job_id):
    response = requests.post(f'{DATABRICKS_INSTANCE}/api/2.0/jobs/run-now', json={"job_id": job_id}, headers=HEADERS)
    if response.status_code == 200:
        return response.json()['run_id']
    else:
        raise Exception("Error al desplegar el job")

# Verificar si el job está corriendo y esperar hasta que lo esté
def wait_for_job_to_run(job_id):
    while True:
        status = check_job_status(job_id)
        if status['life_cycle_state'] == 'RUNNING':
            print("El job está corriendo.")
            break
        elif status['life_cycle_state'] == 'TERMINATED':
            print("El job ha terminado o ha sido cancelado.")
            break
        elif status['life_cycle_state'] == 'PENDING':
            print("El job está pendiente de ejecución, esperando...")
            time.sleep(10)  # Esperar un tiempo antes de volver a verificar
        else:
            raise Exception(f"Estado del job desconocido: {status['life_cycle_state']}")

# Script principal
if __name__ == '__main__':
    # Verificar si el job está actualmente en ejecución y cancelarlo si es necesario
    try:
        status = check_job_status(JOB_ID)
        if status['life_cycle_state'] == 'RUNNING':
            print("Cancelando el job en ejecución...")
            cancel_job(JOB_ID)
    except Exception as e:
        print(f"Error al verificar o cancelar el job: {e}")

    # Desplegar el job
    try:
        print("Desplegando el job...")
        run_id = deploy_job(JOB_ID)
        print(f"Job desplegado con run_id: {run_id}")
    except Exception as e:
        print(f"Error al desplegar el job: {e}")

    # Esperar a que el job esté en 'RUNNING'
    try:
        wait_for_job_to_run(JOB_ID)
    except Exception as e:
        print(f"Error al esperar que el job esté corriendo: {e}")

				
			

Automatización y programación Cosmos DB:

Automatizar y programar un script para reducir al mínimo los Request Units (RU/s) en Azure Cosmos DB puede ayudar a optimizar los costos, especialmente durante los períodos de baja demanda o basándose en métricas de rendimiento o un horario predefinido. Puedes hacer esto usando PowerShell o Python primero debes obtener el throughput actual (RU/s configuradas) del contenedor y luego calcular el 1% de este valor para establecer el nuevo throughput. A continuación, un ejemplo básico en ambos lenguajes.

Usando PowerShell

				
					from azure.cosmos import CosmosClient
import os

# Configuración de Azure Cosmos DB
URL = os.environ.get('AZURE_COSMOS_DB_URL')
KEY = os.environ.get('AZURE_COSMOS_DB_KEY')
DATABASE_NAME = 'tuBaseDeDatos'
CONTAINER_NAME = 'tuContenedor'

# Inicializar cliente de Cosmos DB
client = CosmosClient(URL, credential=KEY)
database = client.get_database_client(DATABASE_NAME)
container = database.get_container_client(CONTAINER_NAME)

# Obtener el throughput actual
throughput_properties = container.read_throughput()
if throughput_properties:
    current_ru = throughput_properties['throughput']
    min_ru = max(int(current_ru * 0.01), 400)  # Calcula el 1%, pero no menos de 400 RU/s

    # Actualizar RU/s
    try:
        container.replace_throughput(min_ru)
    except Exception as e:
        print(f"Error al actualizar RU/s: {e}") 

				
			

Usando Python para reducir RUS bajo demanda o horario de bajo rendimiento

				
					from azure.cosmos import CosmosClient
import os
from datetime import datetime

# Configuración de Azure Cosmos DB
URL = os.environ.get('AZURE_COSMOS_DB_URL')
KEY = os.environ.get('AZURE_COSMOS_DB_KEY')
DATABASE_NAME = 'tuBaseDeDatos'
CONTAINER_NAME = 'tuContenedor'

# Inicializar cliente de Cosmos DB
client = CosmosClient(URL, credential=KEY)
database = client.get_database_client(DATABASE_NAME)
container = database.get_container_client(CONTAINER_NAME)

# Obtener la hora actual
current_hour = datetime.now().hour

# Definir RU/s según la hora del día
if 0 <= current_hour < 7 or 18 <= current_hour < 24:
    new_ru = 400  # RU/s más bajas durante la noche
else:
    new_ru = 1000  # RU/s estándar durante el día

# Actualizar RU/s
container.replace_throughput(new_ru)

				
			

7. Monitoreo continuo y mejora

Revisiones regulares: realice revisiones periódicas del gasto y la utilización de recursos.

Ajustes y mejoras: esté dispuesto a ajustar políticas y prácticas según sea necesario para mejorar continuamente la eficiencia del gasto.

Capacitación y conciencia continua

Un factor diferencial de este tipo de servicios y acompañamiento a nuestros socios tecnológicos es la posibilidad de descubrir, probar a escala y medir objetivamente los beneficios de cada plan de optimización de recursos y costos en sus plataformas, mismo que se plantea como resultado de una revisión regular, proactiva y basada en los cambios liberados por los proveedores de nube.

En Bluetab estamos comprometidos con el ahorro y nuestros especialistas en administración de datos con gusto podrán ayudarte a alcanzar niveles eficientes de monitoreo de costos, servicios y consumo en nubes, que apalanquen tu inversión tecnológica y gastos de operación.

7. Monitoreo continuo y mejora

Implementar FinOps en una empresa que utiliza servicios de Azure no es solo una estrategia para reducir costos, sino una transformación cultural y operativa. Requiere un cambio en la forma en que las organizaciones piensan y actúan respecto al uso de la nube.

Al adoptar FinOps, las empresas pueden no solo optimizar sus gastos en la nube, sino también mejorar la colaboración entre equipos, aumentar la agilidad y fomentar una mayor innovación.

 

Francis Josue De La Cruz

Big Data Architect

Wiener Morán

Data Engineer

¿Quieres saber más de lo que ofrecemos y ver otros casos de éxito?
DESCUBRE BLUETAB

SOLUCIONES, SOMOS EXPERTOS

DATA STRATEGY
DATA FABRIC
AUGMENTED ANALYTICS

Te puede interesar

Data governance in the Contact Center services sector

septiembre 1, 2022
LEER MÁS

Cambios de liderazgo en Bluetab EMEA

abril 3, 2024
LEER MÁS

LakeHouse Streaming on AWS with Apache Flink and Hudi (Part 2)

octubre 4, 2023
LEER MÁS

LA BANCA Y LA ERA DEL OPEN DATA

abril 19, 2023
LEER MÁS

Del negocio físico a la explosión del On-Line

abril 7, 2021
LEER MÁS

Los Incentivos y el Desarrollo de Negocio en las Telecomunicaciones

octubre 9, 2020
LEER MÁS

Publicado en: Blog, Tech

Oscar Hernández, nuevo CEO de Bluetab LATAM

mayo 16, 2024 by Bluetab

Oscar Hernández, nuevo CEO de Bluetab LATAM

Bluetab

  • Oscar asume la responsabilidad de desarrollar, liderar y ejecutar la estrategia de Bluetab en América Latina, con el objetivo de expandir los productos y servicios de la empresa.
  • Bluetab en América inició operaciones en 2012 y tiene presencia en Colombia, México y Perú.

Oscar Hernández Rosales asume la responsabilidad como CEO de Bluetab LATAM y estará a cargo de desarrollar, liderar y ejecutar la estrategia de Bluetab en la región, con el objetivo de expandir los productos y servicios de la empresa para respaldar la transformación digital continua de sus clientes y la creación de valor.

Durante esta transición, Oscar seguirá desempeñando su función como Country Manager de México, lo que garantizará una coordinación efectiva entre nuestras operaciones locales y nuestra estrategia regional, fortaleciendo aún más nuestra posición en el mercado.

"Este nuevo desafío es un privilegio para mí. Estoy comprometido con liderar con visión, seguir fortaleciendo la cultura Bluetab y continuar trabajando por el bienestar de los colaboradores y por el éxito del negocio. Un reto importante en una industria que constantemente se adapta a la evolución de las nuevas tecnologías. Bluetab innova, se adelanta y está dedicada a brindar la mejor experiencia de cliente, apoyada por un equipo profesional, talentoso y apasionado, que conoce las necesidades de las organizaciones", afirma Oscar.

¿Quieres saber más de lo que ofrecemos y ver otros casos de éxito?
DESCUBRE BLUETAB

SOLUCIONES, SOMOS EXPERTOS

DATA STRATEGY
DATA FABRIC
AUGMENTED ANALYTICS

Te puede interesar

Algunas de las capacidades de Matillion ETL en Google Cloud

julio 11, 2022
LEER MÁS

Potencia Tu Negocio con GenAI y GCP: Simple y para Todos

marzo 27, 2024
LEER MÁS

El futuro del Cloud y GenIA en el Next ’23

septiembre 19, 2023
LEER MÁS

Conceptos básicos de AWS Glue

julio 22, 2020
LEER MÁS

Big Data e IoT

febrero 10, 2021
LEER MÁS

5 errores comunes en Redshift

diciembre 15, 2020
LEER MÁS

Publicado en: Blog, Noticias

Cambios de liderazgo en Bluetab EMEA

abril 3, 2024 by Bluetab

Cambios de liderazgo en Bluetab EMEA

Bluetab

  • Luis Malagón, como nuevo CEO de Bluetab EMEA, se convierte en el máximo responsable de la compañía en la región.
  • Por su parte, Tom Uhart continuará impulsando el desarrollo del Offering de Data e Inteligencia Artificial, potenciando el posicionamiento de Bluetab

Foto: Luis Malagón, CEO de Bluetab EMEA, y Tom Uhart, Co-Fundador y Data & AI Offering Lead

Luis Malagón se convierte en el nuevo CEO de Bluetab EMEA tras más de 10 años de experiencia en la compañía y habiendo contribuido enormemente a su éxito y posicionamiento. Sus probadas cualidades de liderazgo lo posicionan perfectamente para impulsar Bluetab en su siguiente fase de crecimiento.

“Este nuevo reto al frente de la región de EMEA es una gran oportunidad para seguir fomentando una cultura orientada al cliente y potenciar sus procesos de transformación. La colaboración forma parte de nuestro ADN y esto sumado a un equipo excepcional nos posiciona en el lugar adecuado y en el momento adecuado. Junto a IBM Consulting vamos a continuar liderando el mercado de las soluciones de Datos e Inteligencia Artificial”, afirma Luis.

“En Bluetab llevamos casi 20 años liderando el sector de los datos. En todo este tiempo, hemos ido adaptándonos a las diferentes tendencias y acompañando a nuestros clientes en su transformación digital, y ahora seguimos haciéndolo con la llegada de la IA Generativa.»

El nuevo rumbo de Tom Uhart

Tom Uhart, Co-Fundador de Bluetab y hasta ahora CEO de EMEA, continuará impulsando el proyecto desde su nuevo rol de Data & AI Offering Lead. De esta manera Tom seguirá impulsando el posicionamiento de la compañía y su expansión internacional de la mano del grupo IBM y otros key players del sector.

“Echando la vista atrás, me siento muy orgulloso de haber visto a Bluetab crecer durante todos estos años. Un equipo que sobresale por su gran talento técnico, espíritu inconformista y cultura de cercanía. Hemos alcanzado grandes metas, superado obstáculos y creado un legado del que todos y todas podemos sentirnos orgullosos. Ahora es la hora de dejar en manos de Luis la siguiente etapa de crecimiento de Bluetab, que estoy seguro será un gran éxito y llevará a la compañía al siguiente nivel”, afirma Tom.

¿Quieres saber más de lo que ofrecemos y ver otros casos de éxito?
DESCUBRE BLUETAB

SOLUCIONES, SOMOS EXPERTOS

DATA STRATEGY
DATA FABRIC
AUGMENTED ANALYTICS

Te puede interesar

Starburst: Construyendo un futuro basado en datos.

mayo 25, 2023
LEER MÁS

Oscar Hernández, nuevo CEO de Bluetab LATAM

mayo 16, 2024
LEER MÁS

Detección de Fraude Bancario con aprendizaje automático

septiembre 17, 2020
LEER MÁS

Data-Drive Agriculture; Big Data, Cloud & AI aplicados

noviembre 4, 2020
LEER MÁS

Bluetab en la ElixirConfEU 2023

mayo 3, 2023
LEER MÁS

Serverless Microservices

octubre 14, 2021
LEER MÁS

Publicado en: Blog, Noticias, Noticias

Leadership changes at Bluetab EMEA

abril 3, 2024 by Bluetab

Leadership changes at Bluetab EMEA

Bluetab

  • Luis Malagón, as the new CEO of Bluetab EMEA, assumes the highest position in the company in the region.
  • Meanwhile, Tom Uhart will continue to drive the development of the Data and Artificial Intelligence Offering, enhancing Bluetab's positioning.

Photo: Luis Malagón, CEO of Bluetab EMEA, and Tom Uhart, Co-Founder y Data & AI Offering Lead

Luis Malagón becomes the new CEO of Bluetab EMEA after more than 10 years of experience within the company, having contributed significantly to its success and positioning. His proven leadership qualities position him perfectly to drive Bluetab in its next phase of growth.

‘This new challenge leading the EMEA region is a great opportunity to continue fostering a customer-oriented culture and enhancing their transformation processes. Collaboration is part of our DNA, and this, combined with an exceptional team, positions us in the right place at the right time. Together with IBM Consulting, we will continue to lead the market in Data and Artificial Intelligence solutions’, states Luis.

At Bluetab, we have been leading the data sector for nearly 20 years. Throughout this time, we have adapted to various trends and accompanied our clients in their digital transformation, and now we continue to do so with the arrival of Generative AI.

Tom Uhart’s new journey

Tom Uhart, Co-Founder of Bluetab and until now CEO of EMEA, will continue to drive the project from his new role as Data & AI Offering Lead. In this way, Tom will continue to enhance the company’s positioning and international expansion hand in hand with the IBM group and other key players in the sector.

‘Looking back, I am very proud to have seen Bluetab grow over all these years. A team that stands out for its great technical talent, rebellious spirit, and culture of closeness. We have achieved great goals, overcome obstacles, and created a legacy of which we can all be proud. Now it's time to leave the next stage of Bluetab's growth in Luis's hands, which I am sure will be a great success and will take the company to the next level’, says Tom.

Do you want to know more about what we offer and to see other success stories?
DISCOVER BLUETAB

SOLUTIONS, WE ARE EXPERTS

DATA STRATEGY
DATA FABRIC
AUGMENTED ANALYTICS

You may be interested in

Snowflake, el Time Travel sin DeLorean para unos datos Fail-Safe.

febrero 23, 2023
READ MORE

DataOps

octubre 24, 2023
READ MORE

Data Mesh

julio 27, 2022
READ MORE

KubeCon 2023: Una mirada hacia el futuro de Kubernetes

abril 26, 2023
READ MORE

¿Existe el Azar?

noviembre 10, 2021
READ MORE

¿Cómo pueden las empresas asegurarse de que sus datos estén estructurados, escalables y disponibles cuando se necesiten?

septiembre 13, 2024
READ MORE

Publicado en: Blog, Blog, Noticias, Noticias

Potencia Tu Negocio con GenAI y GCP: Simple y para Todos

marzo 27, 2024 by Bluetab

Alfonso Zamora
Cloud Engineer

Introducción

El objetivo principal de este artículo es presentar una solución para el análisis y la ingeniería de datos desde el punto de vista del personal de negocio, sin requerir unos conocimientos técnicos especializados. 

Las compañías disponen de una gran cantidad de procesos de ingeniería del dato para sacarle el mayor valor a su negocio, y en ocasiones, soluciones muy complejas para el caso de uso requerido. Desde aquí, proponemos simplificar la operativa para que un usuario de negocio, que anteriormente no podía llevar a cabo el desarrollo y la implementación de la parte técnica, ahora será autosuficiente, y podrá implementar sus propias soluciones técnicas con lenguaje natural.

Para poder cumplir nuestro objetivo, vamos a hacer uso de distintos servicios de la plataforma Google Cloud para crear tanto la infraestructura necesaria como los distintos componentes tecnológicos para poder sacar todo el valor a la información empresarial.

Antes de comenzar

Antes de comenzar con el desarrollo del artículo, vamos a explicar algunos conceptos básicos sobre los servicios y sobre distintos frameworks de trabajo que vamos a utilizar para la implementación:

  1. Cloud Storage[1]: Es un servicio de almacenamiento en la nube proporcionado por Google Cloud Platform (GCP) que permite a los usuarios almacenar y recuperar datos de manera segura y escalable.
  2. BigQuery[2]: Es un servicio de análisis de datos totalmente administrado que permite realizar consultas SQL en conjuntos de datos masivos en GCP. Es especialmente eficaz para el análisis de datos a gran escala.
  3. Terraform[3]: Es una herramienta de infraestructura como código (IaC) desarrollada por HashiCorp. Permite a los usuarios describir y gestionar la infraestructura utilizando archivos de configuración en el lenguaje HashiCorp Configuration Language (HCL). Con Terraform, puedes definir recursos y proveedores de manera declarativa, facilitando la creación y gestión de infraestructuras en plataformas como AWS, Azure y Google Cloud.
  4. PySpark[4]: Es una interfaz de Python para Apache Spark, un marco de procesamiento distribuido de código abierto. PySpark facilita el desarrollo de aplicaciones de análisis de datos paralelas y distribuidas utilizando la potencia de Spark.
  5. Dataproc[5]: Es un servicio de gestión de clústeres para Apache Spark y Hadoop en GCP que permite ejecutar eficientemente tareas de análisis y procesamiento de datos a gran escala. Dataproc admite la ejecución de código PySpark, facilitando la realización de operaciones distribuidas en grandes conjuntos de datos en la infraestructura de Google Cloud.

Qué es un LLM 

Un LLM (Large Language Model) es un tipo de algoritmo de inteligencia artificial (IA) que utiliza técnicas de deep learning y enormes conjuntos de datos para comprender, resumir, generar y predecir nuevos contenidos. Un ejemplo de LLM podría ser ChatGPT que hace uso del modelo GPT desarrollado por OpenAI. 

En nuestro caso, vamos a hacer uso del modelo Codey[6] (code-bison) que es un modelo implementado por Google que está optimizado para generar código ya que ha sido entrenado para esta especialización que se encuentra dentro del stack de VertexAI[7]

Y no solo es importante el modelo que vamos a utilizar, sino también el cómo lo vamos a utilizar. Con esto, me refiero a que es necesario comprender los parámetros de entrada que afectan directamente a las respuestas que nos dará nuestro modelo, en los que podemos destacar los siguientes:

  • Temperatura (temperature): Este parámetro controla la aleatoriedad en las predicciones del modelo. Una temperatura baja, como 0.1, genera resultados más deterministas y enfocados, mientras que una temperatura alta, como 0.8, introduce más variabilidad y creatividad en las respuestas del modelo.
  • Prefix (Prompt): El prompt es el texto de entrada que se proporciona al modelo para iniciar la generación de texto. La elección del prompt es crucial, ya que guía al modelo sobre la tarea específica que se espera realizar. La formulación del prompt puede influir en la calidad y relevancia de las respuestas del modelo, aunque hay que tener en cuenta la longitud para que cumpla con el  número máximo de tokens de entrada que es 6144.
  • Tokens de salida (max_output_tokens): Este parámetro limita el número máximo de tokens que se generarán en la salida. Controlar este valor es útil para evitar respuestas excesivamente largas o para ajustar la longitud de la salida según los requisitos específicos de la aplicación.
  • Recuento de candidatos (candidate_count): Este parámetro controla el número de respuestas candidatas que el modelo genera antes de seleccionar la mejor opción. Un valor más alto puede ser útil para explorar diversas respuestas potenciales, pero también aumentará el costo computacional.

Desarrollo del prompt

Una vez que hemos definido los parámetros y sabemos bien para qué sirve cada uno de ellos y comprendemos lo que es un prompt, vamos a enfocarnos en cómo utilizarlo e implementar uno que se pueda adaptar a nuestras necesidades.

Como se ha comentado anteriormente, el objetivo es generar tanto código Pyspark como terraform para poder realizar las tareas de creación de infraestructura y tratamiento del dato. Como son tareas totalmente distintas, como primera decisión importante para nuestro prompt se ha optado por dividirlo en dos partes específicas para que cada prompt esté entrenado con ejemplos para generar un lenguaje u otro.

Para cada uno de los prompt, se hace una introducción para especificar cuál va a ser el objetivo y qué peticiones se van a realizar, y después una serie de ejemplos en los que se le da un input en lenguaje natural simulando una petición, y posteriormente también se le da el output deseado para asignar el texto al código específico. El objetivo es generar un prompt estructurado que pueda ser procesado de manera eficiente por el modelo para que en los siguientes casos, pueda asociar los ejemplos que tiene disponibles con respuestas adecuadas.

Vamos a poner en práctica estos pequeños tips para ver una de las entradas al prompt de terraform:

input: I need to read a file named `myfile.csv` inside the folder `data/input` in a bucket called `application-data-input`, and I need to create a new dataset and table in BigQuery called `tst_tf_ai`. The process has to read the file, remove the first three characters of the name, and write the result in BigQuery. The schema of the table will be ‘name’ of String type and ‘surname’ of String type. The infrastructure has to be deployed in the project `project-cloud-223` in GCP, and region `europe-southwest1`.
output: «`hcl
terraform {
 required_version = «>= 0.15»
 required_providers {
  google = «~> 5.0»
 }
}

resource «google_storage_bucket» «temporary_files» { 
 project       = «project-cloud-223» 
 name          = «temporary-files-dataproc» 
 location      = «europe-southwest1» 
 force_destroy = true 
} 

resource «google_storage_bucket» «bucket1» { 
 project       = «project-cloud-223» 
 name          = «application-data-input» 
 location      = «europe-southwest1» 
 force_destroy = true 
} 

resource «google_storage_bucket_object» «folder1» {
 name    = «data/input/»
 bucket  = google_storage_bucket.bucket1.name
 content = » «
}

resource «google_bigquery_dataset» «dataset» { 
 project       = «project-cloud-223» 
 dataset_id    = «tst_tf_ai» 
 friendly_name = «tst_tf_ai» 
 description   = «Description» 
 location      = «europe-southwest1» 
} 

resource «google_bigquery_table» «table» { 
 project              = «project-cloud-223» 
 dataset_id           = google_bigquery_dataset.dataset.dataset_id 
 deletion_protection  = false
 table_id             = «tst_tf_ai» 
 schema               = <<EOF
[ 
 { 
  «name»: «name», 
  «type»: «STRING», 
  «mode»: «NULLABLE», 
  «description»: «The name» 
 }, 
 { 
  «name»: «surname», 
  «type»: «STRING», 
  «mode»: «NULLABLE», 
  «description»: «The surname» 
 }
] 
EOF 
} 
«`

Author Name

Es importante implementar ejemplos lo más parecido posible a tu caso de uso para que las respuestas sean más precisas, y también que tenga bastantes ejemplos con variedad de peticiones para que sea más inteligente a la hora de devolver las respuestas. Una de las prácticas para que sea más interactiva la implementación del prompt, puede ser ir probando con distintas peticiones, y si no es capaz de hacer lo que se le ha pedido, se debería modificar las instrucciones.

Como hemos podido observar, el desarrollo del prompt sí necesitamos conocimientos técnicos para poder traducir las peticiones a código, por lo que esta tarea sí se debería de abordar por una persona técnica para posteriormente evadir a la persona de negocio. En otras palabras, necesitamos que una persona técnica genere la primera base de conocimiento para que luego las personas de negocio puedan hacer uso de este tipo de herramientas.

También se ha podido ver, que la generación de código en terraform es más compleja que la generación en Pyspark, por lo que se han requerido de más ejemplos de entrada en la realización del prompt de terraform para que se ajuste a nuestro caso de uso. Por ejemplo, hemos aplicado en los ejemplos que en terraform siempre cree un bucket temporal (temporary-files-dataproc) para que pueda ser utilizado por Dataproc.

Casos prácticos

Se han realizado tres ejemplos con peticiones distintas, requiriendo más o menos infraestructura y transformaciones para ver si nuestro prompt es lo suficientemente robusto. 

En el archivo ai_gen.py vemos el código necesario para hacer las peticiones y los tres ejemplos, en el que cabe destacar la configuración escogida para los parámetros del modelo:

  • Se ha decidido darle valor 1 a candidate_count para que no tenga más que una respuesta final válida para devolver. Además que como se ha comentado, aumentar este número también lleva aumento de costes.
  • El max_output_tokens se ha decidido 2048 que es el mayor número de tokens para este modelo, ya que si se necesita generar una respuesta con diversas transformaciones, no falle por esta limitación.
  • La temperatura se ha variado entre el código terraform y Pyspark, para terraform se ha optado por 0 para que siempre dé la respuesta que se considera más cercana a nuestro prompt para que no genere más de lo estrictamente necesario para nuestro objetivo. En cambio para Pyspark se ha optado por 0.2 que es una temperatura baja para que no sea muy creativo, pero para que también pueda darnos diversas respuestas con cada llamada para también poder hacer pruebas de rendimiento entre ellas.

Vamos a realizar un ejemplo de petición que está disponible en el siguiente repositorio github, en el que está detallado en el README paso por paso para poder ejecutarlo tú mismo. La petición es la siguiente:

In the realm of ‘customer_table,’ my objective is the seamless integration of pivotal fields such as ‘customer_id’, ‘name’, and ‘email’. These components promise to furnish crucial insights into the essence of our valued customer base.

Conversely, when delving into the nuances of ‘sales_table,’ the envisioned tapestry includes essential elements like ‘order_id’ ‘product’ ‘price’, ‘amount’ and ‘customer_id’. Theseattributes, meticulously curated, will play a pivotal role in the nuanced exploration and analysis of sales-related data.

The ‘bigtable_info’ table will have all the fields resulting from the union of the two tables, ‘customer_table’ and ‘sales_table.’ Here, the outcome of joining the two tables by the ‘customer_id’ numeric field will be stored.

Furthermore, as part of our meticulous data collection strategy, I plan to inaugurate a dedicated Google Cloud Storage bucket christened ‘sales-etl-bucket.’ This repository is strategically designed to serve as a robust container for collating data, particularly hailing from CSV files. This endeavor is set to enhance the efficiency and organizational prowess of our data management processes.

To enhance the structure, two distinct subfolders, ‘input/sales’ and ‘input/customers’ have been ingeniously incorporated within the ‘sales-etl-bucket,’ ensuring a refined organization of the incoming data streams.

You will need to read the CSV files within the ‘input/sales’ folder to write the data into the ‘sales_table’. Additionally, you should perform the same operation with the files from the ‘input/customers’ folder to write the data into the ‘customer_table’. Finally, you are required to perform a join between the sales and customers information based on the ‘customer_id’ number field and write the merged information into the ‘bigtable_info’.

Author Name

Ejecutamos  y vamos a analizar las salidas generadas en las carpetas generated/customers/python/etl.py y generated/terraform/main.tf.:

terraform {
 required_version = ">= 0.15"
 required_providers {
   google = "~> 5.0"
 }
}


resource "google_storage_bucket" "temporary_files" {
 project       = "my-cloud-project"
 name          = "temporary-files-dataproc"
 location      = "europe-southwest1"
 force_destroy = true
}


resource "google_storage_bucket" "sales_etl_bucket" {
 project       = "my-cloud-project"
 name          = "sales-etl-bucket"
 location      = "europe-southwest1"
 force_destroy = true
}


resource "google_storage_bucket_object" "sales_folder" {
 name    = "input/sales/"
 bucket  = google_storage_bucket.sales_etl_bucket.name
 content = " "
}


resource "google_storage_bucket_object" "customers_folder" {
 name    = "input/customers/"
 bucket  = google_storage_bucket.sales_etl_bucket.name
 content = " "
}


resource "google_bigquery_dataset" "raw_sales_data" {
 project       = "my-cloud-project"
 dataset_id    = "raw_sales_data"
 friendly_name = "Raw Sales Data"
 description   = "This dataset contains the raw sales data."
 location      = "europe-southwest1"
}


resource "google_bigquery_table" "customer_table" {
 project              = "my-cloud-project"
 dataset_id           = google_bigquery_dataset.raw_sales_data.dataset_id
 deletion_protection  = false
 table_id             = "customer_table"
 schema               = <<EOF
[
 {
   "name": "customer_id",
   "type": "INT64",
   "mode": "REQUIRED",
   "description": "The customer ID."
 },
 {
   "name": "name",
   "type": "STRING",
   "mode": "NULLABLE",
   "description": "The customer's name."
 },
 {
   "name": "email",
   "type": "STRING",
   "mode": "NULLABLE",
   "description": "The customer's email address."
 }
]
EOF
}


resource "google_bigquery_table" "sales_table" {
 project              = "my-cloud-project"
 dataset_id           = google_bigquery_dataset.raw_sales_data.dataset_id
 deletion_protection  = false
 table_id             = "sales_table"
 schema               = <<EOF
[
 {
   "name": "order_id",
   "type": "INT64",
   "mode": "REQUIRED",
   "description": "The order ID."
 },
 {
   "name": "product",
   "type": "STRING",
   "mode": "NULLABLE",
   "description": "The product name."
 },
 {
   "name": "price",
   "type": "FLOAT64",
   "mode": "NULLABLE",
   "description": "The product price."
 },
 {
   "name": "amount",
   "type": "INT64",
   "mode": "NULLABLE",
   "description": "The product amount."
 },
 {
   "name": "customer_id",
   "type": "INT64",
   "mode": "REQUIRED",
   "description": "The customer ID."
 }
]
EOF
}


resource "google_bigquery_dataset" "master_sales_data" {
 project       = "my-cloud-project"
 dataset_id    = "master_sales_data"
 friendly_name = "Master Sales Data"
 description   = "This dataset contains the master sales data."
 location      = "europe-southwest1"
}


resource "google_bigquery_table" "bigtable_info" {
 project              = "my-cloud-project"
 dataset_id           = google_bigquery_dataset.master_sales_data.dataset_id
 deletion_protection  = false
 table_id             = "bigtable_info"
 schema               = <<EOF
[
 {
   "name": "customer_id",
   "type": "INT64",
   "mode": "REQUIRED",
   "description": "The customer ID."
 },
 {
   "name": "name",
   "type": "STRING",
   "mode": "NULLABLE",
   "description": "The customer's name."
 },
 {
   "name": "email",
   "type": "STRING",
   "mode": "NULLABLE",
   "description": "The customer's email address."
 },
 {
   "name": "order_id",
   "type": "INT64",
   "mode": "REQUIRED",
   "description": "The order ID."
 },
 {
   "name": "product",
   "type": "STRING",
   "mode": "NULLABLE",
   "description": "The product name."
 },
 {
   "name": "price",
   "type": "FLOAT64",
   "mode": "NULLABLE",
   "description": "The product price."
 },
 {
   "name": "amount",
   "type": "INT64",
   "mode": "NULLABLE",
   "description": "The product amount."
 }
]
EOF
}


Vemos que va a añadir un bucket con dos carpetas para poder subir los datos a la carpeta correspondiente dependiendo si es sales o customer. También ha creado dos datasets, uno para la capa de raw para tener los datos según nos han venido de origen con las tablas de customers y sales, y el segundo dataset para la tabla final que almacenará el resultado de juntar la información de ambas tablas.

Vamos a revisar el código pyspark:

from pyspark.sql import SparkSession
from pyspark.sql import functions as F


# Configure Spark session
spark = SparkSession.builder.appName("SalesETL").getOrCreate()


# Define file paths
sales_path = "gs://sales-etl-bucket/input/sales/*.csv"
customers_path = "gs://sales-etl-bucket/input/customers/*.csv"


# Read CSV files into DataFrames
sales_df = spark.read.csv(sales_path, header=True, inferSchema=True)
customers_df = spark.read.csv(customers_path, header=True, inferSchema=True)


# Write tables to BigQuery
sales_df.write.format("bigquery") \
   .option("temporaryGcsBucket", "temporary-files-dataproc") \
   .option("table",  "raw_sales_data.sales_table") \
   .mode("overwrite") \
   .save()
customers_df.write.format("bigquery") \
   .option("temporaryGcsBucket", "temporary-files-dataproc") \
   .option("table",  "raw_sales_data.customer_table") \
   .mode("overwrite") \
   .save()


# Join sales and customers tables
bigtable_info_df = sales_df.join(customers_df, on="customer_id", how="inner")


# Write joined table to BigQuery
bigtable_info_df.write.format("bigquery") \
   .option("temporaryGcsBucket", "temporary-files-dataproc") \
   .option("table",  "master_sales_data.bigtable_info") \
   .mode("overwrite") \
   .save()


# Stop the Spark session
spark.stop()

Se puede observar que el código generado realiza la lectura por cada una de las carpetas e inserta cada dato en su tabla correspondiente. 

Para poder asegurarnos de que el ejemplo está bien realizado, podemos seguir los pasos del README en el repositorio GitHub[8] para aplicar los cambios en el código terraform, subir los ficheros de ejemplo que tenemos en la carpeta example_data y a ejecutar un Batch en Dataproc. 

Finalmente, vemos si la información que se ha almacenado en BigQuery es correcta:

  • Tabla customer:
  • Tabla sales:
  • Tabla final:

De esta forma, hemos conseguido de a través de lenguaje natural, tener un proceso funcional totalmente operativo. Hay otro ejemplo que se puede ejecutar, aunque también animo a hacer más ejemplos, o incluso mejorar el prompt, para poder meterle ejemplos más complejos, y también adaptarlo a tu caso de uso.

Conclusiones y Recomendaciones

Al ser ejemplos muy concretos sobre unas tecnologías tan concretas, cuando se hace un cambio en el prompt en cualquier ejemplo puede afectar a los resultados, o también, modificar alguna palabra de la petición de entrada. Esto se traduce en que el prompt no es lo suficientemente robusto como para poder asimilar distintas expresiones sin afectar al código generado. Para poder tener un prompt y un sistema productivo, se necesita más entrenamiento y distinta variedad tanto de soluciones, peticiones, expresiones,. … Con todo ello, finalmente podremos tener una primera versión que poder presentar a nuestro usuario de negocio para que sea autónomo.

Especificar el máximo detalle posible a un LLM es crucial para obtener resultados precisos y contextuales. Aquí hay varios consejos que debemos tener en cuenta para poder tener un resultado adecuado:

  • Claridad y Concisión:
    • Sé claro y conciso en tu prompt, evitando oraciones largas y complicadas.
    • Define claramente el problema o la tarea que deseas que el modelo aborde.
  • Especificidad:
    • Proporciona detalles específicos sobre lo que estás buscando. Cuanto más preciso seas, mejores resultados obtendrás.
  • Variabilidad y Diversidad:
    • Considera incluir diferentes tipos de ejemplos o casos para evaluar la capacidad del modelo para manejar la variabilidad.
  • Feedback Iterativo:
    • Si es posible, realiza iteraciones en tu prompt basándote en los resultados obtenidos y el feedback del modelo.
  • Prueba y Ajuste:
    • Antes de usar el prompt de manera extensa, realiza pruebas con ejemplos y ajusta según sea necesario para obtener resultados deseados.

Perspectivas Futuras

En el ámbito de LLM, las líneas futuras de desarrollo se centran en mejorar la eficiencia y la accesibilidad de la implementación de modelos de lenguaje. Aquí se detallan algunas mejoras clave que podrían potenciar significativamente la experiencia del usuario y la eficacia del sistema:

1. Uso de distintos modelos de LLM:

La inclusión de una función que permita a los usuarios comparar los resultados generados por diferentes modelos sería esencial. Esta característica proporcionaría a los usuarios información valiosa sobre el rendimiento relativo de los modelos disponibles, ayudándoles a seleccionar el modelo más adecuado para sus necesidades específicas en términos de precisión, velocidad y recursos requeridos.

2. Capacidad de retroalimentación del usuario:

Implementar un sistema de retroalimentación que permita a los usuarios calificar y proporcionar comentarios sobre las respuestas generadas podría ser útil para mejorar continuamente la calidad del modelo. Esta información podría utilizarse para ajustar y refinar el modelo a lo largo del tiempo, adaptándose a las preferencias y necesidades cambiantes de los usuarios.

3. RAG (Retrieval-augmented generation)

RAG (Retrieval-augmented generation) es un enfoque que combina la generación de texto y la recuperación de información para mejorar las respuestas de los modelos de lenguaje. Implica el uso de mecanismos de recuperación para obtener información relevante de una base de datos o corpus textual, que luego se integra en el proceso de generación de texto para mejorar la calidad y la coherencia de las respuestas generadas.

Enlaces de interés

Cloud Storage[1]: https://cloud.google.com/storage/docs

BigQuery[2]: https://cloud.google.com/bigquery/docs

Terraform[3]: https://developer.hashicorp.com/terraform/docs

PySpark[4]: https://spark.apache.org/docs/latest/api/python/index.html

Dataproc[5]: https://cloud.google.com/dataproc/docs

Codey[6]: https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/code-generation

VertexAI[7]: https://cloud.google.com/vertex-ai/docs

GitHub[8]: https://github.com/alfonsozamorac/etl-genai

Tabla de contenidos
  1. Introducción
  2. Antes de comenzar
  3. Qué es un LLM 
  4. Desarrollo del prompt
  5. Casos prácticos

Publicado en: Blog, Practices, Tech

Análisis de vulnerabilidades en contenedores con trivy

marzo 22, 2024 by Bluetab

Análisis de vulnerabilidades en contenedores con trivy

Ángel Maroco

AWS Cloud Architect

Dentro del marco de la seguridad en contenedores, la fase de construcción adquiere vital importancia debido a que debemos seleccionar la imagen base sobre la que ejecutarán las aplicaciones. El no disponer de mecanismos automáticos para el análisis de vulnerabilidades puede desembocar en entornos productivos con aplicaciones inseguras con los riesgos que ello conlleva.

En este artículo cubriremos el análisis de vulnerabilidades a través de la solución Trivy de Aqua Security, pero antes de comenzar, es preciso explicar en qué se basan este tipo de soluciones para identificar vulnerabilidades en las imágenes docker.

Introducción a CVE (Common Vulnerabilities and Exposures)

CVE es una lista de información mantenida por MITRE Corporation cuyo objetivo es centralizar el registro de vulnerabilidades de seguridad conocidas, en la que cada referencia tiene un número de identificación CVE-ID, descripción de la vulnerabilidad, que versiones del software están afectadas, posible solución al fallo (si existe) o como configurar para mitigar la vulnerabilidad y referencias a publicaciones o entradas de foros o blog donde se ha hecho pública la vulnerabilidad o se demuestra su explotación.

El CVE-ID ofrece una nomenclatura estándar para identificar de forma inequívoca una vulnerabilidad. Se clasifican en 5 tipologías, las cuales veremos en la sección Interpretación del análisis. Dichas tipologías son asignadas basándose en diferentes métricas (si tenéis curiosidad, consultad CVSS v3 Calculator)

CVE se ha convertido en el estándar para el registro de vulnerabilidades, por lo que la amplia mayoría de empresas de tecnología y particulares hacen uso de la misma.

Disponemos de múltiples canales para estar informados de todas las novedades referentes a vulnerabilidades: blog oficial, twitter, repositorio cvelist en github o LinkedIn.

Adicionalmente, si queréis información más detallada sobre una vulnerabilidad, podéis consultar la web del NIST, en concreto la NVD (National Vulnerability Database)

Os invitamos a buscar alguna de las siguientes vulnerabilidades críticas, es muy posible que de forma directa o indirecta os haya podido afectar. Os adelantamos que han sido de las más sonadas 🙂

  • CVE-2017-5753
  • CVE-2017-5754

Si detectas una vulnerabilidad, te animamos a registrarla a través del siguiente formulario

Aqua Security – Trivy

Trivy es una herramienta open source enfocada en la detección de vulnerabilidades en paquetes a nivel OS y ficheros de dependencias de distintitos lenguajes:

  • OS packages; (Alpine, Red Hat Universal Base Image, Red Hat Enterprise Linux, CentOS, Oracle Linux, Debian, Ubuntu, Amazon Linux, openSUSE Leap, SUSE Enterprise Linux, Photon OS and Distroless)

  • Application dependencies: (Bundler, Composer, Pipenv, Poetry, npm, yarn and Cargo)

Aqua Security, empresa especializada en el desarrollo de soluciones de seguridad, adquirió trivy en 2019. Junto a un amplio número de colaboradores, son los encargados del desarrollo y mantenimiento de la misma.

Instalación

Trivy dispone de instaladores para la mayor parte de sistemas Linux and macOS. Para nuestras pruebas vamos a utilizar el instalador genérico:

curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/master/contrib/install.sh | sudo sh -s -- -b /usr/local/bin 

Si no queremos persistir el binario en nuestro sistema, disponemos de una imagen docker:

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/trivycache:/root/.cache/ aquasec/trivy python:3.4-alpine 

Operaciones básicas

  • Imágenes locales

Trivy dispone de instaladores para la mayor parte de sistemas Linux and macOS. Para nuestras pruebas vamos a utilizar el instalador genérico:

#!/bin/bash
docker build -t cloud-practice/alpine:latest -<<EOF
FROM alpine:latest
RUN echo "hello world"
EOF

trivy image cloud-practice/alpine:latest 
  • Imágenes remotas
#!/bin/bash
trivy image python:3.4-alpine 
  • Proyectos locales:
    Permite analizar ficheros de dependencias (salidas):
    • Pipfile.lock: Python
    • package-lock_react.json: React
    • Gemfile_rails.lock: Rails
    • Gemfile.lock: Ruby
    • Dockerfile: Docker
    • composer_laravel.lock: PHP Lavarel
    • Cargo.lock: Rust
#!/bin/bash
git clone https://github.com/knqyf263/trivy-ci-test
trivy fs trivy-ci-test 
  • Repositorios públicos:
#!/bin/bash
trivy repo https://github.com/knqyf263/trivy-ci-test 
  • Repositorios de imágenes privados:
    • Amazon ECR (Elastic Container Registry)
    • Docker Hub
    • GCR (Google Container Registry)
    • Repositorios privados con BasicAuth
  • Cache database
    La base de datos de vulnerabilidades se aloja en github. Para evitar descargar dicha base de datos en cada operación de análisis, podemos utilizar el parámetro --cache-dir <dir>:
#!/bin/bash trivy –cache-dir .cache/trivy image python:3.4-alpine3.9 
  • Filtrar por criticidad
#!/bin/bash
trivy image --severity HIGH,CRITICAL ruby:2.4.0 
  • Filtrar vulnerabiliades no resueltas
#!/bin/bash
trivy image --ignore-unfixed ruby:2.4.0 
  • Especificar código de salida
    Esta opción en muy util en el proceso de integración continua, ya que podemos especificar que nuestro pipeline finalice con error cuando se encuentre vulnerabilidad de tipo critical pero las tipo medium y high finalicen correctamente.
#!/bin/bash
trivy image --exit-code 0 --severity MEDIUM,HIGH ruby:2.4.0
trivy image --exit-code 1 --severity CRITICAL ruby:2.4.0 
  • Ignorar vulnerabilidades específicas
    A través del fichero .trivyignore, podemos especificar aquellas CVEs que nos interesa descartar. Puede resultar útil si la imagen contiene una vulnerabilidad que no afecta a nuestro desarrollo.
#!/bin/bash
cat .trivyignore
# Accept the risk
CVE-2018-14618

# No impact in our settings
CVE-2019-1543 
  • Exportar salida en formato JSON:
    Esta opción es interesante si quieres automatizar un proceso antes una salida, visualizar los resultados en un front personalizado o persistir la salida con un formato estructurado.
#!/bin/bash
trivy image -f json -o results.json golang:1.12-alpine
cat results.json | jq 
  • Exportar salida en formato SARIF:
    Existe un estandar llamado SARIF (Static Analysis Results Interchange Format) que define el formato que deben tener las salidas cualquier herramienta de análisis de vulnerabilidades.
#!/bin/bash
wget https://raw.githubusercontent.com/aquasecurity/trivy/master/contrib/sarif.tpl
trivy image --format template --template "@sarif.tpl" -o report-golang.sarif  golang:1.12-alpine
cat report-golang.sarif   

VS Code dispone de la extensión sarif-viewer para la visualización de vulnerabilidades.

Procesos de integración contínua

Trivy dispone de plantillas para las principales soluciones de CI/CD:

  • GitHub Actions
  • Travis CI
  • CircleCI
  • GitLab CI
  • AWS CodePipeline
#!/bin/bash
$ cat .gitlab-ci.yml
stages:
  - test

trivy:
  stage: test
  image: docker:stable-git
  before_script:
    - docker build -t trivy-ci-test:${CI_COMMIT_REF_NAME} .
    - export VERSION=$(curl --silent "https://api.github.com/repos/aquasecurity/trivy/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
    - wget https://github.com/aquasecurity/trivy/releases/download/v${VERSION}/trivy_${VERSION}_Linux-64bit.tar.gz
    - tar zxvf trivy_${VERSION}_Linux-64bit.tar.gz
  variables:
    DOCKER_DRIVER: overlay2
  allow_failure: true
  services:
    - docker:stable-dind
  script:
    - ./trivy --exit-code 0 --severity HIGH --no-progress --auto-refresh trivy-ci-test:${CI_COMMIT_REF_NAME}
    - ./trivy --exit-code 1 --severity CRITICAL --no-progress --auto-refresh trivy-ci-test:${CI_COMMIT_REF_NAME} 

Interpretación del análisis

#!/bin/bash
trivy image httpd:2.2-alpine
2020-10-24T09:46:43.186+0200    INFO    Need to update DB
2020-10-24T09:46:43.186+0200    INFO    Downloading DB...
18.63 MiB / 18.63 MiB [---------------------------------------------------------] 100.00% 8.78 MiB p/s 3s
2020-10-24T09:47:08.571+0200    INFO    Detecting Alpine vulnerabilities...
2020-10-24T09:47:08.573+0200    WARN    This OS version is no longer supported by the distribution: alpine 3.4.6
2020-10-24T09:47:08.573+0200    WARN    The vulnerability detection may be insufficient because security updates are not provided

httpd:2.2-alpine (alpine 3.4.6)
===============================
Total: 32 (UNKNOWN: 0, LOW: 0, MEDIUM: 15, HIGH: 14, CRITICAL: 3)

+-----------------------+------------------+----------+-------------------+------------------+--------------------------------+
|        LIBRARY        | VULNERABILITY ID | SEVERITY | INSTALLED VERSION |  FIXED VERSION   |             TITLE              |
+-----------------------+------------------+----------+-------------------+------------------+--------------------------------+
| libcrypto1.0          | CVE-2018-0732    | HIGH     | 1.0.2n-r0         | 1.0.2o-r1        | openssl: Malicious server can  |
|                       |                  |          |                   |                  | send large prime to client     |
|                       |                  |          |                   |                  | during DH(E) TLS...            |
+-----------------------+------------------+----------+-------------------+------------------+--------------------------------+
| postgresql-dev        | CVE-2018-1115    | CRITICAL | 9.5.10-r0         | 9.5.13-r0        | postgresql: Too-permissive     |
|                       |                  |          |                   |                  | access control list on         |
|                       |                  |          |                   |                  | function pg_logfile_rotate()   |
+-----------------------+------------------+----------+-------------------+------------------+--------------------------------+
| libssh2-1             | CVE-2019-17498   | LOW      | 1.8.0-2.1         |                  | libssh2: integer overflow in   |
|                       |                  |          |                   |                  | SSH_MSG_DISCONNECT logic in    |
|                       |                  |          |                   |                  | packet.c                       |
+-----------------------+------------------+----------+-------------------+------------------+--------------------------------+ 
  • Library: librería/paquete donde se ha identificado la vulnerabilidad.

  • Vulnerability ID: Identificador de vulnerabilidad (según estandar CVE).

  • Severity: existe una clasificación con 5 tipologías [fuente] las cuales tienen asignado una puntuación CVSS (Common Vulnerability Scoring System):

    • Critical (puntuación CVSS 9.0-10.0): fallos que podría aprovechar fácilmente un atacante no autenticado y llegar a comprometer el sistema (ejecución de código arbitrario) sin interacción por parte del usuario.

    • High (puntuación CVSS 7.0-8.9): fallos que podrían comprometer fácilmente la confidencialidad, integridad o disponibilidad de los recursos.

    • Medium (puntuación CVSS 4.0-6.9): fallos que, aún siendo más difíciles de aprovechar, pueden seguir comprometiendo la confidencialidad, integridad o disponibilidad de los recursos en determinadas circunstancias.

    • Low (puntuación CVSS 0.1-3.9): resto de problemas que producen un impacto de seguridad. Son los tipos de vulnerabilidades de los que se considera que su aprovechamiento exige unas circunstancias poco probables o que tendría consecuencias mínimas.

    • Unknow (puntuación CVSS 0.0): se otorga a vulnerabilidades que no tienen asignada puntuación.

  • Installed version: versión instalada en el sistema analizado.

  • Fixed version: versión en la que se resuelve el problema. Si no se informa la versión quiere decir que está pendiente de resolución.

  • Title: Descripción corta de la vulnerabilidad. Para más información, consultar NVD.

Ya sabemos interpretar a alto nivel la información que nos muestra el análisis. Ahora bien, ¿qué acciones debería tomar? En la sección Recomendaciones te damos alguna pista.

Recomendaciones

  • En esta sección describimos algunos aspectos más importantes dentro del ámbito de vulnerabilidades en contenedores:

    • Evitar (en la medida de lo posible) hacer uso de imágenes donde se hayan identificado vulnerabilidades critical y high

    • Incluir el análisis de imágenes en procesos de CI
      La seguridad en tu desarrollo no es opcional, automatiza tus pruebas y no dependas de procesos manuales.

    • Utilizar imágenes ligeras, menos exposiciones:
      Las imágenes tipo Alpine / BusyBox están construidas con el menor número de paquetes posible (la imagen base pesa 5MB), lo que se traduce en una reducción de vectores de ataque. Soportan múltiples arquitecturas y se actualizan con bastante frecuencia.
REPOSITORY  TAG     IMAGE ID      CREATED      SIZE
alpine      latest  961769676411  4 weeks ago  5.58MB
ubuntu      latest  2ca708c1c9cc  2 days ago   64.2MB
debian      latest  c2c03a296d23  9 days ago   114MB
centos      latest  67fa590cfc1c  4 weeks ago  202MB 
Si por algún motivo de dependencias no podéis customizar una imagen base de alpine, buscad imágenes tipo slim de proveedores de software confiables. Además del componente de seguridad, las personas que compartan red contigo lo agradecerán al no tener que bajar imágenes de 1GB
  • Obtener imágenes de repositorios oficiales: Lo recomendable es utilizar DockerHub y preferentemente imágenes de publishers oficiales. DockerHub y CVEs

  • Mantener actualizadas las imágenes En el siguiente ejemplo vemos un análisis sobre dos versiones diferentes de apache:

    Imagen publicada el 11/2018

httpd:2.2-alpine (alpine 3.4.6)
 Total: 32 (UNKNOWN: 0, LOW: 0, MEDIUM: 15, **HIGH: 14, CRITICAL: 3**) 

Imagen publicada el 01/2020

httpd:alpine (alpine 3.12.1)
 Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, **HIGH: 0, CRITICAL: 0**) 

Como podéis observar, si un desarrollo finalizó en 2018 y no se realizan tareas de mantenimiento, podría estar exponiendo un apache relativamente vulnerable. No es un problema derivado del uso de contenedores, pero debido a la versatilidad que nos proporciona docker para testar nuevas versiones de productos, ahora no tenemos excusa.

  • Especial atención a vulnerabilidades que afecten a la capa de aplicación:
    Según el estudio realizado por la compañía edgescan, el 19% de las vulnerabilidades detectadas en 2018 corresponden a capa 7 (Modelo OSI), destacando por encima de todos ataques de tipo XSS (Cross-site Scripting).

  • Seleccionar imágenes latest con especial cuidado:
    Aunque este consejo está muy relacionado con el uso de imágenes ligeras, consideramos hacer un inciso sobre las imágenes latest:

Imagen latest Apache (base alpine 3.12)

httpd:alpine (alpine 3.12.1)
 Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0) 

Imagen latest Apache (base debian 10.6)

httpd:latest (debian 10.6)
 Total: 119 (UNKNOWN: 0, LOW: 87, MEDIUM: 10, HIGH: 22, CRITICAL: 0) 

En ambos casos estamos utilizando la misma versión de apache (2.4.46), la diferencia está en el número de vulnerabilidades críticas.
¿Quiere decir que la imagen basada en debian 10 convierte en vulnerable la aplicación que ejecuta en ese sistema? Puede que si o puede que no, hay que evaluar si las vulnerabilidades pueden comprometer nuestra aplicación. La recomendación es utilizar la imagen de alpine.

  • Evaluar el uso de imágenes docker distroless
    El concepto distroless es de Google y consiste en imágenes docker basadas en debian9/debian10, sin gestores de paquetes, shells ni utilidades. Las imágenes están enfocadas a lenguajes de programación (Java, Python, Golang, Node.js, dotnet y Rust), contiene exclusivamente lo necesario para ejecutar las aplicaciones. Al no disponer de gestores de paquetes, no puedes instalar tus propias dependencias, lo que se puede traducir en una gran ventaja y en otros casos, un gran obstáculo. Realizad pruebas y si encaja con los requisitos de vuestro proyecto, adelante, siempre es beneficioso disponer de alternativas. El mantenimiento corre a cuenta de Google, así que el aspecto de seguridad estará bien acotado.

Ecosistema de analizadores de vulnerabilidades para contenedores

En nuestro caso hemos utilizado trivy ya que se trata de una herramienta open source, fiable, estable y en continua evolución, pero disponemos de multitud de herramientas para el análisis de contenedores:
  • Clair
  • Snyk
  • Anchore Cloud
  • Docker Bench
  • Docker Scan
¿Quieres saber más de lo que ofrecemos y ver otros casos de éxito?
DESCUBRE BLUETAB
Ángel Maroco
AWS Cloud Architect

Ángel Maroco llevo en el sector IT más de una década, iniciando mi carrera profesional con el desarrollo web, pasando una buena etapa en distintas plataformas informacionales en entornos bancarios y los últimos 5 años dedicado al diseño de soluciones en entornos AWS.

En la actualidad, compagino mi papel de arquitecto junto al de responsable de la Pŕactica Cloud /bluetab, cuya misión es impulsar la cultura Cloud dentro de la compañía.

SOLUCIONES, SOMOS EXPERTOS

DATA STRATEGY
DATA FABRIC
AUGMENTED ANALYTICS

Te puede interesar

Una estrategia analítica eficiente

diciembre 13, 2022
LEER MÁS

LakeHouse Streaming en AWS con Apache Flink y Hudi

abril 11, 2023
LEER MÁS

Mi experiencia en el mundo de Big Data – Parte I

octubre 14, 2021
LEER MÁS

Cómo depurar una Lambda de AWS en local

octubre 8, 2020
LEER MÁS

Hashicorp Boundary

diciembre 3, 2020
LEER MÁS

Entrena y Despliega tu Modelo de Machine Learning en 15 Minutos con Databricks

junio 10, 2025
LEER MÁS

Publicado en: Blog, Practices, Tech

  • « Ir a la página anterior
  • Página 1
  • Página 2
  • Página 3
  • Página 4
  • Páginas intermedias omitidas …
  • Página 12
  • Ir a la página siguiente »

Footer

LegalPrivacidadPolítica de cookies
LegalPrivacy Cookies policy

Patrono

Patron

Sponsor

Patrocinador

© 2025 Bluetab Solutions Group, SL. All rights reserved.