SKILLS/performing-cloud-asset-inventory-with-cartography/SKILL.md
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.
npx skillsauth add pinkpixel-dev/skills-collection-2 performing-cloud-asset-inventory-with-cartographyInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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.
# Install Cartography
pip install cartography
# Verify installation
cartography --help
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
# Sync AWS account data to Neo4j
cartography \
--neo4j-uri bolt://localhost:7687 \
--neo4j-user neo4j \
--neo4j-password-env-var NEO4J_PASSWORD
cartography \
--neo4j-uri bolt://localhost:7687 \
--neo4j-user neo4j \
--neo4j-password-env-var NEO4J_PASSWORD \
--aws-sync-all-profiles
cartography \
--neo4j-uri bolt://localhost:7687 \
--neo4j-user neo4j \
--neo4j-password-env-var NEO4J_PASSWORD \
--gcp-requested-syncs compute iam storage
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
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
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
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
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
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
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
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
# 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
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:
AWSAccount, GCPProject, AzureSubscriptionEC2Instance, S3Bucket, RDSInstance, AWSLambdaAWSUser, AWSRole, AWSGroup, AWSPolicyEC2SecurityGroup, EC2Subnet, AWSVpcGCPInstance, GCSBucket, GCPRoleRESOURCE: Account owns resourcePOLICY: Principal has policy attachedSTS_ASSUME_ROLE_ALLOWS: Principal can assume roleMEMBER_OF_EC2_SECURITY_GROUP: Instance belongs to SGTRUSTS_AWS_PRINCIPAL: Cross-account trusttools
Perform lateral movement across Windows networks using WMI-based remote execution techniques including Impacket wmiexec.py, CrackMapExec, and native WMI commands for stealthy post-exploitation during red team engagements.
data-ai
Detects lateral movement techniques including Pass-the-Hash, PsExec, WMI execution, RDP pivoting, and SMB-based spreading using SIEM correlation of Windows event logs, network flow data, and endpoint telemetry mapped to MITRE ATT&CK Lateral Movement (TA0008) techniques.
tools
Kubernetes penetration testing systematically evaluates cluster security by simulating attacker techniques against the API server, kubelet, etcd, pods, RBAC, network policies, and secrets. Using tools
testing
Assess the security posture of Kubernetes etcd clusters by evaluating encryption at rest, TLS configuration, access controls, backup encryption, and network isolation.