Lesson 4: Advanced Security
What this lesson covers
- Least privilege IAM (Identity and Access Management)
- Secrets management and rotation
- Supply chain security and code provenance
- Encryption in transit and at rest
Read time: 12 minutes
Simple Explanation
What it is
Advanced security is about locking down permissions, protecting secrets, and reducing supply-chain risk.
Why we need it
Serverless systems often have powerful IAM roles. A single leaked key can expose entire systems.
Benefits
- Lower breach risk with least privilege.
- Safer deployments through code provenance.
- Better compliance with encryption and audits.
Tradeoffs
- More setup for policies and rotations.
- Stricter workflows for developers.
Real-world examples (architecture only)
- Least privilege IAM -> Reduced blast radius.
- Secret rotation -> Shorter exposure window.
Least Privilege IAM
The principle of least privilege: grant only the permissions a function needs, not more.
Serverless functions often have overly permissive roles because developers grant "Action": "*" and "Resource": "*" for speed. This is a critical security gap.
WRONG (too permissive):
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
RIGHT (minimal):
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:PutItem"
],
"Resource": "arn:aws:dynamodb:us-east-1:ACCOUNT:table/orders"
}
AWS Tool: Use Access Analyzer to identify overly permissive policies and auto-generate minimal permissions.
GCP equivalent: IAM Policy Analyzer identifies over-privileged service accounts.
Secrets Management
Never hardcode secrets (API keys, DB passwords, OAuth tokens) in function code or environment variables.
WRONG:
DB_PASSWORD=MySecurePassword123
API_KEY=sk_live_abc123
RIGHT (AWS):
import json
import boto3
secrets_manager = boto3.client("secretsmanager")
def get_secret(secret_name):
response = secrets_manager.get_secret_value(SecretId=secret_name)
return json.loads(response.get("SecretString", "{}"))
# Function code
db_creds = get_secret("prod/db-password")
api_key = get_secret("stripe-api-key")
RIGHT (GCP):
from google.cloud import secretmanager
def get_secret(project_id, secret_name):
client = secretmanager.SecretManagerServiceClient()
name = f"projects/{project_id}/secrets/{secret_name}/versions/latest"
response = client.access_secret_version(request={"name": name})
return response.payload.data.decode("utf-8")
Rotation: Rotate secrets frequently (30–90 days). Both AWS Secrets Manager and GCP Secret Manager support auto-rotation.
Supply Chain Security
Modern serverless relies on open-source dependencies (PyPI, Maven Central). Dependencies can be compromised.
Hardening:
-
Vulnerability Scanning:
- Use
pip auditbefore deployment - Integrate SAST (static application security testing) into CI/CD
- Tools: Snyk, Aqua, Checkmarx
- Use
-
Code Signing:
- Sign container images and Lambda layers
- Verify signatures at deployment
-
Dependency Pinning:
- Pin exact versions (not
^1.2.3or~1.2.3) - Keep
requirements.txtorpoetry.lockin version control
- Pin exact versions (not
-
Private Registries:
- Use private Python registries (AWS CodeArtifact, GCP Artifact Registry) for proprietary packages
Encryption
In Transit (TLS/HTTPS):
- API Gateway enforces HTTPS (no HTTP)
- Use TLS 1.2+ for Lambda-to-service calls
- Validate certificates
At Rest:
# AWS: DynamoDB encryption (enabled by default in 2019+)
# GCP: Firestore/Datastore encrypted by default
# For additional control:
import boto3
kms = boto3.client("kms")
def encrypt_with_kms(plaintext, key_id):
response = kms.encrypt(KeyId=key_id, Plaintext=plaintext)
return response["CiphertextBlob"]
Common Mistakes
- Storing secrets in environment variables — They're readable by other functions on the same account
- Granting
"*"permissions — Makes token theft catastrophic - Forgetting to rotate credentials — If a key leaks, it works forever
- Not validating webhooks — Anyone can trigger your function if they know the URL
- Logging sensitive data — Passwords/tokens appear in CloudWatch/Stackdriver logs
What Comes Next
- Lesson 5: Cost engineering (forecasting, right-sizing, reserved capacity)
- Lesson 6: Chaos and resilience (testing failure scenarios)
Key Takeaway: Security at scale requires automation. Use managed services (Secrets Manager, Access Analyzer), scan dependencies, validate all inputs, and rotate credentials regularly.