AWS S3 Post Object rechaza campos de formulario adicionales
Estoy intentando configurar la clase de almacenamiento de una imagen cargada en un bucket de AWS S3. Lo tengo funcionando excepto para agregar la clase de almacenamiento a la solicitud. La documentación del objeto de publicación de S3 indica que puede haber un campo de entrada de formulario llamado "x-amz-storage-class", pero agregarlo, o cualquier otro campo, arroja un error de AWS que indica que hay demasiados campos de entrada para la publicación. Intenté agregarlo a la política de objetos, pero eso provoca un error de política: "Error de condición de política: [“ eq ”,“ $ x-amz-storage-class ”,“ ONEZONE_IA ”]”. Estoy usando JSP y los campos de entrada del formulario se muestran a continuación. Cualquier ayuda sería apreciada.
<input type="hidden" name="key" value="<%= imageFileName %>">
<input type="hidden" name="AWSAccessKeyId" value="<%= S3AccessKeyId %>">
<input type="hidden" name="acl" value="private">
<input type="hidden" name="success_action_redirect" value="<%= s3SuccessAction %>">
<input type="hidden" name="policy" value="<%= encPolicy %>" >
<input type="hidden" name="signature" value="<%= signature %>" >
<input type="hidden" name="Content-Type" value="image/jpeg">
<input type="hidden" name="x-amz-storage-class" value="ONEZONE_IA"> ***** CAUSES ERROR ****
Errores:
Invalid according to Policy: Policy Condition failed: [“eq”, “$x-amz-storage-class”, “STANDARD_IA”]
<Error>
<Code>AccessDenied</Code>
<Message>
Invalid according to Policy: Extra input fields: x-amz-storage-class
</Message>
<RequestId>1104FC046523752C</RequestId>
<HostId>
m0xPpMKJqBG6kZsdQfl/RY92dHprnvtGtrijHLqVtieM51ew+Mkp0mXGbTwKM7OsoUq6ZZUVIc0=
</HostId>
</Error>
Respuestas
Tengo esto funcionando ahora. La política tiene campos que deben coincidir con los campos del formulario. Se debe agregar "x-amz-storage-class" tanto a los campos del formulario como a la política. Supongo que la política codificada está firmada por razones de seguridad, lo que la hace segura y los campos del formulario deben coincidir con los campos de la política para garantizar que no se hayan modificado. Por qué ambos son necesarios está más allá de mi comprensión. El código corregido está a continuación:
<fieldset>
<input type="hidden" name="key" value="<%= imageFileName %>">
<input type="hidden" name="AWSAccessKeyId" value="<%= S3AccessKeyId %>">
<input type="hidden" name="acl" value="private">
<input type="hidden" name="success_action_redirect" value="<%= s3SuccessAction %>">
<input type="hidden" name="policy" value="<%= encPolicy %>" >
<input type="hidden" name="signature" value="<%= signature %>" >
<input type="hidden" name="Content-Type" value="image/jpeg">
<input type="hidden" name="x-amz-storage-class" value="ONEZONE_IA">
public static String encodeS3Policy(String s3SuccessAction, String bucket) throws Exception
{
String policy =
"{\"expiration\": \"2040-01-01T00:00:00Z\"," +
"\"conditions\": [" +
"{\"bucket\": \"" + bucket + "\"}," +
"[\"starts-with\", \"$key\", \"\"]," + "{\"acl\": \"private\"}," + "{\"success_action_redirect\": \"" + s3SuccessAction + "\"}," + "[\"starts-with\", \"$Content-Type\", \"\"]," +
"{\"x-amz-storage-class\": \"ONEZONE_IA\"}," +
"[\"content-length-range\", 0, 10485760]" + // 10 MB max file up load
"]" +
"}";
policy.replaceAll("\n","").replaceAll("\r","");
// Encode the policy
String encPolicy = Base64.getEncoder().encodeToString(policy.getBytes("UTF-8"));
return encPolicy;
}
Para completar y porque no es obvio, los valores de la clase de almacenamiento son:
Default: STANDARD
STANDARD | REDUCED_REDUNDANCY | GLACIER | STANDARD_IA | ONEZONE_IA | INTELLIGENT_TIERING | DEEP_ARCHIVE
Aquí está la documentación de AWS S3 Post Object