Il servizio Elastic Container Registry (abbreviato con la sigla ECR) è un servizio di registro delle immagini container Docker gestito da AWS che offre elevatissimi livelli di sicurezza, scalabilità e affidabilità. ECR supporta i repository pubblici oppure privati, la sicurezza viene sempre gestita con IAM, in tal modo solo utenti specifici o risorse specifiche possono accedere ai repository e alle immagini contenute. È consigliato l’uso della CLI per inviare, estrarre e gestire le immagini Docker e gestire le varie versioni delle immagini, senza la CLI diventa quasi impossibile usare questo servizio tanto che nella console web è possibile recuperare la sequenza di comandi per inviare in ECR una immagine tramite una combinazione di comandi CLI di AWS e CLI nativa di docker.

Per i Repository pubblici è sempre consigliato far riferimento alla guida utente di Amazon ECR Public. Il servizio si basa su questi concetti che è importante conoscere:

  • Registro: registri privati ECR a ogni account AWS; è possibile crare uno o più repository nel registro e archiviare in questi repository immagini Docker
  • Token di autorizzazione: token autorizzativi finalizzati all’estrazione delle immagini tramite client in maniera sicura
  • Archivio: un repository Amazon ECR contiene le immagini Docker, le immagini Open Container Initiative (OCI) e gli artefatti compatibili.
  • Policy del repository: policy per regolare l’accesso ai repository e al contenuto presente
  • Immagine: immagine docker del container. Possono essere immagini localmente su un ambiente di sviluppo oppure definizioni di attività Amazon ECS e nelle specifiche pod di Kubernetes tramite EKS.

Con Amazon ECR, si paga solo per la quantità di dati archiviati nei repository e per il trasferimento dei dati dagli invii e dalle estrazioni di immagini. Di base i nuovi clienti ricevono 500Mb al mese di archiviazione per i repository privati per il solo primo anno con il piano gratuito AWS, mentre i clienti nuovi e quelli esistenti ottengono 50 GB al mese di spazio di archiviazione sempre gratuito per i loro repository pubblici. L’archiviazione costa 0,10 USD per GB al mese per i dati archiviati in repository pubblici o privati, a questi costi bisogna sempre ricordarsi di aggiungere il costo del traffico di rete generato. Per tutti i dettagli e le informazioni, è consigliato consultare la pagina dei prezzi di ECR.

Da console web è possibile eseguire tutte le operazioni con pochi passi, si rimanda alla documentazione ufficiale per tutti i dettagli riguardo alle procedure di creazione, gestione di un repostory privato e la gestione delle immagini docker.


La CLI mette a disposizione una serie di comandi specifici per la gestione del servizio ERC, in particolare i comandi per eseguire le operazione

  • creazione di un Repository:
    aws ecr create-repository --repository-name project-example-app
  • ottenere la lista di tutti i Repository:
    aws ecr describe-repositories
    aws ecr describe-repositories --query "repositories[*].[repositoryName]" --output table
  • ottenere il token di autorizzazione nel caso di utilizzo del procollo HTTP:
    aws ecr get-authorization-token
    TOKEN=`aws ecr get-authorization-token --query "authorizationData[*].authorizationToken" --output text `
    echo $token
    PROXY=`aws ecr get-authorization-token --query "authorizationData[*].proxyEndpoint" --output text `
  • ottenere il token di autenticazione nel caso di utilizzo della CLI:
    aws ecr get-login-password --region region | docker login --username AWS --password-stdin <aws_account_id>.dkr.ecr.region.amazonaws.com
  • sequenza di comandi per caricare su ECR una immagine combinando la CLI di AWS con la CLI docker:
    aws ecr get-login-password --region eu-west-1 | docker login --username AWS --password-stdin <aws_account_id>.dkr.ecr.eu-west-1.amazonaws.com
    docker build -t <aws_account_id>-ecs-repo-uno .
    docker tag <aws_account_id>-ecs-repo-uno:latest <aws_account_id>.dkr.ecr.eu-west-1.amazonaws.com/<aws_account_id>-ecs-repo-uno:latest
    docker push <aws_account_id>.dkr.ecr.eu-west-1.amazonaws.com/<aws_account_id>-ecs-repo-uno:latest

Per un esempio funzionante di immagine caricata su ECR si rimanda agli esempi presenti nel repository:

https://github.com/alnao/PythonExamples/tree/master/Docker/03ApiPersoneNoDb

Con CloudFormation è possibile creare e gestire Repository tramite è il tipo specifico messo a disposizione dalla libreria, un piccolo esempio è:

Parameters:
  repoName: 
    Description: Name for ecr repo 
    Type: String
    Default: example20
Resources:
  ecrRepo:
    Type: AWS::ECR::Repository
    Properties: 
    RepositoryName: !Sub ${repoName}-repo
    ImageScanningConfiguration: 
    ScanOnPush: true

Da notare che in fase di canellazione compare il messaggio di conferma:

ECR repository OrderedDict([('Fn::Sub', '${repoName}-repo')]) may not be empty. 
Do you want to delete the repository and all the images in it ?

Il codice di esempio può essere trovato al solito repository:

https://github.com/alnao/AWSCloudFormationExamples/tree/master/Esempio20dockerEcrEcs
Pubblicato il 13/04/2024 nella categoria AWS

Amazon Elastic File System, abbreviato con la sigla EFS, è un servizio pensato per offrire un’archiviazione di file serverless completamente elastica che ti aiuta a condividere i dati senza effettuare la configurazione del provisioning o gestire la capacità di archiviazione e le prestazioni, presenta alcune caratteristiche principali:

  • è un servizio interamente gestito: l’infrastruttura di gestione dello storage non è gestita dall’utente
  • è un servizio elastico: è possibile memorizzare petabyte di dati e le dimensioni del filesystem si adattano automaticamente in caso di aggiunta e rimozione dei file. Non è necessario allocare anticipatamente dimensioni specifiche.
  • supporta migliaia di connnesioni ad istanze EC2 connesse simultaneamente

Queste caratteristiche lo differenziano da EBS (non elastico e usabile da una sola istanza) e S3 che necessita di API per lo scambio di dati.

Si rimanda alla documentazione ufficiale per tutti i dettagli del servizio, l’uso di questo servizio può necessitare un approfondimento riguardo ai temi di ciclo di vita (Intelligent-Tiering), le regole di replica e backup, il tipo di protocollo NFS v4.0 e 4.1 e la gestione della crittografia. Come tutti i servizi di AWS, questi sono a pagamento in base all’uso, per esempio in Irlanda il costo nella regione irlandese è di 0,33 USD per Gb al mese, si rimanda sempre alla pagina ufficiale per tutti i dettagli. Usando questo servizio bisogna sempre ricordare la gestione delle regole di accesso, in particolare ogni filesystem mette a disposizione dei punti di mount del tipo:

fs-<id>.efs.<region>.amazonaws.com

in aggiunta al endpoint devono essere configurate le subnet: di fatto il disco EFS viene assegnato ad una VPC e viene “posizionato” in almeno una subnet. Inoltre deve SEMPRE essere presente un security group nella sezione “Network access” per le impostazioni di accesso al disco: deve essere configurato il protocollo NFS per permettere alle istanze EC2 o gli altri servizi ad accedere al disco, senza queste istruzioni il disco non sarà disponibile da nessun punto del Cloud.

Per le istanze EC2 con sistema operativo GNU Linux è possibile eseguire il mount nello user-data grazie ad un pacchetto “amazon-efs-utils” installabile in fase di avvio delle istanze, un semplice esempio di script per eseguire il mount:

#!/bin/bash -xe
yum update -y aws-cfn-bootstrap
sudo yum install -y amazon-efs-utils
sudo mkdir /mnt/efs
sudo chmod 777 /mnt/efs 
sudo mount -t efs -o tls fs-<id> /mnt/efs

La CLI mette a disposizione una serie di comandi per la gestione dei dischi EFS,

  • creazione di un file system
    aws efs create-file-system --performance-mode generalPurpose --throughput-mode bursting --encrypted --tags Key=Name,Value=my-file-system
  • creazione di un punto di mount
    aws efs create-mount-target --file-system-id fs-0baed24c56c977151 --subnet-id subnet-xxxx --security-groups sg-xxxx
  • descrizione di un disco EFS
    aws efs describe-file-systems --file-system-id fs-0baed24c56c977151
  • rimozione di un disco
    aws efs delete-file-system --file-system-id fs-0baed24c56c977151

Con CloudFormation è possibile creare e gestire dischi creati con EFS, si rimanda sempre alla documentazione ufficiale per tutti i dettagli. Un semplice esempio di costruzione di un File system con EFS:

FileSystem:
  Type: AWS::EFS::FileSystem
  Properties:
    Encrypted: !Ref Encryption
    FileSystemTags:
    - Key: Name
      Value: !If [hasFsTags, !Ref FileSystemName, !Sub "${AWS::StackName}FileSystem"]
    KmsKeyId: !If [useDefaultCMK, !Ref "AWS::NoValue", !Ref KmsKeyId]
    PerformanceMode: !Ref PerformanceMode
    ThroughputMode: !Ref ThroughputMode
    ProvisionedThroughputInMibps: !If [provisionedThroughputMode, !Ref ProvisionedThroughputInMibps, !Ref 'AWS::NoValue']
MountTargetSecurityGroup:
  Type: AWS::EC2::SecurityGroup
  Properties:
    GroupDescription: FileSystem Security Group
    VpcId: !Ref VpcId
    GroupName: !If [hasFsTags, !Join ["", [!Ref FileSystemName, "SecurityGroup"]], !Join ["", [!Ref "AWS::StackName", "FileSystemSecurityGroup"]]]
    SecurityGroupIngress:
    - IpProtocol: "tcp"
      FromPort: !Ref FileSharePort
      ToPort: !Ref FileSharePort
      SourceSecurityGroupId: !Ref OriginSecurityGroup

In questo esempio la istanza EC2 esegue il mount del disco nel user data con i comandi:

- |
  sudo yum install -y amazon-efs-utils
  sudo mkdir /mnt/efs
  sudo chmod 777 /mnt/efs 
- 'sudo mount -t efs -o tls '
- !Ref EFSFileSystemId
- ':/ /mnt/efs '

Bisogna sempre ricordarsi che deve essere presente un security group collegato all’istanza EC2 e al disco EFS per gestire il collegamento tra le due risorse: il traffico in l’output dalla EC2 deve essere abilitato per essere in input al disco EFS, per esempio è possibile definire un security group:

MountTargetSecurityGroup:
  Type: AWS::EC2::SecurityGroup
  Properties:
    GroupDescription: FileSystem Security Group
    VpcId: !Ref VpcId
    GroupName: !If [hasFsTags, !Join ["", [!Ref FileSystemName, "SecurityGroup"]], !Join ["", [!Ref "AWS::StackName", "FileSystemSecurityGroup"]]]
    SecurityGroupIngress:
    - IpProtocol: "tcp"
      FromPort: !Ref FileSharePort
      ToPort: !Ref FileSharePort
      SourceSecurityGroupId: !Ref OriginSecurityGroup

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

https://github.com/alnao/AWSCloudFormationExamples/tree/master/Esempio19efsEc2
Pubblicato il 23/03/2024 nella categoria AWS

I metadati di una istanza EC2 sono delle informazioni che l’istanza stessa può recuperare sulla sua natura e sulla sua posizione nel Cloud, infatti di default le istanze non conoscono alcune informazioni che possono essere utili alle esecuzioni delle applicazioni come il nome host, il security group, l’indirizzo di rete. Si rimanda alla documentazione ufficiale per tutte le informazioni riguardanti questo sottoservizio, a volte chiamato anche IMDS.  AWS ha fatto un po’ confusione con i nomi: “user-data” e “mata-data” hanno nomi assonanti ma sono due sottoservizi molto diversi, bisogna prestare sempre attenzione alla differenza tra questi due concetti del servizio EC2.

Come indicato nella documentazione queste informazioni sono disponibili all’interno di una istanza ma chiunque acceda all’istanza può recuperare le informazioni quindi è sconsigliato usare l’usera data per salvare password o altre informazioni critiche che possono essere recuperate con i meta-data. L’elenco completo dei dati disponibili è elencati nel sito ufficiale ed è presente una pagina specifica che descrive le regole di utilizzo di questa tecnica, in particolare bisogna ricordare che ogni istanza ha un “identity role” in IAM che rappresenta la stessa istanza e quello che può fare, questo definisce la regola di accesso al Instance Metadata Service (IMDS) identificato come tipo di risorsa:

/identity-credentials/ec2/security-credentials/ec2-instance

Esistono due tipi di possibilità di accesso al servizio IMDS la prima versione permette l’accesso diretto mentre la seconda versione prevede l’uso di un token autenticato, per ottenere il token bisogna richiamare un istruzione specifica

$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`

Per poi usare il token per accedere ai medatati si usa il comando

$ curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/

con questo comando si ottengono tutti i dati disponibili, per poi accedere e recuperare un dati specifico si può usare lo stesso comando aggiungendo il nome del parametro

$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/ami-id

La libreria SDK mette a disposizione una libreria specifica per l’uso e il recupero dei meta-dati, si rimanda alla documentazione ufficiale per il linguaggio Java o per gli altri linguaggi. Il codice di esempio per il recupero delle ami-id di una istanza è

public static void main( String[] args ) {
  Ec2MetadataClient client = Ec2MetadataClient.create();
  Ec2MetadataResponse response = client.get("/latest/meta-data/ami-id");
  System.out.println(response.asString());
  client.close(); // Closes the internal resources used by the Ec2MetadataClient class.
}

ovviamente questo codice deve essere eseguito da una istanza EC2, al di fuori questo codice genera errore.
L’esempio completo e funzionante è disponibile nel solito repository:

https://github.com/alnao/JavaExamples/tree/master/AwsSdkJava/04_MetadataEc2

Su CloudFormation il concetto di Metadata può essere confuso, per assonanza, con altri tipi specifici previsti dal servizio, in ogni caso è possibile usare i Metadati messi a disposizione da EC2 per alcuni casi d’uso specifici, uno dei più semplici e utili è la definizione di uno script di avvio di un AutoScaling e un comando per la “verifica dello stato dell’istanza”:

LaunchConfig:
  Type: AWS::AutoScaling::LaunchConfiguration
  Metadata:
    AWS::CloudFormation::Init:
      configSets:
        full_install: [install_cfn, install_app, verify_instance_health]
        ...
      verify_instance_health:
        commands:
          ELBHealthCheck:
            command: !Sub
             'until [ "$state" == "\"InService\"" ]; do state=$(aws --region ${AWS::Region} elb describe-instance-health
             --load-balancer-name ${ElasticLoadBalancer}
             --instances $(curl -s http://169.254.169.254/latest/meta-data/instance-id)
             --query InstanceStates[0].State); sleep 10; done'

L’esempio completo può essere trovato nel repository ufficiale di awslabs.

Pubblicato il 16/03/2024 nella categoria AWS

Una necessità frequente in caso di utilizzo di istanze EC2 è la gestione di comandi e schedulare operazioni all’interno delle istanze, la possibilità più semplice è usare gli schedulatori nativi del sistema operativo come Cron per le istanze GNU Linux o lo schedulatore nativo di Microsoft Windows, tuttavia questi necessitano una attività manuale di configurazione e il monitoraggio necessità l’utilizzo di software specifici o di accessi diretti alle istanze e diventa molto complesso da gestire nelle architettura con molte istanze con le stesse schedulazioni come nel caso di architetture studiate per lavorare con la scalabilità. L’uso di System Manager permette l’esecuzione di comandi in istanze senza la necessità di collegamento SSH/Telnet o via desktop remoto ma permette di eseguire comandi in semplicità da un browser o da un qualsiasi computer grazie ai comandi della CLI.

AWS mette a disposizione un sistema gestito e serverless per la gestione degli eventi combinando le funzionalità dei vari sotto-servizi AWS:

  • IAM: gestione dei permessi rendendo sicura e robusta la infrastruttura
  • System Manager: gestione dei comandi con i Document “RunShellScript” e “RunPowerShellScript” sarà possibile avviare un comando in una istanza
  • SSM agent: agente che esegue i comandi nelle istanze e ne gestisce il ritorno
  • EventBridge: per le impostazioni di esecuzioni infatti con questo servizio è possibile legare le schedulazioni ad eventi specifici o regole a frequenza fissa.

Ogni uno di questi componenti deve essere gestito e ben configurato, questo articolo vuole essere un riassunto della documentazione ufficiale e del tutorial ufficiale che si invita a leggere attentamente. Le cose più importanti da tenere a mente sono:

  1. Deve essere presente una regola IAM che permetta alle istanze EC2 di collegarsi ad SSM con la policy chiamata AmazonEC2RoleforSSM:
  2. La regola IAM con la policy permissiva deve essere associata alla istanze EC2
  3. L’agente deve essere installato nella istanza, nelle EC2 con AMI di tipo Linux-Amazon questo è installato di default, negli altri tipi di AMI deve essere installato manualmente, si rimanda alla documentazione ufficiale per questo passo .
  4. Verificare che l’agente è collegato correttamente, nel servizio SSM è disponibile la lista degli agenti collegati in “Fleet manager”

    Il comando base per la verificare lo stato dell’agente in ambiente di GNU Linux è

    sudo systemctl status amazon-ssm-agent
  5. E’ possibile eseguire i comandi dalla shell con la funzionalità specifica prevista dalla console

Tramite console è possibile monitorare le istanze collegate al servizio tramite l’agente nella funzione “Fleet Manager” del AWS Systems Manager.


La CLI mette a disposizione un comando specifico per questo tipo di che si chiama

ssm send-command

la cui documentazione ufficiale descrive il funzionamento e l’elenco di tutti i parametri mentre è presente anche una utile guida. I principali comandi di System Manager per eseguire comandi nelle istanze EC2 sono:

  • elenco di tutte le istanze con l’agente in esecuzione correttamente configurato
    aws ssm describe-instance-information --output text --query "InstanceInformationList[*]"
  • avviare un comando in una istanza specifica di tipo GNU Linux con il tipo RunShellScript:
    aws ssm send-command --document-name "AWS-RunShellScript"
    --targets '[{"Key":"InstanceIds","Values":["i-094d7505c54b0e029"]}]'
    --parameters '{"commands":["sh prova.sh"],"workingDirectory": ["/home/ec2-user"]}'
  • eseguire un comando e recuperare l’output con il comando “list-command-invocations”
    sh_command_id=$(aws ssm send-command --instance-ids "i-094d7505c54b0e029" --document-name "AWS-RunShellScript" --parameters '{"commands":["ifconfig"]}' --output text --query "Command.CommandId")
    aws ssm list-command-invocations --command-id "$sh_command_id" --details --query "CommandInvocations[].CommandPlugins[].{Status:Status,Output:Output}"

Da notare che esiste anche il comando corrispettivo per lanciare comandi su istanza con il sistema operativo MS Windows con il tipo specifico, per maggiori dettagli si rimanda alla documentazione ufficiale.


Con EventBridge è possibile schedulare l’esecuzione di questo tipo di comandi creando regole specifiche indicando come target il tipo AWS-RunShellScript di tipo Systems Manager Run Command impostando come input al processo il tipo Constant con le informazioni del comando in un json:

{
  "executionTimeout": ["3600"],
  "commands": ["sh prova.sh"],
  "workingDirectory": ["/home/ec2-user"]
}

Inoltre bisogna ricordarsi che la regola EventBridge deve essere “abilitata” ad eseguire il comando con nella singola istanza con una policy specifica, per esempio:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Action": "ssm:SendCommand",
    "Effect": "Allow",
    "Resource": [
      "arn:aws:ec2:eu-west-1:xxxxxxx:instance/i-xxxxxxxxxxxxxxxxx",
      "arn:aws:ssm:eu-west-1:*:document/AWS-RunShellScript"
    ]
  }]
}

Nel sito ufficiale è descritto anche un processo diverso per l’esecuzione di comandi nelle istanze per eseguire il comando di avvio e spegnimento, possibilità non permessa dal send-command di ssm, la soluzione proposta dal sito ufficiale descrive la creazione di alcune Lambda avviate da EventBridge per la gestione dello stato delle istanze.

La soluzione proposta prevede un template CloudFormation per la gestione di tutte le risorse, si rimanda al sito ufficiale per tutti i dettagli. Bisogna ricordare che con CloudFormation non è possibile definire dei tipi di risorsa “comando” ma esistono dei tipi “document” che permettono di definire la logica, anche in questo caso si rimanda sempre alla documentazione ufficiale per tutti i dettagli.

Pubblicato il 09/03/2024 nella categoria AWS

Il servizio AWS Key Management Service, spesso abbreviato con la sigla KMS, è studiato per gestire le fasi entyption di oggetti e della gestione delle chiavi di sicurezza usate in fase di cifratura e decifratura. Essendo un servizio unico e centralizzato garantisce la sicurezza ed è studiato per lavorare con tutti gli altri servizi e a tutte le applicazioni AWS. Visto che si tratta di un argomento molto importante e delicato, si rimanda alla guida ufficiale e alla pagina ufficiale per i dettagli, questo vuole essere solo un riassunto dei comandi principali per poter usare questo servizio. Si rimanda alla documentazione ufficiale anche per i dettagli sulla rotazione delle chiavi e la gestione delle policy di accesso, temi molto importanti che è fondamentale conoscere per garantire la sicurezza nel Cloud, è fondamentale anche ricordare che il servizio presenta dei costi d’uso: per ogni chiave c’è un costo di manutenzione mensile e sono previsti dei costi in base alle richieste di operazioni eseguite. Per usare questo servizio bisogna aver presente la differenza tra chiavi simmetriche e asimmetteriche e bisogna conoscere bene la differenza tra i tipi di chiave: owned (SSE), managed oppure custom.

La procedura di creazione di una chiave da console è molto semplice, richiede queste informazioni:

  • tipo: simmetrico o asimmetrico
  • uso: semplice o hMAC
  • origine: KMS, CloudHSM oppure esterna
  • region: semplice o multi AZ
  • nome, descrizione e tags
  • regole IAM di amministratore e l’elenco degli utenti abilitati all’uso delle chiavi

Con la CLI è possibile gestire il servizio KMS con un gruppo di comandi dedicato, i principali comandi sono:

  • la lista di tutte le chiavi:
    $ aws kms list-keys
  • il dettaglio di una chiave:
    $ aws kms describe-key --key-id <key_id>
  • la chiave pubblica di una chiave di tipo asimmetrico:
    $ aws kms get-public-key --key-id <key_id>
  • comando per la cifratura di un file:
    $ aws kms encrypt --key-id <key_id> --plaintext fileb://in.txt --output text
    $ aws kms encrypt --key-id <key_id> --plaintext fileb://in.txt --output text --encryption-algorithm RSAES_OAEP_SHA_256 --query CiphertextBlob | base64 --decode > out.txt
  • comando la la decifratura di un file:
    $ aws kms decrypt --key-id <key_id> --ciphertext-blob fileb://out.txt --encryption-algorithm RSAES_OAEP_SHA_256 --output text --query Plaintext | base64 --decode
  • comando per creare una chive, per questo comando specifico si rimanda alla documentazione ufficiale per tutti i dettagli, un semplice esempio:
    $ aws kms create-key --key-spec RSA_4096 --key-usage ENCRYPT_DECRYPT

Anche la libreria SDK mette a disposizione molte funzioni per la gestione delle chiavi gestite con il servizio KMS, i principali sono:

def get_keys(profile_name):
  boto3.setup_default_session(profile_name=profile_name)
  kms = boto3.client('kms')
  response = kms.list_keys( Limit=100, )#Marker='string'
  if 'Keys' in response:
    return response['Keys']
  return []
def get_key_detail(profile_name,key_id):
  boto3.setup_default_session(profile_name=profile_name)
  kms = boto3.client('kms')
  response = kms.describe_key(KeyId=key_id)
  if 'KeyMetadata' in response:
    return response['KeyMetadata']
  return {}
def get_keys_detail(profile_name):
  l=[]
  lista=get_keys(profile_name)
  for k in lista:
    l.append ( get_key_detail(profile_name,k['KeyId']) )
  return l
def get_public_key(profile_name,key_id):
  boto3.setup_default_session(profile_name=profile_name)
  kms = boto3.client('kms')
  response = kms.get_public_key(KeyId=key_id)
  return response
def entrypt_file(profile_name,key_id,source_file_path,dest_file_path,algoritm):
  boto3.setup_default_session(profile_name=profile_name)
  kms = boto3.client('kms')
  with open(source_file_path, 'rb') as infile :
    with open(dest_file_path, 'wb') as outfile :
      while True:
        chunk = infile.read(1000)
        if not chunk :
          break
        resp = kms.encrypt(KeyId=key_id, Plaintext=chunk,EncryptionAlgorithm=algoritm)['CiphertextBlob']
        outfile.write(resp)
def decrypt_file(profile_name,key_id,source_file_path,dest_file_path,algoritm):
  boto3.setup_default_session(profile_name=profile_name)
  kms = boto3.client('kms')
  with open(source_file_path, 'rb') as infile :
    with open(dest_file_path, 'wb') as outfile :
      while True:
        chunk = infile.read(1000)
        if not chunk :
          break
        resp = kms.decrypt(KeyId=key_id,CiphertextBlob=chunk,EncryptionAlgorithm=algoritm)['Plaintext']
        outfile.write(resp)
  return None

Con CloudFormation non solo è possibile gestire la creazione delle chiavi ma è possibile anche gestire il modo in cui queste sono usate nelle risorse, questo servizi infatti può essere usato assieme ad altri per cifrare cose che devono esserlo, come per esempio le password di un database o la chiave di accesso di un server SFTP. La sintassi CloudFormation per creare chiavi è molto semplice e necessita solo della lista dei permessi, inoltre è possibile creare da template degli alias da usare come referenze nel codice delle applicazioni:

RdsKey:
  Type: AWS::KMS::Key
  Properties:
    KeyPolicy:
      Version: 2012-10-17
      Id: key-rds
      Statement:
      - Sid: Enable IAM User Permissions
        Effect: Allow
        Principal:
          AWS: !Join
          - ''
          - - 'arn:aws:iam::'
            - !Ref 'AWS::AccountId'
            - ':root'
        Action: 'kms:*'
        Resource: '*'
RdsAlias:
  Type: AWS::KMS::Alias
  Properties:
  AliasName: alias/rds
  TargetKeyId:
    Ref: RdsKey
Outputs:
  RdsAlias:
    Description: 'RDS KMS Encryption Key Alias'
    Value:
      Ref: 'RdsAlias'

Le chiavi possono essere usate per impostare la cifrature di un sistema, per esempio nel caso di database RDS:

MySQLDatabase:
  Type: 'AWS::RDS::DBInstance'
  Properties:
    Engine: MySQL
    DBName: "RDS"
    StorageEncrypted: true
    KmsKeyId: !Ref rdsKey
    MasterUsername: 'dbuser'
    MasterUserPassword: 'Passw0rd!'
    DBInstanceClass: db.t2.small
    AllocatedStorage: 5
    DBSubnetGroupName: !Ref RDSDBSubnetGroup
    VPCSecurityGroups:
      - Ref: RDSSecurityGroup

Il servizio KMS si integra perfettamente anche con Secret Manager, infatti con KMS è possibile gestire il sistema di cifratura delle password salvate,si rimanda alla documentazione ufficiale.

Il recupero dei valori segreti è possibile sempre grazie alle librerie SDK, per esempio in python con la libreria Boto3:

import json
import boto3
import json
secrets = boto3.client("secretsmanager")
rds = json.dumps(secrets.get_secret_value(SecretId="prod/app/Database")['SecretString'])
print(rds)
Pubblicato il 02/03/2024 nella categoria AWS

Il servizio SQS di AWS permette di creare code di dati, il nome deriva dall’inglese Simple Queue System. In Infromatica per coda si intende una struttura dati costituita come raccolta di entità gestite in una sequenza che può essere modificata aggiungendo entità a un estremo e rimuovendole dall’altro estremo, si rimanda alla pagina wiki per maggiori dettagli sui vari tipi di code e il loro funzionamento.

Su AWS il servizio SQS ha determinate caratteristiche che lo distinguono da sistemi simili, le principali caratteristiche sono:

  • è di tipo Serverless quindi risulta completamente gestito
  • non ha un limite di scrittura/lettura (throughput) e non ha limiti di numero di entità gestite
  • il limite massimo di retenzione di una entità è di 4 giorni come default che può essere modificato fino a 14 giorni massimo
  • ogni entità ha un limite massimo di 256 Kb
  • è possibile avere entità duplicate e possono essere ordinate, di default infatti le code non sono di tipo FIFO ma può essere attivata come opzione avanzata
  • i servizi che scrivono nella coda sono detti Producer
  • i servizi che leggono dalla coda sono Consumer ed è loro compito eliminare l’elemento letto
  • è possibile gestire la scalabilità dei Consumer tramite AutoScaling grazie ad allarmi di CloudWatch
  • è possibile gestire la sicurezza tramite sistema di entryption con KMS (client side) ed è possibile definire regole di acesso (access policy) trmiate il servizio IAM
  • il servizio prevede molti parametri e configurazioni avanziate per la gestione di un DLQ (dead letter queue), un DQ (delay queue) e il polling (long polling)

Il costo del servizio è calcolato in base all’uso con un milione di richieste al mese gratuite, si rimanda al sito ufficiale per tutti i dettagli sul servizio.


La CLI mette a disposizione una serie di comandi per la gestione delle code SQS, i principali comandi sono:

  • lista delle code:
    aws sqs list-queues
    aws sqs list-queues --queue-name-prefix "rahul"
  • creazione di una nuova coda:
    aws sqs create-queue --queue-name sqs-formaz-with-tag --tags "env"="formazione" --attributes DelaySeconds=10
  • gestione delle entità nella coda:
    aws sqs get-queue-attributes --queue-url https://sqs.us-east-1.amazonaws.com/<aws-account-number>/sqs-formaz-with-tag --attribute-names All
    
    aws sqs send-message --queue-url https://sqs.us-east-1.amazonaws.com/<aws-account-number>/sqs-formaz-with-tag --message-body "Test message to my-sqs-using-cli sqs"
    
    aws sqs receive-message --queue-url https://sqs.us-east-1.amazonaws.com/<aws-account-number>/sqs-formaz-with-tag
    
    aws sqs purge-queue --queue-url https://sqs.us-east-1.amazonaws.com/<aws-account-number>/sqs-formaz-with-tag
  • eliminazione di una coda:
    aws sqs delete-queue --queue-url https://sqs.us-east-1.amazonaws.com/<aws-account-number>/sqs-formaz-with-tag

La libreria SDK mette a disposizione una serie di funzioni per la gestione delle code SQS, nel sito ufficiale possono essere trovati esempi dei principali linguaggi di programmazione come Java , Javascript e Python tramite la libreria boto3, i metodi principali sono:

def get_sns_list(profile_name):
  boto3.setup_default_session(profile_name=profile_name)
  sqs_client = boto3.client("sqs") #, region_name=AWS_REGION
  topics_iter = sqs_client.list_queues(
    MaxResults=100
  )
  if 'QueueUrls' in topics_iter :
    return topics_iter['QueueUrls']
  return []
def create_queue(profile_name, queue_name,delay_seconds,visiblity_timeout):
  boto3.setup_default_session(profile_name=profile_name)
  sqs_client = boto3.client("sqs") #, region_name=AWS_REGION
  response = sqs_client.create_queue(QueueName=queue_name,Attributes={
    'DelaySeconds': str(delay_seconds),
    'VisibilityTimeout': str(visiblity_timeout)
     # 'FifoQueue': 'true'
  })
  return response
def delete_queue(profile_name, queue_name):
  boto3.setup_default_session(profile_name=profile_name)
  sqs_client = boto3.client("sqs") #, region_name=AWS_REGION
  response = sqs_client.delete_queue(QueueUrl=queue_name)
  return response
def get_queue(profile_name, queue_url):
  boto3.setup_default_session(profile_name=profile_name)
  sqs_client = boto3.client("sqs") #, region_name=AWS_REGION
  response = sqs_client.get_queue_attributes( QueueUrl=queue_url, AttributeNames=['All'])
  if 'Attributes' in response:
    return response['Attributes']
  return {}
def send_queue_message(profile_name,queue_url,msg_attributes,msg_body):
  boto3.setup_default_session(profile_name=profile_name)
  sqs_client = boto3.client("sqs") #, region_name=AWS_REGION
  response = sqs_client.send_message(QueueUrl=queue_url,
    MessageAttributes=msg_attributes,
    MessageBody=msg_body)
  return response
def receive_queue_messages(profile_name,queue_url):
  boto3.setup_default_session(profile_name=profile_name)
  sqs_client = boto3.client("sqs") #, region_name=AWS_REGION
  response = sqs_client.receive_message(QueueUrl=queue_url,MaxNumberOfMessages=10)
  if 'Messages' in response:
    return response['Messages']
  return []
def delete_queue_message(profile_name,queue_url, receipt_handle):
  boto3.setup_default_session(profile_name=profile_name)
  sqs_client = boto3.client("sqs") #, region_name=AWS_REGION
  response = sqs_client.delete_message(QueueUrl=queue_url,ReceiptHandle=receipt_handle)
  return response

Con CloudFormation è possibile gestire le risorse di SQS con il tipo specifico

SqsQueue:
  Type: AWS::SQS::Queue
  Properties:
    QueueName: !Ref QueueName
    VisibilityTimeout: 180
    Tags:
    -
      Key: StackId
      Value: !Ref AWS::StackId

Inoltre bisogna ricordarsi che, in presenza di producer/consumer, è sempre necessario gestire le regole di accesso tramite la definizione di una regola IAM, per esempio:

SqsQueueLambdaConsumer:
  Type: AWS::Serverless::Function
  Properties:
    CodeUri: lambda
    Handler: consumer.entrypoint
    Runtime: python3.8
    MemorySize: 1280
    Timeout: 900
    Role: !GetAtt SqsQueueLambdaIamRole.Arn
SqsQueueLambdaIamRole:
  Type: 'AWS::IAM::Role'
  Properties:
    AssumeRolePolicyDocument:
    Version: 2012-10-17
    Statement:
    - Effect: Allow
      Principal:
      Service:
      - lambda.amazonaws.com
      Action:
      - 'sts:AssumeRole'
    Path: /
      Policies:
      - PolicyName: root
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Action:
            - sqs:GetQueueUrl 
            - sqs:SendMessage
            - sqs:ReceiveMessage
            - sqs:DeleteMessage
            Resource:
            - !GetAtt SqsQueue.Arn

L’esempio completo di coda SQS con un funzioni Lambda producer/consumer è disponibile nel solito repository:

https://github.com/alnao/AWSCloudFormationExamples/tree/master/Esempio18sqs
Pubblicato il 24/02/2024 nella categoria AWS

Il servizio AWS Config è stato studiato per permettere ai customer di valutare, registrare e monitorare tutte le modifiche alle configurazioni delle risorse per semplificare la gestione del Cloud. Da notare che come servizio non permette di modificare le configurazione ma è studiato solo per essere uno strumento di monitoraggio con un registro unificato per tutte le risorse del Cloud. Bisogna sempre ricordare che per risorsa AWS si intende qualsiasi entità in AWS e comprende qualsiasi tipo di entità creata, l’elenco completo di tutti i tipi di risorse è disponibile nella documentazione ufficiale:

Da console web è possibile attivare il servizio con una procedura chiamata 1-click, inoltre è possibile definire regole usando quelle definite di default (Managed) e personalizzate (Custom), si rimanda sempre alla documentazione ufficiale per tutti i dettagli.

La documentazione ufficiale descrive molto bene il funzionamento del sistema e presenta diversi esempi di utilizzo con casi d’uso reali , per esempio è possibile contare il numero di istanze EC2 attive aggregando il dato per tipo con una semplice query:

SELECT configuration.instanceType, COUNT(*)
 WHERE resourceType = 'AWS::EC2::Instance'
 GROUP BY configuration.instanceType

La CLI mette a disposizione una serie di comandi per la gestione del servizio. Per evitare problemi con doppi nomi, è stato creato il tipo config-service per far riferimento ai comandi del servizio AWS Config per evitare fraintendimenti con il comando configuration utilizzato per definire i profili della AWS CLI. I principali comandi di questo servizio sono

  • – recupero dello stato dei sistemi di registro di AWS Config
    aws configservice describe-delivery-channels
    aws configservice describe-configuration-recorders
    aws configservice describe-configuration-recorder-status
  • elenco di tutte le regole
    aws configservice describe-config-rules 
    aws configservice describe-config-rules | grep ConfigRuleName
  • creazione ed eliminazione di una regola
    aws configservice put-config-rule --generate-cli-skeleton > putConfi gRule.json
    aws configservice put-config-rule --cli-input-json file://putConfigRule.json
    aws configservice delete-config-rule --config-rule-name ConfigRuleName
  • elenco di tutte le regole compliance
    aws configservice describe-compliance-by-config-rule
    aws configservice describe-compliance-by-resource --resource-type AWS::EC2::Instance
    aws configservice get-compliance-details-by-resource --resource-type AWS::EC2::Instance --resource-id i-nnnnnnnn
  • lista delle risorse
    aws configservice list-discovered-resources
    aws configservice list-discovered-resources --resource-type "AWS::EC2::Instance"
    aws configservice list-discovered-resources --resource-type "AWS::CloudFormation::Stack"
  • storico di eventi di una risorsa
    aws configservice get-resource-config-history --resource-type AWS::EC2::Instance --resource-id i-0117ee5195da9794b

Oltre alla documentazione ufficiale, è consigliata anche la lettura di un libro disponibile nel sito ufficiale che descrive in maniera dettagliata tutti i comandi


Anche la libreria SDK mette a disposizione i metodi per gestire il servizio da codice: la libreria boto3 mette a disposizione metodi per i servizio config, i principali metodi messi a disposizione sono:

def resources_list(profile_name,resource_type):
  boto3.setup_default_session(profile_name=profile_name)
  config = boto3.client('config')
  lista = config.list_discovered_resources(
    resourceType=resource_type
    #limit=100,
    #nextToken='string'
  )
  if 'resourceIdentifiers' in lista:
    return lista['resourceIdentifiers']
  return [] 
def resource_detail(profile_name, resource_type, resource_id):
  boto3.setup_default_session(profile_name=profile_name)
  config = boto3.client('config')
  lista = config.get_resource_config_history(
    resourceType=resource_type,
    resourceId=resource_id,
    limit=100,
    #nextToken='string'
  )
  if 'configurationItems' in lista:
    return lista['configurationItems']
  return []

Per la gestione di AWS Config in CloudFormation sono previsti tutti i tipi di risorse, si rimanda alla documentazione ufficiale per tutti i dettagli. Nell’esempio proposto in AwsLabs viene definita la regola per la registrazione degli evento sui volumi delle EC2:

ConfigRecorder:
  Type: AWS::Config::ConfigurationRecorder
  Properties:
    Name: default
    RecordingGroup:
    ResourceTypes: ['AWS::EC2::Volume']
    RoleARN: !GetAtt [ConfigRole, Arn]
  DeliveryChannel:
    Condition: CreateDeliveryChannel
    Type: AWS::Config::DeliveryChannel
    Properties:
      ConfigSnapshotDeliveryProperties:
        DeliveryFrequency: Six_Hours
      S3BucketName: !Ref 'ConfigBucket'
      SnsTopicARN: !Ref 'ConfigTopic'
  ConfigRuleForVolumeTags:
    Type: AWS::Config::ConfigRule
    Properties:
      InputParameters:
        tag1Key: CostCenter
      Scope:
        ComplianceResourceTypes: ['AWS::EC2::Volume']
      Source:
        Owner: AWS
        SourceIdentifier: REQUIRED_TAGS
    DependsOn: ConfigRecorder

Per ulteriori informazioni ed esempi si rimanda al repository ufficiale di AwsLabs.

Pubblicato il 17/02/2024 nella categoria AWS

Il servizio SNS è studiato appositamente per gestire sistemi di notifiche dove una o più sorgenti abbiano la necessità di inviare notifiche ad uno o più destinatari, questo servizio non è da confondere con il servizio di code SQS che si occupa solo di smistamento di dati e non di notifiche con code come le FIFO. Esistono due tipi di notifiche: A2A e A2P:

  • A2S permette di notificare in maniera asincrona notifiche push anche molti-a-molti come Kinesis, Lambda e API Gateway
  • A2P consente l’invio di messaggi tramite SMS, notiche push ad aplicazioni e/o tramite e-mail.

I casi d’uso più usati sono invio da e per applicazioni per smartphone di messaggi, invio di SMS a clienti, invio di notifiche mail da una applicazione o da altri servizi AWS, procedure AWS Step Function che inviano notifiche nei flusso operativo.

Come ogni servizio AWS prevede un costo calcolato in base ad una tariffa ad uso, si rimanda alla documentazione ufficiale per maggiori dettagli riguardo alle tariffe e tutte le caratteristiche del servizio.


La CLI mette a disposizione una serie di comandi per il controllo del servizio SNS, si rimanda alla documentazione ufficiale. I principali comandi sono:

  • creazione di un topic
    aws sns create-topic --name ProvaAlbertoCLI
  • lista dei topic
    aws sns list-topics
  • lista delle sottoscrizioni
    aws sns list-subscriptions
  • creazione di una sottoscrizione
    aws sns subscribe --topic-arn arn:aws:sns:eu-west-1:xx:ProvaAlbertoCLI --protocol email --notification-endpoint test@email.com
  • pubblicazione di un contenuto in un topic
    aws sns publish --topic-arn arn:aws:sns:eu-west-1:xx:ProvaAlbertoCLI --message "Hello World!"
  • eliminazione di un topic
    aws sns delete-topic --topic-arn arn:aws:sns:eu-west-1:xxx:ProvaAlbertoCLI

Si rimanda sempre alla pagina specifica dove sono elencati tutti i comandi e i parametri previsti.


La libreria SDK mette a disposizione una serie di metodi per la gestione dei topic SNS, per tutti i dettagli si rimanda alla documentazione ufficiale, i principali metodi sono:

def get_sns_list(profile_name):
  boto3.setup_default_session(profile_name=profile_name)
  sns_client = boto3.client('sns')
  topics_iter = sns_client.list_topics()
  if 'Topics' in topics_iter :
    return topics_iter['Topics']
  return []
def create_topic(profile_name, topic_name):
  boto3.setup_default_session(profile_name=profile_name)
  sns_client = boto3.client('sns')
  topic = sns_client.create_topic(Name=topic_name)
  return topic
def delete_topic(profile_name, topic_arn):
  boto3.setup_default_session(profile_name=profile_name)
  sns_client = boto3.client('sns')
  topic = sns_client.delete_topic(TopicArn=topic_arn)
  return topic
def subscribe_topic(profile_name, topic_arn,email):
  boto3.setup_default_session(profile_name=profile_name)
  sns = boto3.client('sns')
  sns_resource = boto3.resource('sns')
  topics_iter = sns.list_topics()
  if 'Topics' in topics_iter :
    for element in topics_iter['Topics']:
      if topic_arn==element['TopicArn']:
        topic_arn = element['TopicArn']
        topic = sns_resource.Topic(arn=topic_arn)
        subscription = topic.subscribe(Protocol='email', Endpoint=email, ReturnSubscriptionArn=True)
        return subscription
  return {}
def get_subscriptions(profile_name,topic_arn):
  boto3.setup_default_session(profile_name=profile_name)
  sns_client = boto3.client('sns')
  subscriptions = sns_client.list_subscriptions()
  if 'Subscriptions' in subscriptions:
    list=[]
    for el in subscriptions['Subscriptions']:
      if topic_arn == el['TopicArn']:
        list.append(el)
      return list
  return []
def publish(profile_name,topic_arn,post):
  boto3.setup_default_session(profile_name=profile_name)
  #sns_client = boto3.client('sns')
  sns_resource = boto3.resource('sns')
  topic = sns_resource.Topic(arn=topic_arn)
  result = topic.publish(Message=post)
  return result

Il servizio CloudFormation permette la definizione e la gestione di SNS, si rimanda alla documentazione ufficiale per tutti i dettagli e la descrizione di tutte le proprietà. Il tipo base permette di definire un sistema di notifiche con poche proprietà:

GenericSnsTopic:
  Type: AWS::SNS::Topic
  Properties:
    DisplayName: uploadGenericSns
    TopicName: uploadGenericSns

Inoltre in un template è possibile anche impostare le sottoscrizioni con una risorsa specifica:

AlarmTopic:
  Type: AWS::SNS::Topic
  Properties:
    DisplayName: uploadGenericSns
    TopicName: uploadGenericSns
    Subscription:
    - Protocol: email
      Endpoint: !Ref NotificationEmail
  NotificationEmail:
    Type: AWS::SNS::Subscription
    Properties:
      Endpoint: example@mail.com
      Protocol: email
      TopicArn: !GetAtt AlarmTopic.Arn

Per tutti i dettagli si rimanda alla documentazione ufficiale, si possono trovare alcuni esempi nel solito repository:

https://github.com/alnao/AWSCloudFormationExamples/tree/master/Esempio13lambdaApplicationS3Utils
Pubblicato il 10/02/2024 nella categoria AWS

Il tema della sicurezza non deve mai essere sottovalutato, in particolare quando si lavora in un Cloud AWS è indispensabile prestare attenzione alle regole di accesso alle istanze Ec2 per evitare che qualcuno di non autorizzato acceda alle istanze e faccia danni o rubi informazioni. In particolare, in AWS, per Security Group si intende il sotto-servizio per la definizione delle regole di accesso alle macchine Ec2: di default tutte le interfacce di rete sono bloccate sia in ingresso sia in uscita ma grazie ai Security Group (spesso indicati con la sigla SG) è possibile abilitare porte di rete in ingresso e in uscita. Si rimanda sempre alla documentazione ufficiale per tutti i dettagli riguardo a questo servizio. Il servizio era inizialmente studiato solo per le istanze E22 ma oggi è usato per gestire le regole di rete anche di altri servizi come RDS e ALB, si tuttavia il SG è un sottoservizio del servio Ec2. Purtroppo spesso in lingua italiana il nome di questo servizio viene tradotto con gruppo di sicurezza, questa traduzione spesso può creare confusione quindi è consigliato usare sempre la lingua inglese per evitare fraintendimenti.

Le regole definite con SG sono di due tipi: in ingresso (incoming) e in uscita (outgoing), tipicamente si autorizza tutto il traffico in uscite mentre è importate limitare le regole in ingresso solo ai protocolli, alle porte e agli IP indispensabili. Si rimanda alla documentazione ufficiale per maggior informazioni riguardo alla procedura guidata via web.


La CLI mette a disposizione una serie di comandi per la gestione dei SecurityGroup, si rimanda alla documentazione ufficiale e alla guida per tutti i dettagli. I principali comandi sono:

  • elenco delle regole e il dettaglio di uno specifico
    aws ec2 describe-security-groups 
    aws ec2 describe-security-groups --group-ids sg-903004f8
  • creazione di un nuovo security group
    aws ec2 create-security-group --group-name my-sg --description "My security group" --vpc-id vpc-xxxx
  • aggiunta, rimozione emodifica di una regola all’interno del security group
    aws ec2 authorize-security-group-ingress --group-id sg-903004f8 --protocol tcp --port 3389 --cidr x.x.x.x/x
    aws ec2 authorize-security-group-ingress --group-id sg-903004f8 --protocol tcp --port 22 --cidr x.x.x.x/x
    aws ec2 modify-security-group-rules ...
    aws ec2 revoke-security-group-ingress ..
  • modifica di una reola con tutti i dettagli
    aws ec2 modify-security-group-rules --group-id sg-1234567890abcdef0 --security-group-rules SecurityGroupRuleId=sgr-abcdef01234567890,SecurityGroupRule='{Description=test,IpProtocol=-1,CidrIpv4=0.0.0.0/0}'
  • cancellazione di un security group
    aws ec2 delete-security-group --group-id sg-903004f8

La libreria boto3 del SDK mette a disposizione molti metodi per la gestione dei security group, si rimanda alla documentazione ufficiale per tutti i dettagli, il principale metodo è quello per recuperare l’elenco completo delle regole:

ec2_client = boto3.client('ec2')
response = ec2_client.describe_security_groups()

Si rimanda alla documentazione ufficiale per esempi in altri linguaggi di programmazione come java.


Con CloudFormation è possibile definire regole con il tipo specifico dedicato:

InstanceSecurityGroup:
  Type: AWS::EC2::SecurityGroup
  Properties:
    GroupDescription: Enable SSH access via port 22
    VpcId: !Ref 'VpcId'
    SecurityGroupIngress:
    - IpProtocol: TCP
      FromPort: 22
      ToPort: 22
      CidrIp: !Ref 'SSHLocation'
    - CidrIp: '0.0.0.0/0'
      IpProtocol: TCP
      FromPort: 80
      ToPort: 80

E nella definizione delle istanze è possibile collegare una EC2 ad uno o più gruppi con la definizione delle istanze:

EC2Instance:
  Type: AWS::EC2::Instance
  Properties:
    InstanceType: !Ref 'InstanceType'
    KeyName: !Ref 'KeyName'
    ImageId: !Ref 'LatestAmiId'
    NetworkInterfaces: 
    - GroupSet: [!Ref 'InstanceSecurityGroup']
      SubnetId: !Ref SubnetId
      AssociatePublicIpAddress: true
    DeviceIndex: '0'
    DeleteOnTermination: true

Nella definizione di un security group è possibile definire nell’input come sorgente l’output di un altro security group, per esempio il traffico di un ALB verso un WebServer può essere regolato con la definizione:

ALBSecurityGroup:
  Type: AWS::EC2::SecurityGroup
  Properties:
    GroupDescription: Load balancer traffic
    SecurityGroupIngress:
    - IpProtocol: TCP
      FromPort: '80'
      ToPort: '80'
      CidrIp: 0.0.0.0/0
    VpcId: !Ref VpcId 
WebServerSecurityGroup:
  Type: 'AWS::EC2::SecurityGroup'
  Properties:
    GroupDescription: Enable HTTP access via port 80 locked down to the load balancer + SSH access
    SecurityGroupIngress:
    - IpProtocol: TCP
      From Port: '80'
      ToPort: '80'
      SourceSecurityGroupId: !Ref ALBSecurityGroup

Da notare che in tutti i punti è indispensabile indicare sempre la VPC dove la regola deve essere definita. Si rimanda i vari esempi presenti al solito repository

https://github.com/alnao/AWSCloudFormationExamples

Per il collegamento dei Security Group alle istanze EC2 esistono diversi modi ma il principale per le istanze GNU Linux rimane il protocollo SSH (secure shell h), questo viene configurato di default nelle istanze AMI standard di tipo GNU Linux, per il collegamento è sempre necessario usare una chiave privata in formato PEM configurabile nel sotto-servizio Key Pairs previsto dal servizio Ec2, si rimanda alla documentazione ufficiale per i dettagli di questo servizio. La o le chiavi devono essere agganciate alle istanze Ec2, questa associazione può essere effettuata da console, da SDK o anche da CloudFormation con la proprietà specifica

KeyName: !Ref 'KeyName'

Nella regola del security group è necessario configurare la porta 22, senza questa regola la porta di rete rimarrebbe chiusa e il collegamento non potrebbe avvenire

SecurityGroupIngress:
- IpProtocol: tcp
  FromPort: 22
  ToPort: 22
  CidrIp: !Ref 'SSHLocation'

Per il collegamento alla istanza è possibile un qualunque programma shell e/o bash, come un terminale GNU Linux o Putty per Windows.

ssh utente@indirizzoip -i key_privata.pem

Da notare che le chiavi pubbliche abilitate al collegamento vengono salvate nelle istanze nel file:

.ssh/authorized_keys

della utenza principale (bitnami nel caso di AMI di quel tipo o ec2_user nel caso di istanze di tipo Amazon Linux).


Per le istanze Windows, è possibile abilitare la connessione tramite desktop remoto abilitando il protocollo RDP (remote desktop protocol), per le istanze con questo sistema operativo non è possibile usare una chiave privata ma bisogna usare le credenziali con username e password. L’abilitazione del protocollo RDP è molto semplice: basta infatti abilitare la porta 3389 nel protocollo TCP, si rimanda alla documentazione ufficiale per maggiori informazioni.

Nota: è sempre sconsigliato utilizzare la Cidr di tipo 0.0.0.0/0 tranne per quelle connessioni aperte verso tutta la rete internet, in particolare per l’accesso con i protocolli SSH e/o RDP è consigliato impostare un Ip fisso o un range molto più ristretto.

Pubblicato il 03/02/2024 nella categoria AWS

Il servizio CloudTrail è studiato per monitorare gli eventi eseguiti nel Cloud non con lo scopo di monitoraggio ma di Audit e gestione della sicurezza, infatti il servizio registra tutte le attività degli utenti e le chiamate alle API nel servizio, in particolare vengono registrati tutti i servizi dei tipi.

A titolo di esempio per il servizio S3 vengono registrati gli eventi:

  • relativi alla gestione: azioni del piano di controllo (control-plane) sulle risorse come la creazione o l’eliminazione di bucket
  • relativi ai dati: azioni del piano dati all’interno di una risorsa come la lettura o la scrittura di un oggetto

CloudTrail utilizza queste fonti di eventi in tre funzionalità: cronologia degli eventi, CloudTrail Lake e Percorsi e la Cronologia degli eventi fornisce un registro visualizzabile, ricercabile, scaricabile e immutabile degli ultimi 90 giorni di eventi di gestione in una Regione AWS. La visualizzazione della Cronologia degli eventi non prevede costi di CloudTrail.

CloudTrail Lake è un data lake gestito per l’acquisizione, l’archiviazione, l’accesso e l’analisi delle attività di utenti e API su AWS a scopo di audit e sicurezza. È possibile aggregare, visualizzare, interrogare e archiviare immutabilmente i log delle attività da fonti AWS e non AWS. I Percorsi acquisiscono un registro delle attività degli account AWS e procedono a distribuire e archiviare tali eventi in S3, con possibilità di distribuzione anche a File di log Amazon CloudWatch e ad Amazon EventBridge, è possibile esportare questi eventi nelle soluzioni di monitoraggio della sicurezza. Per maggiori informazioni su cronologia degli eventi Data Lake AWS CloudTrail e sui percorsi, è possibile consultare il sito ufficiale di CloudTrail.

In particolare bisogna ricordare che il servizio non è gratuito, il piano gratuito prevede la possiblità di usare le funzionalità con alcune limitazioni, si rimanda alla documentazione ufficiale, inoltre bisogna sempre ricordare che è studiato per uno scopo diversi rispetto a CloudWatch: CloudTrail si concentra principalmente sull’auditing e sulla conformità registrando le chiamate API mentre CloudWatch è un servizio di monitoraggio che fornisce dati e informazioni utili per la gestione delle applicazioni


La CLI mette a disposizione il comando lookup-events per il recuperi di informazioni da questo servizio:

aws cloudtrail lookup-events help
aws cloudtrail lookup-events --max-items 10

che permette di recupeare i dati salvati. In particolare esistono alcuni comandi specifici per filtrare i dati, per esempio per filtrare i dati tra due date:

aws cloudtrail lookup-events --start-time <timestamp> --end-time <timestamp>

Si rimanda alla documentazione ufficiale per maggiori dettagli, da notare che esistono comandi specifi anche per il data lake e il viewer.


La libreria SDK mette a disposizione un client specifico per l’uso del servizio Cloudtrail, in particolare il comando lookup_events ha la sintassi del tipo:

response = client.lookup_events(
  LookupAttributes=[{
    'AttributeKey': 'EventId'|'EventName'|'ReadOnly'|'Username'|'ResourceType'|'ResourceName'|'EventSource'|'AccessKeyId',
    'AttributeValue': 'string'
  },],
  StartTime=datetime(2015, 1, 1),
  EndTime=datetime(2024, 1, 1),
  EventCategory='insight',
  MaxResults=123,
  NextToken='string'
)

Dalla libreria sono messe a disposizione anche i comandi per la gestione dei trails, per esempio:

client = boto3.client('cloudtrail')
def list_trail(profile_name):
  response = client.list_trails(
    NextToken='string'
  )
  if 'Trails' in response:
    return response['Trails']
  return []
def get_trail(profile_name, trail_name):
  response = client.get_trail( Name=trail_name )
  if 'Trail' in response:
    return response['Trail']
  return {}
def describe_trails(profile_name, trail_name):
  response = client.describe_trails( trailNameList=[trail_name] )
  if 'trailList' in response:
    return response['trailList']
  return []
Pubblicato il 27/01/2024 nella categoria AWS

Con il servizio ElasticIP è possibile creare e gestire indirizzi IPv4 di tipo pubblico e statico per le risorse presenti nel Cloud che dispongono di indirizzi dinamici come le istanze EC2 eseguite nelle subnet pubbliche. Gli indirizzi ip configurati con questo servizio hanno alcune caratteristiche: sono statici e non possono cambiare nel tempo, vengono assegnati ad una regione e non possono essere spostati, assegnando un indirizzo IP elastico ad una istanze EC2 vengono rilasciati tutti gli IP pubblici dinamici se presenti come specificato nella guida ufficiale ma se si associa un IP elastico ad un’istanza che aveva un nome DNS pubblico, questo cambierà per corrispondere al nuovo indirizzo.

Un indirizzo IP elastico dissociato rimane assegnato all’account finché non viene rilasciato esplicitamente ed è prevista una piccola tariffa oraria per gli indirizzi IP elastici che non sono associati a un’istanza in esecuzione. Un indirizzo IP viene assegnato ad un account AWS e rimane assegnato finchè non è rilasciato, grazie a questo servizio è possibile mascherare il guasto di un’istanza o di un software rimappando rapidamente l’indirizzo su un’altra istanza, in alternativa, è possibile specificare l’indirizzo IP in un record DNS per un dominio, in modo che il dominio punti alla tua istanza.

Per ulteriori informazioni, è possibile consultare la documentazione ufficiale per l’intagazione di ElasticIP con i DNS. ElasticIP è un servizio di rete ma è studiato per essere integrato con EC2 quindi si trova nella console e nelle varie configurazioni dentro al servizio di Elastic Cloud Conputing, spesso viene raffigurato con l’icona di una freccia anche se questo non è un logo ufficiale.


Con i comandi da riga di comando CLI è possibile gestire tutti gli IP con il comando specifico il cui comando principale permette di allocale un IP:

aws ec2 allocate-address

ed ovviamente è disposnibile il comando per consultare la lista degli IP gestiti tramite questo servizio:

aws ec2 describe-addresses

dove è possibile vedere anche in quale VPC e quale IP privato corrisponde l’indirizzo pubblico gestito.

Sono disponibili anche i comandi per disassociare e rilasciare un IP:

aws ec2 disassociate-address --public-ip 198.X.Y.Z
aws ec2 disassociate-address --association-id eipassoc-xxxxx
aws ec2 release-address --public-ip 198.X.Y.Z

Con la libreria SDK è possibile gestire gli indirizzi gestiti con il servizio ElasticIP, in particolare i metodi principali sono tre: elenco, impostazione e rilascio

def get_elastic_addresses(profile_name):
  boto3.setup_default_session(profile_name=profile_name)
  ec2 = boto3.client('ec2')
  filters = [] #[{'Name': 'domain', 'Values': ['vpc']}]
  response = ec2.describe_addresses(Filters=filters)
  if 'Addresses' in response:
    return response['Addresses']
  return []
def allocate_address(profile_name,vpc,instance):
  boto3.setup_default_session(profile_name=profile_name)
  ec2 = boto3.client('ec2')
  try:
    allocation = ec2.allocate_address(Domain=vpc)
    response = ec2.associate_address(AllocationId=allocation['AllocationId'],InstanceId=instance)
    return response
  except ClientError as e:
    print(e)
    return e
def release_address(profile_name,allocationId):
  boto3.setup_default_session(profile_name=profile_name)
  ec2 = boto3.client('ec2')
  try:
    response = ec2.release_address(AllocationId='ALLOCATION_ID')
    return response
  except ClientError as e:
    print(e)
    return e

maggiori dettagli e la descrizione di tutti i parametri di questi comandi possono essere trovati nella pagina ufficiale.


Con CloudFormation è possibile gestire gli indirizzi con il servizio ElasticIP, come indicato nell’esempio disponibile nel sito ufficiale, il tipo di risorsa dedicato è di tipo EIP, per esempio:

Resources:
  EC2Instance:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: "../Esempio02istanzeEC2/template.yaml"
      Parameters:
      SubnetId: !Ref SubnetId
      VpcId: !Ref VpcId
      KeyName: !Ref KeyName
      InstanceType: !Ref InstanceType
      SSHLocation: !Ref SSHLocation
  EIP:
    Type: AWS::EC2::EIP
    Properties:
      InstanceId: !GetAtt EC2Instance.Outputs.InstanceId
Outputs:
  InstanceEIPAddress:
    Description: IP address from Elastic IP
    Value: !Ref EIP
  InstanceId:
    Description: InstanceId of the newly created EC2 instance
    Value: !GetAtt EC2Instance.Outputs.InstanceId

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

https://github.com/alnao/AWSCloudFormationExamples/tree/master/Esempio17elasticIP
Pubblicato il 20/01/2024 nella categoria AWS

Questo articolo non vuole essere una lista la lista dei servizi disponibili, ben descritti nel sito ufficiale, ma questo gruppo di articoli vuole essere una esposizione di esempi pratici di combinazione dei vari servizi. I siti di riferimento sono il centro per sviluppatori e le sezioni dedicate alla IA generativa e al concetto di Machine laerning. Fortunatamente la maggior parte dei linguaggi di programmazione è supportata dal cloud e la lista completa con esempi pratici può essere trovata nel sito ufficiale.

Gli strumenti di sviluppo AWS sono creati per lavorare con AWS e per facilitare al tuo team l’avvio di configurazione e produttività e si basano sul concetto principale di DevOps, si rimanda alla sito ufficiale per maggior dettagli riguardo a questo paradigma della programmazione e alla pagina introduttiva dei servizi dedicati allo sviluppo integrato.

Sono disponibili i vari Tool di AWS come CLI, SDK, CDK e CloudFormation (Infrastructure as Code), questi argomenti sono introdotti in altri articoli e in questa sezione non saranno descritti. Oltre ai servizi messi a disposizione esistono molti Toolkit e IDE specifici per lavorare su AWS come l’estensione ufficiale per Microsoft Visual Studio Code e/o Eclipse, tale toolkit è introdotto nell’articolo sullo sviluppo delle Lambda ed è consigliato agli utenti anche poco esperti, Cloud9 è il tool IDE studiato integrato con la console web di AWS e studiato per integrarsi con tutti gli altri servizi DevOps.


Il servizio Cloud9 è un ambiente di sviluppo integrato (IDE) che permette scrittura di codice, la sua esecuzione anche tramite debugging attraverso browser collegato alla console web di AWS. Include un editor di codice, un dispositivo di esecuzione di debug e di un terminale integrato con tutti gli altri servizi del Cloud. La sua principale potenza è che è studiato per poter essere usato con la maggior parte dei linguaggi di programmazione, tra cui JavaScript, Python, Java e altri. Questo servizio è studiato per permettere ai customer di non dover installare file o configurare il computer di sviluppo ogni volta che inizia un nuovo progetto.

La procedura guidata da console web è molto semplice e necessita pochissime informazioni: un nome simbolico, il tipo di istanza (t2.micro è più che sufficiente e consigliata per evitare costi troppo elevati), il tipo di immagine (Linux 2023), la region, il tipo di connessione e la subnet di destinazione, infatti oltre alle informazioni base bisogna ricordarsi che, trattandosi di sistema virtualizzato, bisogna prestare attenzione agli aspetti di sicurezza, si rimanda alla documentazione ufficiale per maggiori dettagli.

La creazione di ambienti (detto environment) è possibile tramite un comando specifico della CLI che necessita tutti i parametri necessari nella procedura guidata:

aws cloud9 create-environment-ec2
--name my-demo-environment
--description "This environment is for the AWS Cloud9 tutorial."
--instance-type t2.micro
--image-id resolve:ssm:/aws/service/cloud9/amis/amazonlinux-1-x86_64
--region MY-REGION
--connection-type CONNECT_SSM
--subnet-id subnet-1234xxxxx

Questo servizio è stato studiato per essere multi-utente: più utenti possono essere collegati allo stesso ambiente di sviluppo con la possibilità.

Trattandosi di un servizio di sviluppo, è previsto i repository GIT e in particolare è studiato per integrarsi perfettamente con CodeCommit, si rimanda alla documentazione ufficiale dove sono descritti i passi da eseguire per eseguire l’operazione di clonaggio di un repository.

Quando si usa questo servizio bisogna sempre ricordare che l’uso è gratuito ma sono a pagamento tutte le risorse usate, soprattutto l’istanza EC2 usata come base del servizio, si rimanda alla documentazione ufficiale per maggiori dettagli.

Pubblicato il 13/01/2024 nella categoria AWS
MENU