Skip to content
Cloud Security Guide — Shared Responsibility, IAM, KMS, and Zero Trust

Cloud Security Guide — Shared Responsibility, IAM, KMS, and Zero Trust

DodaTech Updated Jun 15, 2026 9 min read

Cloud security is the practice of protecting data, applications, and infrastructure in cloud environments through a shared responsibility model where the provider secures the infrastructure and the customer secures their data and configurations.

What You’ll Learn

By the end of this tutorial, you’ll understand the shared responsibility model, IAM roles and policies, KMS for encryption, security groups and WAF, Zero Trust principles in the cloud, CIS benchmarks, and compliance frameworks (SOC2, HIPAA, GDPR).

Why Cloud Security Matters

Cloud security misconfigurations are the #1 cause of data breaches. Open S3 buckets, exposed IAM keys, and unpatched vulnerabilities are exploited daily. With over 90% of enterprises using cloud services in 2026, understanding how to secure cloud environments is essential for every engineer. DodaTech’s Durga Antivirus Pro cloud infrastructure follows CIS benchmarks and SOC2 compliance.

Cloud Security Learning Path


flowchart LR
  A[Cloud Basics] --> B[Cloud Security]
  B --> C{You Are Here}
  C --> D[Shared Responsibility]
  C --> E[IAM]
  C --> F[Zero Trust]
  D --> G[Provider vs Customer]
  E --> H[Roles & Policies]
  E --> I[KMS Encryption]

Prerequisites: Understanding of cloud computing basics. Familiarity with AWS, Azure, or GCP helps.

What Is Cloud Security?

Think of cloud security like securing an apartment building you don’t own. The building owner (cloud provider) handles outer walls, roof, locks on main doors, fire alarms in hallways, and security cameras at entrances. You (the tenant) are responsible for locking your apartment door, setting your alarm, not sharing your keys, and not leaving valuables in plain sight.

The shared responsibility model defines exactly where the provider’s responsibility ends and yours begins.

Shared Responsibility Model


flowchart TB
  subgraph "Customer Responsibility"
    direction TB
    C1[Data Classification & Encryption]
    C2[Platform & IAM]
    C3[OS, Network & Firewall Config]
    C4[Client-side Encryption]
  end
  subgraph "Provider Responsibility"
    direction TB
    P1[Physical Security]
    P2[Hardware & Networking]
    P3[Virtualization Layer]
    P4[Global Infrastructure]
  end
  C1 --> C2 --> C3 --> C4
  P1 --> P2 --> P3 --> P4

LayerProvider ResponsibleCustomer Responsible
PhysicalData centers, power, coolingNothing
HardwareServers, storage, networkingNothing
VirtualizationHypervisor, host OSGuest OS configuration
ComputeHost maintenanceOS patching, app security
DataStorage infrastructureEncryption, access, classification
NetworkPhysical networkSecurity groups, ACLs, WAF

IAM — Identity and Access Management

IAM controls WHO can do WHAT on WHICH resources.

# iam_policy_simulator.py
# Simulate IAM policy evaluation
import json

class IAMPolicyEngine:
    def __init__(self):
        self.policies = []

    def add_policy(self, name, effect, actions, resources, conditions=None):
        self.policies.append({
            "name": name,
            "effect": effect,
            "actions": actions,
            "resources": resources,
            "conditions": conditions or {},
        })

    def evaluate(self, principal, action, resource, context=None):
        """Evaluate if an action is allowed."""
        matching = []
        for policy in self.policies:
            if action in policy["actions"] or "*" in policy["actions"]:
                if any(resource.startswith(r) or r == "*" for r in policy["resources"]):
                    matching.append(policy)

        # Deny takes precedence over Allow
        for policy in matching:
            if policy["effect"] == "Deny":
                return "DENY"
        for policy in matching:
            if policy["effect"] == "Allow":
                return "ALLOW"
        return "DENY (implicit)"

print("=== IAM Policy Evaluation ===\n")

engine = IAMPolicyEngine()
engine.add_policy("AdminAccess", "Allow", ["*"], ["*"])
engine.add_policy("S3ReadOnly", "Allow", ["s3:Get*", "s3:List*"], ["arn:aws:s3:::dodatech-data"])
engine.add_policy("ExplicitDeny", "Deny", ["s3:Delete*"], ["arn:aws:s3:::*"])

scenarios = [
    ("admin@dodatech", "s3:GetObject", "arn:aws:s3:::dodatech-data/report.pdf"),
    ("analyst@dodatech", "s3:GetObject", "arn:aws:s3:::dodatech-data/report.pdf"),
    ("analyst@dodatech", "s3:DeleteObject", "arn:aws:s3:::dodatech-data/report.pdf"),
    ("intern@dodatech", "s3:PutObject", "arn:aws:s3:::other-bucket/file.txt"),
]

print(f"{'Principal':<20} {'Action':<20} {'Resource':<45} {'Result'}")
print("-" * 100)
for principal, action, resource in scenarios:
    result = engine.evaluate(principal, action, resource)
    print(f"{principal:<20} {action:<20} {resource:<45} {result}")

Expected output:

=== IAM Policy Evaluation ===

Principal            Action               Resource                                       Result
----------------------------------------------------------------------------------------------------
admin@dodatech       s3:GetObject         arn:aws:s3:::dodatech-data/report.pdf           ALLOW
analyst@dodatech     s3:GetObject         arn:aws:s3:::dodatech-data/report.pdf           ALLOW
analyst@dodatech     s3:DeleteObject      arn:aws:s3:::dodatech-data/report.pdf           DENY
intern@dodatech      s3:PutObject         arn:aws:s3:::other-bucket/file.txt              DENY (implicit)

KMS — Key Management Service

KMS manages encryption keys for data at rest and in transit.

# kms_demo.py
# Simulate KMS envelope encryption
import os
import json
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2

class KMS:
    """Simulated KMS for learning (simplified)."""
    def __init__(self):
        self.master_keys = {}
        self.data_keys = {}

    def create_key(self, key_id, description=""):
        self.master_keys[key_id] = {
            "id": key_id,
            "description": description,
            "created": "2026-06-15",
            "enabled": True,
        }
        print(f"[KMS] Created master key: {key_id}")
        return key_id

    def generate_data_key(self, key_id):
        """Generate a data key encrypted under the master key."""
        data_key = Fernet.generate_key()
        self.data_keys[key_id] = data_key
        print(f"[KMS] Generated data key for {key_id}")
        return data_key

    def encrypt(self, key_id, plaintext):
        if key_id not in self.data_keys:
            raise ValueError(f"Data key for {key_id} not found")
        f = Fernet(self.data_keys[key_id])
        ciphertext = f.encrypt(plaintext.encode())
        print(f"[KMS] Encrypted {len(plaintext)} bytes → {len(ciphertext)} bytes")
        return ciphertext

    def decrypt(self, key_id, ciphertext):
        if key_id not in self.data_keys:
            raise ValueError(f"Data key for {key_id} not found")
        f = Fernet(self.data_keys[key_id])
        plaintext = f.decrypt(ciphertext).decode()
        print(f"[KMS] Decrypted {len(ciphertext)} bytes → {len(plaintext)} bytes")
        return plaintext

kms = KMS()
key = kms.create_key("dodatech-app-key", "App secrets encryption")
kms.generate_data_key(key)
secret = "Password: SuperSecret123!"
encrypted = kms.encrypt(key, secret)
decrypted = kms.decrypt(key, encrypted)
print(f"\nOriginal: {secret}")
print(f"Decrypted: {decrypted}")
print(f"Match: {secret == decrypted}")

Expected output:

[KMS] Created master key: dodatech-app-key
[KMS] Generated data key for dodatech-app-key
[KMS] Encrypted 30 bytes → 108 bytes
[KMS] Decrypted 108 bytes → 30 bytes

Original: Password: SuperSecret123!
Decrypted: Password: SuperSecret123!
Match: True

Zero Trust in the Cloud

Zero Trust assumes no entity is trusted by default — every request must be authenticated, authorized, and validated.

PrincipleCloud Implementation
Never trust, always verifyIAM policies, API keys, MFA on every request
Least privilegeGrant minimum permissions needed, use resource-based policies
Assume breachNetwork segmentation, micro-segmentation, encryption everywhere
Continuous verificationCloudTrail logging, anomaly detection, GuardDuty

Security Groups and WAF

# security_groups.py
# Simulate security group evaluation
class SecurityGroup:
    def __init__(self, name):
        self.name = name
        self.inbound_rules = []
        self.outbound_rules = []

    def allow_inbound(self, protocol, port, source, description=""):
        self.inbound_rules.append({"protocol": protocol, "port": port, "source": source, "desc": description})

    def allow_outbound(self, protocol, port, destination, description=""):
        self.outbound_rules.append({"protocol": protocol, "port": port, "destination": destination, "desc": description})

    def check_inbound(self, protocol, port, source_ip):
        for rule in self.inbound_rules:
            if rule["protocol"] in (protocol, "-1") and \
               (rule["port"] == port or rule["port"] == "ALL") and \
               (rule["source"] == "0.0.0.0/0" or source_ip.startswith(rule["source"].replace("0.0.0.0/0", "").rstrip(".0"))):
                return "ALLOW", rule["desc"]
        return "DENY", "No matching rule"

web_sg = SecurityGroup("web-server-sg")
web_sg.allow_inbound("tcp", 80, "0.0.0.0/0", "HTTP traffic")
web_sg.allow_inbound("tcp", 443, "0.0.0.0/0", "HTTPS traffic")
web_sg.allow_inbound("tcp", 22, "10.0.0.0/8", "SSH from internal")
web_sg.allow_outbound("-1", "ALL", "0.0.0.0/0", "All outbound")

print("=== Security Group Rules: web-server-sg ===")
for rule in web_sg.inbound_rules:
    print(f"  {rule['protocol']:<5} {rule['port']:<8} {rule['source']:<20} {rule['desc']}")

print("\n=== Inbound Traffic Checks ===")
checks = [("tcp", 443, "203.0.113.5"), ("tcp", 22, "203.0.113.5"), ("tcp", 22, "10.0.1.50"), ("udp", 53, "8.8.8.8")]
for protocol, port, ip in checks:
    result, reason = web_sg.check_inbound(protocol, port, ip)
    print(f"  {protocol.upper()} {port} from {ip:<20}{result:<6} ({reason})")

Expected output:

=== Security Group Rules: web-server-sg ===
  tcp   80       0.0.0.0/0            HTTP traffic
  tcp   443      0.0.0.0/0            HTTPS traffic
  tcp   22       10.0.0.0/8           SSH from internal

=== Inbound Traffic Checks ===
  TCP 443 from 203.0.113.5         → ALLOW  (HTTPS traffic)
  TCP 22 from 203.0.113.5          → DENY   (No matching rule)
  TCP 22 from 10.0.1.50            → ALLOW  (SSH from internal)
  UDP 53 from 8.8.8.8              → DENY   (No matching rule)

Compliance Frameworks

FrameworkFocusKey Requirements
SOC 2Service organization controlsEncryption, access control, monitoring, incident response
HIPAAHealthcare data privacyBAA agreements, audit logs, encryption, access controls
GDPREU data protectionData classification, right to deletion, consent management
PCI DSSPayment card dataNetwork segmentation, encryption, quarterly scans
ISO 27001Information security managementRisk assessment, security policy, continuous improvement

Common Cloud Security Mistakes

1. Overly Permissive IAM Policies

Using "Action": "*" on "Resource": "*" grants full admin access. Always follow least privilege — define specific actions and resources.

2. Exposed Access Keys

Hard-coded AWS_ACCESS_KEY_ID in GitHub repos, config files, or environment variables. Use IAM roles for EC2/Lambda and Secrets Manager for app secrets.

3. Open Security Groups

Security groups allowing 0.0.0.0/0 on SSH (port 22) or databases (3306, 5432). Restrict to specific IPs or VPC ranges.

4. No Encryption at Rest

S3 buckets, EBS volumes, and RDS databases without encryption expose data if storage is compromised. Enable default encryption everywhere.

5. Disabled Logging and Monitoring

Without CloudTrail (AWS), Activity Logs (Azure), or Cloud Audit (GCP), you can’t detect breaches. Enable logging from day one.

6. Not Using Multi-Factor Authentication

Root accounts and IAM users without MFA are a single password away from compromise. Enforce MFA for all users.

Practice Questions

1. What is the shared responsibility model in cloud security?

The cloud provider secures the infrastructure (physical security, hardware, network). The customer secures everything they deploy (data, IAM, OS config, app security). The boundary varies by service type (IaaS, PaaS, SaaS).

2. What is the principle of least privilege?

Grant only the minimum permissions needed for a user or service to perform their function. Never use wildcard permissions unless absolutely necessary.

3. How does KMS help secure cloud data?

KMS manages encryption keys centrally. It enables envelope encryption (master key encrypts data keys, which encrypt data), automatic key rotation, and access control through IAM.

4. What is Zero Trust security?

An approach where no entity is trusted by default. Every request must be authenticated, authorized, and validated regardless of network location. “Never trust, always verify.”

5. Challenge: Design a security architecture for a multi-tier web application on AWS with web servers, application servers, and a managed database, following least privilege.

Three security groups: (1) Web SG: allow 80/443 from 0.0.0.0/0, 22 from corp VPN only. (2) App SG: allow from Web SG only. (3) DB SG: allow 3306 from App SG only. IAM roles: EC2 gets S3 read role, RDS gets KMS decrypt role. Enable CloudTrail, GuardDuty, and S3 bucket logging.

Mini Project: Cloud Security Audit

# cloud_security_audit.py
# Perform a basic security audit on a simulated cloud environment
import json

def audit_security_group(name, rules, checks):
    findings = []
    for protocol, port, source, description in rules:
        if source == "0.0.0.0/0" and port in (22, 3389, 3306, 5432, 6379, 27017):
            findings.append(f"HIGH: {name} allows public {description} ({protocol}/{port} from {source})")
        elif source == "0.0.0.0/0" and port in checks.get("restricted_ports", []):
            findings.append(f"MEDIUM: {name} allows public {description} ({protocol}/{port} from {source})")
    return findings

def check_iam_policy(policy):
    findings = []
    if policy.get("Action") == "*" and policy.get("Resource") == "*":
        findings.append("CRITICAL: IAM policy grants full admin access (*:* on *)")
    if isinstance(policy.get("Action"), list) and "*" in policy["Action"]:
        findings.append("HIGH: IAM policy uses wildcard Action")
    return findings

audit_results = []

# Security group checks
sg_rules = [
    ("web-sg", 22, "0.0.0.0/0", "SSH"),
    ("web-sg", 443, "0.0.0.0/0", "HTTPS"),
    ("db-sg", 3306, "10.0.0.0/16", "MySQL"),
    ("admin-sg", 22, "203.0.113.0/24", "SSH Admin"),
    ("redis-sg", 6379, "0.0.0.0/0", "Redis"),
]
checks = {"restricted_ports": [22, 3389, 3306, 5432, 6379, 27017, 9200]}
audit_results.extend(audit_security_group("sg-rules", sg_rules, checks))

# IAM policy checks
iam_policies = [
    {"name": "admin-policy", "Action": "*", "Resource": "*"},
    {"name": "s3-readonly", "Action": ["s3:GetObject", "s3:ListBucket"], "Resource": "arn:aws:s3:::my-bucket/*"},
    {"name": "dev-policy", "Action": ["ec2:*", "s3:*", "lambda:*"], "Resource": "*"},
]
for policy in iam_policies:
    audit_results.extend(check_iam_policy(policy))

print("=== Cloud Security Audit Report ===\n")
for finding in audit_results:
    print(f"  • {finding}")

print(f"\nTotal findings: {len(audit_results)}")

Expected output:

=== Cloud Security Audit Report ===

  • HIGH: sg-rules allows public SSH (tcp/22 from 0.0.0.0/0)
  • HIGH: sg-rules allows public MySQL (tcp/3306 from 0.0.0.0/0)
  • HIGH: sg-rules allows public Redis (tcp/6379 from 0.0.0.0/0)
  • CRITICAL: IAM policy grants full admin access (*:* on *)
  • HIGH: IAM policy uses wildcard Action

Total findings: 5

Related Concepts

What’s Next

You now understand cloud security fundamentals! Next, learn cloud cost optimization to manage spending, and cloud monitoring for observability.

  • Practice daily — Review your cloud account’s IAM policies and security groups
  • Build a project — Set up CloudTrail + GuardDuty for your AWS account
  • Explore related topics — Check out DevSecOps for security automation in CI/CD

Remember: every expert was once a beginner. Keep coding!

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro