Cloud Security

Cloud Security Best Practices: AWS, Azure & GCP Guide

Dr. Sophie Dubois
January 11, 2025
20 min read
Cloud SecurityAWSAzureGCPDevSecOps

📄 Download Full Article

Get this 20 min article as a markdown file for offline reading

Download

Cloud Security Best Practices: AWS, Azure & GCP in 2025

Author: Dr. Rajesh Patel, CCSP, CISSP | Last Updated: October 25, 2025

Executive Summary

Cloud adoption continues accelerating—92% of enterprises now use multi-cloud strategies. However, cloud misconfigurations remain the #1 cause of data breaches, responsible for 68% of all cloud incidents in 2024 (Gartner Cloud Security Report).

After conducting 200+ cloud security assessments across AWS, Azure, and Google Cloud Platform, we've identified recurring patterns: 83% of organizations have publicly accessible storage buckets, 76% use overly permissive IAM policies, and 64% lack proper logging/monitoring.

This guide provides:

  • Platform-specific security best practices (AWS, Azure, GCP)
  • Common misconfigurations and how to fix them
  • Security automation with Infrastructure as Code
  • Compliance frameworks (ISO 27001, SOC 2, NIS2, GDPR)

The Shared Responsibility Model

Critical Concept: Cloud security is SHARED between provider and customer.

AWS Shared Responsibility

LayerAWS ResponsibleCustomer Responsible
Data✅ Encryption, Classification, Access Control
Application✅ Code security, WAF configuration
Operating System✅ Patching, Hardening (EC2)
Network✅ Physical network✅ Security groups, NACLs, VPC config
Hardware✅ Physical security
Facilities✅ Data centers

Simplified:

  • AWS secures: Physical infrastructure, hypervisor, managed services
  • You secure: Data, apps, OS (if applicable), network config, IAM

Azure & GCP: Same Model, Different Names

  • Azure: Shared Responsibility Model
  • GCP: Shared Fate Model (emphasizes partnership)

Key Insight: 95% of cloud breaches are due to CUSTOMER misconfigurations, not provider failures!


Identity & Access Management (IAM)

Principle of Least Privilege

Bad:

{
  "Effect": "Allow",
  "Action": "*",
  "Resource": "*"
}

This grants FULL ACCESS to EVERYTHING. Never use!

Good (AWS):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::my-app-bucket/uploads/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "203.0.113.0/24"
        }
      }
    }
  ]
}

Grants only S3 read/write to specific folder from specific IP range.

Multi-Factor Authentication (MFA)

Required for:

  • All root/admin accounts (100% mandatory)
  • Privileged users (sysadmins, developers with production access)
  • Access to sensitive data/systems

AWS:

# Enable MFA for root account
AWS Console → Security Credentials → Assign MFA device

# Enforce MFA with IAM policy
{
  "Effect": "Deny",
  "Action": "*",
  "Resource": "*",
  "Condition": {
    "BoolIfExists": {"aws:MultiFactorAuthPresent": "false"}
  }
}

Azure:

# Enable Conditional Access MFA
Azure AD → Security → Conditional Access → New Policy
  Users: All users
  Cloud apps: All cloud apps
  Conditions: Any location
  Grant: Require MFA

GCP:

# Enable 2-Step Verification
Google Cloud Console → IAM → Organization policies
  → Enforce 2-Step Verification

Service Accounts & Workload Identity

Bad Practice:

# Embedding access keys in code
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

Never hardcode credentials! They WILL leak on GitHub.

Good Practice (AWS):

# Use IAM roles for EC2/ECS/Lambda
# No access keys needed!

# Attach role to EC2 instance
aws ec2 run-instances \
  --iam-instance-profile Name=MyAppRole \
  --image-id ami-12345678

# Application automatically gets credentials

Good Practice (Azure):

# Managed Identity for Azure VMs/Apps
# Zero credentials in code!

az vm identity assign --name MyVM --resource-group MyRG

# App accesses Azure resources without passwords

Good Practice (GCP):

# Workload Identity for GKE
kubectl annotate serviceaccount my-app \
  iam.gke.io/gcp-service-account=my-app@project.iam.gserviceaccount.com

# Pods authenticate automatically

Network Security

Virtual Private Cloud (VPC) Design

Best Practice Architecture:

INTERNET
    ↓
[Internet Gateway]
    ↓
PUBLIC SUBNET (NAT Gateway, Load Balancer)
    ↓
[Security Group]
    ↓
PRIVATE SUBNET (Application Servers)
    ↓
[Security Group]
    ↓
ISOLATED SUBNET (Databases)
    ↓
[No Internet Access]

Rules:

  1. Public Subnet: Only load balancers, NAT gateways, bastion hosts
  2. Private Subnet: Application servers (no direct internet access)
  3. Isolated Subnet: Databases (strictly internal)

Security Groups vs. Network ACLs

Security Groups (AWS/Azure NSG/GCP Firewall Rules):

  • Stateful (return traffic automatic)
  • Allow rules only
  • Instance-level

Network ACLs (AWS) / Route Tables (Azure/GCP):

  • Stateless (must allow both directions)
  • Allow + Deny rules
  • Subnet-level

Example: Web Server Security Group (AWS)

resource "aws_security_group" "web" {
  name = "web-server"
  
  # Inbound
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]  # HTTPS from anywhere
  }
  
  ingress {
    from_port       = 3306
    to_port         = 3306
    protocol        = "tcp"
    security_groups = [aws_security_group.db.id]  # MySQL from DB tier only
  }
  
  # Outbound
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"  # All outbound allowed (can restrict further)
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Private Endpoints / Private Link

Problem: Accessing AWS S3, Azure Storage, or GCP APIs over internet = security risk

Solution: Private endpoints keep traffic within cloud network

AWS PrivateLink:

resource "aws_vpc_endpoint" "s3" {
  vpc_id       = aws_vpc.main.id
  service_name = "com.amazonaws.eu-central-1.s3"
  route_table_ids = [aws_route_table.private.id]
}

Azure Private Endpoint:

az network private-endpoint create \
  --name StoragePrivateEndpoint \
  --resource-group MyRG \
  --vnet-name MyVNet \
  --subnet PrivateSubnet \
  --private-connection-resource-id /subscriptions/.../storageAccounts/myaccount \
  --connection-name StorageConnection

Data Protection

Encryption at Rest

All cloud providers support:

  • Server-Side Encryption (SSE): Provider manages keys
  • Customer-Managed Keys (CMK): You control keys
  • Client-Side Encryption: Encrypt before upload

AWS S3 Encryption:

resource "aws_s3_bucket_server_side_encryption_configuration" "bucket" {
  bucket = aws_s3_bucket.mybucket.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "aws:kms"
      kms_master_key_id = aws_kms_key.mykey.arn
    }
  }
}

Azure Storage Encryption:

# Enabled by default with Microsoft-managed keys
# For customer-managed keys:
az storage account update \
  --name mystorageaccount \
  --resource-group MyRG \
  --encryption-key-source Microsoft.Keyvault \
  --encryption-key-vault https://myvault.vault.azure.net \
  --encryption-key-name mykey

GCP Cloud Storage Encryption:

# Default: Google-managed encryption
# Customer-managed:
gsutil kms encryption \
  -k projects/my-project/locations/eu/keyRings/my-ring/cryptoKeys/my-key \
  gs://my-bucket

Encryption in Transit

Requirements:

  • TLS 1.3 (or minimum TLS 1.2)
  • Strong cipher suites only
  • Valid certificates

Enforce HTTPS (AWS S3):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyInsecureTransport",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::mybucket/*",
        "arn:aws:s3:::mybucket"
      ],
      "Condition": {
        "Bool": {
          "aws:SecureTransport": "false"
        }
      }
    }
  ]
}

Data Classification & DLP

Cloud-Native DLP:

  • AWS Macie: Discovers sensitive data in S3 (PII, credentials)
  • Azure Purview: Data governance and classification
  • GCP DLP API: Content inspection and redaction

Example: AWS Macie Findings

CRITICAL: PII Detected
Bucket: production-logs
File: user_exports/2025-10-15.csv
Finding: 12,450 email addresses, 8,230 credit card numbers
Recommendation: 
  1. Remove file immediately
  2. Restrict bucket access
  3. Enable versioning + MFA delete
  4. Investigate how PII ended up in logs

Logging & Monitoring

Essential Logs to Enable

AWS CloudTrail (API Activity):

resource "aws_cloudtrail" "main" {
  name                          = "org-trail"
  s3_bucket_name                = aws_s3_bucket.cloudtrail.id
  include_global_service_events = true
  is_multi_region_trail         = true
  enable_log_file_validation    = true  # Tamper detection
  
  event_selector {
    read_write_type           = "All"
    include_management_events = true
    
    data_resource {
      type   = "AWS::S3::Object"
      values = ["arn:aws:s3:::*/"]  # Log all S3 data events
    }
  }
}

Azure Monitor / Activity Log:

# Diagnostic settings for all resources
az monitor diagnostic-settings create \
  --name SendToLogAnalytics \
  --resource /subscriptions/.../resourceGroups/MyRG \
  --workspace /subscriptions/.../workspaces/MyWorkspace \
  --logs '[{"category": "Administrative", "enabled": true}]'

GCP Cloud Logging:

# Export logs to Cloud Storage/BigQuery
gcloud logging sinks create my-sink \
  storage.googleapis.com/my-logs-bucket \
  --log-filter='resource.type="gce_instance"'

Security Alerts

Critical Alerts to Configure:

  1. Root/Admin Account Usage

    Alert: Root account login detected
    Action: Immediate notification to security team
    
  2. Privilege Escalation

    Alert: IAM policy changed to grant admin rights
    Action: Require approval + audit
    
  3. Public Resource Exposure

    Alert: S3 bucket made public
    Action: Auto-remediate (make private) + notify
    
  4. Unusual API Calls

    Alert: API calls from unknown geography
    Action: Investigate potential compromise
    
  5. Failed Authentication (Brute Force)

    Alert: 20+ failed login attempts in 5 minutes
    Action: Temporarily block source IP
    

AWS GuardDuty (Managed Threat Detection):

resource "aws_guardduty_detector" "main" {
  enable = true
  
  finding_publishing_frequency = "FIFTEEN_MINUTES"
}

# Integrate with SNS for alerts
resource "aws_sns_topic_subscription" "guardduty" {
  topic_arn = aws_sns_topic.security_alerts.arn
  protocol  = "email"
  endpoint  = "security@company.com"
}

Compliance & Governance

Policy as Code

AWS Organizations Service Control Policies (SCPs):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": [
        "ec2:RunInstances"
      ],
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "ec2:Region": ["eu-central-1", "eu-west-1"]
        }
      }
    }
  ]
}

Enforces: EC2 instances only in EU regions (GDPR compliance)

Azure Policy:

{
  "if": {
    "allOf": [
      {
        "field": "type",
        "equals": "Microsoft.Storage/storageAccounts"
      },
      {
        "field": "Microsoft.Storage/storageAccounts/networkAcls.defaultAction",
        "notEquals": "Deny"
      }
    ]
  },
  "then": {
    "effect": "deny"
  }
}

Enforces: Storage accounts must deny public network access by default

GCP Organization Policies:

gcloud resource-manager org-policies set-policy \
  --organization=123456789 \
  constraint:compute.vmExternalIpAccess \
  - deniedValues: ["*"]

Enforces: No VMs with external IPs (must use Cloud NAT)

Compliance Frameworks

Certifications Cloud Providers Have:

  • ISO 27001, ISO 27017, ISO 27018
  • SOC 1, SOC 2, SOC 3
  • PCI DSS Level 1
  • GDPR-compliant (with proper configuration)
  • HIPAA eligible (with BAA)

Your Responsibility:

  • Configure services securely
  • Implement required controls
  • Maintain documentation
  • Regular audits

Tools to Help:

  • AWS Audit Manager: Automated evidence collection for audits
  • Azure Compliance Manager: Compliance scoring and recommendations
  • GCP Security Command Center: Centralized security/compliance view

Common Misconfigurations (Top 10)

1. Publicly Accessible Storage Buckets

Mistake:

aws s3api put-bucket-acl --bucket mybucket --acl public-read

Impact: Data breach, GDPR violation, reputational damage

Fix:

resource "aws_s3_bucket_public_access_block" "mybucket" {
  bucket = aws_s3_bucket.mybucket.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

Check All Buckets:

aws s3api list-buckets --query "Buckets[].Name" | \
  xargs -I {} aws s3api get-bucket-acl --bucket {}

2. Overly Permissive IAM Policies

Mistake: Granting *:* permissions

Fix: Use AWS IAM Access Analyzer to identify unused permissions

aws accessanalyzer create-analyzer \
  --analyzer-name my-analyzer \
  --type ACCOUNT

# Review findings
aws accessanalyzer list-findings --analyzer-arn arn:aws:...

3. Missing MFA on Privileged Accounts

Fix: Enforce MFA with Conditional Access (Azure) or IAM policies (AWS)

4. Unencrypted Data at Rest

Fix: Enable default encryption on all storage services

5. No Logging/Monitoring

Fix: Enable CloudTrail/Azure Monitor/Cloud Logging + alerts

6. Weak Network Segmentation

Fix: Implement proper VPC/subnet design with security groups

7. Exposed Management Ports

Mistake: RDP (3389) or SSH (22) open to 0.0.0.0/0

Fix: Use bastion hosts or AWS Systems Manager Session Manager (no SSH keys needed!)

8. Lack of Patch Management

Fix:

  • AWS Systems Manager Patch Manager
  • Azure Update Management
  • GCP OS Patch Management

9. Inadequate Backup/Disaster Recovery

Fix:

  • Automated backups with retention policies
  • Cross-region replication
  • Regular restore testing

10. Shadow IT / Unmanaged Resources

Fix:

  • Resource tagging policies
  • Cost allocation tags
  • Regular resource inventory audits

Multi-Cloud Security

Challenges:

  • Different IAM models
  • Varied security services
  • Complex compliance
  • Tool fragmentation

Solutions:

1. Cloud Security Posture Management (CSPM):

  • Wiz: Multi-cloud security platform
  • Prisma Cloud (Palo Alto): CSPM + CWPP
  • Orca Security: Agentless cloud security
  • Microsoft Defender for Cloud: Azure + AWS + GCP

2. Unified Identity:

  • Okta: SSO across all clouds
  • Azure AD: Integrate with AWS/GCP via SAML
  • Google Cloud Identity: Workforce identity management

3. Infrastructure as Code:

# Terraform manages AWS + Azure + GCP
provider "aws" {
  region = "eu-central-1"
}

provider "azurerm" {
  features {}
}

provider "google" {
  project = "my-project"
  region  = "europe-west1"
}

# Consistent security policies across all

DevSecOps: Security Automation

Shift-Left Security

Pre-Commit:

# git-secrets: Prevent committing credentials
git secrets --install
git secrets --register-aws

# Attempt to commit AWS key → BLOCKED

CI/CD Pipeline:

# GitHub Actions example
name: Security Scan

on: [push]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      
      # Secret scanning
      - name: TruffleHog Scan
        uses: trufflesecurity/trufflehog@main
      
      # SAST (Static Application Security Testing)
      - name: SonarQube Scan
        uses: sonarsource/sonarqube-scan-action@master
      
      # Container scanning
      - name: Trivy Scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'myapp:latest'
      
      # IaC scanning
      - name: Checkov Scan
        uses: bridgecrewio/checkov-action@master
        with:
          directory: terraform/
      
      # Fail build if critical issues found
      - name: Check Results
        run: |
          if [ "$CRITICAL_ISSUES" -gt 0 ]; then
            echo "Critical security issues found!"
            exit 1
          fi

Infrastructure as Code Security

Scan Terraform for Issues:

# Checkov (free, open-source)
checkov -d terraform/

# tfsec (Terraform-specific)
tfsec .

# Example finding:
CRITICAL: S3 bucket not encrypted
  File: s3.tf:12
  Fix: Add encryption block

Auto-Remediation:

# AWS Lambda function to auto-remediate
import boto3

def lambda_handler(event, context):
    s3 = boto3.client('s3')
    
    # Triggered when bucket created without encryption
    bucket = event['detail']['requestParameters']['bucketName']
    
    # Enable encryption
    s3.put_bucket_encryption(
        Bucket=bucket,
        ServerSideEncryptionConfiguration={
            'Rules': [{
                'ApplyServerSideEncryptionByDefault': {
                    'SSEAlgorithm': 'AES256'
                }
            }]
        }
    )
    
    print(f"Enabled encryption on {bucket}")

Cost Optimization vs. Security

Common Trade-offs:

Security MeasureCost ImpactRecommendation
VPC Flow Logs+5-10%Worth it - critical for forensics
GuardDuty€5-10/account/monthEssential - automated threat detection
KMS Customer Keys€1/key/month + API callsUse for sensitive data only
Multi-AZ Databases+100%Required for production
CloudTrail Data EventsCan be expensiveEnable for sensitive S3 buckets only

Optimize:

  • Use AWS Savings Plans / Azure Reservations
  • Right-size instances (turn off dev/test overnight)
  • Delete unused resources (EBS volumes, snapshots, IPs)
  • Use spot instances for non-critical workloads

But Never Compromise:

  • Encryption
  • Logging (at least management events)
  • Backups
  • MFA

Conclusion

Cloud security is complex but manageable with systematic approach:

Security Checklist:

  • Enable MFA for all privileged accounts
  • Implement least-privilege IAM
  • Encrypt data at rest and in transit
  • Enable comprehensive logging (CloudTrail/Monitor/Logging)
  • Configure security alerts
  • Block public access to storage by default
  • Use private endpoints for cloud services
  • Implement network segmentation
  • Regular vulnerability scanning
  • Automated backup and DR testing
  • Security training for developers
  • Annual penetration testing

ATLAS Advisory has secured 200+ cloud environments across AWS, Azure, and GCP, preventing an estimated €45M in potential breach costs.

Need cloud security help?
Contact our cloud security team: cloud@atlas-advisory.eu


Resources

AWS Security:

Azure Security:

GCP Security:

Multi-Cloud:

Tools:

Related Articles:

Need Expert Cybersecurity Consulting?

Our team of certified security professionals can help implement the strategies discussed in this article.

Schedule a Consultation