Skip to content

feat(scan): organization-wide phantom user scan via AssumeRole#23

Merged
MrCloudSec merged 14 commits into
BeyondTrust:mainfrom
RajChowdhury240:main
May 18, 2026
Merged

feat(scan): organization-wide phantom user scan via AssumeRole#23
MrCloudSec merged 14 commits into
BeyondTrust:mainfrom
RajChowdhury240:main

Conversation

@RajChowdhury240
Copy link
Copy Markdown
Contributor

@RajChowdhury240 RajChowdhury240 commented May 10, 2026

Summary

Adds bks scan --org: enumerate every ACTIVE member account in the AWS Organization, AssumeRole into each in parallel,
run the existing PhantomUserScanner per account, aggregate into a single report. Closes the enterprise gap —
single-account scan was the toolkit's biggest scale ceiling.

Why

Real environments have 50–500 AWS accounts. v1.1.0 forced operators to loop bks scan per account and merge JSON
manually. Phantom users are a fleet-wide problem: any developer in any account can spawn one through the Console. SOC
needs one cross-org view.

What changes

  • New flags on scan:
    • --org — enable org mode
    • --org-role NAME — cross-account role (default OrganizationAccountAccessRole)
    • --org-accounts IDS — scope to comma-separated 12-digit IDs
    • --org-skip IDS — exclude comma-separated IDs
  • New core/org.py with OrgScanner (parallel, fail-isolated per account).
  • New AWSSession.from_credentials(...) factory for post-AssumeRole sessions.
  • New aggregate output output/bks-scan-org--.{json,csv}. CSV flattens one row per phantom user with
    account_id / account_name prepended.
  • Single-account path unchanged. New flags rejected unless --org set.

Design choices

  • Concurrency cap 8 accounts. STS throttles aggressively from one principal; IAM list_users per-account fans out 4
    sub-calls per phantom. 8× safe under default throttle.
  • 15-min AssumeRole DurationSeconds. Blast-radius cap if a session token leaks via verbose logs or CI artifacts.
  • Per-account failure → status=error in result, scan continues. One missing role in one account must not poison the
    report.
  • Management account skips AssumeRole — reuses base session. Cheap and avoids needing a self-trust on the role.
  • Sort order: errors first, then at_risk DESC, active DESC, account_id ASC. SOC eyes hit problems before noise.
  • 12-digit-only validation on --org-accounts / --org-skip — prevents typo-induced silent skip.

Permissions

Documented in docs/permissions.md. Caller (mgmt / delegated admin) needs organizations:ListAccounts + sts:AssumeRole on arn:aws:iam::*:role/. Each member account's role needs the existing scan permission set.

@RajChowdhury240 RajChowdhury240 requested a review from a team as a code owner May 10, 2026 06:49
Copy link
Copy Markdown
Member

@MrCloudSec MrCloudSec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution @RajChowdhury240 !

@MrCloudSec MrCloudSec merged commit 0849a66 into BeyondTrust:main May 18, 2026
7 checks passed
@MrCloudSec MrCloudSec mentioned this pull request May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants