Asi performing-cloud-asset-inventory-with-cartography
Perform comprehensive cloud asset inventory and relationship mapping using Cartography to build a Neo4j security graph of infrastructure assets, IAM permissions, and attack paths across AWS, GCP, and Azure.
install
source · Clone the upstream repo
git clone https://github.com/plurigrid/asi
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/asi/skills/performing-cloud-asset-inventory-with-cartography" ~/.claude/skills/plurigrid-asi-performing-cloud-asset-inventory-with-cartography && rm -rf "$T"
manifest:
plugins/asi/skills/performing-cloud-asset-inventory-with-cartography/SKILL.mdsource content
Performing Cloud Asset Inventory with Cartography
Overview
Cartography is a CNCF sandbox project (originally created at Lyft) that consolidates infrastructure assets and their relationships into a Neo4j graph database. It queries cloud APIs to discover resources, maps relationships between them, and enables security teams to identify attack paths, generate asset reports, and find areas for security improvement. The graph model reveals hidden connections such as IAM permission chains, network paths, and cross-account trust relationships.
When to Use
- When conducting security assessments that involve performing cloud asset inventory with cartography
- When following incident response procedures for related security events
- When performing scheduled security testing or auditing activities
- When validating security controls through hands-on testing
Prerequisites
- Python 3.8+
- Neo4j 4.x or 5.x database
- Cloud provider credentials (AWS, GCP, Azure)
- Docker (optional, for Neo4j deployment)
- Minimum 4GB RAM for Neo4j, more for large environments
Installation
# Install Cartography pip install cartography # Verify installation cartography --help
Deploy Neo4j with Docker
docker run -d \ --name neo4j \ -p 7474:7474 -p 7687:7687 \ -e NEO4J_AUTH=neo4j/changethispassword \ -e NEO4J_PLUGINS='["apoc"]' \ -v neo4j_data:/data \ neo4j:5-community
Running Cartography
Basic AWS Sync
# Sync AWS account data to Neo4j cartography \ --neo4j-uri bolt://localhost:7687 \ --neo4j-user neo4j \ --neo4j-password-env-var NEO4J_PASSWORD
Sync specific AWS modules
cartography \ --neo4j-uri bolt://localhost:7687 \ --neo4j-user neo4j \ --neo4j-password-env-var NEO4J_PASSWORD \ --aws-sync-all-profiles
GCP Sync
cartography \ --neo4j-uri bolt://localhost:7687 \ --neo4j-user neo4j \ --neo4j-password-env-var NEO4J_PASSWORD \ --gcp-requested-syncs compute iam storage
Security-Focused Cypher Queries
Find all S3 buckets with public access
MATCH (b:S3Bucket) WHERE b.anonymous_access = true OR b.anonymous_actions IS NOT NULL RETURN b.name, b.anonymous_actions, b.region, b.arn ORDER BY b.name
Identify IAM users with admin policies
MATCH (user:AWSUser)-[:POLICY]->(policy:AWSPolicy) WHERE policy.name = 'AdministratorAccess' OR policy.arn CONTAINS 'AdministratorAccess' RETURN user.name, user.arn, policy.name, user.password_last_used
Find EC2 instances exposed to internet
MATCH (instance:EC2Instance)-[:MEMBER_OF_EC2_SECURITY_GROUP]->(sg:EC2SecurityGroup) -[:MEMBER_OF_EC2_SECURITY_GROUP_RULE]->(rule:IpRule) WHERE rule.fromport <= 22 AND rule.toport >= 22 AND rule.protocol IN ['tcp', '-1'] AND '0.0.0.0/0' IN rule.ipranges RETURN instance.instanceid, instance.publicipaddress, sg.groupid, sg.name
Discover cross-account trust relationships
MATCH (role:AWSRole)-[:TRUSTS_AWS_PRINCIPAL]->(principal:AWSPrincipal) WHERE principal.arn CONTAINS ':root' AND NOT principal.arn CONTAINS role.accountid RETURN role.arn, role.name, principal.arn AS trusted_account ORDER BY role.name
Find attack path from public EC2 to sensitive S3
MATCH path = (instance:EC2Instance)-[:STS_ASSUME_ROLE_ALLOWS|MEMBER_OF_EC2_SECURITY_GROUP| POLICY|INSTANCE_PROFILE*1..5]->(bucket:S3Bucket) WHERE instance.publicipaddress IS NOT NULL AND bucket.name CONTAINS 'sensitive' RETURN path LIMIT 25
Identify unused IAM roles
MATCH (role:AWSRole) WHERE role.last_used IS NULL OR role.last_used < datetime().epochMillis - (90 * 24 * 60 * 60 * 1000) RETURN role.name, role.arn, role.last_used ORDER BY role.last_used
Find Lambda functions with overprivileged roles
MATCH (func:AWSLambda)-[:STS_ASSUME_ROLE_ALLOWS]->(role:AWSRole)-[:POLICY]->(policy:AWSPolicy) WHERE policy.name = 'AdministratorAccess' RETURN func.name, func.arn, role.name, policy.name
Network path analysis
MATCH (vpc:AWSVpc)-[:RESOURCE]->(subnet:EC2Subnet)-[:MEMBER_OF_SUBNET]->(instance:EC2Instance) WHERE instance.publicipaddress IS NOT NULL RETURN vpc.id, subnet.subnetid, subnet.cidr_block, instance.instanceid, instance.publicipaddress, instance.state
Scheduling Regular Syncs
Cron-based sync
# Add to crontab - sync every 6 hours 0 */6 * * * /usr/local/bin/cartography \ --neo4j-uri bolt://localhost:7687 \ --neo4j-user neo4j \ --neo4j-password-env-var NEO4J_PASSWORD \ >> /var/log/cartography/sync.log 2>&1
Docker Compose deployment
version: '3.8' services: neo4j: image: neo4j:5-community ports: - "7474:7474" - "7687:7687" environment: NEO4J_AUTH: neo4j/securepwd123 NEO4J_PLUGINS: '["apoc"]' NEO4J_dbms_memory_heap_max__size: 4G volumes: - neo4j_data:/data cartography: image: ghcr.io/cartography-cncf/cartography:latest depends_on: - neo4j environment: NEO4J_PASSWORD: securepwd123 AWS_DEFAULT_REGION: us-east-1 command: > --neo4j-uri bolt://neo4j:7687 --neo4j-user neo4j --neo4j-password-env-var NEO4J_PASSWORD volumes: neo4j_data:
Data Model Overview
Key Node Types
,AWSAccount
,GCPProjectAzureSubscription
,EC2Instance
,S3Bucket
,RDSInstanceAWSLambda
,AWSUser
,AWSRole
,AWSGroupAWSPolicy
,EC2SecurityGroup
,EC2SubnetAWSVpc
,GCPInstance
,GCSBucketGCPRole
Key Relationship Types
: Account owns resourceRESOURCE
: Principal has policy attachedPOLICY
: Principal can assume roleSTS_ASSUME_ROLE_ALLOWS
: Instance belongs to SGMEMBER_OF_EC2_SECURITY_GROUP
: Cross-account trustTRUSTS_AWS_PRINCIPAL
References
- Cartography GitHub: https://github.com/cartography-cncf/cartography
- Cartography Documentation: https://cartography.dev
- CNCF Sandbox Project
- Neo4j Cypher Query Language Reference