Aggiungi dati a un oggetto S3


96

Diciamo che ho una macchina che voglio essere in grado di scrivere in un determinato file di registro memorizzato su un bucket S3.

Quindi, la macchina deve avere capacità di scrittura in quel bucket, ma non voglio che abbia la capacità di sovrascrivere o eliminare alcun file in quel bucket (incluso quello su cui voglio che scriva).

Quindi, fondamentalmente, voglio che la mia macchina sia in grado di aggiungere solo dati a quel file di registro, senza sovrascriverlo o scaricarlo.

C'è un modo per configurare il mio S3 in modo che funzioni in questo modo? Forse c'è qualche criterio IAM che posso allegare ad esso in modo che funzioni come voglio?


Non puoi modificare gli oggetti in S3. Potresti semplicemente aggiungere un nuovo file di registro? Sarebbe un modello migliore e supporterebbe più client simultanei.
jarmod

@jarmod Sì, ci ho pensato, ma il problema è che se un utente malintenzionato riesce ad accedere al mio server, avrà la possibilità di eliminare il file locale memorizzato su di esso, prima che fosse inviato al bucket S3 (che diciamo succede alla fine della giornata).
Theodore

Potresti anche voler dare un'occhiata ai log di CloudWatch. Lascia che gestisca la complessità della raccolta e dell'archiviazione dei tuoi registri, fornisca strutture di ricerca, criteri di conservazione e ti consenta di generare avvisi basati su metriche che puoi personalizzare per i tuoi registri.
jarmod

1
Potresti anche dare un'occhiata a Google BigQuery. Puoi usarlo per risolvere il tuo problema.
Daniel777

Risposte:


137

Purtroppo non puoi.

S3 non ha un'operazione di "aggiunta". * Una volta che un oggetto è stato caricato, non c'è modo di modificarlo in posizione; la tua unica opzione è caricare un nuovo oggetto per sostituirlo, che non soddisfa i tuoi requisiti.

*: Sì, lo so che questo post risale a un paio di anni fa. È comunque accurato.


Posso sapere che utilizzando Multipart Upload possiamo ottenere questo risultato?
Anjali

2
Il caricamento in più parti ti consentirà di ottenere i dati in S3 senza scaricare l'oggetto originale, ma non ti consentirà di sovrascrivere direttamente l'oggetto originale. Vedere ad esempio docs.aws.amazon.com/AmazonS3/latest/API/… È quindi possibile eliminare il vecchio oggetto / rinominare quello nuovo. Questo, tuttavia, non è ciò che si pone la domanda.
MikeGM

Penso che l'utilizzo di Multipart Upload possa effettivamente funzionare. Tutte le tue parti sono segmenti sequenziali dello stesso file. Se la parte riesce a essere caricata, potresti eventualmente impegnare il caricamento per poter leggere il file. Quindi, fino a quando non è necessario leggere il contenuto del file, è possibile aggiungerlo utilizzando lo stesso caricamento in più parti.
cerebrotecnologico

@cerebrotecnologico Continuo a non pensare che soddisfi i requisiti dell'OP. Non sono a conoscenza di alcun modo per limitare un utente S3 a eseguire caricamenti in più parti che si aggiungono a un oggetto: se possono eseguire un caricamento in più parti, possono caricare qualsiasi contenuto desiderano.
duskwuff -inattivo-

19

Come afferma la risposta accettata, non puoi. La soluzione migliore di cui sono a conoscenza è usare:

AWS Kinesis Firehose

https://aws.amazon.com/kinesis/firehose/

Il loro esempio di codice sembra complicato ma il tuo può essere davvero semplice. Continui a eseguire operazioni PUT (o BATCH PUT) su un flusso di distribuzione Kinesis Firehose nella tua applicazione (utilizzando l'SDK AWS) e configuri il flusso di consegna Kinesis Firehose per inviare i tuoi dati in streaming a un bucket AWS S3 di tua scelta (nel Console AWS Kinesis Firehose).

inserisci qui la descrizione dell'immagine

Non è ancora così conveniente come >>dalla riga di comando di Linux, perché una volta creato un file su S3 devi di nuovo occuparti di scaricare, aggiungere e caricare il nuovo file ma devi farlo solo una volta per batch di righe piuttosto rispetto a ogni riga di dati, quindi non devi preoccuparti di addebiti enormi a causa del volume delle operazioni di aggiunta. Forse si può fare ma non vedo come farlo dalla console.


8
Nota che c'è un tempo massimo (900 secondi dalla creazione del file) o una dimensione massima (dimensione del file 128mb) per farlo, il che significa che Kinesis Firehose si accoderà allo stesso file S3 fino a raggiungere uno di questi limiti: docs.aws .amazon.com / firehose / latest / dev / create-configure.html
Yaron Budowski

Puoi usare un singolo file S3 come output sulla Firehose? Sembra un po 'complicato dover unire più file in un bucket S3.
Jón Trausti Arason

1
Sfortunatamente no. Anch'io vorrei che ci fosse una soluzione migliore.
Sridhar Sarnobat,

Sì, è un peccato. Sono principalmente preoccupato per le condizioni di gara se scarico e accodo manualmente i record a un singolo oggetto S3. Ho pensato di aggiungere i record a SQS e quindi di utilizzare una logica con SNS + Lambda per eseguire il polling di SQS e quindi scrivere le nuove voci nell'oggetto S3.
Jón Trausti Arason

7

Gli oggetti su S3 non possono essere aggiunti. Hai 2 soluzioni in questo caso:

  1. copia tutti i dati S3 su un nuovo oggetto, aggiungi il nuovo contenuto e riscrivi su S3.
function writeToS3(input) {
    var content;
    var getParams = {
        Bucket: 'myBucket', 
        Key: "myKey"
    };

    s3.getObject(getParams, function(err, data) {
        if (err) console.log(err, err.stack);
        else {
            content = new Buffer(data.Body).toString("utf8");
            content = content + '\n' + new Date() + '\t' + input;
            var putParams = {
                Body: content,
                Bucket: 'myBucket', 
                Key: "myKey",
                ACL: "public-read"
             };

            s3.putObject(putParams, function(err, data) {
                if (err) console.log(err, err.stack); // an error occurred
                else     {
                    console.log(data);           // successful response
                }
             });
        }
    });  
}
  1. La seconda opzione è usare Kinesis Firehose. Questo è abbastanza semplice. Devi creare il tuo flusso di consegna Firehose e collegare la destinazione al bucket S3. Questo è tutto!
function writeToS3(input) {
    var content = "\n" + new Date() + "\t" + input;
    var params = {
      DeliveryStreamName: 'myDeliveryStream', /* required */
      Record: { /* required */
        Data: new Buffer(content) || 'STRING_VALUE' /* Strings will be Base-64 encoded on your behalf */ /* required */
      }
    };

    firehose.putRecord(params, function(err, data) {
      if (err) console.log(err, err.stack); // an error occurred
      else     console.log(data);           // successful response
    }); 
}

Puoi usare un singolo file S3 come output?
Jón Trausti Arason

2

Nel caso in cui qualcuno desideri aggiungere dati a un oggetto con un servizio simile a S3, Alibaba Cloud OSS (Object Storage Service) lo supporta in modo nativo .

OSS fornisce il caricamento delle aggiunte (tramite l'API AppendObject), che consente di aggiungere direttamente il contenuto alla fine di un oggetto. Gli oggetti caricati utilizzando questo metodo sono oggetti aggiungibili, mentre gli oggetti caricati utilizzando altri metodi sono oggetti normali. I dati aggiunti sono immediatamente leggibili.


1

Come altri hanno affermato in precedenza, gli oggetti S3 non possono essere aggiunti.
Tuttavia, un'altra soluzione sarebbe scrivere nei log di CloudWatch e quindi esportare i log che desideri su S3 . Ciò impedirebbe anche a qualsiasi utente malintenzionato che accede al tuo server di eliminare dal tuo bucket S3, poiché Lambda non richiederebbe alcuna autorizzazione S3.


-1

Ho avuto il problema simile e questo è quello che avevo chiesto

come aggiungere dati nel file utilizzando AWS Lambda

Ecco cosa mi viene in mente per risolvere il problema di cui sopra:

Usa getObject per recuperare dal file esistente

   s3.getObject(getParams, function(err, data) {
   if (err) console.log(err, err.stack); // an error occurred
   else{
       console.log(data);           // successful response
       var s3Projects = JSON.parse(data.Body);
       console.log('s3 data==>', s3Projects);
       if(s3Projects.length > 0) {
           projects = s3Projects;
       }   
   }
   projects.push(event);
   writeToS3(); // Calling function to append the data
});

Funzione di scrittura da aggiungere al file

   function writeToS3() {
    var putParams = {
      Body: JSON.stringify(projects),
      Bucket: bucketPath, 
      Key: "projects.json",
      ACL: "public-read"
     };

    s3.putObject(putParams, function(err, data) {
       if (err) console.log(err, err.stack); // an error occurred
       else     console.log(data);           // successful response
        callback(null, 'Hello from Lambda');
     });
}

Spero che questo aiuto !!


13
La tua writeToS3funzione sovrascriverà un file, non vi verrà aggiunto.
duskwuff -inattivo-

@ duskwuff-inactive- concordato, e inoltre soffre di race condition se due metodi tentano di funzionare sullo stesso oggetto, ma questo non è molto diverso dai linguaggi che hanno stringhe o tipi immutabili: simuli un'appendice restituendo / sovrascrivendo con un nuovo oggetto.
fatal_error
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.