2012-01-24 21 views
5

Sto provando a caricare un file con Amazon Java SDK, tramite caricamento multipart. L'idea è di passare un id di caricamento a un'applet, che mette le parti del file in un bucket di sola lettura. Andando in questo modo, evito di memorizzare le credenziali AWS nell'applet.Metti il ​​file su Amazon S3 usando il caricamento multipart

Nei miei test, genera un id di caricamento con boto (python) e memorizza un file nel bucket. Funziona bene

L'applet riceve un "403 accesso negato" dall'S3 e non ho idea del perché.

Ecco il mio codice (che è parzialmente tratto da 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)); 
} 

Nel registro applet di debug, ho trovato questo, quindi:

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 

si fa a trovare eventuali errori evidenti nella codice?

Grazie, Stefan

risposta

6

Mentre il vostro caso d'uso è sana e questo è un evidente tentativo anzi, non credo che il Multipart Upload API è stato progettato per permettere questo e in realtà si sta violando una barriera di sicurezza:

L'ID di caricamento è semplicemente un identificatore per assistere l'API di caricamento multipart assemblando le parti insieme (ovvero più come una chiave di oggetto temporanea) non un meccanismo di sicurezza dedicato (vedi sotto). Di conseguenza, hai ancora bisogno di credenziali di accesso adeguate, ma dal momento che stai chiamando AmazonS3Client(), che Costruisce un nuovo client Amazon S3 che effettuerà richieste anonime ad Amazon S3, la tua richiesta produce un 403 accesso negato di conseguenza.

cosa si sta cercando di raggiungere è possibile tramite Uploading Objects Using Pre-Signed URLs, anche se solo senza la funzionalità multipart, purtroppo:

Un URL pre-firmato consente di accedere all'oggetto identificato nella URL, a condizione che il il creatore dell'URL pre-firmato dispone delle autorizzazioni per l'accesso a . Cioè, se ricevi un URL pre-firmato per caricare un oggetto , puoi caricare l'oggetto solo se il creatore dell'URL pre-firmato ha le autorizzazioni necessarie per caricare quell'oggetto.

[...] Gli URL pre-firmato sono utili se si desidera che l'utente/cliente di essere caricati in grado una specifica oggetto [...], ma non si richiede loro di avere la sicurezza AWS credenziali o permessi. Quando si crea un URL pre-firmato, è necessario specificare le proprie credenziali di sicurezza, specificare un nome bucket un oggetto , un metodo HTTP (PUT di caricamento degli oggetti) e una data di scadenza e una data di scadenza. [...]

La citazione lenghty illustra, perché un sistema come questo probabile ha bisogno di un progetto di sicurezza più complesso di 'solo' distribuendo un ID di upload (il più simile entrambi potrebbero apparire a prima vista) .

Ovviamente uno vorrebbe essere in grado di utilizzare entrambe le funzionalità insieme, ma questo non sembra essere ancora disponibile.

+1

Grazie mille per i vostri pensieri. Anche se è possibile eseguire richieste anonime a S3 se il bucket è pubblicamente disponibile, la tua ipotesi sembra vera, che i caricamenti multipart non sono fatti per il mio caso. E quegli URL pre-firmati non sono disponibili per i caricamenti multipart è troppo male. Tuttavia, ho deciso di utilizzare il meccanismo AWS IAM per impostare un criterio writeonly per il bucket e per memorizzare le credenziali per un nuovo utente di conseguenza configurato nell'applet. Dal punto di vista della sicurezza, dovrebbe andare bene. – schneck

+0

@schneck: Facilitare una politica di sola scrittura IAM è un'eccellente alternativa, anzi, mi sono concentrato troppo su * come * stai cercando di raggiungere il tuo obiettivo piuttosto che sul caso di utilizzo effettivo - potresti farlo ancora di più [Making Richieste utilizzando le credenziali temporanee dell'utente IAM] (http://docs.amazonwebservices.com/AmazonS3/latest/dev/AuthUsingTempSessionTokenJava.html) per evitare completamente la memorizzazione di credenziali permanenti all'interno dell'applet. –

+0

Il pericolo con un bucket pubblico di sola scrittura non è che qualcuno potrebbe spammare il tuo secchio usando nient'altro che curl? O mi sta sfuggendo qualcosa? – sethcall

Problemi correlati