Cloud CLI automation: AWS, GCP, Azure via Bash

1. Introdução à Automação Multi-Cloud com Bash

O Bash continua sendo uma das ferramentas mais poderosas para automação de infraestrutura em nuvem. Sua portabilidade entre sistemas Unix-like e a capacidade de encadear comandos de forma simples fazem dele a escolha ideal para scripts de Cloud CLI. Com ele, é possível gerenciar recursos na AWS, GCP e Azure usando uma sintaxe consistente e reutilizável.

Cada provedor oferece sua própria CLI: aws (AWS CLI), gcloud (Google Cloud SDK) e az (Azure CLI). A configuração inicial envolve instalação via gerenciadores de pacotes e autenticação:

# AWS CLI
pip install awscli
aws configure
# Insira Access Key ID, Secret Access Key, região e formato de saída

# GCP gcloud
curl https://sdk.cloud.google.com | bash
gcloud init
gcloud auth application-default login

# Azure CLI
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
az login

2. Gerenciamento de Recursos com AWS CLI

Provisionamento de Instâncias EC2

Script para criar e gerenciar instâncias EC2 com tags:

#!/bin/bash
INSTANCE_NAME="web-server-$(date +%Y%m%d)"
AMI_ID="ami-0c55b159cbfafe1f0"
INSTANCE_TYPE="t2.micro"

# Criar instância
INSTANCE_ID=$(aws ec2 run-instances \
  --image-id $AMI_ID \
  --instance-type $INSTANCE_TYPE \
  --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=$INSTANCE_NAME}]" \
  --query 'Instances[0].InstanceId' \
  --output text)

echo "Instância $INSTANCE_ID criada com nome $INSTANCE_NAME"

# Aguardar estado running
aws ec2 wait instance-running --instance-ids $INSTANCE_ID

# Parar instância após uso
aws ec2 stop-instances --instance-ids $INSTANCE_ID

Automação de Buckets S3

Gerenciamento de buckets com políticas de ciclo de vida:

#!/bin/bash
BUCKET_NAME="backup-$(date +%Y%m%d%H%M%S)"

# Criar bucket
aws s3api create-bucket \
  --bucket $BUCKET_NAME \
  --region us-east-1

# Upload síncrono de diretório local
aws s3 sync ./dados s3://$BUCKET_NAME/dados

# Configurar política de ciclo de vida (expirar após 30 dias)
cat > lifecycle.json << EOF
{
  "Rules": [
    {
      "Status": "Enabled",
      "Prefix": "",
      "Expiration": { "Days": 30 }
    }
  ]
}
EOF

aws s3api put-bucket-lifecycle-configuration \
  --bucket $BUCKET_NAME \
  --lifecycle-configuration file://lifecycle.json

Security Groups e IAM Roles

#!/bin/bash
# Criar Security Group para HTTP/HTTPS
SG_ID=$(aws ec2 create-security-group \
  --group-name "web-sg" \
  --description "Security group for web servers" \
  --query 'GroupId' --output text)

aws ec2 authorize-security-group-ingress \
  --group-id $SG_ID \
  --protocol tcp \
  --port 80 \
  --cidr 0.0.0.0/0

aws ec2 authorize-security-group-ingress \
  --group-id $SG_ID \
  --protocol tcp \
  --port 443 \
  --cidr 0.0.0.0/0

3. Automação no Google Cloud Platform (GCP) com gcloud

Compute Engine

Criação e gerenciamento de instâncias com snapshots:

#!/bin/bash
INSTANCE_NAME="app-server"
ZONE="us-central1-a"
MACHINE_TYPE="e2-medium"

# Criar instância
gcloud compute instances create $INSTANCE_NAME \
  --zone=$ZONE \
  --machine-type=$MACHINE_TYPE \
  --image-family=ubuntu-2204-lts \
  --image-project=ubuntu-os-cloud

# Criar snapshot
gcloud compute disks snapshot $INSTANCE_NAME \
  --zone=$ZONE \
  --snapshot-names="${INSTANCE_NAME}-snap-$(date +%Y%m%d)"

# Listar snapshots com retenção de 7 dias
SNAPSHOTS=$(gcloud compute snapshots list \
  --filter="creationTimestamp < -P7D" \
  --format="value(name)")

for SNAPSHOT in $SNAPSHOTS; do
  gcloud compute snapshots delete $SNAPSHOT --quiet
done

Cloud Storage

Configuração de buckets com versionamento e rsync:

#!/bin/bash
BUCKET_NAME="gcp-backup-$(date +%Y%m%d)"

# Criar bucket
gcloud storage buckets create gs://$BUCKET_NAME \
  --location=us-central1

# Habilitar versionamento
gcloud storage buckets update gs://$BUCKET_NAME \
  --versioning

# Sincronizar diretório local
gcloud storage rsync ./dados gs://$BUCKET_NAME/dados \
  --recursive --delete-orphaned-directories

VPC Networks e Firewall

#!/bin/bash
NETWORK_NAME="custom-vpc"
SUBNET_NAME="subnet-a"

# Criar VPC
gcloud compute networks create $NETWORK_NAME \
  --subnet-mode=custom

# Criar sub-rede
gcloud compute networks subnets create $SUBNET_NAME \
  --network=$NETWORK_NAME \
  --range=10.0.1.0/24 \
  --region=us-central1

# Regra de firewall para SSH
gcloud compute firewall-rules create allow-ssh \
  --network=$NETWORK_NAME \
  --allow=tcp:22 \
  --source-ranges=0.0.0.0/0

4. Integração com Azure CLI

Provisionamento de VMs Azure

Criação de Resource Groups e máquinas virtuais:

#!/bin/bash
RESOURCE_GROUP="rg-producao"
VM_NAME="vm-app"
LOCATION="eastus"

# Criar Resource Group
az group create \
  --name $RESOURCE_GROUP \
  --location $LOCATION

# Criar VM
az vm create \
  --resource-group $RESOURCE_GROUP \
  --name $VM_NAME \
  --image Ubuntu2204 \
  --size Standard_B1s \
  --admin-username azureuser \
  --generate-ssh-keys

Blob Storage com SAS Tokens

#!/bin/bash
STORAGE_ACCOUNT="storage$(date +%s)"
CONTAINER_NAME="backups"

# Criar Storage Account
az storage account create \
  --name $STORAGE_ACCOUNT \
  --resource-group $RESOURCE_GROUP \
  --location eastus \
  --sku Standard_LRS

# Criar container
az storage container create \
  --name $CONTAINER_NAME \
  --account-name $STORAGE_ACCOUNT

# Gerar SAS token para upload seguro
SAS_TOKEN=$(az storage container generate-sas \
  --account-name $STORAGE_ACCOUNT \
  --name $CONTAINER_NAME \
  --permissions w \
  --expiry $(date -d "+1 day" +%Y-%m-%d) \
  --output tsv)

# Upload recursivo
az storage blob upload-batch \
  --account-name $STORAGE_ACCOUNT \
  --destination $CONTAINER_NAME \
  --source ./dados \
  --sas-token "$SAS_TOKEN"

5. Padrões de Scripting Multi-Cloud

Funções reutilizáveis para autenticação e tratamento de erros:

#!/bin/bash
set -euo pipefail

# Função de autenticação genérica
authenticate_cloud() {
  local provider=$1
  case $provider in
    aws)
      aws sts get-caller-identity > /dev/null && echo "AWS autenticado" || return 1
      ;;
    gcp)
      gcloud auth list --filter=status:ACTIVE --format="value(account)" > /dev/null && echo "GCP autenticado" || return 1
      ;;
    azure)
      az account show > /dev/null && echo "Azure autenticado" || return 1
      ;;
  esac
}

# Função para listar VMs de qualquer provedor
list_instances() {
  local provider=$1
  case $provider in
    aws)
      aws ec2 describe-instances --query 'Reservations[*].Instances[*].[InstanceId,State.Name]' --output table
      ;;
    gcp)
      gcloud compute instances list --format="table(name,status)"
      ;;
    azure)
      az vm list --query "[].{Name:name, PowerState:powerState}" --output table
      ;;
  esac
}

# Variáveis de ambiente para alternar provedor
CLOUD_PROVIDER="${CLOUD_PROVIDER:-aws}"
list_instances $CLOUD_PROVIDER

6. Orquestração e Pipeline com Bash

Script de Backup Multi-Cloud

#!/bin/bash
BACKUP_DIR="/tmp/backup-$(date +%Y%m%d%H%M%S)"
RETENTION_DAYS=7

# Função para backup em cada cloud
backup_to_aws() {
  aws s3 sync $BACKUP_DIR s3://my-backup-bucket/backups/
}

backup_to_gcp() {
  gcloud storage rsync $BACKUP_DIR gs://my-backup-bucket/backups/
}

backup_to_azure() {
  az storage blob upload-batch \
    --account-name mystorage \
    --destination backups \
    --source $BACKUP_DIR
}

# Executar backup
mkdir -p $BACKUP_DIR
tar -czf "$BACKUP_DIR/data.tar.gz" /var/lib/data/

backup_to_aws
backup_to_gcp
backup_to_azure

# Limpeza
rm -rf $BACKUP_DIR

Integração com Cron

# Executar backup diário às 2h da manhã
0 2 * * * /usr/local/bin/multi-cloud-backup.sh >> /var/log/backup.log 2>&1

7. Segurança e Boas Práticas

Gerenciamento de Credenciais

#!/bin/bash
# AWS Secrets Manager
DB_PASSWORD=$(aws secretsmanager get-secret-value \
  --secret-id prod/db-password \
  --query SecretString \
  --output text | jq -r '.password')

# GCP Secret Manager
API_KEY=$(gcloud secrets versions access latest \
  --secret="api-key" \
  --format="get(payload.data)" | base64 --decode)

# Azure Key Vault
az keyvault secret show \
  --name "db-password" \
  --vault-name "my-keyvault" \
  --query "value" \
  --output tsv

Logging e Notificações

#!/bin/bash
log_message() {
  local level=$1
  local message=$2
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $message" >> /var/log/cloud-automation.log

  # Notificação Slack
  if [ "$level" == "ERROR" ]; then
    curl -X POST -H "Content-type: application/json" \
      --data "{\"text\":\"Erro: $message\"}" \
      https://hooks.slack.com/services/TOKEN
  fi
}

# Validação de idempotência
create_resource_if_not_exists() {
  local resource_id=$1
  if ! aws ec2 describe-instances --instance-ids $resource_id 2>/dev/null; then
    log_message "INFO" "Criando recurso $resource_id"
    # Comando de criação aqui
  else
    log_message "INFO" "Recurso $resource_id já existe"
  fi
}

8. Considerações Finais e Próximos Passos

A automação multi-cloud com Bash oferece um equilíbrio entre simplicidade e poder. Enquanto as CLIs nativas têm performances similares, o Bash permite criar abstrações que funcionam em todos os provedores. Para depuração, use --debug (AWS), --log-http (GCP) ou --debug (Azure) para entender requisições HTTP. O --dry-run simula operações sem executá-las, essencial para scripts críticos.

Para ambientes complexos, considere ferramentas como Terraform ou Ansible, mas para automações rápidas e scripts de manutenção, o Bash continua imbatível. Invista em logs estruturados (JSON) para facilitar análise em ferramentas como ELK Stack.

Referências