Cloud Security Basics
Startups in Bengaluru, banks in Mumbai and government portals all run on cloud platforms such as AWS, Microsoft Azure and Google Cloud. The cloud provider secures its data centres extremely well, yet cloud data leaks keep making the news. Almost all of them come from the customer's side: a storage bucket left public, an access key pushed to GitHub, or an account with far more permissions than it needs.
In this lesson you will learn who is responsible for what in the cloud, how identity and access management (IAM) works, the most common cloud misconfigurations, and how to audit IAM policies, firewall rules and code for secrets with Python.
The shared responsibility model
The provider is responsible for security of the cloud: buildings, hardware, the network and the virtualisation layer. You are responsible for security in the cloud: your data, identities and configuration. Where the line falls depends on the service model:
| Layer | IaaS (virtual machines) | PaaS (managed database, app platform) | SaaS (email, office suite) |
|---|---|---|---|
| Data and who can access it | You | You | You |
| Identities, passwords, MFA | You | You | You |
| Application code | You | You | Provider |
| Operating system patching | You | Provider | Provider |
| Network controls (firewall rules) | You | Shared | Provider |
| Physical servers and data centres | Provider | Provider | Provider |
Notice the top two rows: data and identity are always your responsibility, even in SaaS. If an employee's Microsoft 365 or Google Workspace password is phished and there is no MFA, that is the customer's problem, not the provider's.
Identity and access management (IAM)
In the cloud, identity is the new perimeter: anyone with valid credentials and enough permissions can reach your resources from anywhere. IAM controls this with:
- Identities: human users, groups, and roles that applications and services assume.
- Policies: documents that list which actions are allowed on which resources, sometimes with conditions (such as "only from our office IP" or "only with MFA").
Best practices across all providers:
- Protect the root or owner account with strong MFA, and do not use it for daily work.
- Give people access through single sign-on and groups, with MFA for everyone.
- Prefer roles with temporary credentials for applications over long-lived access keys.
- Grant least privilege: start with nothing and add only the actions a job needs.
- Separate production, testing and development into different accounts, subscriptions or projects.
- Review permissions regularly and remove what is unused.
A least-privilege AWS IAM policy that lets an app only read files from one bucket looks like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::rohtak-shop-invoices/*"
}
]
}(2012-10-17 is the policy language version that AWS requires in this field, not a date you should change.) Wildcards are the most common IAM mistake. This auditor flags them:
import json
policy = json.loads("""{
"Version": "2012-10-17",
"Statement": [
{"Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::shop-invoices/*"},
{"Effect": "Allow", "Action": "s3:*", "Resource": "*"},
{"Effect": "Allow", "Action": "*", "Resource": "*"},
{"Effect": "Allow", "Action": "iam:PassRole", "Resource": "*"}
]
}""")
for n, st in enumerate(policy["Statement"], start=1):
actions = st["Action"] if isinstance(st["Action"], list) else [st["Action"]]
resources = st["Resource"] if isinstance(st["Resource"], list) else [st["Resource"]]
issues = []
if "*" in actions:
issues.append("FULL ADMIN: every action allowed")
elif any(a.endswith(":*") for a in actions):
issues.append("all actions of a service")
if "*" in resources:
issues.append("applies to every resource")
if any(a.startswith("iam:") for a in actions):
issues.append("can change permissions (privilege escalation risk)")
print(f"Statement {n}: {', '.join(actions)} ->", "; ".join(issues) or "ok")Statement 1: s3:GetObject -> ok Statement 2: s3:* -> all actions of a service; applies to every resource Statement 3: * -> FULL ADMIN: every action allowed; applies to every resource Statement 4: iam:PassRole -> applies to every resource; can change permissions (privilege escalation risk)
Common cloud misconfigurations
- Public storage: object storage buckets or containers readable (or writable) by anyone. Major providers now block public access by default for new buckets; keep that setting on unless a bucket truly hosts public files.
- Open firewall rules: security groups that allow SSH (22), RDP (3389) or databases from
0.0.0.0/0, the whole internet. - Leaked secrets: access keys and passwords committed to Git repositories, container images or mobile apps. Automated bots scan public repositories for keys within minutes.
- Logging switched off: no audit trail of who changed what.
- Unencrypted data and snapshots, or snapshots shared publicly.
- Exposed metadata service: SSRF bugs that let attackers request temporary credentials from the instance metadata endpoint (see Access Control, CSRF & SSRF).
Network rules are easy to audit automatically:
SENSITIVE = {22: "SSH", 3389: "RDP", 3306: "MySQL", 5432: "PostgreSQL", 6379: "Redis", 27017: "MongoDB"}
security_group = [
{"port": 443, "source": "0.0.0.0/0"},
{"port": 22, "source": "0.0.0.0/0"},
{"port": 3306, "source": "10.0.1.0/24"},
{"port": 6379, "source": "0.0.0.0/0"},
]
for rule in security_group:
port, source = rule["port"], rule["source"]
open_to_world = source in ("0.0.0.0/0", "::/0")
if open_to_world and port in SENSITIVE:
print(f"HIGH {SENSITIVE[port]} ({port}) open to the whole internet")
elif open_to_world:
print(f"info port {port} public (fine for a website)")
else:
print(f"ok port {port} limited to {source}")info port 443 public (fine for a website) HIGH SSH (22) open to the whole internet ok port 3306 limited to 10.0.1.0/24 HIGH Redis (6379) open to the whole internet
Secrets in code
A leaked cloud key can cost lakhs of rupees in hijacked servers within hours. Use the provider's secrets manager or environment configuration instead of hard-coding keys, add secret scanning to your Git workflow (tools such as gitleaks, or the scanning built into code hosting platforms), and rotate any key that has ever been committed, even if you deleted it later, because Git history keeps it. A simple scanner uses regular expressions for known key formats:
import re
PATTERNS = {
"AWS access key ID": r"\bAKIA[0-9A-Z]{16}\b",
"Private key block": r"-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----",
"Password in code": r"(?i)password\s*=\s*['\"][^'\"]{4,}['\"]",
}
source = '''DB_HOST = "10.0.1.15"
password = "Rohtak@2026"
aws_key = "AKIAABCDEFGHIJKLMNOP"
# -----BEGIN OPENSSH PRIVATE KEY----- (pasted by mistake)'''
for n, line in enumerate(source.splitlines(), start=1):
for name, pattern in PATTERNS.items():
if re.search(pattern, line):
print(f"line {n}: {name}")line 2: Password in code line 3: AWS access key ID line 4: Private key block
Logging, monitoring and posture
Turn on the provider's audit logs from day one (AWS CloudTrail, Azure Activity Log and Microsoft Entra ID logs, Google Cloud Audit Logs), send them to a separate, protected account or workspace, and alert on risky events such as root logins, new access keys, disabled logging and public buckets. Cloud security posture management (CSPM) tools, such as the providers' own security centres or open-source tools like Prowler, check accounts against hundreds of best-practice rules automatically.
India-specific points
- The CERT-In directions apply to cloud service providers and to companies using them: logs for 180 days within Indian jurisdiction and 6-hour incident reporting.
- Under the DPDP Act, a cloud provider processing personal data for you is usually a Data Processor, while you remain the Data Fiduciary responsible for safeguards.
- RBI requires payment system data to be stored only in India, which affects region choice for payment companies; government bodies use cloud services empanelled by MeitY.
- Testing your own cloud resources is allowed under each provider's security testing policy, but never test the provider's own infrastructure or other customers. Read the policy before any assessment.
Common mistakes
- Using the root account every day or without MFA.
- Granting
*permissions to "make it work" and never narrowing them. - Long-lived access keys on laptops and servers instead of roles and temporary credentials.
- Opening SSH or RDP to the internet. Use a VPN, a bastion host or the provider's session manager.
- Assuming the provider handles security. Data, identity and configuration are always yours.
Key points
- The provider secures the cloud; you secure what you put in it, and data and identity are always yours.
- IAM uses identities, roles and policies; apply least privilege and MFA, and prefer temporary credentials.
- Common failures are public storage, open security groups, leaked keys, missing logs and SSRF to metadata.
- Scan policies, network rules and code automatically; rotate any leaked key.
- Turn on audit logs early, protect them, and use CSPM tools to find misconfigurations.
Exercise
Extend the security group auditor so that it also flags IPv6 rules (::/0) and any rule whose port is a range string such as "0-65535". Test it with {"port": 22, "source": "::/0"} and {"port": "0-65535", "source": "10.0.0.0/8"}.
Show solution
SENSITIVE = {22: "SSH", 3389: "RDP", 6379: "Redis"}
rules = [{"port": 22, "source": "::/0"}, {"port": "0-65535", "source": "10.0.0.0/8"}]
for rule in rules:
port, source = rule["port"], rule["source"]
if isinstance(port, str) and "-" in port:
print(f"MEDIUM port range {port} allowed from {source}: list only the ports you need")
elif source in ("0.0.0.0/0", "::/0") and port in SENSITIVE:
print(f"HIGH {SENSITIVE[port]} ({port}) open to the whole internet over {'IPv6' if ':' in source else 'IPv4'}")The first rule is flagged HIGH as SSH open to the IPv6 internet, and the second as an overly broad port range, even though its source is internal.
Quick Quiz
1. In SaaS, who is responsible for protecting user accounts with MFA?
Identity and data stay the customer's responsibility in every service model.
2. Which is the best way for an application on a cloud server to get credentials?
Roles give short-lived, automatically rotated credentials.
3. A security group allows port 3389 from 0.0.0.0/0. What is the problem?
RDP exposed to the internet is a common ransomware entry point.
4. You accidentally committed an access key and deleted it in the next commit. What must you do?
Bots scan public repositories quickly, and history keeps the old commit.
Learn Cyber Security with a mentor
Free lessons get you started. Our Ethical Hacking & Cyber Security training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
