Skip to content

[Tier 5] Cloud IAM posture: AWS / Azure / GCP IAM connectors + rule pack #57

@dcoln25-writer

Description

@dcoln25-writer

Problem

Aperio is pure SaaS posture today. The single biggest gap relative to the broader security-posture market is cloud IAM — AWS, Azure, GCP — where the JML / privilege-sprawl / over-permissive-role problems are even more acute than in SaaS, and where every buyer evaluating an SSPM is also asking "do you also do CIEM?"

Adding cloud IAM posture turns Aperio from "SSPM with optional adjacencies" into a unified identity & access posture platform spanning SaaS + cloud. The Person model from #45 already anticipates this: cloud principals are just another SaasIdentity.kind once the model permits it.

Goals

  1. AWS, Azure, GCP IAM connectors that inventory principals, roles, policies, and access grants.
  2. Detection rules for the highest-signal cloud IAM postures (over-permissive roles, dormant access keys, cross-account trust sprawl, public S3 buckets, public storage objects).
  3. Cross-cloud Person linkage — a Person row (from Identity-first correlation, lifecycle & non-human inventory (ISPM) #45) ties their Okta SSO identity to their AWS IAM principal to their Azure AD object, and we surface the unified access surface.
  4. Cloud IAM remediation actions through the existing AgentProposal gate (revoke key, detach policy, disable principal).

Non-goals

  • Not building full CSPM (cloud security posture) covering compute, network, encryption — that's a much larger product. v1 is IAM only.
  • Not handling every AWS service — start with IAM + S3 + STS, expand later.
  • Not running scans inside the customer's cloud account — pure read-only API caller from Aperio.

Proposed design

Schema extensions

Add three new providers to the existing SaaSProvider enum:

enum SaaSProvider {
  // ... existing ...
  AWS_IAM
  AZURE_AD
  GCP_IAM
}

SaasIdentity already supports SERVICE_ACCOUNT kind — no schema change needed for cloud service principals; just emit them with the right kind.

SecurityAsset.type gains:

enum SecurityAssetType {
  // ... existing ...
  CLOUD_ACCOUNT
  CLOUD_BUCKET
  CLOUD_ROLE
  CLOUD_KEY
}

Connector implementations

Connector Auth model What it reads
AWS IAM Cross-account IAM role (customer-deployed CloudFormation stack provisions a read-only role; Aperio assumes via STS) iam:ListUsers, iam:ListRoles, iam:ListAccessKeys, iam:GetAccountAuthorizationDetails, s3:GetBucketAcl, s3:GetBucketPublicAccessBlock, s3:GetBucketPolicy, sts:GetCallerIdentity, CloudTrail for activity baselines (UEBA #12)
Azure AD / Entra ID Service principal w/ application permissions (Directory.Read.All, RoleManagement.Read.Directory, AuditLog.Read.All) Graph /users, /servicePrincipals, /roleAssignments, /auditLogs/directoryAudits
GCP IAM Service account w/ workload identity federation or JSON key iam.googleapis.com for service accounts, cloudresourcemanager.googleapis.com for IAM policies, storage.googleapis.com for bucket ACLs

Each connector ships as a Go package under internal/connectors/<provider>/ mirroring the Google Workspace pattern in internal/bootstrap/google_oauth.go.

Day-one rule pack (cloud IAM)

Rule Severity Trigger
aws.public_s3_bucket CRITICAL Bucket ACL or policy permits public-read / * principal
aws.iam_user_no_mfa HIGH IAM user with console access and no MFA
aws.iam_root_access_key_active CRITICAL Root account has an active access key
aws.iam_dormant_access_key MEDIUM Access key unused > 90 days
aws.iam_role_admin_policy HIGH Role grants AdministratorAccess to wide trust principal
aws.cross_account_trust_external_account HIGH Role trust policy permits a principal in an unknown account ID
azure.privileged_role_no_pim HIGH Permanent privileged role assignment without PIM eligibility
azure.guest_user_admin_role CRITICAL Guest (B2B) user with admin role
azure.app_admin_consent_high_scope HIGH App granted admin consent for Mail.Read.All / Sites.FullControl.All (overlaps with M365 #48)
gcp.public_storage_bucket CRITICAL allUsers / allAuthenticatedUsers granted on bucket
gcp.service_account_user_managed_key HIGH Service account has user-managed keys (vs. workload-identity)
gcp.project_owner_external HIGH roles/owner granted to external identity

Cross-cloud Person linkage

When the identity linker (from #45) runs, it also joins:

  • AWS IAM users to Person.primaryEmail via email tag or username pattern.
  • Azure AD users to Person.externalEmployeeId (the canonical Entra ID → HRIS bridge).
  • GCP IAM members to Person.primaryEmail.

Once linked, the /identities/<personId> page from #45 shows cloud access alongside SaaS access — unified. This is the moment Aperio becomes a CIEM.

Remediation actions

Add to remediationActionDefinitions (internal/bootstrap/remediation_actions.go):

Provider Action Class
AWS_IAM aws.disable_access_key real-provider
AWS_IAM aws.detach_user_policy real-provider
AWS_IAM aws.block_s3_public_access real-provider
AZURE_AD azure.revoke_role_assignment real-provider
AZURE_AD azure.disable_user real-provider
GCP_IAM gcp.remove_iam_binding real-provider
GCP_IAM gcp.disable_service_account_key real-provider

All require AgentProposal.APPROVED.

Phasing

Phase Scope
P1 AWS IAM connector + top 4 AWS rules (public S3, IAM user no MFA, root access key, dormant access key); CloudFormation template for the read-only role
P2 Azure AD / Entra ID connector + 3 Azure rules; cross-cloud Person linkage in the identity linker
P3 GCP IAM connector + 3 GCP rules
P4 Remediation handlers for all three clouds; CloudTrail/Activity-log ingestion to feed UEBA #12

Open questions

  • AWS cross-account auth model — managed CloudFormation stack vs. customer-supplied access key? Stack is more user-friendly but couples deploy lifecycle.
  • Org-level vs. account-level granularity for AWS (does Aperio scan one account or assume role across an entire AWS Org)?
  • For Azure, MS Graph rate limits are brutal — likely need a separate background-sync cadence.
  • Public-bucket detection has well-known FP cases (CloudFront origins, intentionally public sites) — should we ship a builtin allowlist pattern?

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    cloud-iamCloud IAM posture (AWS / Azure / GCP)connectorsConnector pipeline and rule packstier-5-surface-expansionTier 5: expand the surfaces Aperio covers

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions