2012-01-24 9 views
5

Estoy tratando de cargar un archivo con Amazon Java SDK, a través de la carga de varias partes. La idea es pasar un ID de carga a un applet, que coloca las partes del archivo en un solo depósito. Yendo de esta manera, evito almacenar las credenciales de AWS en el applet.Poner el archivo en Amazon S3 usando la carga de varias partes

En mis pruebas, genero un id de carga con boto (python) y almaceno un archivo en el cubo. Eso funciona bien

Mi Applet obtiene un "Acceso 403 denegado" del S3, y no tengo idea de por qué.

Aquí está mi código (que se toma parcialmente de http://docs.amazonwebservices.com/AmazonS3/latest/dev/llJavaUploadFile.html):

AmazonS3 s3Client = new AmazonS3Client(); 
List<PartETag> partETags = new ArrayList<PartETag>(); 

long contentLength = file.length(); 
long partSize = Config.getInstance().getInt("part_size"); 
String bucketName = Config.getInstance().getString("bucket"); 
String keyName = "mykey"; 
String uploadId = getParameter("upload_id"); 

try { 
    long filePosition = 0; 
    for (int i = 1; filePosition < contentLength; i++) { 

     partSize = Math.min(partSize, (contentLength - filePosition)); 

     // Create request to upload a part. 
     UploadPartRequest uploadRequest = new UploadPartRequest() 
      .withBucketName(bucket).withKey(keyName) 
      .withUploadId(uploadId).withPartNumber(i) 
      .withFileOffset(filePosition) 
      .withFile(file) 
      .withPartSize(partSize); 

     // Upload part and add response to our list. 
     partETags.add(s3Client.uploadPart(uploadRequest).getPartETag()); 

     filePosition += partSize; 
    } 

    System.out.println("Completing upload"); 
    CompleteMultipartUploadRequest compRequest = new 
       CompleteMultipartUploadRequest(bucket, 
              keyName, 
              uploadId, 
              partETags); 

    s3Client.completeMultipartUpload(compRequest); 
} catch (Exception e) { 
    s3Client.abortMultipartUpload(new AbortMultipartUploadRequest(
      bucketName, keyName, uploadId)); 
} 

En el registro de applet de depuración, encuentro esto, entonces:

INFO: Sending Request: PUT https://mybucket.s3.amazonaws.com /mykey Parameters: (uploadId: V4hwobOLQ1rYof54zRW0pfk2EfhN7B0fpMJTOpHOcmaUl8k_ejSo_znPI540.lpO.ZO.bGjh.3cx8a12ZMODfA--, partNumber: 1,) Headers: (Content-Length: 4288546, Content-Type: application/x-www-form-urlencoded; charset=utf-8,) 
24.01.2012 16:48:42 com.amazonaws.http.AmazonHttpClient handleErrorResponse 
INFO: Received error response: Status Code: 403, AWS Service: null, AWS Request ID: DECF32CCFEE9EBF0, AWS Error Code: AccessDenied, AWS Error Message: Access Denied, S3 Extended Request ID: xtL1ixsGM2/vsxJ+cZRHpkPZ23SMfP8hZZjQCQnp8oWGwdS2/aGfYgomihyqaDCQ 

¿Encuentra los fallos obvios en el ¿código?

Gracias, Stefan

Respuesta

6

Mientras su caso de uso es de sonido y esto es un intento obvio de hecho, no creo que la Multipart Upload API ha sido diseñado para permitir esto y en realidad se está violando una barrera de seguridad:

El ID de carga es simplemente un identificador para ayudar al Multipart Upload API al ensamblar las piezas (es decir, más como una llave de objeto temporal) que como un mecanismo de seguridad dedicado (ver a continuación). En consecuencia, todavía necesita credenciales de acceso adecuadas, pero como llama al AmazonS3Client(), Construye un nuevo cliente de Amazon S3 que realizará solicitudes anónimas a Amazon S3, su solicitud arroja un 403 Acceso denegado en consecuencia.

Lo que estamos tratando de lograr es posible a través de Uploading Objects Using Pre-Signed URLs, aunque sólo sin la funcionalidad de varias partes, por desgracia:

Una URL pre-firmado le da acceso al objeto identificado en la URL, siempre que el El creador de la URL pre-firmada tiene permisos para acceder a ese objeto. Es decir, si recibe una URL firmada previamente para cargar un objeto , puede cargar el objeto solo si el creador de la URL pre-firmada tiene los permisos necesarios para cargar ese objeto.

[...] Las URL previamente firmadas son útiles si desea que su usuario/cliente sea capaz de subida un objeto específico [...], pero no les obligan a tener la seguridad de AWS credenciales o permisos. Cuando crea una URL firmada previamente, debe proporcionar sus credenciales de seguridad, especificar un nombre de cubo, una clave de objeto , un método HTTP (PUT de cargar objetos) y una fecha de caducidad y hora. [...]

La cita ilustra devuelvan todo, ¿por qué un sistema como este probable necesita un diseño de seguridad más complejo que 'sólo' la entrega de un ID de carga (lo más similar tanto podría parecer a primera vista) .

Obviamente, uno quisiera poder utilizar ambas funciones juntas, pero esto no parece estar disponible aún.

+1

Muchas gracias por sus pensamientos. Incluso dado que es posible realizar solicitudes anónimas a S3 si el depósito está disponible públicamente, su suposición parece cierta, que las subidas de varias partes no se realizan para mi caso. Y que las URL pre-firmadas no están disponibles para cargas de varias partes es una lástima. Sin embargo, decidí usar el mecanismo AWS IAM para establecer una política de solo escritura para el depósito y para almacenar las credenciales para un nuevo usuario configurado de acuerdo en el applet. Desde la perspectiva de seguridad, debería estar bien. – schneck

+0

@schneck: Facilitar una política de solo escritura de IAM es una excelente alternativa, me he centrado demasiado en * cómo * está tratando de lograr su objetivo en lugar del caso real de uso; podría llevar eso aún más allá al [Hacer Solicitudes de uso de credenciales temporales de usuario de IAM] (http://docs.amazonwebservices.com/AmazonS3/latest/dev/AuthUsingTempSessionTokenJava.html) para evitar por completo el almacenamiento de credenciales permanentes dentro de su applet. –

+0

¿No es el peligro con un cubo de solo escritura, público, que alguien pueda enviar correo no deseado con tan solo usar curl? ¿O me estoy perdiendo algo? – sethcall

Cuestiones relacionadas