What CloudSecOps is
Link to section “What CloudSecOps is”In 30 seconds
Link to section “In 30 seconds”CloudSecOps (cloud security operations) is the continuous work of keeping a cloud estate secure through the provider’s own control plane: guardrails that stop unsafe configuration before it exists, posture checks that find drift, audit logs that record every administrative action, and detection and response for suspicious control-plane activity.
For cloud security and platform engineers, security architects, SOC leads, and leaders who decide what to enforce. Facts last checked 2026-10-17.
At a glance
Link to section “At a glance”| Item | Summary |
|---|---|
| Term status | Emerging. In use in trade press by 2022; the practices are documented by providers, CIS, CSA, NSA/CISA and MITRE. |
| Goals | Unsafe configurations blocked or found quickly; every administrative action logged where attackers cannot erase it; control-plane threats detected and contained. |
| In scope | Shared responsibility for security controls, security guardrails and drift, CSPM/CWPP/CNAPP, cloud IAM misconfigurations, keys, audit logging, public storage, CIS cloud benchmarks, cloud detection and response basics. |
| Out of scope | See What CloudSecOps is not. |
| Prerequisites | CloudOps (hierarchy, accounts, Regions); basic IAM; one provider’s CLI. |
| Key outputs | A versioned security guardrail set with exceptions, an organisation-wide audit log archive, a triaged posture backlog with owners, tested control-plane detections and runbooks. |
The problem it solves
Link to section “The problem it solves”In the cloud, a bucket becomes public, a key is created or a log is switched off with one API call by anyone holding the right permission, including an attacker holding someone else’s. Three patterns recur:
- Configuration. The Cloud Security Alliance’s 2024 Top Threats ranking, built from a poll of more than 500 industry experts, put misconfiguration and inadequate change control first and identity and access management second.[4] It is an expert ranking, not incident data.
- Credentials. Mandiant traced every incident it handled in the 2024 Snowflake customer campaign “back to compromised customer credentials”, on accounts without multi-factor authentication.[5]
- Missing logs. In the 2023 Exchange Online intrusion reviewed by the US Cyber Safety Review Board, one victim agency “could not view past activity as these logs only captured data from the time that Microsoft enabled the advanced logging”.[6]
| Operating reality | Without CloudSecOps | With CloudSecOps |
|---|---|---|
| A risky setting (public bucket, open admin port) | Found by an outsider | Blocked, or found and assigned within hours |
| Audit logs | A 90-day built-in history, plus account-level trails or exports that account admins can stop or delete | An organisation trail or export into an account workload admins cannot change |
| A suspicious API call | Nobody is looking | A tested detection pages an on-call engineer with a runbook |
| Exceptions | Permanent, undocumented | Owner, reason, expiry date, review |
What CloudSecOps is not
Link to section “What CloudSecOps is not”- Not SecOps with a cloud connector. In this Atlas, SecOps is the collaboration hub between security and IT operations and governs hardening baselines; SOC Ops runs triage. CloudSecOps supplies them with cloud-specific controls, telemetry and runbooks.
- Not DevSecOps. DevSecOps catches misconfigurations in the pull request; CloudSecOps owns the deployed state, including changes made outside the pipeline.
- Not CloudOps. CloudOps owns the account structure, operational guardrails (Regions, tags, budgets) and teaches the shared responsibility model; CloudSecOps decides which security guardrails to enforce and watches them drift.
- Not identity engineering. How policies are written and evaluated → IAMOps; accounts and SSO → IdentityOps; just-in-time elevation → AccessOps.
- Not a product, not compliance. A posture tool gives findings, not owners or fixes; audit programmes belong to ComplianceOps, and CloudSecOps produces their evidence.
Where CloudSecOps comes from and where it sits
Link to section “Where CloudSecOps comes from and where it sits”Origins and evolution
Link to section “Origins and evolution”No founding document exists. These dated milestones can be verified:
| Date | Milestone | What it shows |
|---|---|---|
| 2021 | A Wiz-authored post on the CSA blog says Gartner coined “CNAPP”[7] | Posture and workload tools start to converge |
| 2022 | TechTarget SearchSecurity and Data Center Knowledge articles use “CloudSecOps”[1][2] | The label is in use, with different emphases |
| 2024 | CISA and NSA cloud information sheets (March);[8] the Snowflake customer campaign (June);[5] CSRB calls for free default audit logging;[6] CISA BOD 25-01 (December)[9] | Credentials and logging become policy topics |
| 2026 | Google closes its Wiz acquisition (March);[10] MITRE ATT&CK v20 regroups cloud log tampering under a new technique ID[11] | Tools consolidate; vocabulary still moves |
Glossary and mental model
Link to section “Glossary and mental model”| Term | Meaning on this page |
|---|---|
| Control plane / data plane | Management operations that create, change and delete resources, versus operations inside a resource. Azure’s activity log records the first; its resource logs record the second.[12] |
| Posture | The security-relevant configuration of the estate at a point in time, measured against a baseline. |
| Guardrail | A control that runs continuously in the background;[1] this page distinguishes preventive (blocks the call), detective (reports drift) and responsive (alerts or remediates). |
| SCP / RCP | AWS organisation policies that cap what principals (SCP) or resources (RCP) can do. Neither grants permissions; effective permissions are the intersection with identity and resource policies.[13][14] |
| OU, service-linked role | An organisational unit groups AWS accounts so that one attached policy covers them all. A service-linked role is predefined by an AWS service and used on your behalf; SCPs and RCPs do not restrict it.[13] |
| IMDSv2 | The session-oriented version of the EC2 instance metadata service, which AWS links to defence in depth against SSRF (see Use case 1).[15] |
| Data perimeter | AWS: “a set of preventive controls you can use to help ensure that only your trusted identities access your trusted resources from expected networks”.[16] |
| CSPM, CWPP, CNAPP | Posture management, workload protection, and the platform that combines them. Microsoft describes Defender for Cloud as a CNAPP with CSPM, DevSecOps and CWPP components.[17] |
The mental model: four questions at the API. Every cloud action is an authenticated API call. CloudSecOps keeps four answers current: who can call (the identity perimeter), what they may configure (preventive guardrails), what the estate looks like now (posture), and what happened (logs and detections). A perfect posture score says nothing about an attacker using valid keys. This model is this Atlas’s teaching device, not an industry framework.
How CloudSecOps relates to other Ops
Link to section “How CloudSecOps relates to other Ops”| Page | Shared ground | CloudSecOps focus | Their focus |
|---|---|---|---|
| CloudOps | Organisation policies | Security guardrails, posture, CIS benchmarks | Hierarchy, Regions, tags, budgets, quotas |
| IAMOps | SCPs, Azure Policy | Which guardrails to enforce and their drift | Writing and evaluating policy language |
| DevSecOps | IaC findings | Deployed state and out-of-band change | The pull request and pipeline |
| KubernetesSecOps | Workload identity | Cloud accounts | Admission and runtime in clusters |
| SecOps, SOC Ops | Alerts, baselines | Cloud context, telemetry and runbooks | Coordination; 24×7 triage |
| DetectionOps, SecDataOps | Cloud logs | Which logs exist and where | Detection logic; telemetry pipelines |
| ComplianceOps | Benchmarks | Producing evidence | Audit programmes |
| VulnerabilityOps | Findings | Configuration findings | Software vulnerabilities and patch priority |
Principles and operating model
Link to section “Principles and operating model”Charter and principles
Link to section “Charter and principles”This charter is this Atlas’s proposal; no official CloudSecOps manifesto exists.
Mission: make unsafe cloud configuration hard to create, quick to find and hard to hide.
- Prevent centrally what must never happen; detect the rest. Organisation-level denies for a short list of catastrophic actions, detective checks for everything that has legitimate exceptions.
- Every guardrail has an owner, a test, an exception path and a measurement. A rule without an exception path creates shadow accounts.
- Collect logs before you need them, where workload administrators cannot change them.
- Identity is the perimeter. Long-lived keys are debt with interest; federated, short-lived credentials are the default.
- Know each control’s preconditions. Name the accounts, Regions and principals a control does not cover.
- Fix in code. The next deployment reverts a console fix; remediate in the infrastructure as code (InfraOps).
Non-goals: writing application code, running the SOC, designing permission models for each workload.
Fundamentals: shared responsibility applied to controls
Link to section “Fundamentals: shared responsibility applied to controls”CloudOps teaches the shared responsibility model; this table applies Microsoft’s matrix to security controls.[18]
| Control area | IaaS | PaaS and serverless | SaaS |
|---|---|---|---|
| Identities, access, configuration settings, data | Customer | Customer | Customer |
| Network controls | Customer | Shared | Provider |
| Operating system and patching | Customer | Provider | Provider |
The building blocks follow the four questions: an identity perimeter of federated, short-lived credentials (designed in
IAMOps and IdentityOps); preventive guardrails such as AWS SCPs, RCPs and declarative
policies, Azure Policy deny and Google Organization Policy constraints;[13][14][19][20][21]
detective posture, including analysis of resources shared outside a “zone of trust”;[22] and audit logs with
detections. Keys and encryption cut across all four.
Defaults decide where the work starts (as of October 2026):
| Log | AWS | Azure | Google Cloud |
|---|---|---|---|
| Control-plane audit log | Event history keeps 90 days of management events; a trail stores more[23] | Activity log kept 90 days; export with a diagnostic setting[12] | Admin Activity logs “always written”; cannot be disabled[24] |
| Data-plane audit log | Data events off by default, charged extra[25] | Resource logs need a diagnostic setting[12] | Data Access logs off by default except BigQuery[24] |
| Identity sign-ins and directory changes | Console sign-ins are CloudTrail events[26] | Entra ID sign-in and audit logs kept 7 days (Free) or 30 days (P1/P2); route them out with Azure Monitor[27] | Cloud Identity and Workspace login logs reach Cloud Logging only once you enable sharing[28] |
If identity is the perimeter, the identity row matters most, and Entra retention is not retroactive: after an upgrade from Free, “only data still within the free retention period (up to seven days) is available”.[27]
Two other defaults matter. On AWS, instances accept both IMDSv1 and IMDSv2 unless a newer default requires IMDSv2.[15][29] On Google Cloud, organisations created on or after 3 May 2024 start with baseline constraints such as disabled service-account key creation and uniform bucket-level access; older organisations may not have them.[30]
Keys, secrets and encryption
Link to section “Keys, secrets and encryption”Most services encrypt at rest by default, so the work is deciding who controls each key and who may use it. AWS owned keys cost nothing, but “you cannot change their policies, you cannot audit activities on these keys, and you cannot delete them”; customer managed keys give “full control over the lifecycle and usage” for a monthly fee.[31] Azure and Google Cloud call these customer-managed keys (CMK, CMEK). Pay for one when you must see every use in your own logs, decide who may use it, or make data unreadable by disabling it. Three controls then matter more than rotation:
- Separate administering from using. AWS’s default key policy lets key administrators manage a key but not use it; because they can edit the policy, they “can give themselves and others” more access, so treat key administration as privileged.[32]
- Guard deletion. Deleting a KMS key “is destructive and potentially dangerous”: the data it protects “becomes
unrecoverable”, so each provider adds a delay. AWS KMS waits 7–30 days (default 30);[33] AWS’s sample SCPs reserve
kms:ScheduleKeyDeletionfor a privileged role or forbid waiting periods under 30 days.[34] Azure Key Vault keeps deleted keys recoverable for 7–90 days; add purge protection, which services such as Azure Storage require.[35] Cloud KMS waits 30 days by default, and an organisation policy can enforce a minimum.[36] - Keep key-use logs. CloudTrail logs all AWS KMS actions by default, but a trail can exclude them all to cut volume;[37] never exclude them from the trail covering accounts that hold sensitive data.
Secrets belong in the provider’s secret store (AWS Secrets Manager, Azure Key Vault, Google Secret Manager), never in code or instance user data; how pipelines fetch them belongs to DevSecOps.
Roles, ownership and RACI
Link to section “Roles, ownership and RACI”Microsoft’s Cloud Adoption Framework describes posture management as “the operational security team that focuses on security enablement for technical operations teams”.[38] The RACI below is this Atlas’s proposal (R = responsible, A = accountable, C = consulted, I = informed).
| Activity | Cloud security | Cloud platform | Workload team | SOC | Risk owner / GRC |
|---|---|---|---|---|---|
| Choose the security guardrail set and baseline | A/R | C | C | I | C |
| Deploy organisation policies through the pipeline | A | R | I | I | I |
| Organisation audit log, archive account, retention | A/R | R | I | C | C |
| Triage and route posture findings | A/R | C | I | I | I |
| Fix a misconfiguration in a workload | C | C | A/R | I | I |
| Approve an exception | R | C | R (requests) | I | A |
| Cloud detection use cases and runbooks | A/R | C | I | R | I |
| Contain a cloud incident | R | R | C | A | I |
Skills: IAM evaluation logic, policy as code, logging architecture, audit-log queries, incident handling. Small organisations combine these roles (see When to use).
Lifecycle: Day 0, Day 1, Day 2
Link to section “Lifecycle: Day 0, Day 1, Day 2”- Day 0, design. Pick a baseline (a CIS Foundations benchmark or the provider’s), list the few actions to deny everywhere, design the log archive and its retention, decide the exception process.
- Day 1, roll out. Turn on organisation-wide logging and posture scanning first, then trial guardrails, then enforce OU by OU.
Azure’s
DoNotEnforcemode exists “when you want to evaluate the policy assignment before enforcement”,[39] and Google supports dry-run organisation policies.[21] AWS SCPs and RCPs have no documented evaluate-only mode, so on AWS the trial is a test OU and a review of its access-denied events.[13] - Day 2, run. The cadences below.
Operating model and governance
Link to section “Operating model and governance”| Cadence | Activity | Output |
|---|---|---|
| Continuous | Guardrail enforcement, posture scans, control-plane detections | Denied calls, findings, alerts |
| Daily | Triage of new critical findings | Owner and due date on each |
| Weekly | Exception and overdue-finding review | Renewed, closed or escalated exceptions |
| Monthly | Guardrail and benchmark review | Changes to the guardrail set, staged by OU |
| Quarterly | Game day and metrics review (scorecard in Templates) | Tested detections, trend report to leadership |
Release guardrails like software, from a test OU to ever broader OUs; CloudOps teaches that staged rollout.[34] Exceptions use the exception request, capped at 90 days (this page’s suggestion).
Architecture and workflow
Link to section “Architecture and workflow”Reference architecture: guardrail and evidence layers
Link to section “Reference architecture: guardrail and evidence layers”CloudOps shows the landing zone; this view adds the security layers in AWS terms, and the table after it gives the Azure and Google Cloud counterparts.
Diagram source (Mermaid)
flowchart TB MGMT["Management account: no workloads, outside SCPs and RCPs"] -->|"attaches"| POL POL["Organisation policies: SCP, RCP, declarative"] POL --> MEM["Member accounts: workloads and sandboxes"] MEM -->|"organisation trail"| LOG["Log archive account"] MEM -->|"findings"| SEC["Security tooling account"] LOG --> SIEM["Query store or SIEM"] SEC --> TRI["Triage queue"] TRI -->|"misconfiguration"| OWN["Workload owner: fix in IaC"] TRI -->|"threat"| SOC["SOC: incident"] classDef core fill:#e8f3f2,stroke:#16756f,color:#122029 classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029 classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029 class POL,LOG,SEC,TRI core class MEM,SIEM,OWN,SOC neutral class MGMT risk
Text equivalent: The management account, marked as a risk, holds no workloads because SCPs and RCPs do not limit it; it attaches the organisation policies (SCP, RCP, declarative), which apply to the member accounts holding workloads. Member accounts send audit events through the organisation trail to a log archive account, which feeds a query store or SIEM, and findings to a security tooling account and its triage queue: misconfigurations go to the workload owner to fix in code, threats to the SOC.
Design choices, with their evidence:
- Keep the management account empty. “SCPs don’t affect users or roles in the management account”, nor RCPs its resources.[13][14]
- Log through the organisation. Member-account users “do not have sufficient permissions to delete organization trails, turn logging on or off, change what types of events are logged”.[40] Only the security team administers the archive account.
- Cover every enabled Region. Security Hub CSPM “only receives and processes findings in the Region where you enabled” it, and AWS recommends enabling GuardDuty “in all AWS Regions”, including ones you do not use, because attackers can create resources there.[41][42]
| Layer | AWS | Azure | Google Cloud |
|---|---|---|---|
| Hierarchy for policy | Organization, OUs, accounts | Management groups, subscriptions | Organization, folders, projects |
| Preventive guardrails | SCP, RCP, declarative policies | Azure Policy (deny, denyAction)[20] |
Organization Policy constraints[21] |
| Control-plane log | CloudTrail organisation trail[40] | Activity log via diagnostic settings[12] | Admin Activity audit logs[24] |
End-to-end workflow: from change to verified fix
Link to section “End-to-end workflow: from change to verified fix”Diagram source (Mermaid)
flowchart TB
CHG["Change: pipeline, console, script or attacker"] --> PRE{"Preventive guardrail matches?"}
PRE -->|"yes"| DENY["Call denied and logged"]
DENY --> EXC{"Legitimate need?"}
EXC -->|"yes"| REQ["Exception request: owner, reason, expiry"]
EXC -->|"no"| STOP["Requester changes the design"]
PRE -->|"no"| RES["Resource created or changed"]
RES --> SCAN["Posture scan or detection"]
SCAN --> TRI{"Finding type?"}
TRI -->|"misconfiguration"| FIX["Owner fixes in IaC within SLA"]
TRI -->|"suspicious activity"| INC["SOC incident and runbook"]
FIX --> VER["Rescan confirms closure"]
FIX -->|"SLA missed"| ESC["Escalate, or exception with expiry"]
classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
class CHG,RES,SCAN,FIX,VER,REQ core
class PRE,EXC,TRI decision
class DENY,INC,ESC,STOP risk
Text equivalent: A change arrives from a pipeline, console, script or attacker. If a preventive guardrail matches, the call is denied and logged; a legitimate need becomes an exception request with owner, reason and expiry, otherwise the design changes. If not, the change happens and a posture scan or detection evaluates it: misconfigurations go to the owner to fix in infrastructure as code, confirmed by a rescan (a missed target escalates or becomes a time-limited exception); suspicious activity becomes a SOC incident with a runbook.
Acceptance criteria (this page’s suggestion): every finding has an owner within one working day, and every closure is confirmed by a rescan, not a ticket comment.
Practices, frameworks and tools
Link to section “Practices, frameworks and tools”Core practices and playbooks
Link to section “Core practices and playbooks”| Practice | Trigger | Owner | Output | Verification |
|---|---|---|---|---|
| Guardrail release | New risk, incident, benchmark change | Cloud security, with platform | Policy as code, staged by OU | No unexpected denials in the test OU |
| Logging baseline | New account or Region | Platform | Organisation trail or exports | A test event reaches the archive |
| Posture triage | New critical finding | Cloud security | Owner and due date, or false-positive record | Finding closes on rescan |
| Credential hygiene | Long-lived key detected | Workload owner | Key replaced by role or federation | Unused-access findings fall |
| Detection game day | Quarterly, new detection | Cloud security with SOC | Alert received, runbook followed | Time to alert within target |
Methods, standards and frameworks
Link to section “Methods, standards and frameworks”Separate what binds you from what guides you:
| Framework | Type | Use it for | Caveat |
|---|---|---|---|
| CIS Foundations Benchmarks (AWS 7.1.0, Azure 6.0.0, Google Cloud 5.0.0 as of October 2026)[43][44][45] | Consensus guidance, free PDF for non-commercial use | A starting baseline with assessment procedures | Tools lag versions; some checks are manual |
| Microsoft cloud security benchmark (v1; v2 in preview)[46] | Vendor benchmark, multicloud | Azure-first estates; pre-mapped to CIS, NIST, PCI DSS | v2 baselines not yet published |
| CSA Cloud Controls Matrix v4.1[47] | Control framework, 197 objectives in 17 domains | Assigning each control to provider or customer | Control objectives, not settings |
| CISA/NSA cloud information sheets (2024)[8] | Government guidance | Identity, keys, segmentation, data, MSP risks | Advisory outside US federal mandates |
| CISA BOD 25-01[9] | Mandatory for US federal civilian agencies | SaaS tenant baselines (SCuBA: Secure Cloud Business Applications) | Binding only in its jurisdiction |
| MITRE ATT&CK Cloud matrix (v20)[48] | Threat knowledge base | Choosing and testing control-plane detections | Coverage maps are not protection |
Tools lag benchmarks. CIS lists AWS Foundations 7.1.0 as current,[43] while Security Hub CSPM “supports CIS AWS Foundations Benchmark versions 5.0.0, 3.0.0, 1.4.0, and 1.2.0” and leaves some requirements, such as metric-filter alarms, as manual checks.[49] A green dashboard means passes the automated subset of an earlier version; record the version.
Common IAM and exposure misconfigurations
Link to section “Common IAM and exposure misconfigurations”This page maps the most consequential recurring mistakes to Security Hub CSPM control IDs and to a preventive option (AWS, as of October 2026).[50]
| Misconfiguration | Check | Preventive option |
|---|---|---|
A policy allowing * actions on * resources |
IAM.1 | Validation gate and permission boundaries (IAMOps) |
| Root user access keys | IAM.4 | Centralised root access, then delete member-account root credentials[51] |
| User credentials unused for 45 days | IAM.22 | Federation for people; unused-access findings[22] |
| Trust or resource policies open to other accounts | IAM.28 (analyzer on) | External-access findings; data-perimeter RCP[16] |
| Publicly restorable EBS snapshots | EC2.1, EC2.182 | Snapshot and image block public access (EC2 declarative policy)[29] |
Admin ports open to 0.0.0.0/0 or ::/0 |
EC2.53, EC2.54 | Detective, routed to the owner; VPC Block Public Access where no ingress is needed[29] |
| Public buckets | S3.1, S3.8 | Organisation-level S3 block[52] |
| IMDSv1 still accepted | EC2.8 | Instance metadata defaults (EC2 declarative policy)[29] |
| KMS key scheduled for deletion | KMS.3 | SCP on kms:ScheduleKeyDeletion[34] |
Tooling landscape
Link to section “Tooling landscape”| Category | Job | Verified examples (October 2026) | Limits and selection criteria |
|---|---|---|---|
| Native preventive | Block calls or settings | AWS SCP, RCP, declarative policies; Azure Policy; Google Organization Policy | Provider-specific; know exempt principals |
| Native posture | Check configuration against standards | Security Hub CSPM (needs AWS Config, Regional; also checks Azure);[41][53] Defender for Cloud;[17] Security Command Center[54] | Attack paths only in paid tiers (Defender CSPM, SCC Premium) |
| Access analysis | Find external, internal and unused access | IAM Access Analyzer[22] | External analyzers are Regional |
| Threat detection | Flag suspicious control-plane and network activity | GuardDuty;[42] Defender for Cloud plans; Security Command Center Premium | Detections are vendor-defined; test them |
| Multicloud CNAPP | One posture and risk view across providers | Defender for Cloud (AWS, GCP connectors); Security Hub CSPM (Azure); commercial CNAPPs | Consolidation risk: SCC Enterprise shuts down on 21 May 2027;[54] Google closed its Wiz acquisition in March 2026[10] |
| Open source | Scan or enforce as code | Prowler (Apache 2.0, many providers);[55] Cloud Custodian (CNCF incubating)[56] | You run, update and tune them |
Native tools now cross providers (as of October 2026). AWS runs two services. Security Hub CSPM, cited throughout this page, also scores Azure against CIS Azure Foundations v4.0 (CIS lists 6.0.0). The newer AWS Security Hub correlates CSPM, Inspector, Macie and GuardDuty findings into exposure findings with an attack path graph, in OCSF (Open Cybersecurity Schema Framework). AWS recommends enabling both.[53][57]
Selection criteria: coverage of the benchmark version you need; organisation-wide and cross-Region aggregation; export in an open format (Prowler writes CSV and JSON-OCSF by default; its SARIF output, a static-analysis format, is for IaC scans only);[58] routing to owners rather than to one security queue; cost model (per check, per resource, per role); and an exit plan if the vendor changes hands.
Automation and AI
Link to section “Automation and AI”Automate prevention freely and remediation carefully: only what is reversible, high-confidence and narrow, such as
re-enabling a public access block on a bucket tagged as private; never auto-delete data or rotate credentials in use. Azure
Policy’s modify and deployIfNotExists effects remediate inside the platform;[20] elsewhere, run automation as a
dedicated, logged role. Language models can summarise findings and draft runbook steps, but their suggestions are changes that
need review; see AIOps for Security.
CloudSecOps in practice
Link to section “CloudSecOps in practice”Reference implementation
Link to section “Reference implementation”Assumptions: an AWS organisation with all features enabled, a security tooling account, a log archive account, policies kept in Git and deployed by a pipeline role. The worked artefacts are AWS-first: for Azure and Google Cloud, item 3 gives the storage equivalent and the layer table names the policy and log mechanisms, without worked examples.
1. A service control policy that protects security telemetry. Adapted from AWS’s samples: member accounts cannot leave the
organisation, stop or narrow audit and posture recording, disable detectors, or suppress findings (archive rules, filters,
trusted-IP lists, or setting a Security Hub CSPM finding to SUPPRESSED), and only the deployer can alter the two exempt
roles.[34][59] IAMOps
teaches how such policies are written; its example protects the trail and access keys, while this one covers posture, detection
and the break-glass path.
Example status: JSON syntax-checked by the validator; not executed (requires an AWS organisation). Action names and the Security Hub condition key checked against AWS’s machine-readable service reference on 2026-10-17.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyLeaveOrganization",
"Effect": "Deny",
"Action": "organizations:LeaveOrganization",
"Resource": "*"
},
{
"Sid": "ProtectAuditAndPosture",
"Effect": "Deny",
"Action": [
"cloudtrail:DeleteTrail",
"cloudtrail:StopLogging",
"cloudtrail:UpdateTrail",
"cloudtrail:PutEventSelectors",
"config:StopConfigurationRecorder",
"config:DeleteConfigurationRecorder",
"config:PutConfigurationRecorder",
"config:DeleteDeliveryChannel",
"config:PutDeliveryChannel",
"securityhub:DisableSecurityHub",
"securityhub:BatchDisableStandards",
"securityhub:UpdateStandardsControl",
"securityhub:BatchUpdateStandardsControlAssociations",
"securityhub:DisassociateFromAdministratorAccount",
"securityhub:DisassociateFromMasterAccount",
"access-analyzer:DeleteAnalyzer",
"access-analyzer:CreateArchiveRule",
"access-analyzer:UpdateArchiveRule",
"access-analyzer:ApplyArchiveRule",
"access-analyzer:UpdateFindings"
],
"Resource": "*",
"Condition": {
"ArnNotLike": {
"aws:PrincipalARN": [
"arn:aws:iam::*:role/security-breakglass",
"arn:aws:iam::*:role/org-baseline-deployer"
]
}
}
},
{
"Sid": "DenyFindingSuppression",
"Effect": "Deny",
"Action": "securityhub:BatchUpdateFindings",
"Resource": "*",
"Condition": {
"StringEquals": {
"securityhub:ASFFSyntaxPath/Workflow.Status": "SUPPRESSED"
},
"ArnNotLike": {
"aws:PrincipalARN": [
"arn:aws:iam::*:role/security-breakglass",
"arn:aws:iam::*:role/org-baseline-deployer"
]
}
}
},
{
"Sid": "ProtectThreatDetection",
"Effect": "Deny",
"Action": [
"guardduty:DeleteDetector",
"guardduty:UpdateDetector",
"guardduty:DisassociateFromAdministratorAccount",
"guardduty:DisassociateFromMasterAccount",
"guardduty:ArchiveFindings",
"guardduty:CreateFilter",
"guardduty:UpdateFilter",
"guardduty:CreateIPSet",
"guardduty:UpdateIPSet",
"guardduty:CreateTrustedEntitySet",
"guardduty:UpdateTrustedEntitySet"
],
"Resource": "*",
"Condition": {
"ArnNotLike": {
"aws:PrincipalARN": [
"arn:aws:iam::*:role/security-breakglass",
"arn:aws:iam::*:role/org-baseline-deployer"
]
}
}
},
{
"Sid": "ProtectExemptRoles",
"Effect": "Deny",
"Action": [
"iam:CreateRole",
"iam:DeleteRole",
"iam:UpdateRole",
"iam:UpdateAssumeRolePolicy",
"iam:AttachRolePolicy",
"iam:DetachRolePolicy",
"iam:PutRolePolicy",
"iam:DeleteRolePolicy",
"iam:PutRolePermissionsBoundary",
"iam:DeleteRolePermissionsBoundary",
"iam:TagRole",
"iam:UntagRole"
],
"Resource": [
"arn:aws:iam::*:role/security-breakglass",
"arn:aws:iam::*:role/org-baseline-deployer"
],
"Condition": {
"ArnNotLike": {
"aws:PrincipalARN": "arn:aws:iam::*:role/org-baseline-deployer"
}
}
}
]
}
Preconditions and limits:
- Scope. It binds only member accounts, and not service-linked roles.[13] It does not cover Macie, Inspector, the EventBridge rules behind your detections, or the log archive’s key and bucket.
- Exempt roles. Each exemption matches a role name in any account, so both names are protected: create the roles while vending an account, before it joins a governed OU, and alert on every use.
- A second layer. Member accounts cannot change an organisation trail anyway,[40] so the CloudTrail actions protect account-level trails. Manage GuardDuty and Security Hub CSPM through Organizations, where only the administrator manages GuardDuty’s lists and central configuration stops centrally managed accounts from disabling standards or controls.[60][61]
- Finding suppression.
DenyFindingSuppressioncloses the scoring trap under Metrics: a member account “can update findings only for their own account”. AWS documents this deny as an IAM policy, so validate it as an SCP (Lab 2, step 1) before attaching.[59]
2. A resource control policy that requires TLS. A shortened version of AWS’s sample “Restrict access to only HTTPS connections to your resources” (the sample covers more services).[16] RCPs apply to a listed subset of services and not to resources in the management account.[14]
Example status: JSON syntax-checked; not executed.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EnforceSecureTransport",
"Effect": "Deny",
"Principal": "*",
"Action": ["s3:*", "sts:*", "kms:*", "sqs:*", "secretsmanager:*"],
"Resource": "*",
"Condition": {
"BoolIfExists": {
"aws:SecureTransport": "false"
}
}
}
]
}
3. The same intent on Google Cloud: prevent public Cloud Storage access across the organisation. When enforced, “no one can make data in applicable buckets public through IAM policies or ACLs”; existing public grants stay in place but are overridden.[62]
Example status: YAML syntax-checked; not executed. Replace the organisation ID.
name: organizations/123456789012/policies/storage.publicAccessPrevention
spec:
rules:
- enforce: true
Apply it with gcloud org-policies set-policy policy.yaml; the same command accepts a dry-run specification for testing
first.[21] On Azure, assign a deny policy for the same intent with enforcementMode set to DoNotEnforce, review
compliance, then switch to Default.[39]
4. Validate before you attach. IAM Access Analyzer validates SCPs and RCPs against grammar and best practice and returns
ERROR, SECURITY_WARNING, WARNING and SUGGESTION findings.[63] Make an empty ERROR and SECURITY_WARNING list a
pipeline gate.
Hands-on labs
Link to section “Hands-on labs”Lab 1 runs anywhere with Python and was executed. Labs 2 and 3 need an AWS organisation and were not executed; their expected outputs come from the cited documentation.
Lab 1 (beginner): find public storage exposure and expired exceptions
Link to section “Lab 1 (beginner): find public storage exposure and expired exceptions”Objective: learn how layered public-access settings combine, why a “fixed value” condition matters, and why exceptions need expiry dates. Prerequisites: Python 3.8 or later; no cloud account, cost or risk; 40 minutes.
The script is a teaching approximation of the Amazon S3 rules for what counts as “public”:[64] a statement that allows
Principal: "*" is public unless a listed condition key has a fixed value, and an aws:SourceIp range broader than /8 still counts
as public. It treats negated operators (StringNotEquals, NotIpAddress) as not narrowing, and ignores aws:userid, access
points and the ForAnyValue/ForAllValues set operators. Use IAM Access Analyzer or S3’s own policy status for real decisions.
- Save the three files below as
exposure_check.py,inventory.jsonandexceptions.json. - Run
python3 exposure_check.py inventory.json exceptions.json 2026-10-16, thenecho $?. - In
inventory.json, set the account’sIgnorePublicAclstofalseand run again. - Restore it, set
"org_bpa": {"enforced": true}and run again. Ask what happens tomarketing-site, which serves a website.
Example status: verified by execution (Python 3.8.10, 2026-10-16; re-run after the r1 change, 2026-10-17); outputs below are verbatim.
"""Teaching approximation of S3 public-exposure evaluation (not a replacement
for IAM Access Analyzer or S3's own policy-status check)."""
import ipaddress
import json
import sys
from datetime import date
FIXED_KEYS = { # condition keys that can make a policy non-public (AWS S3 docs)
"aws:principalorgid", "aws:sourceip", "aws:sourcearn", "aws:sourcevpc",
"aws:sourcevpce", "aws:sourceowner", "aws:sourceaccount",
"s3:dataaccesspointarn", "s3:dataaccesspointaccount",
}
BPA = ["BlockPublicAcls", "IgnorePublicAcls", "BlockPublicPolicy",
"RestrictPublicBuckets"]
PUBLIC_GROUPS = ("AllUsers", "AuthenticatedUsers")
def effective_bpa(org, account, bucket):
"""Most restrictive combination: a setting is on if any level turns it on."""
org_all = org.get("enforced", False) # org level is all-or-nothing
return {k: org_all or account.get(k, False) or bucket.get(k, False) for k in BPA}
def is_fixed(value):
values = value if isinstance(value, list) else [value]
return all(isinstance(v, str) and not any(c in v for c in "*?$") for v in values)
RFC1918 = [ipaddress.ip_network(n) for n in
("10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16")]
def too_broad(cidrs):
"""Broader than /8 (IPv4) or /32 (IPv6), RFC 1918 ranges excepted."""
cidrs = cidrs if isinstance(cidrs, list) else [cidrs]
for c in cidrs:
net = ipaddress.ip_network(c, strict=False)
if net.version == 4 and any(net.subnet_of(p) for p in RFC1918):
continue
if net.prefixlen < (8 if net.version == 4 else 32):
return True
return False
def statement_is_public(stmt):
if stmt.get("Effect") != "Allow":
return False
principal = stmt.get("Principal")
if isinstance(principal, dict):
principal = principal.get("AWS")
principals = principal if isinstance(principal, list) else [principal]
if "*" not in principals:
return False
for op_name, operator in stmt.get("Condition", {}).items():
if "Not" in op_name: # negated operators never narrow a grant
continue
for key, value in operator.items():
if key.lower() not in FIXED_KEYS or not is_fixed(value):
continue
if key.lower() == "aws:sourceip" and too_broad(value):
continue
return False # one fixed-value key narrows the grant
return True
def assess(bucket, org, account):
bpa = effective_bpa(org, account, bucket.get("bpa", {}))
stmts = bucket.get("policy", {}).get("Statement", [])
policy_public = any(statement_is_public(s) for s in stmts)
acl_public = any(g in PUBLIC_GROUPS for g in bucket.get("acl_grantees", []))
exposed = []
if policy_public and not bpa["RestrictPublicBuckets"]:
exposed.append("bucket policy")
if acl_public and not bpa["IgnorePublicAcls"]:
exposed.append("ACL")
return exposed, bpa
def main(inventory_path, exceptions_path, today):
inv = json.load(open(inventory_path))
exceptions = {e["bucket"]: e for e in json.load(open(exceptions_path))}
failures = 0
for b in inv["buckets"]:
exposed, _ = assess(b, inv.get("org_bpa", {}), inv.get("account_bpa", {}))
exc = exceptions.get(b["name"])
if not exposed:
status = "OK"
elif exc and date.fromisoformat(exc["expires"]) >= today:
status = f"PUBLIC, excepted to {exc['expires']} ({exc['owner']})"
elif exc:
status = f"PUBLIC, exception EXPIRED {exc['expires']}"
failures += 1
else:
status = "PUBLIC, no exception"
failures += 1
via = f" via {', '.join(exposed)}" if exposed else ""
print(f"{b['name']:<18} {status}{via}")
print(f"summary: {len(inv['buckets'])} buckets, {failures} need action")
return 1 if failures else 0
if __name__ == "__main__":
as_of = date.fromisoformat(sys.argv[3]) if len(sys.argv) > 3 else date.today()
sys.exit(main(sys.argv[1], sys.argv[2], as_of))
{
"org_bpa": {"enforced": false},
"account_bpa": {"BlockPublicAcls": true, "IgnorePublicAcls": true},
"buckets": [
{"name": "app-logs-prod",
"policy": {"Statement": [{"Effect": "Allow",
"Principal": {"Service": "logging.s3.amazonaws.com"},
"Action": "s3:PutObject", "Resource": "*"}]}},
{"name": "partner-drop",
"policy": {"Statement": [{"Effect": "Allow", "Principal": "*",
"Action": "s3:GetObject", "Resource": "*",
"Condition": {"StringEquals": {"aws:PrincipalOrgID": "o-exampleorg1"}}}]}},
{"name": "marketing-site",
"policy": {"Statement": [{"Effect": "Allow", "Principal": "*",
"Action": "s3:GetObject", "Resource": "*"}]}},
{"name": "legacy-exports",
"acl_grantees": ["AllUsers"],
"policy": {"Statement": [{"Effect": "Allow", "Principal": {"AWS": "*"},
"Action": "s3:GetObject", "Resource": "*",
"Condition": {"IpAddress": {"aws:SourceIp": "0.0.0.0/1"}}}]}},
{"name": "data-science-tmp",
"bpa": {"RestrictPublicBuckets": true},
"policy": {"Statement": [{"Effect": "Allow", "Principal": "*",
"Action": "s3:GetObject", "Resource": "*"}]}}
]
}
[
{"bucket": "marketing-site", "owner": "web-team", "reason": "static site",
"expires": "2026-12-31"},
{"bucket": "legacy-exports", "owner": "finance-it", "reason": "vendor migration",
"expires": "2026-09-30"}
]
Expected output (step 2), exit code 1:
app-logs-prod OK
partner-drop OK
marketing-site PUBLIC, excepted to 2026-12-31 (web-team) via bucket policy
legacy-exports PUBLIC, exception EXPIRED 2026-09-30 via bucket policy
data-science-tmp OK
summary: 5 buckets, 1 need action
Validation. Step 3 changes one line to legacy-exports PUBLIC, exception EXPIRED 2026-09-30 via bucket policy, ACL
(exit code 1): with IgnorePublicAcls off, the public ACL counts again. Step 4 prints OK for all five buckets and
summary: 5 buckets, 0 need action (exit code 0), because the organisation level applies all four settings together.[64]
What to notice: partner-drop is not public because its condition uses a fixed aws:PrincipalOrgID; legacy-exports is
public because 0.0.0.0/1 is broader than /8; data-science-tmp relies on a bucket setting that its editors could remove. In
step 4 the website stops serving the public, the trade-off examined in
A judgement call.
Troubleshooting: JSONDecodeError usually means a trailing comma; AttributeError: … subnet_of means Python older than 3.7.
Teardown: delete the three files.
Lab 2 (intermediate): stage two guardrails in a test OU (AWS)
Link to section “Lab 2 (intermediate): stage two guardrails in a test OU (AWS)”Objective: release the reference SCP and RCP to one test OU and prove they work.[65] Prerequisites:
- an AWS organisation with all features;
- a pipeline role limited to Organizations policy actions, or a member account made a delegated administrator for policies, not management-account administrator credentials;[66]
- a test OU with one sandbox account holding a test role, an account-level trail named
sandbox-trailand a bucket with one throw-away object.
Cost and risk: negligible cost; a wrong attachment can lock users out, so attach only to the test OU.[13] Time: 60 minutes.
Example status: syntax-checked; not executed (no AWS organisation available). IDs such as r-exam and ou-exam-test1234 are
placeholders.
# 1. Validate both policies (expect no ERROR or SECURITY_WARNING findings).
aws accessanalyzer validate-policy --policy-type SERVICE_CONTROL_POLICY \
--policy-document file://scp-protect.json
aws accessanalyzer validate-policy --policy-type RESOURCE_CONTROL_POLICY \
--policy-document file://rcp-tls.json
# 2. Enable RCPs once for the organisation root.
aws organizations enable-policy-type --root-id r-exam \
--policy-type RESOURCE_CONTROL_POLICY
# 3. Create the policies and attach them to the test OU only.
SCP_ID=$(aws organizations create-policy --type SERVICE_CONTROL_POLICY \
--name protect-security-telemetry --description "Lab 2 SCP" \
--content file://scp-protect.json --query Policy.PolicySummary.Id --output text)
RCP_ID=$(aws organizations create-policy --type RESOURCE_CONTROL_POLICY \
--name require-tls --description "Lab 2 RCP" \
--content file://rcp-tls.json --query Policy.PolicySummary.Id --output text)
aws organizations attach-policy --policy-id "$SCP_ID" --target-id ou-exam-test1234
aws organizations attach-policy --policy-id "$RCP_ID" --target-id ou-exam-test1234
# 4. From the sandbox account's test role: both calls should be denied.
# The second sends a signed request over plain HTTP on purpose; use the
# bucket's own Region in the endpoint URL.
aws cloudtrail stop-logging --name sandbox-trail
aws s3api get-object --bucket example-lab-bucket --key test.txt out.txt \
--endpoint-url http://s3.eu-west-1.amazonaws.com
# 5. Confirm the trail is still logging and HTTPS access still works.
aws cloudtrail get-trail-status --name sandbox-trail --query IsLogging
aws s3api get-object --bucket example-lab-bucket --key test.txt out.txt
Expected output: step 1 returns an empty or suggestion-only findings list; step 4 returns two access-denied errors (the first
should name an explicit deny in a service control policy); step 5 prints true and downloads the object. Validation: the denied
calls appear in the sandbox account’s event history with an access-denied error code. Troubleshooting: if step 4 succeeds,
check that the account really sits in the test OU and that the role has neither exempt name; if step 3 fails with a
policy-type error, step 2 has not completed. Teardown: aws organizations detach-policy for both IDs, then
aws organizations delete-policy; disable the RCP type if nothing else uses it.
Lab 3 (advanced): detect logging tampering and test the alert
Link to section “Lab 3 (advanced): detect logging tampering and test the alert”Objective: alert within minutes when anyone stops or changes a trail, and measure the time to alert. Prerequisites: a
sandbox account with an active trail, permission to manage EventBridge and SNS, and a way to run cloudtrail stop-logging there
(the break-glass role, or detach the Lab 2 SCP first). Cost: negligible. Time: 45 minutes.
To receive these events in EventBridge “you must enable a CloudTrail trail with logging”; they reach the account’s default event
bus, and rules in the default ENABLED state match write management events.[67] ATT&CK v20 files this behaviour as T1685.002,
Disable or Modify Cloud Log.[11]
Example status: JSON syntax-checked; not executed.
{
"source": ["aws.cloudtrail"],
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"eventSource": ["cloudtrail.amazonaws.com"],
"eventName": ["StopLogging", "DeleteTrail", "UpdateTrail", "PutEventSelectors"]
}
}
Save the pattern above as pattern.json and the topic policy below as topic-policy.json, with your Region and account ID. AWS
documents this EventBridge statement without a condition, so keep the topic for this rule alone.[68]
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublishEventsToMyTopic",
"Effect": "Allow",
"Principal": {"Service": "events.amazonaws.com"},
"Action": "sns:Publish",
"Resource": "arn:aws:sns:eu-west-1:111122223333:cloud-log-tamper"
}
]
}
TOPIC_ARN=$(aws sns create-topic --name cloud-log-tamper --query TopicArn --output text)
aws sns set-topic-attributes --topic-arn "$TOPIC_ARN" --attribute-name Policy \
--attribute-value file://topic-policy.json
aws sns subscribe --topic-arn "$TOPIC_ARN" --protocol email \
--notification-endpoint secops-oncall@example.com
aws events put-rule --name cloud-log-tamper --event-pattern file://pattern.json
aws events put-targets --rule cloud-log-tamper --targets "Id=sns,Arn=$TOPIC_ARN"
# Game day: note the time, stop logging, wait for the e-mail, restart logging.
date -u +%H:%M:%S
aws cloudtrail stop-logging --name sandbox-trail
aws cloudtrail start-logging --name sandbox-trail
Expected output: an SNS e-mail containing "eventName": "StopLogging" and the caller’s ARN. Validation: record the minutes
between the date output and the e-mail; get-trail-status shows IsLogging true after the restart. Troubleshooting: no
e-mail usually means an unconfirmed subscription, a missing topic policy, or a rule created in a different Region from the call.
The lesson: if the stopped trail were the account’s only trail, later calls might never reach EventBridge; the organisation
trail and GuardDuty, whose consumption your CloudTrail settings do not affect, cover that gap.[42] Teardown:
aws events remove-targets --rule cloud-log-tamper --ids sns, aws events delete-rule --name cloud-log-tamper,
aws sns delete-topic --topic-arn "$TOPIC_ARN".
Use cases and scenarios
Link to section “Use cases and scenarios”For the sourced cases, the lessons drawn are this page’s mapping, not the investigators’ findings.
| Scenario | Context | CloudSecOps response | Success measure |
|---|---|---|---|
| 1. Over-permissioned role (sourced) | Capital One, 2019: “The intrusion occurred through a misconfigured web application firewall that enabled access to the data” (DOJ).[69] Krebs reported request forgery against the metadata service and a role “assigned too many permissions”.[70] | IMDSv2 by default through an EC2 declarative policy;[29] roles scoped to named buckets; data events on sensitive buckets[25] | Instances requiring IMDSv2; sensitive buckets logged |
| 2. Valid stolen credentials (sourced) | Snowflake customers, 2024: no MFA, credentials “had not been rotated or updated”, no network allow lists.[5] A SaaS platform, but the failure, identity at the tenant API, transfers to any provider (IdentityOps teaches the case as its Case 3) | MFA and federation for people; long-lived keys replaced; access from trusted networks only; alerts on abnormal access | Long-lived credentials trending to zero |
| 3. Missing logs (sourced) | Exchange Online, 2023: the detecting agency relied on a premium-licence log (SOC Ops teaches the detection); the CSRB asked for default logs “without additional charges, with a minimum default retention of six months”.[6] | Inventory default logs per provider and licence; enable what investigations need before an incident | Logging coverage matches the written standard |
| 4. A 40-account scale-up turns on CSPM (illustrative) | Thousands of findings on day one; teams ignore the dashboard | Exposure findings first; organisation-level blocks where no legitimate use exists; owners and SLAs for the rest | Critical dwell time on target within a quarter |
Measure, govern, pay
Link to section “Measure, govern, pay”Metrics and KPIs
Link to section “Metrics and KPIs”| KPI | Definition and formula | Data source | Pitfall | Cadence |
|---|---|---|---|---|
| Guardrail coverage | Accounts under the current guardrail set ÷ active accounts | Organisation policy attachments | Management account always excluded; report it separately | Monthly |
| Logging coverage | (Account, enabled Region) pairs whose control-plane events reach the organisation archive ÷ all pairs | Trail and export status | Opt-in Regions enabled later are missed | Weekly |
| Detection coverage | Pairs with threat detection on ÷ all pairs | Detector status | Detectors off in newly enabled Regions | Weekly |
| Critical exposure dwell time | Median of (closed − first seen) for public-exposure and admin-credential findings | Posture tool timestamps | Counts closed findings only, so leaving the hardest open improves it; closure by suppression | Weekly |
| Open critical finding age | p50 and p90 of (now − first seen) for open critical findings | Posture tool | Report it beside dwell time, never instead | Weekly |
| Exception debt | Open exceptions past expiry ÷ open exceptions | Exception register | Silent renewals; count renewals too | Weekly |
| Long-lived credentials | Active user access keys + service-account keys | IAM reports, Access Analyzer | Counting keys, not their privilege | Monthly |
| Detection test pass rate | Control-plane tests that alerted within target ÷ tests run | Game-day log | Testing only easy detections | Quarterly |
| Tool control pass rate | Passed ÷ (passed + failed + unknown) controls | Posture tool | Suppressing failed findings raises it | Monthly, as context only |
The last row is a trap. AWS defines its security score as “the proportion of Passed controls to enabled controls” and warns that “if you suppress all failed findings for a control, its status becomes Passed”.[71] A score is a lagging, gameable view of an automated subset; dwell time, open-finding age and exception debt show whether the operating model works.
Quality, security, privacy and compliance
Link to section “Quality, security, privacy and compliance”The main quality risk is self-inflicted: a deny at the wrong level locks out a team or a pipeline, which is why AWS “strongly recommends” testing SCPs before attaching them to the root.[13] Regulation is jurisdictional: BOD 25-01 binds only US federal civilian agencies.[9] Audit logs contain personal data such as user names and IP addresses, so set their retention with PrivacyOps and their evidence use with ComplianceOps. Accepting a residual risk is its owner’s decision (RiskOps), not the finder’s. This page is not legal advice.
Cost, capacity and sustainability
Link to section “Cost, capacity and sustainability”Logging and posture costs shape design (as of October 2026):
- CloudTrail delivers one copy of management events without a CloudTrail charge (storage is billed); scope the extra-cost data events to sensitive data stores.[23][25]
- Azure charges no ingestion for activity logs in Log Analytics, only retention beyond 90 days.[12] Google leaves Data Access logs off “because they can generate large volumes of data”.[24]
- Security Hub CSPM charges per check and finding after a 30-day trial; Access Analyzer charges for unused and internal access analysis; Defender’s foundational CSPM and SCC Standard cost nothing extra.[41][22][17][54]
Price logging by the investigations it enables: a missing log cannot be bought during an incident. Cost allocation belongs to FinOps.
Assurance of the operating model
Link to section “Assurance of the operating model”Assure the guardrails themselves: run the Lab 3 game day quarterly for each critical detection; diff attached organisation policies against Git weekly; enable a new benchmark version before disabling the old one, as AWS advises.[49] Risk indicators: denials that teams work around by moving accounts between OUs, exceptions renewed rather than closed, findings closed without a rescan, detectors off in newly enabled Regions, and growing counts of long-lived keys.
When things go wrong
Link to section “When things go wrong”Common failures and troubleshooting
Link to section “Common failures and troubleshooting”| Symptom | Likely cause | Diagnosis | Remediation | Prevention |
|---|---|---|---|---|
| A team is locked out after a policy change | Deny attached too high, missing exception | Access-denied events naming a service control policy | Detach or narrow; add exception | Staged rollout by OU |
| Dashboard green, auditor finds gaps | Tool covers an older benchmark or only automated checks | Compare tool version with CIS list[49] | Add manual checks | Record benchmark version |
| Findings never close | No owner, or fix made in console and reverted by IaC | Finding reopens after deploy | Fix in code | Route by owner tag |
| Alert expected, none arrived | Trail stopped, rule in wrong Region, detector off in that Region | Trail status, rule Region, detector list | Restore; extend coverage | Logging-coverage KPI |
| A public bucket reappears | Bucket-level block removed by someone with bucket rights[64] | Event history for the setting change | Account or organisation block | Organisation-level block |
| Investigation lacks data | Data events or Data Access logs never enabled | Logging standard vs reality | Enable now; accept the historical gap | Logging standard reviewed with responders |
Worked runbook: logging stopped and an unknown access key is active
Link to section “Worked runbook: logging stopped and an unknown access key is active”Trigger: the Lab 3 rule reports StopLogging on a production account trail, and threat detection reports API calls from an
access key in a country where the team does not work. Severity: high until scoped. Incident command follows
IncidentOps; evidence and eradication depth follow ResponseOps.
Diagram source (Mermaid)
sequenceDiagram participant S as SOC lead participant E as On-call engineer participant P as Cloud APIs and log archive Note over E: Alert: StopLogging and odd key use E->>P: Query activity since key creation P-->>E: Calls and resources touched E->>S: Declare incident with scope E->>P: Disable key, deny user, revoke sessions P-->>E: Confirmed E->>P: Remove persistence, restart logging E->>S: Hand over evidence and timeline
Text equivalent: On the alert, the on-call engineer queries the log archive for the key’s activity since it was created, gets back the calls and resources touched, and declares a scoped incident to the SOC lead. Through the cloud APIs the engineer disables the key, denies all actions to the user and revokes role sessions (confirmed), removes persistence, restarts logging, and hands evidence and a timeline to the SOC lead.
- Confirm and preserve. Check that the organisation trail is still logging (member accounts cannot stop it).[40] Do not delete anything; snapshot evidence before changing resources.
- Scope. In the log archive, list every call made with the access key ID, every role it assumed, and every
GetSessionTokenorGetFederationTokencall: those return temporary keys (IDs startingASIA) that keep working after the long-term key is disabled, so follow their key IDs too.[72] Note created users, keys, roles, trust-policy changes and data reads. - Contain. Deactivate the key (
aws iam update-access-key --user-name <user> --access-key-id <key-id> --status Inactive), then attach the AWS managed policyAWSDenyAllto the user. Temporary credentials “are valid until they expire” (up to 36 hours), and AWS says “you must also change permissions for the IAM user or role” to stop them; sessions the user created are evaluated against the user’s own policies, so the deny ends them. Root-user sessions cannot be stopped this way, one more reason for IAM.4.[73] For roles the key assumed, revoke sessions: AWS attaches a deny onaws:TokenIssueTime, which does not stop sessions assumed afterwards, so first remove the attacker’s ability to re-assume the role.[74] - Eradicate. Delete persistence found in step 2; check for new resources in Regions you do not use.
- Recover and verify. Restart the trail, confirm
IsLoggingistrue, rerun the posture scan, watch for the key ID for 30 days. - Learn. Why did a long-lived key exist, and why could its holder stop logging? Usually both lead to a guardrail (the reference SCP) and a credential-hygiene backlog item.
Anti-patterns and myths
Link to section “Anti-patterns and myths”- “The provider secures the cloud for us.” The provider secures its infrastructure; configurations, identities and data stay with you in every model.[18]
- Dashboard-driven security. Chasing a score invites suppression, which raises it.[71] Manage dwell time and exceptions.
- Deny everything at the root on day one. It locks out teams and produces exception sprawl; stage by OU.[34]
- Exempting a role name without protecting it. Anyone who can create a role with that name inherits the bypass.
- “Key rotation protects our data.” AWS states that rotation “has no effect on the data that the KMS key protects” and “will not mitigate the effect of a compromised data key”; KMS keys are mostly wrapping keys “almost never reused enough to risk key exhaustion”.[75] Rotate where rules require it, but spend effort on who can use the key.
- “GuardDuty keeps our logs.” It extracts fields “and then discards these logs”; investigations need your own archive.[42]
Deciding and adopting
Link to section “Deciding and adopting”When to use and when not to use
Link to section “When to use and when not to use”Use a deliberate CloudSecOps practice when several hold: more than a handful of accounts or subscriptions; production or regulated data in the cloud; many teams with API access; a security team that cannot review every change; auditors who expect continuous control evidence.
Do not build a separate function when the estate is one or two accounts run by one small team. For small organisations Microsoft’s guidance is to “Combine cloud platform engineering and security responsibilities into a single function”;[38] free native posture tiers and an organisation-wide log are enough to start. Do not buy a CNAPP first if nobody owns findings: it will produce a backlog without a workflow. Hidden responsibilities: maintaining exceptions, benchmark upgrades, detector coverage in new Regions, and the on-call rota for control-plane alerts.
Decision framework
Link to section “Decision framework”Most decisions in CloudSecOps are about where a control should live. The tree below is this Atlas’s proposal.
Diagram source (Mermaid)
flowchart TB
Q1{"Could this action cause severe harm in any account?"}
Q1 -->|"no"| D1["Detective check, routed to owner"]
Q1 -->|"yes"| Q2{"Any legitimate use in some accounts?"}
Q2 -->|"yes"| Q3{"Can those accounts sit in their own OU?"}
Q2 -->|"no"| P1["Preventive at organisation root, staged"]
Q3 -->|"yes"| P2["Preventive on other OUs; detective there"]
Q3 -->|"no"| Q4{"Can a condition express the exception?"}
Q4 -->|"no"| D2["Detective with fast SLA and auto-alert"]
Q4 -->|"yes"| P3["Preventive with tested condition"]
D1 --> R["Review quarterly: promote or retire"]
D2 --> R
classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
class Q1,Q2,Q3,Q4 decision
class P1,P2,P3 core
class D1,D2,R neutral
Text equivalent: If the action cannot cause severe harm in any account, use a detective check routed to the owner. If it can and has no legitimate use, make it preventive at the organisation root, staged. If some accounts need it and can sit in their own OU, prevent it elsewhere and detect it there. Otherwise prevent with a tested policy condition if one can express the exception, or detect with a fast service-level target and automatic alerts. Detective controls are reviewed quarterly and promoted or retired.
Assumptions: preventive controls can be tested in a non-production OU, and the people a condition constrains cannot set it themselves; if a tag drives the exception, protect the tag or it becomes a bypass.
Maturity model
Link to section “Maturity model”This maturity model is this Atlas’s proposal, not an industry standard.
| Level | Observable behaviour | Exit criteria |
|---|---|---|
| 0 Ad hoc | Per-account defaults; findings seen only after incidents | Organisation-wide audit log and posture scan enabled |
| 1 Visible | Findings exist but few have owners | Every critical finding has an owner within a day |
| 2 Baselined | Written baseline, guardrails in audit mode or a test OU, exception register | Benchmark version recorded; exceptions all have expiry dates |
| 3 Enforced | Preventive guardrails by OU, logging and detection coverage complete | Coverage 100%; median critical dwell under target for a quarter |
| 4 Engineered | Guardrails as tested code; detections game-dayed; metrics change the baseline | Each critical detection passes its quarterly test |
Diagram source (Mermaid)
flowchart TB L0["0 Ad hoc"] -->|"turn on org logging and scans"| L1["1 Visible"] L1 -->|"owners and SLAs"| L2["2 Baselined"] L2 -->|"enforce by OU"| L3["3 Enforced"] L3 -->|"test guardrails and detections"| L4["4 Engineered"] L3 -.->|"exceptions renewed, not closed"| L2 L2 -.->|"triage stops, backlog grows"| L1 classDef core fill:#e8f3f2,stroke:#16756f,color:#122029 classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029 class L0,L1,L2,L3,L4 core
Text equivalent: The five levels of the table in order, each step labelled with its main action (organisation logging and scans, owners and SLAs, enforcement by OU, tested guardrails and detections). Two dotted arrows show regressions: level 3 falls back to 2 when exceptions are renewed rather than closed, and level 2 to 1 when triage stops and the backlog grows.
Adoption roadmap: 30/60/90 days
Link to section “Adoption roadmap: 30/60/90 days”| Window | Actions | Milestone | Metric |
|---|---|---|---|
| Days 1–30 | Organisation-wide logs into a locked archive; posture scans and threat detection in all enabled Regions; one benchmark version; long-lived key inventory | Level 1 | Logging and detection coverage measured |
| Days 31–60 | Owners and SLAs for critical findings; exception register with expiry; reference SCP and storage block in a test OU; Lab 3 detection live | Level 2 | Median critical dwell time measured |
| Days 61–90 | Enforce the first preventive guardrails OU by OU; quarterly scorecard to leadership; first game day | Start of level 3 | Guardrail coverage; exception debt |
Quick wins: storage blocks on OUs with no public buckets; no root access keys; threat detection in unused Regions. Dependency: an IaC pipeline for organisation policies (InfraOps).
Toolkit
Link to section “Toolkit”Checklists
Link to section “Checklists”Quick start
- Organisation-wide control-plane logging into an account workload admins cannot change
- Posture scanning and threat detection in every enabled Region
- One benchmark version chosen and recorded
- Critical-finding routing to owners, with a service-level target
Guardrail preflight
- Policy validated (no
ERRORorSECURITY_WARNINGfindings) - Exempt principals listed and protected; management account and service-linked roles noted as not covered
- Attached to a test OU for at least one week with access-denied events reviewed
- Rollback is a one-line detach in the pipeline
Logging readiness
- Data-plane logs enabled for sensitive data stores
- Identity-provider sign-in and directory logs exported beyond their default retention
- Retention set with privacy and compliance owners
- A test event found in the archive in under one hour
Quarterly review
- Each critical detection passed its game day
- Exceptions past expiry: zero
- Benchmark and tool versions re-checked
Templates
Link to section “Templates”Guardrail record (one per guardrail, kept next to the policy code):
id: GR-007
intent: Member accounts cannot disable, narrow or suppress audit, posture or detection
type: preventive (second layer)
mechanism: AWS SCP protect-security-telemetry (incl. DenyFindingSuppression)
preconditions: [GuardDuty and Security Hub CSPM managed via Organizations]
scope: all OUs except Sandbox (detective there)
not_covered: [management account, service-linked roles, Macie, Inspector, detection rules]
exempt_principals: [role/security-breakglass, role/org-baseline-deployer]
owner: cloud-security
test: Lab 3 game day, quarterly
exceptions: none
last_reviewed: 2026-10-16
Exception request:
Exception ID: EX-2026-031
Guardrail: GR-012 (no public object storage)
Resource / account: marketing-site / web-prod
Reason: Static website; CDN migration planned
Compensating control: Bucket holds public assets only; data events logged
Risk owner: Head of Web (accepts the residual risk)
Expires: 2026-12-31 (max 90 days; renewal needs a new review)
Quarterly scorecard: guardrail, logging and detection coverage, median and mean critical dwell time, open critical finding age, exception debt, long-lived credential count, detection test pass rate, benchmark version assessed, top three risks and decisions needed.
Deep comparisons
Link to section “Deep comparisons”| Approach | Strength | Weakness | Choose when |
|---|---|---|---|
| Native tools per provider | Free or cheap tiers; deep integration | Partial cross-provider coverage; attack paths in paid tiers | One or two main providers |
| Multicloud CNAPP | One workflow and risk model across providers | Licence cost; vendor consolidation risk | Three or more providers, small team |
| Open source (Prowler, Cloud Custodian) | Transparent checks; runs in your pipeline | You maintain and tune it | Strong engineering team; need for custom checks |
Is CloudSecOps a job title or a team? Both appear; the label is not standardised. What matters is that someone owns guardrails, posture, logging and cloud detections.
Do we need a CNAPP? Not to start: the free tiers and trial under Cost are enough to begin. Attack-path analysis no longer needs one: AWS Security Hub, the paid Defender CSPM plan and SCC Premium offer it.[57][17][54] A CNAPP earns its cost through one workflow across several providers.
Should every CIS check be enforced? No. Your baseline chooses among the recommendations and records exceptions.
Does SaaS belong here? It is a close neighbour: CISA’s BOD 25-01 sets baselines for Microsoft 365 tenants.[9] This page covers infrastructure and platform providers, but the guardrail-and-evidence pattern carries over.
What if the provider itself is compromised? You cannot prevent it, but your logs, keys you control and detections on your own tenancy are what let you see it. The CSRB report describes a customer whose own logs first revealed an intrusion that turned out to stem from a provider key compromise.[6]
Going further
Link to section “Going further”Advanced topics and emerging direction
Link to section “Advanced topics and emerging direction”- Data perimeters: combining SCPs, RCPs and network conditions so only trusted identities reach trusted resources.[16]
- Configuration that survives new APIs: AWS declarative policies are enforced “in the service’s control plane”, so the baseline holds “even when the service introduces new features or APIs”.[19]
- AI workloads: AI posture management in Defender for Cloud and an AI domain in the Microsoft benchmark v2 preview are early signs.[17][46]
- Provider logging norms: the CSRB asked cloud providers for default audit logs without extra charge, kept at least six months.[6] Microsoft raised Purview Audit (Standard) retention from 90 to 180 days for records from 17 October 2023;[76] this page found no cross-provider standard for the wider ask (as of October 2026).
- Shifting vocabulary: ATT&CK v20 moved cloud log tampering to T1685.002 under a “Defense Impairment” tactic;[11] update detection mappings that use the old ID.
Learning path
Link to section “Learning path”- Prerequisites: CloudOps for hierarchy and accounts; one provider’s IAM evaluation logic (IAMOps).
- One day: Lab 1; read your provider’s SCP or Azure Policy documentation and its audit-log defaults.
- One week: Labs 2 and 3 in a sandbox organisation; run Prowler with
--complianceagainst a test account and triage the output.[55][77] - 30 days: write a baseline mapped to one CIS benchmark, an exception process and the scorecard; run one game day.
- Specialise: cluster security (KubernetesSecOps), detections (DetectionOps), telemetry (SecDataOps) or response (ResponseOps).
- Portfolio: a public repository with tested guardrail policies, a logging standard and a game-day report.
Wrap-up
Link to section “Wrap-up”Executive recap and cheat sheet
Link to section “Executive recap and cheat sheet”| Topic | Remember |
|---|---|
| What it is | Security enforced, measured and investigated at the provider API |
| Decide | Which few actions to deny everywhere; which logs to keep and for how long; who owns findings |
| Practices | Staged guardrails, organisation-wide logging, owner-routed triage, expiring exceptions, game days |
| Metrics | Guardrail, logging and detection coverage; critical dwell time with open-finding age; exception debt; long-lived credentials |
| Watch-outs | Management account and service-linked roles sit outside SCPs and RCPs; tools lag benchmarks; scores can be gamed |
| Next action | Run Lab 1 on a real inventory export and count your expired exceptions |
A judgement call: block public storage across the organisation now, or fix first?
Link to section “A judgement call: block public storage across the organisation now, or fix first?”Situation (illustrative): an AWS estate of 60 accounts has 14 publicly readable buckets. Nine hold website assets; five are unexplained. The CISO asks for an organisation-level S3 block “today”.
Option A, enforce at the root now. Organisation-level S3 policies apply all four block settings together and override account settings.[52] Every unexplained exposure closes at once, but the nine website buckets stop serving too, and the pressure to restore them can produce exemptions by moving accounts out of the OU, weakening every guardrail for those accounts.
Option B, detect and fix first. Triage all 14 within days, move websites behind a CDN with private origins, then enforce. The estate stays exposed during the work, and “temporary” can become permanent.
Assumptions that decide it: whether the five unexplained buckets hold sensitive data (unknown until triaged), and whether OUs can be split so website accounts sit apart. A reasoned choice: close the five unexplained exposures now with account- or bucket-level blocks, enforce the organisation-level block today on every OU without a public bucket (Lab 1’s step 4 shows the effect), and give the website OU a dated plan to move behind a CDN, with a detective rule meanwhile. Option A looks safest, but breaking production on day one is how guardrails lose their sponsors. Uncertainty: if an unexplained bucket holds personal data, that account moves to Option A and to incident handling.
Learning objectives and mastery check
Link to section “Learning objectives and mastery check”You can now explain what CloudSecOps covers and where its label is unsettled; design a guardrail set with exceptions; operate logging, posture triage and control-plane detections; and evaluate posture metrics and tools critically.
- An SCP denies
cloudtrail:StopLogging, yet a trail was stopped. Name two ways this can happen.
Show answer for question 1
The call came from the management account, which SCPs do not affect, or from a principal matching the exemption (for example, a role created with the break-glass name in an account that does not protect it).[13] A service-linked role is also outside SCPs.
- Your posture score rose from 71% to 90% in a week with no deployments. What do you check first?
Show answer for question 2
Suppressions and archived findings. AWS notes that suppressing all failed findings for a control makes it “Passed”.[71] Also check whether a standard was disabled or a Region removed from aggregation.
- Why does
BlockPublicPolicyalone not close an existing public bucket?
Show answer for question 3
It rejects new public bucket policies but “doesn’t affect existing” ones. RestrictPublicBuckets limits access granted by an
existing public policy.[64] Lab 1’s data-science-tmp shows the effect.
- During an investigation you need object reads from six months ago on AWS and Google Cloud. What do you probably lack, and why?
Show answer for question 4
- A team revoked active sessions on a compromised role, yet the attacker is back an hour later. Why? And what else must you do when the stolen credential is an IAM user’s access key?
Show answer for question 5
Revocation denies sessions issued before the revocation time; a session assumed afterwards is not affected.[74] The attacker
still held whatever let them assume the role. Remove that source (a key, a trust-policy entry) first. For a user key, deactivation
leaves sessions from GetSessionToken or GetFederationToken valid until they expire, up to 36 hours; attach a deny-all policy
to the user as well.[73]
- Your tool reports full CIS compliance on AWS. What two caveats belong in the report?
Show answer for question 6
Conclusion
Link to section “Conclusion”CloudSecOps is a young name for an old problem in a new place. The name will keep shifting; trade press and a certification body already use it differently. The place will not: every cloud resource, permission and log setting passes through a provider API, and the cases that teach most (an over-permissioned role, valid stolen passwords, logs nobody switched on) were failures of configuration, identity and evidence at that layer. This page’s proposal is simple to state: enforce centrally a short list of things that must never happen, let owners fix everything else in code against a clock, and test guardrails and detections like applications. Start with logs you can trust; then make dangerous things impossible, one OU at a time.
Sources and further reading
Link to section “Sources and further reading”Claim-by-claim evidence: research/cloudsecops-ledger.md. Re-verify dated facts (versions, retention defaults, prices) quarterly or
when CIS, AWS, Microsoft or Google announce changes, and re-check neighbour anchors on each rebuild.
Changelog. 2026-10-16, r0: first version; Lab 1 executed, Labs 2–3 not executed. 2026-10-17, r1: revised after independent
review reviews/cloudsecops-r1.md (item-by-item response in reviews/cloudsecops-r1-response.md): TechTarget definition,
stolen-key containment, telemetry SCP, identity-log defaults, keys and misconfiguration sections, Security Hub split; Lab 1 re-run.
2026-10-17, r1.1: score follow-ups S1, S2, S5, S6 (reviews/cloudsecops-score-superseded-20261017T0519.md): the
DenyFindingSuppression statement, IdentityOps link, decision-tree title, re-check cadence. 2026-10-17, post-score polish
(reviews/cloudsecops-polish.md): worked artefacts labelled AWS-first; SCP action names and condition key re-checked against AWS’s
service reference; dense passages split into lists; decision tree narrowed; restatements trimmed.
SecOps vs. CloudSecOps: What does a CloudSecOps team do? — Dave Shackleford, TechTarget, 2022-07-14. Checked 2026-10-16. ↩︎ ↩︎ ↩︎
CloudSecOps: When SecOps Meets Cloud Security — Gilad David Maayan, Data Center Knowledge, 2022-02-16. Checked 2026-10-16. ↩︎ ↩︎
CCSP Certification Exam Outline — ISC2, page dated 2026-08-01. Checked 2026-10-16. ↩︎
Cloud Security Alliance Releases Top Threats to Cloud Computing 2024 Report — CSA, 2024-08-06. Checked 2026-10-16. ↩︎
UNC5537 Targets Snowflake Customer Instances for Data Theft and Extortion — Mandiant, Google Cloud blog, 2024-06-10. Checked 2026-10-16. ↩︎ ↩︎ ↩︎
Review of the Summer 2023 Microsoft Exchange Online Intrusion — Cyber Safety Review Board, report dated 2024-03-20. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
What is a Cloud Native Application Protection Platform (CNAPP)? — Josh Dreyfuss (Wiz), Cloud Security Alliance blog, 2021-10-25. Checked 2026-10-16. ↩︎
CISA and NSA Release Cybersecurity Information Sheets on Cloud Security Best Practices — CISA, 2024-03-07. Checked 2026-10-16. ↩︎ ↩︎
BOD 25-01: Implementing Secure Practices for Cloud Services — CISA, 2024-12-17. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
Google Completes $32 Billion Acquisition of Wiz — Cleary Gottlieb, 2026-03-11. Checked 2026-10-16. ↩︎ ↩︎
Disable or Modify Tools: Disable or Modify Cloud Log, T1685.002 — MITRE ATT&CK, modified 2026-05-12. Checked 2026-10-16. ↩︎ ↩︎ ↩︎
Activity Log in Azure Monitor — Microsoft Learn, updated 2026-10-15. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Service control policies (SCPs) — AWS Organizations. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Resource control policies (RCPs) — AWS Organizations. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
Use the Instance Metadata Service to access instance metadata — AWS. Checked 2026-10-16. ↩︎ ↩︎
Resource control policy examples and Data perimeter policy examples — AWS samples on GitHub. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
Microsoft Defender for Cloud Overview — Microsoft Learn, updated 2026-08-10. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Shared responsibility in the cloud — Microsoft Learn, updated 2026-08-24. Checked 2026-10-16. ↩︎ ↩︎
Declarative policies in AWS Organizations — AWS. Checked 2026-10-16. ↩︎ ↩︎
Azure Policy definitions effect basics — Microsoft Learn, updated 2025-12-01. Checked 2026-10-16. ↩︎ ↩︎ ↩︎
Creating and managing organization policies — Google Cloud; see also gcloud org-policies set-policy. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
Using AWS IAM Access Analyzer — AWS. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
What Is AWS CloudTrail? — AWS. Checked 2026-10-16. ↩︎ ↩︎
Cloud Audit Logs overview — Google Cloud, updated 2026-10-16. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Logging data events — AWS CloudTrail. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
AWS Management Console sign-in events — AWS CloudTrail. Checked 2026-10-17. ↩︎
Microsoft Entra data retention — Microsoft Learn, updated 2026-03-25. Checked 2026-10-17. ↩︎ ↩︎
Audit logs for Google Workspace — Google Cloud, updated 2026-10-16. Checked 2026-10-17. ↩︎
EC2 policies — AWS Organizations. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Managing secure-by-default organization resources — Google Cloud, updated 2026-10-13. Checked 2026-10-16. ↩︎
AWS KMS keys — AWS KMS Developer Guide. Checked 2026-10-17. ↩︎
Default key policy — AWS KMS Developer Guide. Checked 2026-10-17. ↩︎
Delete an AWS KMS key — AWS KMS Developer Guide. Checked 2026-10-17. ↩︎
Service control policy examples — AWS Organizations, with the linked sample repository. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Azure Key Vault soft-delete overview — Microsoft Learn, updated 2026-06-12. Checked 2026-10-17. ↩︎
Destroy and restore key versions — Google Cloud, updated 2026-10-13. Checked 2026-10-17. ↩︎
Logging AWS KMS API calls with AWS CloudTrail — AWS KMS Developer Guide. Checked 2026-10-17. ↩︎
Security Teams, Roles, and Functions — Microsoft Cloud Adoption Framework, updated 2026-10-01. Checked 2026-10-16. ↩︎ ↩︎
Details of the policy assignment structure — Microsoft Learn, updated 2026-09-18. Checked 2026-10-16. ↩︎ ↩︎
Creating a trail for an organization — AWS CloudTrail. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
Introduction to AWS Security Hub CSPM — AWS. Checked 2026-10-16. ↩︎ ↩︎ ↩︎
GuardDuty foundational data sources — AWS. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
CIS Amazon Web Services Benchmarks — Center for Internet Security. Checked 2026-10-16. ↩︎ ↩︎ ↩︎
CIS Microsoft Azure Benchmarks — Center for Internet Security. Checked 2026-10-16. ↩︎
CIS Google Cloud Computing Platform Benchmarks — Center for Internet Security. Checked 2026-10-16. ↩︎
Microsoft cloud security benchmark introduction — Microsoft Learn, updated 2026-02-03. Checked 2026-10-16. ↩︎ ↩︎
Cloud Controls Matrix — Cloud Security Alliance (version 4.1). Checked 2026-10-16. ↩︎
Cloud Matrix — MITRE ATT&CK, content v20. Checked 2026-10-16. ↩︎
CIS AWS Foundations Benchmark in Security Hub CSPM — AWS. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
Security Hub CSPM controls reference — AWS. Checked 2026-10-17. ↩︎
Centralize root access for member accounts — AWS IAM User Guide. Checked 2026-10-17. ↩︎
Amazon S3 policies — AWS Organizations. Checked 2026-10-16. ↩︎ ↩︎
Integrating Security Hub CSPM with Microsoft Azure — AWS. Checked 2026-10-17. ↩︎ ↩︎
Security Command Center service tiers — Google Cloud, updated 2026-10-15. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
prowler-cloud/prowler — Prowler, GitHub. Checked 2026-10-16. ↩︎ ↩︎
Cloud Custodian — CNCF. Checked 2026-10-16. ↩︎
What are Security Hub and Security Hub CSPM? and Introduction to AWS Security Hub — AWS. Checked 2026-10-17. ↩︎ ↩︎
Reporting in Prowler — Prowler documentation. Checked 2026-10-17. ↩︎
Using BatchUpdateFindings to update a finding and BatchUpdateFindings API — AWS Security Hub CSPM. Checked 2026-10-17. ↩︎ ↩︎
Working with trusted lists and threat lists — Amazon GuardDuty User Guide. Checked 2026-10-17. ↩︎
Understanding central configuration in Security Hub CSPM — AWS. Checked 2026-10-17. ↩︎
Public access prevention — Google Cloud. Checked 2026-10-16. ↩︎
aws accessanalyzer validate-policy — AWS CLI Command Reference. Checked 2026-10-16. ↩︎
Blocking public access to your Amazon S3 storage — AWS. Checked 2026-10-16. ↩︎ ↩︎ ↩︎ ↩︎
aws organizations create-policy — AWS CLI Command Reference. Checked 2026-10-16. ↩︎
Delegated administrator for AWS Organizations — AWS Organizations. Checked 2026-10-17. ↩︎
AWS service events delivered via AWS CloudTrail — Amazon EventBridge. Checked 2026-10-16. ↩︎
Using resource-based policies for Amazon EventBridge — Amazon EventBridge. Checked 2026-10-17. ↩︎
United States v. Paige Thompson — US Attorney’s Office, Western District of Washington, updated 2022-01-13. Checked 2026-10-16. ↩︎
What We Can Learn from the Capital One Hack — Brian Krebs, Krebs on Security, 2019-08-02. Checked 2026-10-16. ↩︎
Calculating security scores — AWS Security Hub CSPM. Checked 2026-10-16. ↩︎ ↩︎ ↩︎
IAM identifiers — AWS IAM User Guide. Checked 2026-10-17. ↩︎
Disabling permissions for temporary security credentials and Permissions for GetFederationToken — AWS IAM User Guide. Checked 2026-10-17. ↩︎ ↩︎
Revoke IAM role temporary security credentials — AWS. Checked 2026-10-16. ↩︎ ↩︎
Rotate AWS KMS keys — AWS. Checked 2026-10-16. ↩︎
Learn about auditing solutions in Microsoft Purview — Microsoft Learn, updated 2026-07-08. Checked 2026-10-17. ↩︎
Compliance — Prowler documentation. Checked 2026-10-16. ↩︎