amazon-web-services amazon-s3 http-status-code-403 pre-signed-url

amazon web services - AWS S3 maneja con gracia 403 después de que getSignedUrl expiró



amazon-web-services amazon-s3 (1)

Intento manejar el 403 con gracia cuando visito un recurso S3 a través de una URL vencida. Actualmente devuelve una página de error de amz xml. Cargué un recurso 403.html y pensé que podría redireccionar a eso.

Los recursos del depósito son elementos guardados / recuperados por mi aplicación. Aún así, al leer los documentos, establecí las propiedades del depósito para manejar el depósito como una página de página web estática y cargué un 403.html en la raíz del depósito. Todos los permisos públicos están bloqueados, excepto el acceso público GET al recurso 403.html. En las propiedades del depósito, la configuración del sitio web indiqué el 403.html como página de error. Visitar http://<bucket>.s3-website-us-east-1.amazonaws.com/some-asset.html redirige correctamente a http://<bucket>.s3-website-us-east-1.amazonaws.com/403.html

Sin embargo, cuando uso aws-sdk js / node y llamo al método getSignedUrl(''getObject'', params) para generar la url firmada, devuelve una URL de host diferente: https://<bucket>.s3.amazonaws.com/ Visiting los recursos caducados de este método no se redireccionan a 403.html. Supongo que, dado que la dirección del host es diferente, esta es la razón por la que no está redirigiendo automáticamente.

También he configurado reglas de enrutamiento de sitios web estáticos para la condición

<Condition> <HttpErrorCodeReturnedEquals>403</HttpErrorCodeReturnedEquals> </Condition> <Redirect> <ReplaceKeyWith>403.html</ReplaceKeyWith> </Redirect>

Aún así, eso no redirige las URL firmadas. Por lo tanto, no sé cómo manejar elegantemente estas URL expiradas. Cualquier ayuda sería muy apreciada.


Las cubetas S3 tienen 2 interfaces públicas, REST y sitio web. Esa es la diferencia entre los dos nombres de host y la diferencia en el comportamiento que está viendo.

Tienen dos conjuntos de características diferentes.

feature REST Endpoint Website Endpoint ---------------- ------------------- ------------------- Access control yes no, public content only Error messages XML HTML Redirection no yes, bucket, rule, and object-level Request types all supported GET and HEAD only Root of bucket lists keys returns index document SSL yes no

Fuente: http://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteEndpoints.html

Entonces, como puede ver en la tabla, el punto final REST admite URL firmadas, pero no errores amistosos, mientras que el punto final del sitio web admite errores amistosos, pero no URLs firmadas. Los dos no se pueden mezclar y combinar, por lo que lo que estás tratando de hacer no es compatible con S3.

He solucionado esta limitación al pasar todas las solicitudes del depósito a través de HAProxy en una instancia de EC2 y en el punto final REST para el depósito.

Cuando se devuelve un mensaje de error 403, el proxy modifica el cuerpo XML de la respuesta utilizando el nuevo intérprete Lua incorporado , y lo agrega antes de la etiqueta <Error> .

<?xml-stylesheet type="text/xsl" href="/error.xsl"?>/n

El archivo /error.xsl es legible públicamente y utiliza XSLT del lado del navegador para generar una bonita respuesta de error.

El proxy también inyecta un par de etiquetas adicionales en el xml, <ProxyTime> y <ProxyHTTPCode> para usar en la salida. El XML resultante se ve así:

<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="/error.xsl"?> <Error><ProxyTime>2015-10-13T17:36:01Z</ProxyTime><ProxyHTTPCode>403</ProxyHTTPCode><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>9D3E05D20C1BD6AC</RequestId><HostId>WvdkvIRIDMjfa/1Oi3DGVOTR0hABCDEFGHIJKLMNOPQRSTUVWXYZ+B8thZahg7W/I/ExAmPlEAQ=</HostId></Error>

Luego modifico la salida que se muestra al usuario con las pruebas XSL para determinar qué condición de error ha arrojado S3:

<xsl:if test="//Code = ''AccessDenied''"> <p>It seems we may have provided you with a link to a resource to which you do not have access, or a resource which does not exist, or that our internal security mechanisms were unable to reach consensus on your authorization to view it.</p> </xsl:if>

Y el resultado final se ve así:

Lo anterior es un "acceso denegado" general porque no se proporcionaron credenciales. Aquí hay un ejemplo de una firma caducada.

No HostId el HostId en el resultado, ya que es feo y ruidoso, y, si alguna vez lo necesito, el proxy lo capturó y lo registró, y puedo hacer una referencia cruzada al ID de la solicitud.

Como beneficio adicional, por supuesto, ejecutar las solicitudes a través de mi proxy significa que puedo usar mi propio nombre de dominio y mi propio certificado SSL cuando publico contenido del paquete, y tengo registros de acceso en tiempo real sin demora. Cuando el proxy se encuentra en la misma región que el depósito, no hay cargo adicional por el paso adicional de transferencia de datos, y estoy muy contento con esta configuración.