Security AWS

Configure CrowdStrike Falcon Cloud Security CSPM and ECR Registry Assessment for AWS

A payments company runs 42 AWS accounts under one Organization, and the cloud security team has exactly the problem every multi-account shop hits eventually: they have agent coverage on EC2 from the CrowdStrike Falcon sensor, but no continuous picture of the configuration of the accounts themselves — the public S3 bucket someone spun up for a one-day test, the security group that quietly opened 0.0.0.0/0 to RDS, the IAM role with *:* that a contractor created and never removed. They also ship roughly 200 container images a week to Amazon ECR, and “is this image safe to deploy” is currently answered by a vibe. The mandate from the CISO is concrete: onboard every account into CrowdStrike Falcon Cloud Security for agentless posture management (CSPM), turn on behavioural Indicator of Attack (IOA) detection so a live attacker action — not just a static misconfiguration — pages the SOC, and make ECR registry scanning a gate in the build pipeline.

This guide is the step-by-step to do exactly that, repeatably, with CloudFormation and Terraform. It is an implementation guide, so the hands-on lab — a full Organization registration, a StackSet fan-out, an IOA smoke test, an ECR scan gate, and a wave-based rollout runbook — is the centerpiece. Around it sits everything you need to run the platform after day one: how the cross-account IAM reader role and external ID actually work, what the onboarding CloudFormation stack really creates in your accounts, how the policy framework layers CIS benchmarks and CrowdStrike’s own rules into IOM (Indicator of Misconfiguration) findings, how 1-click and guided remediation differ and when each is safe, how the attack path graph turns 4,000 findings into 12 that matter, and how agentless CSPM composes with the sensor-based Cloud Workload Protection (CWP) you already run.

The thing to internalise before you start: Falcon Cloud Security gives you three complementary lenses. Agentless CSPM reads your AWS control plane through a cross-account IAM role on a scan schedule and tells you what is misconfigured and what an attack path looks like. IOA detection consumes a CloudTrail-derived event stream over EventBridge in near-real-time and tells you what an attacker is doing right now — a root login from a new geography, a disabled GuardDuty detector, a sudden PutBucketPolicy that makes data public. Registry and snapshot assessment is the third lens, on your supply chain and unsensored hosts. You will wire all three, prove each one works with a deliberate test finding, and leave with a teardown path that removes every artefact cleanly.

What problem this solves

Multi-account AWS estates drift. Every account is a blast radius with its own IAM surface, its own network edges, and its own S3 buckets, and past about five accounts nobody can hold the posture in their head. AWS-native tooling covers pieces — Config rules for drift, GuardDuty for threat findings, Security Hub for aggregation — but teams that already standardised on Falcon for endpoint want one console, one severity language, one ticket pipeline for both “the sensor saw a reverse shell on EC2” and “this bucket went public an hour ago”. That single-pane requirement, not a gap in AWS tooling, is usually why Falcon Cloud Security lands on the roadmap.

What breaks without a CSPM layer is predictable, and it is worth being concrete because these are the findings the platform will surface in week one:

Failure mode you have today How it happens What it costs when it bites Which Falcon lens catches it
Public S3 bucket with customer data One-off test bucket, policy pasted from Stack Overflow Breach disclosure, regulator fines IOM (CSPM scan) + IOA (PutBucketPolicy event)
Security group open to 0.0.0.0/0 on 5432/3306 “Temporary” debug rule never removed Database credential stuffing, crypto-mining IOM (CSPM scan)
IAM role with AdministratorAccess + no boundary Contractor onboarding shortcut Full-account takeover from one leaked key IOM + attack path graph
CloudTrail stopped in one account Attacker’s first move post-compromise Blind forensics, undetected lateral movement IOA (behavioural, near-real-time)
Root user console login Break-glass creds reused casually Untraceable privileged change IOA
Vulnerable base image promoted to prod No scan gate between build and deploy Exploitable CVE in a payment path Registry assessment (ECR)
Unsensored EC2 with 2-year-old kernel Team that “doesn’t do agents” Unpatched remote-code-execution exposure Snapshot (agentless host) assessment
GuardDuty/Config disabled to “save cost” Well-meaning cost cleanup Native detection silently dark IOM + IOA (DeleteDetector event)

The second problem this guide solves is operational, not detective: onboarding 42 accounts by clicking through a console wizard 42 times is how you get 38 registered accounts, three half-registered ones, and one nobody remembers. Everything here is expressed as CloudFormation and Terraform so that account 43 — created next quarter by Control Tower — onboards itself with zero human action, and so that teardown is a terraform destroy, not an archaeology project.

The three lenses differ in mechanism, latency, and what they can see. Keep this table in your head for the whole article — every later design decision derives from it:

Lens Mechanism Latency What it sees What it cannot see
CSPM / IOM Falcon assumes a read-only IAM role, enumerates config via AWS APIs on a scan schedule Scan interval (hours) Misconfigurations, IAM relationships, exposure, compliance state Live process activity, events between scans
IOA (behavioural) Per-account, per-region EventBridge rules forward CloudTrail management events to a CrowdStrike event bus; a behavioural engine scores sequences Near-real-time (minutes) Attacker actions: logging tampering, privilege grants, exfil setup, anomalous logins Anything CloudTrail doesn’t log (data events unless enabled, in-instance activity)
Registry / snapshot assessment Falcon pulls ECR image layers (or CI pushes them to a scanner), and scans EBS snapshots of running hosts On push / scheduled OS + language-package CVEs, embedded secrets, malware in images and unsensored hosts Runtime behaviour, memory-only threats (that is the sensor’s job)

Learning objectives

By the end of this article you can:

Prerequisites & where this fits

You should be comfortable with AWS Organizations concepts (management account, OUs, trusted access, delegated administration), IAM cross-account trust policies, CloudFormation StackSets, and intermediate Terraform. On the CrowdStrike side you need console access and the right subscription; this article assumes the Falcon sensor story (endpoint/EKS) is already handled — if it is not, read Deploy CrowdStrike Falcon Sensor to Linux Fleets and Kubernetes via Helm DaemonSet first, because the CWP integration section below builds on it.

Concretely, have these in hand before the lab:

Prerequisite Specifics Why it blocks you without it
Falcon Cloud Security subscription The CSPM/cloud module licensed for your CID (Customer ID) Registration endpoints return 403 without the entitlement
Falcon console role Falcon Administrator or Cloud Security manager role on your user Needed to create API clients and view registration pages
Falcon API client Client ID + secret with CSPM registration: Read & Write and Falcon Container Image: Read & Write scopes Every API/Terraform step authenticates with it
Your Falcon cloud region us-1, us-2, eu-1, or us-gov-1 — check your console URL Tokens minted against the wrong regional API base fail
AWS Organizations management account access Ability to create StackSets with Org trusted access, or a delegated admin account Org-wide registration deploys from here
Org-wide CloudTrail An organization trail logging management events, IsLogging = true IOA detection has nothing to score without it
Terraform ≥ 1.6, AWS provider ≥ 5.40 Run from CI with sts:AssumeRole into the management account The lab is Terraform-first
Secrets store HashiCorp Vault (or AWS Secrets Manager) path for the API secret The client secret is shown once; it must never live in tfvars or git
SSO to the Falcon console Okta or Entra ID SAML federation with MFA Analyst access should be corporate identity, not local passwords

The Falcon cloud region deserves its own lookup because it is the number-one cause of “nothing works” on day one. Your tenant lives in exactly one, and every API call, scanner image path, and provider block must agree with it:

Falcon cloud API base URL Console URL Who is on it
us-1 api.crowdstrike.com falcon.crowdstrike.com Most US commercial tenants
us-2 api.us-2.crowdstrike.com falcon.us-2.crowdstrike.com Newer US commercial tenants
eu-1 api.eu-1.crowdstrike.com falcon.eu-1.crowdstrike.com EU tenants (data residency)
us-gov-1 api.laggar.gcw.crowdstrike.com falcon.laggar.gcw.crowdstrike.com US GovCloud tenants

Where this fits in the corpus: it is the AWS-side CSPM implementation in the multi-cloud security track. The org-plumbing it rides on is covered in Enforcing Org-Wide Guardrails with AWS Organizations, SCPs, and Delegated Administration and AWS Control Tower Guardrails: Building a Secure Multi-Account Foundation. The CloudTrail foundation IOA depends on is AWS CloudTrail and Config: Audit and Compliance at Scale. If your shop evaluates Wiz for the same job, Roll Out Wiz CSPM Across a Multi-Account AWS Organization with the AWS Connector is the direct parallel — the reader-role/external-ID pattern is nearly identical, which tells you it is the industry-standard shape for agentless CSPM.

Core concepts

Five mental models make every later step obvious.

Registration is an API object; the IAM role is its AWS-side half. When you “onboard an account”, you create a registration record in CrowdStrike’s backend (via console, API, or Terraform) keyed by your AWS account ID or Organization ID. That record generates two values: the IAM role name Falcon expects to find in your account and the external ID it will present when assuming it. Nothing works until both halves exist — a registration without the role shows the account as pending/inactive; a role without a registration is an orphan grant nobody uses. Every onboarding method (console wizard, API, Terraform) is just a different way of creating the record and then materialising the role.

The trust chain is: CrowdStrike’s AWS account → intermediate role → your reader role, locked by external ID. Falcon’s scanners run in CrowdStrike-owned AWS accounts. They first assume an intermediate role in CrowdStrike’s own environment, and that role is the principal your reader role trusts. Your role’s trust policy adds an sts:ExternalId condition carrying the per-registration external ID. This is the classic confused-deputy defence: even if an attacker convinces CrowdStrike’s infrastructure to assume roles on their behalf, they cannot name your role and your external ID together without your registration record. The external ID is not a secret in the cryptographic sense, but treat it like one — it is the only thing distinguishing your grant from anyone else’s.

IOM and IOA are different engines answering different questions. An Indicator of Misconfiguration is the output of the assessment engine: on each scan cycle, Falcon enumerates resources through the reader role, evaluates them against configuration policies (CIS controls plus CrowdStrike’s own rules), and emits findings with a severity and a remediation. An Indicator of Attack is the output of the behavioural engine: CloudTrail management events stream in through EventBridge, and the engine scores event sequences against attacker tradecraft — not “this bucket is public” but “this principal just disabled logging, created an access key, and attached an admin policy inside ten minutes”. IOMs tell you where the doors are unlocked; IOAs tell you the handle is turning. Teams that treat the platform as IOM-only buy half the product and none of the urgency.

Agentless and agent are complements, not substitutes. The reader role sees the control plane: what exists, how it is configured, who can reach what. The Falcon sensor (CWP) sees the data plane inside the host: processes, memory, network syscalls, container runtime behaviour. Snapshot scanning bridges the gap for hosts that cannot take a sensor — it reads EBS snapshots for vulnerable packages, but still cannot see live behaviour. The console unifies all of it per cloud asset, which is precisely the argument for running CSPM where your EDR already lives.

Everything you create in AWS is read-only and inert. The reader role carries AWS-managed SecurityAudit plus a small CrowdStrike supplement of Describe*/Get*/List* permissions; the EventBridge rules only forward events; the ECR grant only pulls layers. Falcon cannot mutate your environment through anything this guide deploys — remediation, when you enable it, is a separately-permissioned, deliberately-scoped add-on. You will verify the read-only claim empirically in the lab rather than trusting the vendor or this article.

Pin the vocabulary before the deep sections:

Term One-line definition Where it lives
CID Your CrowdStrike customer/tenant ID Falcon backend
Registration The record binding an AWS account/Org to your CID Falcon backend (API object)
Reader role Read-only IAM role Falcon assumes for assessment Every AWS account
Intermediate role CrowdStrike-side role that is the trusted principal CrowdStrike’s AWS account
External ID Per-registration sts:ExternalId condition value Trust policy + Falcon backend
IOM Indicator of Misconfiguration — a static posture finding Assessment engine
IOA Indicator of Attack — a behavioural detection from event streams Behavioural engine
Realtime visibility The IOA feature flag on a registration Registration record
Event bus (CrowdStrike) The EventBridge bus in CrowdStrike’s account your rules target CrowdStrike’s AWS account
CWP Cloud Workload Protection — the sensor-based runtime lens Your hosts/clusters
Image assessment CVE/secret/malware analysis of container images Falcon registry/CI scanning
Snapshot assessment Agentless vulnerability scan of EBS snapshots Your account + Falcon
Attack path Graph chaining findings from exposure to crown-jewel data Falcon console
Fusion workflow Falcon’s SOAR automation (triggers → conditions → actions) Falcon console

And keep the account-level data flows straight — three distinct pipes, three distinct AWS primitives:

Pipe AWS primitive on your side Direction Frequency Payload
Assessment (IOM) IAM reader role (sts:AssumeRole inbound) Falcon pulls Scan schedule (configurable, hours) AWS API read responses
Behavioural (IOA) EventBridge rule + IAM role for events:PutEvents You push Continuous (event-driven) CloudTrail management events
Registry assessment ECR pull permissions on the reader role (or CI push) Falcon pulls / CI pushes On schedule / on build Image manifests + layers

Account registration: the trust chain, the stack, and the StackSet

Registration is where most rollouts stall, so this section goes mechanism-by-mechanism. There are three ways to onboard, and they all converge on the same two artefacts — the registration record in Falcon and the reader role in AWS:

Method How it works Best for Repeatability Gotcha
Console quick-create (CloudFormation) Falcon console generates a pre-parameterised CloudFormation quick-create URL; you launch it in the management account; the stack creates roles + StackSets + EventBridge rules First account, proof-of-value, teams without IaC discipline Low — parameters live in a browser session The stack name and role names are CrowdStrike defaults; changing them later means re-registering
API (cloud-connect-cspm-aws) POST /cloud-connect-cspm-aws/entities/account/v1 creates the registration and returns the role name + external ID; you deploy the role yourself Scripted onboarding from existing automation (Lambda, Step Functions, account-vending pipelines) High You own the drift between record and role; deletion must be two-sided
Terraform (crowdstrike/crowdstrike provider) crowdstrike_cloud_aws_account resource creates the record; outputs feed an aws_cloudformation_stack_set in the same plan Production, multi-account, anything you intend to keep Highest — one plan shows both sides Provider needs FALCON_CLIENT_ID/FALCON_CLIENT_SECRET/FALCON_CLOUD env vars; state now contains the external ID (encrypt your backend)

Use the console flow once in a sandbox to see what it creates, then do production in Terraform. Never mix methods for the same account — a Terraform-managed registration that someone “fixes” in the console is drift you will chase for a week.

What the onboarding stack actually creates

Whichever method you choose, the AWS-side footprint is the same shape. Inventory it before you deploy it, because your security review will ask, and because knowing what should exist is how you spot a broken rollout later:

Artefact Scope Created by Purpose Mutating power
Reader IAM role (e.g. CrowdStrikeCSPMReader) Every account Stack / StackSet Assessment engine assumes it to enumerate config None — read-only
Reader role inline/supplement policy Every account Stack / StackSet Describe*/Get*/List* for services SecurityAudit misses (ECR pulls, Lambda config, EKS describe) None — read-only
EventBridge rules (per region in scope) Every account, each active region Stack / StackSet Match CloudTrail management events, forward to CrowdStrike’s bus Forward-only
EventBridge target IAM role Every account Stack / StackSet Grants events:PutEvents on the CrowdStrike event bus ARN only Forward-only
StackSet(s) + Org trusted access Management account Root stack Fan the above out to members; auto-enrol new accounts Deploys the above
(Optional) snapshot-scanning role/infra Accounts you enable it in Separate template Lets the scanner read EBS snapshots Read snapshots only

Two things are deliberately absent from that list: nothing writes to your resources, and nothing runs compute in your accounts for core CSPM/IOA (snapshot scanning is the exception you opt into). That absence is the security-review headline.

Anatomy of the reader role

The role is two policy attachments and one trust policy. The permissions half:

Attachment What it grants Why it is there
AWS managed arn:aws:iam::aws:policy/SecurityAudit Broad read-only across ~100 services: Describe*, List*, Get* on config metadata (not data) The baseline every CSPM vendor uses; AWS maintains it as services evolve
CrowdStrike supplement policy The deltas: ecr:GetDownloadUrlForLayer, ecr:BatchGetImage, eks:Describe*/ListClusters, lambda:GetFunction, backup:List*, and similar SecurityAudit deliberately excludes anything that could read content; Falcon needs a handful of these (notably ECR layer pulls for registry assessment)

Note the asymmetry: SecurityAudit cannot read your S3 objects, your secrets, or your snapshots — it reads configuration about resources. The supplement’s ecr:GetDownloadUrlForLayer/BatchGetImage is the one place the role touches content (image layers), and only because you want image scanning. If you do not license registry assessment, strip those statements.

The trust policy is where the security actually lives:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<CROWDSTRIKE_ACCOUNT_ID>:role/<INTERMEDIATE_ROLE_NAME>"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": { "sts:ExternalId": "<YOUR_REGISTRATION_EXTERNAL_ID>" }
      }
    }
  ]
}

Read it like an auditor:

Field Value What it defends against
Principal.AWS CrowdStrike’s intermediate role ARN (returned by your registration, not hand-typed) Any principal outside CrowdStrike’s scanner infrastructure
Action sts:AssumeRole only The role cannot be passed, federated, or used with web identity
Condition sts:ExternalId Your per-registration external ID Confused deputy: another CrowdStrike customer (or a hijacked internal path) naming your role ARN still fails the condition
(What’s absent) no aws:SourceIp, no MFA Deliberate: scanner fleet IPs churn; the external ID + principal pin is the contract

If your org standard demands more, you can add an aws:PrincipalOrgID-style condition only if CrowdStrike publishes one for their org — they do not, so resist inventing conditions that will silently break scanning after their infra rotates. The correct hardening dial is elsewhere: alert on AssumeRole calls against this role from unexpected principals via your own CloudTrail analytics.

Organization-wide registration with Terraform

Here is the production pattern end to end: register the Organization, then fan the role out via a SERVICE_MANAGED StackSet. The provider handles the Falcon side; the StackSet handles all member accounts and — critically — every future account.

terraform {
  required_providers {
    crowdstrike = { source = "crowdstrike/crowdstrike", version = "~> 0.4" }
    aws         = { source = "hashicorp/aws", version = "~> 5.40" }
  }
}

# Reads FALCON_CLIENT_ID / FALCON_CLIENT_SECRET / FALCON_CLOUD from env — never tfvars
provider "crowdstrike" {}
provider "aws" { region = "us-east-1" }   # management account credentials

# 1) The registration record: whole Org, assessment + behavioural IOA on
resource "crowdstrike_cloud_aws_account" "org" {
  account_id           = "111111111111"        # Organization MANAGEMENT account
  organization_id      = "o-abcd1234ef"
  is_organization_mgmt = true

  asset_inventory = { enabled = true }          # agentless CSPM (IOM) scanning
  realtime_visibility = {                       # behavioural IOA feed
    enabled           = true
    cloudtrail_region = "us-east-1"             # region your org trail's home is in
  }
  sensor_management = { enabled = false }       # sensors handled by our own pipeline
}

# 2) Falcon hands back the AWS-side contract as attributes
locals {
  role_name    = crowdstrike_cloud_aws_account.org.iam_role_name
  external_id  = crowdstrike_cloud_aws_account.org.external_id
  cs_role_arn  = crowdstrike_cloud_aws_account.org.intermediate_role_arn
  cs_bus_arn   = crowdstrike_cloud_aws_account.org.eventbus_arn
}

# 3) StackSet that lands the reader role + IOA forwarding in every member account
resource "aws_cloudformation_stack_set" "falcon" {
  name             = "crowdstrike-falcon-cloud-security"
  description      = "CrowdStrike FCS reader role + IOA EventBridge forwarding"
  permission_model = "SERVICE_MANAGED"          # Org trusted access, no per-account exec roles
  capabilities     = ["CAPABILITY_NAMED_IAM"]
  call_as          = "SELF"                     # or DELEGATED_ADMIN from a delegated account

  auto_deployment {
    enabled                          = true     # account 43 onboards itself
    retain_stacks_on_account_removal = false
  }

  operation_preferences {
    max_concurrent_percentage    = 25           # wave through the Org, don't carpet-bomb it
    failure_tolerance_percentage = 10
    region_concurrency_type      = "PARALLEL"
  }

  parameters = {
    ReaderRoleName    = local.role_name
    ExternalID        = local.external_id
    CSIntermediateArn = local.cs_role_arn
    CSEventBusArn     = local.cs_bus_arn
  }

  template_body = file("${path.module}/templates/falcon-member.yaml")
}

resource "aws_cloudformation_stack_set_instance" "members" {
  stack_set_name = aws_cloudformation_stack_set.falcon.name
  region         = "us-east-1"                  # IAM is global; one home region for the stacks
  deployment_targets {
    organizational_unit_ids = [
      "ou-abcd-workloads1",                      # prod + non-prod workload OUs
      "ou-abcd-platform22",
    ]
  }
}

# The management account is NOT covered by a service-managed StackSet — stack it directly
resource "aws_cloudformation_stack" "mgmt" {
  name         = "crowdstrike-falcon-cloud-security-mgmt"
  capabilities = ["CAPABILITY_NAMED_IAM"]
  parameters = {
    ReaderRoleName    = local.role_name
    ExternalID        = local.external_id
    CSIntermediateArn = local.cs_role_arn
    CSEventBusArn     = local.cs_bus_arn
  }
  template_body = file("${path.module}/templates/falcon-member.yaml")
}

The StackSet decisions that matter, since each is a fork you cannot cheaply reverse:

Decision Options Pick Why
Permission model SERVICE_MANAGED vs SELF_MANAGED SERVICE_MANAGED Uses Organizations trusted access; no AWSCloudFormationStackSetExecutionRole to pre-stage in 42 accounts; enables auto-deployment
call_as SELF (management) vs DELEGATED_ADMIN DELEGATED_ADMIN if you have a security-tooling account registered as delegated admin for CloudFormation Keeps humans and pipelines out of the management account
Auto-deployment on/off On, retain_stacks_on_account_removal = false New accounts get the role at creation; departing accounts get scrubbed
Targets Root vs specific OUs Specific OUs Excludes suspended/sandbox OUs you don’t license; targeting root also hits accounts mid-decommission
Concurrency max_concurrent_percentage, failure_tolerance_percentage 25% / 10% A bad template parameter fails fast on the first wave instead of wedging 42 accounts
Management account StackSet vs direct stack Direct aws_cloudformation_stack Service-managed StackSets skip the management account by design — forgetting this is the #1 “one account missing” cause

API onboarding (when Terraform is not in the loop)

Account-vending pipelines sometimes need to register an account the moment it is created, before any Terraform runs. The raw API is two calls — create the registration, read back the contract:

# OAuth2 token (client-credentials)
TOKEN=$(curl -s -X POST "https://api.${FALCON_CLOUD}.crowdstrike.com/oauth2/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id=${FALCON_CLIENT_ID}&client_secret=${FALCON_CLIENT_SECRET}" \
  | jq -r .access_token)

# Register one member account under the existing Org registration
curl -s -X POST "https://api.${FALCON_CLOUD}.crowdstrike.com/cloud-connect-cspm-aws/entities/account/v1" \
  -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
  -d '{"resources":[{"account_id":"222222222222","organization_id":"o-abcd1234ef","account_type":"commercial"}]}'

# Read the registration back — role name, external ID, provisioning status
curl -s "https://api.${FALCON_CLOUD}.crowdstrike.com/cloud-connect-cspm-aws/entities/account/v1?ids=222222222222" \
  -H "Authorization: Bearer ${TOKEN}" | jq '.resources[] | {account_id, iam_role_arn, external_id, status}'

The same via FalconPy (the official Python SDK), which is what you embed in a Lambda hooked to your account-creation event:

from falconpy import CSPMRegistration

falcon = CSPMRegistration(client_id=CID, client_secret=SECRET, base_url="us-1")

resp = falcon.create_aws_account(
    account_id="222222222222",
    organization_id="o-abcd1234ef",
    behavior_assessment_enabled=True,   # IOA
    sensor_management_enabled=False,
)
assert resp["status_code"] in (200, 201), resp["body"]["errors"]

Whichever path creates the record, the account shows Inactive/Pending in Cloud security → Settings → Account registration until the role exists and the first assessment succeeds — the StackSet’s auto-deployment usually closes that gap within minutes of account creation.

The policy framework: how findings get made

An IOM finding is the intersection of three things: a resource (enumerated through the reader role), a policy (a rule with a severity, mapped to one or more compliance frameworks), and an assessment run (the scan cycle that evaluated it). Understanding the policy layer is what separates teams that operate CSPM from teams that stare at a 4,000-finding wall.

Falcon ships policies in families. The ones that matter on AWS:

Policy family Source Coverage character Typical count/scope How you use it
CIS AWS Foundations Benchmark Center for Internet Security (v1.4/v2.0/v3.0 mappings) The auditable baseline: ~60 prescriptive controls on IAM, logging, monitoring, networking Identity, CloudTrail, Config, S3, VPC Compliance reporting; the floor every auditor recognises
CrowdStrike configuration policies CrowdStrike research Broader and more opinionated than CIS: per-service misconfiguration rules across S3, EC2, RDS, EKS, Lambda, KMS, ELB, and more Hundreds of rules across services Day-to-day IOM findings; the operational queue
Behavioural policies (IOA) CrowdStrike threat research Attacker tradecraft over CloudTrail event sequences Dozens of behaviour patterns SOC detections, not posture backlog
Framework mappings PCI DSS, NIST 800-53, SOC 2, HIPAA, ISO 27001, MITRE ATT&CK cloud matrix Same underlying rules, re-grouped per framework Reporting views Evidence packs; scoping which accounts need which framework
Custom policies You Org-specific rules (naming, mandated tags, banned regions) where supported As needed Encode house rules the vendors cannot know

Severity is the language everything downstream speaks — ticket priority, SLA, paging. Falcon grades IOMs and IOAs on the same scale, which is exactly why a unified queue works:

Severity What it means in practice Example IOM Example IOA Sane SLA
Critical Internet-reachable path to data or control plane, or active-attack indicator S3 bucket public + contains data classifiers CloudTrail logging disabled in prod Fix/contain same day
High Exploitable weakness needing one more step SG open to world on 22/3389; IAM user without MFA with console access Root user API activity 7 days
Medium Defence-in-depth gap EBS volumes unencrypted; RDS not multi-AZ backup-verified Unusual region activity for a principal 30 days
Informational Hygiene and context Untagged resources; idle credentials First-seen-service events Backlog / trend only

Reading and tuning IOM policies

A representative slice of what turns up in week one on a real estate — learn to read the policy → finding → fix chain:

Policy (IOM) Service Default severity What triggers it The fix it prescribes
S3 bucket is publicly accessible S3 Critical Bucket policy/ACL grants * read, and account/bucket Public Access Block off Enable Public Access Block; rewrite policy
Security group allows unrestricted ingress to admin port EC2/VPC High 0.0.0.0/0 or ::/0 on 22/3389 Restrict CIDR; prefer SSM Session Manager
IAM policy allows full administrative privileges IAM High Customer policy with "Action":"*","Resource":"*" attached Split to least privilege; add permission boundary
CloudTrail not enabled in all regions CloudTrail High No multi-region/org trail Create org trail (see the CloudTrail article)
RDS instance is publicly accessible RDS Critical PubliclyAccessible=true + subnet route to IGW Disable flag; move to private subnets
EBS volume not encrypted EC2 Medium Volume without KMS encryption Enable default EBS encryption per region
Access key not rotated in 90 days IAM Medium Active key age > 90d Rotate; move workload to roles
EKS cluster endpoint publicly accessible EKS High Public API endpoint without CIDR allowlist Private endpoint or tighten publicAccessCidrs

Tuning is where you keep the queue honest. Every knob, and the cost of misusing it:

Tuning action Where When it is right When it is a mistake
Disable a policy tenant-wide Cloud security → policies The rule genuinely doesn’t apply (e.g. a service you ban via SCP anyway) Disabling “noisy” rules that are noisy because the estate is actually bad
Override severity Per policy Your threat model genuinely differs (e.g. all data is public by design on a CDN bucket set) Downgrading Critical to make a dashboard green
Exclude resources (exemptions) Per finding/resource, with expiry Sanctioned exceptions with an owner and a review date Permanent exclusions with no owner — that is shadow risk acceptance
Scope policies per account group Registration/account groups Sandbox OUs held to a lighter bar than prod Scoping prod out of CIS to pass an audit
Custom policy Policy builder (where supported) House rules: mandatory data-classification tag, banned regions Re-implementing CIS badly

The discipline that makes this work: every exemption carries an owner tag and an expiry, reviewed monthly. Falcon lets you suppress; only your process makes suppression safe.

Behavioural IOAs: the near-real-time pipeline

IOA detection is a streaming pipeline, and you own the first half of it. When it is silent, you debug it hop by hop, so learn the hops now:

# Hop Owner What happens Failure mode to check
1 CloudTrail records a management event You API call in any member account lands in the org trail Trail not logging; management events excluded
2 Event surfaces on the account’s default EventBridge bus AWS CloudTrail management events are visible to EventBridge rules in the same region Region not covered by a rule
3 Falcon forwarding rule matches You (StackSet) Rule pattern detail-type: AWS API Call via CloudTrail (plus console sign-in events) matches Rule deleted/disabled by account owner
4 events:PutEvents to CrowdStrike’s bus You → CrowdStrike Target role posts the event cross-account to the bus ARN from your registration Target role trust/permission broken; wrong bus ARN
5 Behavioural engine scores sequences CrowdStrike Single events and multi-event sequences evaluated against IOA patterns Registration’s realtime visibility disabled
6 Detection raised, severity assigned CrowdStrike Appears in Cloud security detections; Fusion workflows fire Nobody subscribed — detection lands in an unwatched queue

Two design consequences fall out of that table. First, coverage is per region: the forwarding rule must exist in every region where API activity can occur, which is why the member template stamps rules into each enabled region rather than only your home region — an attacker who notices you only watch us-east-1 will happily create their access keys in ap-northeast-3. Second, IOA is downstream of CloudTrail health: aws cloudtrail get-trail-status belongs in the same monitoring tier as the detections themselves, because stopping the trail blinds hop 1 — which is precisely why “CloudTrail logging disabled” is itself a high-severity IOA. The event-bus mechanics (buses, rules, cross-account targets) are standard EventBridge — Designing Event-Driven Architectures with Amazon EventBridge: Buses, Rules, Schemas, and Archive/Replay covers the primitive itself in depth.

What the engine actually catches — representative behavioural IOAs and why each is high-signal:

Behavioural IOA (representative) Underlying events Why it is attacker-shaped
CloudTrail logging disabled or trail deleted StopLogging, DeleteTrail, PutEventSelectors (scoping down) Defence evasion is step one of competent intrusions
GuardDuty detector disabled DeleteDetector, UpdateDetector Same evasion class, native-tooling flavour
Root account activity Console sign-in / API calls as root Root has no business in daily ops; break-glass only
Console login without MFA / from anonymising infrastructure Sign-in events + context Credential-stuffing and token-theft tradecraft
IAM privilege escalation sequence CreateUserCreateAccessKeyAttachUserPolicy(AdministratorAccess) in a tight window The canonical persistence chain; single events look innocent, the sequence does not
Security group opened to the world on a sensitive port AuthorizeSecurityGroupIngress with 0.0.0.0/0 Exposure created now, not found at next scan
S3 bucket made public PutBucketPolicy / PutBucketAcl with public grants The IOA twin of the classic IOM — minutes, not hours
Unusual compute spin-up pattern Burst RunInstances in odd regions/instance types Cryptomining monetisation after credential theft

The IOM/IOA pairing is the operational punchline: the same public-bucket problem surfaces as an IOA within minutes (someone just did it) and as an IOM at the next scan (it is still true). Route the IOA to the SOC pager and the IOM to the backlog — same policy family, different consumers, and you configure that split in the triage section below.

Remediation: 1-click, guided, or automated — and when each is safe

Finding things is the easy half. Falcon offers a spectrum of remediation mechanics, and picking the wrong one for a resource class creates a different incident — usually IaC drift or a broken workload. The spectrum:

Mode Mechanism Speed Blast-radius control Where it is safe
Guided remediation The finding panel shows the exact fix: console path, aws CLI command, and the reasoning Human-paced Full — a person executes with change control Default for everything; the only mode for Terraform-managed resources (fix the module, not the resource)
1-click remediation A remediation action attached to the finding executes the fix through a scoped role/workflow you provisioned Seconds Per-action approval Click-ops estates; true emergencies (public bucket with regulated data) where drift is the lesser evil
Fusion workflow auto-remediation Trigger (detection/finding) → conditions → action (Lambda, webhook, native action) with no human in the loop Seconds, 24/7 Conditions + scoping only Narrow, rehearsed playbooks: quarantine-tag an instance, block a public-ACL bucket in a sandbox OU
IaC pull request Finding routed to the owning repo; fix lands as a Terraform/CloudFormation PR through CI Hours–days Full review + plan The correct steady-state for everything IaC-managed; pairs with pipeline scanning

The decision rule that keeps you out of trouble:

If the resource is… And the finding is… Then remediate via… Because…
Terraform/CloudFormation-managed Any severity IaC PR (guided remediation as the PR’s content) 1-click fixes get reverted by the next apply — or worse, half-reverted
Click-ops / unmanaged Critical, internet-exposed 1-click now, then import to IaC Minutes matter; drift is moot on unmanaged resources
Sandbox/dev OU Repeat offender classes (public buckets, open SGs) Fusion auto-remediation Low blast radius, high toil savings
Production data stores Anything touching policies/encryption Guided + change window An automated PutBucketPolicy “fix” that breaks a legitimate cross-account grant is a P1
Anything with an SCP already denying it The same control Fix the finding source (delete the resource) and rely on the SCP Two enforcement layers disagreeing is confusion, not defence

Note what 1-click requires that plain CSPM does not: a write-capable path into your account. That is a deliberate, separately-provisioned role or workflow target with a tightly scoped policy (e.g. only s3:PutBucketPublicAccessBlock, only in tagged accounts) — never a broadening of the reader role. If a security review finds write verbs on the reader role, someone wired remediation lazily; fail the review.

Attack paths: from 4,000 findings to the 12 that matter

A fresh 42-account onboarding will produce thousands of IOMs. Triaging them severity-first is better than nothing, but severity is a local property — it scores one resource in isolation. The attack path view (CrowdStrike’s graph analysis; the capability family the industry files under exposure management, and post the Bionic acquisition extended toward ASPM, application security posture management) scores combinations: it chains an internet-exposed entry point through IAM and network edges to a crown-jewel target, and only complete chains rank.

The graph’s building blocks:

Element Examples Contribution to a path
Entry node (exposure) Public ALB/EC2/API endpoint, public bucket, leaked-key-shaped IAM user Where the adversary starts
Pivot edge (identity) Instance profile → role, role trust → role, over-broad iam:PassRole, sts:AssumeRole grants How they become someone else
Pivot edge (network) SG/NACL reachability, peering, TGW routes, VPC endpoints Where they can move
Amplifier finding Missing MFA, unrotated key, unpatched CVE from snapshot/registry assessment What makes each hop cheap
Target node (crown jewel) RDS/DynamoDB with data classifiers, S3 with sensitive data, KMS keys, the management account What ends up in the ransom note

The operational play: sort by paths terminating at data, fix the choke-point edge (the one edge appearing in the most paths — often a single over-permissive role trust or one iam:PassRole wildcard), and watch dozens of paths collapse at once. In practice, week-one estates repeatedly show the same choke points: a CI/CD role assumable from too many places, an SSM automation role with PassRole *, and a legacy peering connection nobody remembered. Fixing three edges did more for the payments company in the scenario below than closing three hundred medium IOMs — that is the entire argument for graph-first triage, and it is also the honest counter to “we already have Config rules”: native tooling evaluates resources; the graph evaluates reachability.

Composing agentless CSPM with the sensor (CWP)

You already run the Falcon sensor on EC2 and EKS — that is Cloud Workload Protection: runtime process telemetry, exploit blocking, container drift detection. The composition question is what each layer contributes per asset class, because coverage gaps hide in the seams:

Asset class Agentless CSPM sees Sensor (CWP) sees Snapshot/registry assessment adds Residual gap
EC2 with sensor Its config: SGs, IAM profile, exposure, encryption Processes, memory, network behaviour, malware (Snapshot redundant)
EC2 without sensor Config only OS/package CVEs via EBS snapshot scan Live behaviour invisible — close it or accept it in writing
EKS nodes/pods Cluster config: endpoint exposure, RBAC-adjacent config, node IAM Container runtime behaviour via DaemonSet sensor Image CVEs via ECR assessment Admission control (separate policy layer)
Fargate tasks Task/service config Sensor as sidecar/patched runtime (see the EKS/Fargate article) Image CVEs Kernel-level visibility (by design on Fargate)
Lambda Function config: role, env, triggers, public URLs — (no sensor) Layer/package CVEs where licensed Runtime tracing
RDS/S3/managed data Full config posture n/a n/a Data-plane access patterns (CloudTrail data events, if enabled)

The console stitches these into one asset view: open an EC2 instance and you see its IOMs, its sensor detections, its CVEs, and the attack paths through it — one severity model, one timeline. Two integration behaviours worth configuring deliberately:

The anti-pattern to ban in design review: treating a green CSPM dashboard as runtime safety, or sensor coverage as posture. The lenses answer different questions; the value is the join.

Registry and snapshot assessment: the supply-chain lens

ECR: registry connection vs CI gate

There are two integration styles for image assessment, and mature pipelines run both, because they answer different questions — “what is in my registry” versus “should this build promote”:

Dimension Style A — registry connection Style B — inline CI scan
Mechanism Falcon inventories the ECR registry via IAM role (external-ID trust, ecr:GetAuthorizationToken/BatchGetImage/GetDownloadUrlForLayer) and assesses images on a schedule Your pipeline runs the falcon-image-analyzer container against the just-built image and uploads results
Latency Scheduled (catches images however they arrived) At build time (before promotion)
Can block a deploy No — detective Yes — exit code gates the job
Catches Everything in the registry: old images, hotfix pushes that bypassed CI, third-party images teams pulled in Only what flows through the pipeline
New-CVE re-evaluation Yes — tomorrow’s CVE against today’s inventory No — a build is scanned once
Cost profile Falcon-side licensing; negligible AWS (ECR egress within region) CI minutes + scanner image pull (cache it)
Failure mode Stale credentials/role → silent inventory gap Scanner outage blocks all builds — decide fail-open vs fail-closed in writing

Register the registry connection through Cloud security → Registry connections or the container-security API; the role it assumes can be the reader role (which already carries the ECR read statements) or a dedicated CrowdStrike-ECR-Read role if you want separately revocable supply-chain access — take the dedicated role in regulated estates. The CI style drops into any runner:

# GitHub Actions — scan-and-gate after build, before push/promote
- name: CrowdStrike image assessment gate
  env:
    FALCON_CLIENT_ID:     ${{ secrets.FALCON_CLIENT_ID }}
    FALCON_CLIENT_SECRET: ${{ secrets.FALCON_CLIENT_SECRET }}
  run: |
    docker run --rm \
      -v /var/run/docker.sock:/var/run/docker.sock \
      registry.crowdstrike.com/falcon-imageanalyzer/us-1/release/falcon-image-analyzer:latest \
      --client-id "$FALCON_CLIENT_ID" --client-secret "$FALCON_CLIENT_SECRET" \
      --cloud us-1 \
      --image "111111111111.dkr.ecr.us-east-1.amazonaws.com/payments-api:${GITHUB_SHA}"

What the gate actually evaluates is an image assessment policy you define in the console — the pipeline only enforces the verdict:

Policy criterion Typical production setting Rationale
CVE severity threshold Fail on Critical; fail on High with fix available “High with no vendor fix” blocks forever; track it, don’t block on it
Exploit status Fail on known-exploited regardless of severity score CVSS is not exploitability
Embedded secrets Fail, always A key baked into a layer is already leaked
Malware / packers Fail, always Non-negotiable
Base-image age / OS EOL Warn → fail after grace period Forces base-image hygiene without breaking Friday
Registry scope Per-repository or per-tag-pattern Hold prod-* repos to the strict policy, sandbox-* to warn-only

Pair the Falcon gate with ECR’s own hygiene — immutable tags, scan-on-push, lifecycle policies — which is a five-minute add via Terraform Module: AWS ECR Repository. And if your platform team also runs Wiz on the pipeline side, the gate-design trade-offs are the same shape: Integrate Wiz Code into GitHub Actions for IaC and Container Scanning Gates.

Snapshot assessment: the no-agent hosts

Some fleet will never take a sensor — appliance AMIs, vendor-managed instances, teams with change freezes. Snapshot assessment closes the vulnerability-visibility gap agentlessly:

Aspect How it works The catch
Acquisition EBS snapshots of in-scope instances are read and their filesystems analysed for installed-package inventories Needs snapshot-read/creation permissions beyond the base reader role — a separate opt-in template
Scope OS packages, language packages, some config files Point-in-time: it sees the disk, never memory or processes
Cadence Scheduled re-scans; new snapshots as instances change Snapshot churn has an AWS storage cost (see Cost & sizing)
Output CVEs per host, merged into the same asset view and attack paths as sensor-derived vulns Same CVE may appear from sensor and snapshot — the console de-duplicates per asset
When to use Unsensorable hosts, M&A due diligence on an unfamiliar estate, pre-sensor triage of a new Org It is a bridge, not a substitute — no runtime protection, only knowledge

Compliance dashboards and reporting

Compliance is the same findings re-projected: each framework view groups policy results into control families, scores them, and exports evidence. The operating model that works: pick one framework per audience — CIS for engineering (“is the floor solid”), PCI DSS scoped to the cardholder-data OUs for the auditor, MITRE mapping for the SOC (“which tactics are we blind to”) — and schedule exports rather than screenshotting dashboards:

Reporting need Mechanism Cadence
Auditor evidence pack Framework view → scheduled export (CSV/PDF) filtered to in-scope account group Quarterly, and frozen at audit kickoff
Engineering burn-down Findings API pull → your BI (severity × service × account trend) Weekly
Executive posture score Framework compliance % per BU account group Monthly
SOC coverage review MITRE-mapped detections vs tactics matrix Quarterly

Two habits keep the numbers honest. Scope frameworks to account groups — running PCI against your marketing sandbox produces noise that erodes trust in the real number. And track trend, not point-in-time: a 71% CIS score means nothing; 71% up from 44% in eight weeks is a programme working. If you also aggregate into AWS-native tooling for a second opinion, Security Hub’s standards engine covers similar ground — Terraform Module: AWS Security Hub stands it up in one block.

Findings triage → ticketing: making someone own every red row

A finding nobody owns is a dashboard decoration. The routing model that survives contact with production splits by lens and severity, not by tool:

Signal Route Consumer SLA clock
IOA, Critical/High Fusion workflow → ServiceNow security incident + SOC channel page SOC (24/7) Minutes — treat as live attack until triaged
IOA, Medium/Info ServiceNow queue, no page SOC next business day 1–3 days
IOM, Critical ServiceNow incident to the owning team (account tag → assignment group) Resource owner Same day
IOM, High ServiceNow change/task, batched daily Resource owner 7 days
IOM, Medium/Info Weekly digest + backlog import (Jira/ADO) Team backlog 30 days / grooming
Image gate failure The failed build itself + repo notification The committing developer Immediate — it is their red build
Attack path (new, terminating at data) Security architecture review, one ticket per choke-point edge Cloud security team 7 days

The ServiceNow mapping is configured once in the Falcon ServiceNow integration (or a Fusion workflow calling the ServiceNow API) and then argued about forever, so write it down:

Falcon field ServiceNow field Mapping rule
Severity Impact/Urgency → Priority Critical→P1, High→P2, Medium→P3, Info→P4
AWS account ID Assignment group Via your account-metadata table (account → team) — this lookup is the whole game
Resource ARN + region CI / affected item Direct
Policy ID + finding description Short description + work notes Include the guided-remediation text so the assignee never opens the console cold
Finding ID Correlation ID Dedupe: re-detections update, never re-create

The one non-negotiable: close the loop in Falcon. When ServiceNow resolves, the fix must show as the finding disappearing at next scan (IOM) or the detection being closed with a disposition (IOA). Tickets closed while findings persist means your assignment-group lookup is wrong or teams are closing without fixing — both are audit findings in the making. The broader governance pattern (CMDB-driven ownership, ServiceNow as the system of record across scanners) is the subject of Multi-Account AWS Governance: Tying Wiz, ServiceNow, and Control Tower Together — the same skeleton applies with Falcon as the emitter.

Architecture at a glance

Walk the diagram left to right as three flows converging on one Falcon tenant. The CSPM flow starts in CrowdStrike’s own AWS environment: the assessment engine assumes the intermediate role, then hops cross-account into the read-only reader role stamped into every one of your accounts by the StackSet, presenting your registration’s external ID; it enumerates configuration and feeds the IOM/assessment and attack-path views. The IOA flow runs the opposite direction: CloudTrail management events in each account and region hit the Falcon-deployed EventBridge forwarding rules, which PutEvents onto CrowdStrike’s event bus, where the behavioural engine turns event sequences into detections within minutes. The registry flow has Falcon pulling image layers from ECR through the same trust pattern on a schedule, while your CI pushes just-built images through the inline analyzer as a promotion gate. Around the edges sit the operating integrations: Okta/Entra ID gate console access over SAML, Vault holds the API client credentials, detections fan out to ServiceNow and the SOC, Wiz runs as an independent posture cross-check, and Datadog/Dynatrace ingest the detection stream for dashboards.

CrowdStrike Falcon Cloud Security on AWS: the assessment engine assuming the cross-account read-only reader role (external-ID trust) into every Organization account for CSPM/IOM scanning; per-account EventBridge rules forwarding CloudTrail management events to CrowdStrike's event bus for behavioural IOA detection; ECR registry assessment pulling image layers plus the inline CI scan gate; with Okta/Entra SSO, Vault-held API credentials, and findings fanning out to ServiceNow, the SOC, Wiz, and Datadog/Dynatrace

The property to notice: every arrow into your accounts is either read (role assumption for enumeration, ECR layer pulls) or outbound push you control (EventBridge forwarding). Nothing in the core deployment gives CrowdStrike write access to your environment, which is why the whole architecture can ship through a security review in one pass — and why remediation, which does need write, is deliberately a separate, opt-in path.

Real-world scenario: 42 accounts, 6 weeks, one choke point

SwiftRail Payments (fictional, realistic) runs 42 accounts: 8 prod, 22 non-prod, 12 sandbox, Control Tower-vended, with the Falcon sensor already on ~600 EC2 instances and 14 EKS clusters. Two staff engineers got the CSPM mandate with a hard constraint: no console click-ops, everything reviewable in git.

Week 1 they registered the Organization via the Terraform provider and stacked the reader role into the 8 prod accounts only (max_concurrent_percentage = 25), deliberately excluding sandboxes from licensing scope. First full scan: 3,847 IOMs — 41 Critical, 312 High. The team did not file 3,847 tickets. They filed 41, from which two patterns emerged: 29 of the Criticals were the same public-snapshot misconfiguration stamped by one legacy AMI-bakery module, and the attack-path view showed one choke point — a CI role in a shared-services account assumable by arn:aws:iam::* principals within the org and holding iam:PassRole on *. One Terraform PR to the bakery module and one to the CI role’s trust policy closed 29 Criticals and collapsed 14 of the 17 data-terminating attack paths. Total effort: four days.

Week 3, IOA went live org-wide. Day two produced a page: StopLogging on a member-account trail — not an attacker, but a cost-cleanup script an SRE had written months earlier that disabled “unused” trails, which had been silently running ever since. The behavioural lens caught in 6 minutes what the posture lens would have reported at next scan as one more High among hundreds; the SRE’s script got an allowlist and a code review. The same week, ServiceNow routing went in with the account→assignment-group lookup, and the first weekly digest went to team backlogs.

Week 5, the ECR gate turned on in warn mode across 61 repositories: 34% of builds carried a fixable Critical, almost all from two stale base images. Platform published refreshed bases, gave teams a two-week grace window, then flipped prod-* repos to fail-closed. Break-glass procedure (deploy despite a finding, VP sign-off, 72-hour expiry) was used twice in the first month — both times for CVEs with no vendor fix, both tracked to closure.

Week 6 numbers: Criticals 41 → 3 (all exempted with expiry and owner), data-terminating attack paths 17 → 2, image-gate pass rate 66% → 94%, mean SOC triage time for cloud IOAs 11 minutes. The retrospective’s one-liner: “The graph told us which three edges to cut; everything else was backlog.”

Advantages and disadvantages

Advantages Disadvantages
One console and one severity language across endpoint (sensor), posture (IOM), behaviour (IOA), and images — the join is the product Licensing is per-asset/account and commercially significant; sandbox scoping decisions become budget decisions
Read-only, externally-auditable AWS footprint; security review is straightforward Scan-cycle latency on IOMs — between scans, only IOA sees change, and only for CloudTrail-visible actions
Org-level registration + SERVICE_MANAGED StackSet auto-enrols future accounts — governance that scales past human memory Trust chain depends on CrowdStrike-side infrastructure (intermediate role, event bus); an upstream change can silently degrade coverage until you alert on it
Behavioural IOAs catch attacker sequences natively (multi-event patterns GuardDuty scores differently or not at all) IOA coverage is bounded by CloudTrail management events — data-plane exfiltration needs data events or the sensor
Attack-path graph turns finding floods into a short choke-point worklist Graph quality depends on complete registration — a few unregistered accounts create false “no path” confidence
Terraform provider + API make the entire lifecycle IaC-native, including teardown Provider ecosystem is younger than the platform; some console features (policy tuning, Fusion workflows) still lack full IaC coverage — document the click-configured remainder
Registry + snapshot assessment extend one CVE model to images and unsensored hosts Overlap with AWS-native (Config, GuardDuty, Inspector, Security Hub) means paying twice unless you consciously assign each tool a job

The honest competitive note: if you have no CrowdStrike footprint at all, evaluate this against Wiz and against an all-native stack on joins, not features — every vendor’s checklist looks identical. Falcon’s differentiated join is sensor-runtime + posture in one asset record; if that join is worthless to you, the calculus changes.

Hands-on lab: register the Org, prove all three lenses, roll out in waves

This is the centerpiece. It assumes the prerequisites table is satisfied, runs from a workstation or CI runner with management-account credentials, and finishes with a verified, torn-downable deployment. Run steps 1–8 in a sandbox Organization first if you have one; the runbook in step 9 is how you take it to production.

Lab variables — set once, reference everywhere:

export FALCON_CLOUD="us-1"                    # your tenant's cloud from the region table
export MGMT_ACCOUNT="111111111111"
export ORG_ID="o-abcd1234ef"
export SANDBOX_ACCOUNT="333333333333"         # a member account you can safely break
export HOME_REGION="us-east-1"

Step 1 — API client, secret into Vault, token smoke test

In the console: Support and resources → API clients and keys → Create API client. Name aws-cspm-onboarding, scopes CSPM registration: Read & Write and Falcon Container Image: Read & Write. The secret displays exactly once — put it straight into Vault:

vault kv put secret/falcon/cspm client_id="$CID" client_secret="$CSECRET" cloud="$FALCON_CLOUD"
export FALCON_CLIENT_ID=$(vault kv get -field=client_id  secret/falcon/cspm)
export FALCON_CLIENT_SECRET=$(vault kv get -field=client_secret secret/falcon/cspm)

# Smoke test — expect: token-ok
curl -s -X POST "https://api.${FALCON_CLOUD}.crowdstrike.com/oauth2/token" \
  -d "client_id=${FALCON_CLIENT_ID}&client_secret=${FALCON_CLIENT_SECRET}" \
  | python3 -c "import sys,json;print('token-ok' if json.load(sys.stdin).get('access_token') else 'FAILED')"

FAILED here is a wrong FALCON_CLOUD or mistyped secret — fix before proceeding; nothing downstream works without it. (Vault-side patterns for exactly this shape of credential are in HashiCorp Vault as Central Secrets Broker for Multi-Cloud Workloads.)

Step 2 — Confirm the CloudTrail foundation

aws cloudtrail describe-trails \
  --query 'trailList[].[Name,IsOrganizationTrail,IsMultiRegionTrail]' --output table
aws cloudtrail get-trail-status --name org-management-trail --query 'IsLogging'
# Expect: an org trail, multi-region, IsLogging: true

No org trail, or IsLogging: false → stop and fix that first (the CloudTrail article has the module). IOA without a logging trail is a pipeline to nowhere.

Step 3 — Register the Organization (Terraform)

Apply the registration + StackSet configuration from the registration section above (crowdstrike_cloud_aws_account.org, aws_cloudformation_stack_set.falcon, instances, and the direct management-account stack):

terraform init && terraform plan -out=tf.plan     # review: 1 Falcon registration, 1 StackSet, instances, 1 stack
terraform apply tf.plan
terraform output external_id                       # note it; validation uses it

Step 4 — Watch the StackSet fan out, then confirm registration health

aws cloudformation list-stack-instances \
  --stack-set-name crowdstrike-falcon-cloud-security \
  --query 'Summaries[].[Account,Region,Status,StatusReason]' --output table
# Expect: every targeted account CURRENT; investigate any OUTDATED/FAILED row before proceeding

TOKEN=$(curl -s -X POST "https://api.${FALCON_CLOUD}.crowdstrike.com/oauth2/token" \
  -d "client_id=${FALCON_CLIENT_ID}&client_secret=${FALCON_CLIENT_SECRET}" | jq -r .access_token)
curl -s "https://api.${FALCON_CLOUD}.crowdstrike.com/cloud-connect-cspm-aws/entities/account/v1?organization-ids=${ORG_ID}" \
  -H "Authorization: Bearer ${TOKEN}" \
  | jq '[.resources[] | {account_id, status}] | group_by(.status) | map({status: .[0].status, n: length})'
# Expect: all accounts "provisioned"/"Active" once the role exists and the first scan touched them

Console check: Cloud security → Settings → Account registration — every account green. Accounts stuck Pending past an hour: wrong role name, wrong external ID, or the StackSet skipped them (management account? excluded OU?).

Step 5 — Prove the IOM lens with a deliberate finding (sandbox account)

aws s3api create-bucket --bucket "cs-iom-canary-${SANDBOX_ACCOUNT}" --region "$HOME_REGION"
aws s3api put-public-access-block --bucket "cs-iom-canary-${SANDBOX_ACCOUNT}" \
  --public-access-block-configuration BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false
aws s3api put-bucket-policy --bucket "cs-iom-canary-${SANDBOX_ACCOUNT}" --policy '{
  "Version":"2012-10-17",
  "Statement":[{"Effect":"Allow","Principal":"*","Action":"s3:GetObject",
                "Resource":"arn:aws:s3:::cs-iom-canary-'"${SANDBOX_ACCOUNT}"'/*"}]}'

Within one scan cycle, Cloud security → Misconfigurations, filter the sandbox account → expect the public-bucket Critical against your canary. Open it and read the guided remediation panel — this is the panel your ServiceNow tickets will embed. Do not fix it yet; step 7 uses it.

Step 6 — Prove the IOA lens (sandbox only, and re-enable immediately)

# Classic defence-evasion IOA: stop a sandbox trail (NEVER the org trail)
aws cloudtrail stop-logging --name sandbox-local-trail
sleep 300
aws cloudtrail start-logging --name sandbox-local-trail

Expect a behavioural detection (“CloudTrail logging disabled”-class) in Cloud security → Detections within minutes, severity High+, carrying the principal, source IP, and event narrative. If nothing after ~15 minutes, debug the six-hop pipeline table from the IOA section — in practice: hop 3 (rule missing in that region) or hop 4 (target role broken).

Step 7 — Prove read-only, then close the loop

# The reader role must be able to READ...
aws sts assume-role --role-arn "arn:aws:iam::${SANDBOX_ACCOUNT}:role/$(terraform output -raw iam_role_name)" \
  --role-session-name verify --external-id "$(terraform output -raw external_id)" > /tmp/cs.json
export AWS_ACCESS_KEY_ID=$(jq -r .Credentials.AccessKeyId /tmp/cs.json) \
       AWS_SECRET_ACCESS_KEY=$(jq -r .Credentials.SecretAccessKey /tmp/cs.json) \
       AWS_SESSION_TOKEN=$(jq -r .Credentials.SessionToken /tmp/cs.json)
aws s3api list-buckets --query 'Buckets | length(@)'          # succeeds: read works
aws s3api put-object --bucket "cs-iom-canary-${SANDBOX_ACCOUNT}" --key x --body /etc/hostname 2>&1 \
  | grep -q AccessDenied && echo "read-only confirmed"        # writes: denied
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN

Now remediate the canary the way production will: apply the guided-remediation fix (re-enable Public Access Block, delete the policy), and confirm the finding clears at the next scan — that disappearance is your triage loop’s “done” signal.

Step 8 — Wire and gate ECR

Register the registry connection (console Registry connections, or the container-security API) against a dedicated CrowdStrike-ECR-Read role, then prove the CI gate fails closed:

docker pull vulnerables/web-dvwa:latest    # a knowingly-vulnerable image
docker tag vulnerables/web-dvwa:latest "${MGMT_ACCOUNT}.dkr.ecr.${HOME_REGION}.amazonaws.com/lab-canary:dvwa"
# Run the falcon-image-analyzer step from the registry section against it — expect a non-zero exit
echo "exit=$?"                              # a 0 here means your policy is warn-only: fix the policy, not the pipeline

Console: Cloud security → Images shows the digest with its CVE counts; the assessment policy verdict matches the exit code.

Step 9 — The production rollout runbook

With the mechanics proven, production is sequencing. This is the wave plan that avoids both big-bang risk and eternal pilots:

Wave Scope Actions Gate to next wave
0 (day 0) Sandbox Org / 1 sandbox account Steps 1–8 end to end, including teardown rehearsal All three lenses proven + teardown clean
1 (week 1) Security/tooling + 2 low-risk prod accounts Register, stack, first scan; baseline finding counts; no ticketing yet Registration green; scan completes; no unexplained findings class
2 (week 2) All prod OUs StackSet targets widen; IOA on; SOC dry-run on detections SOC triage runbook exercised on ≥1 real IOA
3 (week 3–4) Non-prod OUs; ServiceNow routing live Account→assignment-group lookup verified per account; Critical/High SLAs start <5% ticket misroutes in the first week
4 (week 4–5) ECR gate warn-mode on all repos Publish base-image fixes; grace window announced Pass rate > 90% on prod-* repos
5 (week 6) Gate fail-closed on prod-*; auto-deployment on for new accounts Flip policy; enable StackSet auto-deployment against the full OU set; exemption register reviewed Steady state — hand to operations

Step 10 — Validation matrix (run at every wave boundary)

Check Command / place Pass condition
Registration health API query from step 4 100% of wave accounts provisioned
StackSet drift aws cloudformation detect-stack-set-drift + instance list All CURRENT, no drift
IOM pipeline Canary bucket (sandbox) Finding within one scan cycle, clears after fix
IOA pipeline Sandbox trail stop/start Detection < 15 min, correct principal
Read-only invariant Step 7 assume-role probe Write denied, read allowed
ECR gate Vulnerable-image scan Non-zero exit on policy breach
Ticket routing Latest 20 ServiceNow incidents Correct assignment group ≥ 95%
New-account auto-enrol Vend a test account Registered + stacked with zero human action

Step 11 — Teardown (sandbox, or full decommission)

Order matters — forwarders first, then roles, then the registration, then credentials:

aws s3 rb "s3://cs-iom-canary-${SANDBOX_ACCOUNT}" --force        # lab canaries out first
terraform destroy -target=aws_cloudformation_stack_set_instance.members   # EventBridge rules + roles leave members
terraform destroy -target=aws_cloudformation_stack.mgmt
terraform destroy -target=aws_cloudformation_stack_set.falcon
terraform destroy -target=crowdstrike_cloud_aws_account.org      # deregister from Falcon
# API fallback if state is lost:
curl -s -X DELETE "https://api.${FALCON_CLOUD}.crowdstrike.com/cloud-connect-cspm-aws/entities/account/v1?ids=${MGMT_ACCOUNT}" \
  -H "Authorization: Bearer ${TOKEN}"
vault kv delete secret/falcon/cspm                               # then revoke the API client in the console

Verify: registration page empty, list-stack-instances empty, no cs-/CrowdStrike-named roles or EventBridge rules left in a spot-checked member account.

Common mistakes & troubleshooting

The playbook, symptom-first — these twelve cover essentially every stuck rollout I have seen:

# Symptom Root cause Confirm Fix
1 OAuth token call fails with 403/opaque error Wrong Falcon cloud (us-1 vs us-2 vs eu-1) Compare console URL to the region table Pin FALCON_CLOUD in Vault; retest step 1
2 Account stuck Pending/Inactive after stacking Role name or external ID mismatch vs registration aws iam get-role on the member; diff trust policy vs terraform output Redeploy StackSet with outputs sourced from the registration, never hand-copied
3 One account missing from an otherwise green Org Management account skipped (service-managed StackSets exclude it by design) list-stack-instances has no row for it Direct aws_cloudformation_stack in the management account
4 Whole OU missing OU not in deployment_targets, or account suspended StackSet targets vs aws organizations list-organizational-units-for-parent Add the OU; re-run instance deployment
5 StackSet instance FAILED: Role name already exists Prior manual/console onboarding left an old role StatusReason on the instance; get-role shows unmanaged role Delete the orphan role, or import it; never run two onboarding methods per account
6 CSPM green but zero IOA detections ever CloudTrail not logging, or forwarding rules dead get-trail-status; aws events list-rules in the member; sandbox trail-stop test Fix trail; redeploy rules; re-run step 6
7 IOA works in us-east-1 only Forwarding rules stamped in one region list-rules per enabled region Extend the member template to all enabled regions
8 AccessDenied errors in your CloudTrail from the reader role Normal: Falcon probing services SecurityAudit doesn’t cover, or SCP-denied regions Event source/action pattern is all reads Expected noise — allowlist the role in your CloudTrail analytics rather than “fixing” it
9 Registry connection shows no images ECR role lacks GetDownloadUrlForLayer/BatchGetImage, or wrong registry URL Test aws ecr get-download-url-for-layer with the role’s creds Correct the role policy / registry URL (account+region specific)
10 CI gate passes visibly vulnerable images Assessment policy is warn-only, or scoped to the wrong repos Policy scope vs repo name pattern Fix the policy criteria/scope; re-run the DVWA canary
11 Finding counts explode after adding sandbox OUs Licensing/scope decision made implicitly by a StackSet target change Finding trend by account group Scope registration + policies by account group deliberately; exclude or lighten sandboxes
12 Tickets closed but findings persist Assignment-group lookup wrong, or teams closing without fixing Sample 10 closed tickets vs live findings Fix account→team mapping; make “finding cleared at rescan” the ServiceNow close condition

Two systemic mistakes sit above the table. Mixing onboarding methods (console for account A, Terraform for the Org, an API script from a hackathon) produces exactly the drift zoo rows 2 and 5 describe — pick Terraform and delete the rest. And turning on ticketing before baselining (wave 3 before wave 1) floods teams with thousands of legacy findings, burning the political capital the programme needs; baseline, fix the choke points, then open the tap.

Best practices

Security notes

Least privilege runs in both directions. Toward AWS: the reader role is SecurityAudit plus enumerated read statements, no write verbs, external-ID-pinned trust to one CrowdStrike principal — and you verified it empirically in the lab rather than trusting the template. Toward Falcon: the API client carries exactly two scopes; console humans authenticate through Okta/Entra SAML with MFA and IdP-group-mapped roles, so analyst/manager/admin separation lives in the identity layer where joiner-leaver processes already work. The external ID and API secret live in Vault with access audit; Terraform state contains the external ID, so the state backend is encrypted and access-controlled like the secret store it now effectively is. The IOA pipe is one-way outbound (events:PutEvents to one bus ARN) and carries management-event metadata, not data-plane content — put that sentence in your DPIA. Finally, monitor the monitors: alert on AssumeRole against the reader role from unexpected principals, on DeleteRule/RemoveTargets against the forwarding rules, and on the registration count dropping — an attacker who knows you run Falcon will try to unplug it before working.

Cost & sizing

Falcon Cloud Security is commercially licensed (typically per cloud asset/workload under CrowdStrike’s Falcon Flex or module bundles — get real numbers from your rep; list prices in public marketplaces run low-hundreds of USD per workload per year, and Org size changes everything). What you engineer, though, is the scoping and the AWS-side bill:

Cost line Driver Order of magnitude Your lever
Falcon licensing Assets/accounts in scope The dominant line Scope OUs deliberately; sandbox accounts on a lighter (or no) tier
CloudTrail Management events, first copy free; S3 storage for the trail ₹2,000–8,000/mo for a mid-size Org’s trail storage Lifecycle old logs to Glacier tiers
EventBridge forwarding Cross-account PutEvents to the CrowdStrike bus (custom-event pricing, ~$1/million events) A 42-account Org doing 50M management events/mo ≈ $50 (~₹4,200)/mo Nothing worth doing — this is the whole IOA pipe
Snapshot assessment Snapshot storage + scan churn in enabled accounts GB-month pricing on changed blocks Enable per-OU, only where sensors are impossible
CI scan minutes Scanner image pull + scan time per build Minutes per build Cache the analyzer image on runners
SIEM/observability ingest Detection stream into Datadog/Splunk Per-GB ingest Forward High/Critical only; the console keeps the rest

Sizing rules of thumb: the AWS-side infrastructure is effectively free relative to licensing — roles and rules have no hourly cost, and the EventBridge line above is lunch money. The real sizing decision is which OUs are in scope, and the honest way to make it is the failure-mode table from the top of this article: any OU whose compromise you would page a human for belongs in scope; any OU you would shrug at can wait.

Interview & exam questions

Q1. Why does the reader role’s trust policy carry an external ID, and what attack does it stop? It pins role assumption to CrowdStrike’s intermediate principal and a per-registration secret-ish value, defeating the confused deputy: another CrowdStrike tenant (or abused internal path) naming your role ARN still fails the sts:ExternalId condition. Without it, any principal CrowdStrike’s infra serves could potentially enumerate your account.

Q2. IOM vs IOA — mechanism and latency. IOM: assessment engine assumes the reader role on a scan schedule, evaluates config against policies — latency is the scan interval, hours. IOA: CloudTrail management events forwarded via EventBridge to CrowdStrike’s bus, behavioural engine scores event sequences — latency is minutes. IOM says the door is unlocked; IOA says the handle is turning.

Q3. Why does a service-managed StackSet miss the management account, and what do you do? By design, SERVICE_MANAGED StackSets deploy only to member accounts via Organizations trusted access. You deploy a direct CloudFormation stack (same template) in the management account — forgetting this is the classic “one account never registered”.

Q4. A team asks for 1-click remediation on a Terraform-managed prod bucket. Answer? No — the next terraform apply reverts the fix (or half-reverts it), recreating the finding plus drift. Route it as an IaC PR using the guided-remediation content; reserve 1-click for unmanaged resources or genuine emergencies, followed by import.

Q5. IOA has never fired in eu-west-2. Name the two most likely hops broken. Forwarding rules were only stamped into the home region (hop 3), or the region’s events aren’t in scope because the trail isn’t multi-region (hop 1). Confirm with aws events list-rules in that region and describe-trails.

Q6. Registry connection vs inline CI scan — why run both? The connection answers “what is in my registry”, re-evaluates on new CVEs, and catches images that bypassed CI; the inline scan answers “should this build promote” and can block. One is detective and retroactive, the other preventive and point-in-time.

Q7. What can snapshot assessment never tell you? Runtime behaviour: processes, memory, live network activity. It reads a disk image — it finds vulnerable packages on unsensored hosts but detects no active attacker. It is a bridge to sensor coverage, not a substitute.

Q8. Where does SecurityAudit stop and the CrowdStrike supplement start? SecurityAudit is config-metadata reads across ~100 services but deliberately excludes content reads. The supplement adds specific extras Falcon needs — notably ecr:GetDownloadUrlForLayer/BatchGetImage (image layers are content) and a few Describe/Get calls on newer services.

Q9. Your CISO asks why buy this when GuardDuty + Config + Security Hub exist. The join: one asset record carrying sensor runtime detections, posture findings, image CVEs, and attack paths, with one severity language and one ticket pipe — valuable precisely proportional to your existing Falcon footprint. Feature-by-feature, natives cover much of it; the argument is operational consolidation, and it is honest to say so.

Q10. How do you prove the integration is read-only to an auditor? Empirically: assume the reader role with the external ID, demonstrate a read succeeding and a write returning AccessDenied (lab step 7), and show the trust policy plus the absence of write verbs in both attachments. Evidence beats template review.

Q11. What breaks if someone rotates/deletes the org CloudTrail without telling security? Hop 1 of the IOA pipeline goes dark: CSPM stays green, EventBridge rules sit idle, and the SOC sees silence indistinguishable from safety. This is why trail health is monitored alongside detections and why “CloudTrail disabled” is itself a high-severity IOA.

Q12. Design the exemption process that keeps suppressions from becoming shadow risk. Every exemption carries an owner, a justification, and an expiry; monthly review re-approves or lapses them; the exemption count is a tracked metric. Suppression without expiry is unbooked risk acceptance by whoever clicked fastest.

Quick check

  1. Which two values does a registration hand back that the AWS-side deployment must consume exactly?
  2. An account shows Pending in the registration page an hour after the StackSet succeeded. First two things to diff?
  3. Which lens catches AuthorizeSecurityGroupIngress to 0.0.0.0/0 within minutes, and which reports it hours later if still true?
  4. Why fail-closed on the image gate only for prod-* repositories initially?
  5. In teardown, why do EventBridge rules leave before the registration is deleted?

Answers

  1. The IAM role name and the external ID (plus the intermediate role ARN and event bus ARN as trust/target inputs).
  2. The deployed role’s name vs the registration’s expected name, and the trust policy’s external ID vs terraform output — mismatches there are the dominant cause.
  3. IOA (behavioural, event-driven) in minutes; IOM at the next assessment scan.
  4. Fail-closed needs a rehearsed break-glass and a >90% pass rate first; flipping everything at once turns the security gate into an outage generator and burns goodwill.
  5. So no forwarding rule ever targets a bus ARN whose registration (and thus permission grant) no longer exists — orphaned rules fail forever and pollute logs.

Glossary

Next steps

AWSCrowdStrikeCSPMCloud SecurityECRTerraformEventBridgeCloudFormation
Need this built for real?

Vinod is a Senior Cloud Architect (22+ yrs) — available for Azure / AWS / GCP architecture, landing zones, and migrations.

Work with me

Comments

Keep Reading