Skip to content

Blog

Azure Container Apps en 2025: La Evolución del Serverless para Contenedores

Resumen

Azure Container Apps ha evolucionado significativamente desde su lanzamiento en 2022. Este artículo actualizado explora las capacidades actuales del servicio, las novedades incorporadas en 2024-2025, y cómo se posiciona como la solución ideal para ejecutar aplicaciones nativas de la nube sin la complejidad de gestionar Kubernetes directamente.

TL;DR

  • Azure Container Apps es un servicio serverless que ejecuta contenedores sin gestionar infraestructura, construido sobre Kubernetes, KEDA, Dapr y Envoy
  • Novedades 2024-2025: GPUs serverless, Dynamic Sessions, Azure Functions integradas, workload profiles dedicados con GPUs A100/T4
  • Casos de uso: microservicios, APIs, procesamiento de eventos, cargas AI/ML, aplicaciones con IA generativa
  • Escalado automático (incluso a cero), revisiones, traffic splitting, integración nativa con servicios Azure

El Problema que Resuelve

«Necesito ejecutar aplicaciones Cloud Native en contenedores, pero no quiero la complejidad operativa de Kubernetes, OpenShift, etc.»

Esta es una necesidad recurrente en equipos de desarrollo que quieren aprovechar las ventajas de los contenedores y arquitecturas de microservicios sin dedicar recursos a:

  • Configurar y mantener clusters de Kubernetes
  • Gestionar nodos, redes, almacenamiento
  • Administrar actualizaciones y parches del orquestador
  • Implementar observabilidad y monitorización avanzada desde cero

Azure Container Apps: La Solución Serverless

Azure Container Apps es un servicio gestionado serverless que permite ejecutar contenedores sin preocuparse por la infraestructura subyacente. Lanzado inicialmente en 2022 y con mejoras continuas, se ha convertido en una opción madura para desplegar aplicaciones modernas.

Arquitectura Subyacente

Aunque no gestionas directamente Kubernetes, bajo el telón Azure Container Apps funciona sobre:

  • Azure Kubernetes Service (AKS): proporciona el orquestador
  • KEDA (Kubernetes Event Driven Autoscaling): escalado basado en eventos
  • Dapr (Distributed Application Runtime): integración nativa para microservicios
  • Envoy: proxy para enrutamiento y observabilidad
flowchart TB
  subgraph Internet["Internet / Usuarios"]
    USER["Cliente HTTP/API"]
  end

  subgraph ACA["Azure Container Apps Environment"]
    INGRESS["Ingress (Envoy)"]
    APP1["Container App 1"]
    APP2["Container App 2"]
    APP3["Container App 3"]
    DAPR["Dapr Sidecar"]
    KEDA["KEDA Scaler"]
  end

  subgraph Backend["Servicios Backend"]
    STORAGE["Azure Storage"]
    COSMOSDB["Cosmos DB"]
    SERVICEBUS["Service Bus"]
  end

  USER --> INGRESS
  INGRESS --> APP1
  INGRESS --> APP2
  INGRESS --> APP3
  APP1 --> DAPR
  APP2 --> DAPR
  DAPR --> STORAGE
  DAPR --> COSMOSDB
  SERVICEBUS --> KEDA
  KEDA --> APP3

Características Distintivas

Azure Container Apps se diferencia de otras soluciones de contenedores en Azure por:

  1. Optimización para microservicios: diseñado específicamente para aplicaciones que abarcan múltiples contenedores desplegados como servicios independientes

  2. Tecnologías open-source integradas:

  3. Dapr: service-to-service invocation, pub/sub, state management
  4. KEDA: escalado basado en eventos y métricas
  5. Envoy: balanceo de carga y observabilidad

  6. Arquitecturas event-driven: escalado basado en:

  7. Tráfico HTTP
  8. Mensajes en colas (Service Bus, Storage Queues, Event Hubs)
  9. Métricas personalizadas
  10. Escalado a cero para reducir costes

  11. Soporte para cargas de larga duración: procesos background, jobs y tareas programadas

Novedades 2024-2025: Lo que ha Cambiado

Desde el post original de 2022, Azure Container Apps ha incorporado capacidades empresariales significativas:

1. GPUs Serverless y Dedicadas (2024)

Serverless GPUs disponibles en regiones West US 3, Australia East y Sweden Central:

  • NVIDIA T4: coste-efectivas para inferencia de modelos pequeños (<10GB)
  • NVIDIA A100: para modelos grandes (>10GB), training, y cargas computacionales intensivas

Dedicated GPU workload profiles:

  • Perfiles NC24-A100, NC48-A100, NC96-A100
  • Aislamiento garantizado con hardware dedicado
  • Ideal para cargas de IA/ML continuas con baja latencia
# Ejemplo: Crear environment con GPU serverless
az containerapp env create \
  --name my-gpu-environment \
  --resource-group my-rg \
  --location westus3 \
  --enable-workload-profiles

# Desplegar app con GPU T4
az containerapp create \
  --name my-ai-app \
  --resource-group my-rg \
  --environment my-gpu-environment \
  --image myregistry.azurecr.io/ml-inference:latest \
  --cpu 8 --memory 56Gi \
  --workload-profile-name Consumption-GPU-NC8as-T4 \
  --target-port 8080 \
  --ingress external

2. Dynamic Sessions (Preview - 2024)

Ejecución segura y aislada de código generado por IA, ideal para:

  • Sandboxing de código no confiable
  • Evaluación de código generado por LLMs
  • Agentes de IA que ejecutan código dinámicamente

Características:

  • Aislamiento completo mediante Hyper-V
  • Contenedores gestionados (Python, Node.js) o personalizados
  • Escalado rápido y efímero

3. Azure Functions en Container Apps (GA - 2024)

Despliegue de Azure Functions como contenedores dentro de Container Apps:

  • Todos los triggers de Functions disponibles
  • Escalado basado en KEDA
  • Compartir infraestructura con microservicios y APIs
  • Soporte para GPUs en funciones compute-intensive
# Crear Function App optimizada para Container Apps
az containerapp create \
  --name my-function-app \
  --resource-group my-rg \
  --environment my-environment \
  --image myregistry.azurecr.io/my-functions:latest \
  --kind functionapp \
  --ingress external \
  --target-port 80

4. Workload Profiles Mejorados

Consumption Profile (por defecto): - Escalado automático - Pago solo por uso activo - Hasta 4 vCPU / 8 GiB memoria por réplica

Dedicated Profiles (opcionales): - General purpose (D4, D8, D16, D32) - Memory optimized (E4, E8, E16, E32) - GPU enabled (NC24-A100, NC48-A100, NC96-A100)

5. Networking y Seguridad Avanzada

  • Private Endpoints: acceso privado sin exposición pública
  • User Defined Routes (UDR): control total del tráfico de salida
  • NAT Gateway integration: simplifica conectividad saliente
  • Azure Front Door integration: CDN y WAF con Private Link
  • Client certificate authentication (mTLS): autenticación mutua TLS

6. Certificados Gestionados y Key Vault (GA - 2024)

  • Certificados TLS gratuitos gestionados automáticamente
  • Integración con Azure Key Vault para certificados personalizados
  • Renovación automática

7. Componentes Java Gestionados (Preview - 2024)

Para aplicaciones Spring:

  • Eureka Server: service discovery gestionado
  • Config Server: configuración centralizada
  • Tomcat support: despliegue directo desde código
  • JVM memory fit: configuración automática de memoria JVM

8. Observabilidad Mejorada

  • OpenTelemetry Agent (Preview): exportación de métricas, logs y traces sin configurar colector
  • Aspire Dashboard (Preview): dashboard interactivo para aplicaciones .NET
  • Java metrics: métricas de garbage collection, memoria, threads
  • Integración completa con Azure Monitor y Application Insights

Comparativa: ¿Cuándo Usar Container Apps?

Servicio Caso de Uso Ideal
Azure Container Apps Microservicios, APIs, event-driven apps, cargas AI/ML serverless, aplicaciones con escalado a cero
Azure Kubernetes Service (AKS) Control total de Kubernetes API, workloads complejos con requisitos específicos de K8s
Azure Red Hat OpenShift Despliegue OpenShift gestionado, migración desde on-premises OpenShift
Azure Functions Funciones FaaS puras, integraciones rápidas con triggers Azure, sin contenedores
Web App for Containers Aplicaciones web en contenedores Windows/Linux, migración lift-and-shift
Container Instances Contenedores de corta duración, batch jobs simples, aislamiento por hipervisor
Service Fabric Aplicaciones distribuidas legacy, necesidad de reliable services/actors
Container Registry Almacenamiento, gestión y replicación de imágenes de contenedor

Diagrama de Decisión Simplificado

flowchart TD
  START["¿Necesitas ejecutar contenedores?"]
  START --> K8S_API{"¿Necesitas acceso directo a Kubernetes API?"}

  K8S_API -->|Sí| AKS["Azure Kubernetes Service (AKS)"]
  K8S_API -->|No| SERVERLESS{"¿Prefieres serverless con escalado a cero?"}

  SERVERLESS -->|Sí| MICROSERVICES{"¿Es una arquitectura de microservicios / API?"}
  SERVERLESS -->|No| DEDICATED{"¿Necesitas hardware dedicado/GPU?"}

  MICROSERVICES -->|Sí| ACA["✅ Azure Container Apps"]
  MICROSERVICES -->|No| FUNCTIONS{"¿Solo funciones event-driven?"}

  FUNCTIONS -->|Sí| AZFUNC["Azure Functions"]
  FUNCTIONS -->|No| ACA2["✅ Azure Container Apps"]

  DEDICATED -->|Sí| ACA_DEDICATED["✅ Azure Container Apps
(Dedicated Workload Profiles)"] DEDICATED -->|No| WEBAPP["Web App for Containers"]

Casos de Uso Prácticos

1. Aplicación de IA Generativa con RAG

Implementar un chatbot con Retrieval Augmented Generation:

  • Frontend: contenedor React/Vue en Container App con ingress externo
  • API Gateway: contenedor .NET/Java con autenticación Entra ID
  • RAG Service: contenedor Python con GPU T4 para embeddings y inference
  • Vector Store: Cosmos DB con búsqueda vectorial
  • Escalado basado en peticiones HTTP, escala a cero en inactividad

2. Procesamiento de Eventos IoT

Pipeline de procesamiento de telemetría:

  • Ingestion: Container App escalando con Event Hubs (KEDA scaler)
  • Processing: múltiples Container Apps para transformación, enriquecimiento
  • Storage: escritura en Azure Storage / Cosmos DB mediante Dapr
  • Escalado automático según volumen de mensajes

3. Microservicios con Dapr

Arquitectura de e-commerce:

  • Catalog Service: gestión de productos
  • Order Service: procesamiento de pedidos
  • Inventory Service: control de stock
  • Payment Service: integración con pasarelas de pago

Comunicación via Dapr service invocation, state management en Redis/Cosmos DB, pub/sub con Service Bus.

4. Jobs Programados y Batch Processing

  • Jobs en Container Apps para tareas programadas (cron)
  • Procesamiento de archivos cargados en Storage
  • Generación de informes nocturnos
  • Limpieza de datos y mantenimiento

Despliegue: Ejemplos Prácticos

Despliegue Rápido con Azure CLI

# Variables
RESOURCE_GROUP="my-container-apps-rg"
LOCATION="westeurope"
ENVIRONMENT="my-environment"
APP_NAME="my-api"

# Crear resource group
az group create --name $RESOURCE_GROUP --location $LOCATION

# Crear environment
az containerapp env create \
  --name $ENVIRONMENT \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION

# Desplegar desde imagen pública
az containerapp create \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --environment $ENVIRONMENT \
  --image mcr.microsoft.com/k8se/quickstart:latest \
  --target-port 80 \
  --ingress external \
  --min-replicas 0 \
  --max-replicas 10

Despliegue con Bicep

param location string = resourceGroup().location
param environmentName string = 'my-environment'
param containerAppName string = 'my-api'
param containerImage string = 'mcr.microsoft.com/k8se/quickstart:latest'

resource environment 'Microsoft.App/managedEnvironments@2023-05-01' = {
  name: environmentName
  location: location
  properties: {
    appLogsConfiguration: {
      destination: 'log-analytics'
      logAnalyticsConfiguration: {
        customerId: logAnalytics.properties.customerId
        sharedKey: logAnalytics.listKeys().primarySharedKey
      }
    }
  }
}

resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {
  name: containerAppName
  location: location
  properties: {
    managedEnvironmentId: environment.id
    configuration: {
      ingress: {
        external: true
        targetPort: 80
        transport: 'auto'
      }
    }
    template: {
      containers: [
        {
          name: 'main'
          image: containerImage
          resources: {
            cpu: json('0.5')
            memory: '1Gi'
          }
        }
      ]
      scale: {
        minReplicas: 0
        maxReplicas: 10
        rules: [
          {
            name: 'http-rule'
            http: {
              metadata: {
                concurrentRequests: '100'
              }
            }
          }
        ]
      }
    }
  }
}

resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
  name: '${environmentName}-logs'
  location: location
  properties: {
    sku: {
      name: 'PerGB2018'
    }
  }
}

Despliegue con Dapr Habilitado

# Crear app con Dapr
az containerapp create \
  --name order-service \
  --resource-group $RESOURCE_GROUP \
  --environment $ENVIRONMENT \
  --image myregistry.azurecr.io/order-service:v1 \
  --target-port 3000 \
  --ingress internal \
  --min-replicas 1 \
  --enable-dapr \
  --dapr-app-id order-service \
  --dapr-app-port 3000 \
  --dapr-app-protocol http

# Invocar otro servicio via Dapr
# Desde código: http://localhost:3500/v1.0/invoke/inventory-service/method/check-stock

Administración del Ciclo de Vida: Revisiones

Una de las características más potentes de Container Apps son las revisiones (revisions):

  • Cada cambio en la configuración o imagen crea una nueva revisión
  • Múltiples revisiones activas simultáneamente
  • Traffic splitting: distribuir tráfico entre revisiones (A/B testing, blue/green)
  • Labels: asignar etiquetas (blue, green, canary) para URLs estables

Ejemplo: Blue/Green Deployment

# Desplegar revisión "blue" (producción actual)
az containerapp create \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --environment $ENVIRONMENT \
  --image myregistry.azurecr.io/myapp:v1.0 \
  --revision-suffix blue \
  --ingress external \
  --target-port 80 \
  --revisions-mode multiple

# Fijar 100% tráfico a blue
az containerapp ingress traffic set \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --revision-weight $APP_NAME--blue=100

# Asignar label "blue"
az containerapp revision label add \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --label blue \
  --revision $APP_NAME--blue

# Desplegar revisión "green" (nueva versión)
az containerapp update \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --image myregistry.azurecr.io/myapp:v2.0 \
  --revision-suffix green

# Probar green en URL específica: https://my-app---green.<environment-domain>

# Traffic splitting progresivo: 80% blue, 20% green
az containerapp ingress traffic set \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --revision-weight $APP_NAME--blue=80 $APP_NAME--green=20

# Si green funciona bien, cambiar 100% a green
az containerapp ingress traffic set \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --revision-weight $APP_NAME--green=100

# Desactivar revisión blue
az containerapp revision deactivate \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --revision $APP_NAME--blue

Networking: Opciones y Escenarios

Niveles de Accesibilidad

  1. External ingress: aplicación accesible desde Internet
  2. Internal ingress: solo accesible dentro del environment o VNet
  3. No ingress: para background workers o jobs

Integración con VNet

# Crear environment con VNet personalizada
az containerapp env create \
  --name $ENVIRONMENT \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION \
  --infrastructure-subnet-resource-id /subscriptions/.../subnets/aca-subnet \
  --internal-only false

# Subnet mínimo: /27 (para workload profiles)
# Subnet mínimo: /23 (para consumption only)

Private Endpoints

# Crear environment con private endpoint
az containerapp env create \
  --name $ENVIRONMENT \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION \
  --enable-workload-profiles \
  --public-network-access Disabled

# Crear private endpoint
az network private-endpoint create \
  --name my-private-endpoint \
  --resource-group $RESOURCE_GROUP \
  --vnet-name my-vnet \
  --subnet my-subnet \
  --private-connection-resource-id /subscriptions/.../managedEnvironments/$ENVIRONMENT \
  --group-id managedEnvironment \
  --connection-name my-connection

Observabilidad y Monitorización

Integración con Azure Monitor

Container Apps se integra automáticamente con:

  • Log Analytics: logs de contenedor, system logs
  • Application Insights: telemetría de aplicaciones, distributed tracing
  • Metrics: CPU, memoria, peticiones HTTP, réplicas activas
# Habilitar Application Insights
az containerapp env create \
  --name $ENVIRONMENT \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION \
  --logs-workspace-id <LOG_ANALYTICS_WORKSPACE_ID> \
  --logs-workspace-key <LOG_ANALYTICS_WORKSPACE_KEY>

Consultas Útiles en Log Analytics

// Logs de aplicación
ContainerAppConsoleLogs_CL
| where ContainerAppName_s == "my-api"
| where TimeGenerated > ago(1h)
| project TimeGenerated, Log_s
| order by TimeGenerated desc

// Métricas de réplicas
ContainerAppSystemLogs_CL
| where Category == "ContainerAppScaling"
| where ContainerAppName_s == "my-api"
| project TimeGenerated, ReplicaCount_d
| render timechart

OpenTelemetry (Preview)

# Habilitar agente OpenTelemetry
az containerapp env telemetry app-insights set \
  --name $ENVIRONMENT \
  --resource-group $RESOURCE_GROUP \
  --connection-string "InstrumentationKey=...;IngestionEndpoint=..."

# Las apps envían automáticamente traces, metrics y logs a App Insights

Costes y Optimización

Modelo de Facturación

Consumption Plan:

  • Consumo activo: vCPU-segundos y GiB-segundos consumidos
  • Consumo idle: tarifa reducida cuando réplicas están idle (no procesando, <0.01 vCPU, <1KB/s red)
  • Requests: primeros 2 millones gratis/mes, luego por millón adicional
  • GPUs serverless: sin cargo por idle, solo por uso activo

Dedicated Plan (workload profiles):

  • Cargo fijo por gestión del plan si usas perfiles dedicados
  • Cargo por instancia de perfil (D4, E8, NC24-A100, etc.)
  • Escalado in/out ajusta coste según demanda

Estrategias de Optimización

  1. Escala a cero: configura minReplicas: 0 para apps con tráfico intermitente
  2. Right-sizing: ajusta CPU/memoria a necesidades reales
  3. Workload profiles: agrupa apps similares en el mismo perfil dedicado
  4. Savings Plans: Azure Container Apps elegible para planes de ahorro
  5. GPUs serverless: para cargas AI/ML variables, usa serverless en lugar de dedicado
# Configurar escalado a cero
az containerapp update \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --min-replicas 0 \
  --max-replicas 10 \
  --scale-rule-name http-rule \
  --scale-rule-type http \
  --scale-rule-metadata concurrentRequests=50

Seguridad: Mejores Prácticas

1. Managed Identities

# Habilitar system-assigned identity
az containerapp identity assign \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --system-assigned

# Asignar rol para acceder a Key Vault
IDENTITY_ID=$(az containerapp identity show \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --query principalId -o tsv)

az keyvault set-policy \
  --name my-keyvault \
  --object-id $IDENTITY_ID \
  --secret-permissions get list

2. Secretos

# Añadir secreto
az containerapp secret set \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --secrets db-connection="Server=...;Password=..."

# Referenciar en variable de entorno
az containerapp update \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --set-env-vars "DB_CONNECTION=secretref:db-connection"

3. Autenticación Built-in (EasyAuth)

# Habilitar autenticación con Entra ID
az containerapp auth update \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --enable \
  --action RequireAuthentication \
  --aad-tenant-id <TENANT_ID> \
  --aad-client-id <CLIENT_ID> \
  --aad-client-secret <CLIENT_SECRET>

4. Restricciones de IP

# Limitar acceso por IP
az containerapp ingress access-restriction set \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --rule-name office-network \
  --ip-address 203.0.113.0/24 \
  --action Allow

Conclusión

Azure Container Apps en 2025 es una plataforma madura y completa para ejecutar aplicaciones Cloud Native sin la complejidad de gestionar Kubernetes directamente. Con las incorporaciones de 2024-2025, se ha convertido en una opción viable para:

  • Microservicios y APIs: escalado automático, revisiones, traffic splitting
  • Event-driven architectures: integración con KEDA y múltiples event sources
  • Cargas AI/ML: GPUs serverless y dedicadas, Dynamic Sessions
  • Aplicaciones empresariales: networking avanzado, private endpoints, integración con Azure Functions

¿Cuándo Elegir Container Apps?

, si:

  • Quieres serverless con escalado a cero
  • Necesitas desplegar microservicios o APIs rápidamente
  • Prefieres no gestionar Kubernetes directamente
  • Quieres integración nativa con Dapr, KEDA, Envoy
  • Necesitas GPUs para cargas AI/ML con tráfico variable

No, si:

  • Necesitas acceso completo a Kubernetes API y CRDs
  • Tienes requisitos muy específicos de configuración de K8s
  • Ya tienes inversión significativa en operadores y herramientas K8s personalizadas

En resumen: si no necesitas acceso directo a Kubernetes API y trabajas con aplicaciones Cloud Native, Azure Container Apps es tu servicio en Azure.

Referencias y Recursos


Artículo actualizado en octubre de 2025. Para la versión original de 2022, ver Introducción a Azure Container Apps (Keepler Blog).

Cómo Resolver Divergencias en Git: Sincronizando Ramas Local y Remota

El Problema

Al intentar hacer git pull, te encuentras con el siguiente error:

hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint: 
hint:   git config pull.rebase false  # merge
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only

Este mensaje indica que tu rama local y la rama remota han divergido: ambas tienen commits únicos que la otra no tiene. Git necesita que decidas cómo combinar estos cambios.

¿Por Qué Ocurre?

La divergencia sucede cuando:

  1. Trabajas localmente y realizas commits en tu rama main
  2. Mientras tanto, cambios se fusionan en el remoto (por ejemplo, a través de Pull Requests)
  3. Ambas ramas tienen commits exclusivos que la otra no posee

Ejemplo visual:

Local:   A---B---C---L1
                      ^(tu commit local)
Remote:  A---B---C---R1---R2---R3
                      ^(commits del remoto vía PR)

Análisis: Identificar la Divergencia

Antes de resolver, es crucial entender qué ha divergido.

Paso 1: Sincronizar con el Remoto

git fetch origin main --tags

Este comando descarga los cambios del remoto sin fusionarlos.

Paso 2: Comparar Commits

Verifica qué commits están únicamente en cada lado:

# Commits que tienes localmente pero no están en el remoto
git log origin/main..main --oneline

# Commits que están en el remoto pero no tienes localmente
git log main..origin/main --oneline

Paso 3: Revisar los HEADs

# Ver el commit actual local
git rev-parse HEAD

# Ver el commit actual remoto
git rev-parse origin/main

Ejemplo Real

En nuestro caso, obtuvimos:

--- Commits en local, no en remoto ---
81e3b93 feat: add new feature for data processing

--- Commits en remoto, no en local ---
9d3e3e9 Merge pull request #42 from team/feature/update-docs
285a538 Complete documentation review - all documents validated
000b9cb Fix configuration and add new parameters
a7694d3 Initial implementation plan

Interpretación: El remoto tiene un PR fusionado con 4 commits que no tenemos localmente, y nosotros tenemos 1 commit local que el remoto no tiene.

Estrategias de Resolución

Existen tres estrategias principales:

1. Merge (Recomendado para Trabajo Colaborativo)

Cuándo usarlo: Cuando trabajas con un equipo y quieres preservar toda la historia, incluyendo los merge commits de PRs.

Ventajas: - ✅ Preserva la historia completa (incluidos merge commits) - ✅ Muestra claramente cuándo se integraron features - ✅ Más seguro: no reescribe historia

Desventajas: - ⚠️ Crea un commit de merge adicional - ⚠️ Historia no completamente lineal

Comando:

git merge origin/main --no-edit

Si prefieres revisar/editar el mensaje de merge:

git merge origin/main

2. Rebase (Para Historia Lineal)

Cuándo usarlo: Cuando trabajas solo o en una feature branch que aún no has compartido públicamente.

Ventajas: - ✅ Historia completamente lineal - ✅ Más limpia para revisar con git log

Desventajas: - ⚠️ Reescribe commits locales (cambian sus SHAs) - ⚠️ Puede causar problemas si ya compartiste estos commits - ⚠️ Pierdes el contexto de cuándo se integró el PR remoto

Comando:

git rebase origin/main

3. Fast-Forward Only (Restrictivo)

Cuándo usarlo: Cuando quieres asegurarte de que solo hagas pull si no hay divergencia.

Comando:

git config pull.ff only
git pull

Si hay divergencia, fallará y tendrás que decidir merge o rebase manualmente.

Solución Paso a Paso (Merge)

1. Analizar la Situación

# Sincronizar con remoto
git fetch origin main --tags

# Ver divergencias
echo "--- Commits locales únicos ---"
git log origin/main..main --oneline

echo "--- Commits remotos únicos ---"
git log main..origin/main --oneline

2. Decidir Estrategia

Para equipos colaborativos con PRs, merge es la opción más segura:

git merge origin/main --no-edit

3. Resolver Conflictos (Si Ocurren)

Si hay conflictos, Git te lo indicará:

Auto-merging some-file.md
CONFLICT (content): Merge conflict in some-file.md
Automatic merge failed; fix conflicts and then commit the result.

Pasos para resolver:

a) Abre el archivo con conflictos:

<<<<<<< HEAD
Tu versión local
=======
Versión del remoto
>>>>>>> origin/main

b) Edita manualmente para quedarte con el contenido correcto

c) Marca como resuelto:

git add some-file.md

d) Completa el merge:

git commit -m "Merge origin/main into main"

4. Verificar el Resultado

# Ver el log reciente
git log --oneline --graph -10

Deberías ver algo como:

*   3e1ed57 (HEAD -> main) Merge remote-tracking branch 'origin/main' into main
|\  
| * 9d3e3e9 (origin/main) Merge pull request #42
| * 285a538 Complete documentation review
| * 000b9cb Fix configuration parameters
| * a7694d3 Initial implementation plan
* | 81e3b93 feat: add new feature for data processing
|/  
* d140dce feat: improved monthly workflow

5. Empujar los Cambios

git push origin main

Salida esperada:

Enumerating objects: 15, done.
Counting objects: 100% (12/12), done.
Delta compression using up to 8 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 1.08 KiB | 1.08 MiB/s, done.
Total 7 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5), completed with 4 local objects.
To https://github.com/tu-usuario/tu-repositorio.git
   9d3e3e9..3e1ed57  main -> main

Verificación Post-Merge

Comprobar Archivos Críticos

Si tienes workflows de CI/CD u otros archivos críticos, verifica su integridad:

# Buscar un patrón específico en un archivo
grep -n "specific_pattern" .github/workflows/deploy.yml

# O leer el archivo completo
cat .github/workflows/deploy.yml

Confirmar Sincronización

# Ambos deberían apuntar al mismo commit ahora
git rev-parse HEAD
git rev-parse origin/main

Configuración Permanente

Si quieres establecer una estrategia por defecto para futuros git pull:

Para Merge (Recomendado)

git config pull.rebase false

Para Rebase

git config pull.rebase true

Global (Todos tus Repos)

Añade --global:

git config --global pull.rebase false

Mejores Prácticas

✅ Hacer Fetch Frecuentemente

# Ejecutar cada mañana o antes de empezar a trabajar
git fetch origin

Esto te mantiene informado de cambios remotos sin afectar tu trabajo local.

✅ Trabajar en Feature Branches

En lugar de trabajar directamente en main:

git checkout -b feature/my-feature
# ... hacer commits ...
git push origin feature/my-feature
# Abrir PR en GitHub

Esto evita divergencias en main.

✅ Pull Antes de Push

git fetch origin
git status
# Si hay cambios remotos, decide merge o rebase
git pull
# Ahora puedes pushear
git push

⚠️ Evitar Force Push en Ramas Compartidas

# ❌ NUNCA en main compartido
git push --force origin main

# ✅ OK solo en tus feature branches
git push --force origin feature/my-feature

Casos Especiales

Si Hiciste Rebase por Error y Quieres Revertir

# Ver el reflog (historial de cambios de HEAD)
git reflog

# Volver a un estado anterior
git reset --hard HEAD@{2}

Si Quieres Descartar Tus Commits Locales

# ⚠️ CUIDADO: Esto descarta tus commits locales permanentemente
git reset --hard origin/main

Si Quieres Preservar Cambios Locales Sin Commit

# Guardar cambios temporalmente
git stash

# Sincronizar con remoto
git pull

# Recuperar tus cambios
git stash pop

Resumen: Checklist Rápido

  • Fetch: git fetch origin main --tags
  • Analizar: git log origin/main..main --oneline y git log main..origin/main --oneline
  • Decidir: Merge (preservar historia) vs Rebase (lineal)
  • Ejecutar: git merge origin/main o git rebase origin/main
  • Resolver: Conflictos si los hay
  • Verificar: git log --graph --oneline -10
  • Push: git push origin main
  • Confirmar: Archivos críticos intactos

Conclusión

La divergencia de ramas es un escenario común en equipos colaborativos. La clave está en:

  1. Entender qué ha divergido (análisis con git log)
  2. Elegir la estrategia correcta (merge para equipos, rebase para trabajo local)
  3. Verificar el resultado antes de hacer push

En entornos colaborativos con Pull Requests, merge es generalmente la opción más segura ya que preserva la historia completa y evita reescribir commits que otros pueden estar usando como base.


Referencias

Power BI On-Premises Data Gateway: guía práctica (instalación estándar)

Resumen

Esta entrada explica de forma práctica qué es el Power BI On-Premises Data Gateway Standard, su arquitectura básica, y cómo realizar una instalación estándar y configurarlo para refrescos y conexiones seguras desde el servicio de Power BI. Está orientada a administradores y responsables de plataforma que necesiten conectar fuentes de datos locales a Power BI sin usar soluciones de red avanzadas (no cubre la instalación en Virtual Network Data Gateway ni escenarios sovereign).

¿Qué es el On-Premises Data Gateway?

El On-Premises Data Gateway es un componente que actúa como puente entre los servicios cloud de Microsoft (por ejemplo, Power BI, Power Automate, Power Apps) y tus datos que residen en la red local o en entornos no accesibles públicamente. Proporciona un canal saliente seguro (TLS) para permitir conexiones desde la nube hacia los orígenes de datos on‑premises sin abrir puertos entrantes en tu red.

Principales funciones: - Habilitar refrescos programados de datasets de Power BI. - Soportar consultas en vivo (DirectQuery/Live Connection) hacia orígenes compatibles. - Permitir que flujos y aplicaciones en cloud accedan a bases de datos y servicios internos.

Arquitectura básica

  • Gateway instalado en uno o varios servidores dentro de la red local.
  • El servicio gateway establece conexiones salientes a los endpoints de Microsoft (no requiere inbound).
  • En producción, se recomienda desplegar gateways en modo cluster (alta disponibilidad) y definir data sources centralizados en el panel de administración de Power BI.

Diagrama (simplificado)

flowchart LR
  PB["Power BI Service"]
  AZ["Azure Relay / Service Bus"]
  GW["On-Premises Gateway"]
  DB["Origen de datos"]  
  DB --> GW
  GW --> | TLS saliente | AZ 
  AZ --> PB

Arquitectura: Gateway en cluster (alta disponibilidad)

flowchart LR
  subgraph Cloud["Servicio Cloud"]
    PB["Power BI Service"]
  end

  subgraph Cluster["Cluster de Gateways (HA)"]
    GW1["Gateway - Nodo 1"]
    GW2["Gateway - Nodo 2"]
    GW3["Gateway - Nodo N"]
  end

  subgraph OnPrem["Red On-Premises"]
    DB["(Origen de datos)"]
  end
  AZ["Azure Relay / Service Bus"]


  GW1 --- GW2
  GW2 --- GW3
  AZ --> PB
  Cluster --> | TLS saliente | AZ
  DB --> Cluster


Note

Físicamente el Gateway establece conexiones salientes TLS hacia los servicios de Azure (Azure Service Bus / Azure Relay). Las solicitudes brokered se mantienen gracias a las conexiones salientes iniciadas por el gateway.

Instalación (instalación estándar)

Los pasos siguientes describen una instalación típica y segura de un Gateway estándar:

  1. Descargar el instalador oficial
  2. Descargar el instalador del gateway desde el sitio oficial de Microsoft.

  3. Ejecutar el instalador en el servidor destinado

  4. Ejecuta el instalador con privilegios de administrador.
  5. Acepta los términos y elige la instalación estándar cuando se solicite.

  6. Iniciar sesión y registrar el gateway

  7. Al finalizar la instalación se abrirá un asistente que solicita iniciar sesión con una cuenta organizativa (Entra ID).
  8. Registra el gateway en tu tenant y proporciona un nombre descriptivo para el gateway.

  9. Definir la clave de recuperación

  10. El asistente pedirá que crees una "recovery key". Guárdala en un lugar seguro: es necesaria para migrar o restaurar el gateway.

  11. Elegir cuenta de servicio (opcional)

  12. Puedes ejecutar el servicio con la cuenta de sistema local por defecto o configurar una cuenta de dominio/service account con los permisos mínimos necesarios para acceder a los orígenes de datos.

  13. Verificar conectividad

  14. Asegúrate de que el servidor puede establecer conexiones TLS salientes a los endpoints de Microsoft (comprobar reglas de firewall/proxy si existen).

  15. (Opcional) Agregar nodos al cluster

  16. Para alta disponibilidad, instala el gateway en otro servidor y en lugar de registrar un nuevo gateway selecciona unirte al cluster existente.

Configuración en el servicio Power BI

  1. Abrir el portal de Power BI y acceder a "Manage gateways" (Administrar gateways).
  2. Crear y/o revisar Data Sources dentro del gateway: especifica el tipo de origen (SQL Server, Analysis Services, etc.), cadena de conexión, y credenciales.
  3. En los datasets de Power BI: configurar el dataset para usar el gateway correspondiente y programar refrescos.
  4. Para DirectQuery/Live connection: asegúrate de que el data source esté correctamente configurado y que el usuario tenga permisos adecuados.

Consejos prácticos: - Centraliza la definición de data sources para facilitar el mantenimiento. - Usa credenciales de tipo "service principal" o cuentas administradas cuando el origen lo permita y por seguridad.

Buenas prácticas y seguridad

  • Alta disponibilidad: despliega gateways en cluster para evitar puntos únicos de fallo.
  • Mínimos privilegios: la cuenta que use el gateway solo debería tener los permisos necesarios en los orígenes de datos.
  • Key management: guarda la recovery key en un almacén seguro y documenta el proceso de recuperación.
  • Parches y mantenimiento: aplica actualizaciones del sistema operativo y del gateway según las políticas de tu organización.
  • Monitorización: habilita logs y métricas para detectar problemas de rendimiento y errores en los refrescos.
  • Red y firewall: permite únicamente el tráfico saliente necesario hacia los endpoints de Microsoft y evita abrir puertos entrantes.

Monitorización y diagnóstico

  • Revisa el panel de estado del gateway en Power BI Service para incidentes y estado de los nodos.
  • Examina los registros locales del gateway (ubicación estándar indicada por el instalador) para errores detallados.
  • Utiliza contadores de rendimiento (CPU, memoria, latencia de red) en el servidor para diagnosticar cuellos de botella.
  • Para problemas de refresco: revisa el historial de refrescos del dataset en Power BI y los detalles del error proporcionados por el servicio.

Referencias y lecturas recomendadas

  • Documentación oficial de Microsoft (Power BI - On-premises data gateway): https://learn.microsoft.com/power-bi/connect-data/service-gateway-onprem

Documentar con EPAC

Voy al grano: EPAC tiene una opción muy útil llamada "Document All Assignments" que genera Markdown y CSV con todas las asignaciones de policy. Pero hay dos detalles importantes que conviene saber:

1) Antes no se podían excluir tipos enteros de scope (por ejemplo: todas las subscriptions o resourceGroups) desde la configuración.

2) He subido una PR para solucionarlo: https://github.com/Azure/enterprise-azure-policy-as-code/pull/1056

Aquí lo que cambia, rápido y claro.

Problema

Si usas documentAllAssignments y quieres evitar documentar todo lo que hay a nivel de suscripción o de resource groups, la versión anterior obligaba a listar cada id con skipPolicyAssignments o a procesar el CSV resultante. En entornos grandes eso resulta muy tedioso y genera mucho ruido en los informes.

Qué hace la PR #1056

  • Añade excludeScopeTypes en la configuración de documentAllAssignments. Con esto se puede indicar que no se documenten assignments que estén en subscriptions o en resourceGroups.
  • Añade StrictMode (switch) en los scripts. Por defecto está activado. Si lo desactivas (-StrictMode:$false) el script no aborta cuando falta alguna definición; registra avisos y continúa. Útil en pipelines de prueba.
  • Mejora el parsing y el manejo de skipPolicyAssignments/skipPolicyDefinitions (funcionan mejor con arrays u objetos) y corrige bugs menores (p. ej. convertir markdownMaxParameterLength a entero).

PR: https://github.com/Azure/enterprise-azure-policy-as-code/pull/1056

Antes / Después (ejemplo práctico)

Antes tenías que usar algo así:

{
  "documentAssignments": {
    "documentAllAssignments": [
      {
        "pacEnvironment": "EPAC-Prod",
        "skipPolicyAssignments": [],
        "skipPolicyDefinitions": ["/providers/.../policySetDefinitions/..."]
      }
    ]
  }
}

Después basta con añadir excludeScopeTypes:

{
  "documentAssignments": {
    "documentAllAssignments": [
      {
        "pacEnvironment": "EPAC-Prod",
        "excludeScopeTypes": ["subscriptions", "resourceGroups"],
        "skipPolicyAssignments": [],
        "skipPolicyDefinitions": ["/providers/.../policySetDefinitions/..."]
      }
    ]
  }
}

Y si quieres pruebas rápidas sin que el pipeline falle por referencias rotas:

./Build-PolicyDocumentation.ps1 -StrictMode:$false

Recomendaciones prácticas

  • Usa excludeScopeTypes para reducir ruido cuando necesites una vista global.
  • No confundas excludeScopeTypes con exemptions: esto solo evita que se documente; no evita que la policy se aplique. Para eso usa exemptions.
  • Mantén StrictMode activado en producción (ayuda a detectar referencias rotas).
  • Usa skipPolicyAssignments para exclusiones puntuales que conozcas por id.

Cierre

La mejora es pequeña pero práctica: menos limpieza manual, informes más útiles. Si quieres puedo:

  • Añadir un ejemplo real con IDs/outputs.
  • Hacer build local del sitio y comprobar cómo queda el Markdown final.

PR de referencia: https://github.com/Azure/enterprise-azure-policy-as-code/pull/1056

Analizando VNet Flow Logs en Azure

En este post explico qué son los VNet flow logs (logs de flujo de red de Azure), cómo habilitarlos y cómo analizarlos con un pequeño script PowerShell que desarrollé para facilitar la detección de anomalías y la generación de reportes.

Documentación oficial (Microsoft):

https://learn.microsoft.com/azure/network-watcher/vnet-flow-logs-overview

Resumen rápido

  • Los VNet flow logs capturan información sobre el tráfico IP que atraviesa subredes y recursos dentro de una Virtual Network. Almacenan datos similares a los NSG flow logs pero a nivel de VNet.
  • Se pueden enviar a una cuenta de almacenamiento, a Log Analytics o a Event Hub. El formato JSON resultante contiene un array records con campos que describen cada flujo y sus métricas (bytes, paquetes, acción, puertos, etc.).

Por qué analizarlos

  • Identificar hosts con alto volumen de tráfico.
  • Detectar intentos de escaneo de puertos o reintentos persistentes.
  • Encontrar conexiones denegadas o patrones sospechosos.

Herramienta: script PowerShell

He incluido un script llamado Analyze-VNETFlowLogs.ps1 que procesa archivos JSON con VNet flow logs y genera un análisis en consola. Además puede exportar dos ficheros CSV con el detalle y el resumen del análisis.

(Opcional) Descarga de Flow Logs previa

Si tus logs están aún en la cuenta de almacenamiento, puedes usar el script de apoyo Download-FlowLogs.ps1 para:

  • Descargar todos los blobs del contenedor (por defecto insights-logs-flowlogflowevent).
  • Manejar rutas largas en Windows (hash si usas -AutoShorten).
  • Reorganizar los archivos en una jerarquía YYYY-MM-DD/HH/FlowLog_<timestamp>_*.json.
  • Facilitar un patrón único de entrada para el analizador.

Parámetros clave: - -StorageAccount (obligatorio): Nombre de la storage account. - -ContainerName: Contenedor (default: insights-logs-flowlogflowevent). - -DownloadPath: Carpeta destino local (default: ./FlowLogs). - -AutoShorten: Acorta automáticamente rutas demasiado largas mediante hashing. - -Force: Omite confirmaciones interactivas.

Variables de entorno soportadas: - AZ_STORAGE_KEY: Si está definida se usa esa clave directamente. - AZ_RESOURCE_GROUP: Permite intentar descubrir la key si no se pasó manualmente.

Si no hay clave disponible o el intento de descubrimiento falla, se intentará usar automáticamente --auth-mode login para la autenticación.

Ejemplo de uso completo (descarga + análisis):

# 1. Descargar y organizar
pwsh -File ./Download-FlowLogs.ps1 -StorageAccount mystorageacct -DownloadPath ./FlowLogs -AutoShorten -Force

# 2. Analizar todos los logs resultantes
pwsh -File ./Analyze-VNETFlowLogs.ps1 -LogFiles "./FlowLogs/**/*.json" -ExportCSV -OutputPath ./reports -ShowGraphs

Si ya tienes los JSON en local (por AzCopy u otro método), puedes saltarte el paso 1.

Dónde está el script y ejemplos

Cómo usar el script

  1. Preparar archivos JSON descargados desde la cuenta de almacenamiento o exportados desde Log Analytics.
  2. Abrir PowerShell (Windows) o pwsh (Linux/macOS) y ejecutar (ejemplo):
pwsh -File "./Analyze-VNETFlowLogs.ps1" -LogFiles "./samples/*.json" -ExportCSV -OutputPath "./reports" -ShowGraphs

Explicación rápida de parámetros

  • -LogFiles: rutas a los JSON (acepta wildcards).
  • -ExportCSV: exporta VNetFlowAnalysis_Details_<timestamp>.csv y VNetFlowAnalysis_Summary_<timestamp>.csv.
  • -OutputPath: directorio para los CSV.
  • -SpecificIPs: array de IPs para análisis centrado en hosts concretos.
  • -ShowGraphs: muestra gráficas de barras simples en la consola.

Ejemplo práctico (archivo de ejemplo incluido)

  • He añadido samples/sample-flowlog.json con varios flujos que cubren casos típicos (permitidos, denegados, varios BEGIN para simular reintentos/posible escaneo).
  • Ejecutando el comando anterior sobre ese ejemplo se generan dos CSV de salida en reports/ y se muestra un resumen en consola.

Notas y recomendaciones

  • El script agrupa los flows en memoria para facilitar el análisis; para datasets muy grandes conviene procesar por lotes o filtrar por rango de tiempo antes de ejecutar.
  • Revisa la documentación oficial (enlace arriba) si tu flujo JSON tiene un formato distinto o campos adicionales; la función Parse-FlowTuple del script espera un orden concreto de campos, que puedes adaptar si es necesario.

Contribuciones y siguientes pasos

  • Si quieres, puedo añadir un conjunto de tests que ejecuten el script sobre el ejemplo y verifiquen los CSV generados automáticamente.
  • También puedo crear un pequeño tutorial paso a paso para habilitar VNet flow logs en Azure y obtener los JSON desde una cuenta de almacenamiento.

Archivos incluidos

  • Analyze-VNETFlowLogs.ps1 — script principal.
  • Download-FlowLogs.ps1 — utilidad para descargar y normalizar logs desde la cuenta de almacenamiento.
  • README.md — instrucciones y referencia a la doc oficial.
  • samples/sample-flowlog.json — ejemplo para pruebas.

Espero que esto te ayude a analizar flujos en tus VNets.

Scripts de Reporte para Credenciales Federadas de Azure: Visibilidad Total de tus Identidades Administradas

¡Hola a todos! En el mundo de la seguridad en la nube, mantener un control exhaustivo sobre las credenciales federadas es fundamental para una gestión de identidades robusta. Hoy quiero compartir con vosotros una solución que he desarrollado para resolver uno de los retos más comunes: generar reportes completos de las credenciales federadas de identidades administradas en Azure.

Si habéis trabajado con GitHub Actions, Azure DevOps, o cualquier sistema CI/CD que se integre con Azure usando identidades administradas, sabréis lo importante que es tener visibilidad sobre qué credenciales están configuradas, dónde y cómo.

El Problema: Falta de Visibilidad

Cuando gestionáis múltiples suscripciones de Azure con decenas o cientos de identidades administradas, es muy difícil responder a preguntas básicas como:

  • ¿Qué credenciales federadas tengo configuradas en todas mis suscripciones?
  • ¿Qué repositorios de GitHub tienen acceso a mis recursos de Azure?
  • ¿Hay credenciales obsoletas que debería eliminar?
  • ¿Cómo puedo auditar todas mis configuraciones de identidad federada?

El portal de Azure nos permite ver esto recurso por recurso, pero no hay una vista consolidada que nos permita tener el "big picture" de toda nuestra configuración de seguridad.

La Solución: Scripts de Reporte Automatizados

He desarrollado una solución completa que incluye scripts tanto en Python como en PowerShell para generar reportes detallados de todas las credenciales federadas de identidades administradas en vuestro entorno Azure.

Características Principales

Soporte Multi-Suscripción: Procesa todas las suscripciones disponibles o las que especifiquéis
Filtrado por Tenant: Permite filtrar suscripciones por tenant específico
Múltiples Formatos: Exporta a JSON, CSV y Excel
Logging Robusto: Logs detallados separados de los datos de salida
Validación de Datos: Evita procesar identidades con datos inválidos
Autenticación Flexible: Soporta Managed Identity, Azure CLI, MFA, etc.
Archivo de Tuplas: Genera un archivo adicional con solo las tuplas de credenciales

¿Qué Información Captura?

Los scripts capturan información completa tanto de las identidades administradas como de sus credenciales federadas:

Información de la Identidad: - Nombre y ID de la identidad - Grupo de recursos y ubicación - Principal ID y Client ID - Tenant ID

Información de las Credenciales Federadas: - Nombre e ID de la credencial - Issuer (emisor) - Subject (sujeto) - Audiences (audiencias) - Descripción y tipo

Metadatos del Reporte: - ID y nombre de la suscripción - Tenant ID - Timestamp del reporte

¿Cómo Empezar?

Requisitos Previos

Para Python:

pip install azure-identity azure-mgmt-msi azure-mgmt-resource pandas openpyxl

Para PowerShell:

Install-Module -Name Az.Accounts, Az.ManagedServiceIdentity, Az.Resources, ImportExcel

Ejemplos de Uso

Script de Python:

# Reporte de todas las suscripciones
python federated-identity-credentials-report.py --all-subscriptions --format excel

# Reporte filtrado por tenant
python federated-identity-credentials-report.py --tenant-id "your-tenant-id" --all-subscriptions --format json

# Reporte de una suscripción específica
python federated-identity-credentials-report.py --subscription-id "12345678-1234-1234-1234-123456789012" --format csv

Script de PowerShell:

# Reporte de todas las suscripciones
.\federated-identity-credentials-report.ps1 -AllSubscriptions -Format Excel

# Reporte filtrado por tenant
.\federated-identity-credentials-report.ps1 -TenantId "your-tenant-id" -AllSubscriptions -Format JSON

# Reporte de un grupo de recursos específico
.\federated-identity-credentials-report.ps1 -SubscriptionId "12345678-1234-1234-1234-123456789012" -ResourceGroupName "my-rg" -Format CSV

Características Avanzadas

Archivo de Tuplas de Credenciales

Además del reporte principal, los scripts generan automáticamente un archivo adicional con solo las tuplas de credenciales (credential_issuer, credential_subject, credential_audiences, credential_type). Esto es especialmente útil para:

  • Análisis de patrones de configuración
  • Auditorías de seguridad
  • Integración con otras herramientas de análisis

Logging Separado

Una característica importante es que los logs nunca se mezclan con los datos de salida. Los logs van a stderr y a un archivo de log separado, mientras que los datos puros van a stdout o al archivo especificado. Esto es crucial para la automatización y integración con pipelines de CI/CD.

Validación de Datos

Los scripts incluyen validación robusta para evitar procesar identidades con nombres vacíos o nulos, lo que puede ocurrir en ciertos escenarios de configuración incompleta.

Casos de Uso Reales

1. Auditoría de Seguridad

# Generar reporte completo en Excel para auditoría
python federated-identity-credentials-report.py --all-subscriptions --format excel --output security-audit-$(date +%Y%m%d).xlsx

2. Cleanup de Credenciales Obsoletas

# Exportar a CSV para análisis con herramientas de datos
python federated-identity-credentials-report.py --all-subscriptions --format csv | grep "old-repo-name"

3. Monitoreo Continuo

# Integrar en pipeline de CI/CD para monitoreo continuo
python federated-identity-credentials-report.py --tenant-id "$TENANT_ID" --all-subscriptions --format json > daily-report.json

Estructura de Archivos Generados

Archivo Principal (federated_identity_credentials_report_YYYYMMDD_HHMMSS.json/csv/xlsx):

[
  {
    "identity_name": "github-actions-identity",
    "identity_id": "/subscriptions/.../userAssignedIdentities/github-actions-identity",
    "identity_resource_group": "security-rg",
    "identity_location": "eastus",
    "credential_name": "GitHub-Main-Branch",
    "credential_issuer": "https://token.actions.githubusercontent.com",
    "credential_subject": "repo:myorg/myrepo:ref:refs/heads/main",
    "credential_audiences": "api://AzureADTokenExchange",
    "subscription_name": "Production",
    "tenant_id": "12345678-1234-1234-1234-123456789012",
    "report_timestamp": "2025-07-01T10:30:00"
  }
]

Archivo de Tuplas (credential_tuples_YYYYMMDD_HHMMSS.json/csv/xlsx):

[
  {
    "credential_issuer": "https://token.actions.githubusercontent.com",
    "credential_subject": "repo:myorg/myrepo:ref:refs/heads/main",
    "credential_audiences": "api://AzureADTokenExchange",
    "credential_type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials"
  }
]

Mejores Prácticas de Uso

1. Automatización

Integrad estos scripts en vuestros pipelines de CI/CD para generar reportes automáticos:

# GitHub Actions ejemplo
- name: Generate Federated Credentials Report
  run: |
    python federated-identity-credentials-report.py --all-subscriptions --format json --output report-${{ github.run_number }}.json

- name: Upload Report as Artifact
  uses: actions/upload-artifact@v3
  with:
    name: federated-credentials-report
    path: report-*.json

2. Monitoreo Regular

Ejecutad los scripts de forma regular (diaria o semanal) para detectar cambios no autorizados:

# Cron job ejemplo
0 6 * * 1 /usr/bin/python3 /path/to/federated-identity-credentials-report.py --all-subscriptions --format excel --output /reports/weekly-$(date +\%Y\%m\%d).xlsx

3. Análisis de Drift

Comparad reportes de diferentes fechas para detectar cambios de configuración:

# Comparar reportes para detectar cambios
diff <(jq -S . report-20250701.json) <(jq -S . report-20250708.json)

Consideraciones de Seguridad

⚠️ Permisos Mínimos: Los scripts requieren permisos de lectura sobre las identidades administradas y sus credenciales federadas
⚠️ Datos Sensibles: Los reportes contienen información de configuración sensible - almacenadlos de forma segura
⚠️ Logs: Revisad los logs regularmente para detectar errores de autenticación o acceso

Conclusión

Tener visibilidad completa sobre las credenciales federadas de vuestras identidades administradas es fundamental para mantener una postura de seguridad sólida en Azure. Estos scripts os permitirán:

  • Reducir el riesgo de seguridad mediante auditorías regulares
  • Cumplir con requisitos de compliance generando reportes detallados
  • Optimizar la gestión identificando credenciales obsoletas o mal configuradas
  • Automatizar el monitoreo integrando los scripts en vuestros procesos existentes

Los scripts están disponibles en mi repositorio y son completamente gratuitos y de código abierto. Si os resultan útiles, no dudéis en contribuir con mejoras o reportar issues.

¡Espero que esta herramienta os ayude a mantener vuestros entornos Azure más seguros y mejor documentados!

Enlaces útiles: - 📖 Documentación completa y scripts


Os presento inventariographdrawio: De vuestro Azure a un Diagrama, Automáticamente

¡Hola a todos! Como muchos profesionales que trabajáis día a día con la nube, seguro que os habéis enfrentado al mismo reto que yo una y otra vez: mantener una documentación visual de la infraestructura que sea fiel a la realidad. Dibujar diagramas a mano es tedioso y, peor aún, quedan obsoletos casi al instante.

Cansado de esta tarea manual y de la eterna duda de si un diagrama reflejaba o no el estado real de los recursos, decidí que tenía que haber una forma mejor de hacerlo.

Por eso, hoy quiero presentaros con mucha ilusión un proyecto personal en el que he estado trabajando: inventariographdrawio.

¿Qué es inventariographdrawio?

Es una herramienta de línea de comandos que he creado para solucionar este problema de raíz. Se conecta a una suscripción de Microsoft Azure, analiza los recursos que tienes desplegados y genera automáticamente un diagrama limpio y organizado en formato Draw.io (diagrams.net).

En pocas palabras, es mi solución para pasar de la infraestructura real en Azure a un diagrama editable, sin esfuerzo y en segundos.

¿Por qué lo creé? (Mis Objetivos Principales)

Cuando empecé a desarrollar esta herramienta, tenía varios objetivos en mente:

  1. Ahorrar tiempo: Mi primer objetivo era eliminar las horas que todos perdemos en tareas de documentación repetitivas. Quería que el análisis y el dibujo lo hiciera una máquina, para poder dedicar mi tiempo a lo que de verdad importa: diseñar y mejorar la arquitectura.
  2. Tener una fuente de la verdad: Necesitaba un diagrama en el que pudiera confiar. Con inventariographdrawio, el resultado es un reflejo exacto de lo que hay desplegado, perfecto para auditorías, revisiones o para explicarle la arquitectura a un nuevo compañero.
  3. Mejorar la visibilidad: A veces, en el portal de Azure es difícil ver el "big picture". Representar los recursos de forma gráfica me ayuda a entender las dependencias y la estructura general de un solo vistazo.
  4. Enfocarme en Azure: Decidí centrarme exclusivamente en Azure para poder ofrecer un buen nivel de detalle y precisión en los recursos y servicios específicos de la plataforma, que es donde trabajo principalmente.

¿Cómo podéis empezar a usarlo?

He intentado que sea lo más sencillo posible. Solo tenéis que seguir estos pasos:

  1. Clonar el repositorio:

    git clone https://github.com/rfernandezdo/inventariographdrawio.git
    cd inventariographdrawio
    
  2. Instalar las dependencias: La herramienta tiene unas pocas dependencias que podéis instalar fácilmente (revisad el fichero README.md para las instrucciones exactas).

  3. Configurar el acceso a Azure: Aseguraos de tener vuestra sesión de Azure activa (por ejemplo, con az login desde Azure CLI) para que la herramienta pueda autenticarse y leer los recursos.

  4. Ejecutar y ¡listo! Lanzad el script y veréis cómo aparece un nuevo fichero .drawio en la carpeta del proyecto, listo para abrir y editar.

Aquí un ejemplo navegable de un diagrama de Azure con iconos, creado con draw.io y exportado como un enlace para visualizarlo directamente en el navegador, es navegable:

Microsoft Entra Domain Services con Replica Set en una vpn Vnet2Vnet

El futuro

Este es solo el comienzo del proyecto. Mi idea es seguir ampliándolo para que sea compatible con más servicios de Azure y añadir nuevas funcionalidades que lo hagan aún más útil.

Al ser un proyecto de código abierto, cualquier ayuda es bienvenida. Si os animáis, podéis abrir issues con sugerencias o incluso enviar vuestros propios pull requests.

Espero de corazón que esta herramienta os resulte útil y os ahorre tanto tiempo como a mí.

¡Gracias por leer!

Streamline Your Workflow: Activate All Your PIM Roles with a Single Script Using the JAz.PIM Module

For professionals working with Azure, Privileged Identity Management (PIM) is a cornerstone of robust security hygiene. PIM enables just-in-time access to privileged roles, but manually activating multiple roles each morning can quickly become a repetitive and time-consuming task.

Fortunately, the PowerShell community provides powerful tools to automate such processes. This article introduces a script leveraging the JAz.PIM module, an excellent solution developed by Justin Grote, to simplify and accelerate role activation.

While the script is straightforward, its effectiveness is remarkable.

# Check if the JAz.PIM module is installed; if not, install it
if (-not (Get-module -ListAvailable -Name JAz.PIM)) {
    Install-Module -Name JAz.PIM -Force -Scope CurrentUser
}

# Import the JAz.PIM module if it is not already loaded in the session
if (-not (Get-module -Name JAz.PIM)) {
    Import-module JAz.PIM
}

# Verify Azure login status; if not logged in, initiate login
if (-not (Get-AzContext)) {
    Connect-AzAccount
}

# Set the default activation duration for roles to 8 hours
$PSDefaultParameterValues['Enable-JAz*Role:Hours'] = 8

# Retrieve and activate all eligible roles (Azure Resource and/or Azure AD roles)
Get-JAzRole | Enable-JAzRole -Justification "Administrative task"

This script ensures the JAz.PIM module is installed, connects to Azure if necessary, and activates all your eligible roles in a single command.

Key components: * Get-JAzRole: This cmdlet from the JAz.PIM module retrieves all roles for which you are eligible. * Enable-JAzRole: This command processes each role in the list, submitting an activation request with the specified justification.

Notably, JAz.PIM can manage both Azure Resource roles (Owner, Contributor, etc.) and Azure AD roles (Global Administrator, etc.).

Conclusion

Automation is essential for optimizing daily administrative tasks. This script, powered by the community-driven JAz.PIM module, exemplifies how a manual, repetitive process can be transformed into a quick and efficient command. Adopting such tools not only saves time but also helps maintain PIM security best practices with minimal friction.

If you found this article helpful, consider sharing it with your colleagues and continue exploring the capabilities of PowerShell and Azure. Your time is valuable—make every second count.

For more information about the JAz.PIM module, visit its GitHub repository.

How to set consistent naming in cloud with Azure Naming Tool and Terraform

Consistent naming across cloud resources is crucial for maintainability, clarity, and compliance. The Azure Naming Tool is a powerful tool that helps you define and enforce naming conventions for Azure resources. In this post, we will explore how to use the Azure Naming Tool in conjunction with Terraform to ensure consistent naming across your cloud infrastructure.

What is the Azure Naming Tool?

The Azure Naming Tool is an open-source project that provides a framework for defining and enforcing naming conventions for Azure resources. It allows you to create a set of rules that can be applied to various resource types, ensuring that all resources follow a consistent naming pattern. This is particularly useful in large organizations where multiple teams may be creating resources independently.

Really, the Azure Naming Tool is not only for Azure, it can be used for any cloud provider, as it is a generic tool that can be adapted to different environments if you define the rules correctly. You have the option Resource Type Editing documentation that allows you to define the rules for each resource type or create your own custom resource types, for AWS, GCP, or any other cloud provider.

Why Use Consistent Naming?

Consistent naming is essential for several reasons:

  • Clarity: Clear and consistent names make it easier to understand the purpose of each resource.
  • Maintainability: When resources are named consistently, it simplifies management and reduces the risk of errors.
  • Compliance: Many organizations have compliance requirements that mandate specific naming conventions for resources.
  • Automation: Consistent naming allows for easier automation and scripting, as you can predict resource names based on their types and roles.

What is the problem?

The problem with naming is the interfaces that we use to create resources, Azure Naming Tool portal is a great tool to define the rules, but it is not integrated with Terraform, so we need another way to apply the rules defined in the Azure Naming Tool to our Terraform code.

Solution

To solve the problem of integrating the Azure Naming Tool with Terraform, I created a Terraform module that allows you to use the naming rules defined in the Azure Naming Tool directly in your Terraform code. This module post a request to the Azure Naming Tool API to get the name of the resource based on the rules defined in the Azure Naming Tool.

This example shows how to use the module to create a resource group with a name generated by the Azure Naming Tool based on the rules defined in the Azure Naming Tool portal. The module uses the data.external and data.http resources to call the Azure Naming Tool API and get the name of the resource.

terraform apply -auto-approve
module.azurenamingtool.data.external.aad_token: Reading...
module.azurenamingtool.data.external.aad_token: Read complete after 0s [id=-]
module.azurenamingtool.data.http.name_generation_post: Reading...
module.azurenamingtool.data.http.name_generation_post: Read complete after 1s [id=https://azurenamingtool.azurewebsites.net/api/ResourceNamingRequests/RequestName]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # azurerm_resource_group.example will be created
  + resource "azurerm_resource_group" "example" {
      + id       = (known after apply)
      + location = "westeurope"
      + name     = "rg-spa-dev-auc-025"
      + tags     = {
          + "environment" = "example"
          + "project"     = "azurenamingtool"
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + generated_name = "rg-spa-dev-auc-025"
azurerm_resource_group.example: Creating...
azurerm_resource_group.example: Still creating... [00m10s elapsed]
azurerm_resource_group.example: Creation complete after 16s [id=/subscriptions/000000-0000-0000-0000-000000000000/resourceGroups/rg-spa-dev-auc-025]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

generated_name = "rg-spa-dev-auc-025"

You can check the module in the Terraform Registry.

Conclusion

Using the Azure Naming Tool in conjunction with Terraform allows you to enforce consistent naming conventions across your cloud resources. By integrating the Azure Naming Tool API into your Terraform workflows, you can automate the naming process and ensure that all resources follow the defined rules. This not only improves clarity and maintainability but also helps meet compliance requirements.

Enjoy the benefits of consistent naming in your cloud infrastructure with the Azure Naming Tool and Terraform!

Azure Virtual Network Manager: Illustrative relationship between components

graph TD
    subgraph "Azure Scope"
        MG["Management Group / Subscription"]
    end
    subgraph "Azure Virtual Network Manager (AVNM)"
        AVNM_Instance["AVNM Instance"] -- Manages --> MG
        AVNM_Instance -- Contains --> NG1["Network Group A (e.g., Production)"]
        AVNM_Instance -- Contains --> NG2["Network Group B (e.g., Test)"]
    end
    subgraph "Virtual Networks (VNets)"
        VNet1["VNet 1"]
        VNet2["VNet 2"]
        VNet3["VNet 3"]
        VNet4["VNet 4"]
    end
    subgraph "Membership"
        Static["Static Membership"] -- Manually Adds --> NG1
        Static -- Manually Adds --> NG2
        VNet1 -- Member Of --> Static
        VNet4 -- Member Of --> Static
        Dynamic["Dynamic Membership (Azure Policy)"] -- Automatically Adds --> NG1
        Dynamic -- Automatically Adds --> NG2
        Policy["Azure Policy Definition (e.g., 'tag=prod')"] -- Defines --> Dynamic
        VNet2 -- Meets Policy --> Dynamic
        VNet3 -- Meets Policy --> Dynamic
    end
    subgraph "Configurations"
        ConnConfig["Connectivity Config (Mesh / Hub-Spoke)"] -- Targets --> NG1
        SecConfig["Security Admin Config (Rules)"] -- Targets --> NG1
        SecConfig2["Security Admin Config (Rules)"] -- Targets --> NG2
    end
    subgraph "Deployment & Enforcement"
        Deploy["Deployment"] -- Applies --> ConnConfig
        Deploy -- Applies --> SecConfig
        Deploy -- Applies --> SecConfig2
        NG1 -- Receives --> ConnConfig
        NG1 -- Receives --> SecConfig
        NG2 -- Receives --> SecConfig2
        VNet1 -- Enforced --> NG1
        VNet2 -- Enforced --> NG1
        VNet3 -- Enforced --> NG1
        VNet4 -- Enforced --> NG2
    end
    %% Removed 'fill' for better dark mode compatibility, kept colored strokes
    classDef avnm stroke:#f9f,stroke-width:2px;
    classDef ng stroke:#ccf,stroke-width:1px;
    classDef vnet stroke:#cfc,stroke-width:1px;
    classDef config stroke:#ffc,stroke-width:1px;
    classDef policy stroke:#fcc,stroke-width:1px;
    class AVNM_Instance avnm;
    class NG1,NG2 ng;
    class VNet1,VNet2,VNet3,VNet4 vnet;
    class ConnConfig,SecConfig,SecConfig2 config;
    class Policy,Dynamic,Static policy;

Diagram Explanation

  1. Azure Scope: Azure Virtual Network Manager (AVNM) operates within a defined scope, which can be a Management Group or a Subscription. This determines which VNets AVNM can "see" and manage.
  2. AVNM Instance: This is the main Azure Virtual Network Manager resource. Network groups and configurations are created and managed from here.
  3. Network Groups:
    • These are logical containers for your Virtual Networks (VNets).
    • They allow you to group VNets with common characteristics (environment, region, etc.).
    • A VNet can belong to multiple network groups.
  4. Membership: How VNets are added to Network Groups:
    • Static Membership: You add VNets manually, selecting them one by one.
    • Dynamic Membership: Uses Azure Policy to automatically add VNets that meet certain criteria (like tags, names, locations). VNets matching the policy are dynamically added (and removed) from the group.
  5. Virtual Networks (VNets): These are the Azure virtual networks that are being managed.
  6. Configurations: AVNM allows you to apply two main types of configurations to Network Groups:
    • Connectivity Config: Defines how VNets connect within a group (or between groups). You can create topologies like Mesh (all connected to each other) or Hub-and-Spoke (a central VNet connected to several "spoke" VNets).
    • Security Admin Config: Allows you to define high-level security rules that apply to the VNets in a group. These rules can override Network Security Group (NSG) rules, enabling centralized and mandatory security policies.
  7. Deployment & Enforcement:

    • The created configurations (connectivity and security) must be Deployed.
    • During deployment, AVNM translates these configurations and applies them to the VNets that are members of the target network groups in the selected regions.
    • Once deployed, the VNets within the groups receive and apply (Enforced) these configurations, establishing the defined connections and security rules.

    And maybe this post will be published in the official documentation of Azure Virtual Network Manager, who knows? 😉