Ajouter des données à un objet S3

91

Disons que j'ai une machine que je souhaite pouvoir écrire dans un certain fichier journal stocké sur un compartiment S3.

Donc, la machine doit avoir des capacités d'écriture dans ce compartiment, mais je ne veux pas qu'elle ait la capacité d'écraser ou de supprimer les fichiers de ce compartiment (y compris celui sur lequel je veux écrire).

Donc, fondamentalement, je veux que ma machine puisse uniquement ajouter des données à ce fichier journal, sans le remplacer ni le télécharger.

Existe-t-il un moyen de configurer mon S3 pour qu'il fonctionne comme ça? Peut-être y a-t-il une politique IAM que je peux y attacher pour qu'elle fonctionne comme je le souhaite?

Théodore
la source
Vous ne pouvez pas modifier les objets dans S3. Pourriez-vous simplement ajouter un nouveau fichier journal? Ce serait un meilleur modèle et prendrait en charge plusieurs clients simultanés.
jarmod
@jarmod Oui, j'y ai pensé, mais le problème est que si un attaquant réussit à accéder à mon serveur, il aura la possibilité de supprimer le fichier local stocké dessus, avant qu'il ne soit envoyé dans le compartiment S3 (ce qui disons arrive à la fin de la journée).
Theodore
Vous pouvez également consulter les journaux CloudWatch. Laissez-le gérer la complexité de la collecte et du stockage de vos journaux, fournissez des fonctionnalités de recherche, des politiques de rétention et vous permettez de générer des alertes basées sur des mesures que vous pouvez personnaliser pour vos journaux.
jarmod
1
Vous pouvez également jeter un œil à Google BigQuery. Vous pouvez l'utiliser pour résoudre votre problème.
Daniel777

Réponses:

133

Malheureusement, vous ne pouvez pas.

S3 n'a pas d'opération "append". * Une fois qu'un objet a été téléchargé, il n'y a aucun moyen de le modifier en place; votre seule option est de télécharger un nouvel objet pour le remplacer, ce qui ne répond pas à vos exigences.

*: Oui, je sais que ce post date de quelques années. C'est toujours exact, cependant.

duskwuff -inactif-
la source
Puis-je savoir qu'en utilisant le téléchargement en plusieurs parties, pouvons-nous y parvenir?
Anjali
1
Le téléchargement en plusieurs parties vous permettra d'obtenir les données dans S3 sans télécharger l'objet d'origine, mais il ne vous permettra pas d'écraser directement l'objet d'origine. Voir par exemple docs.aws.amazon.com/AmazonS3/latest/API/ ... Vous pouvez alors supprimer l'ancien objet / renommer le nouveau. Ce n'est cependant pas ce que la question pose.
MikeGM
Je pense que l'utilisation de Multipart Upload peut réellement fonctionner. Toutes vos pièces sont des segments séquentiels du même fichier. Si la partie réussit à être téléchargée, vous pouvez éventuellement valider le téléchargement pour pouvoir lire le fichier. Ainsi, tant que vous n'avez pas besoin de lire le contenu du fichier, vous pouvez ajouter le même téléchargement en plusieurs parties.
cerebrotecnologico
@cerebrotecnologico Je ne pense toujours pas qu'il réponde aux exigences de l'OP. À ma connaissance, il n'y a aucun moyen de restreindre un utilisateur S3 à effectuer des téléchargements en plusieurs parties qui s'ajoutent à un objet - s'ils peuvent effectuer un téléchargement en plusieurs parties, ils peuvent télécharger le contenu de leur choix.
duskwuff -inactive-
16

Comme l'indique la réponse acceptée, vous ne pouvez pas. La meilleure solution que je connaisse est d'utiliser:

AWS Kinesis Firehose

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

Leur exemple de code semble compliqué, mais le vôtre peut être très simple. Vous continuez à effectuer des opérations PUT (ou BATCH PUT) sur un flux de livraison Kinesis Firehose dans votre application (à l'aide du kit AWS SDK), et vous configurez le flux de livraison Kinesis Firehose pour envoyer vos données en streaming vers un compartiment AWS S3 de votre choix (dans le Console AWS Kinesis Firehose).

entrez la description de l'image ici

Ce n'est toujours pas aussi pratique que >>depuis la ligne de commande Linux, car une fois que vous avez créé un fichier sur S3, vous devez à nouveau gérer le téléchargement, l'ajout et le téléchargement du nouveau fichier, mais vous ne devez le faire qu'une fois par lot de lignes. que pour chaque ligne de données, vous n'avez donc pas à vous soucier des frais énormes en raison du volume des opérations d'ajout. Peut-être que cela peut être fait mais je ne vois pas comment le faire à partir de la console.

Sridhar Sarnobat
la source
8
Notez qu'il y a soit un temps maximum (900 secondes depuis la création du fichier) soit une taille maximum (taille de fichier de 128 Mo) pour faire cela - ce qui signifie que Kinesis Firehose s'ajoutera au même fichier S3 jusqu'à ce qu'il atteigne l'une de ces limites: docs.aws .amazon.com / firehose / latest / dev / create-configure.html
Yaron Budowski
Pouvez-vous utiliser un seul fichier S3 comme sortie sur le Firehose? Cela semble un peu compliqué de devoir fusionner plusieurs fichiers dans un compartiment S3.
Jón Trausti Arason
1
Malheureusement non. Je souhaite moi aussi qu'il y ait une meilleure solution.
Sridhar Sarnobat
Ouais c'est malheureux. Je suis surtout préoccupé par la condition de concurrence si je télécharge et ajoute manuellement des enregistrements à un seul objet S3. J'ai pensé à ajouter les enregistrements à SQS, puis à utiliser une logique avec SNS + Lambda pour interroger le SQS, puis à écrire les nouvelles entrées dans l'objet S3.
Jón Trausti Arason
6

Les objets sur S3 ne peuvent pas être ajoutés. Vous avez 2 solutions dans ce cas:

  1. copiez toutes les données S3 dans un nouvel objet, ajoutez le nouveau contenu et réécrivez dans 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 deuxième option consiste à utiliser Kinesis Firehose. C'est assez simple. Vous devez créer votre flux de diffusion Firehose et lier la destination au compartiment S3. C'est ça!
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
    }); 
}
Bharthan
la source
Pouvez-vous utiliser un seul fichier S3 comme sortie?
Jón Trausti Arason
1

Comme d'autres l'ont indiqué précédemment, les objets S3 ne peuvent pas être ajoutés.
Cependant, une autre solution serait d'écrire dans les journaux CloudWatch, puis d' exporter les journaux que vous souhaitez vers S3 . Cela empêcherait également les attaquants qui accèdent à votre serveur de supprimer de votre compartiment S3, car Lambda ne nécessiterait aucune autorisation S3.

Leo Glowacki
la source
1

Au cas où quelqu'un souhaiterait ajouter des données à un objet avec un service de type S3, Alibaba Cloud OSS (Object Storage Service) le prend en charge de manière native .

OSS fournit le téléchargement d'ajout (via l'API AppendObject), qui vous permet d'ajouter directement du contenu à la fin d'un objet. Les objets téléchargés à l'aide de cette méthode sont des objets pouvant être ajoutés, tandis que les objets téléchargés à l'aide d'autres méthodes sont des objets normaux. Les données ajoutées sont instantanément lisibles.

Wanghq
la source
-1

J'ai eu le même problème et c'est ce que j'avais demandé

comment ajouter des données dans un fichier à l'aide d'AWS Lambda

Voici ce que je propose pour résoudre le problème ci-dessus:

Utilisez getObject pour récupérer du fichier existant

   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
});

Fonction d'écriture à ajouter dans le fichier

   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');
     });
}

J'espère que cette aide !!

Neeraj Kumar
la source
13
Votre writeToS3fonction écrasera un fichier, ne lui ajoutera pas.
duskwuff -inactif-
@ duskwuff-inactive- convenu, et il souffre également de conditions de concurrence si deux méthodes tentent de travailler sur le même objet, mais ce n'est pas vraiment différent des langages qui ont des chaînes ou des types immuables - vous simulez un ajout en retournant / écrasant avec un nouvel objet.
fatal_error