Chapter 58 Β· Examples

Cloud Infrastructure in Practice

Shared responsibility failures, IaC misconfigurations, over-privileged serverless functions, API security gaps, and hybrid cloud design walkthroughs.

Example 1 Β· Shared Responsibility Failure β€” The Misconfigured S3 Bucket

A healthcare analytics company migrates its patient data warehouse to AWS (IaaS). The migration team creates an S3 bucket to store exported database files during the migration. In the interest of getting the migration done quickly, they set the bucket's access policy to public β€” intending to make it temporarily accessible to the receiving team's laptops without dealing with IAM credential configuration. The migration completes and the team forgets to change the bucket policy back. The bucket remains publicly readable for seven months.

S3 Bucket: patient-data-migration-2023
Contents: 4.2 million patient records (name, DOB, SSN, diagnosis codes, insurance IDs)
Access policy: s3:GetObject β€” Principal: * (everyone, including unauthenticated)
Duration publicly accessible: 7 months
Discovery: automated security scanner flagged publicly readable bucket
Regulatory impact: HIPAA breach β€” PHI exposed; notification required for 4.2M individuals

Who was responsible β€” and for what:

This is an IaaS deployment. The shared responsibility analysis is straightforward:

The breach was not caused by AWS failing to secure the infrastructure. It was caused by the customer misconfiguring their own resource β€” specifically, the access management decision that the customer always owns regardless of service model. AWS later introduced tools (S3 Block Public Access settings, AWS Config rules, Security Hub findings) that alert on or prevent public bucket configurations, but these must be enabled and enforced by the customer.

Controls that would have prevented this:

  1. S3 Block Public Access: An account-level setting that prevents any bucket from being made publicly accessible, overriding individual bucket policies. Should be enabled by default on all accounts.
  2. AWS Config rule: A continuous compliance check that alerts whenever any S3 bucket is configured as publicly readable β€” providing a real-time notification rather than a 7-month discovery window.
  3. Principle of least privilege: The migration team should have created a time-limited IAM role for the receiving laptops rather than making the bucket public. Temporary credentials scoped to specific resources and automatically expiring would have served the legitimate need without public exposure.
  4. Data classification: Patient data should have been tagged as sensitive with a policy requiring encryption and restricted access regardless of where it resides. A classification-aware control would have blocked the public policy configuration entirely.

Example 2 Β· IaC Configuration Drift β€” The Manual Change That Returned

A financial services firm manages its AWS infrastructure using Terraform. All infrastructure changes go through a Git-based code review process: a developer proposes a change, a senior engineer reviews it, and an automated CI/CD pipeline applies approved changes to production. This process ensures consistent, reviewed infrastructure.

During an incident one Sunday night, an on-call engineer needs to quickly allow a specific monitoring tool to reach a production server. Instead of going through the IaC process (which would take hours of review), they log into the AWS console and manually add an inbound rule to the production security group: permit TCP port 8443 from the monitoring subnet 10.20.30.0/24.

What happened next:

Sunday night: Engineer manually opens TCP 8443 in AWS console β†’ monitoring tool works
Engineer notes in incident ticket: "Opened port 8443 temporarily β€” will update Terraform later"
Monday morning: Engineer is busy with other work; Terraform update is forgotten
Three weeks later: Quarterly infrastructure deployment runs β€” Terraform applies the stored
  state to all environments. The production security group is overwritten to match the
  Terraform definition, which does not include port 8443.
Port 8443 is closed. Monitoring tool stops receiving data. No one notices for 4 days.
More seriously: the manual rule had actually been more permissive than noted β€”
  the engineer added: permit TCP 8443 from 0.0.0.0/0 (any source, not just the monitoring subnet)
  This was an error made under pressure at 11PM.
The Terraform deployment accidentally fixed the security misconfiguration while breaking the monitoring.

What this example illustrates:

Configuration drift β€” the divergence between the Terraform state and the actual AWS configuration β€” created two problems simultaneously: a broken monitoring tool (operational impact) and an unintentional open security group rule (security risk). The quarterly Terraform deployment resolved the security issue and created the operational one.

The correct process:

  1. In an emergency, the manual change is acceptable to restore service β€” but must be documented immediately as technical debt with a ticket to update the Terraform code.
  2. The Terraform code update should go through the normal review process and be deployed before the next quarterly deployment overwrites the manual change.
  3. The rule should explicitly specify the monitoring subnet (10.20.30.0/24), not 0.0.0.0/0 β€” even under time pressure, the principle of least privilege applies to firewall rules.
  4. AWS Config or Terraform drift detection tools should alert when the actual infrastructure diverges from the Terraform state β€” making the 3-week undiscovered drift window impossible.

Example 3 Β· Over-Privileged Serverless Function β€” Event Injection

A retail company builds an order processing pipeline using AWS Lambda. A Lambda function processes incoming order webhooks: it receives a JSON payload from the e-commerce platform, looks up the product inventory, and writes the order to a DynamoDB table. During development, the team gave the Lambda function an IAM role with AdministratorAccess β€” the broadest possible AWS permission β€” "just to avoid permission errors while building."

The function's actual permission needs vs. what was granted:

What the function actually needs:
  dynamodb:PutItem on table: arn:aws:dynamodb:us-east-1:123456789:table/Orders
  dynamodb:GetItem on table: arn:aws:dynamodb:us-east-1:123456789:table/Inventory

What the function was granted:
  AdministratorAccess (arn:aws:iam::aws:policy/AdministratorAccess)
  β†’ Can read/write ALL DynamoDB tables (including customer PII, payment tokens)
  β†’ Can read ALL S3 buckets (including unencrypted backups, internal documents)
  β†’ Can create/delete AWS resources including IAM users
  β†’ Can read AWS Secrets Manager (all stored credentials)
  β†’ Can transfer data to any external destination

The attack β€” event injection:

An attacker who can submit crafted webhook payloads to the order endpoint discovers that the function does not validate its input. By sending a malformed JSON payload, the attacker triggers an error condition that causes the function to log its full execution context β€” including the IAM role's temporary credentials β€” to CloudWatch Logs. The attacker then uses those credentials (which have AdministratorAccess) to:

Step 1: Use leaked temp credentials to call AWS STS GetCallerIdentity β†’ confirm AdminAccess
Step 2: List all S3 buckets β†’ discover customer-backup-pii bucket
Step 3: Download all objects from customer-backup-pii β†’ 2.1M customer records exfiltrated
Step 4: Create a new IAM user with AdministratorAccess for persistent backdoor access
Step 5: Delete CloudTrail logs to cover tracks

The attacker never needed to compromise the Lambda code, the underlying servers, or the AWS account credentials. They only needed to trigger an error in an over-privileged function and capture the leaked credentials from the logs.

Two controls that would have prevented this:

  1. Least-privilege IAM role: The function should have been granted only the specific DynamoDB permissions it requires β€” PutItem on Orders, GetItem on Inventory. With those permissions, the leaked credentials would have been useless for S3 access, IAM manipulation, or any action outside those two tables.
  2. Input validation: The function should validate the structure, type, and content of the incoming JSON payload before processing. A malformed payload should be rejected with a 400 error β€” not processed in a way that leaks credentials to logs.

Example 4 Β· Microservices API Security Gap

A fintech startup decomposes its payment platform into microservices: an authentication service, an account service, a transaction service, and a reporting service. The services are deployed in Kubernetes and communicate via REST APIs over the internal cluster network. During the initial deployment, inter-service authentication was listed as a "phase 2" item β€” the team decided to launch without it since the services are "internal and not reachable from the internet."

Current inter-service communication (no auth):

Transaction Service β†’ Account Service:
  GET http://account-service/accounts/12345/balance
  (no Authorization header, no service identity verification)
  Response: {"accountId":"12345","balance":84291.00,"routing":"021000021"}

Any service in the cluster can call any other service's API with no authentication.

The attack path β€” compromised logging service:

An attacker exploits a vulnerability in the reporting service (a public-facing read-only dashboard). Once inside the reporting service's container, they discover that internal service URLs are exposed in the reporting service's logs. They begin making direct API calls from the compromised reporting service container to other internal services:

From compromised reporting service container:

GET http://account-service/accounts?limit=10000 β†’ 10,000 account records returned
GET http://transaction-service/transactions?from=2020-01-01 β†’ full transaction history
POST http://account-service/accounts/99999/transfer β†’ attempts fund transfer

The account service processes all requests β€” it cannot distinguish the legitimate
transaction service from the compromised reporting service. Both are "internal."

Why "internal = trusted" is wrong: The perimeter model assumes that anything inside the network is trusted. Microservices security rejects this assumption β€” when there are dozens of independently developed and deployed services, a compromise of any one of them gives an attacker a foothold inside the perimeter. Every internal API call must authenticate the caller's identity and verify authorization for the specific operation.

Correct inter-service security model:

  1. Service-to-service authentication: Each service has its own identity (JWT tokens, mutual TLS certificates, or a service mesh like Istio). The account service verifies that the caller is the transaction service before responding β€” the reporting service's identity is not authorized to call account balance or transfer APIs.
  2. Authorization by service identity: The account service's authorization policy: transaction service can read balances and initiate transfers; reporting service can read aggregate statistics only; no service has cross-account transfer access except the transaction service.
  3. API gateway: Centralized enforcement point for authentication, authorization, rate limiting, and logging for all external-facing APIs β€” internal services call each other through the service mesh, not the public gateway, but the same authentication requirements apply.
  4. Zero-trust network model: "Network location does not imply trust" β€” every request authenticated regardless of whether it comes from inside or outside the cluster perimeter.

Exam Scenario Β· Hybrid Cloud Architecture Review

Scenario: A law firm runs its case management system on an on-premises private cloud. It also uses a public cloud provider for document collaboration (SaaS), external-facing client portal (IaaS), and a recently deployed AI document analysis tool (PaaS). An architect must identify the security responsibilities and risks in each environment. Answer the following:

A. For the client portal running on IaaS, who is responsible for OS patching?

The customer (law firm). In IaaS, the provider secures the physical infrastructure through the hypervisor. The operating system is a virtual machine the customer controls β€” patching it, hardening it, and configuring its firewall are all the customer's responsibility. If the client portal's web server OS has an unpatched vulnerability and is exploited, that is the firm's responsibility, not the cloud provider's.

B. For the document collaboration SaaS tool, who is responsible for ensuring that only authorized employees can access the system?

The customer (law firm). In SaaS, the provider manages the application. Access management β€” which accounts exist, what permissions they have, whether MFA is required, and whether accounts are disabled when employees leave β€” is always the customer's responsibility regardless of service model. If a former employee's account is still active in the SaaS tool six months after they left, that is the firm's access management failure.

C. The firm connects the on-premises case management system to the public cloud client portal so that case files can be retrieved by the portal. What is the primary security risk of this connection?

The primary risk is data transfer across the hybrid boundary. Case files containing privileged attorney-client communications traverse from the private environment to the public cloud environment. Without a dedicated private connection (Direct Connect / ExpressRoute), this transfer crosses public internet infrastructure. Controls required: encryption of all data in transit (TLS); authentication of the connection endpoints; data classification confirming that case files are permitted to traverse this boundary under applicable ethics and compliance rules; and monitoring of the data flow for anomalies (unusual volumes, unusual destinations).

D. The AI document analysis tool is deployed on PaaS. A developer writes analysis code and deploys it to the platform. A vulnerability is discovered in the Python runtime version used by the platform. Who is responsible for patching it?

The provider. In PaaS, the provider manages the runtime and middleware layer. A vulnerability in the Python runtime (or the underlying OS) is within the provider's responsibility β€” the customer deployed their code on top of the provider-managed platform. The customer is responsible for their application code; the runtime is the provider's. This is a key advantage of PaaS over IaaS: the customer does not need to track and patch runtime vulnerabilities.

E. An MSP has administrative access to the firm's IaaS and PaaS environments. The MSP is later revealed to have been compromised in a supply chain attack. What is the impact on the firm?

The attacker who compromised the MSP now has the MSP's administrative credentials to the firm's cloud environments. Administrative access = ability to read all data, modify configurations, create backdoor accounts, delete resources, and exfiltrate anything accessible to the MSP. This is the highest-impact third-party risk scenario. Mitigation: MSP access should have been scoped to the minimum required (not global admin); privileged access should have been time-limited with just-in-time provisioning; all MSP actions should have been logged in the SIEM with alerting on anomalous activity; the incident response plan should include the MSP compromise scenario with defined steps for revoking MSP access and assessing the scope of unauthorized actions.