AI SecurityCrowdStrikeAWSCloud SecuritySOC Automation

Cloud Account Discovery at Scale: Triaging CrowdStrike Alerts with an AI Agent

How to turn a noisy, high-volume CrowdStrike detection class - AWS IAM account discovery - into an agent-driven triage workflow that classifies alerts, hunts proactively, and only surfaces what needs human eyes.

Luis Torres-Villarreal

Series: Agent-Driven Workflows - CrowdStrike Detection Triage. Post 1 of 5. Originally published on LinkedIn.

Detection Context

Account Discovery is one of the most common post-access behaviors in AWS environments - and one of the noisiest. Adversaries use IAM GetUser calls to map out the account structure, identify privileged identities, and find their next pivot. The challenge isn’t detecting the behavior; CrowdStrike does that well. The challenge is separating hundreds of automated service-account lookups from the one that isn’t.

MITRE ATT&CK: T1087.004 - Account Discovery: Cloud Account (Tactic: TA0007 Discovery). Source: Falcon Cloud Security, ingesting CloudTrail via iam.amazonaws.com.

Scenario

Over a period spanning several months in a production multi-account AWS environment, CrowdStrike Falcon Cloud Security generated hundreds of detections in this category across two distinct behaviors:

  • “Potential discovery of Admin accounts” - Fires when an IAM GetUser API call targets an account whose userName contains “Admin” or a variant. In isolation, a single GetUser on an Admin-named account is almost always benign - CI/CD pipelines and automation scripts make these calls constantly. The signal is volume and pattern: multiple lookups across different Admin-named accounts in a short window is enumeration behavior.
  • “Console login without MFA by IAM user” - Fires when a console authentication event succeeds with mfaAuthenticated: false. This is a separate risk class entirely - not enumeration, but a configuration gap and policy violation. One event is enough to warrant action.

The core problem: high alert volume, mostly low-severity, arriving continuously. A human analyst triaging each one manually is not scalable, and most alerts will age out unreviewed. The AI agent’s job is to work the queue, classify each alert, and surface only the ones that need human eyes.

Prompt Chain

The following prompt chain drives the full triage workflow. These were run against a Claude Code instance (Hermes/OpenClaw also work) with CrowdStrike API access, AWS CLI credentials, and Okta read access. The same chain works in any harness with tool-use and multi-step reasoning.

Prompt 1 - Pull and classify the alert queue

Pull all new CrowdStrike Falcon alerts with type ‘ldt’ and status ‘new’ from the last 24 hours. For each alert, extract: alert ID, display name, severity, event name, source IP, AWS access key ID, target IAM username, affected AWS account ID, and MFA authenticated status.

Group results into two buckets:

  • GetUser alerts (event_name = GetUser)
  • ConsoleLogin alerts (event_name = ConsoleLogin, mfa_authenticated = false)

Present a summary table before proceeding.

Prompt 2 - Investigate GetUser alerts

For each GetUser alert, do the following in sequence:

  1. Classify the source IP: check against corporate VPN ranges, AWS ip-ranges.json service IPs, and CI/CD runner CIDRs. Label each as: internal, aws-service, or external-unknown.
  2. Pull CloudTrail events for the associated access key ID in a plus/minus 30 minute window around the alert timestamp. Look for: GetUser, ListUsers, ListGroups, GetAccountSummary, AssumeRole, CreateAccessKey, CreateLoginProfile.
  3. Count distinct Admin-named usernames queried by this key.
  4. Resolve the key to an IAM identity using get-access-key-last-used. Verify that identity exists and is active in Okta.
  5. Apply this decision logic and assign a verdict to each alert:
    • Internal IP + 1 Admin lookup + known service account -> BENIGN
    • Internal IP + 5+ Admin lookups -> REVIEW
    • External IP + 1-2 lookups + verified employee -> VERIFY WITH USER
    • External IP + 3+ Admin lookups -> ESCALATE
    • External IP + 5+ lookups + no MFA -> INCIDENT

Summarize findings per alert with the verdict and key evidence.

Prompt 3 - Investigate MFA alerts

For each ConsoleLogin alert where mfa_authenticated is false:

  1. Confirm via AWS IAM whether the account has any MFA device registered: run list-mfa-devices for the IAM username.
  2. Check if this user has an active Okta account and whether Okta MFA is enforced for AWS console access.
  3. Assign verdict:
    • No MFA device registered -> REMEDIATION REQUIRED (config gap)
    • MFA device exists but not used -> INVESTIGATE (policy enforcement gap)

Flag each as a compliance finding independent of the GetUser triage.

Prompt 4 - Generate triage report and take action

Based on the triage results:

  1. Draft a structured triage report with: alert ID, verdict, evidence summary, and recommended action for each alert.
  2. For alerts marked BENIGN: update status to ‘closed’ in Falcon and add a note identifying the service account and automation owner.
  3. For alerts marked REMEDIATION REQUIRED: draft a Jira ticket for the IAM owner with steps to enforce MFA and a compliance deadline.
  4. For alerts marked ESCALATE or INCIDENT: do not auto-close. Draft an incident summary and flag for analyst review.
  5. Post a summary of all verdicts and actions to the #security-alerts Slack channel.

Agent Workflow

This is what the agent actually does when it runs those prompts - step by step, using real APIs.

Step 1 - Pull full alert details from the Falcon Alerts API

GET /alerts/queries/alerts/v2
Filter: type='ldt' AND status='new'

For each alert ID returned, pull the full body:

POST /alerts/entities/alerts/v2
Body: { "ids": ["<alert_id>"] }

Extracts per alert: aws_access_key_id, request_parameters.userName, source_ip_address, aws_recipient_account_id, mfa_authenticated.

Key fields available for triage:

Field Description
event_name CloudTrail event: GetUser, ConsoleLogin
request_parameters.userName Target IAM username queried or authenticated
aws_access_key_id The access key that made the API call
aws_recipient_account_id The AWS account the call landed in
source_ip_address Origin IP of the API call
mfa_authenticated true or false - populated on ConsoleLogin events only
first_timestamp / last_timestamp Alert time window
falcon_host_link Direct link to the alert in Falcon console

Step 2 - Classify the source IP

Compares source_ip_address against:

  • Corporate VPN egress ranges
  • AWS service IP ranges (ip-ranges.json)
  • Allowlisted CIDRs for CI/CD runners and automation

Outcome: internal, aws-service, or external-unknown - each carries a different risk weight into the decision logic.

Step 3 - Query CloudTrail for the full API session

aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=<aws_access_key_id> \
  --start-time <first_timestamp - 30min> \
  --end-time <last_timestamp + 30min>

Scans the event sequence for escalation signals: ListUsers, ListGroups, GetAccountSummary, AssumeRole, CreateAccessKey, CreateLoginProfile. A GetUser call surrounded by these is a different risk profile from a GetUser call that stands alone.

Step 4 - Resolve the calling identity

aws iam get-access-key-last-used --access-key-id <aws_access_key_id>

Returns the IAM username. Verified against Okta:

GET /api/v1/users?search=profile.login eq "<username>"

Confirms: does the identity exist, is the account active, is this a service account or a human?

Step 5 - Count distinct Admin accounts queried

From the CloudTrail session pull, extracts all unique requestParameters.userName values containing “admin” (case-insensitive).

Distinct count Interpretation
1 Single lookup - consistent with routine automation
2-4 Borderline - verify caller intent
5+ Enumeration pattern - escalate regardless of IP

Step 6 - MFA check for ConsoleLogin alerts

For any event_name = ConsoleLogin with mfa_authenticated = false:

aws iam list-mfa-devices --user-name <username>

No MFA device attached = configuration gap, flagged as a compliance finding independent of the enumeration triage.

Step 7 - CQL hunt query in CrowdStrike NGSIEM / LogScale

For proactive hunting beyond the alert queue - surfaces enumeration patterns not yet fired as detections:

#repo=search-all eventSource="iam.amazonaws.com"
  requestParameters.userName=~wildcard("*Admin*")
  OR requestParameters.userName=~wildcard("*admin*")
| select([
    eventTime,
    userIdentity.accessKeyId,
    userIdentity.arn,
    requestParameters.userName,
    sourceIPAddress,
    userAgent
  ])
| groupBy(
    [userIdentity.accessKeyId],
    function=[
      count(as=total_lookups),
      collect([requestParameters.userName]),
      min(eventTime, as=first_seen),
      max(eventTime, as=last_seen)
    ]
  )
| sort(total_lookups, order=desc)
| total_lookups > 3

Surfaces access keys making more than 3 GetUser calls on Admin-named accounts, with the full list of target usernames and the activity time window. Tune the threshold and add source IP filters for your environment.

Output & Decision

The agent produces a structured triage report for each alert, then branches on verdict:

False Positive - Alert is closed in Falcon with an analyst note identifying the service account, automation owner, and call context. If the same key generates repeated alerts, a suppression rule is created scoped to that key and source IP. Activity log updated.

True Positive - Escalation path depends on severity:

  • MFA gap -> remediation ticket opened for the IAM owner with a compliance deadline
  • Enumeration confirmed -> access key revoked or deactivated immediately, full CloudTrail pulled across all accounts the key touched, incident tracking begins, account owner notified
  • Credential compromise indicators -> treat as active incident, escalate to IR

Undetermined - Triage report drafted with all evidence collected, alert flagged for analyst review. The agent does not auto-close. A summary is posted to Slack with the open questions the analyst needs to answer.

Prerequisites

Access:

Requirement Detail
CrowdStrike API client Scopes: Alerts (read/write), Detections (read)
AWS credentials IAM read: GetUser, ListMFADevices, GetAccessKeyLastUsed; CloudTrail: LookupEvents
Okta API token Read scope on Users
Slack webhook or bot token For alert summary posting
Jira API token For ticket creation on remediation/escalation findings

Context (what you feed the harness). This is what separates a generic AI assistant from an agent that can actually do the work. The harness needs:

  • Falcon Alerts API reference - endpoint paths, filter syntax, field schema for alert objects. Without this, the agent guesses at field names and gets them wrong.
  • CQL / LogScale syntax reference - groupBy, collect, wildcard, aggregation functions. CQL is not SQL; the agent needs explicit examples.
  • CloudTrail event schema - which fields appear in IAM events, what requestParameters looks like for GetUser vs. ConsoleLogin.
  • Your environment context - VPN CIDR ranges, CI/CD runner IPs, known service account naming conventions, AWS account IDs and their friendly names.
  • MITRE T1087.004 context - what adversaries are doing with this technique, what the escalation signals look like.

In a Claude Code, Hermes, or OpenClaw setup, this context lives in a skill file - a structured document the agent loads before running the workflow. That’s the mechanism. In other tooling, it’s a system prompt, a RAG chunk, or a prepended reference document. The format varies but the need is the same.

Closing

Once you’ve run this workflow a few times and the verdicts hold up, the process should be codified - whether that’s a skill, a SOAR playbook, a prompt library, or a runbook in your wiki. The goal is that the next time these fire, the agent already knows what to do. No one drafts the prompts from scratch and no one re-explains what CQL groupBy does.

That’s how AI compounds in a security operation: not by being impressive once, but by getting faster and more consistent every time the same detection class reappears. And as a bonus, a codified workflow is a documented procedure. That’s auditable. That’s something you can show an assessor when SOC 2 comes around.

The detection class will come back. It always does. The question is whether your response is faster the second time.


Want to automate alert triage like this across your own stack? See how 543HQ builds security automation workflows.

Disclaimer: The AI-assisted workflows described in this article are intended to augment human judgment, not replace it. All agent outputs (verdicts, recommendations, and draft actions) require human review and verification before execution. Use of agentic tooling in security must align with your organization's policies, change management procedures, and applicable compliance requirements.

Luis Torres-Villarreal is a Senior Leader with 15+ years in IT, Information Security, PCI DSS, HITRUST, NIST CSF, and SOC 2 Type II compliance. He writes about AI agents, Security Automation, and the evolution of InfoSec Teams.

Need a hand with this at your company?

543HQ helps startups and growing companies build security programs that actually work. Start with a free 30-minute call.

Book a Free Call