Cloud Security: IAM, Network Isolation, and Encryption

Implement defense-in-depth security for cloud infrastructure—identity and access management, network isolation, encryption, and security monitoring.

published: reading time: 13 min read

Cloud Security: IAM, Network Isolation, and Encryption

Cloud security requires rethinking the assumption that your network perimeter is safe. In cloud environments, the network is potentially hostile by default. Any resource with a public IP or membership in a security group with public access is exposed. Security must be layered: identity, network, and data encryption work together for defense in depth.

This post covers the core security practices that apply regardless of which cloud provider you use. The examples use AWS, but the concepts translate to Azure, GCP, and other providers with different service names.

When to Use

Cloud-Native Security Services vs. Third-Party

Choose cloud-native security services when you are already invested in a single cloud provider and want integrated visibility without additional vendor complexity. Security Hub, GuardDuty, and CloudTrail work together out of the box on AWS.

Choose third-party security tools when you run a multi-cloud environment and want unified visibility across providers, or when you need capabilities that cloud-native tools do not cover—advanced threat hunting, specific compliance frameworks, or integration with on-premises security tools.

VPC Endpoints vs. NAT Gateway

Use VPC endpoints when you need private resources like S3 or DynamoDB to be accessible from within your VPC without traffic leaving the AWS network. VPC endpoints are faster, cheaper, and more secure than routing through NAT.

Use NAT gateway when private instances need outbound internet access—for patching, downloading packages, or calling external APIs. NAT gateway does not allow inbound connections from the internet; it only handles outbound from private subnets.

Customer-Managed KMS Keys vs. Cloud-Managed Keys

Use customer-managed KMS keys when you need control over key rotation, key policies, or cross-account access to keys. Customer-managed keys cost money but give you audit trails and policy control.

Use cloud-managed keys when you do not need those controls and want to minimize cost and operational overhead. Cloud-managed keys are free and automatic, but you cannot inspect their policies or control rotation.

IAM Best Practices

Identity and Access Management (IAM) is the foundation of cloud security. Every request to a cloud API requires authentication and authorization. IAM policies determine what identities can do what operations on which resources.

The cardinal rule is least privilege: grant only the permissions required for a task, and nothing more. This applies to human users, service accounts, and compute workloads.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "S3ReadOnlyForApplication",
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:ListBucket"],
      "Resource": ["arn:aws:s3:::my-app-bucket", "arn:aws:s3:::my-app-bucket/*"]
    }
  ]
}

Avoid attaching policies directly to users. Instead, create groups for roles, add users to groups, and attach policies to groups. This makes permission management systematic rather than ad hoc.

# Create a group
aws iam create-group --group-name developers

# Attach a policy to the group
aws iam attach-group-policy \
  --group-name developers \
  --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess

# Add a user to the group
aws iam add-user-to-group \
  --group-name developers \
  --user-name alice

Regularly audit IAM configurations. AWS Access Analyzer, Azure AD external identities, and GCP Policy Analyzer can identify permissions that grant external access or violate least privilege. Remove unused access keys, deactivate old credentials, and rotate secrets on a schedule.

Service Accounts and Workload Identity

Human users are not the only identities in cloud environments. Compute workloads—EC2 instances, containers, Lambda functions—need permissions to access other AWS services. The question is how those workloads authenticate.

Embedding long-lived credentials in instance profiles or environment variables is risky. Credentials persist beyond the workload lifecycle and can be exfiltrated from logs or environment variables.

Workload identity is the solution. Instead of storing credentials, workloads assume a role using short-lived tokens. The role permissions are scoped to what the workload actually needs.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

For Kubernetes workloads, cloud providers offer operators that project Kubernetes service account tokens into cloud IAM roles. This lets you create Kubernetes service accounts with specific IAM permissions without managing cloud credentials.

# Kubernetes service account with IAM role
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app
  namespace: production
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: my-app-role
rules:
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: my-app-role-binding
subjects:
  - kind: ServiceAccount
    name: my-app
    namespace: production
roleRef:
  kind: Role
  name: my-app-role

VPC and Network Isolation

Network isolation in cloud environments uses virtual private clouds (VPCs) with subnet segmentation. The principle is straightforward: nothing should be directly accessible from the internet unless intentionally exposed.

# VPC with public and private subnets
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true
}

# Public subnets for load balancers
resource "aws_subnet" "public" {
  count             = 2
  vpc_id             = aws_vpc.main.id
  cidr_block        = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
  availability_zone = data.aws_availability_zones.available.names[count.index]
  map_public_ip_on_launch = true

  tags = {
    Type = "Public"
  }
}

# Private subnets for application servers
resource "aws_subnet" "private" {
  count             = 2
  vpc_id             = aws_vpc.main.id
  cidr_block        = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index + 10)
  availability_zone = data.aws_availability_zones.available.names[count.index]

  tags = {
    Type = "Private"
  }
}

# NAT gateway for outbound traffic from private subnets
resource "aws_eip" "nat" {
  domain = "vpc"
}

resource "aws_nat_gateway" "main" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public[0].id
}

resource "aws_route_table" "private" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.main.id
  }
}

Application servers sit in private subnets and cannot be reached directly from the internet. Load balancers in public subnets route traffic to application servers. Database and cache servers sit in private subnets with no internet access at all.

Security groups act as instance-level firewalls. They are stateful: allowing inbound traffic automatically allows outbound response traffic.

# Security group for web servers
resource "aws_security_group" "web" {
  name        = "web-servers"
  description = "Security group for web servers"
  vpc_id      = aws_vpc.main.id

  # Allow inbound HTTP/HTTPS from load balancer
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["10.0.1.0/24"]  # Private subnet CIDR
  }

  # Allow outbound to internet via NAT
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Encryption at Rest and in Transit

Encrypt data wherever it lives. Cloud providers offer encryption at rest by default for most services, using KMS keys you control or provider-managed keys.

# S3 bucket with encryption
resource "aws_s3_bucket" "data" {
  bucket = "my-sensitive-data"

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm     = "aws:kms"
        kms_key_id        = aws_kms_key.data.arn
      }
    }
  }
}

# KMS key with restricted usage
resource "aws_kms_key" "data" {
  description             = "KMS key for sensitive data"
  deletion_window_in_days  = 30
  enable_key_rotation     = true

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid = "Enable IAM User Permissions"
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::123456789:root"
        }
        Action = "kms:*"
        Resource = "*"
      },
      {
        Sid = "Allow use by application"
        Effect = "Allow"
        Principal = {
          Service = "ec2.amazonaws.com"
        }
        Action = ["kms:Encrypt", "kms:Decrypt"]
        Resource = "*"
      }
    ]
  })
}

TLS encrypts data in transit. Force HTTPS on all public endpoints. Use TLS for connections between services, especially when they cross network boundaries. Certificate management can be automated with services like AWS Certificate Manager or Let’s Encrypt.

Security Groups and Firewall Rules

Security groups should be as restrictive as possible. Start with deny all inbound, allow specific ports and sources.

# Database security group - minimal access
resource "aws_security_group" "database" {
  name        = "database"
  description = "Security group for RDS instance"
  vpc_id      = aws_vpc.main.id

  # No inbound rules - RDS is only reachable from application tier
  # via security group references

  egress {
    from_port   = 5432
    to_port     = 5432
    protocol    = "tcp"
    security_groups = [aws_security_group.app.id]
  }
}

Network ACLs provide subnet-level filtering as a secondary control. Security groups handle instance-level filtering. Use both together: NACLs for subnet-wide rules like blocking a specific IP range, security groups for instance-specific access control.

VPC endpoint policies restrict which actions are allowed through VPC endpoints. Without endpoints, traffic to S3 and DynamoDB leaves the VPC and re-enters from the internet. Endpoints keep traffic internal but require explicit policies to control access.

Cloud-Native Security Services

Each major cloud provider offers security services that layer on top of basic IAM and networking.

AWS Security Hub aggregates findings from GuardDuty, Inspector, and Macie. Azure Security Center and GCP Security Command Center play similar roles. These services provide centralized visibility and compliance monitoring across your cloud footprint.

Cloud-native firewalls and WAFs filter traffic at the edge. AWS WAF works with CloudFront and Application Load Balancers, Azure WAF with Application Gateway, and GCP Cloud Armor with Cloud CDN and load balancers. If you expose any HTTP services, a WAF is not optional—it’s the first thing attackers probe.

Logging and monitoring make incident response possible. CloudTrail logs every API call in your account, VPC Flow Logs capture every network connection, and GuardDuty uses machine learning to flag anomalies. Route these to a SIEM or analytics platform. Without them, you are blind to what is happening in your environment.

Defense-in-Depth Architecture

flowchart TD
    A[Internet Traffic] --> B[WAF / Cloud Firewall]
    B --> C[Load Balancer]
    C --> D[Security Groups]
    D --> E[Application Tier]
    E --> F[Database Tier]
    F --> G[KMS Encryption]
    A --> H[IAM Authentication]
    H --> E
    E --> I[VPC Endpoints]
    I --> J[S3 / DynamoDB]

Cloud Security Trade-offs

Security ControlComplexitySecurity BenefitBest For
Customer-managed KMS keysHighFull audit and rotation controlRegulated workloads, cross-account access
Cloud-managed KMS keysLowAutomatic rotation, no costDevelopment, non-sensitive workloads
VPC endpointsMediumTraffic stays internal, lower costPrivate access to S3, DynamoDB from private subnets
NAT gateway for private trafficMediumOutbound-only internet for private subnetsPatching, external API calls from private instances
Security groupsLowInstance-level stateful firewallPrimary network isolation for compute
NACLsMediumSubnet-level stateless filteringBroad subnet rules, blocking specific CIDRs
IAM roles over user credentialsLowShort-lived tokens, no credential managementAll compute workloads

Production Failure Scenarios

FailureImpactMitigation
IAM role trust policy misconfiguration locking out resourcesResources cannot assume roles, deployments failUse AWS Access Analyzer before deploying, test trust policies in dev
KMS key deletion without waiting for grace periodEncrypted data becomes irrecoverableUse 7-30 day deletion windows, never delete keys with production data
Security group overly restrictive blocking legitimate trafficApplication cannot connect to dependencies, outagesAlways test security group changes in staging first, use descriptive names
VPC endpoint policy denying required S3 accessApplication cannot read from S3, deployments failExplicitly list required actions in endpoint policy, test after changes
CloudTrail not enabled for all regionsAttack activity in disabled regions goes unloggedEnable CloudTrail across all regions, aggregate to single bucket

Cloud Security Observability

What to monitor:

CloudTrail monitors all API calls. Enable it in all regions and route logs to a centralized bucket with object lock to prevent tampering.

GuardDuty monitors for compromised workloads. Review findings daily and route alerts to your security team’s notification channel.

Security Hub aggregates findings from GuardDuty, Inspector, and Macie into a unified view. Enable all integrated services for complete coverage.

VPC Flow Logs record source and destination IPs, ports, and bytes transferred. Use Flow Logs to detect lateral movement and unusual traffic patterns.

Key commands and queries:

# List recent CloudTrail events
aws cloudtrail lookup-events --max-results 10

# Get GuardDuty findings
aws guardduty list-findings \
  --detector-id abc123 \
  --finding-criteria '{"Severity": [{"Eq": ["HIGH"]}]}'

# Query VPC Flow Logs for port 22 access
aws logs insights query \
  --log-group-name /aws/vpc/flow-logs \
  --query-string 'fields srcAddr, dstAddr, dstPort, action | filter dstPort = 22 | limit 20'

# Check IAM access analyzer findings
aws accessanalyzer list-findings \
  --analyzer-name my-analyzer

Common Anti-Patterns

Using AWS root account for daily operations. The root account has full permissions and cannot be restricted by IAM policies. Use root account only for initial setup, then switch to IAM users and roles for everything else.

Over-permissive IAM roles. Granting *:* or AdministratorAccess to workloads because it is faster than scoping permissions defeats the purpose of least privilege. Start with minimal permissions and add only what the workload actually needs.

Leaving security groups open to 0.0.0.0/0. Allowing all inbound traffic to a database or cache port from anywhere on the internet is a common breach vector. Security groups should restrict access to known CIDRs or specific security groups.

Not enabling encryption by default. Some services allow creating unencrypted resources by default. Enforce encryption through service control policies or AWS Config rules so new resources cannot be created without encryption.

Forgetting to rotate access keys. Long-lived access keys on service accounts are a common exfiltration target. Rotate keys regularly, use short-lived credentials via IAM roles wherever possible.

Quick Recap

Key Takeaways

  • Defense in depth means layering IAM, network isolation, and encryption—not relying on any single control
  • Least privilege is the cardinal rule: grant only the permissions needed, nothing more
  • IAM roles with short-lived tokens beat long-lived credentials embedded in code or environment variables
  • VPC endpoints keep traffic internal and avoid NAT gateway costs for private resource access
  • CloudTrail, GuardDuty, and Security Hub provide the monitoring foundation for any AWS environment

Cloud Security Checklist

# 1. Enable CloudTrail in all regions
aws cloudtrail create-trail --name my-trail --is-multi-region --bucket-name my-cloudtrail-bucket

# 2. Enable GuardDuty
aws guardduty enable-detector --detector-id $(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)

# 3. Enforce encryption on S3 buckets
aws s3api put-bucket-encryption \
  --bucket my-bucket \
  --server-side-encryption-configuration '{"Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}]}'

# 4. Create IAM group with minimal permissions
aws iam create-group --group-name readonly
aws iam attach-group-policy --group-name readonly --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess

# 5. Block public access to S3 buckets
aws s3api put-public-access-block \
  --bucket my-bucket \
  --public-access-block-configuration 'BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true'

For more on managing cloud infrastructure, see our post on Cost Optimization.

Trade-off Summary

Security ToolPreventative vs DetectiveCI/CD vs RuntimeCost
Cloud-native (GuardDuty, Security Hub, Defender)DetectiveRuntimePay per consume
CSPM (Prisma Cloud, Wiz)BothRuntimePer-asset pricing
SAST / IaC scanningPreventativeCI/CDTool cost
Secret scanning (Gitleaks, TruffleHog)PreventativeCI/CDFree / paid tiers
Runtime security (Falco, Sysdig)DetectiveRuntimeInfrastructure + license
SIEM (Splunk, Elastic)DetectiveRuntimeHigh (licensing + storage)

Conclusion

Cloud security rests on three pillars: strong identity through least-privilege IAM, network isolation through VPCs and security groups, and encryption for data at rest and in transit. Cloud-native security services provide visibility and threat detection on top of these foundations.

Security is not a product you deploy but a practice you maintain. Regular audits, automated policy enforcement, and incident response planning keep your cloud environment secure. The cloud gives you powerful security tools—use them consistently and intentionally.

Category

Related Posts

Kubernetes Network Policies: Securing Pod-to-Pod Communication

Implement microsegmentation in Kubernetes using Network Policies to control traffic flow between pods and enforce zero-trust networking.

#kubernetes #network-policies #security

Encryption at Rest: TDE, Key Management, and Performance

Learn Transparent Data Encryption (TDE), application-level encryption, and key management using AWS KMS and HashiCorp Vault. Performance overhead explained.

#database #encryption #security

AWS Core Services for DevOps: EC2, ECS, EKS, S3, Lambda

Navigate essential AWS services for DevOps workloads—compute (EC2, ECS, EKS), storage (S3), serverless (Lambda), and foundational networking.

#aws #cloud #devops