cartography 0.102.0rc1__py3-none-any.whl → 0.103.0rc1__py3-none-any.whl

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 (251) hide show
  1. cartography/__main__.py +1 -2
  2. cartography/_version.py +2 -2
  3. cartography/cli.py +302 -253
  4. cartography/client/core/tx.py +39 -18
  5. cartography/config.py +4 -0
  6. cartography/driftdetect/__main__.py +1 -2
  7. cartography/driftdetect/add_shortcut.py +10 -2
  8. cartography/driftdetect/cli.py +71 -75
  9. cartography/driftdetect/detect_deviations.py +7 -3
  10. cartography/driftdetect/get_states.py +20 -8
  11. cartography/driftdetect/model.py +5 -5
  12. cartography/driftdetect/serializers.py +8 -6
  13. cartography/driftdetect/storage.py +2 -2
  14. cartography/graph/cleanupbuilder.py +35 -15
  15. cartography/graph/job.py +46 -17
  16. cartography/graph/querybuilder.py +165 -80
  17. cartography/graph/statement.py +35 -26
  18. cartography/intel/analysis.py +4 -1
  19. cartography/intel/aws/__init__.py +114 -55
  20. cartography/intel/aws/apigateway.py +134 -63
  21. cartography/intel/aws/cloudtrail.py +127 -0
  22. cartography/intel/aws/config.py +56 -20
  23. cartography/intel/aws/dynamodb.py +108 -40
  24. cartography/intel/aws/ec2/__init__.py +2 -2
  25. cartography/intel/aws/ec2/auto_scaling_groups.py +181 -78
  26. cartography/intel/aws/ec2/elastic_ip_addresses.py +41 -13
  27. cartography/intel/aws/ec2/images.py +49 -20
  28. cartography/intel/aws/ec2/instances.py +234 -136
  29. cartography/intel/aws/ec2/internet_gateways.py +40 -11
  30. cartography/intel/aws/ec2/key_pairs.py +44 -20
  31. cartography/intel/aws/ec2/launch_templates.py +101 -59
  32. cartography/intel/aws/ec2/load_balancer_v2s.py +104 -39
  33. cartography/intel/aws/ec2/load_balancers.py +82 -42
  34. cartography/intel/aws/ec2/network_acls.py +89 -65
  35. cartography/intel/aws/ec2/network_interfaces.py +146 -87
  36. cartography/intel/aws/ec2/reserved_instances.py +45 -16
  37. cartography/intel/aws/ec2/route_tables.py +327 -0
  38. cartography/intel/aws/ec2/security_groups.py +71 -21
  39. cartography/intel/aws/ec2/snapshots.py +61 -22
  40. cartography/intel/aws/ec2/subnets.py +54 -18
  41. cartography/intel/aws/ec2/tgw.py +100 -34
  42. cartography/intel/aws/ec2/util.py +1 -1
  43. cartography/intel/aws/ec2/volumes.py +69 -41
  44. cartography/intel/aws/ec2/vpc.py +37 -12
  45. cartography/intel/aws/ec2/vpc_peerings.py +83 -24
  46. cartography/intel/aws/ecr.py +88 -32
  47. cartography/intel/aws/ecs.py +83 -47
  48. cartography/intel/aws/eks.py +55 -29
  49. cartography/intel/aws/elasticache.py +42 -18
  50. cartography/intel/aws/elasticsearch.py +57 -20
  51. cartography/intel/aws/emr.py +61 -23
  52. cartography/intel/aws/iam.py +401 -145
  53. cartography/intel/aws/iam_instance_profiles.py +22 -22
  54. cartography/intel/aws/identitycenter.py +71 -37
  55. cartography/intel/aws/inspector.py +159 -89
  56. cartography/intel/aws/kms.py +92 -38
  57. cartography/intel/aws/lambda_function.py +103 -34
  58. cartography/intel/aws/organizations.py +30 -10
  59. cartography/intel/aws/permission_relationships.py +133 -51
  60. cartography/intel/aws/rds.py +249 -85
  61. cartography/intel/aws/redshift.py +107 -46
  62. cartography/intel/aws/resourcegroupstaggingapi.py +120 -66
  63. cartography/intel/aws/resources.py +53 -44
  64. cartography/intel/aws/route53.py +108 -61
  65. cartography/intel/aws/s3.py +168 -83
  66. cartography/intel/aws/s3accountpublicaccessblock.py +157 -0
  67. cartography/intel/aws/secretsmanager.py +24 -12
  68. cartography/intel/aws/securityhub.py +20 -9
  69. cartography/intel/aws/sns.py +166 -0
  70. cartography/intel/aws/sqs.py +60 -28
  71. cartography/intel/aws/ssm.py +70 -30
  72. cartography/intel/aws/util/arns.py +7 -7
  73. cartography/intel/aws/util/common.py +31 -4
  74. cartography/intel/azure/__init__.py +78 -19
  75. cartography/intel/azure/compute.py +101 -27
  76. cartography/intel/azure/cosmosdb.py +496 -170
  77. cartography/intel/azure/sql.py +296 -105
  78. cartography/intel/azure/storage.py +322 -113
  79. cartography/intel/azure/subscription.py +39 -23
  80. cartography/intel/azure/tenant.py +13 -4
  81. cartography/intel/azure/util/credentials.py +95 -55
  82. cartography/intel/bigfix/__init__.py +2 -2
  83. cartography/intel/bigfix/computers.py +93 -65
  84. cartography/intel/create_indexes.py +3 -2
  85. cartography/intel/crowdstrike/__init__.py +11 -9
  86. cartography/intel/crowdstrike/endpoints.py +5 -1
  87. cartography/intel/crowdstrike/spotlight.py +8 -3
  88. cartography/intel/cve/__init__.py +46 -13
  89. cartography/intel/cve/feed.py +48 -12
  90. cartography/intel/digitalocean/__init__.py +22 -13
  91. cartography/intel/digitalocean/compute.py +75 -108
  92. cartography/intel/digitalocean/management.py +44 -80
  93. cartography/intel/digitalocean/platform.py +48 -43
  94. cartography/intel/dns.py +36 -10
  95. cartography/intel/duo/__init__.py +21 -16
  96. cartography/intel/duo/api_host.py +14 -9
  97. cartography/intel/duo/endpoints.py +50 -45
  98. cartography/intel/duo/groups.py +18 -14
  99. cartography/intel/duo/phones.py +37 -34
  100. cartography/intel/duo/tokens.py +26 -23
  101. cartography/intel/duo/users.py +54 -50
  102. cartography/intel/duo/web_authn_credentials.py +30 -25
  103. cartography/intel/entra/__init__.py +25 -7
  104. cartography/intel/entra/ou.py +112 -0
  105. cartography/intel/entra/users.py +69 -63
  106. cartography/intel/gcp/__init__.py +185 -49
  107. cartography/intel/gcp/compute.py +418 -231
  108. cartography/intel/gcp/crm.py +96 -43
  109. cartography/intel/gcp/dns.py +60 -19
  110. cartography/intel/gcp/gke.py +72 -38
  111. cartography/intel/gcp/iam.py +61 -41
  112. cartography/intel/gcp/storage.py +84 -55
  113. cartography/intel/github/__init__.py +13 -11
  114. cartography/intel/github/repos.py +270 -137
  115. cartography/intel/github/teams.py +170 -88
  116. cartography/intel/github/users.py +70 -39
  117. cartography/intel/github/util.py +36 -34
  118. cartography/intel/gsuite/__init__.py +47 -26
  119. cartography/intel/gsuite/api.py +73 -30
  120. cartography/intel/jamf/__init__.py +19 -1
  121. cartography/intel/jamf/computers.py +30 -7
  122. cartography/intel/jamf/util.py +7 -2
  123. cartography/intel/kandji/__init__.py +6 -3
  124. cartography/intel/kandji/devices.py +14 -8
  125. cartography/intel/kubernetes/namespaces.py +7 -4
  126. cartography/intel/kubernetes/pods.py +7 -4
  127. cartography/intel/kubernetes/services.py +8 -4
  128. cartography/intel/lastpass/__init__.py +2 -2
  129. cartography/intel/lastpass/users.py +23 -12
  130. cartography/intel/oci/__init__.py +44 -11
  131. cartography/intel/oci/iam.py +134 -38
  132. cartography/intel/oci/organizations.py +13 -6
  133. cartography/intel/oci/utils.py +43 -20
  134. cartography/intel/okta/__init__.py +66 -15
  135. cartography/intel/okta/applications.py +42 -20
  136. cartography/intel/okta/awssaml.py +93 -33
  137. cartography/intel/okta/factors.py +16 -4
  138. cartography/intel/okta/groups.py +56 -29
  139. cartography/intel/okta/organization.py +5 -1
  140. cartography/intel/okta/origins.py +6 -2
  141. cartography/intel/okta/roles.py +15 -5
  142. cartography/intel/okta/users.py +20 -8
  143. cartography/intel/okta/utils.py +6 -4
  144. cartography/intel/pagerduty/__init__.py +8 -7
  145. cartography/intel/pagerduty/escalation_policies.py +18 -6
  146. cartography/intel/pagerduty/schedules.py +12 -4
  147. cartography/intel/pagerduty/services.py +11 -4
  148. cartography/intel/pagerduty/teams.py +8 -3
  149. cartography/intel/pagerduty/users.py +3 -1
  150. cartography/intel/pagerduty/vendors.py +3 -1
  151. cartography/intel/semgrep/__init__.py +24 -6
  152. cartography/intel/semgrep/dependencies.py +50 -28
  153. cartography/intel/semgrep/deployment.py +3 -1
  154. cartography/intel/semgrep/findings.py +42 -18
  155. cartography/intel/snipeit/__init__.py +17 -3
  156. cartography/intel/snipeit/asset.py +12 -6
  157. cartography/intel/snipeit/user.py +8 -5
  158. cartography/intel/snipeit/util.py +9 -4
  159. cartography/models/aws/apigateway.py +21 -17
  160. cartography/models/aws/apigatewaycertificate.py +28 -22
  161. cartography/models/aws/apigatewayresource.py +28 -20
  162. cartography/models/aws/apigatewaystage.py +33 -25
  163. cartography/models/aws/cloudtrail/__init__.py +0 -0
  164. cartography/models/aws/cloudtrail/trail.py +61 -0
  165. cartography/models/aws/dynamodb/gsi.py +30 -22
  166. cartography/models/aws/dynamodb/tables.py +25 -17
  167. cartography/models/aws/ec2/auto_scaling_groups.py +102 -82
  168. cartography/models/aws/ec2/images.py +36 -34
  169. cartography/models/aws/ec2/instances.py +51 -45
  170. cartography/models/aws/ec2/keypair.py +21 -16
  171. cartography/models/aws/ec2/keypair_instance.py +28 -21
  172. cartography/models/aws/ec2/launch_configurations.py +30 -26
  173. cartography/models/aws/ec2/launch_template_versions.py +48 -38
  174. cartography/models/aws/ec2/launch_templates.py +21 -17
  175. cartography/models/aws/ec2/load_balancer_listeners.py +27 -23
  176. cartography/models/aws/ec2/load_balancers.py +47 -37
  177. cartography/models/aws/ec2/network_acl_rules.py +38 -30
  178. cartography/models/aws/ec2/network_acls.py +38 -29
  179. cartography/models/aws/ec2/networkinterface_instance.py +52 -39
  180. cartography/models/aws/ec2/networkinterfaces.py +53 -37
  181. cartography/models/aws/ec2/privateip_networkinterface.py +32 -22
  182. cartography/models/aws/ec2/reservations.py +18 -14
  183. cartography/models/aws/ec2/route_table_associations.py +97 -0
  184. cartography/models/aws/ec2/route_tables.py +128 -0
  185. cartography/models/aws/ec2/routes.py +85 -0
  186. cartography/models/aws/ec2/securitygroup_instance.py +29 -20
  187. cartography/models/aws/ec2/securitygroup_networkinterface.py +24 -15
  188. cartography/models/aws/ec2/subnet_instance.py +24 -19
  189. cartography/models/aws/ec2/subnet_networkinterface.py +40 -31
  190. cartography/models/aws/ec2/volumes.py +47 -40
  191. cartography/models/aws/eks/clusters.py +23 -21
  192. cartography/models/aws/emr.py +32 -30
  193. cartography/models/aws/iam/instanceprofile.py +33 -24
  194. cartography/models/aws/identitycenter/awsidentitycenter.py +18 -14
  195. cartography/models/aws/identitycenter/awspermissionset.py +37 -29
  196. cartography/models/aws/identitycenter/awsssouser.py +23 -21
  197. cartography/models/aws/inspector/findings.py +77 -65
  198. cartography/models/aws/inspector/packages.py +35 -29
  199. cartography/models/aws/s3/__init__.py +0 -0
  200. cartography/models/aws/s3/account_public_access_block.py +51 -0
  201. cartography/models/aws/sns/__init__.py +0 -0
  202. cartography/models/aws/sns/topic.py +50 -0
  203. cartography/models/aws/ssm/instance_information.py +51 -39
  204. cartography/models/aws/ssm/instance_patch.py +32 -26
  205. cartography/models/bigfix/bigfix_computer.py +42 -38
  206. cartography/models/bigfix/bigfix_root.py +3 -3
  207. cartography/models/core/common.py +12 -10
  208. cartography/models/core/nodes.py +5 -2
  209. cartography/models/core/relationships.py +14 -6
  210. cartography/models/crowdstrike/hosts.py +37 -35
  211. cartography/models/cve/cve.py +34 -32
  212. cartography/models/cve/cve_feed.py +6 -6
  213. cartography/models/digitalocean/__init__.py +0 -0
  214. cartography/models/digitalocean/account.py +21 -0
  215. cartography/models/digitalocean/droplet.py +56 -0
  216. cartography/models/digitalocean/project.py +48 -0
  217. cartography/models/duo/api_host.py +3 -3
  218. cartography/models/duo/endpoint.py +43 -41
  219. cartography/models/duo/group.py +14 -14
  220. cartography/models/duo/phone.py +27 -27
  221. cartography/models/duo/token.py +16 -16
  222. cartography/models/duo/user.py +46 -44
  223. cartography/models/duo/web_authn_credential.py +27 -19
  224. cartography/models/entra/ou.py +48 -0
  225. cartography/models/entra/tenant.py +24 -18
  226. cartography/models/entra/user.py +64 -48
  227. cartography/models/gcp/iam.py +23 -23
  228. cartography/models/github/orgs.py +5 -4
  229. cartography/models/github/teams.py +37 -31
  230. cartography/models/github/users.py +34 -23
  231. cartography/models/kandji/device.py +22 -16
  232. cartography/models/kandji/tenant.py +6 -4
  233. cartography/models/lastpass/tenant.py +3 -3
  234. cartography/models/lastpass/user.py +32 -28
  235. cartography/models/semgrep/dependencies.py +36 -24
  236. cartography/models/semgrep/deployment.py +5 -5
  237. cartography/models/semgrep/findings.py +58 -42
  238. cartography/models/semgrep/locations.py +27 -21
  239. cartography/models/snipeit/asset.py +30 -21
  240. cartography/models/snipeit/tenant.py +6 -4
  241. cartography/models/snipeit/user.py +19 -12
  242. cartography/stats.py +3 -3
  243. cartography/sync.py +107 -31
  244. cartography/util.py +84 -62
  245. {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/METADATA +3 -14
  246. cartography-0.103.0rc1.dist-info/RECORD +396 -0
  247. {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/WHEEL +1 -1
  248. cartography-0.102.0rc1.dist-info/RECORD +0 -377
  249. {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/entry_points.txt +0 -0
  250. {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/licenses/LICENSE +0 -0
  251. {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/top_level.txt +0 -0
@@ -12,14 +12,19 @@ _TIMEOUT = (60, 60)
12
12
 
13
13
 
14
14
  @timeit
15
- def call_jamf_api(api_and_parameters: str, jamf_base_uri: str, jamf_user: str, jamf_password: str) -> List[Dict]:
15
+ def call_jamf_api(
16
+ api_and_parameters: str,
17
+ jamf_base_uri: str,
18
+ jamf_user: str,
19
+ jamf_password: str,
20
+ ) -> List[Dict]:
16
21
  uri = jamf_base_uri + api_and_parameters
17
22
  jamf_auth = requests.auth.HTTPBasicAuth(jamf_user, jamf_password)
18
23
  try:
19
24
  response = requests.get(
20
25
  uri,
21
26
  auth=jamf_auth,
22
- headers={'Accept': 'application/json'},
27
+ headers={"Accept": "application/json"},
23
28
  timeout=_TIMEOUT,
24
29
  )
25
30
  except requests.exceptions.Timeout:
@@ -19,10 +19,13 @@ def start_kandji_ingestion(neo4j_session: neo4j.Session, config: Config) -> None
19
19
 
20
20
  :return: None
21
21
  """
22
- if config.kandji_base_uri is None or config.kandji_token is None or config.kandji_tenant_id is None:
22
+ if (
23
+ config.kandji_base_uri is None
24
+ or config.kandji_token is None
25
+ or config.kandji_tenant_id is None
26
+ ):
23
27
  logger.warning(
24
- 'Required parameter missing. Skipping sync. '
25
- 'See docs to configure.',
28
+ "Required parameter missing. Skipping sync. " "See docs to configure.",
26
29
  )
27
30
  return
28
31
 
@@ -12,7 +12,6 @@ from cartography.models.kandji.device import KandjiDeviceSchema
12
12
  from cartography.models.kandji.tenant import KandjiTenantSchema
13
13
  from cartography.util import timeit
14
14
 
15
-
16
15
  logger = logging.getLogger(__name__)
17
16
  _TIMEOUT = (60, 60)
18
17
 
@@ -21,8 +20,8 @@ _TIMEOUT = (60, 60)
21
20
  def get(kandji_base_uri: str, kandji_token: str) -> List[Dict[str, Any]]:
22
21
  api_endpoint = f"{kandji_base_uri}/api/v1/devices"
23
22
  headers = {
24
- 'Accept': 'application/json',
25
- 'Authorization': f'Bearer {kandji_token}',
23
+ "Accept": "application/json",
24
+ "Authorization": f"Bearer {kandji_token}",
26
25
  }
27
26
 
28
27
  offset = 0
@@ -39,7 +38,9 @@ def get(kandji_base_uri: str, kandji_token: str) -> List[Dict[str, Any]]:
39
38
  logger.debug("Kandji device offset: %s", offset)
40
39
 
41
40
  params["offset"] = offset
42
- response = session.get(api_endpoint, headers=headers, timeout=_TIMEOUT, params=params)
41
+ response = session.get(
42
+ api_endpoint, headers=headers, timeout=_TIMEOUT, params=params
43
+ )
43
44
  response.raise_for_status()
44
45
 
45
46
  result = response.json()
@@ -60,7 +61,7 @@ def transform(api_result: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
60
61
  result: List[Dict[str, Any]] = []
61
62
  for device in api_result:
62
63
  n_device = device
63
- n_device['id'] = device['device_id']
64
+ n_device["id"] = device["device_id"]
64
65
  result.append(n_device)
65
66
  return result
66
67
 
@@ -78,7 +79,7 @@ def load_devices(
78
79
  load(
79
80
  neo4j_session,
80
81
  KandjiTenantSchema(),
81
- [{'id': tenant_id}],
82
+ [{"id": tenant_id}],
82
83
  lastupdated=update_tag,
83
84
  )
84
85
 
@@ -91,8 +92,13 @@ def load_devices(
91
92
  )
92
93
 
93
94
 
94
- def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]) -> None:
95
- GraphJob.from_node_schema(KandjiDeviceSchema(), common_job_parameters).run(neo4j_session)
95
+ def cleanup(
96
+ neo4j_session: neo4j.Session,
97
+ common_job_parameters: Dict[str, Any],
98
+ ) -> None:
99
+ GraphJob.from_node_schema(KandjiDeviceSchema(), common_job_parameters).run(
100
+ neo4j_session,
101
+ )
96
102
 
97
103
 
98
104
  @timeit
@@ -21,9 +21,9 @@ def sync_namespaces(session: Session, client: K8sClient, update_tag: int) -> Dic
21
21
  load_namespaces(session, cluster, namespaces, update_tag)
22
22
  merge_module_sync_metadata(
23
23
  session,
24
- group_type='KubernetesCluster',
25
- group_id=cluster['uid'],
26
- synced_type='KubernetesCluster',
24
+ group_type="KubernetesCluster",
25
+ group_id=cluster["uid"],
26
+ synced_type="KubernetesCluster",
27
27
  update_tag=update_tag,
28
28
  stat_handler=stat_handler,
29
29
  )
@@ -49,7 +49,10 @@ def get_namespaces(client: K8sClient) -> Tuple[Dict, List[Dict]]:
49
49
 
50
50
 
51
51
  def load_namespaces(
52
- session: Session, cluster: Dict, data: List[Dict], update_tag: int,
52
+ session: Session,
53
+ cluster: Dict,
54
+ data: List[Dict],
55
+ update_tag: int,
53
56
  ) -> None:
54
57
  ingestion_cypher_query = """
55
58
  MERGE (cluster:KubernetesCluster {id: $cluster_id})
@@ -13,7 +13,10 @@ logger = logging.getLogger(__name__)
13
13
 
14
14
  @timeit
15
15
  def sync_pods(
16
- session: Session, client: K8sClient, update_tag: int, cluster: Dict,
16
+ session: Session,
17
+ client: K8sClient,
18
+ update_tag: int,
19
+ cluster: Dict,
17
20
  ) -> List[Dict]:
18
21
  pods = get_pods(client, cluster)
19
22
  load_pods(session, pods, update_tag)
@@ -34,11 +37,11 @@ def get_pods(client: K8sClient, cluster: Dict) -> List[Dict]:
34
37
  if pod.status and pod.status.container_statuses:
35
38
  for status in pod.status.container_statuses:
36
39
  if status.name in containers:
37
- _state = 'waiting'
40
+ _state = "waiting"
38
41
  if status.state.running:
39
- _state = 'running'
42
+ _state = "running"
40
43
  elif status.state.terminated:
41
- _state = 'terminated'
44
+ _state = "terminated"
42
45
  try:
43
46
  image_sha = status.image_id.split("@")[1]
44
47
  except IndexError:
@@ -13,7 +13,11 @@ logger = logging.getLogger(__name__)
13
13
 
14
14
  @timeit
15
15
  def sync_services(
16
- session: Session, client: K8sClient, update_tag: int, cluster: Dict, pods: List[Dict],
16
+ session: Session,
17
+ client: K8sClient,
18
+ update_tag: int,
19
+ cluster: Dict,
20
+ pods: List[Dict],
17
21
  ) -> None:
18
22
  services = get_services(client, cluster, pods)
19
23
  load_services(session, services, update_tag)
@@ -44,9 +48,9 @@ def get_services(client: K8sClient, cluster: Dict, pods: List[Dict]) -> List[Dic
44
48
  is_service_pod = True if service.spec.selector else False
45
49
  for selector in service.spec.selector or dict():
46
50
  if (
47
- not pod.get("labels") or
48
- selector not in pod["labels"] or
49
- service.spec.selector[selector] != pod["labels"][selector]
51
+ not pod.get("labels")
52
+ or selector not in pod["labels"]
53
+ or service.spec.selector[selector] != pod["labels"][selector]
50
54
  ):
51
55
  is_service_pod = False
52
56
  break
@@ -20,8 +20,8 @@ def start_lastpass_ingestion(neo4j_session: neo4j.Session, config: Config) -> No
20
20
 
21
21
  if not config.lastpass_cid or not config.lastpass_provhash:
22
22
  logger.info(
23
- 'Lastpass import is not configured - skipping this module. '
24
- 'See docs to configure.',
23
+ "Lastpass import is not configured - skipping this module. "
24
+ "See docs to configure.",
25
25
  )
26
26
  return
27
27
 
@@ -35,13 +35,17 @@ def sync(
35
35
  @timeit
36
36
  def get(lastpass_provhash: str, tenant_id: int) -> Dict[str, Any]:
37
37
  payload = {
38
- 'cid': tenant_id,
39
- 'provhash': lastpass_provhash,
40
- 'cmd': 'getuserdata',
41
- 'data': None,
38
+ "cid": tenant_id,
39
+ "provhash": lastpass_provhash,
40
+ "cmd": "getuserdata",
41
+ "data": None,
42
42
  }
43
43
  session = Session()
44
- req = session.post('https://lastpass.com/enterpriseapi.php', data=payload, timeout=_TIMEOUT)
44
+ req = session.post(
45
+ "https://lastpass.com/enterpriseapi.php",
46
+ data=payload,
47
+ timeout=_TIMEOUT,
48
+ )
45
49
  req.raise_for_status()
46
50
  return req.json()
47
51
 
@@ -49,11 +53,13 @@ def get(lastpass_provhash: str, tenant_id: int) -> Dict[str, Any]:
49
53
  @timeit
50
54
  def transform(api_result: Dict[str, Any]) -> List[Dict[str, Any]]:
51
55
  result: List[Dict[str, Any]] = []
52
- for uid, user in api_result['Users'].items():
56
+ for uid, user in api_result["Users"].items():
53
57
  n_user = user.copy()
54
- n_user['id'] = int(uid)
55
- for k in ('created', 'last_pw_change', 'last_login'):
56
- n_user[k] = int(dt_parse.parse(user[k]).timestamp() * 1000) if user[k] else None
58
+ n_user["id"] = int(uid)
59
+ for k in ("created", "last_pw_change", "last_login"):
60
+ n_user[k] = (
61
+ int(dt_parse.parse(user[k]).timestamp() * 1000) if user[k] else None
62
+ )
57
63
  result.append(n_user)
58
64
  return result
59
65
 
@@ -68,7 +74,7 @@ def load_users(
68
74
  load(
69
75
  neo4j_session,
70
76
  LastpassTenantSchema(),
71
- [{'id': tenant_id}],
77
+ [{"id": tenant_id}],
72
78
  lastupdated=update_tag,
73
79
  )
74
80
 
@@ -81,5 +87,10 @@ def load_users(
81
87
  )
82
88
 
83
89
 
84
- def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]) -> None:
85
- GraphJob.from_node_schema(LastpassUserSchema(), common_job_parameters).run(neo4j_session)
90
+ def cleanup(
91
+ neo4j_session: neo4j.Session,
92
+ common_job_parameters: Dict[str, Any],
93
+ ) -> None:
94
+ GraphJob.from_node_schema(LastpassUserSchema(), common_job_parameters).run(
95
+ neo4j_session,
96
+ )
@@ -11,17 +11,19 @@ from oci.exceptions import ConfigFileNotFound
11
11
  from oci.exceptions import InvalidConfig
12
12
  from oci.exceptions import ProfileNotFound
13
13
 
14
+ from cartography.config import Config
15
+
14
16
  from . import iam
15
17
  from . import organizations
16
18
  from . import utils
17
- from cartography.config import Config
19
+
18
20
  # from cartography.util import run_analysis_job
19
21
  # from cartography.util import run_cleanup_job
20
22
  # from . import network
21
23
  # from . import compute
22
24
 
23
25
  logger = logging.getLogger(__name__)
24
- Resources = namedtuple('Resources', 'compute iam network')
26
+ Resources = namedtuple("Resources", "compute iam network")
25
27
 
26
28
 
27
29
  def _sync_one_account(
@@ -32,11 +34,21 @@ def _sync_one_account(
32
34
  common_job_parameters: Dict[str, Any],
33
35
  ) -> None:
34
36
  logger.info("Syncing OCI IAM client for OCI Tenancy with ID '%s'.", tenancy_id)
35
- iam.sync(neo4j_session, resources.iam, tenancy_id, oci_sync_tag, common_job_parameters)
37
+ iam.sync(
38
+ neo4j_session,
39
+ resources.iam,
40
+ tenancy_id,
41
+ oci_sync_tag,
42
+ common_job_parameters,
43
+ )
36
44
 
37
45
  regions = utils.get_regions_in_tenancy(neo4j_session, tenancy_id)
38
46
  for region in regions:
39
- logger.info("Syncing OCI region '%s' for OCI Tenancy with ID '%s'.", region["name"], tenancy_id)
47
+ logger.info(
48
+ "Syncing OCI region '%s' for OCI Tenancy with ID '%s'.",
49
+ region["name"],
50
+ tenancy_id,
51
+ )
40
52
  _change_resources_region(resources, region["name"])
41
53
  # compute.sync(neo4j_session, resources.compute,
42
54
  # tenancy_id, region["name"], oci_sync_tag, common_job_parameters
@@ -56,15 +68,25 @@ def _sync_multiple_accounts(
56
68
  sync_tag: int,
57
69
  common_job_parameters: Dict[str, Any],
58
70
  ) -> None:
59
- logger.debug("Syncing OCI accounts: %s", ', '.join(accounts.keys()))
71
+ logger.debug("Syncing OCI accounts: %s", ", ".join(accounts.keys()))
60
72
  organizations.sync(neo4j_session, accounts, sync_tag, common_job_parameters)
61
73
 
62
74
  for name in accounts:
63
- logger.info("Syncing OCI Tenancy with ID '%s' using configured profile '%s'.", accounts[name]["tenancy"], name)
75
+ logger.info(
76
+ "Syncing OCI Tenancy with ID '%s' using configured profile '%s'.",
77
+ accounts[name]["tenancy"],
78
+ name,
79
+ )
64
80
  resources = _initialize_resources(accounts[name])
65
81
  tenancy_id = accounts[name]["tenancy"]
66
82
  common_job_parameters["OCI_TENANCY_ID"] = tenancy_id
67
- _sync_one_account(neo4j_session, resources, tenancy_id, sync_tag, common_job_parameters)
83
+ _sync_one_account(
84
+ neo4j_session,
85
+ resources,
86
+ tenancy_id,
87
+ sync_tag,
88
+ common_job_parameters,
89
+ )
68
90
 
69
91
  del common_job_parameters["OCI_TENANCY_ID"]
70
92
 
@@ -82,7 +104,9 @@ def _change_resources_region(resources: NamedTuple, region: str) -> None:
82
104
  resource.base_client.set_region(region)
83
105
 
84
106
 
85
- def _get_network_resource(credentials: Dict[str, Any]) -> oci.core.virtual_network_client.VirtualNetworkClient:
107
+ def _get_network_resource(
108
+ credentials: Dict[str, Any],
109
+ ) -> oci.core.virtual_network_client.VirtualNetworkClient:
86
110
  """
87
111
  Instantiates a OCI VirtualNetworkClient resource object to call the Network API.
88
112
  See https://docs.cloud.oracle.com/en-us/iaas/Content/Network/Concepts/overview.htm.
@@ -92,7 +116,9 @@ def _get_network_resource(credentials: Dict[str, Any]) -> oci.core.virtual_netwo
92
116
  return oci.core.VirtualNetworkClient(credentials)
93
117
 
94
118
 
95
- def _get_iam_resource(credentials: Dict[str, Any]) -> oci.identity.identity_client.IdentityClient:
119
+ def _get_iam_resource(
120
+ credentials: Dict[str, Any],
121
+ ) -> oci.identity.identity_client.IdentityClient:
96
122
  """
97
123
  Instantiates a OCI IdentityCleint resource object to call the Identity API. This is used to users,
98
124
  ..., ... and ... data. See https://docs.cloud.oracle.com/iaas/Content/Compute/Concepts/computeoverview.htm.
@@ -102,7 +128,9 @@ def _get_iam_resource(credentials: Dict[str, Any]) -> oci.identity.identity_clie
102
128
  return oci.identity.IdentityClient(credentials)
103
129
 
104
130
 
105
- def _get_compute_resource(credentials: Dict[str, Any]) -> oci.core.compute_client.ComputeClient:
131
+ def _get_compute_resource(
132
+ credentials: Dict[str, Any],
133
+ ) -> oci.core.compute_client.ComputeClient:
106
134
  """
107
135
  Instantiates a OCI ComputeClient resource object to call the Compute API. This is used to pull zone, instance, and
108
136
  networking data. https://docs.cloud.oracle.com/iaas/Content/Compute/Concepts/computeoverview.htm.
@@ -180,7 +208,12 @@ def start_oci_ingestion(neo4j_session: neo4j.Session, config: Config) -> None:
180
208
  )
181
209
  return
182
210
 
183
- _sync_multiple_accounts(neo4j_session, oci_accounts, config.update_tag, common_job_parameters)
211
+ _sync_multiple_accounts(
212
+ neo4j_session,
213
+ oci_accounts,
214
+ config.update_tag,
215
+ common_job_parameters,
216
+ )
184
217
 
185
218
  # Look into adding analysis job once compute is implemented.
186
219
  # run_analysis_job(