cartography 0.93.0__tar.gz → 0.94.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cartography might be problematic. Click here for more details.

Files changed (354) hide show
  1. {cartography-0.93.0/cartography.egg-info → cartography-0.94.0}/PKG-INFO +1 -1
  2. {cartography-0.93.0 → cartography-0.94.0}/README.md +3 -1
  3. {cartography-0.93.0 → cartography-0.94.0}/cartography/cli.py +42 -0
  4. {cartography-0.93.0 → cartography-0.94.0}/cartography/config.py +12 -0
  5. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/scoped_analysis/semgrep_sca_risk_analysis.json +13 -13
  6. {cartography-0.93.0 → cartography-0.94.0}/cartography/graph/job.py +8 -1
  7. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/inspector.py +12 -1
  8. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/permission_relationships.py +6 -2
  9. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/github/teams.py +41 -10
  10. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/kandji/__init__.py +1 -1
  11. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/semgrep/findings.py +106 -59
  12. cartography-0.94.0/cartography/intel/snipeit/__init__.py +30 -0
  13. cartography-0.94.0/cartography/intel/snipeit/asset.py +74 -0
  14. cartography-0.94.0/cartography/intel/snipeit/user.py +75 -0
  15. cartography-0.94.0/cartography/intel/snipeit/util.py +35 -0
  16. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/semgrep/findings.py +3 -1
  17. cartography-0.94.0/cartography/models/snipeit/asset.py +81 -0
  18. cartography-0.94.0/cartography/models/snipeit/tenant.py +17 -0
  19. cartography-0.94.0/cartography/models/snipeit/user.py +49 -0
  20. cartography-0.94.0/cartography/py.typed +0 -0
  21. {cartography-0.93.0 → cartography-0.94.0}/cartography/sync.py +2 -0
  22. {cartography-0.93.0 → cartography-0.94.0/cartography.egg-info}/PKG-INFO +1 -1
  23. {cartography-0.93.0 → cartography-0.94.0}/cartography.egg-info/SOURCES.txt +9 -1
  24. {cartography-0.93.0 → cartography-0.94.0}/setup.py +1 -1
  25. {cartography-0.93.0 → cartography-0.94.0}/LICENSE +0 -0
  26. {cartography-0.93.0 → cartography-0.94.0}/NOTICE +0 -0
  27. {cartography-0.93.0 → cartography-0.94.0}/cartography/__init__.py +0 -0
  28. {cartography-0.93.0 → cartography-0.94.0}/cartography/__main__.py +0 -0
  29. {cartography-0.93.0 → cartography-0.94.0}/cartography/client/__init__.py +0 -0
  30. {cartography-0.93.0 → cartography-0.94.0}/cartography/client/aws/__init__.py +0 -0
  31. {cartography-0.93.0 → cartography-0.94.0}/cartography/client/aws/iam.py +0 -0
  32. {cartography-0.93.0 → cartography-0.94.0}/cartography/client/core/__init__.py +0 -0
  33. {cartography-0.93.0 → cartography-0.94.0}/cartography/client/core/tx.py +0 -0
  34. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/__init__.py +0 -0
  35. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/indexes.cypher +0 -0
  36. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/__init__.py +0 -0
  37. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/analysis/__init__.py +0 -0
  38. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/analysis/aws_ec2_asset_exposure.json +0 -0
  39. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/analysis/aws_ec2_iaminstance.json +0 -0
  40. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/analysis/aws_ec2_iaminstanceprofile.json +0 -0
  41. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/analysis/aws_ec2_keypair_analysis.json +0 -0
  42. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/analysis/aws_eks_asset_exposure.json +0 -0
  43. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/analysis/aws_foreign_accounts.json +0 -0
  44. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/analysis/aws_lambda_ecr.json +0 -0
  45. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/analysis/aws_s3acl_analysis.json +0 -0
  46. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/analysis/gcp_compute_asset_inet_exposure.json +0 -0
  47. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/analysis/gcp_gke_asset_exposure.json +0 -0
  48. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/analysis/gcp_gke_basic_auth.json +0 -0
  49. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/analysis/gsuite_human_link.json +0 -0
  50. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/__init__.py +0 -0
  51. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_account_cleanup.json +0 -0
  52. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_apigateway_details.json +0 -0
  53. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_dns_cleanup.json +0 -0
  54. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_account_access_key_cleanup.json +0 -0
  55. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_apigateway_cleanup.json +0 -0
  56. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_config_cleanup.json +0 -0
  57. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_ec2_launch_configurations_cleanup.json +0 -0
  58. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_ec2_security_groupinfo_cleanup.json +0 -0
  59. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_ecr_cleanup.json +0 -0
  60. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_ecs_cleanup.json +0 -0
  61. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_elastic_ip_addresses_cleanup.json +0 -0
  62. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_elasticache_cleanup.json +0 -0
  63. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_es_cleanup.json +0 -0
  64. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_groups_cleanup.json +0 -0
  65. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_groups_membership_cleanup.json +0 -0
  66. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_groups_policy_cleanup.json +0 -0
  67. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_internet_gateways_cleanup.json +0 -0
  68. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_kms_cleanup.json +0 -0
  69. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_lambda_cleanup.json +0 -0
  70. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_principals_cleanup.json +0 -0
  71. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_rds_clusters_cleanup.json +0 -0
  72. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_rds_instances_cleanup.json +0 -0
  73. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_rds_snapshots_cleanup.json +0 -0
  74. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_redshift_clusters_cleanup.json +0 -0
  75. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_reserved_instances_cleanup.json +0 -0
  76. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_roles_cleanup.json +0 -0
  77. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_roles_policy_cleanup.json +0 -0
  78. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_s3_acl_cleanup.json +0 -0
  79. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_s3_buckets_cleanup.json +0 -0
  80. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_secrets_cleanup.json +0 -0
  81. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_securityhub_cleanup.json +0 -0
  82. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_snapshots_cleanup.json +0 -0
  83. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_sqs_queues_cleanup.json +0 -0
  84. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_tags_cleanup.json +0 -0
  85. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_tgw_cleanup.json +0 -0
  86. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_users_cleanup.json +0 -0
  87. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_vpc_cleanup.json +0 -0
  88. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_import_vpc_peering_cleanup.json +0 -0
  89. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_ingest_ec2_auto_scaling_groups_cleanup.json +0 -0
  90. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_ingest_load_balancers_cleanup.json +0 -0
  91. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_ingest_load_balancers_v2_cleanup.json +0 -0
  92. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_ingest_subnets_cleanup.json +0 -0
  93. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_kms_details.json +0 -0
  94. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_post_ingestion_principals_cleanup.json +0 -0
  95. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/aws_s3_details.json +0 -0
  96. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/azure_cosmosdb_cassandra_keyspace_cleanup.json +0 -0
  97. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/azure_cosmosdb_cors_details.json +0 -0
  98. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/azure_cosmosdb_mongodb_database_cleanup.json +0 -0
  99. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/azure_cosmosdb_sql_database_cleanup.json +0 -0
  100. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/azure_cosmosdb_table_resources_cleanup.json +0 -0
  101. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/azure_database_account_cleanup.json +0 -0
  102. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/azure_import_disks_cleanup.json +0 -0
  103. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/azure_import_snapshots_cleanup.json +0 -0
  104. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/azure_import_virtual_machines_cleanup.json +0 -0
  105. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/azure_sql_server_cleanup.json +0 -0
  106. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/azure_storage_account_cleanup.json +0 -0
  107. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/azure_subscriptions_cleanup.json +0 -0
  108. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/azure_tenant_cleanup.json +0 -0
  109. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/crowdstrike_import_cleanup.json +0 -0
  110. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/crxcavator_import_cleanup.json +0 -0
  111. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/digitalocean_droplet_cleanup.json +0 -0
  112. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/digitalocean_project_cleanup.json +0 -0
  113. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/gcp_compute_firewall_cleanup.json +0 -0
  114. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/gcp_compute_forwarding_rules_cleanup.json +0 -0
  115. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/gcp_compute_instance_cleanup.json +0 -0
  116. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/gcp_compute_vpc_cleanup.json +0 -0
  117. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/gcp_compute_vpc_subnet_cleanup.json +0 -0
  118. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/gcp_crm_folder_cleanup.json +0 -0
  119. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/gcp_crm_organization_cleanup.json +0 -0
  120. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/gcp_crm_project_cleanup.json +0 -0
  121. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/gcp_dns_cleanup.json +0 -0
  122. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/gcp_gke_cluster_cleanup.json +0 -0
  123. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/gcp_storage_bucket_cleanup.json +0 -0
  124. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/github_repos_cleanup.json +0 -0
  125. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/github_users_cleanup.json +0 -0
  126. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/gsuite_ingest_groups_cleanup.json +0 -0
  127. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/gsuite_ingest_users_cleanup.json +0 -0
  128. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/jamf_import_computers_cleanup.json +0 -0
  129. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/kubernetes_import_cleanup.json +0 -0
  130. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/oci_import_compartments_cleanup.json +0 -0
  131. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/oci_import_groups_cleanup.json +0 -0
  132. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/oci_import_groups_membership_cleanup.json +0 -0
  133. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/oci_import_policies_cleanup.json +0 -0
  134. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/oci_import_users_cleanup.json +0 -0
  135. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/oci_tenancy_cleanup.json +0 -0
  136. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/okta_groups_cleanup.json +0 -0
  137. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/okta_import_cleanup.json +0 -0
  138. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/cleanup/pagerduty_import_cleanup.json +0 -0
  139. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/jobs/scoped_analysis/__init__.py +0 -0
  140. {cartography-0.93.0 → cartography-0.94.0}/cartography/data/permission_relationships.yaml +0 -0
  141. {cartography-0.93.0 → cartography-0.94.0}/cartography/driftdetect/__init__.py +0 -0
  142. {cartography-0.93.0 → cartography-0.94.0}/cartography/driftdetect/__main__.py +0 -0
  143. {cartography-0.93.0 → cartography-0.94.0}/cartography/driftdetect/add_shortcut.py +0 -0
  144. {cartography-0.93.0 → cartography-0.94.0}/cartography/driftdetect/cli.py +0 -0
  145. {cartography-0.93.0 → cartography-0.94.0}/cartography/driftdetect/config.py +0 -0
  146. {cartography-0.93.0 → cartography-0.94.0}/cartography/driftdetect/detect_deviations.py +0 -0
  147. {cartography-0.93.0 → cartography-0.94.0}/cartography/driftdetect/get_states.py +0 -0
  148. {cartography-0.93.0 → cartography-0.94.0}/cartography/driftdetect/model.py +0 -0
  149. {cartography-0.93.0 → cartography-0.94.0}/cartography/driftdetect/reporter.py +0 -0
  150. {cartography-0.93.0 → cartography-0.94.0}/cartography/driftdetect/serializers.py +0 -0
  151. {cartography-0.93.0 → cartography-0.94.0}/cartography/driftdetect/shortcut.py +0 -0
  152. {cartography-0.93.0 → cartography-0.94.0}/cartography/driftdetect/storage.py +0 -0
  153. {cartography-0.93.0 → cartography-0.94.0}/cartography/driftdetect/util.py +0 -0
  154. {cartography-0.93.0 → cartography-0.94.0}/cartography/graph/__init__.py +0 -0
  155. {cartography-0.93.0 → cartography-0.94.0}/cartography/graph/cleanupbuilder.py +0 -0
  156. {cartography-0.93.0 → cartography-0.94.0}/cartography/graph/context.py +0 -0
  157. {cartography-0.93.0 → cartography-0.94.0}/cartography/graph/querybuilder.py +0 -0
  158. {cartography-0.93.0 → cartography-0.94.0}/cartography/graph/statement.py +0 -0
  159. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/__init__.py +0 -0
  160. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/analysis.py +0 -0
  161. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/__init__.py +0 -0
  162. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/apigateway.py +0 -0
  163. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/config.py +0 -0
  164. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/dynamodb.py +0 -0
  165. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/__init__.py +0 -0
  166. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/auto_scaling_groups.py +0 -0
  167. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/elastic_ip_addresses.py +0 -0
  168. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/images.py +0 -0
  169. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/instances.py +0 -0
  170. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/internet_gateways.py +0 -0
  171. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/key_pairs.py +0 -0
  172. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/launch_templates.py +0 -0
  173. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/load_balancer_v2s.py +0 -0
  174. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/load_balancers.py +0 -0
  175. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/network_interfaces.py +0 -0
  176. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/reserved_instances.py +0 -0
  177. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/security_groups.py +0 -0
  178. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/snapshots.py +0 -0
  179. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/subnets.py +0 -0
  180. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/tgw.py +0 -0
  181. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/util.py +0 -0
  182. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/volumes.py +0 -0
  183. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/vpc.py +0 -0
  184. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ec2/vpc_peerings.py +0 -0
  185. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ecr.py +0 -0
  186. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ecs.py +0 -0
  187. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/eks.py +0 -0
  188. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/elasticache.py +0 -0
  189. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/elasticsearch.py +0 -0
  190. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/emr.py +0 -0
  191. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/iam.py +0 -0
  192. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/kms.py +0 -0
  193. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/lambda_function.py +0 -0
  194. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/organizations.py +0 -0
  195. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/rds.py +0 -0
  196. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/redshift.py +0 -0
  197. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/resourcegroupstaggingapi.py +0 -0
  198. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/resources.py +0 -0
  199. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/route53.py +0 -0
  200. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/s3.py +0 -0
  201. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/secretsmanager.py +0 -0
  202. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/securityhub.py +0 -0
  203. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/sqs.py +0 -0
  204. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/ssm.py +0 -0
  205. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/util/__init__.py +0 -0
  206. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/util/arns.py +0 -0
  207. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/aws/util/common.py +0 -0
  208. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/azure/__init__.py +0 -0
  209. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/azure/compute.py +0 -0
  210. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/azure/cosmosdb.py +0 -0
  211. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/azure/sql.py +0 -0
  212. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/azure/storage.py +0 -0
  213. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/azure/subscription.py +0 -0
  214. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/azure/tenant.py +0 -0
  215. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/azure/util/__init__.py +0 -0
  216. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/azure/util/credentials.py +0 -0
  217. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/bigfix/__init__.py +0 -0
  218. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/bigfix/computers.py +0 -0
  219. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/create_indexes.py +0 -0
  220. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/crowdstrike/__init__.py +0 -0
  221. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/crowdstrike/endpoints.py +0 -0
  222. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/crowdstrike/spotlight.py +0 -0
  223. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/crowdstrike/util.py +0 -0
  224. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/crxcavator/__init__.py +0 -0
  225. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/crxcavator/crxcavator.py +0 -0
  226. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/cve/__init__.py +0 -0
  227. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/cve/feed.py +0 -0
  228. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/digitalocean/__init__.py +0 -0
  229. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/digitalocean/compute.py +0 -0
  230. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/digitalocean/management.py +0 -0
  231. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/digitalocean/platform.py +0 -0
  232. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/dns.py +0 -0
  233. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/duo/__init__.py +0 -0
  234. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/duo/api_host.py +0 -0
  235. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/duo/endpoints.py +0 -0
  236. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/duo/groups.py +0 -0
  237. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/duo/phones.py +0 -0
  238. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/duo/tokens.py +0 -0
  239. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/duo/users.py +0 -0
  240. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/duo/web_authn_credentials.py +0 -0
  241. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/gcp/__init__.py +0 -0
  242. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/gcp/compute.py +0 -0
  243. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/gcp/crm.py +0 -0
  244. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/gcp/dns.py +0 -0
  245. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/gcp/gke.py +0 -0
  246. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/gcp/storage.py +0 -0
  247. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/github/__init__.py +0 -0
  248. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/github/repos.py +0 -0
  249. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/github/users.py +0 -0
  250. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/github/util.py +0 -0
  251. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/gsuite/__init__.py +0 -0
  252. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/gsuite/api.py +0 -0
  253. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/jamf/__init__.py +0 -0
  254. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/jamf/computers.py +0 -0
  255. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/jamf/util.py +0 -0
  256. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/kandji/devices.py +0 -0
  257. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/kubernetes/__init__.py +0 -0
  258. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/kubernetes/namespaces.py +0 -0
  259. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/kubernetes/pods.py +0 -0
  260. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/kubernetes/secrets.py +0 -0
  261. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/kubernetes/services.py +0 -0
  262. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/kubernetes/util.py +0 -0
  263. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/lastpass/__init__.py +0 -0
  264. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/lastpass/users.py +0 -0
  265. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/oci/__init__.py +0 -0
  266. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/oci/iam.py +0 -0
  267. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/oci/organizations.py +0 -0
  268. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/oci/utils.py +0 -0
  269. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/okta/__init__.py +0 -0
  270. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/okta/applications.py +0 -0
  271. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/okta/awssaml.py +0 -0
  272. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/okta/factors.py +0 -0
  273. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/okta/groups.py +0 -0
  274. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/okta/organization.py +0 -0
  275. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/okta/origins.py +0 -0
  276. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/okta/roles.py +0 -0
  277. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/okta/sync_state.py +0 -0
  278. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/okta/users.py +0 -0
  279. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/okta/utils.py +0 -0
  280. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/pagerduty/__init__.py +0 -0
  281. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/pagerduty/escalation_policies.py +0 -0
  282. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/pagerduty/schedules.py +0 -0
  283. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/pagerduty/services.py +0 -0
  284. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/pagerduty/teams.py +0 -0
  285. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/pagerduty/users.py +0 -0
  286. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/pagerduty/vendors.py +0 -0
  287. {cartography-0.93.0 → cartography-0.94.0}/cartography/intel/semgrep/__init__.py +0 -0
  288. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/__init__.py +0 -0
  289. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/__init__.py +0 -0
  290. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/dynamodb/__init__.py +0 -0
  291. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/dynamodb/gsi.py +0 -0
  292. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/dynamodb/tables.py +0 -0
  293. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/__init__.py +0 -0
  294. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/images.py +0 -0
  295. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/instances.py +0 -0
  296. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/keypairs.py +0 -0
  297. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/launch_template_versions.py +0 -0
  298. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/launch_templates.py +0 -0
  299. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/loadbalancerv2.py +0 -0
  300. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/networkinterface_instance.py +0 -0
  301. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/networkinterfaces.py +0 -0
  302. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/privateip_networkinterface.py +0 -0
  303. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/reservations.py +0 -0
  304. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/securitygroup_instance.py +0 -0
  305. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/securitygroup_networkinterface.py +0 -0
  306. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/subnet_instance.py +0 -0
  307. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/subnet_networkinterface.py +0 -0
  308. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ec2/volumes.py +0 -0
  309. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/eks/__init__.py +0 -0
  310. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/eks/clusters.py +0 -0
  311. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/emr.py +0 -0
  312. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/inspector/__init__.py +0 -0
  313. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/inspector/findings.py +0 -0
  314. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/inspector/packages.py +0 -0
  315. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ssm/__init__.py +0 -0
  316. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ssm/instance_information.py +0 -0
  317. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/aws/ssm/instance_patch.py +0 -0
  318. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/bigfix/__init__.py +0 -0
  319. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/bigfix/bigfix_computer.py +0 -0
  320. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/bigfix/bigfix_root.py +0 -0
  321. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/core/__init__.py +0 -0
  322. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/core/common.py +0 -0
  323. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/core/nodes.py +0 -0
  324. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/core/relationships.py +0 -0
  325. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/cve/__init__.py +0 -0
  326. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/cve/cve.py +0 -0
  327. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/cve/cve_feed.py +0 -0
  328. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/duo/__init__.py +0 -0
  329. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/duo/api_host.py +0 -0
  330. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/duo/endpoint.py +0 -0
  331. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/duo/group.py +0 -0
  332. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/duo/phone.py +0 -0
  333. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/duo/token.py +0 -0
  334. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/duo/user.py +0 -0
  335. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/duo/web_authn_credential.py +0 -0
  336. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/github/__init__.py +0 -0
  337. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/github/teams.py +0 -0
  338. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/kandji/__init__.py +0 -0
  339. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/kandji/device.py +0 -0
  340. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/kandji/tenant.py +0 -0
  341. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/lastpass/__init__.py +0 -0
  342. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/lastpass/tenant.py +0 -0
  343. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/lastpass/user.py +0 -0
  344. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/semgrep/__init__.py +0 -0
  345. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/semgrep/deployment.py +0 -0
  346. {cartography-0.93.0 → cartography-0.94.0}/cartography/models/semgrep/locations.py +0 -0
  347. /cartography-0.93.0/cartography/py.typed → /cartography-0.94.0/cartography/models/snipeit/__init__.py +0 -0
  348. {cartography-0.93.0 → cartography-0.94.0}/cartography/stats.py +0 -0
  349. {cartography-0.93.0 → cartography-0.94.0}/cartography/util.py +0 -0
  350. {cartography-0.93.0 → cartography-0.94.0}/cartography.egg-info/dependency_links.txt +0 -0
  351. {cartography-0.93.0 → cartography-0.94.0}/cartography.egg-info/entry_points.txt +0 -0
  352. {cartography-0.93.0 → cartography-0.94.0}/cartography.egg-info/requires.txt +0 -0
  353. {cartography-0.93.0 → cartography-0.94.0}/cartography.egg-info/top_level.txt +0 -0
  354. {cartography-0.93.0 → cartography-0.94.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cartography
3
- Version: 0.93.0
3
+ Version: 0.94.0
4
4
  Summary: Explore assets and their relationships across your technical infrastructure.
5
5
  Home-page: https://www.github.com/lyft/cartography
6
6
  Maintainer: Lyft
@@ -34,7 +34,8 @@ Start [here](https://lyft.github.io/cartography/install.html).
34
34
  - [Lastpass](https://lyft.github.io/cartography/modules/lastpass/index.html) - users
35
35
  - [BigFix](https://lyft.github.io/cartography/modules/bigfix/index.html) - Computers
36
36
  - [Duo](https://lyft.github.io/cartography/modules/duo/index.html) - Users, Groups, Endpoints
37
-
37
+ - [Kandji](https://lyft.github.io/cartography/modules/kandji/index.html) - Devices
38
+ - [SnipeIT](https://lyft.github.io/cartography/modules/snipeit/index.html) - Users, Assets
38
39
 
39
40
  ## Usage
40
41
  Start with our [tutorial](https://lyft.github.io/cartography/usage/tutorial.html). Our [data schema](https://lyft.github.io/cartography/usage/schema.html) is a helpful reference when you get stuck.
@@ -74,6 +75,7 @@ and follow the instructions to sign the CLA.
74
75
  1. [MessageBird](https://messagebird.com)
75
76
  1. [Cloudanix](https://www.cloudanix.com/)
76
77
  1. [ZeusCloud](https://www.zeuscloud.io/)
78
+ 1. [Corelight](https://www.corelight.com/)
77
79
  1. {Your company here} :-)
78
80
 
79
81
  If your organization uses Cartography, please file a PR and update this list. Say hi on Slack too!
@@ -541,6 +541,28 @@ class CLI:
541
541
  'Required if you are using the Semgrep intel module. Ignored otherwise.'
542
542
  ),
543
543
  )
544
+ parser.add_argument(
545
+ '--snipeit-base-uri',
546
+ type=str,
547
+ default=None,
548
+ help=(
549
+ 'Your SnipeIT base URI'
550
+ 'Required if you are using the SnipeIT intel module. Ignored otherwise.'
551
+ ),
552
+ )
553
+ parser.add_argument(
554
+ '--snipeit-token-env-var',
555
+ type=str,
556
+ default=None,
557
+ help='The name of an environment variable containing token with which to authenticate to SnipeIT.',
558
+ )
559
+ parser.add_argument(
560
+ '--snipeit-tenant-id',
561
+ type=str,
562
+ default=None,
563
+ help='An ID for the SnipeIT tenant.',
564
+ )
565
+
544
566
  return parser
545
567
 
546
568
  def main(self, argv: str) -> int:
@@ -744,6 +766,26 @@ class CLI:
744
766
  else:
745
767
  config.cve_api_key = None
746
768
 
769
+ # SnipeIT config
770
+ if config.snipeit_base_uri:
771
+ if config.snipeit_token_env_var:
772
+ logger.debug(
773
+ "Reading SnipeIT API token from environment variable '%s'.",
774
+ config.snipeit_token_env_var,
775
+ )
776
+ config.snipeit_token = os.environ.get(config.snipeit_token_env_var)
777
+ elif os.environ.get('SNIPEIT_TOKEN'):
778
+ logger.debug(
779
+ "Reading SnipeIT API token from environment variable 'SNIPEIT_TOKEN'.",
780
+ )
781
+ config.snipeit_token = os.environ.get('SNIPEIT_TOKEN')
782
+ else:
783
+ logger.warning("A SnipeIT base URI was provided but a token was not.")
784
+ config.kandji_token = None
785
+ else:
786
+ logger.warning("A SnipeIT base URI was not provided.")
787
+ config.snipeit_base_uri = None
788
+
747
789
  # Run cartography
748
790
  try:
749
791
  return cartography.sync.run_with_config(self.sync, config)
@@ -111,6 +111,12 @@ class Config:
111
111
  :param duo_api_hostname: The Duo api hostname, e.g. "api-abc123.duosecurity.com". Optional.
112
112
  :param semgrep_app_token: The Semgrep api token. Optional.
113
113
  :type semgrep_app_token: str
114
+ :type snipeit_base_uri: string
115
+ :param snipeit_base_uri: SnipeIT data provider base URI. Optional.
116
+ :type snipeit_token: string
117
+ :param snipeit_token: Token used to authenticate to the SnipeIT data provider. Optional.
118
+ :type snipeit_tenant_id: string
119
+ :param snipeit_tenant_id: Token used to authenticate to the SnipeIT data provider. Optional.
114
120
  """
115
121
 
116
122
  def __init__(
@@ -170,6 +176,9 @@ class Config:
170
176
  duo_api_secret=None,
171
177
  duo_api_hostname=None,
172
178
  semgrep_app_token=None,
179
+ snipeit_base_uri=None,
180
+ snipeit_token=None,
181
+ snipeit_tenant_id=None,
173
182
  ):
174
183
  self.neo4j_uri = neo4j_uri
175
184
  self.neo4j_user = neo4j_user
@@ -226,3 +235,6 @@ class Config:
226
235
  self.duo_api_secret = duo_api_secret
227
236
  self.duo_api_hostname = duo_api_hostname
228
237
  self.semgrep_app_token = semgrep_app_token
238
+ self.snipeit_base_uri = snipeit_base_uri
239
+ self.snipeit_token = snipeit_token
240
+ self.snipeit_tenant_id = snipeit_tenant_id
@@ -13,47 +13,47 @@
13
13
  },
14
14
  {
15
15
  "__comment__": "not possible to identify if reachable && version specifier is the only flag of the vulnerability (likelihood = rare) && severity in [low, medium, high] -> Risk = Info",
16
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'UNKNOWN_EXPOSURE', reachability_check:'VERSION_SPECIFIER', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity IN ['LOW', 'MEDIUM', 'HIGH'] SET s.reachability_risk = 'INFO' return COUNT(*) as TotalCompleted",
16
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'UNREACHABLE', reachability_check:'NO REACHABILITY ANALYSIS', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity IN ['LOW', 'MEDIUM', 'HIGH'] SET s.reachability_risk = 'INFO' return COUNT(*) as TotalCompleted",
17
17
  "iterative": false
18
18
  },
19
19
  {
20
20
  "__comment__": "not possible to identify if reachable && version specifier is the only flag of the vulnerability (likelihood = rare) && severity = critical -> Risk = Low",
21
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'UNKNOWN_EXPOSURE', reachability_check:'VERSION_SPECIFIER', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'CRITICAL' SET s.reachability_risk = 'LOW' return COUNT(*) as TotalCompleted",
21
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'UNREACHABLE', reachability_check:'NO REACHABILITY ANALYSIS', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'CRITICAL' SET s.reachability_risk = 'LOW' return COUNT(*) as TotalCompleted",
22
22
  "iterative": false
23
23
  },
24
24
  {
25
- "__comment__": "manual review required to confirm && version specifier is the only flag of the vulnerability (likelihood = possible) && severity in [low, medium] -> Risk = Low",
26
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'MANUAL_REVIEW_REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity IN ['LOW', 'MEDIUM'] SET s.reachability_risk = 'LOW' return COUNT(*) as TotalCompleted",
25
+ "__comment__": "manual review required to confirm exploitation when conditions met && identified version is vulnerable (likelihood = possible) && severity in [low, medium] -> Risk = Low",
26
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'CONDITIONALLY REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity IN ['LOW', 'MEDIUM'] SET s.reachability_risk = 'LOW' return COUNT(*) as TotalCompleted",
27
27
  "iterative": false
28
28
  },
29
29
  {
30
- "__comment__": "manual review required to confirm && version specifier is the only flag of the vulnerability (likelihood = possible) && severity = high -> Risk = Medium",
31
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'MANUAL_REVIEW_REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'HIGH' SET s.reachability_risk = 'MEDIUM' return COUNT(*) as TotalCompleted",
30
+ "__comment__": "manual review required to confirm exploitation when conditions met && identified version is vulnerable (likelihood = possible) && severity = high -> Risk = Medium",
31
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'CONDITIONALLY REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'HIGH' SET s.reachability_risk = 'MEDIUM' return COUNT(*) as TotalCompleted",
32
32
  "iterative": false
33
33
  },
34
34
  {
35
- "__comment__": "manual review required to confirm && version specifier is the only flag of the vulnerability (likelihood = possible) && severity = critical -> Risk = High",
36
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'MANUAL_REVIEW_REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'CRITICAL' SET s.reachability_risk = 'HIGH' return COUNT(*) as TotalCompleted",
35
+ "__comment__": "manual review required to confirm exploitation when conditions met && identified version is vulnerable (likelihood = possible) && severity = critical -> Risk = High",
36
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'CONDITIONALLY REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'CRITICAL' SET s.reachability_risk = 'HIGH' return COUNT(*) as TotalCompleted",
37
37
  "iterative": false
38
38
  },
39
39
  {
40
40
  "__comment__": "adding the vulnerable version flags it reachable (likelihood = likely) && severity in [low, medium] -> Risk = Low",
41
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'ALWAYS_REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity IN ['LOW','MEDIUM'] SET s.reachability_risk = 'LOW' return COUNT(*) as TotalCompleted",
41
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'ALWAYS REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity IN ['LOW','MEDIUM'] SET s.reachability_risk = 'LOW' return COUNT(*) as TotalCompleted",
42
42
  "iterative": false
43
43
  },
44
44
  {
45
- "__comment__": "adding the vulnerable version flags it reachable (likelihood = likely) && severity = high -> Risk = Low",
46
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'ALWAYS_REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'HIGH' SET s.reachability_risk = 'MEDIUM' return COUNT(*) as TotalCompleted",
45
+ "__comment__": "adding the vulnerable version flags it reachable (likelihood = likely) && severity = high -> Risk = Medium",
46
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'ALWAYS REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'HIGH' SET s.reachability_risk = 'MEDIUM' return COUNT(*) as TotalCompleted",
47
47
  "iterative": false
48
48
  },
49
49
  {
50
50
  "__comment__": "adding the vulnerable version flags it reachable (special case for critical, if something is so critical that needs to be fixed, likelihood = likely)) && severity = critical -> Risk = Critical",
51
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'ALWAYS_REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'CRITICAL' SET s.reachability_risk = 'CRITICAL' return COUNT(*) as TotalCompleted",
51
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'ALWAYS REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'CRITICAL' SET s.reachability_risk = 'CRITICAL' return COUNT(*) as TotalCompleted",
52
52
  "iterative": false
53
53
  },
54
54
  {
55
55
  "__comment__": "if reachability analysis confirmed that is rechable (likelihood = certain) -> Risk = Severity",
56
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'REACHABILITY', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) SET s.reachability_risk = s.severity return COUNT(*) as TotalCompleted",
56
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) SET s.reachability_risk = s.severity return COUNT(*) as TotalCompleted",
57
57
  "iterative": false
58
58
  },
59
59
  {
@@ -150,7 +150,14 @@ class GraphJob:
150
150
  )
151
151
 
152
152
  statements: List[GraphStatement] = [
153
- GraphStatement(query, parameters=parameters, iterative=True, iterationsize=100) for query in queries
153
+ GraphStatement(
154
+ query,
155
+ parameters=parameters,
156
+ iterative=True,
157
+ iterationsize=100,
158
+ parent_job_name=node_schema.label,
159
+ parent_job_sequence_num=idx,
160
+ ) for idx, query in enumerate(queries, start=1)
154
161
  ]
155
162
 
156
163
  return cls(
@@ -18,6 +18,15 @@ from cartography.util import timeit
18
18
 
19
19
  logger = logging.getLogger(__name__)
20
20
 
21
+ # As of 7/22/24, Inspector is only available in the below regions. We will need to update this hardcoded list here over
22
+ # time. :\ https://docs.aws.amazon.com/general/latest/gr/inspector2.html
23
+ AWS_INSPECTOR_REGIONS = {
24
+ "us-east-2", "us-east-1", "us-west-1", "us-west-2", "af-south-1", "ap-east-1", "ap-southeast-3", "ap-south-1",
25
+ "ap-northeast-3", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "ap-northeast-1", "ca-central-1",
26
+ "eu-central-1", "eu-west-1", "eu-west-2", "eu-south-1", "eu-west-3", "eu-north-1", "eu-central-2", "me-south-1",
27
+ "sa-east-1",
28
+ }
29
+
21
30
 
22
31
  @timeit
23
32
  @aws_handle_regions
@@ -206,7 +215,9 @@ def sync(
206
215
  update_tag: int,
207
216
  common_job_parameters: Dict[str, Any],
208
217
  ) -> None:
209
- for region in regions:
218
+ inspector_regions = [region for region in regions if region in AWS_INSPECTOR_REGIONS]
219
+
220
+ for region in inspector_regions:
210
221
  logger.info(f"Syncing AWS Inspector findings for account {current_aws_account_id} and region {region}")
211
222
  findings = get_inspector_findings(boto3_session, region, current_aws_account_id)
212
223
  finding_data, package_data = transform_inspector_findings(findings)
@@ -322,8 +322,12 @@ def cleanup_rpr(
322
322
  )
323
323
 
324
324
  statement = GraphStatement(
325
- cleanup_rpr_query_template, {'UPDATE_TAG': update_tag, 'AWS_ID': current_aws_id},
326
- True, 1000,
325
+ cleanup_rpr_query_template,
326
+ {'UPDATE_TAG': update_tag, 'AWS_ID': current_aws_id},
327
+ True,
328
+ 1000,
329
+ parent_job_name=f"{relationship_name}:{node_label}",
330
+ parent_job_sequence_num=1,
327
331
  )
328
332
  statement.run(neo4j_session)
329
333
 
@@ -1,4 +1,6 @@
1
1
  import logging
2
+ from collections import namedtuple
3
+ from time import sleep
2
4
  from typing import Any
3
5
  from typing import Dict
4
6
  from typing import List
@@ -15,6 +17,8 @@ from cartography.util import timeit
15
17
 
16
18
  logger = logging.getLogger(__name__)
17
19
 
20
+ RepoPermission = namedtuple('RepoPermission', ['repo_url', 'permission'])
21
+
18
22
 
19
23
  @timeit
20
24
  def get_teams(org: str, api_url: str, token: str) -> Tuple[PaginatedGraphqlData, Dict[str, Any]]:
@@ -45,26 +49,53 @@ def get_teams(org: str, api_url: str, token: str) -> Tuple[PaginatedGraphqlData,
45
49
 
46
50
  @timeit
47
51
  def _get_team_repos_for_multiple_teams(
48
- team_raw_data: List[Dict[str, Any]],
52
+ team_raw_data: list[dict[str, Any]],
49
53
  org: str,
50
54
  api_url: str,
51
55
  token: str,
52
- ) -> Dict[str, Any]:
53
- result = {}
56
+ ) -> dict[str, list[RepoPermission]]:
57
+ result: dict[str, list[RepoPermission]] = {}
54
58
  for team in team_raw_data:
55
59
  team_name = team['slug']
56
60
  repo_count = team['repositories']['totalCount']
57
61
 
58
- team_repos = _get_team_repos(org, api_url, token, team_name) if repo_count > 0 else None
62
+ if repo_count == 0:
63
+ # This team has access to no repos so let's move on
64
+ result[team_name] = []
65
+ continue
59
66
 
60
67
  repo_urls = []
61
68
  repo_permissions = []
62
- if team_repos:
63
- repo_urls = [t['url'] for t in team_repos.nodes] if team_repos.nodes else []
64
- repo_permissions = [t['permission'] for t in team_repos.edges] if team_repos.edges else []
69
+
70
+ max_tries = 5
71
+
72
+ for current_try in range(1, max_tries + 1):
73
+ team_repos = _get_team_repos(org, api_url, token, team_name)
74
+
75
+ try:
76
+ # The `or []` is because `.nodes` can be None. See:
77
+ # https://docs.github.com/en/graphql/reference/objects#teamrepositoryconnection
78
+ for repo in team_repos.nodes or []:
79
+ repo_urls.append(repo['url'])
80
+
81
+ # The `or []` is because `.edges` can be None.
82
+ for edge in team_repos.edges or []:
83
+ repo_permissions.append(edge['permission'])
84
+ # We're done! Break out of the retry loop.
85
+ break
86
+
87
+ except TypeError:
88
+ # Handles issue #1334
89
+ logger.warning(
90
+ f"GitHub returned None when trying to find repo or permission data for team {team_name}.",
91
+ exc_info=True,
92
+ )
93
+ if current_try == max_tries:
94
+ raise RuntimeError(f"GitHub returned a None repo url for team {team_name}, retries exhausted.")
95
+ sleep(current_try ** 2)
65
96
 
66
97
  # Shape = [(repo_url, 'WRITE'), ...]]
67
- result[team_name] = list(zip(repo_urls, repo_permissions))
98
+ result[team_name] = [RepoPermission(url, perm) for url, perm in zip(repo_urls, repo_permissions)]
68
99
  return result
69
100
 
70
101
 
@@ -114,8 +145,8 @@ def _get_team_repos(org: str, api_url: str, token: str, team: str) -> PaginatedG
114
145
  def transform_teams(
115
146
  team_paginated_data: PaginatedGraphqlData,
116
147
  org_data: Dict[str, Any],
117
- team_repo_data: Dict[str, Any],
118
- ) -> List[Dict[str, Any]]:
148
+ team_repo_data: dict[str, list[RepoPermission]],
149
+ ) -> list[dict[str, Any]]:
119
150
  result = []
120
151
  for team in team_paginated_data.nodes:
121
152
  team_name = team['slug']
@@ -21,7 +21,7 @@ def start_kandji_ingestion(neo4j_session: neo4j.Session, config: Config) -> None
21
21
  """
22
22
  if config.kandji_base_uri is None or config.kandji_token is None or config.kandji_tenant_id is None:
23
23
  logger.warning(
24
- 'Required parameter(s) missing. Skipping sync.',
24
+ 'Required parameter missing. Skipping sync. '
25
25
  'See docs to configure.',
26
26
  )
27
27
  return
@@ -3,10 +3,11 @@ from typing import Any
3
3
  from typing import Dict
4
4
  from typing import List
5
5
  from typing import Tuple
6
- from urllib.error import HTTPError
7
6
 
8
7
  import neo4j
9
8
  import requests
9
+ from requests.exceptions import HTTPError
10
+ from requests.exceptions import ReadTimeout
10
11
 
11
12
  from cartography.client.core.tx import load
12
13
  from cartography.graph.job import GraphJob
@@ -20,6 +21,7 @@ from cartography.util import timeit
20
21
 
21
22
  logger = logging.getLogger(__name__)
22
23
  stat_handler = get_stats_client(__name__)
24
+ _PAGE_SIZE = 500
23
25
  _TIMEOUT = (60, 60)
24
26
  _MAX_RETRIES = 3
25
27
 
@@ -48,60 +50,91 @@ def get_deployment(semgrep_app_token: str) -> Dict[str, Any]:
48
50
 
49
51
 
50
52
  @timeit
51
- def get_sca_vulns(semgrep_app_token: str, deployment_id: str) -> List[Dict[str, Any]]:
53
+ def get_sca_vulns(semgrep_app_token: str, deployment_slug: str) -> List[Dict[str, Any]]:
52
54
  """
53
55
  Gets the SCA vulns associated with the passed Semgrep App token and deployment id.
54
56
  param: semgrep_app_token: The Semgrep App token to use for authentication.
55
- param: deployment_id: The Semgrep deployment id to use for retrieving SCA vulns.
57
+ param: deployment_slug: The Semgrep deployment slug to use for retrieving SCA vulns.
56
58
  """
57
59
  all_vulns = []
58
- sca_url = f"https://semgrep.dev/api/v1/deployments/{deployment_id}/ssc-vulns"
60
+ sca_url = f"https://semgrep.dev/api/v1/deployments/{deployment_slug}/findings"
59
61
  has_more = True
60
- cursor: Dict[str, str] = {}
61
- page = 1
62
+ page = 0
62
63
  retries = 0
63
64
  headers = {
64
65
  "Content-Type": "application/json",
65
66
  "Authorization": f"Bearer {semgrep_app_token}",
66
67
  }
67
68
 
68
- request_data = {
69
- "deploymentId": deployment_id,
70
- "pageSize": 100,
71
- "exposure": ["UNREACHABLE", "REACHABLE", "UNKNOWN_EXPOSURE"],
72
- "refs": ["_default"],
69
+ request_data: dict[str, Any] = {
70
+ "page": page,
71
+ "page_size": _PAGE_SIZE,
72
+ "issue_type": "sca",
73
+ "exposures": "reachable,always_reachable,conditionally_reachable,unreachable,unknown",
74
+ "ref": "_default",
75
+ "dedup": "true",
73
76
  }
74
-
77
+ logger.info(f"Retrieving Semgrep SCA vulns for deployment '{deployment_slug}'.")
75
78
  while has_more:
76
79
 
77
- if cursor:
78
- request_data.update({
79
- "cursor": {
80
- "vulnOffset": cursor["vulnOffset"],
81
- "issueOffset": cursor["issueOffset"],
82
- },
83
- })
84
80
  try:
85
- response = requests.post(sca_url, json=request_data, headers=headers, timeout=_TIMEOUT)
81
+ response = requests.get(sca_url, params=request_data, headers=headers, timeout=_TIMEOUT)
86
82
  response.raise_for_status()
87
83
  data = response.json()
88
- except HTTPError as e:
84
+ except (ReadTimeout, HTTPError) as e:
89
85
  logger.warning(f"Failed to retrieve Semgrep SCA vulns for page {page}. Retrying...")
90
86
  retries += 1
91
87
  if retries >= _MAX_RETRIES:
92
88
  raise e
93
89
  continue
94
- vulns = data["vulns"]
95
- cursor = data.get("cursor")
96
- has_more = data.get("hasMore", False)
90
+ vulns = data["findings"]
91
+ has_more = len(vulns) > 0
97
92
  if page % 10 == 0:
98
- logger.info(f"Processed {page} pages of Semgrep SCA vulnerabilities so far.")
93
+ logger.info(f"Processed page {page} of Semgrep SCA vulnerabilities.")
99
94
  all_vulns.extend(vulns)
100
95
  retries = 0
96
+ page += 1
97
+ request_data["page"] = page
101
98
 
99
+ logger.info(f"Retrieved {len(all_vulns)} Semgrep SCA vulns in {page} pages.")
102
100
  return all_vulns
103
101
 
104
102
 
103
+ def _get_vuln_class(vuln: Dict) -> str:
104
+ vulnerability_classes = vuln["rule"].get("vulnerability_classes", [])
105
+ if vulnerability_classes:
106
+ return vulnerability_classes[0]
107
+ return "Other"
108
+
109
+
110
+ def _determine_exposure(vuln: Dict[str, Any]) -> str | None:
111
+ # See Semgrep reachability types:
112
+ # https://semgrep.dev/docs/semgrep-supply-chain/overview#types-of-semgrep-supply-chain-findings
113
+ reachability_types = {
114
+ "NO REACHABILITY ANALYSIS": 2,
115
+ "UNREACHABLE": 2,
116
+ "REACHABLE": 0,
117
+ "ALWAYS REACHABLE": 0,
118
+ "CONDITIONALLY REACHABLE": 1,
119
+ }
120
+ reachable_flag = vuln["reachability"]
121
+ if reachable_flag and reachable_flag.upper() in reachability_types:
122
+ reach_score = reachability_types[reachable_flag.upper()]
123
+ if reach_score < reachability_types["UNREACHABLE"]:
124
+ return "REACHABLE"
125
+ else:
126
+ return "UNREACHABLE"
127
+ return None
128
+
129
+
130
+ def _build_vuln_url(vuln: str) -> str | None:
131
+ if 'CVE' in vuln:
132
+ return f"https://nvd.nist.gov/vuln/detail/{vuln}"
133
+ if 'GHSA' in vuln:
134
+ return f"https://github.com/advisories/{vuln}"
135
+ return None
136
+
137
+
105
138
  def transform_sca_vulns(raw_vulns: List[Dict[str, Any]]) -> Tuple[List[Dict[str, Any]], List[Dict[str, str]]]:
106
139
  """
107
140
  Transforms the raw SCA vulns response from Semgrep API into a list of dicts
@@ -112,46 +145,59 @@ def transform_sca_vulns(raw_vulns: List[Dict[str, Any]]) -> Tuple[List[Dict[str,
112
145
  for vuln in raw_vulns:
113
146
  sca_vuln: Dict[str, Any] = {}
114
147
  # Mandatory fields
115
- sca_vuln["id"] = vuln["groupKey"]
116
- sca_vuln["repositoryName"] = vuln["repositoryName"]
117
- sca_vuln["ruleId"] = vuln["advisory"]["ruleId"]
118
- sca_vuln["title"] = vuln["advisory"]["title"]
119
- sca_vuln["description"] = vuln["advisory"]["description"]
120
- sca_vuln["ecosystem"] = vuln["advisory"]["ecosystem"]
121
- sca_vuln["severity"] = vuln["advisory"]["severity"]
122
- sca_vuln["reachability"] = vuln["advisory"]["reachability"]
123
- sca_vuln["reachableIf"] = vuln["advisory"]["reachableIf"]
124
- sca_vuln["exposureType"] = vuln["exposureType"]
125
- dependency = f"{vuln['matchedDependency']['name']}|{vuln['matchedDependency']['versionSpecifier']}"
148
+ repository_name = vuln["repository"]["name"]
149
+ rule_id = vuln["rule"]["name"]
150
+ vulnerability_class = _get_vuln_class(vuln)
151
+ package = vuln['found_dependency']['package']
152
+ sca_vuln["id"] = vuln["id"]
153
+ sca_vuln["repositoryName"] = repository_name
154
+ sca_vuln["branch"] = vuln["ref"]
155
+ sca_vuln["ruleId"] = rule_id
156
+ sca_vuln["title"] = package + ":" + vulnerability_class
157
+ sca_vuln["description"] = vuln["rule"]["message"]
158
+ sca_vuln["ecosystem"] = vuln["found_dependency"]["ecosystem"]
159
+ sca_vuln["severity"] = vuln["severity"].upper()
160
+ sca_vuln["reachability"] = vuln["reachability"].upper() # Check done to determine rechabilitity
161
+ sca_vuln["reachableIf"] = vuln["reachable_condition"].upper() if vuln["reachable_condition"] else None
162
+ sca_vuln["exposureType"] = _determine_exposure(vuln) # Determintes if reachable or unreachable
163
+ dependency = f"{package}|{vuln['found_dependency']['version']}"
126
164
  sca_vuln["matchedDependency"] = dependency
127
- sca_vuln["dependencyFileLocation_path"] = vuln["dependencyFileLocation"]["path"]
128
- sca_vuln["dependencyFileLocation_url"] = vuln["dependencyFileLocation"]["url"]
129
- # Optional fields
130
- sca_vuln["transitivity"] = vuln.get("transitivity", None)
131
- cves = vuln.get("advisory", {}).get("references", {}).get("cveIds")
132
- if len(cves) > 0:
133
- # Take the first CVE
134
- sca_vuln["cveId"] = vuln["advisory"]["references"]["cveIds"][0]
135
- if vuln.get('closestSafeDependency'):
136
- dep_fix = f"{vuln['closestSafeDependency']['name']}|{vuln['closestSafeDependency']['versionSpecifier']}"
165
+ dep_url = vuln["found_dependency"]["lockfile_line_url"]
166
+ if dep_url: # Lock file can be null, need to set
167
+ dep_file = dep_url.split("/")[-1].split("#")[0]
168
+ sca_vuln["dependencyFileLocation_path"] = dep_file
169
+ sca_vuln["dependencyFileLocation_url"] = dep_url
170
+ else:
171
+ if sca_vuln.get("location"):
172
+ sca_vuln["dependencyFileLocation_path"] = sca_vuln["location"]["file_path"]
173
+ sca_vuln["transitivity"] = vuln["found_dependency"]["transitivity"].upper()
174
+ if vuln.get("vulnerability_identifier"):
175
+ vuln_id = vuln["vulnerability_identifier"].upper()
176
+ sca_vuln["cveId"] = vuln_id
177
+ sca_vuln["ref_urls"] = [_build_vuln_url(vuln_id)]
178
+ if vuln.get('fix_recommendations') and len(vuln['fix_recommendations']) > 0:
179
+ fix = vuln['fix_recommendations'][0]
180
+ dep_fix = f"{fix['package']}|{fix['version']}"
137
181
  sca_vuln["closestSafeDependency"] = dep_fix
138
- if vuln["advisory"].get("references", {}).get("urls", []):
139
- sca_vuln["ref_urls"] = vuln["advisory"].get("references", {}).get("urls", [])
140
- sca_vuln["openedAt"] = vuln.get("openedAt", None)
141
- sca_vuln["announcedAt"] = vuln.get("announcedAt", None)
142
- sca_vuln["fixStatus"] = vuln["triage"]["status"]
143
- for usage in vuln.get("usages", []):
182
+ sca_vuln["openedAt"] = vuln["created_at"]
183
+ sca_vuln["fixStatus"] = vuln["status"]
184
+ sca_vuln["triageStatus"] = vuln["triage_state"]
185
+ sca_vuln["confidence"] = vuln["confidence"]
186
+ usage = vuln.get("usage")
187
+ if usage:
144
188
  usage_dict = {}
189
+ url = usage["location"]["url"]
145
190
  usage_dict["SCA_ID"] = sca_vuln["id"]
146
- usage_dict["findingId"] = usage["findingId"]
191
+ usage_dict["findingId"] = hash(url.split("github.com/")[-1])
147
192
  usage_dict["path"] = usage["location"]["path"]
148
- usage_dict["startLine"] = usage["location"]["startLine"]
149
- usage_dict["startCol"] = usage["location"]["startCol"]
150
- usage_dict["endLine"] = usage["location"]["endLine"]
151
- usage_dict["endCol"] = usage["location"]["endCol"]
152
- usage_dict["url"] = usage["location"]["url"]
193
+ usage_dict["startLine"] = usage["location"]["start_line"]
194
+ usage_dict["startCol"] = usage["location"]["start_col"]
195
+ usage_dict["endLine"] = usage["location"]["end_line"]
196
+ usage_dict["endCol"] = usage["location"]["end_col"]
197
+ usage_dict["url"] = url
153
198
  usages.append(usage_dict)
154
199
  vulns.append(sca_vuln)
200
+
155
201
  return vulns, usages
156
202
 
157
203
 
@@ -228,9 +274,10 @@ def sync(
228
274
  logger.info("Running Semgrep SCA findings sync job.")
229
275
  semgrep_deployment = get_deployment(semgrep_app_token)
230
276
  deployment_id = semgrep_deployment["id"]
277
+ deployment_slug = semgrep_deployment["slug"]
231
278
  load_semgrep_deployment(neo4j_sesion, semgrep_deployment, update_tag)
232
279
  common_job_parameters["DEPLOYMENT_ID"] = deployment_id
233
- raw_vulns = get_sca_vulns(semgrep_app_token, deployment_id)
280
+ raw_vulns = get_sca_vulns(semgrep_app_token, deployment_slug)
234
281
  vulns, usages = transform_sca_vulns(raw_vulns)
235
282
  load_semgrep_sca_vulns(neo4j_sesion, vulns, deployment_id, update_tag)
236
283
  load_semgrep_sca_usages(neo4j_sesion, usages, deployment_id, update_tag)
@@ -0,0 +1,30 @@
1
+ import logging
2
+
3
+ import neo4j
4
+
5
+ from cartography.config import Config
6
+ from cartography.intel.snipeit import asset
7
+ from cartography.intel.snipeit import user
8
+ from cartography.stats import get_stats_client
9
+ from cartography.util import timeit
10
+
11
+ logger = logging.getLogger(__name__)
12
+ stat_handler = get_stats_client(__name__)
13
+
14
+
15
+ @timeit
16
+ def start_snipeit_ingestion(neo4j_session: neo4j.Session, config: Config) -> None:
17
+ if config.snipeit_base_uri is None or config.snipeit_token is None or config.snipeit_tenant_id is None:
18
+ logger.warning(
19
+ "Required parameter(s) missing. Skipping sync.",
20
+ )
21
+ return
22
+
23
+ common_job_parameters = {
24
+ "UPDATE_TAG": config.update_tag,
25
+ "TENANT_ID": config.snipeit_tenant_id,
26
+ }
27
+
28
+ # Ingest SnipeIT users and assets
29
+ user.sync(neo4j_session, common_job_parameters, config.snipeit_base_uri, config.snipeit_token)
30
+ asset.sync(neo4j_session, common_job_parameters, config.snipeit_base_uri, config.snipeit_token)