Module 8 · Cloud Fundamentals: Cost, Scaling and Reliability
Security and access
Audit who can do what in a cloud account (multi-factor authentication, administrators, people who have left, old access keys, unused service accounts and public storage) and fix the riskiest findings first.
About 25 minutes
The problem
Cloud breaches rarely involve clever attacks on the provider. They usually come through the customer's own doors: a password without multi-factor authentication, an access key copied into a script years ago, an account belonging to someone who left, or a storage bucket that was made public "for a moment".
Tallybook's account has 20 people and 8 service accounts (logins used by software, such as the deployment pipeline). Nobody has reviewed them since the company was founded. A customer has asked, as part of their own security checks, whether Tallybook follows basic cloud security practice.
The concept
Identity and access management (IAM)
Every person and program that can act in the account is a principal with permissions.
| Check | Why it matters |
|---|---|
| MFA on every person | a stolen password alone isn't enough to get in |
| Few administrators | each admin account is a full-power target |
| Remove people who've left | their access should end on their last day |
| Rotate access keys | old keys are more likely to have leaked; rotate every 90 days |
| Remove unused service accounts | software that no longer runs shouldn't hold keys |
| No unintended public storage | public buckets are readable by anyone on the internet |
Least privilege
Give each principal only the permissions its job needs. Developers rarely need admin; a backup job needs to write backups, not delete databases.
Fix by risk
An administrator without MFA, or an admin access key that's two years old, comes before a non-admin's stale key.
Example
import pandas as pd
base = "https://academy.cloudtechanalytics.com/datasets/cloud/"
access = pd.read_csv(base + "access.csv")
resources = pd.read_csv(base + "resources.csv")
people = access[access["kind"] == "person"]
services = access[access["kind"] == "service account"]
findings = pd.concat([
people[people["mfa_enabled"] == 0].assign(finding="person without MFA"),
people[people["days_since_last_use"] > 90].assign(finding="person inactive over 90 days"),
access[access["oldest_access_key_days"] > 90].assign(finding="access key over 90 days old"),
services[services["days_since_last_use"] > 90].assign(finding="service account unused over 90 days"),
])
findings["risk"] = findings["admin"].map({1: "high", 0: "medium"})
print(findings.groupby(["finding", "risk"]).size().unstack(fill_value=0))
print("Administrators:", int(access["admin"].sum()), "of", len(access))risk high medium
finding
access key over 90 days old 4 5
person inactive over 90 days 1 2
person without MFA 0 6
service account unused over 90 days 1 1
Administrators: 9 of 28The high-risk column is where to start: administrator accounts with a weakness. Here they are:
print(findings[findings["risk"] == "high"][["principal", "kind", "finding", "days_since_last_use", "oldest_access_key_days"]].sort_values("principal").to_string(index=False))principal kind finding days_since_last_use oldest_access_key_days
bisi@tallybook.example person access key over 90 days old 11 491.0
ci-deploy service account access key over 90 days old 0 540.0
old-zapier service account access key over 90 days old 210 900.0
old-zapier service account service account unused over 90 days 210 900.0
yusuf@tallybook.example person person inactive over 90 days 250 692.0
yusuf@tallybook.example person access key over 90 days old 250 692.0Now storage open to the internet:
resources[(resources["type"] == "bucket") & (resources["public_access"] == "yes")][["name", "environment", "team", "storage_gb"]]name environment team storage_gb
122 website-assets production marketing 40.0
123 customer-uploads-2024 production NaN 350.0website-assets is meant to be public: it holds images for the marketing site. customer-uploads-2024 has no owning team and holds customers' files. It must be made private today, and someone must check whether it has already been accessed.
Walkthrough
- Run the cells. Which principals appear in more than one finding?
- For each high-risk finding, write the fix and who should do it.
- List which of the 20 people actually need admin, based on their roles (assume only the platform lead and CTO do).
- Write the security review summary (the task below).
Practice
Practice
How many people don't have MFA enabled?
Practice
How many high-risk findings are there in total?
Task
8 minWrite the security fixes in priority order, one per numbered line: at least five, covering the public bucket, MFA, people who have left, old keys, and too many admins, each with when it will be done.
Your work is checked for
- At least five numbered fixes
- The public bucket first
- MFA
- People who have left
- Old keys (rotate)
- Fewer admins (least privilege)
- Timing (today, this week, by a date)
Check your understanding
Answer every question to check.