Saltar al contenido principal

Cómo alojar archivos estáticos en un CDN con Casdoor: S3, MinIO, Azure Blob y otros proveedores de almacenamiento

· 11 min de lectura
Yang Luo
Casdoor Maintainer

Para alojar archivos estáticos en un CDN, colóquelos en un almacenamiento de objetos (Amazon S3, MinIO, Azure Blob Storage, Google Cloud Storage, Alibaba Cloud OSS o Tencent Cloud COS), haga que el CDN extraiga de ese bucket como su origen y distribuya URLs en el dominio del CDN. En Casdoor esto es una sola configuración: cree un proveedor de almacenamiento para el bucket y coloque la dirección del CDN en su campo Domain. Casdoor sube avatares y otros archivos a través de la API del proveedor y guarda URLs que comienzan con ese dominio. El frontend propio de Casdoor también puede provenir de un CDN, mediante frontendCdnUrl y staticBaseUrl en app.conf.

Proveedores de almacenamiento de un vistazo​

Un proveedor de almacenamiento decide dónde escribe Casdoor los archivos subidos: avatares de usuario, imágenes de documentos de identidad, páginas de términos de uso y cualquier cosa subida en la página Resources. Agregue el proveedor a una aplicación, y las subidas realizadas en esa aplicación irán a él. La visión general del proveedor de almacenamiento lista todos los tipos. Esta tabla cubre los que suelen preguntar:

AlmacenamientoTipo de proveedor de Casdoor¿Casdoor usa la API S3?AutoalojableCómo se establece la URL pública
Sistema de archivos localLocal File SystemNo, archivos planos en discoSí, es el servidor de CasdoorServido por Casdoor bajo /files/. Domain es de solo lectura
Amazon S3AWS S3SíNoDomain: la URL del bucket o un dominio de CloudFront. Endpoint (Intranet): un punto final VPC
MinIOMinIOSí, con solicitudes estilo rutaSíDomain: la URL de MinIO seguida del nombre del bucket, o un dominio de CDN
Alibaba Cloud OSSAliyun OSSNo, el SDK de OSSNoDomain: un dominio de CDN. Si se deja vacío, se convierte en bucket.endpoint. Endpoint (Intranet): el punto final interno
Tencent Cloud COSTencent Cloud COSNo, la API COSNoDomain: un dominio de CDN
Azure Blob StorageAzure BlobNo, la API BlobNoDomain: un dominio personalizado o de Front Door. Casdoor añade el nombre del contenedor a la ruta
Google Cloud StorageGoogle Cloud StorageNo, el cliente Go de GoogleNoDomain: si se deja vacío, se convierte en https://storage.googleapis.com. Casdoor añade el nombre del bucket a la ruta
NAS SynologySynologyNo, la API DSM File StationSíNo hay campo Domain. La URL se basa en Endpoint

Casdoor también admite Qiniu Cloud Kodo, CUCloud OSS y Casdoor, que almacena archivos en otra instancia de Casdoor. Las guías por proveedor para Amazon S3, MinIO, Azure Blob, Google Cloud Storage, Alibaba Cloud OSS, Tencent Cloud COS, NAS Synology y el sistema de archivos local muestran qué valor va en qué campo.

Endpoint frente a Domain​

Estos dos campos realizan trabajos diferentes, y la mayoría de los problemas con el CDN provienen de confundirlos.

  • Endpoint es la dirección que Casdoor usa para hablar con la API de almacenamiento: subir, eliminar, listar. El CDN no interviene.
  • Endpoint (Intranet) sustituye a Endpoint cuando se establece isCloudIntranet = true en app.conf. Esto mantiene el tráfico de carga en la red interna del proveedor cuando Casdoor se ejecuta en la misma nube. El campo aparece para AWS S3, Aliyun OSS, Azure Blob y CUCloud OSS.
  • Domain es la base de la URL que Casdoor guarda y que los navegadores solicitan. Si tienes una CDN, su dominio va aquí.
  • Path prefix se coloca delante de cada clave de objeto. Con un prefijo de casdoor, un avatar termina bajo casdoor/avatar/....

Casdoor construye la URL del archivo a partir del esquema y host de Domain, luego la ruta de Domain, luego el path prefix, y finalmente la ruta del archivo. Un Domain sin esquema recibe https://. La parte de ruta de Domain también pasa a formar parte de la clave del objeto, por lo que https://cdn.example.com/casdoor/ almacena archivos bajo casdoor/ en el bucket. Para Azure Blob y Google Cloud Storage, Casdoor añade el nombre del contenedor o bucket como primer segmento de ruta después del host. Tu CDN debe servir esa ruta.

Si Domain está vacío, Casdoor lo rellena desde el endpoint del proveedor la primera vez que usa dicho proveedor, y lo guarda. A veces el resultado funciona, como con OSS y GCS. A veces no: para un endpoint de S3 sin el nombre del bucket, o para MinIO, donde las solicitudes de estilo de ruta ponen el nombre del bucket en la ruta, la URL generada carece del bucket. Establece Domain tú mismo, sube un avatar de prueba y abre la URL que devuelve Casdoor antes de que nadie más la use.

El proveedor que Casdoor utiliza para avatars copiados de inicios de sesión sociales proviene de defaultStorageProvider en app.conf. Es el nombre de un proveedor propiedad de admin (consulta la referencia de configuración):

defaultStorageProvider = provider_storage_s3
isCloudIntranet = false

Buckets públicos, buckets privados y URLs firmadas​

Casdoor guarda una URL plana y permanente en el campo avatar del usuario y en el registro de recursos. No crea URLs firmadas ni caducas para estos archivos. Por lo tanto, lo que esté en Domain debe responder a una solicitud GET anónima. Hay dos formas de hacerlo.

Haz que los objetos sean públicos. Con AWS S3 y MinIO, Casdoor sube cada objeto con la ACL enlatada public-read. Con Aliyun OSS, la biblioteca cliente hace lo mismo por defecto. En S3 esto entra en conflicto con los valores predeterminados para nuevos buckets: según AWS, los nuevos buckets usan la configuración Bucket owner enforced, que deshabilita las ACLs, y una carga que establezca una ACL como public-read falla con AccessControlListNotSupported. Por eso la guía de Amazon S3 te pide activar las ACLs y desactivar Block all public access. En OSS, la ACL de un objeto tiene prioridad sobre la ACL del bucket, por lo que un objeto public-read puede leerse incluso en un bucket privado. MinIO no usa la ACL para lecturas anónimas. Usa una política de bucket:

mc anonymous set download myminio/casdoor

Azure necesita que se permita el acceso anónimo en la cuenta de almacenamiento y que el contenedor esté configurado con el nivel de acceso Blob. Google Cloud Storage necesita que el rol Storage Object Viewer (roles/storage.objectViewer) se conceda a allUsers en el bucket.

Mantén el bucket privado y deja que solo la CDN lo lea. La CDN firma sus solicitudes al origen, y los espectadores pasan por la CDN sin firma. Cada proveedor tiene su propia versión:

  • CloudFront tiene control de acceso al origen (OAC). AWS requiere Bucket owner enforced para OAC, o Bucket owner preferred si necesitas ACLs.
  • Alibaba Cloud CDN puede obtener datos de un bucket OSS privado después de que lo autorices.
  • Tencent Cloud CDN tiene autenticación de extracción de origen para buckets COS privados.
  • Azure Front Door Premium puede alcanzar una cuenta de almacenamiento mediante Private Link.
  • La guía de Cloud CDN de Google también cubre el acceso a buckets privados, donde el rol Storage Object Viewer se concede a una cuenta de servicio en lugar de a allUsers.

Esto oculta la URL propia del bucket, pero los archivos siguen siendo públicos a través de la CDN. Con los tipos AWS S3 y Aliyun OSS, los objetos también permanecen legibles en sus URLs de bucket debido a la ACL public-read que establece Casdoor.

Si los avatares no deben ser públicos en absoluto, una CDN frente al almacenamiento de objetos es la herramienta equivocada. Mantén esos archivos en un tipo de almacenamiento que controles y limita quién puede alcanzar ese host.

Encabezados de caché y la trampa de los avatares​

En S3 y MinIO, Casdoor establece Content-Type a partir de la extensión del archivo al subirlo. No establece Cache-Control en ningún proveedor. Eso significa que se aplica el TTL predeterminado de la CDN. En CloudFront, los objetos sin Cache-Control se almacenan en caché durante el TTL predeterminado, que es de 24 horas si no usas una política de caché. Para controlar esto por objeto, agrega metadatos Cache-Control en el bucket. Para una ruta completa, usa una regla de caché en la CDN.

Los avatares necesitan un TTL corto. Cuando un usuario cambia su imagen, Casdoor escribe el nuevo archivo en la misma clave, avatar/<organization>/<username>.<extension>, y guarda la misma URL. Un TTL largo significa que la gente verá la imagen vieja hasta que expire o hasta que purgues o invalides esa ruta. Otras cargas reciben un sufijo numerado (-1, -2, ...) cuando el nombre ya está ocupado, por lo que una nueva carga obtiene una nueva URL y puede almacenarse en caché durante mucho tiempo.

Un diseño que funciona:

RutaCaché sugerida
avatar/*TTL corto (minutos), o purga al cambiar
resource/* y otras cargasTTL largo
Recursos frontend hasheados (assets/*)TTL muy largo. El nombre de archivo cambia en cada compilación

El frontend propio de Casdoor en una CDN​

Separado de las cargas de usuario, hay tres formas de mover los archivos estáticos propios de Casdoor fuera del servidor Casdoor.

frontendCdnUrl. Úsalo si instalas el frontend desde el paquete npm casdoor-web. Apúntalo a una CDN de npm, por ejemplo:

frontendCdnUrl = "https://cdn.jsdelivr.net/npm/{name}@{version}"

Casdoor lee el nombre del paquete y la versión del package.json en la carpeta de compilación. Reescribe los enlaces de scripts y hojas de estilo en index.html a esa CDN y mantiene las rutas locales como alternativa. Si un archivo falla al cargar, el navegador lo carga desde Casdoor, y una cookie mantiene ese navegador en archivos locales durante el resto de la sesión. Un frontend que compiles tú mismo no tiene tal package.json, por lo que la configuración no tiene efecto en él.

El script de despliegue. Para un frontend que se compila desde el código fuente, Alojar los archivos del frontend en una CDN explica deployment/deploy_test.go. Sube web/build/assets/ a través de uno de tus proveedores de almacenamiento y apunta index.html al dominio del proveedor, que debe terminar en /. Vite genera hashes para estos nombres de archivo, por lo que son adecuados para el TTL largo indicado en la tabla anterior.

staticBaseUrl. Esto establece dónde se obtienen las imágenes predeterminadas, como logotipos, iconos de proveedores y el avatar predeterminado. El valor predeterminado es https://cdn.casbin.org, que sirve el repositorio casbin/static. En una red sin acceso a Internet, aloja tu propia copia de ese repositorio y apunta staticBaseUrl hacia ella, como se describe en Alojar archivos estáticos en una intranet.

Elegir una opción​

  • Un servidor, base de usuarios pequeña: Local File System. Monta el directorio files en un volumen si Casdoor se ejecuta en un contenedor. Casdoor envía X-Content-Type-Options: nosniff y una Content-Security-Policy de aislamiento con estos archivos, por lo que un archivo HTML o SVG subido no puede ejecutar scripts en tu dominio de Casdoor.
  • Autoalojado y compatible con S3: MinIO. También es el tipo que la documentación sugiere para otros almacenes compatibles con S3.
  • Ya estás en la nube: usa el almacenamiento de objetos y la CDN de esa nube, establece Endpoint (Intranet) donde Casdoor se ejecuta en la misma nube, y establece Domain en la CDN.

Referencias​