Security and Compliance
Topic 4 of 5 · Study notes
AWS Certified CloudOps Engineer - Associate (SOA-C03) — Domain 4: Security and Compliance
Exam Code: SOA-C03 | Level: Associate
Domain Weight: 16% | Total Domains: 6 | Passing Score: 720/1000
Table of Contents
- IAM — Identity and Access Management
- Encryption — KMS and ACM
- AWS Secrets Manager
- AWS Config — Compliance Monitoring
- Cost Allocation and Billing Security
- Federation and Identity
- Exam Tips & Quick Reference
1. IAM — Identity and Access Management
IAM is the foundation of AWS security. The exam tests authentication methods, role vs. user decisions, policy evaluation logic, and least-privilege policy generation.
1.1 IAM Authentication Methods
| Access Method | Credential Type |
|---|---|
| AWS Console | Username + password (+ optional MFA) |
| AWS CLI / SDK / API | Access Key ID + Secret Access Key |
| EC2 SSH access | SSH key pair (managed separately from IAM) |
| Cross-account / service access | IAM roles + STS temporary credentials |
Exam Tip: "A CloudOps Engineer is unable to authenticate an AWS CLI call. What is the cause?" → There is no access key configured — not a password, not an SSH key, not a server certificate.
1.2 IAM Roles vs. IAM Users
Always Use Roles for EC2 Instances
Never embed access keys in code or EC2 instances. Instead, create an IAM role with required permissions, attach the role to the EC2 instance as an instance profile, and let applications access credentials via the instance metadata service (IMDS). Credentials are automatically rotated by AWS.
import boto3
s3 = boto3.client('s3') # Automatically uses instance role credentials
IAM Roles for Cross-Account Access
Pattern for Lambda in Account A accessing S3 bucket in Account B:
- In Account B: create an IAM role with S3 access that trusts Account A.
- In Account A: Lambda execution role must have
sts:AssumeRolepermission to assume Account B's role. - Lambda calls
sts.assume_role()to get temporary credentials for Account B.
IAM User Groups
Assign policies to groups and add users to groups. Use customer managed policies (versionable, reusable) over inline policies — updating one policy affects all group members.
1.3 IAM Policy Types
| Policy Type | Attached To | Purpose |
|---|---|---|
| Identity-based | Users, groups, roles | Grant permissions to a principal |
| Resource-based | S3 buckets, KMS keys, SQS queues | Define who can access the resource |
| Service Control Policy | OU or account in Org | Maximum permissions boundary for entire account |
| Permissions boundary | User or role | Maximum permissions for that specific principal |
| Session policy | Assumed role session | Further restrict a session's permissions |
Policy Evaluation Logic
Explicit DENY anywhere? → DENY (final)
↓
Explicit ALLOW in identity policy + resource policy? → ALLOW
↓
Cross-account: both accounts must have ALLOW
↓
Default → DENY
For cross-account S3 bucket access, both must grant access: an identity-based policy in the requester's account (s3:GetObject on the bucket ARN) and a resource-based policy on the S3 bucket allowing the requesting principal. If only one grants access, the request is denied.
1.4 MFA for AWS CLI
IAM policies with aws:MultiFactorAuthPresent: "true" require MFA, but standard AWS CLI long-term access keys do NOT provide MFA authentication — the condition evaluates to false.
The solution: use sts get-session-token to obtain temporary credentials that satisfy MFA requirements:
# Step 1: Get temporary credentials using MFA token
aws sts get-session-token \
--serial-number arn:aws:iam::123456789:mfa/mydevice \
--token-code 123456
# Step 2: Export temporary credentials
export AWS_ACCESS_KEY_ID=ASIAXXX
export AWS_SECRET_ACCESS_KEY=xxxxx
export AWS_SESSION_TOKEN=xxxxx
# Step 3: Now API calls satisfy aws:MultiFactorAuthPresent = true
aws s3 ls s3://protected-bucket/
Exam Tip: "Users can run CLI commands without MFA despite policy requiring it. What additional step?" → Require users to call
aws sts get-session-tokenwith their MFA device to get temporary credentials before using the CLI.
1.5 IAM Access Analyzer
Generating Least-Privilege Policies from CloudTrail
- Enable AWS CloudTrail to record all API calls for the role.
- Let the application run its normal workflow for a representative period.
- Use IAM Access Analyzer policy generation with the CloudTrail ARN and time range.
- Review and refine the generated policy.
- Replace the overly-permissive policy with the generated one.
Exam Tip: "Company's IAM role allows full access to all AWS services. Create a policy with only required permissions." → Enable CloudTrail + use IAM Access Analyzer to generate a least-privilege policy from the access history.
2. Encryption — KMS and ACM
2.1 AWS KMS — Key Management Service
Key Types
| Key Type | Who Creates | Cost | Auto-Rotation | Cross-Account |
|---|---|---|---|---|
| AWS managed keys | AWS on behalf of services | Free | Annual | No |
| Customer managed keys (CMK) | You create and control | $1/month | Optional | Yes (via key policy) |
| Imported key material | You provide key material | $1/month | No | Possible |
Customer Managed Key Rotation
When auto-rotation is enabled, the key ID and alias remain the same while new cryptographic material is generated. Old material is kept to decrypt data that was previously encrypted.
Note: Auto-rotation is NOT available for keys with imported key material. For those keys, create a new CMK with new imported key material and update the key alias to point to the new CMK. Applications referencing the alias automatically start using the new key.
aws kms update-alias \
--alias-name alias/my-app-key \
--target-key-id arn:aws:kms:us-east-1:123456789:key/new-key-id
Cross-Account KMS Key Sharing
To allow another account to use your KMS key (e.g., for cross-account RDS snapshot sharing):
- Update the key policy in the source account to grant the target account the four required permissions:
{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::TARGET-ACCOUNT:root"},
"Action": ["kms:DescribeKey", "kms:ReEncrypt*", "kms:CreateGrant", "kms:Decrypt"],
"Resource": "*"
}
- In the target account, create an IAM policy allowing use of the source account's key.
Exam Tip: Cross-account KMS requires exactly these four permissions:
kms:DescribeKey,kms:ReEncrypt*,kms:CreateGrant,kms:Decrypt. Memorize all four.
Sharing Encrypted AMIs Across Accounts
- Create a CMK in the AMI owner account (cannot share AMIs encrypted with an AWS managed key).
- Create a copy of the AMI specifying the CMK.
- Update the key policy with the four required permissions for the target account.
- Modify AMI permissions to include the target account number.
- Do NOT make the AMI public.
2.2 AWS Certificate Manager (ACM)
ACM-Issued Certificates — Auto-Renewal
ACM automatically renews certificates that IT issued when the certificate is less than 60 days from expiration. No action is required by the CloudOps Engineer. This applies to certificates associated with ALB, CloudFront, API Gateway, and similar services.
Imported Certificates — Manual Renewal Required
ACM does NOT auto-renew certificates imported from third-party CAs. ACM sends expiry notifications via EventBridge 45, 30, 15, 7, 3, and 1 days before expiration. Set up an EventBridge rule → SNS notification → alert the team when an imported certificate is about to expire.
Exam Tip: "Company uses ACM certificate. CloudOps Engineer must create a solution to automatically renew certificates." → If the certificate was issued by ACM, auto-renewal is already built in — no Lambda needed. If the certificate is imported from a third party, ACM does NOT auto-renew; handle it separately via EventBridge.
2.3 Encryption at Rest — Service Restrictions
| Service | Can Encrypt Existing Resource In-Place? |
|---|---|
| S3 objects | Yes — enable default encryption; use Batch Operations for existing objects |
| EBS volumes | No — snapshot → copy with encryption → restore |
| RDS instances | No — snapshot → copy with encryption → restore |
| EFS file systems | No — create new encrypted EFS → migrate data |
| DynamoDB tables | Yes — encryption managed by AWS; enabled by default |
Forcing HTTPS on S3 Bucket
Add a bucket policy that denies all non-HTTPS requests:
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"],
"Condition": { "Bool": { "aws:SecureTransport": "false" } }
}
Note: The condition is
aws:SecureTransport: false→ DENY when NOT using HTTPS. This forces all S3 access to use HTTPS.
3. AWS Secrets Manager
3.1 Secrets Manager Features
Auto-Rotation Architecture
When rotation is enabled, Secrets Manager creates a new secret version (AWSPENDING), invokes the rotation Lambda function, the Lambda updates the secret in Secrets Manager and the actual password in the database, tests the new credentials, then marks the new version as AWSCURRENT and the old version as AWSPREVIOUS.
AWS provides pre-built rotation Lambda functions for Amazon RDS (MySQL, PostgreSQL, Oracle, MSSQL, MariaDB), Amazon Redshift, Amazon DocumentDB, and Amazon Aurora.
Diagnosing Rotation Failures
When an application gets authentication failures after a rotation: check the Lambda function logs in CloudWatch Logs — the rotation Lambda logs its operations and any errors.
CloudFormation Integration
MyDBSecret:
Type: AWS::SecretsManager::Secret
Properties:
GenerateSecretString:
SecretStringTemplate: '{"username": "admin"}'
GenerateStringKey: "password"
PasswordLength: 16
MyDBSecretRotationSchedule:
Type: AWS::SecretsManager::RotationSchedule
Properties:
SecretId: !Ref MyDBSecret
RotationLambdaARN: !GetAtt RotationLambda.Arn
RotationRules:
AutomaticallyAfterDays: 30
MyDatabase:
Type: AWS::RDS::DBInstance
Properties:
MasterUserPassword: "{{resolve:secretsmanager:MyDatabaseSecret:SecretString:password}}"
3.2 Parameter Store vs. Secrets Manager — Decision Matrix
| Requirement | Use | Reason |
|---|---|---|
| Store CloudWatch agent JSON config | Parameter Store | No secrets; large value; free |
| Store RDS password with monthly rotation | Secrets Manager | Built-in RDS rotation Lambda |
| Store API keys needing rotation | Secrets Manager | Rotation scheduling available |
| Store non-secret app configuration | Parameter Store | Free; simple key-value |
| Cross-account secret sharing | Secrets Manager | Resource policy support |
| Secrets for CloudFormation templates | Secrets Manager | Dynamic references; generate during deploy |
4. AWS Config — Compliance Monitoring
4.1 AWS Config Core Functionality
Config monitors configuration history (complete audit trail of every change to every resource), compliance evaluation (compare current configuration against rules), and resource relationships.
Config Rules
| Type | Description | Examples |
|---|---|---|
| Managed rules | Pre-built by AWS | required-tags, restricted-ssh, s3-bucket-public-read-prohibited, rds-multi-az-support, encrypted-volumes |
| Custom rules | Lambda function you write | Any custom compliance logic |
| Service-managed rules | Rules from AWS services | Security Hub rules, Control Tower guardrails |
Config + SSM Automation = Auto-Remediation
Non-compliant resource detected
│
▼
Config marks resource as NON_COMPLIANT
│
▼
Remediation action triggered
│
▼
SSM Automation runbook executes
│
▼
Resource brought into compliance
Key Concept: "Re-enable CloudTrail without writing custom code if it gets disabled" → Config rule (detects the change) + SSM Automation runbook (re-enables it). This is the canonical "no custom code" pattern for auto-remediation.
4.2 Security Services — Comparison and Use Cases
| Need | Service |
|---|---|
| Security groups open to internet (port 3389) | AWS Trusted Advisor |
| Compromised EC2 instance detected | Amazon GuardDuty |
| CVE vulnerabilities on EC2 instances | Amazon Inspector |
| PII sensitive data in S3 buckets | Amazon Macie |
| Aggregate security findings from all services | AWS Security Hub |
| Continuous configuration compliance | AWS Config |
| Check IAM policy count vs. service limits | AWS Trusted Advisor |
| Block suspicious traffic | WAF, NACLs, Security Groups |
Key Concept: GuardDuty detects threats using ML analysis of CloudTrail, VPC Flow Logs, and DNS logs. It does NOT block traffic or remediate — to block a GuardDuty-identified threat, use NACLs, security groups, or WAF separately.
The number of available Trusted Advisor checks is determined by the AWS Support plan level — Basic/Developer plans have limited free checks, Business and Enterprise plans have all checks plus API access.
4.3 AWS WAF — Web Application Firewall
WAF Scopes
| Scope | Where Deployed | Protects |
|---|---|---|
| Global (us-east-1) | CloudFront | CloudFront distributions globally |
| Regional | Each region | ALB, API Gateway, AppSync in that region |
Exam Tip: WAF for CloudFront MUST be deployed in us-east-1 as a global resource, regardless of where your application runs. WAF cannot be attached directly to S3 buckets.
WAF Rate-Based Rules for DDoS Protection
- Create a global WAF web ACL (for CloudFront).
- Add a rate-based rule: block IPs exceeding X requests per 5 minutes.
- Set the default action to Allow (block only rate-exceeded IPs).
- Associate the web ACL with the CloudFront distribution.
Exam Tip: Wrong answers for "protect S3 website behind CloudFront from DDoS": Block as the default action (would block ALL traffic), regional WAF on S3 (WAF cannot be attached to S3 buckets), WAF directly on S3 (not supported).
5. Cost Allocation and Billing Security
5.1 Cost Allocation Tags
Tags must be activated in the payer (management) account's Billing console. Member accounts cannot activate tags for organization-wide cost allocation. After activation, tags appear in Cost Explorer within 24 hours.
Types of cost allocation tags: user-defined tags you apply to resources (e.g., Project: Phoenix) and AWS-generated tags automatically added by AWS (e.g., aws:createdBy showing the IAM identity that created the resource).
Exam Tip: "Managers in member accounts cannot configure billing alarms. What is wrong?" → The management/payer account does not have billing alerts turned on. Enable billing alerts in the payer account first.
5.2 Amazon Cognito for Authentication
When enterprise users need to log into Kibana using their corporate Active Directory credentials:
- Deploy Amazon Cognito user pool with Active Directory as an external identity provider (SAML).
- Configure the user pool with the AD FS SAML endpoint.
- Enable Cognito authentication for Kibana on the Elasticsearch/OpenSearch domain.
- Users authenticate via Cognito → Cognito authenticates with AD → issues token → Kibana access granted.
Note: Kibana does not have native IAM authentication. Cognito provides the bridge between enterprise identity (AD) and Kibana access.
5.3 IAM Identity Center for Multi-Account Access
When a company already has on-premises Active Directory and wants to use it for AWS access:
- AD Connector (recommended): proxies authentication requests to on-premises AD; no user data is synchronized to AWS; users authenticate with existing AD credentials; works over Direct Connect or VPN.
- Simple AD: creates a new AWS-managed directory; requires recreating or syncing users; use only when there is no existing on-premises AD.
Permission Sets define IAM permissions for each role (DevOps, ReadOnly, Admin) and can be assigned to user groups for specific accounts. One permission set can be used across multiple accounts.
Exam Tip: "Centrally manage user accounts across multiple AWS accounts; integrate with existing on-premises AD; already have Direct Connect" → IAM Identity Center + AD Connector pointing to on-premises AD over Direct Connect.
6. Federation and Identity
6.1 SAML Federation for Enterprise SSO
User's Browser
│ Login with AD credentials
▼
AD FS / Identity Provider
│ Authenticate user, create SAML assertion
▼
AWS SAML Endpoint (sts:AssumeRoleWithSAML)
│ Exchange SAML assertion for temporary credentials
▼
IAM Role (mapped from SAML attributes/group membership)
│ Temporary credentials
▼
AWS Console / API / CLI
Each LDAP group maps to an IAM role: AD Group: AWS-Admin → IAM Role: Administrator, AD Group: AWS-DevOps → IAM Role: DevOpsRole, and so on.
Exam Tip: "Organization uses LDAP for IT department access management. Allow AWS access using existing LDAP credentials with minimum new IAM users." → Federate the LDAP directory with IAM using SAML. Create IAM roles corresponding to LDAP groups.
Exam Tips & Quick Reference
Scenario-to-Answer Mapping
| Scenario Keyword / Requirement | Correct Answer |
|---|---|
| "CLI authentication fails" | No access key configured (not password, not SSH key) |
| "API calls without MFA despite policy requiring it" | Use aws sts get-session-token to get temporary credentials with MFA |
| "Create least-privilege policy for role" | Enable CloudTrail + IAM Access Analyzer policy generation |
| "Automatically renew certificate on ELB" | ACM-issued cert auto-renews; no Lambda needed |
| "Auto-renew imported third-party cert" | ACM does NOT auto-renew imported certs; use EventBridge + SNS |
| "Rotate KMS key with imported material" | Create new CMK + new imported key material; update alias |
| "Share encrypted RDS snapshot cross-account" | Update KMS key policy with 4 permissions; share snapshot |
| "Encrypt existing unencrypted S3 objects" | Enable default encryption + S3 Batch Operations copy in-place |
| "Encrypt existing unencrypted RDS" | Snapshot → copy with encryption → restore new instance |
| "Encrypt existing unencrypted EFS" | Create new encrypted EFS → migrate data |
| "Re-enable CloudTrail without custom code" | Config rule + SSM Automation runbook |
| "Classify PII in S3" | Amazon Macie discovery job |
| "EC2 vulnerability scanning" | Amazon Inspector |
| "Threat detection for compromised EC2" | Amazon GuardDuty |
| "Aggregate security findings all accounts" | AWS Security Hub |
| "Security group open to internet port 3389" | AWS Trusted Advisor |
| "WAF to protect CloudFront distribution" | Global-scoped WAF web ACL deployed in us-east-1 |
| "WAF for ALB" | Regional WAF web ACL in same region as ALB |
| "WAF directly on S3 bucket" | Not possible; WAF cannot be attached to S3 |
| "Billing alarms cannot be configured in member accounts" | Enable billing alerts in payer account first |
| "Cost allocation tags not appearing in Cost Explorer" | Activate tags in payer account (not member account) |
| "Enterprise SSO with on-premises AD" | IAM Identity Center + AD Connector |
| "Kibana access with corporate AD credentials" | Amazon Cognito user pool + AD as identity provider |
| "Force HTTPS on S3 bucket" | Bucket policy: Deny when aws:SecureTransport: false |
Common Traps
- ACM auto-renewal is scoped to ACM-issued certs only: Certificates imported from third-party CAs are never automatically renewed. Always ask whether the cert was issued by ACM or imported.
- KMS imported key material cannot auto-rotate: The only rotation option is to create a new CMK, import new material, and update the alias. The application does not need to change if it references the alias.
- GuardDuty detects — it does NOT block: Blocking always requires a separate action (NACL, security group, WAF rule). Selecting GuardDuty as the "block" answer is always wrong.
- WAF scope must match the service it protects: Global WAF (in us-east-1) for CloudFront; regional WAF (in the same region) for ALB. Cross-matching these will fail.
Key Terms — Domain 4
| Term | One-Line Definition |
|---|---|
| IAM instance profile | Container for an IAM role attached to an EC2 instance for IMDS-based credential access |
| STS get-session-token | API call that returns temporary credentials satisfying MFA requirements for CLI use |
| IAM Access Analyzer | Service that generates least-privilege IAM policies from CloudTrail activity logs |
| Customer Managed Key (CMK) | KMS key you create and control, with optional manual or automatic rotation |
| Config managed rule | Pre-built AWS Config rule for common compliance checks (e.g., required-tags, encrypted-volumes) |
| GuardDuty | ML-based threat detection service analyzing CloudTrail, VPC Flow Logs, and DNS logs |
| Macie | ML-based sensitive data discovery service that classifies PII and PHI in S3 |
| WAF global scope | WAF web ACL deployed in us-east-1 for protecting CloudFront distributions |
| AD Connector | Directory Gateway that proxies authentication to an existing on-premises Active Directory |
| SAML Federation | Protocol enabling LDAP/AD group memberships to map to IAM roles for AWS access |
End of Domain 4. Continue to Domain 5: Networking and Content Delivery →
Ready to test yourself?
Practice questions for this topic