Pubblicato il 02/09/2023 da alnao nella categoria AWS

Simple Storage Service, abbreviato con la sigla S3, è il principale servizio di archiviazione del servizio Cloud di AWS, studiato per memorizzare e recuperare qualsiasi volume di dati, in qualunque momento e da qualunque luogo. Le caratteristiche principali del servizio sono: gli oggetti sono salvati in contenitori chiamati bucket (non a caso il logo di questo servizio è proprio un secchio), ogni elemento ha un nome (key), gli oggetti sono organizzati in strutture (path), l’accesso agli oggetti può essere personalizzato grazie a regole IAM, gli accessi possono essere salvati in registri specifici nel servizio CloudWatch. E’ possibile cancellare o spostare oggetti e il servizio permette di attivare il sistema di versioning per avere la storia di tutti gli oggetti. Per qualsiasi informazione e approfondimenti si può fare riferimento alla pagina dedicata al servizio S3 nel sito ufficiale.


La AWS-CLI mette a disposizione tutta una serie di comandi per la gestione dei bucket e degli oggetti, in particolare “mb” può essere usato per creare bucket:

$ aws s3 mb s3://bucket-name

ricordandosi che il nome deve essere globalmente unico (globally unique unique across all of Amazon S3) e deve rispettare le regole imposte da AWS. La lista dei bucket disponibili si recupera con il comando:

$ aws s3 ls

e per cancellare un bucket (che non contiene nessun oggetto) si usa il comando rb:

$ aws s3 rb s3://bucket-name

Per ottenere la lista di tutti gli oggetti contenuti in un bucket:

$ aws s3 ls bucket-name

E per muovere oggetti tra bucket o scaricare un oggetto cancellandolo si usa la sintassi:

$ aws s3 mv s3://bucket-name/example.txt s3://bucket-name2/
$ aws s3 mv s3://bucket-name/filename.txt ./

Mentre per copiare tra bucket o dal sistema locale da/per un bucket si usa la sintassi:

$ aws s3 cp s3://bucket-name/example.txt s3://my-bucket/
$ aws s3 cp ./filename.txt s3://bucket-name
$ aws s3 cp s3://bucket-name/filename.txt ./

I comandi possono essere combinati con i comandi Linux, per esempio per scrivere o leggere un oggetto:

$ echo "hello world" | aws s3 cp - s3://bucket-name/filename.txt
$ aws s3 cp s3://bucket-name/filename.txt -

Il comando Sync permette di tenere sincronizzato una cartella locale con un bucket, quindi eventuali orfani vengono cancellati e nuovi file vengono copiati, la sintassi preve solo la cartella sorgente e il bucket di destinazione:

$ aws s3 sync . s3://my-bucket/path

Per svuotare un bucket da tutti gli oggetti contenuti si può usare il comando rm con il parametro ricorsivo:

$ aws s3 rm s3://my-bucket/path --recursive

è ovvio che bisogna sempre prestate attenzione a questo ultimo comandi in quanto rimuove tutti gli oggetti e, senza sistema di versionamento attivo, gli oggetti vengono cancellati in maniera permanente. Tutti i parametri e le caratteristiche di questo comando sono disponibili alla pagina della documentazione ufficiale.


I template CloudFormation spesso hanno al proprio interno definizione o riferimenti a bucket S3, il tipo specifico AWS::S3::Bucket che ha come unico parametro obbligatorio il nome (che deve sempre rispettare le regole previste da AWS)

Resources:
  S3Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Ref NomeBucket

La documentazione ufficiale è ricca di esempi e può essere sempre consultata come fonte principale di informazioni. Il più semplice esempio è la gestione di siti web esposti dallo stesso servizio S3 senza l’uso di CloudFront o altri servizi dedicati, ispirato alla documentazione ufficiale con in aggiunta le regole ACL, nel template è indispensabile aggiungere la regola di accesso al bucket tramite un oggetto di tipo BucketPolicy:

S3BucketPolicy:
  Type: AWS::S3::BucketPolicy
  Properties:
    Bucket: !Ref NomeBucket
    PolicyDocument:
    Version: 2012-10-17
    Statement:
     - Sid: AllowSSLRequestsOnly
       Action: 's3:GetObject'
       Effect: Allow
       Resource: !Join
         - ''
         - - 'arn:aws:s3:::'
           - !Ref NomeBucket
           - /*
       Principal: '*'

L’esempio completo funzionante può essere trovato al solito repository

github.com/alnao/AWSCloudFormationExamples/tree/master/Esempio03bucketS3sito

La libreria CDK mette a disposizione classi per la gestione dei bucket, la documentazione ufficiale è ricca di esempi pratici. Per il linguaggio Java la principale risorsa è proprio il builder di Bucket:

Bucket bucket = Bucket.Builder.create(this, "MyBucket")
  .versioned(true)
  .encryption(BucketEncryption.KMS_MANAGED)
  .build();

Per il linguaggio Python la creazione di bucket è ancora più semplice, un esempio ripreso dalla guida ufficiale:

from aws_cdk import (aws_s3 as s3,core)
class MyStack(core.Stack):
  def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
  super().__init__(scope, id, **kwargs)
  # Create an S3 bucket
  bucket = s3.Bucket(self, "MyBucket",
    bucket_name="my-unique-bucket-name",#unique bucket name
    versioned=True, # enable versioning for the bucket
    encryption=s3.BucketEncryption.S3_MANAGED
  )
app = core.App()
MyStack(app, "MyStack")
app.synth()

La libreria SDK è ricca di classi e metodi per la gestione dei bucket e dei contenuti, per il linguaggio di programmazione Python il sito ufficiale mette a disposizione diversi esempi i principali metodi messi a disposizione del servizio S3 sono:

#Lista dei bucket
s3_client.list_buckets()["Buckets"]

#Lista di oggetti
response = s3_client.list_objects_v2(
  Bucket=bucket_name, Delimiter="/",
  Prefix=path,
)
if "Contents" in response:
  response["objects"]=response["Contents"]
if "CommonPrefixes" in response:
  response["folders"]=response["CommonPrefixes"]

#Lista di oggetti con metodo paginante
s3_paginator = s3_client.get_paginator('list_objects_v2')
for page in s3_paginator.paginate(Bucket=bucket_name, 
   Prefix=path, Delimiter='/'): #, StartAfter=start_after):
if "Contents" in page:
  response["objects"]=response["objects"] + page["Contents"] #sum to append
if "CommonPrefixes" in page:
  response["folders"]=response["folders"] + page["CommonPrefixes"] #sum to append

#Contenuto di un file di testo
content = s3_client.get_object(Bucket=bucket_name, Key=key)["Body"].iter_lines()

#Scrivere un file di testo
string_encoded = body.encode("utf-8")
s3_client.put_object(Bucket=bucket_name, Key=key, Body=string_encoded)

Nel la libreria per il linguaggio Java le classi disponibili sono nel package:

software.amazon.awssdk.services.s3

Per esempio per ottenere la lista completa di tutti i bucket si può usare il semplice metodo:

S3Client client = S3Client.builder().build();
...
public static List<Bucket> getBucketList(S3Client s3Client){
  ArrayList<Bucket> l=new ArrayList<Bucket>();
  ListBucketsRequest listBucketsRequest = ListBucketsRequest.builder().build();
  ListBucketsResponse listBuckets = s3Client.listBuckets(listBucketsRequest);
  listBuckets.buckets().stream().forEach(x -> l.add(x));
  return l;
}

Un semplice esempio dei vari metodi messi a disposizione della libreria può essere trovato al solito repository oppure mella documentazione ufficiale sono disponibili molti esempi di gestione dei bucket

MENU