Maggio 02, 2024

Java Client per Amazon S3 con AWS SDK

AWS SDK mette a disposizione dello sviluppatore una serie di strumenti e API che permettono di interagire per via programmatica con i servizi di Amazon AWS come EC2, S3, SimpleDB e così via. In questo articolo riporto una descrizione ad alto livello di J4S3, un piccolo progetto che sto sviluppando per interagire con i servizi S3 di cloud storage e che fa uso delle API Java di AWS.

J4S3 sta per “Java client For S3” e implementa un client S3 a riga di comando che permette di:

  • criptare su file le proprie credenziali AWS con password-based encryption;
  • inviare o ricevere oggetti su un bucket Amazon S3.

L’idea è nata dall’esigenza di:

  • interagire con S3 da postazioni remote su cui non è presente interfaccia grafica;
  • utilizzare una soluzione java a riga di comando, alternativa ad altri noti client come AWS CLI o S3cmd;
  • rendere riservate le proprie credenziali AWS ed evitare di fornire AWS Id e AWS Key in chiaro su file system (tipicamente in ~/.aws/credentials);
  • interagire con S3 per via programmatica e avere un’alternativa ai servizi REST o alla classica navigazione da browser di S3;
  • personalizzare AWSCredentialsProvider, l’interfaccia di default per passare le proprie credenziali di accesso ai servizi di AWS.

SOURCE CODE (/giuseu/aws)

GIT
git clone https://gitlab.com/giuseppeurso-eu/aws

L’immagine di seguito mostra l’upload di una directory locale verso una bucket S3 su region ES_WEST_1.

giuseppe-urso-Java-Client-for-Amazon-S3-with-AWS-SDK-01Per poter accedere a S3 è necessario essere in possesso di un account Amazon AWS. Ulteriori dettagli sulle modalità di autenticazione e accesso ai servizi di Amazon AWS si trovano qui.

J4S3 utilizza una modalità di accesso ai bucket S3 basata su IAM. Una volta create la propria policy IAM, è possibile utilizzare J4S3 per cifrare su file (con password-based encryption), access ID e access KEY dell’utente AWS. Tale file, protetto da password, sarà  utilizzato per inviare oggetti su S3. Le immagini di segutio mostrano una visione ad alto livello delle due fasi.

giuseppe-urso-Java-Client-for-Amazon-S3-with-AWS-SDK-02

giuseppe-urso-Java-Client-for-Amazon-S3-with-AWS-SDK-03
Per avere subito una prima versione funzionante del tool, ho riutilizzato un implementazione di password-based encryption di esempio che avevo già realizzato in passato dove viene utilizzata una cifratura SHA-256 e  salt fisso. Il sorgente si trova qui e sono presenti alcuni esempi di encryption/decryption di dati fatti con JCA e  bouncycastle (ulteriori dettagli in questo articolo).

L’immagine sotto, mostra un diagramma delle classi di J4S3. L’oggetto PBECredentialsProvider implementa AWSCredentialsProvider e serve per recuperare le credenziali AWS dal file criptato da PasswordBasedEncryption di jca. L’oggetto TransportAgent contiene i metodi per interagire direttamente con AWS S3. Le classi in UI implementano una interfaccia utente a riga di comando molto basilare. Quando viene lanciato il jar eseguible di J4S3, il metodo main() di CLI gestisce interattivamente l’input dell’utente con l’oggetto System.in.

giuseppe-urso-Java-Client-for-Amazon-S3-with-AWS-SDK-04

Ecco un estratto del metodo implementato in PBECredentialsProvider per personalizzare la modalità di accesso alle credenziali AWS criptate su file.

[...]
public class PBECredentialsProvider implements AWSCredentialsProvider {
[...]
public AWSCredentials getCredentials() {
		
		String awsAccessId="";
		String awsAccessKey="";
		try {
			awsAccessId = retrieveAWSKey(awsAccessIdProperty);
			awsAccessKey = retrieveAWSKey(awsAccessKeyProperty);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		AWSCredentials awsc = new BasicAWSCredentials(awsAccessId, awsAccessKey);
		return awsc;
	}

Un altro oggetto interessante di AWS è il MultipleFileUpload molto utile per effettuare upload di grossi file in un più parti. Inoltre mette a disposizione una serie di metodi molto utili per calcolare la percentuale di dati trasferiti oppure il totale di bytes inviati. Ecco come ho realizzato una semplice progress bar che mi stampa a video lo stato del trasferimento (vedi immagine console).

private void uploadProgressBar(MultipleFileUpload multipleFileUpload){
      System.out.print("Progress:[=");
      try {
       while (multipleFileUpload.isDone() == false) {
        long perc = (long) multipleFileUpload.getProgress().getPercentTransferred();
        System.out.print("= ");
        System.out.print(perc+"%");
        if (perc<10) {
          System.out.print("\b\b\b");
        }else {
         System.out.print("\b\b\b\b");
        }
        Thread.currentThread();
        Thread.sleep(2000);
       }
      }catch (InterruptedException e) {
       e.printStackTrace();
      }
      System.out.print("\b] Done "+(long) multipleFileUpload.getProgress().getPercentTransferred()+" %\n");
      long total = multipleFileUpload.getProgress().getBytesTransferred();
      String roundOff = new DecimalFormat("#.##").format((double)total/1000000);
      System.out.println("Total transferred: "+total +" bytes (~ "+roundOff+ " MB)");
}

Per quanto riguarda il traffico di dati inviati verso S3, ho fatto un’indagine per verificare che l’interazione con AWS avvenisse su canale sicuro SSL. L’immagine di seguito mostra un estratto di analisi dei pacchetti fatto con tpcdump durante una sessione di upload dati.

giuseppe-urso-Java-Client-for-Amazon-S3-with-AWS-SDK-05

Related posts

Leave a Reply

Your email address will not be published.