La lección anterior dejó una regla clara: una aplicación que escala horizontalmente no puede guardar nada en su disco local. Y Contoso Airlines genera un fichero por cada venta: la tarjeta de embarque en PDF. Ese fichero tiene que vivir en algún sitio al que lleguen todas las instancias, que aguante millones de objetos, que sea barato y que permita dar al cliente un enlace de descarga sin abrir el almacén entero a internet.

Ese sitio es Azure Storage. En el módulo 1 ya creaste la cuenta sttarjetascontosodev con su contenedor tarjetas-embarque, HTTPS obligatorio y acceso anónimo desactivado, pero dejaste aplazada una decisión importante: qué redundancia usar en desarrollo y cuál en producción. Esta lección recoge ese cabo suelto y lo cierra.

Aprenderás qué son los cuatro servicios que caben en una cuenta de almacenamiento, cómo funciona Blob Storage en detalle (tipos de blob, niveles de acceso y reglas de ciclo de vida), para qué sirven Azure Files, Queue Storage y Table Storage, cómo se protege el acceso con firmas de acceso compartido e identidades, y qué herramientas usar en cada caso. Al final montarás el flujo real de Contoso: subir una tarjeta de embarque, generar un enlace temporal para el pasajero y programar que el fichero se abarate solo con el tiempo.

Aviso de coste: el almacenamiento se factura por GB al mes, por operaciones y por salida de datos. Los ejemplos de esta lección mueven kilobytes y cuestan céntimos, pero las cuentas de almacenamiento olvidadas se acumulan. Al final tienes la limpieza.

Contenido

  1. La cuenta de almacenamiento: un recurso, cuatro servicios
  2. Blob Storage: contenedores y tipos de blob
  3. Niveles de acceso: Hot, Cool, Cold y Archive
  4. Reglas de ciclo de vida: las tarjetas de embarque de Contoso
  5. Azure Files: el recurso compartido de la oficina
  6. Queue Storage: desacoplar la emisión de tarjetas
  7. Table Storage y su relación con Cosmos DB
  8. Redundancia: LRS, ZRS, GRS, GZRS y RA-GRS
  9. Seguridad de acceso: claves, SAS e identidades
  10. Cifrado, versionado, instantáneas y eliminación temporal
  11. Herramientas: az storage, AzCopy y Storage Explorer
  12. Ejemplo completo: la tarjeta de embarque de principio a fin
  13. Limpieza
  14. Errores Comunes y Consejos
  15. Ejercicios
  16. Conclusión

  1. La cuenta de almacenamiento: un recurso, cuatro servicios

Una cuenta de almacenamiento es el contenedor de facturación, seguridad y configuración de hasta cuatro servicios de datos distintos, cada uno con su propio punto de conexión:

Servicio Para qué sirve Punto de conexión
Blob Objetos no estructurados: PDF, imágenes, copias, registros https://<cuenta>.blob.core.windows.net
File Recursos compartidos de red por SMB o NFS https://<cuenta>.file.core.windows.net
Queue Colas de mensajes sencillas para desacoplar procesos https://<cuenta>.queue.core.windows.net
Table Almacén NoSQL de clave-valor, muy barato https://<cuenta>.table.core.windows.net

Al crear la cuenta eliges dos cosas que condicionan todo lo demás:

Decisión Opciones Qué implica
Tipo de cuenta StorageV2 (uso general v2), BlockBlobStorage (premium para blobs), FileStorage (premium para archivos) StorageV2 es la opción por defecto y la correcta salvo necesidad específica
Rendimiento Standard (HDD por detrás) o Premium (SSD, latencia baja) Standard admite los cuatro servicios; Premium se especializa por tipo

Y una restricción que sorprende a todos: el nombre de la cuenta es globalmente único, entre 3 y 24 caracteres, solo minúsculas y números. Nada de guiones. Por eso las cuentas de Contoso se llaman sttarjetascontosodev y sttarjetascontosopro y no siguen el patrón con guiones del resto de recursos.

Recordatorio de lo creado en el módulo 1, con el comando completo por si necesitas rehacerlo:

az storage account create \
  --resource-group rg-contoso-reservas-dev \
  --name sttarjetascontosodev \
  --location westeurope \
  --sku Standard_LRS \
  --kind StorageV2 \
  --https-only true \
  --min-tls-version TLS1_2 \
  --allow-blob-public-access false \
  --tags entorno=desarrollo proyecto=contoso-reservas \
         centro-coste=CC-1042 [email protected] \
  --output table

--allow-blob-public-access false es la línea que impide que nadie pueda abrir un contenedor al público por error. Con ella activada a nivel de cuenta, ninguna configuración de contenedor puede exponer los ficheros anónimamente.

  1. Blob Storage: contenedores y tipos de blob

La jerarquía de Blob Storage tiene tres niveles y no más:

Cuenta de almacenamiento (sttarjetascontosopro)
└── Contenedor (tarjetas-embarque)
    └── Blob (2026/08/IB3241-20260814-A7K2.pdf)

No existen carpetas reales: lo que parece una jerarquía son nombres de blob con barras. Las herramientas la muestran como si fuera un árbol, pero para el servicio es un nombre plano. Esto tiene una consecuencia práctica útil: puedes listar «una carpeta» con un prefijo, y es una operación eficiente.

Los tres tipos de blob

Tipo Cómo funciona Tamaño máximo Casos de uso
En bloques (block) Se compone de bloques que se suben en paralelo y se confirman ~190 TiB El 95 % de los casos: PDF, imágenes, vídeo, copias, ZIP
De anexos (append) Solo permite añadir al final; optimizado para escritura secuencial ~195 GiB Registros de auditoría, ficheros de log
De páginas (page) Acceso aleatorio por páginas de 512 bytes 8 TiB Discos de VM (los discos gestionados son blobs de páginas por debajo)

Para las tarjetas de embarque de Contoso: blobs en bloques, sin duda.

Operaciones básicas con la CLI

CUENTA="sttarjetascontosodev"
CONTENEDOR="tarjetas-embarque"

# Crear el contenedor. --auth-mode login usa tu identidad de Entra ID
# en lugar de la clave de la cuenta: es la forma recomendada.
az storage container create \
  --account-name "${CUENTA}" \
  --name "${CONTENEDOR}" \
  --auth-mode login \
  --public-access off \
  --output table

# Subir una tarjeta de embarque.
az storage blob upload \
  --account-name "${CUENTA}" \
  --container-name "${CONTENEDOR}" \
  --name "2026/08/IB3241-20260814-A7K2.pdf" \
  --file ./tarjeta.pdf \
  --content-type "application/pdf" \
  --auth-mode login \
  --overwrite

# Listar las tarjetas de agosto de 2026 usando el prefijo.
az storage blob list \
  --account-name "${CUENTA}" \
  --container-name "${CONTENEDOR}" \
  --prefix "2026/08/" \
  --auth-mode login \
  --query "[].{Nombre:name, Bytes:properties.contentLength, Nivel:properties.blobTier}" \
  --output table

Fíjate en --content-type "application/pdf": sin él, el navegador puede descargar el fichero en lugar de mostrarlo. Es un detalle pequeño que genera muchas incidencias de soporte.

Consejo de diseño del nombre: 2026/08/IB3241-20260814-A7K2.pdf incluye año, mes, vuelo, fecha y localizador. Ese esquema permite listar por periodo con prefijos y aplicar reglas de ciclo de vida por carpeta. Un nombre plano tipo tarjeta12345.pdf funciona igual de bien para leer, pero te deja sin herramientas para gestionar el ciclo de vida.

  1. Niveles de acceso: Hot, Cool, Cold y Archive

Aquí está el mecanismo con el que Azure Storage se abarata de verdad. Cada blob tiene un nivel de acceso que intercambia coste de almacenamiento por coste y tiempo de recuperación.

Nivel Coste de almacenamiento Coste de acceso Permanencia mínima Disponibilidad Uso previsto
Hot El más alto El más bajo Ninguna Inmediata Datos en uso activo
Cool ~50 % menos que Hot Mayor por operación y por GB leído 30 días Inmediata Datos de los últimos meses, acceso ocasional
Cold Menor que Cool Mayor que Cool 90 días Inmediata Datos que casi no se tocan pero deben estar disponibles ya
Archive El más bajo, con diferencia El más alto, y con espera 180 días Requiere rehidratación: de 1 a 15 horas Retención legal, copias históricas

Cuatro reglas que evitan sustos:

  1. La permanencia mínima se factura aunque borres antes. Si subes un blob a Cool y lo borras a los 3 días, pagas los 30. Cambiar de nivel demasiado pronto también cuenta como borrado anticipado.
  2. Archive no se lee. Un blob en Archive está fuera de línea: hay que rehidratarlo (az storage blob set-tier --rehydrate-priority High) y esperar horas. No sirve para nada que un cliente pueda pedir en caliente.
  3. El nivel se aplica por blob, aunque la cuenta tenga un nivel predeterminado para los blobs nuevos.
  4. Bajar de nivel ahorra en almacenamiento pero encarece cada lectura. Si un fichero se lee cada semana, Cool puede salir más caro que Hot.

El patrón de uso de las tarjetas de embarque de Contoso, medido por Diego Salas:

Antigüedad de la tarjeta Descargas Nivel adecuado
0–7 días (antes y durante el vuelo) Muy alto: el pasajero la abre varias veces Hot
8–90 días (reclamaciones, justificantes de gasto) Bajo pero real Cool
91 días – 5 años (retención legal y fiscal) Casi nulo Archive
Más de 5 años Ninguna Borrar

Ese patrón se traduce directamente en una regla de ciclo de vida.

  1. Reglas de ciclo de vida: las tarjetas de embarque de Contoso

Una regla de ciclo de vida (lifecycle management) es una política que Azure ejecuta a diario sobre los blobs de la cuenta, moviéndolos de nivel o borrándolos según su antigüedad. Es automática y gratuita: solo pagas las operaciones que genera.

{
  "rules": [
    {
      "enabled": true,
      "name": "ciclo-tarjetas-embarque",
      "type": "Lifecycle",
      "definition": {
        "filters": {
          "blobTypes": [ "blockBlob" ],
          "prefixMatch": [ "tarjetas-embarque/" ]
        },
        "actions": {
          "baseBlob": {
            "tierToCool":    { "daysAfterModificationGreaterThan": 30 },
            "tierToArchive": { "daysAfterModificationGreaterThan": 90 },
            "delete":        { "daysAfterModificationGreaterThan": 1825 }
          },
          "snapshot": {
            "delete": { "daysAfterCreationGreaterThan": 90 }
          }
        }
      }
    }
  ]
}

Lectura del documento, apartado por apartado:

  • filters.blobTypes: solo afecta a blobs en bloques (los de páginas de un disco no deben moverse jamás a Cool).
  • filters.prefixMatch: el prefijo empieza por el nombre del contenedor, no por el nombre del blob. Es el error de sintaxis más frecuente de estas reglas.
  • tierToCool a los 30 días, tierToArchive a los 90, delete a los 1825 (5 años): exactamente la política de retención de Contoso.
  • snapshot.delete: las instantáneas antiguas también ocupan y se facturan.

Aplicación de la regla:

# Guarda el JSON anterior como ciclo-tarjetas.json y aplícalo a la cuenta.
az storage account management-policy create \
  --account-name sttarjetascontosopro \
  --resource-group rg-contoso-reservas-pro \
  --policy @ciclo-tarjetas.json \
  --output none

# Comprobar la política activa.
az storage account management-policy show \
  --account-name sttarjetascontosopro \
  --resource-group rg-contoso-reservas-pro \
  --output json

Dos advertencias operativas: la política tarda hasta 24 horas en ejecutarse por primera vez (no esperes ver el cambio en cinco minutos), y daysAfterModificationGreaterThan cuenta desde la última modificación, no desde la creación. Si un proceso reescribe los ficheros, el reloj se reinicia y nada baja de nivel nunca.

  1. Azure Files: el recurso compartido de la oficina

Azure Files ofrece recursos compartidos de red accesibles por SMB (el protocolo de Windows, también soportado en Linux y macOS) y por NFS (solo en cuentas premium). A diferencia de los blobs, aquí sí hay un sistema de ficheros real con carpetas, permisos y bloqueo de ficheros.

Contoso tiene un caso claro: en las oficinas de Barcelona y Palma hay un recurso compartido \\servidor-oficina\operaciones con partes de incidencias, plantillas y hojas de cálculo que el personal de tierra abre a diario desde Windows. Ese recurso puede moverse tal cual a Azure Files sin cambiar la forma de trabajar de nadie.

Cuándo usar Blob Storage Azure Files
Aplicación que sube y descarga objetos por HTTPS Sí Se puede, pero no es lo natural
Recurso compartido montado como unidad de red No Sí
Software heredado que exige una ruta de sistema de ficheros No Sí
Millones de objetos con acceso por URL Sí No
Coste por GB Menor Mayor
# 1. Crear el recurso compartido con cuota de 100 GiB.
az storage share-rm create \
  --resource-group rg-contoso-reservas-pro \
  --storage-account stoperacionescontosopro \
  --name compartido-operaciones \
  --quota 100 \
  --output table

# 2. Montarlo en Linux (el paquete cifs-utils debe estar instalado).
sudo mkdir -p /mnt/operaciones
sudo mount -t cifs \
  //stoperacionescontosopro.file.core.windows.net/compartido-operaciones \
  /mnt/operaciones \
  -o vers=3.1.1,username=stoperacionescontosopro,password="${CLAVE_CUENTA}",serverino

En Windows sería un net use Z: \\stoperacionescontosopro.file.core.windows.net\compartido-operaciones. Dos consideraciones importantes:

  • El puerto 445 (SMB) está bloqueado por muchos proveedores de internet domésticos y corporativos. Por eso el montaje desde una oficina exige, en la práctica, conectividad privada: VPN o ExpressRoute. Es justo lo que veremos en la lección 02-06.
  • Existe Azure File Sync, que mantiene sincronizado un servidor de ficheros local con el recurso de Azure y deja en local solo los ficheros usados recientemente. Es la vía habitual para migrar un servidor de ficheros de oficina sin cambiar nada para el usuario.

  1. Queue Storage: desacoplar la emisión de tarjetas

Queue Storage es un servicio de colas de mensajes sencillo: un productor deja un mensaje, un consumidor lo recoge y lo procesa. Mensajes de hasta 64 KB, hasta millones en una cola, con una semántica de «al menos una vez».

El caso de Contoso: cuando un pasajero compra un billete, generar el PDF de la tarjeta de embarque tarda un par de segundos. Hacerlo dentro de la petición web significa que el cliente espera; si el generador falla, la compra falla. Con una cola, la web deja un mensaje y responde de inmediato; un proceso aparte genera el PDF y lo sube al contenedor.

# Crear la cola y encolar una solicitud de emisión.
az storage queue create \
  --account-name sttarjetascontosopro \
  --name cola-emision-tarjetas \
  --auth-mode login --output none

az storage message put \
  --account-name sttarjetascontosopro \
  --queue-name cola-emision-tarjetas \
  --content '{"localizador":"A7K2","vuelo":"IB3241","fecha":"2026-08-14"}' \
  --auth-mode login --output none

Queue Storage es la opción básica y barata. Cuando hacen falta temas de publicación y suscripción, sesiones, transacciones, orden garantizado o mensajes de más de 64 KB, la respuesta es Azure Service Bus; y para eventos a gran escala, Event Grid y Event Hubs. Los tres se comparan en la lección 06-05; aquí basta con que sepas que la cola existe dentro de la cuenta de almacenamiento y para qué sirve.

  1. Table Storage y su relación con Cosmos DB

Table Storage es un almacén NoSQL de clave-valor con esquema flexible. Cada entidad tiene:

  • PartitionKey: agrupa entidades; determina el reparto y el rendimiento.
  • RowKey: identifica la entidad dentro de la partición.
  • Hasta 252 propiedades más, sin esquema fijo.

Su virtud es el precio: almacenar millones de filas simples cuesta una fracción de lo que costaría una base relacional. Su límite es la consulta: solo es rápida buscando por PartitionKey + RowKey. Cualquier otra consulta recorre la tabla.

az storage table create --account-name sttarjetascontosopro \
  --name registroembarques --auth-mode login --output none

# Una entidad de auditoría: partición por vuelo, fila por localizador.
az storage entity insert \
  --account-name sttarjetascontosopro \
  --table-name registroembarques \
  --entity PartitionKey=IB3241 RowKey=A7K2 \
           emitida=2026-08-14T09:12:00Z puerta=B14 \
  --auth-mode login --output none

Relación con Cosmos DB: Azure Cosmos DB for Table ofrece la misma API con distribución global, latencia garantizada por SLA, índices sobre todas las propiedades y rendimiento aprovisionado. Es la evolución natural cuando Table Storage se queda corto. La comparación completa y cuándo dar el salto están en la lección 03-03.

Criterio rápido: si tu dato es una tabla de auditoría barata con acceso por clave, Table Storage. Si necesitas consultas variadas, latencia garantizada o presencia global, Cosmos DB.

  1. Redundancia: LRS, ZRS, GRS, GZRS y RA-GRS

Este es el cabo suelto que dejó el módulo 1. Azure Storage siempre guarda varias copias de tus datos; lo que eliges es dónde están esas copias, y eso determina de qué fallo te protege.

Opción Copias y ubicación Protege de Lectura en la región secundaria Coste relativo
LRS (local) 3 copias en un mismo centro de datos Fallo de disco, bastidor o servidor — €
ZRS (zona) 3 copias en tres zonas de la región Caída de un centro de datos completo — €€
GRS (geográfica) 3 copias locales + 3 en la región pareja Desastre regional No (la secundaria solo se lee tras conmutación) €€
GZRS (zona + geográfica) 3 zonas en la principal + 3 locales en la pareja Caída de zona y desastre regional No €€€
RA-GRS / RA-GZRS Como GRS/GZRS, con acceso de lectura a la secundaria Lo mismo, y además permite leer en la secundaria Sí, por un punto de conexión -secondary €€€€

Detalles que hay que conocer antes de decidir:

  • La región pareja de West Europe es North Europe (fijado en la lección 01-02). La replicación geográfica es asíncrona: en un desastre puedes perder los últimos minutos de escrituras (el llamado punto de recuperación, RPO, de unos 15 minutos).
  • La conmutación por error a la región pareja es una operación que se inicia (az storage account failover), no algo instantáneo y automático.
  • Con RA-GRS puedes leer siempre de la secundaria en https://<cuenta>-secondary.blob.core.windows.net, pero esos datos pueden ir retrasados. Sirve para informes o lecturas tolerantes, no para dar una tarjeta de embarque recién emitida.
  • La redundancia se puede cambiar después (az storage account update --sku), aunque algunos saltos (por ejemplo, a ZRS) pueden requerir una migración solicitada.

La decisión de Contoso Airlines

Cuenta Entorno Redundancia Justificación
sttarjetascontosodev Desarrollo LRS (Standard_LRS) Los datos son desechables y regenerables. Pagar redundancia geográfica por ficheros de prueba es tirar dinero
sttarjetascontosopro Producción GZRS (Standard_GZRS) Las tarjetas de embarque son un documento del pasajero con obligación de retención. GZRS cubre la caída de una zona (política de Contoso) y el desastre regional
stoperacionescontosopro Producción, ficheros de oficina ZRS (Standard_ZRS) Contenido operativo importante pero reconstruible desde los sistemas de origen; basta la protección zonal
# Aplicar la decisión en producción.
az storage account update \
  --resource-group rg-contoso-reservas-pro \
  --name sttarjetascontosopro \
  --sku Standard_GZRS \
  --output table

# Comprobar la redundancia de todas las cuentas de la suscripción.
az storage account list \
  --query "[].{Cuenta:name, Redundancia:sku.name, Region:location, Grupo:resourceGroup}" \
  --output table

Y una advertencia que hay que decir en voz alta: la redundancia no es una copia de seguridad. GZRS replica fielmente los borrados y las sobrescrituras. Si un proceso borra las tarjetas de agosto, se borran en las seis copias a la vez. Contra eso protegen el versionado y la eliminación temporal del apartado 10, y Azure Backup en la lección 07-05.

  1. Seguridad de acceso: claves, SAS e identidades

Hay tres formas de autorizar el acceso a los datos, y están ordenadas de peor a mejor.

Claves de la cuenta

Cada cuenta tiene dos claves de 512 bits que dan control total sobre todo el contenido, sin caducidad y sin identidad asociada.

# Ver las claves (y por qué esto debería incomodarte).
az storage account keys list \
  --resource-group rg-contoso-reservas-dev \
  --account-name sttarjetascontosodev \
  --output table

# Rotar la clave primaria.
az storage account keys renew \
  --resource-group rg-contoso-reservas-dev \
  --account-name sttarjetascontosodev \
  --key primary --output none

Que haya dos claves es precisamente para poder rotar sin cortes: configuras las aplicaciones con la secundaria, renuevas la primaria, cambias las aplicaciones y renuevas la secundaria. Aun así, la recomendación es no usarlas: si una clave se filtra en un repositorio, cualquiera lee y borra todo. Puedes deshabilitarlas por completo:

az storage account update \
  --resource-group rg-contoso-reservas-pro \
  --name sttarjetascontosopro \
  --allow-shared-key-access false --output none

Firmas de acceso compartido (SAS)

Una SAS es una URL con permisos limitados y caducidad. Es la forma de dar a un pasajero acceso a su tarjeta de embarque y a nada más.

Tipo de SAS Cómo se firma Alcance Revocación
De servicio Con la clave de la cuenta Un recurso concreto (un blob, un contenedor) Rotando la clave o con una directiva almacenada
De cuenta Con la clave de la cuenta Varios servicios y operaciones de gestión Rotando la clave
De delegación de usuario Con una clave de Entra ID, no con la clave de la cuenta Blobs Revocando la clave de delegación, sin tocar la cuenta

La de delegación de usuario es la recomendada: no requiere que la aplicación conozca la clave de la cuenta, queda asociada a una identidad y se puede revocar sin romper todo lo demás.

# SAS de delegación de usuario: lectura de un blob concreto, válida 15 minutos.
CADUCIDAD=$(date -u -d "15 minutes" '+%Y-%m-%dT%H:%MZ')

SAS=$(az storage blob generate-sas \
  --account-name sttarjetascontosopro \
  --container-name tarjetas-embarque \
  --name "2026/08/IB3241-20260814-A7K2.pdf" \
  --permissions r \
  --expiry "${CADUCIDAD}" \
  --https-only \
  --as-user --auth-mode login \
  --full-uri --output tsv)

echo "Enlace temporal: ${SAS}"

Desglose de las opciones, porque cada una es una decisión de seguridad:

Opción Efecto
--permissions r Solo lectura. Los permisos se componen con letras: r leer, w escribir, d borrar, l listar, a añadir, c crear
--expiry Caducidad. Corta siempre: minutos u horas, nunca meses
--https-only La URL no funciona por HTTP
--as-user --auth-mode login SAS de delegación de usuario, firmada con Entra ID y no con la clave
--full-uri Devuelve la URL completa lista para entregar

Buenas prácticas de SAS que Contoso aplica: caducidad de 15 minutos para descargas de pasajero, permisos mínimos, generación en el servidor (nunca en el navegador), y directivas de acceso almacenadas a nivel de contenedor cuando se necesita poder revocar en masa.

Acceso por identidad de Microsoft Entra ID

La opción correcta para que una aplicación acceda a los datos: sin claves, sin SAS, con permisos RBAC concretos y auditoría.

# Dar a la web de reservas permiso para escribir tarjetas, usando su identidad administrada.
ID_APP=$(az webapp identity assign \
  --resource-group rg-contoso-reservas-pro \
  --name app-contoso-reservas-pro \
  --query principalId --output tsv)

ID_CUENTA=$(az storage account show \
  --resource-group rg-contoso-reservas-pro \
  --name sttarjetascontosopro --query id --output tsv)

az role assignment create \
  --assignee "${ID_APP}" \
  --role "Storage Blob Data Contributor" \
  --scope "${ID_CUENTA}" --output none

Los roles de datos más usados: Storage Blob Data Reader (leer), Storage Blob Data Contributor (leer y escribir) y Storage Blob Data Owner (además, gestionar permisos POSIX). Ojo con una confusión clásica: el rol Colaborador de Azure permite gestionar la cuenta, pero no da acceso a los datos salvo a través de las claves. Identidades administradas y RBAC se desarrollan en la lección 04-02.

  1. Cifrado, versionado, instantáneas y eliminación temporal

Cifrado en reposo: todo lo que hay en Azure Storage se cifra con AES de 256 bits, siempre y sin coste. Puedes usar claves gestionadas por Microsoft (por defecto) o claves propias en Key Vault (04-03) cuando el cumplimiento normativo lo exija.

Cifrado en tránsito: --https-only true y --min-tls-version TLS1_2, ya aplicados en la cuenta de Contoso desde el módulo 1.

Protección contra el borrado, que es lo que la redundancia no cubre:

CUENTA="sttarjetascontosopro"
GRUPO="rg-contoso-reservas-pro"

# 1. Eliminación temporal de blobs: 30 días para recuperar lo borrado.
az storage account blob-service-properties update \
  --account-name "${CUENTA}" --resource-group "${GRUPO}" \
  --enable-delete-retention true --delete-retention-days 30 --output none

# 2. Eliminación temporal de contenedores enteros.
az storage account blob-service-properties update \
  --account-name "${CUENTA}" --resource-group "${GRUPO}" \
  --enable-container-delete-retention true --container-delete-retention-days 30 --output none

# 3. Versionado: cada sobrescritura conserva la versión anterior.
az storage account blob-service-properties update \
  --account-name "${CUENTA}" --resource-group "${GRUPO}" \
  --enable-versioning true --output none
Mecanismo De qué protege Coste
Eliminación temporal Borrado accidental de blobs o contenedores Se factura el espacio de lo borrado durante la retención
Versionado Sobrescritura accidental o cifrado por ransomware Cada versión ocupa y se factura: combínalo con ciclo de vida
Instantáneas Punto de retorno manual antes de un cambio Solo los bloques modificados
Bloqueo inmutable (WORM) Manipulación deliberada; cumplimiento legal El blob no se puede borrar ni modificar durante el periodo fijado

Contoso activa eliminación temporal de 30 días y versionado en producción, y añade a la regla de ciclo de vida el borrado de versiones antiguas para que el versionado no dispare la factura.

  1. Herramientas: az storage, AzCopy y Storage Explorer

Herramienta Cuándo usarla Fortaleza
az storage (Azure CLI) Automatización, scripts, tuberías Ya la tienes instalada; se integra con el resto de comandos
AzCopy Transferencias masivas y sincronización Mucho más rápido: paraleliza, reanuda transferencias y sincroniza
Azure Storage Explorer Exploración visual y depuración Interfaz gráfica multiplataforma, muy útil para ver qué hay realmente
SDK (Java, .NET, Python, JS) Desde el código de la aplicación Reintentos, flujos y autenticación por identidad integrados
# AzCopy con inicio de sesión de Entra ID (sin claves).
azcopy login

# Copiar un directorio completo de tarjetas históricas, recursivo.
azcopy copy "./tarjetas-2025/" \
  "https://sttarjetascontosopro.blob.core.windows.net/tarjetas-embarque/2025/" \
  --recursive=true

# Sincronizar: solo sube lo que ha cambiado. Ideal para migraciones repetidas.
azcopy sync "./tarjetas-2025/" \
  "https://sttarjetascontosopro.blob.core.windows.net/tarjetas-embarque/2025/" \
  --recursive=true --delete-destination=false

Regla práctica: para mover más de unos cientos de megabytes o más de unos cientos de ficheros, AzCopy. az storage blob upload-batch funciona, pero es notablemente más lento.

  1. Ejemplo completo: la tarjeta de embarque de principio a fin

Este script reúne todo lo anterior en el flujo real de Contoso: preparar la cuenta con la redundancia decidida, subir la tarjeta, entregar un enlace temporal al pasajero y programar el abaratamiento automático.

#!/usr/bin/env bash
set -euo pipefail

# ---------- Parámetros ----------
GRUPO="rg-contoso-reservas-dev"
CUENTA="sttarjetascontosodev"
CONTENEDOR="tarjetas-embarque"
LOCALIZADOR="A7K2"
VUELO="IB3241"
FECHA="2026-08-14"
BLOB="$(date -d "${FECHA}" '+%Y/%m')/${VUELO}-$(date -d "${FECHA}" '+%Y%m%d')-${LOCALIZADOR}.pdf"

# ---------- 1. Contenedor privado (idempotente) ----------
az storage container create \
  --account-name "${CUENTA}" --name "${CONTENEDOR}" \
  --public-access off --auth-mode login --output none

# ---------- 2. Subir la tarjeta con su tipo de contenido ----------
az storage blob upload \
  --account-name "${CUENTA}" --container-name "${CONTENEDOR}" \
  --name "${BLOB}" --file "./tarjeta-${LOCALIZADOR}.pdf" \
  --content-type "application/pdf" \
  --content-disposition "inline; filename=\"tarjeta-${VUELO}.pdf\"" \
  --tier Hot \
  --auth-mode login --overwrite --output none

echo "Tarjeta subida como ${BLOB}"

# ---------- 3. Enlace temporal para el pasajero (15 minutos, solo lectura) ----------
CADUCIDAD=$(date -u -d "15 minutes" '+%Y-%m-%dT%H:%MZ')
ENLACE=$(az storage blob generate-sas \
  --account-name "${CUENTA}" --container-name "${CONTENEDOR}" --name "${BLOB}" \
  --permissions r --expiry "${CADUCIDAD}" --https-only \
  --as-user --auth-mode login --full-uri --output tsv)

echo "Enlace para el pasajero (caduca ${CADUCIDAD}): ${ENLACE}"

# ---------- 4. Regla de ciclo de vida: Cool a los 30 días ----------
cat > ciclo-tarjetas.json <<'EOF'
{
  "rules": [
    {
      "enabled": true,
      "name": "ciclo-tarjetas-embarque",
      "type": "Lifecycle",
      "definition": {
        "filters": { "blobTypes": ["blockBlob"], "prefixMatch": ["tarjetas-embarque/"] },
        "actions": {
          "baseBlob": {
            "tierToCool":    { "daysAfterModificationGreaterThan": 30 },
            "tierToArchive": { "daysAfterModificationGreaterThan": 90 },
            "delete":        { "daysAfterModificationGreaterThan": 1825 }
          }
        }
      }
    }
  ]
}
EOF

az storage account management-policy create \
  --account-name "${CUENTA}" --resource-group "${GRUPO}" \
  --policy @ciclo-tarjetas.json --output none

echo "Politica de ciclo de vida aplicada."

# ---------- 5. Verificación ----------
az storage blob show \
  --account-name "${CUENTA}" --container-name "${CONTENEDOR}" --name "${BLOB}" \
  --auth-mode login \
  --query "{Nombre:name, Nivel:properties.blobTier, Bytes:properties.contentLength, Tipo:properties.contentSettings.contentType}" \
  --output table

Prueba el enlace con curl -I "${ENLACE}": debe devolver HTTP/1.1 200 OK. Espera a que caduque y repítelo: obtendrás un 403 con el código AuthenticationFailed. Esa es exactamente la protección que buscamos: el enlace sirve para descargar la tarjeta ahora, no para siempre.

  1. Limpieza

# Borrar los blobs de prueba de un prefijo.
az storage blob delete-batch \
  --account-name sttarjetascontosodev \
  --source tarjetas-embarque \
  --pattern "2026/08/*" \
  --auth-mode login

# Quitar la política de ciclo de vida si era solo una prueba.
az storage account management-policy delete \
  --account-name sttarjetascontosodev \
  --resource-group rg-contoso-reservas-dev

# Borrar la cuenta entera (solo en laboratorio).
# az storage account delete --name sttarjetascontosodev \
#   --resource-group rg-contoso-reservas-dev --yes

Recuerda: con la eliminación temporal activada, los blobs borrados siguen ocupando y facturando durante los días de retención. Es lo correcto para producción, pero tenlo en cuenta al limpiar un laboratorio.

Errores Comunes y Consejos

  • Repartir la clave de la cuenta para dar acceso a un fichero. Da control total sobre todo. Usa SAS de delegación de usuario con caducidad corta, o identidades administradas.
  • Generar SAS con caducidad de meses o años. Una URL con un año de vida acaba en un correo, en un ticket y en un buscador. Minutos, no meses.
  • Subir a Archive lo que un cliente puede pedir hoy. Archive está fuera de línea: rehidratar tarda horas. Nunca para tarjetas del vuelo de mañana.
  • Olvidar la permanencia mínima. Mover a Cool y borrar a los tres días cuesta los 30 días completos. Ajusta la política a la realidad de tus datos.
  • Confundir redundancia con copia de seguridad. GZRS replica los borrados fielmente. Activa eliminación temporal y versionado.
  • Poner mal el prefixMatch de la regla de ciclo de vida. Empieza por el nombre del contenedor, no por el del blob. Es el fallo más habitual y silencioso: la regla no falla, simplemente no hace nada.
  • Esperar que la regla actúe al instante. Se ejecuta a diario y la primera vez puede tardar 24 horas.
  • No poner el content-type al subir. El PDF se descarga en vez de verse; luego llegan las incidencias de soporte.
  • Usar Azure Files donde bastan blobs. Files cuesta más por GB y añade dependencia del puerto 445.
  • Activar versionado sin ciclo de vida. Cada sobrescritura crea una versión que se factura para siempre. Combina siempre ambas cosas.
  • Consejo: activa --allow-shared-key-access false en producción. Fuerza a que todo el acceso sea por Entra ID y elimina de golpe la clase entera de incidentes por clave filtrada.
  • Consejo: diseña el nombre del blob con jerarquía por fecha (aaaa/mm/). Te da listados por prefijo y políticas de ciclo de vida por periodo prácticamente gratis.

Ejercicios

Ejercicio 1: elegir servicio, nivel y redundancia

Para cada dato de Contoso Airlines, indica qué servicio de la cuenta de almacenamiento usarías, qué nivel de acceso y qué redundancia, con su justificación:

  1. Tarjetas de embarque en PDF de producción, retención legal de 5 años.
  2. Plantillas y hojas de cálculo que el personal de tierra de Palma abre desde el explorador de Windows.
  3. Solicitudes de emisión de tarjeta pendientes de procesar por el generador de PDF.
  4. Registro de auditoría de cada emisión: qué vuelo, qué localizador, a qué hora, para consulta por vuelo.
  5. Copias de los ficheros de prueba que Diego regenera cada semana.

Ejercicio 2: enlace temporal y ciclo de vida

  1. Sube un fichero de prueba a tarjetas-embarque en la cuenta de desarrollo con el tipo de contenido correcto.
  2. Genera una SAS de delegación de usuario, de solo lectura, válida 10 minutos y solo por HTTPS.
  3. Verifica con curl que funciona, y explica qué respuesta esperas cuando caduque.
  4. Escribe la política de ciclo de vida que mueva a Cool a los 30 días, a Archive a los 90 y borre a los 5 años.

Ejercicio 3: auditoría de almacenamiento

Escribe los comandos de Azure CLI que respondan a estas preguntas sobre la suscripción:

  1. ¿Qué cuentas de almacenamiento hay y con qué redundancia?
  2. ¿Alguna permite acceso público a blobs o admite claves compartidas?
  3. ¿Alguna acepta TLS por debajo de 1.2?
  4. ¿Qué cuentas de producción no tienen política de ciclo de vida?

Soluciones

Solución 1:

Dato Servicio Nivel Redundancia Justificación
1. Tarjetas de producción Blob (en bloques) Hot → Cool (30 d) → Archive (90 d) GZRS Documento del pasajero con retención legal: protección zonal y geográfica; el ciclo de vida abarata la retención larga
2. Plantillas de la oficina File (SMB) — ZRS Necesita montarse como unidad de red desde Windows; contenido reconstruible, basta protección zonal
3. Solicitudes pendientes Queue — La de la cuenta (ZRS/GZRS) Mensajes efímeros que desacoplan la web del generador de PDF
4. Registro de auditoría por vuelo Table — La de la cuenta Clave-valor barato: PartitionKey = vuelo, RowKey = localizador, que es justo el patrón de consulta
5. Ficheros de prueba de Diego Blob Hot LRS Datos desechables y regenerables: la redundancia geográfica sería gasto puro

Solución 2:

#!/usr/bin/env bash
set -euo pipefail
CUENTA="sttarjetascontosodev"
CONTENEDOR="tarjetas-embarque"
BLOB="2026/08/PRUEBA-20260814-TEST.pdf"

# 1. Subida con tipo de contenido correcto.
az storage blob upload \
  --account-name "${CUENTA}" --container-name "${CONTENEDOR}" \
  --name "${BLOB}" --file ./prueba.pdf \
  --content-type "application/pdf" \
  --auth-mode login --overwrite --output none

# 2. SAS de delegación de usuario, lectura, 10 minutos, solo HTTPS.
CADUCIDAD=$(date -u -d "10 minutes" '+%Y-%m-%dT%H:%MZ')
ENLACE=$(az storage blob generate-sas \
  --account-name "${CUENTA}" --container-name "${CONTENEDOR}" --name "${BLOB}" \
  --permissions r --expiry "${CADUCIDAD}" --https-only \
  --as-user --auth-mode login --full-uri --output tsv)

# 3. Verificación.
curl -I "${ENLACE}"   # Esperado ahora: HTTP/1.1 200 OK
  1. Una vez pasados los 10 minutos, la misma URL devuelve HTTP/1.1 403 Forbidden con el código de error AuthenticationFailed: la firma incluye la caducidad y el servicio la valida en cada petición. No hace falta borrar ni revocar nada.

  2. Política:

{
  "rules": [{
    "enabled": true,
    "name": "ciclo-tarjetas-embarque",
    "type": "Lifecycle",
    "definition": {
      "filters": { "blobTypes": ["blockBlob"], "prefixMatch": ["tarjetas-embarque/"] },
      "actions": {
        "baseBlob": {
          "tierToCool":    { "daysAfterModificationGreaterThan": 30 },
          "tierToArchive": { "daysAfterModificationGreaterThan": 90 },
          "delete":        { "daysAfterModificationGreaterThan": 1825 }
        }
      }
    }
  }]
}

Solución 3:

# 1. Cuentas y redundancia.
az storage account list \
  --query "[].{Cuenta:name, Redundancia:sku.name, Region:location, Grupo:resourceGroup}" \
  --output table

# 2. Acceso público a blobs o claves compartidas permitidas.
az storage account list \
  --query "[?allowBlobPublicAccess==\`true\` || allowSharedKeyAccess==\`true\`].{Cuenta:name, Publico:allowBlobPublicAccess, ClaveCompartida:allowSharedKeyAccess}" \
  --output table

# 3. TLS por debajo de 1.2.
az storage account list \
  --query "[?minimumTlsVersion!='TLS1_2'].{Cuenta:name, TLS:minimumTlsVersion}" \
  --output table

# 4. Cuentas de producción sin política de ciclo de vida (bucle, porque
#    la política es un subrecurso y no aparece en la lista de cuentas).
for CUENTA in $(az storage account list \
      --query "[?tags.entorno=='produccion'].name" -o tsv); do
  GRUPO=$(az storage account show -n "${CUENTA}" --query resourceGroup -o tsv)
  if ! az storage account management-policy show \
        --account-name "${CUENTA}" --resource-group "${GRUPO}" \
        --output none 2>/dev/null; then
    echo "SIN POLITICA DE CICLO DE VIDA: ${CUENTA} (${GRUPO})"
  fi
done

En el módulo 4 verás cómo convertir estas comprobaciones en Azure Policy para que no dependan de que alguien se acuerde de ejecutarlas.

Conclusión

Has cerrado el cabo suelto que dejó el módulo 1 y, de paso, has aprendido el servicio de datos más transversal de Azure. Sabes que una cuenta de almacenamiento aloja cuatro servicios —Blob, File, Queue y Table— con su propio punto de conexión y su nombre globalmente único en minúsculas. Conoces Blob Storage en detalle: contenedores, la jerarquía plana con prefijos, los tres tipos de blob y los niveles de acceso Hot, Cool, Cold y Archive con su compromiso entre coste de almacenamiento y de recuperación, las permanencias mínimas y la rehidratación de Archive. Has traducido el patrón real de uso de las tarjetas de embarque de Contoso —mucho la primera semana, casi nada después— en una regla de ciclo de vida que las abarata sola. Sabes cuándo tiene sentido Azure Files para el recurso compartido de la oficina, para qué sirve Queue Storage como desacoplador y qué relación tiene Table Storage con Cosmos DB. Y has fijado la decisión de redundancia de Contoso: LRS en desarrollo, GZRS para las tarjetas de producción y ZRS para los ficheros de operaciones, con la advertencia esencial de que la redundancia no es una copia de seguridad, para lo cual has activado eliminación temporal y versionado. En seguridad de acceso, has bajado por la escalera de lo malo a lo bueno: claves de cuenta (evitar y deshabilitar), SAS de servicio, de cuenta y de delegación de usuario con caducidad corta, y acceso por identidad de Microsoft Entra ID, que es el destino final.

Fíjate en lo que tienes ya montado: cómputo elástico, aplicaciones publicadas y almacenamiento con su política de ciclo de vida. Pero todo eso, tal como está, habla por internet. La web llega a la API por su nombre público, la aplicación llega al almacenamiento por su punto de conexión público, y la base de datos que viene en el módulo 3 estaría igual de expuesta. Ninguna arquitectura seria se queda así.

En la siguiente lección, Redes en Azure: redes virtuales, subredes y NSG, damos ese paso: planificarás el espacio de direcciones de vnet-contoso-pro con la aritmética CIDR explicada desde cero, diseñarás las subredes snet-web, snet-app, snet-datos y snet-gestion, escribirás reglas de grupos de seguridad de red que abran solo lo imprescindible, entenderás el emparejamiento de redes y el patrón hub-and-spoke, y verás la diferencia decisiva entre puntos de conexión de servicio y Azure Private Link —que es exactamente lo que hará que la cuenta sttarjetascontosopro y la base de datos de reservas dejen de ser accesibles desde internet.

Curso de Azure

Módulo 1: Introducción a Azure

Módulo 2: Servicios principales de Azure

Módulo 3: Bases de datos de Azure

Módulo 4: Seguridad en Azure

Módulo 5: Azure DevOps

Módulo 6: Servicios avanzados de Azure

Módulo 7: Monitoreo y gestión

Módulo 8: Gestión y optimización de costos

Módulo 9: Estudios de caso y mejores prácticas

© Copyright 2026. Todos los derechos reservados