Skip to main content

AWS Integration Patterns: Competitive Analysis

Date: 2026-03-31 Purpose: Document how Veza and other security platforms integrate with AWS, focusing on multi-account onboarding architecture, cross-account access patterns, and centralized data collection. This informs SecurityV0's own AWS connector architecture.


Executive Summary

Every major security platform uses the same fundamental AWS integration pattern: cross-account IAM roles with ExternalId, deployed via CloudFormation StackSets. The differences are in where the hub sits (vendor SaaS vs customer account) and which centralized AWS services they leverage.

VendorHub AccountStackSetsOrgs Auto-DiscoveryDeployment Model
VezaVeza SaaS accountLikelyYesSaaS, agentless
WizOptional customer OutpostYesYes (root OU)SaaS or customer VPC
CrowdStrikeCS intermediate accountYesYesSaaS
Prisma CloudTrusts Prisma acct directlyYes (SERVICE_MANAGED)YesSaaS
LaceworkCustomer scanner accountYesYesCustomer VPC + SaaS
OrcaNo hub (SideScanning)YesYesPure SaaS
SailPointVirtual Appliance (optional)NoLimited (CIEM only)SaaS or VA
SaviyntNoNoVia Identity CenterSaaS or self-hosted

Key insight for SecurityV0: The pattern is proven and standardized. SecurityV0 should adopt the same cross-account role + StackSet approach, but differentiate on what data we collect and how we use it (NHI execution chains, not generic CSPM).


1. Veza AWS Integration

Coverage

Veza integrates with 28+ AWS services as a native connector (not OAA-based):

CategoryServices
IdentityIAM, Identity Center (SSO), Organizations, IAM Roles Anywhere, Cognito
ComputeEC2, EKS, Lambda, EMR
DataS3, RDS (6 engine variants), Redshift, DynamoDB, DocumentDB, Neptune
SecurityKMS, Secrets Manager, Certificate Manager, Systems Manager
AIBedrock (agents + guardrail policies)
ContainerECR
NetworkVPC

Entity Model

Veza builds an "Authorization Metadata Graph" with confirmed entity types:

  • AwsIamUser — IAM users with access key and MFA metadata
  • AwsIamRole — Roles with trust policies and permission resolution
  • S3Bucket — Buckets with policy and encryption metadata
  • EC2, EKS, Lambda, EMR classified as NHI entities (added May 2024)
  • Full IAM policy evaluation chain: identity-based → resource-based → permission boundaries → SCPs → Resource Control Policies

Key capability: "Explain Assumed Roles" (GA Nov 2025) traces role assumption chains through trust relationships. This is the closest any competitor comes to SecurityV0's execution chain concept, but it remains a static authorization analysis — not observed execution evidence.

Cross-Account Architecture

Veza's detailed setup docs are behind authentication (docs.veza.com), but the pattern is standard SaaS cross-account:

  1. Customer creates IAM role in each account trusting Veza's SaaS AWS account
  2. ExternalId prevents confused-deputy attacks
  3. Organizations integration provides account/OU discovery and SCP context
  4. Agentless, read-only — no agents deployed in customer accounts

OAA SDK Cross-Account Features

Veza's open-source OAA SDK (oaaclient-py) provides methods for custom integrations that link to AWS:

  • CustomIdPUser.add_assumed_role_arns(arns) — binds IdP users to AWS IAM Roles
  • CustomIdPGroup.add_assumed_role_arns(arns) — same for groups
  • CustomResource.add_resource_connection(id, node_type) — connects OAA resources to Veza-discovered AWS entities

Permissions Required

Inferred from supported services (exact policy is behind docs.veza.com):

  • SecurityAudit AWS managed policy covers most read-only needs
  • Custom additions for newer services: bedrock:List*, bedrock:Get*, neptune:Describe*
  • CloudTrail read access for root user login tracking
  • organizations:List*, organizations:Describe* for org context

Platform Architecture (from OAA SDK, product whitepaper, and public documentation)

Understanding Veza's internal architecture informs SecurityV0's own design decisions — where to follow proven patterns and where to differentiate.

Graph Database and Storage

Veza uses a multi-store architecture with purpose-built databases for each workload:

StoreTechnologyPurpose
Authorization GraphNeo4j (graph database)Entity/relationship traversal for "who can access what" queries. The core authorization graph that powers all access path analysis.
OperationalPostgreSQL (relational)Tenant configuration, user management, policy metadata, schema definitions
AnalyticsClickHouse (columnar)Audit logs, event history, telemetry — append-only immutable store for compliance and time-series analytics
StreamingKafkaEvent propagation between services — extraction events, audit events, owner change notifications
ObjectS3Raw connector payloads, historical exports, debug artifacts

Implication for SecurityV0: Veza's choice of Neo4j for graph traversal validates the need for a graph-aware storage layer. SecurityV0 currently uses MongoDB with application-level graph traversal via the @xyflow/react + ELK.js visualization. If access path queries become a bottleneck at scale, a dedicated graph database should be evaluated. However, for SecurityV0's execution chain model (which is narrower than Veza's full authorization graph), MongoDB with indexed relationship queries may remain sufficient.

Graph Schema

Based on the OAA SDK, product documentation, and VQL query examples, Veza's graph uses these node and edge types:

Node types:

Node TypeDescriptionSecurityV0 Equivalent
LocalUserApplication-native user identity (human or NHI, with identity_type discriminator)identity entity
LocalGroupCollection of users within an application (supports nesting)No direct equivalent — SecurityV0 models group membership as relationships
LocalRolePermission container for RBAC models (supports nesting via add_role())role entity
CustomPermissionGranular access right, mapped to canonical CRUD verbspermission entity
CustomResourceProtected entity, hierarchical via sub-resourcesresource entity
IdPIdentityFederated identity from external IdP (Okta, Entra, Google Workspace, AD, OneLogin)identity entity (with source_system discriminator)
AccessCredentialToken, API key, or service account key with lifecycle metadatacredential entity
HRISEmployeeHR system employee record (department, manager, employment status)owner entity (with HR enrichment)

Edge types:

EdgeSemanticsSecurityV0 Equivalent
has_permissionIdentity → Permission (scoped to resources)No single edge — closest equivalent is the HAS_ROLEGRANTS path
has_roleIdentity → Role assignmentHAS_ROLE relationship
member_ofUser → Group or Group → Group (nesting)MEMBER_OF relationship
role_containsRole → Permission or Role → Role (nesting)Flattened in SecurityV0
identity_linkLocalUser ↔ IdPIdentity — cross-system identity resolutionCross-source correlation; AUTHENTICATES_AS only when the auth chain is explicit
assumed_role_arnsIdentity → AWS IAM Role ARNNo first-class equivalent yet — represented as trust-policy-derived structural authority
ownsOwner → Resource/Role/GroupOWNED_BY relationship

Key insight: Veza's graph is authorization-centric (who CAN access what). SecurityV0's graph is execution-centric (who DID access what, under what identity, across which boundaries). This is a fundamental architectural difference, not just a feature gap.

Connector Architecture

Veza's connector model uses a pull → transform → push pattern:

  1. Pull — Connector agents extract authorization data from target system APIs
  2. Transform — Data is modeled into OAA template structures (CustomApplication, CustomIdentityProvider, etc.)
  3. Push — A complete snapshot payload is submitted to the OAA API, replacing the entire data source

Key architectural details:

  • No delta/diff API — Each push replaces the full data source. No incremental updates.
  • Built-in connectors run inside a dedicated data plane service with configurable worker pools (discoverer workers for entity enumeration, extractor workers for detailed authorization data extraction)
  • OAA custom connectors are external scripts using the oaaclient Python SDK — community examples cover GitHub, GitLab, Jira, Slack, PagerDuty, Looker
  • All connectors are polling-based — no webhook receiver or event ingestion endpoint exists in the OAA API
  • Payloads are gzip-compressed and base64-encoded; large payloads (>50MB) use a multipart upload flow

Implication for SecurityV0: Veza's full-replacement model is simple but wasteful for large data sources. SecurityV0's existing change detection on findings (preventing unnecessary evidence pack rebuilds) is already more sophisticated. However, Veza's worker pool architecture (separate discoverer and extractor roles) is a pattern worth considering for SecurityV0's connector scaling.

Effective Permission Computation

Veza computes effective permissions through a three-stage pipeline:

  1. Graph traversal — Walking from identity nodes through group memberships, role assignments, and permission bindings to resource nodes
  2. Policy resolution — For systems like AWS, resolving the multi-step evaluation chain (identity policies → resource policies → SCPs → permission boundaries → session policies → conditionals)
  3. CRUD normalization — Translating vendor-specific permission verbs into the canonical vocabulary (DataRead, DataWrite, MetadataRead, etc.)

Computation is batch/snapshot-based — triggered after each connector push completes, not incremental. This means permission queries reflect the state at last ingestion, not real-time.

Implication for SecurityV0: SecurityV0's evaluator already uses a similar batch pattern (evaluate after ingestion). The difference is that SecurityV0 evaluates for findings (deterministic rules), not for effective permissions (graph traversal). Adding AWS permission evaluation in Phase 3 should follow a similar batch pattern but with explicit caveats when SCP/KMS layers are not fully evaluated.

Cross-System Identity Resolution

Veza resolves identities across systems through two mechanisms:

Mechanism 1 — Identity array matching: Each LocalUser carries an identities array (typically email addresses). The platform matches these identifiers against IdP principals. For example, an AWS IAM user linked to jdoe@company.com and a Snowflake user linked to the same email are stitched together through their shared IdP identity node.

Mechanism 2 — Property-based mapping configuration: For cases where email matching is insufficient, explicit property matchers can be configured per data source type. This allows resolution by arbitrary properties (e.g., matching a Kerberos principal to a Snowflake username).

Implication for SecurityV0: SecurityV0's current cross-system correlation (Entra ↔ ServiceNow via client_id matching) is more precise but narrower. As we add AWS, we'll need a similar multi-mechanism approach: client_id for OAuth apps, email for human owners, ARN matching for IAM roles, and OIDC subject for federated identities.

Multi-Tenancy

Veza implements per-tenant isolation at multiple layers:

  • Separate Kubernetes namespaces per tenant (control plane + data plane)
  • Per-tenant database instances (graph and relational)
  • Per-tenant TLS certificates from a dedicated certificate authority
  • IAM role scoping per tenant with principal restrictions
  • All inter-service communication uses mTLS (no shared secrets)

Implication for SecurityV0: SecurityV0's current single-tenant design (tenant isolation via X-Tenant-Id header + MongoDB tenant scoping) is adequate for the current stage. Veza's per-tenant infrastructure isolation reflects enterprise SaaS scale requirements that SecurityV0 should plan for but not build prematurely.

Temporal Model

Veza uses point-in-time snapshots (not diff-based):

  • Historical graph snapshots are maintained for "as-of" queries
  • Daily volume snapshots for disaster recovery
  • ClickHouse stores immutable event history for time-series analytics
  • No diff/patch endpoint in the OAA API

Implication for SecurityV0: SecurityV0's temporal model (point-in-time queries with first_seen, last_seen, and drift detection) is already more sophisticated than Veza's snapshot approach. Veza can answer "what did permissions look like on date X" but cannot answer "when exactly did this permission change" without comparing full snapshots. SecurityV0's change detection at the finding level provides finer-grained temporal precision.

What Veza Does NOT Do (SecurityV0 Opportunity)

  • No observed execution evidence (CloudTrail-based proof that a role actually executed)
  • No cross-system execution chains (ServiceNow → AWS → Azure)
  • No ownership decay tracking across systems
  • No Bedrock agent → Lambda action group → external system chain tracing
  • No temporal drift detection ("this role gained AdministratorAccess 47 days ago")
  • No incremental change detection — full snapshot replacement on every ingestion cycle
  • No webhook/event-driven ingestion — all connectors are polling-based

2. Wiz AWS Integration

Architecture

Two deployment modes:

Standard SaaS (most common):

  • Wiz's SaaS AWS account assumes cross-account roles directly into customer accounts
  • CloudFormation StackSets deploy WizAccess-Role to every member account
  • Trust policy: customer role trusts Wiz's AWS account + unique external ID per customer
  • Targets root OU for full coverage, with excludedAccounts / excludedOUs support

Outpost (regulated environments):

  • Customer designates a "scanner account" in their own environment
  • Wiz deploys scanning infrastructure (ECS-like VPC) in the scanner account
  • EBS snapshots created in target accounts, copied to scanner account for analysis
  • Only metadata/results flow back to Wiz SaaS

IAM Permissions

  • Read path: SecurityAudit managed policy + custom read-only policy for extended services
  • Agentless scanning (optional): Write permissions scoped to EBS snapshots: ec2:CreateSnapshot, ec2:CreateVolume, kms:Decrypt
  • Separate diskAnalyzer.scanner.roleARN for the scanning role

Organizations Integration

  • Root OU deployment auto-enrolls new accounts via StackSet propagation
  • Management account not required to run workloads — standard delegated pattern
  • SCP protection recommendations to prevent spoke role tampering

Terraform Resource

resource "wiz_connector_aws" "example" {
auth_params {
customerRoleARN = "arn:aws:iam::ACCOUNT:role/WizAccess-Role"
}
extra_config {
excludedAccounts = ["111111111111"]
excludedOUs = ["ou-xxxx-sandbox"]
}
}

3. CrowdStrike Falcon Cloud Security

Architecture — The "Intermediate Role" Pattern

CrowdStrike uses a unique architecture:

  1. CrowdStrike maintains an intermediate IAM role in their own AWS account
  2. Customer creates a reader role in each account trusting the CrowdStrike intermediate role
  3. External ID is a crypto UUID, auto-generated per customer (not user-configurable)
  4. Reader role name contains a random string to prevent guessability
Customer Account         CrowdStrike Account        CrowdStrike SaaS
┌──────────────┐ ┌───────────────────┐ ┌────────────┐
│ Reader Role │◄───────│ Intermediate Role │◄──────│ Falcon │
│ (per-account)│ trust │ (per-customer) │ │ Platform │
└──────────────┘ └───────────────────┘ └────────────┘

CloudFormation Architecture (Organizations)

Multi-stack deployment:

  1. Root stack in management account — Lambda registers accounts with CrowdStrike API, stores Falcon API creds in Secrets Manager
  2. IOM StackSet — Deploys reader role to all accounts in targeted OUs (SecurityAudit + custom inline)
  3. EventBridge StackSet — Deploys EventBridge rules for real-time IOA (threat detection)
  4. Management EventBridge stack — EventBridge in management account

API-Driven Registration

POST /cloud-connect-cspm-aws/entities/account/v1
Parameters: is_master, organization_id, target_ous[]
Returns: auto-generated iam_role_arn, intermediate_role_arn

Key Differentiator

CrowdStrike's EventBridge integration gives them near-real-time CloudTrail-based detection, not just periodic scanning. SecurityV0 should note this as a pattern for evidence ingestion.


4. Prisma Cloud (Palo Alto Networks)

Architecture

  • Organization management account gets an IAM role trusting Prisma's known SaaS account (arn:aws:iam::188619942792:root)
  • External ID unique per onboarding
  • Member accounts get roles via SERVICE_MANAGED StackSets (delegated administrator mode)
  • Auto-deployment enabled: new accounts in targeted OUs automatically get the role

IAM Permissions

Five functional policies distributed across areas:

  1. Logging, audit events, SSM, KMS
  2. Remediation, compute discovery
  3. Config, database, storage, application services
  4. Foundational (EC2, IAM, Lambda)
  5. Extended (RDS, ECS, EKS)

Prisma is notable for having write permissions for optional auto-remediation — a pattern SecurityV0 explicitly avoids (read-only constraint).

Onboarding API Workflow

  1. GET /cas/v1/features/cloud/aws — fetch supported features
  2. POST /cas/v1/aws_template/presigned_url — get S3-hosted CFT (1-hour validity)
  3. Customer deploys CloudFormation stack
  4. POST /cas/v1/aws_account with role ARN to register

5. Lacework (FortiCNAPP)

Architecture — Customer-Side Scanner Account

Lacework's most notable pattern for SecurityV0:

  1. Customer designates a scanner/security account where Lacework deploys:
    • New VPC + Internet Gateway per region
    • ECS Cluster for running scan tasks
    • S3 bucket for scan results
  2. Management account gets organizations:ListAccounts for enumeration
  3. Snapshot role deployed to all accounts via StackSet
  4. Scanner account assumes snapshot role → creates EBS snapshots → copies to scanner VPC for analysis

IAM Roles (5 total)

  1. agentless_scan_ecs_task_role — scanning operations
  2. agentless_scan_ecs_execution_role — container execution
  3. agentless_scan_ecs_event_role — CloudWatch event triggers
  4. agentless_scan_cross_account_role — trusts Lacework SaaS account
  5. agentless_scan_snapshot_role — deployed per account via StackSet

6. Orca Security

Architecture — Pure SaaS SideScanning

  • Orca's patented SideScanning reads block storage out-of-band from Orca's own infrastructure
  • No agent or scanner in customer VPC
  • Single read-only IAM role per account trusting Orca's SaaS account + external ID
  • Creates EBS snapshots, reads them from Orca's side, deletes after analysis

Permissions (7 policies)

6 customer-managed policies + 1 AWS-managed (SecurityAudit). Two scan modes:

  • Control plane only: Configuration assessment (no snapshots)
  • Full scan (default): Control plane + data plane via EBS snapshots

7. SailPoint / Saviynt (IGA)

SailPoint IdentityNow

Different pattern from CSPM vendors:

  • Virtual Appliance (VA) runs in customer's network, or SaaS connector
  • Authenticates via IAM User access keys (legacy) or IAM role assumption (preferred)
  • Multi-account: AssumeRole fan-out from VA to target accounts
  • No CloudFormation StackSet automation — roles must be created per account
  • CIEM module supports up to 9,000 accounts (inventory) / 3,000 accounts (activity)
  • Requires separate connectors for IAM users vs IAM Identity Center

Saviynt

  • Access keys or IAM roles for authentication
  • Integrates with IAM Identity Center for cross-account identity lifecycle
  • Cross-references Identity Center with IAM Access Analyzer findings
  • No StackSet-based automated multi-account deployment

8. Cross-Account Hub Architecture Patterns

These are the building blocks any AWS security tool uses. SecurityV0 should adopt a two-tier model.

Tier 1: Central Account Services (No Spoke Roles Needed)

AWS ServiceWhat It ProvidesSetup
Organizations APIAccount/OU discovery, SCPs, Resource Control Policies, delegated admin registryRole in management account or delegated admin
AWS Config AggregatorResource inventory across all accounts/regions — IAM users, roles, policies, Lambda, S3, etc.Organization aggregator in delegated admin account. No per-account authorization needed.
Security HubAggregated findings from Access Analyzer, GuardDuty, Inspector, etc.Organization-level with delegated admin
CloudTrail Organization TrailAPI activity across all accounts → central S3Org trail in management/delegated admin → central logging bucket
IAM Access AnalyzerExternal access findings + unused access findingsOrganization-level analyzer in delegated admin
IAM Identity CenterPermission sets, account assignments, federation configCentral service, org-scoped

Critical insight: Config Aggregator alone provides IAM::User, IAM::Role, IAM::Policy, IAM::Group, Lambda::Function, S3::Bucket, and 100+ other resource types across ALL accounts without ANY spoke-side roles. This should be SecurityV0's primary resource inventory source.

Tier 2: Spoke Roles (For Deep IAM Analysis)

Config Aggregator doesn't provide everything. Spoke roles are needed for:

DataAPIWhy Not Available Centrally
Full IAM dumpiam:GetAccountAuthorizationDetailsReturns all users, roles, policies, trust policies in one call per account — most efficient API
Credential reportiam:GenerateCredentialReportAccess key ages, MFA status, last used — per-account only
Service last accessediam:GenerateServiceLastAccessedDetailsWhich services a role actually uses vs what it's allowed — per-account only
Resource-based policiess3:GetBucketPolicy, kms:GetKeyPolicy, lambda:GetPolicyEmbedded in resource, not in Config
Connectivity validationsts:GetCallerIdentityConfirms role assumption works

Spoke Role Trust Policy

{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<CUSTOMER_SECURITY_ACCOUNT>:role/SecurityV0HubRole"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "<TENANT_SPECIFIC_EXTERNAL_ID>",
"aws:PrincipalOrgID": "<ORG_ID>"
}
}
}]
}

Spoke Role Permission Policy

This is an illustrative spoke-role baseline, not a universal superset. Centralized services in the delegated-admin account should handle Organizations, Config Aggregator, Security Hub / Access Analyzer aggregation, and org-trail access. The spoke role should focus on per-account IAM detail, resource-based policies, and service-specific deep reads.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SecurityV0ReadOnly",
"Effect": "Allow",
"Action": [
"iam:List*",
"iam:Get*",
"iam:GenerateCredentialReport",
"iam:GenerateServiceLastAccessedDetails",
"iam:GetServiceLastAccessedDetails",
"s3:GetBucketPolicy",
"s3:GetBucketAcl",
"s3:ListAllMyBuckets",
"lambda:GetPolicy",
"lambda:ListFunctions",
"kms:ListKeys",
"kms:GetKeyPolicy",
"kms:ListAliases",
"ec2:Describe*",
"rds:Describe*",
"ecs:Describe*",
"ecs:List*",
"eks:Describe*",
"eks:List*",
"secretsmanager:ListSecrets",
"secretsmanager:DescribeSecret",
"ssm:DescribeParameters",
"ssm:GetParametersByPath",
"states:List*",
"states:Describe*",
"events:List*",
"events:Describe*",
"bedrock:List*",
"bedrock:Get*",
"sts:GetCallerIdentity"
],
"Resource": "*"
},
{
"Sid": "ExplicitDenyWrites",
"Effect": "Deny",
"Action": [
"iam:Create*",
"iam:Delete*",
"iam:Put*",
"iam:Update*",
"iam:Attach*",
"iam:Detach*",
"iam:Add*",
"iam:Remove*",
"s3:Put*",
"s3:Delete*",
"secretsmanager:GetSecretValue",
"ssm:GetParameter",
"kms:Decrypt",
"kms:Encrypt"
],
"Resource": "*"
}
]
}

Note: The explicit deny ensures the role cannot read secret values or decrypt data, even if attached policies are accidentally broadened.

Delegated Admin Best Practice

Do NOT run SecurityV0's connector in the management account. The management account:

  • Cannot be restricted by SCPs (unlimited power)
  • Is the blast-radius ceiling for the entire organization
  • Should contain no business workloads (AWS best practice)

Instead:

  1. Customer designates a Security Tooling account
  2. Register it as delegated admin for Config, Security Hub, Access Analyzer, GuardDuty
  3. Grant Organizations read-only access via a role in the management account (trust limited to security account)
# Customer registers delegated admin (run in management account)
aws organizations register-delegated-administrator \
--account-id <SECURITY_ACCOUNT_ID> \
--service-principal config-multiaccountsetup.amazonaws.com

aws organizations register-delegated-administrator \
--account-id <SECURITY_ACCOUNT_ID> \
--service-principal securityhub.amazonaws.com

aws organizations register-delegated-administrator \
--account-id <SECURITY_ACCOUNT_ID> \
--service-principal access-analyzer.amazonaws.com

Operational Gotchas

IssueDetailMitigation
STS rate limits~100 TPS per account for sts:AssumeRole. Scanning 500 accounts requires throttling.Exponential backoff, parallel with concurrency cap, credential caching
Chained session capRole A → Role B chained sessions are always capped at 1 hour regardless of MaxSessionDurationDon't chain roles; assume directly from hub to spoke
Credential cachingEvery AssumeRole call returns temp creds valid for 1-12 hoursCache and reuse; don't call per API request
StackSet driftIf someone deletes a spoke role manually, StackSet doesn't auto-repairEnable drift detection, alert on role absence
Config Aggregator delayResource changes take minutes to propagate to aggregatorNot suitable for real-time alerting; use for inventory
Config recorder costCustomer pays per configuration item recorded per regionDocument cost impact; recommend recording specific resource types
Cross-partitionCannot AssumeRole from aws to aws-cn or aws-us-govSeparate connector instances per partition
Delegated admin limitsEach service has 1-5 delegated admin slots. Customer may already use them for Wiz/CrowdStrike.Check availability during onboarding; fall back to management account role if needed
Regional STS endpointsGlobal STS endpoint has higher latency and single-region availabilityUse regional endpoints (sts.us-east-1.amazonaws.com); must be explicitly activated

9. Architectural Patterns Summary

Pattern A: Pure SaaS Cross-Account (Wiz, CrowdStrike, Prisma, Orca, Veza)

Vendor's SaaS AWS account assumes directly into customer accounts. Most common, simplest for customers.

Vendor SaaS Account  ──► sts:AssumeRole ──►  Customer Account Role

ExternalId + trust policy

Pattern B: Customer-Side Hub Account (Lacework, Wiz Outpost)

Customer designates a security account where scanning runs. Only metadata flows to vendor.

Vendor SaaS  ◄──metadata──  Customer Hub Account  ──► sts:AssumeRole ──►  Spoke Accounts

scanning infra (ECS/VPC)

Pattern C: IGA Connector (SailPoint, Saviynt)

Virtual Appliance or direct SaaS connector with per-account role assumption. No StackSets.

SailPoint VA (customer VPC)  ──► sts:AssumeRole ──►  Target Account Role
or
SailPoint SaaS ──► access keys ──► IAM User (legacy)

Pattern A+ — SaaS cross-account with centralized AWS services:

SecurityV0 SaaS
──► sts:AssumeRole ──► Customer Security Account (delegated admin)

├── Config Aggregator (resource inventory, all accounts)
├── Security Hub (Access Analyzer findings, all accounts)
├── CloudTrail Org Trail (S3 bucket, all accounts)
├── Organizations API (account/OU discovery)

└── sts:AssumeRole ──► Spoke Account Roles

├── GetAccountAuthorizationDetails
├── GenerateCredentialReport
├── Resource-based policies
└── GenerateServiceLastAccessedDetails

This two-tier approach minimizes the number of spoke-role API calls while maximizing data coverage.


10. What SecurityV0 Should Learn from Each Competitor

VendorLesson for SecurityV0
VezaOAA canonical permission mapping (DataRead/Write/etc.) is well-designed — our SCIM/OAA export should stay compatible. Their "Explain Assumed Roles" validates our execution chain concept but they lack observed evidence. Their multi-store architecture (Neo4j for graph + PostgreSQL for ops + ClickHouse for analytics + Kafka for events) is a proven pattern at scale. Their full-replacement connector model (no delta API) is simpler but wasteful — SecurityV0's change detection is already more sophisticated. Their cross-system identity resolution (email matching + property-based mapping) is a pattern we'll need as we add AWS.
WizStackSet deployment with OU exclusion is the gold standard for onboarding UX. Their Terraform provider shows how infrastructure teams want to manage connectors.
CrowdStrikeEventBridge integration for near-real-time CloudTrail events is the best evidence ingestion pattern. Their intermediate role pattern adds a security layer (customer never trusts vendor directly).
Prisma CloudSERVICE_MANAGED StackSets (delegated admin mode) avoid needing management account access for deployment. Their 5-policy split shows how to organize permissions logically.
LaceworkCustomer-side scanner account is the right pattern for regulated customers who cannot allow SaaS to touch their data. SecurityV0 should support this as an optional mode.
SailPointCIEM module's 9,000-account scale limit and 150-CloudTrail-ARN limit show what enterprise scale looks like. Design for this from day one.

11. What SecurityV0 Should NOT Copy

PatternWhy Not
Write-back / remediation (Prisma, Veza)SecurityV0's read-only constraint is a feature — zero change-management friction
Agent deployment (CrowdStrike Falcon agent)Agentless is simpler and faster to deploy. No agents.
EBS snapshot scanning (Wiz, Lacework, Orca)SecurityV0 is not a vulnerability scanner or CSPM. We read metadata and evidence, not disk images.
Per-account IAM user with access keys (SailPoint legacy)Always use AssumeRole with temp credentials. Never long-lived keys.
Full-replacement ingestion (Veza OAA)Veza replaces the entire data source on every push — no delta API. SecurityV0's change detection on findings already avoids unnecessary evidence pack rebuilds. Maintain incremental processing.
Per-tenant infrastructure isolation (Veza)Veza runs separate K8s namespaces, databases, and TLS CAs per tenant. This is enterprise SaaS at scale. SecurityV0's X-Tenant-Id + MongoDB scoping is adequate now — don't over-engineer multi-tenancy prematurely.

Sources (Veza Platform Architecture)