cartography 0.102.0rc1__py3-none-any.whl → 0.103.0__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 (297) hide show
  1. cartography/__main__.py +1 -2
  2. cartography/_version.py +2 -2
  3. cartography/cli.py +376 -249
  4. cartography/client/core/tx.py +39 -18
  5. cartography/config.py +28 -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/cloudwatch.py +93 -0
  23. cartography/intel/aws/config.py +56 -20
  24. cartography/intel/aws/dynamodb.py +108 -40
  25. cartography/intel/aws/ec2/__init__.py +2 -2
  26. cartography/intel/aws/ec2/auto_scaling_groups.py +181 -78
  27. cartography/intel/aws/ec2/elastic_ip_addresses.py +41 -13
  28. cartography/intel/aws/ec2/images.py +49 -20
  29. cartography/intel/aws/ec2/instances.py +234 -136
  30. cartography/intel/aws/ec2/internet_gateways.py +40 -11
  31. cartography/intel/aws/ec2/key_pairs.py +44 -20
  32. cartography/intel/aws/ec2/launch_templates.py +101 -59
  33. cartography/intel/aws/ec2/load_balancer_v2s.py +104 -39
  34. cartography/intel/aws/ec2/load_balancers.py +82 -42
  35. cartography/intel/aws/ec2/network_acls.py +89 -65
  36. cartography/intel/aws/ec2/network_interfaces.py +146 -87
  37. cartography/intel/aws/ec2/reserved_instances.py +45 -16
  38. cartography/intel/aws/ec2/route_tables.py +327 -0
  39. cartography/intel/aws/ec2/security_groups.py +71 -21
  40. cartography/intel/aws/ec2/snapshots.py +61 -22
  41. cartography/intel/aws/ec2/subnets.py +54 -18
  42. cartography/intel/aws/ec2/tgw.py +100 -34
  43. cartography/intel/aws/ec2/util.py +1 -1
  44. cartography/intel/aws/ec2/volumes.py +69 -41
  45. cartography/intel/aws/ec2/vpc.py +37 -12
  46. cartography/intel/aws/ec2/vpc_peerings.py +83 -24
  47. cartography/intel/aws/ecr.py +88 -32
  48. cartography/intel/aws/ecs.py +83 -47
  49. cartography/intel/aws/efs.py +93 -0
  50. cartography/intel/aws/eks.py +55 -29
  51. cartography/intel/aws/elasticache.py +42 -18
  52. cartography/intel/aws/elasticsearch.py +57 -20
  53. cartography/intel/aws/emr.py +61 -23
  54. cartography/intel/aws/iam.py +401 -145
  55. cartography/intel/aws/iam_instance_profiles.py +22 -22
  56. cartography/intel/aws/identitycenter.py +71 -37
  57. cartography/intel/aws/inspector.py +159 -89
  58. cartography/intel/aws/kms.py +92 -38
  59. cartography/intel/aws/lambda_function.py +103 -34
  60. cartography/intel/aws/organizations.py +30 -10
  61. cartography/intel/aws/permission_relationships.py +133 -51
  62. cartography/intel/aws/rds.py +249 -85
  63. cartography/intel/aws/redshift.py +107 -46
  64. cartography/intel/aws/resourcegroupstaggingapi.py +120 -66
  65. cartography/intel/aws/resources.py +57 -44
  66. cartography/intel/aws/route53.py +108 -61
  67. cartography/intel/aws/s3.py +168 -83
  68. cartography/intel/aws/s3accountpublicaccessblock.py +157 -0
  69. cartography/intel/aws/secretsmanager.py +24 -12
  70. cartography/intel/aws/securityhub.py +20 -9
  71. cartography/intel/aws/sns.py +166 -0
  72. cartography/intel/aws/sqs.py +60 -28
  73. cartography/intel/aws/ssm.py +70 -30
  74. cartography/intel/aws/util/arns.py +7 -7
  75. cartography/intel/aws/util/common.py +31 -4
  76. cartography/intel/azure/__init__.py +78 -19
  77. cartography/intel/azure/compute.py +101 -27
  78. cartography/intel/azure/cosmosdb.py +496 -170
  79. cartography/intel/azure/sql.py +296 -105
  80. cartography/intel/azure/storage.py +322 -113
  81. cartography/intel/azure/subscription.py +39 -23
  82. cartography/intel/azure/tenant.py +13 -4
  83. cartography/intel/azure/util/credentials.py +95 -55
  84. cartography/intel/bigfix/__init__.py +2 -2
  85. cartography/intel/bigfix/computers.py +93 -65
  86. cartography/intel/cloudflare/__init__.py +74 -0
  87. cartography/intel/cloudflare/accounts.py +57 -0
  88. cartography/intel/cloudflare/dnsrecords.py +64 -0
  89. cartography/intel/cloudflare/members.py +75 -0
  90. cartography/intel/cloudflare/roles.py +65 -0
  91. cartography/intel/cloudflare/zones.py +64 -0
  92. cartography/intel/create_indexes.py +3 -2
  93. cartography/intel/crowdstrike/__init__.py +11 -9
  94. cartography/intel/crowdstrike/endpoints.py +5 -1
  95. cartography/intel/crowdstrike/spotlight.py +8 -3
  96. cartography/intel/cve/__init__.py +46 -13
  97. cartography/intel/cve/feed.py +48 -12
  98. cartography/intel/digitalocean/__init__.py +22 -13
  99. cartography/intel/digitalocean/compute.py +75 -108
  100. cartography/intel/digitalocean/management.py +44 -80
  101. cartography/intel/digitalocean/platform.py +48 -43
  102. cartography/intel/dns.py +36 -10
  103. cartography/intel/duo/__init__.py +21 -16
  104. cartography/intel/duo/api_host.py +14 -9
  105. cartography/intel/duo/endpoints.py +50 -45
  106. cartography/intel/duo/groups.py +18 -14
  107. cartography/intel/duo/phones.py +37 -34
  108. cartography/intel/duo/tokens.py +26 -23
  109. cartography/intel/duo/users.py +54 -50
  110. cartography/intel/duo/web_authn_credentials.py +30 -25
  111. cartography/intel/entra/__init__.py +25 -7
  112. cartography/intel/entra/ou.py +112 -0
  113. cartography/intel/entra/users.py +69 -63
  114. cartography/intel/gcp/__init__.py +185 -49
  115. cartography/intel/gcp/compute.py +418 -231
  116. cartography/intel/gcp/crm.py +96 -43
  117. cartography/intel/gcp/dns.py +60 -19
  118. cartography/intel/gcp/gke.py +72 -38
  119. cartography/intel/gcp/iam.py +61 -41
  120. cartography/intel/gcp/storage.py +84 -55
  121. cartography/intel/github/__init__.py +13 -11
  122. cartography/intel/github/repos.py +270 -137
  123. cartography/intel/github/teams.py +170 -88
  124. cartography/intel/github/users.py +70 -39
  125. cartography/intel/github/util.py +36 -34
  126. cartography/intel/gsuite/__init__.py +47 -26
  127. cartography/intel/gsuite/api.py +73 -30
  128. cartography/intel/jamf/__init__.py +19 -1
  129. cartography/intel/jamf/computers.py +30 -7
  130. cartography/intel/jamf/util.py +7 -2
  131. cartography/intel/kandji/__init__.py +6 -3
  132. cartography/intel/kandji/devices.py +14 -8
  133. cartography/intel/kubernetes/namespaces.py +7 -4
  134. cartography/intel/kubernetes/pods.py +7 -4
  135. cartography/intel/kubernetes/services.py +8 -4
  136. cartography/intel/lastpass/__init__.py +2 -2
  137. cartography/intel/lastpass/users.py +23 -12
  138. cartography/intel/oci/__init__.py +44 -11
  139. cartography/intel/oci/iam.py +134 -38
  140. cartography/intel/oci/organizations.py +13 -6
  141. cartography/intel/oci/utils.py +43 -20
  142. cartography/intel/okta/__init__.py +66 -15
  143. cartography/intel/okta/applications.py +42 -20
  144. cartography/intel/okta/awssaml.py +93 -33
  145. cartography/intel/okta/factors.py +16 -4
  146. cartography/intel/okta/groups.py +56 -29
  147. cartography/intel/okta/organization.py +5 -1
  148. cartography/intel/okta/origins.py +6 -2
  149. cartography/intel/okta/roles.py +15 -5
  150. cartography/intel/okta/users.py +20 -8
  151. cartography/intel/okta/utils.py +6 -4
  152. cartography/intel/openai/__init__.py +86 -0
  153. cartography/intel/openai/adminapikeys.py +90 -0
  154. cartography/intel/openai/apikeys.py +96 -0
  155. cartography/intel/openai/projects.py +94 -0
  156. cartography/intel/openai/serviceaccounts.py +82 -0
  157. cartography/intel/openai/users.py +78 -0
  158. cartography/intel/openai/util.py +29 -0
  159. cartography/intel/pagerduty/__init__.py +8 -7
  160. cartography/intel/pagerduty/escalation_policies.py +18 -6
  161. cartography/intel/pagerduty/schedules.py +12 -4
  162. cartography/intel/pagerduty/services.py +11 -4
  163. cartography/intel/pagerduty/teams.py +8 -3
  164. cartography/intel/pagerduty/users.py +3 -1
  165. cartography/intel/pagerduty/vendors.py +3 -1
  166. cartography/intel/semgrep/__init__.py +24 -6
  167. cartography/intel/semgrep/dependencies.py +50 -28
  168. cartography/intel/semgrep/deployment.py +3 -1
  169. cartography/intel/semgrep/findings.py +42 -18
  170. cartography/intel/snipeit/__init__.py +17 -3
  171. cartography/intel/snipeit/asset.py +12 -6
  172. cartography/intel/snipeit/user.py +8 -5
  173. cartography/intel/snipeit/util.py +9 -4
  174. cartography/intel/tailscale/__init__.py +77 -0
  175. cartography/intel/tailscale/acls.py +146 -0
  176. cartography/intel/tailscale/devices.py +127 -0
  177. cartography/intel/tailscale/postureintegrations.py +81 -0
  178. cartography/intel/tailscale/tailnets.py +76 -0
  179. cartography/intel/tailscale/users.py +80 -0
  180. cartography/intel/tailscale/utils.py +132 -0
  181. cartography/models/aws/apigateway.py +21 -17
  182. cartography/models/aws/apigatewaycertificate.py +28 -22
  183. cartography/models/aws/apigatewayresource.py +28 -20
  184. cartography/models/aws/apigatewaystage.py +33 -25
  185. cartography/models/aws/cloudtrail/__init__.py +0 -0
  186. cartography/models/aws/cloudtrail/trail.py +61 -0
  187. cartography/models/aws/cloudwatch/__init__.py +0 -0
  188. cartography/models/aws/cloudwatch/loggroup.py +52 -0
  189. cartography/models/aws/dynamodb/gsi.py +30 -22
  190. cartography/models/aws/dynamodb/tables.py +25 -17
  191. cartography/models/aws/ec2/auto_scaling_groups.py +102 -82
  192. cartography/models/aws/ec2/images.py +36 -34
  193. cartography/models/aws/ec2/instances.py +51 -45
  194. cartography/models/aws/ec2/keypair.py +21 -16
  195. cartography/models/aws/ec2/keypair_instance.py +28 -21
  196. cartography/models/aws/ec2/launch_configurations.py +30 -26
  197. cartography/models/aws/ec2/launch_template_versions.py +48 -38
  198. cartography/models/aws/ec2/launch_templates.py +21 -17
  199. cartography/models/aws/ec2/load_balancer_listeners.py +27 -23
  200. cartography/models/aws/ec2/load_balancers.py +47 -37
  201. cartography/models/aws/ec2/network_acl_rules.py +38 -30
  202. cartography/models/aws/ec2/network_acls.py +38 -29
  203. cartography/models/aws/ec2/networkinterface_instance.py +52 -39
  204. cartography/models/aws/ec2/networkinterfaces.py +53 -37
  205. cartography/models/aws/ec2/privateip_networkinterface.py +32 -22
  206. cartography/models/aws/ec2/reservations.py +18 -14
  207. cartography/models/aws/ec2/route_table_associations.py +97 -0
  208. cartography/models/aws/ec2/route_tables.py +128 -0
  209. cartography/models/aws/ec2/routes.py +85 -0
  210. cartography/models/aws/ec2/securitygroup_instance.py +29 -20
  211. cartography/models/aws/ec2/securitygroup_networkinterface.py +24 -15
  212. cartography/models/aws/ec2/subnet_instance.py +24 -19
  213. cartography/models/aws/ec2/subnet_networkinterface.py +40 -31
  214. cartography/models/aws/ec2/volumes.py +47 -40
  215. cartography/models/aws/efs/__init__.py +0 -0
  216. cartography/models/aws/efs/mount_target.py +52 -0
  217. cartography/models/aws/eks/clusters.py +23 -21
  218. cartography/models/aws/emr.py +32 -30
  219. cartography/models/aws/iam/instanceprofile.py +33 -24
  220. cartography/models/aws/identitycenter/awsidentitycenter.py +18 -14
  221. cartography/models/aws/identitycenter/awspermissionset.py +37 -29
  222. cartography/models/aws/identitycenter/awsssouser.py +23 -21
  223. cartography/models/aws/inspector/findings.py +77 -65
  224. cartography/models/aws/inspector/packages.py +35 -29
  225. cartography/models/aws/s3/__init__.py +0 -0
  226. cartography/models/aws/s3/account_public_access_block.py +51 -0
  227. cartography/models/aws/sns/__init__.py +0 -0
  228. cartography/models/aws/sns/topic.py +50 -0
  229. cartography/models/aws/ssm/instance_information.py +51 -39
  230. cartography/models/aws/ssm/instance_patch.py +32 -26
  231. cartography/models/bigfix/bigfix_computer.py +42 -38
  232. cartography/models/bigfix/bigfix_root.py +3 -3
  233. cartography/models/cloudflare/__init__.py +0 -0
  234. cartography/models/cloudflare/account.py +25 -0
  235. cartography/models/cloudflare/dnsrecord.py +55 -0
  236. cartography/models/cloudflare/member.py +82 -0
  237. cartography/models/cloudflare/role.py +44 -0
  238. cartography/models/cloudflare/zone.py +59 -0
  239. cartography/models/core/common.py +12 -10
  240. cartography/models/core/nodes.py +5 -2
  241. cartography/models/core/relationships.py +14 -6
  242. cartography/models/crowdstrike/hosts.py +37 -35
  243. cartography/models/cve/cve.py +34 -32
  244. cartography/models/cve/cve_feed.py +6 -6
  245. cartography/models/digitalocean/__init__.py +0 -0
  246. cartography/models/digitalocean/account.py +21 -0
  247. cartography/models/digitalocean/droplet.py +56 -0
  248. cartography/models/digitalocean/project.py +48 -0
  249. cartography/models/duo/api_host.py +3 -3
  250. cartography/models/duo/endpoint.py +43 -41
  251. cartography/models/duo/group.py +14 -14
  252. cartography/models/duo/phone.py +27 -27
  253. cartography/models/duo/token.py +16 -16
  254. cartography/models/duo/user.py +46 -44
  255. cartography/models/duo/web_authn_credential.py +27 -19
  256. cartography/models/entra/ou.py +48 -0
  257. cartography/models/entra/tenant.py +24 -18
  258. cartography/models/entra/user.py +64 -48
  259. cartography/models/gcp/iam.py +23 -23
  260. cartography/models/github/orgs.py +5 -4
  261. cartography/models/github/teams.py +37 -31
  262. cartography/models/github/users.py +34 -23
  263. cartography/models/kandji/device.py +22 -16
  264. cartography/models/kandji/tenant.py +6 -4
  265. cartography/models/lastpass/tenant.py +3 -3
  266. cartography/models/lastpass/user.py +32 -28
  267. cartography/models/openai/__init__.py +0 -0
  268. cartography/models/openai/adminapikey.py +90 -0
  269. cartography/models/openai/apikey.py +84 -0
  270. cartography/models/openai/organization.py +17 -0
  271. cartography/models/openai/project.py +70 -0
  272. cartography/models/openai/serviceaccount.py +50 -0
  273. cartography/models/openai/user.py +49 -0
  274. cartography/models/semgrep/dependencies.py +36 -24
  275. cartography/models/semgrep/deployment.py +5 -5
  276. cartography/models/semgrep/findings.py +58 -42
  277. cartography/models/semgrep/locations.py +27 -21
  278. cartography/models/snipeit/asset.py +30 -21
  279. cartography/models/snipeit/tenant.py +6 -4
  280. cartography/models/snipeit/user.py +19 -12
  281. cartography/models/tailscale/__init__.py +0 -0
  282. cartography/models/tailscale/device.py +95 -0
  283. cartography/models/tailscale/group.py +86 -0
  284. cartography/models/tailscale/postureintegration.py +58 -0
  285. cartography/models/tailscale/tag.py +102 -0
  286. cartography/models/tailscale/tailnet.py +29 -0
  287. cartography/models/tailscale/user.py +52 -0
  288. cartography/stats.py +3 -3
  289. cartography/sync.py +113 -31
  290. cartography/util.py +84 -62
  291. {cartography-0.102.0rc1.dist-info → cartography-0.103.0.dist-info}/METADATA +8 -15
  292. cartography-0.103.0.dist-info/RECORD +442 -0
  293. {cartography-0.102.0rc1.dist-info → cartography-0.103.0.dist-info}/WHEEL +1 -1
  294. cartography-0.102.0rc1.dist-info/RECORD +0 -377
  295. {cartography-0.102.0rc1.dist-info → cartography-0.103.0.dist-info}/entry_points.txt +0 -0
  296. {cartography-0.102.0rc1.dist-info → cartography-0.103.0.dist-info}/licenses/LICENSE +0 -0
  297. {cartography-0.102.0rc1.dist-info → cartography-0.103.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,80 @@
1
+ import logging
2
+ from typing import Any
3
+ from typing import Dict
4
+ from typing import List
5
+
6
+ import neo4j
7
+ import requests
8
+
9
+ from cartography.client.core.tx import load
10
+ from cartography.graph.job import GraphJob
11
+ from cartography.models.tailscale.user import TailscaleUserSchema
12
+ from cartography.util import timeit
13
+
14
+ logger = logging.getLogger(__name__)
15
+ # Connect and read timeouts of 60 seconds each; see https://requests.readthedocs.io/en/master/user/advanced/#timeouts
16
+ _TIMEOUT = (60, 60)
17
+
18
+
19
+ @timeit
20
+ def sync(
21
+ neo4j_session: neo4j.Session,
22
+ api_session: requests.Session,
23
+ common_job_parameters: Dict[str, Any],
24
+ org: str,
25
+ ) -> List[Dict]:
26
+ users = get(
27
+ api_session,
28
+ common_job_parameters["BASE_URL"],
29
+ org,
30
+ )
31
+ load_users(
32
+ neo4j_session,
33
+ users,
34
+ org,
35
+ common_job_parameters["UPDATE_TAG"],
36
+ )
37
+ cleanup(neo4j_session, common_job_parameters)
38
+ return users
39
+
40
+
41
+ @timeit
42
+ def get(
43
+ api_session: requests.Session,
44
+ base_url: str,
45
+ org: str,
46
+ ) -> List[Dict[str, Any]]:
47
+ results: List[Dict[str, Any]] = []
48
+ req = api_session.get(
49
+ f"{base_url}/tailnet/{org}/users",
50
+ timeout=_TIMEOUT,
51
+ )
52
+ req.raise_for_status()
53
+ results = req.json()["users"]
54
+ return results
55
+
56
+
57
+ @timeit
58
+ def load_users(
59
+ neo4j_session: neo4j.Session,
60
+ data: List[Dict[str, Any]],
61
+ org: str,
62
+ update_tag: int,
63
+ ) -> None:
64
+ logger.info(f"Loading {len(data)} Tailscale Users to the graph")
65
+ load(
66
+ neo4j_session,
67
+ TailscaleUserSchema(),
68
+ data,
69
+ lastupdated=update_tag,
70
+ org=org,
71
+ )
72
+
73
+
74
+ @timeit
75
+ def cleanup(
76
+ neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
77
+ ) -> None:
78
+ GraphJob.from_node_schema(TailscaleUserSchema(), common_job_parameters).run(
79
+ neo4j_session
80
+ )
@@ -0,0 +1,132 @@
1
+ import json
2
+ import re
3
+ from typing import Any
4
+ from typing import Dict
5
+ from typing import List
6
+
7
+
8
+ class ACLParser:
9
+ """ACLParser is a class that parses Tailscale ACLs to extract data.
10
+
11
+ It removes comments and trailing commas from the ACL string
12
+ and converts it to a JSON object. It then provides methods
13
+ to extract groups and tags from the ACL.
14
+ The ACL string is expected to be in a format similar to JSON,
15
+ but with some Tailscale-specific syntax. The parser handles
16
+ single-line comments (//) and multi-line comments (/* */)
17
+ and removes trailing commas from the JSON-like structure.
18
+ The parser also handles Tailscale-specific syntax for groups
19
+ and tags, which may include user and group identifiers.
20
+ The parser is initialized with a raw ACL string, which is
21
+ processed to remove comments and trailing commas.
22
+
23
+ Args:
24
+ raw_acl (str): The raw ACL string to be parsed.
25
+
26
+ Attributes:
27
+ data (dict): The parsed JSON object representing the ACL.
28
+ """
29
+
30
+ RE_SINGLE_LINE_COMMENT = re.compile(r'("(?:(?=(\\?))\2.)*?")|(?:\/{2,}.*)')
31
+ RE_MULTI_LINE_COMMENT = re.compile(
32
+ r'("(?:(?=(\\?))\2.)*?")|(?:\/\*(?:(?!\*\/).)+\*\/)', flags=re.M | re.DOTALL
33
+ )
34
+ RE_TRAILING_COMMA = re.compile(r",(?=\s*?[\}\]])")
35
+
36
+ def __init__(self, raw_acl: str) -> None:
37
+ # Tailscale ACL use comments and trailing commas
38
+ # that are not valid JSON
39
+ filtered_json_string = self.RE_SINGLE_LINE_COMMENT.sub(r"\1", raw_acl)
40
+ filtered_json_string = self.RE_MULTI_LINE_COMMENT.sub(
41
+ r"\1", filtered_json_string
42
+ )
43
+ filtered_json_string = self.RE_TRAILING_COMMA.sub("", filtered_json_string)
44
+ self.data = json.loads(filtered_json_string)
45
+
46
+ def get_groups(self) -> List[Dict[str, Any]]:
47
+ """
48
+ Get all groups from the ACL
49
+
50
+ :return: list of groups
51
+ """
52
+ result: List[Dict[str, Any]] = []
53
+ groups = self.data.get("groups", {})
54
+ for group_id, members in groups.items():
55
+ group_name = group_id.split(":")[-1]
56
+ users_members = []
57
+ sub_groups = []
58
+ domain_members = []
59
+ for member in members:
60
+ if member.startswith("group:") or member.startswith("autogroup:"):
61
+ sub_groups.append(member)
62
+ elif member.startswith("user:*@"):
63
+ domain_members.append(member[7:])
64
+ elif member.startswith("user:"):
65
+ users_members.append(member[5:])
66
+ else:
67
+ users_members.append(member)
68
+ result.append(
69
+ {
70
+ "id": group_id,
71
+ "name": group_name,
72
+ "members": users_members,
73
+ "sub_groups": sub_groups,
74
+ "domain_members": domain_members,
75
+ }
76
+ )
77
+ return result
78
+
79
+ def get_tags(self) -> List[Dict[str, Any]]:
80
+ """
81
+ Get all tags from the ACL
82
+
83
+ :return: list of tags
84
+ """
85
+ result: List[Dict[str, Any]] = []
86
+ for tag, owners in self.data.get("tagOwners", {}).items():
87
+ tag_name = tag.split(":")[-1]
88
+ user_owners = []
89
+ group_owners = []
90
+ domain_owners = []
91
+ for owner in owners:
92
+ if owner.startswith("group:") or owner.startswith("autogroup:"):
93
+ group_owners.append(owner)
94
+ elif owner.startswith("user:*@"):
95
+ domain_owners.append(owner[7:])
96
+ elif owner.startswith("user:"):
97
+ user_owners.append(owner[5:])
98
+ else:
99
+ user_owners.append(owner)
100
+ result.append(
101
+ {
102
+ "id": tag,
103
+ "name": tag_name,
104
+ "owners": user_owners,
105
+ "group_owners": group_owners,
106
+ "domain_owners": domain_owners,
107
+ }
108
+ )
109
+ return result
110
+
111
+
112
+ def role_to_group(role: str) -> list[str]:
113
+ """Convert Tailscale role to group
114
+
115
+ This function is used to convert Tailscale role to autogroup
116
+ group. The autogroup is used to manage the access control
117
+ in Tailscale.
118
+
119
+ Args:
120
+ role (str): The role of the user in Tailscale. (eg: owner, admin, member, etc)
121
+
122
+ Returns:
123
+ list[str]: The list of autogroup that the user belongs to. (eg: autogroup:admin, autogroup:member, etc)
124
+ """
125
+ result: list[str] = []
126
+ result.append(f"autogroup:{role}")
127
+ if role == "owner":
128
+ result.append("autogroup:admin")
129
+ result.append("autogroup:member")
130
+ elif role in ("admin", "auditor", "billing-admin", "it-admin", "network-admin"):
131
+ result.append("autogroup:member")
132
+ return result
@@ -12,36 +12,40 @@ from cartography.models.core.relationships import TargetNodeMatcher
12
12
 
13
13
  @dataclass(frozen=True)
14
14
  class APIGatewayRestAPINodeProperties(CartographyNodeProperties):
15
- id: PropertyRef = PropertyRef('id', extra_index=True)
16
- createddate: PropertyRef = PropertyRef('createdDate')
17
- version: PropertyRef = PropertyRef('version')
18
- minimumcompressionsize: PropertyRef = PropertyRef('minimumCompressionSize')
19
- disableexecuteapiendpoint: PropertyRef = PropertyRef('disableExecuteApiEndpoint')
20
- region: PropertyRef = PropertyRef('region', set_in_kwargs=True)
21
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
22
- anonymous_access: PropertyRef = PropertyRef('anonymous_access')
23
- anonymous_actions: PropertyRef = PropertyRef('anonymous_actions')
15
+ id: PropertyRef = PropertyRef("id", extra_index=True)
16
+ createddate: PropertyRef = PropertyRef("createdDate")
17
+ version: PropertyRef = PropertyRef("version")
18
+ minimumcompressionsize: PropertyRef = PropertyRef("minimumCompressionSize")
19
+ disableexecuteapiendpoint: PropertyRef = PropertyRef("disableExecuteApiEndpoint")
20
+ region: PropertyRef = PropertyRef("region", set_in_kwargs=True)
21
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
22
+ anonymous_access: PropertyRef = PropertyRef("anonymous_access")
23
+ anonymous_actions: PropertyRef = PropertyRef("anonymous_actions")
24
24
 
25
25
 
26
26
  @dataclass(frozen=True)
27
- class APIGatewayRestAPIToAwsAccountRelProperties(CartographyRelProperties):
28
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
27
+ class APIGatewayRestAPIToAWSAccountRelRelProperties(CartographyRelProperties):
28
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
29
29
 
30
30
 
31
31
  @dataclass(frozen=True)
32
32
  # (:APIGatewayRestAPI)<-[:RESOURCE]-(:AWSAccount)
33
- class APIGatewayRestAPIToAWSAccount(CartographyRelSchema):
34
- target_node_label: str = 'AWSAccount'
33
+ class APIGatewayRestAPIToAWSAccountRel(CartographyRelSchema):
34
+ target_node_label: str = "AWSAccount"
35
35
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
36
- {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
36
+ {"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
37
37
  )
38
38
  direction: LinkDirection = LinkDirection.INWARD
39
39
  rel_label: str = "RESOURCE"
40
- properties: APIGatewayRestAPIToAwsAccountRelProperties = APIGatewayRestAPIToAwsAccountRelProperties()
40
+ properties: APIGatewayRestAPIToAWSAccountRelRelProperties = (
41
+ APIGatewayRestAPIToAWSAccountRelRelProperties()
42
+ )
41
43
 
42
44
 
43
45
  @dataclass(frozen=True)
44
46
  class APIGatewayRestAPISchema(CartographyNodeSchema):
45
- label: str = 'APIGatewayRestAPI'
47
+ label: str = "APIGatewayRestAPI"
46
48
  properties: APIGatewayRestAPINodeProperties = APIGatewayRestAPINodeProperties()
47
- sub_resource_relationship: APIGatewayRestAPIToAWSAccount = APIGatewayRestAPIToAWSAccount()
49
+ sub_resource_relationship: APIGatewayRestAPIToAWSAccountRel = (
50
+ APIGatewayRestAPIToAWSAccountRel()
51
+ )
@@ -13,54 +13,60 @@ from cartography.models.core.relationships import TargetNodeMatcher
13
13
 
14
14
  @dataclass(frozen=True)
15
15
  class APIGatewayClientCertificateNodeProperties(CartographyNodeProperties):
16
- id: PropertyRef = PropertyRef('clientCertificateId')
17
- createddate: PropertyRef = PropertyRef('createdDate')
18
- expirationdate: PropertyRef = PropertyRef('expirationDate')
19
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
16
+ id: PropertyRef = PropertyRef("clientCertificateId")
17
+ createddate: PropertyRef = PropertyRef("createdDate")
18
+ expirationdate: PropertyRef = PropertyRef("expirationDate")
19
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
20
20
 
21
21
 
22
22
  @dataclass(frozen=True)
23
- class APIGatewayClientCertificateToStageRelProperties(CartographyRelProperties):
24
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
23
+ class APIGatewayClientCertificateToStageRelRelProperties(CartographyRelProperties):
24
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
25
25
 
26
26
 
27
27
  @dataclass(frozen=True)
28
- class CertToStageRelProps(CartographyRelProperties):
29
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
28
+ class CertToStageRelProperties(CartographyRelProperties):
29
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
30
30
 
31
31
 
32
32
  @dataclass(frozen=True)
33
33
  # (:APIGatewayStage)-[:HAS_CERTIFICATE]->(:APIGatewayClientCertificate)
34
- class APIGatewayClientCertificateToStage(CartographyRelSchema):
35
- target_node_label: str = 'APIGatewayStage'
34
+ class APIGatewayClientCertificateToStageRel(CartographyRelSchema):
35
+ target_node_label: str = "APIGatewayStage"
36
36
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
37
- {'id': PropertyRef('stageArn')},
37
+ {"id": PropertyRef("stageArn")},
38
38
  )
39
39
  direction: LinkDirection = LinkDirection.INWARD
40
40
  rel_label: str = "HAS_CERTIFICATE"
41
- properties: CertToStageRelProps = CertToStageRelProps()
41
+ properties: CertToStageRelProperties = CertToStageRelProperties()
42
42
 
43
43
 
44
44
  @dataclass(frozen=True)
45
- class CertToAccountRelProps(CartographyRelProperties):
46
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
45
+ class CertToAccountRelProperties(CartographyRelProperties):
46
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
47
47
 
48
48
 
49
49
  @dataclass(frozen=True)
50
50
  # (:APIGatewayClientCertificate)<-[:RESOURCE]-(:AWSAccount)
51
- class APIGatewayClientCertificateToAWSAccount(CartographyRelSchema):
52
- target_node_label: str = 'AWSAccount'
51
+ class APIGatewayClientCertificateToAWSAccountRel(CartographyRelSchema):
52
+ target_node_label: str = "AWSAccount"
53
53
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
54
- {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
54
+ {"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
55
55
  )
56
56
  direction: LinkDirection = LinkDirection.INWARD
57
57
  rel_label: str = "RESOURCE"
58
- properties: CertToAccountRelProps = CertToAccountRelProps()
58
+ properties: CertToAccountRelProperties = CertToAccountRelProperties()
59
59
 
60
60
 
61
61
  @dataclass(frozen=True)
62
62
  class APIGatewayClientCertificateSchema(CartographyNodeSchema):
63
- label: str = 'APIGatewayClientCertificate'
64
- properties: APIGatewayClientCertificateNodeProperties = APIGatewayClientCertificateNodeProperties()
65
- sub_resource_relationship: APIGatewayClientCertificateToAWSAccount = APIGatewayClientCertificateToAWSAccount()
66
- other_relationships: OtherRelationships = OtherRelationships([APIGatewayClientCertificateToStage()])
63
+ label: str = "APIGatewayClientCertificate"
64
+ properties: APIGatewayClientCertificateNodeProperties = (
65
+ APIGatewayClientCertificateNodeProperties()
66
+ )
67
+ sub_resource_relationship: APIGatewayClientCertificateToAWSAccountRel = (
68
+ APIGatewayClientCertificateToAWSAccountRel()
69
+ )
70
+ other_relationships: OtherRelationships = OtherRelationships(
71
+ [APIGatewayClientCertificateToStageRel()],
72
+ )
@@ -13,50 +13,58 @@ from cartography.models.core.relationships import TargetNodeMatcher
13
13
 
14
14
  @dataclass(frozen=True)
15
15
  class APIGatewayResourceNodeProperties(CartographyNodeProperties):
16
- id: PropertyRef = PropertyRef('id')
17
- path: PropertyRef = PropertyRef('path')
18
- pathpart: PropertyRef = PropertyRef('pathPart')
19
- parentid: PropertyRef = PropertyRef('parentId')
20
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
16
+ id: PropertyRef = PropertyRef("id")
17
+ path: PropertyRef = PropertyRef("path")
18
+ pathpart: PropertyRef = PropertyRef("pathPart")
19
+ parentid: PropertyRef = PropertyRef("parentId")
20
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
21
21
 
22
22
 
23
23
  @dataclass(frozen=True)
24
- class APIGatewayResourceToRestAPIRelProperties(CartographyRelProperties):
25
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
24
+ class APIGatewayResourceToRestAPIRelRelProperties(CartographyRelProperties):
25
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
26
26
 
27
27
 
28
28
  @dataclass(frozen=True)
29
29
  # (:APIGatewayResource)<-[:RESOURCE]-(:APIGatewayRestAPI)
30
- class APIGatewayResourceToRestAPI(CartographyRelSchema):
31
- target_node_label: str = 'APIGatewayRestAPI'
30
+ class APIGatewayResourceToRestAPIRel(CartographyRelSchema):
31
+ target_node_label: str = "APIGatewayRestAPI"
32
32
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
33
- {'id': PropertyRef('apiId')},
33
+ {"id": PropertyRef("apiId")},
34
34
  )
35
35
  direction: LinkDirection = LinkDirection.INWARD
36
36
  rel_label: str = "RESOURCE"
37
- properties: APIGatewayResourceToRestAPIRelProperties = APIGatewayResourceToRestAPIRelProperties()
37
+ properties: APIGatewayResourceToRestAPIRelRelProperties = (
38
+ APIGatewayResourceToRestAPIRelRelProperties()
39
+ )
38
40
 
39
41
 
40
42
  @dataclass(frozen=True)
41
- class APIGatewayResourceToAwsAccountRelProperties(CartographyRelProperties):
42
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
43
+ class APIGatewayResourceToAWSAccountRelRelProperties(CartographyRelProperties):
44
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
43
45
 
44
46
 
45
47
  @dataclass(frozen=True)
46
48
  # (:APIGatewayResource)<-[:RESOURCE]-(:AWSAccount)
47
- class APIGatewayResourceToAWSAccount(CartographyRelSchema):
48
- target_node_label: str = 'AWSAccount'
49
+ class APIGatewayResourceToAWSAccountRel(CartographyRelSchema):
50
+ target_node_label: str = "AWSAccount"
49
51
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
50
- {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
52
+ {"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
51
53
  )
52
54
  direction: LinkDirection = LinkDirection.INWARD
53
55
  rel_label: str = "RESOURCE"
54
- properties: APIGatewayResourceToAwsAccountRelProperties = APIGatewayResourceToAwsAccountRelProperties()
56
+ properties: APIGatewayResourceToAWSAccountRelRelProperties = (
57
+ APIGatewayResourceToAWSAccountRelRelProperties()
58
+ )
55
59
 
56
60
 
57
61
  @dataclass(frozen=True)
58
62
  class APIGatewayResourceSchema(CartographyNodeSchema):
59
- label: str = 'APIGatewayResource'
63
+ label: str = "APIGatewayResource"
60
64
  properties: APIGatewayResourceNodeProperties = APIGatewayResourceNodeProperties()
61
- sub_resource_relationship: APIGatewayResourceToAWSAccount = APIGatewayResourceToAWSAccount()
62
- other_relationships: OtherRelationships = OtherRelationships([APIGatewayResourceToRestAPI()])
65
+ sub_resource_relationship: APIGatewayResourceToAWSAccountRel = (
66
+ APIGatewayResourceToAWSAccountRel()
67
+ )
68
+ other_relationships: OtherRelationships = OtherRelationships(
69
+ [APIGatewayResourceToRestAPIRel()],
70
+ )
@@ -13,55 +13,63 @@ from cartography.models.core.relationships import TargetNodeMatcher
13
13
 
14
14
  @dataclass(frozen=True)
15
15
  class APIGatewayStageNodeProperties(CartographyNodeProperties):
16
- id: PropertyRef = PropertyRef('arn')
17
- stagename: PropertyRef = PropertyRef('stageName')
18
- createddate: PropertyRef = PropertyRef('createdDate')
19
- deploymentid: PropertyRef = PropertyRef('deploymentId')
20
- clientcertificateid: PropertyRef = PropertyRef('clientCertificateId')
21
- cacheclusterenabled: PropertyRef = PropertyRef('cacheClusterEnabled')
22
- cacheclusterstatus: PropertyRef = PropertyRef('cacheClusterStatus')
23
- tracingenabled: PropertyRef = PropertyRef('tracingEnabled')
24
- webaclarn: PropertyRef = PropertyRef('webAclArn')
25
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
16
+ id: PropertyRef = PropertyRef("arn")
17
+ stagename: PropertyRef = PropertyRef("stageName")
18
+ createddate: PropertyRef = PropertyRef("createdDate")
19
+ deploymentid: PropertyRef = PropertyRef("deploymentId")
20
+ clientcertificateid: PropertyRef = PropertyRef("clientCertificateId")
21
+ cacheclusterenabled: PropertyRef = PropertyRef("cacheClusterEnabled")
22
+ cacheclusterstatus: PropertyRef = PropertyRef("cacheClusterStatus")
23
+ tracingenabled: PropertyRef = PropertyRef("tracingEnabled")
24
+ webaclarn: PropertyRef = PropertyRef("webAclArn")
25
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
26
26
 
27
27
 
28
28
  @dataclass(frozen=True)
29
- class APIGatewayStageToRestAPIRelProperties(CartographyRelProperties):
30
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
29
+ class APIGatewayStageToRestAPIRelRelProperties(CartographyRelProperties):
30
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
31
31
 
32
32
 
33
33
  @dataclass(frozen=True)
34
34
  # (:APIGatewayStage)<-[:ASSOCIATED_WITH]-(:APIGatewayRestAPI)
35
- class APIGatewayStageToRestAPI(CartographyRelSchema):
36
- target_node_label: str = 'APIGatewayRestAPI'
35
+ class APIGatewayStageToRestAPIRel(CartographyRelSchema):
36
+ target_node_label: str = "APIGatewayRestAPI"
37
37
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
38
- {'id': PropertyRef('apiId')},
38
+ {"id": PropertyRef("apiId")},
39
39
  )
40
40
  direction: LinkDirection = LinkDirection.INWARD
41
41
  rel_label: str = "ASSOCIATED_WITH"
42
- properties: APIGatewayStageToRestAPIRelProperties = APIGatewayStageToRestAPIRelProperties()
42
+ properties: APIGatewayStageToRestAPIRelRelProperties = (
43
+ APIGatewayStageToRestAPIRelRelProperties()
44
+ )
43
45
 
44
46
 
45
47
  @dataclass(frozen=True)
46
- class APIGatewayStageToAwsAccountRelProperties(CartographyRelProperties):
47
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
48
+ class APIGatewayStageToAWSAccountRelRelProperties(CartographyRelProperties):
49
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
48
50
 
49
51
 
50
52
  @dataclass(frozen=True)
51
53
  # (:APIGatewayStage)<-[:RESOURCE]-(:AWSAccount)
52
- class APIGatewayStageToAWSAccount(CartographyRelSchema):
53
- target_node_label: str = 'AWSAccount'
54
+ class APIGatewayStageToAWSAccountRel(CartographyRelSchema):
55
+ target_node_label: str = "AWSAccount"
54
56
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
55
- {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
57
+ {"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
56
58
  )
57
59
  direction: LinkDirection = LinkDirection.INWARD
58
60
  rel_label: str = "RESOURCE"
59
- properties: APIGatewayStageToAwsAccountRelProperties = APIGatewayStageToAwsAccountRelProperties()
61
+ properties: APIGatewayStageToAWSAccountRelRelProperties = (
62
+ APIGatewayStageToAWSAccountRelRelProperties()
63
+ )
60
64
 
61
65
 
62
66
  @dataclass(frozen=True)
63
67
  class APIGatewayStageSchema(CartographyNodeSchema):
64
- label: str = 'APIGatewayStage'
68
+ label: str = "APIGatewayStage"
65
69
  properties: APIGatewayStageNodeProperties = APIGatewayStageNodeProperties()
66
- sub_resource_relationship: APIGatewayStageToAWSAccount = APIGatewayStageToAWSAccount()
67
- other_relationships: OtherRelationships = OtherRelationships([APIGatewayStageToRestAPI()])
70
+ sub_resource_relationship: APIGatewayStageToAWSAccountRel = (
71
+ APIGatewayStageToAWSAccountRel()
72
+ )
73
+ other_relationships: OtherRelationships = OtherRelationships(
74
+ [APIGatewayStageToRestAPIRel()],
75
+ )
File without changes
@@ -0,0 +1,61 @@
1
+ from dataclasses import dataclass
2
+
3
+ from cartography.models.core.common import PropertyRef
4
+ from cartography.models.core.nodes import CartographyNodeProperties
5
+ from cartography.models.core.nodes import CartographyNodeSchema
6
+ from cartography.models.core.relationships import CartographyRelProperties
7
+ from cartography.models.core.relationships import CartographyRelSchema
8
+ from cartography.models.core.relationships import LinkDirection
9
+ from cartography.models.core.relationships import make_target_node_matcher
10
+ from cartography.models.core.relationships import TargetNodeMatcher
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class CloudTrailTrailNodeProperties(CartographyNodeProperties):
15
+ id: PropertyRef = PropertyRef("TrailARN")
16
+ arn: PropertyRef = PropertyRef("TrailARN")
17
+ name: PropertyRef = PropertyRef("Name")
18
+ region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
19
+ cloudwatch_logs_log_group_arn: PropertyRef = PropertyRef(
20
+ "CloudWatchLogsLogGroupArn"
21
+ )
22
+ cloudwatch_logs_role_arn: PropertyRef = PropertyRef("CloudWatchLogsRoleArn")
23
+ has_custom_event_selectors: PropertyRef = PropertyRef("HasCustomEventSelectors")
24
+ has_insight_selectors: PropertyRef = PropertyRef("HasInsightSelectors")
25
+ home_region: PropertyRef = PropertyRef("HomeRegion")
26
+ include_global_service_events: PropertyRef = PropertyRef(
27
+ "IncludeGlobalServiceEvents"
28
+ )
29
+ is_multi_region_trail: PropertyRef = PropertyRef("IsMultiRegionTrail")
30
+ is_organization_trail: PropertyRef = PropertyRef("IsOrganizationTrail")
31
+ kms_key_id: PropertyRef = PropertyRef("KmsKeyId")
32
+ log_file_validation_enabled: PropertyRef = PropertyRef("LogFileValidationEnabled")
33
+ s3_bucket_name: PropertyRef = PropertyRef("S3BucketName")
34
+ s3_key_prefix: PropertyRef = PropertyRef("S3KeyPrefix")
35
+ sns_topic_arn: PropertyRef = PropertyRef("SnsTopicARN")
36
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
37
+
38
+
39
+ @dataclass(frozen=True)
40
+ class CloudTrailTrailToAwsAccountRelProperties(CartographyRelProperties):
41
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
42
+
43
+
44
+ @dataclass(frozen=True)
45
+ class CloudTrailToAWSAccountRel(CartographyRelSchema):
46
+ target_node_label: str = "AWSAccount"
47
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
48
+ {"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
49
+ )
50
+ direction: LinkDirection = LinkDirection.INWARD
51
+ rel_label: str = "RESOURCE"
52
+ properties: CloudTrailTrailToAwsAccountRelProperties = (
53
+ CloudTrailTrailToAwsAccountRelProperties()
54
+ )
55
+
56
+
57
+ @dataclass(frozen=True)
58
+ class CloudTrailTrailSchema(CartographyNodeSchema):
59
+ label: str = "CloudTrailTrail"
60
+ properties: CloudTrailTrailNodeProperties = CloudTrailTrailNodeProperties()
61
+ sub_resource_relationship: CloudTrailToAWSAccountRel = CloudTrailToAWSAccountRel()
File without changes
@@ -0,0 +1,52 @@
1
+ from dataclasses import dataclass
2
+
3
+ from cartography.models.core.common import PropertyRef
4
+ from cartography.models.core.nodes import CartographyNodeProperties
5
+ from cartography.models.core.nodes import CartographyNodeSchema
6
+ from cartography.models.core.relationships import CartographyRelProperties
7
+ from cartography.models.core.relationships import CartographyRelSchema
8
+ from cartography.models.core.relationships import LinkDirection
9
+ from cartography.models.core.relationships import make_target_node_matcher
10
+ from cartography.models.core.relationships import TargetNodeMatcher
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class CloudWatchLogGroupNodeProperties(CartographyNodeProperties):
15
+ id: PropertyRef = PropertyRef("logGroupArn")
16
+ arn: PropertyRef = PropertyRef("logGroupArn", extra_index=True)
17
+ creation_time: PropertyRef = PropertyRef("creationTime")
18
+ data_protection_status: PropertyRef = PropertyRef("dataProtectionStatus")
19
+ inherited_properties: PropertyRef = PropertyRef("inheritedProperties")
20
+ kms_key_id: PropertyRef = PropertyRef("kmsKeyId")
21
+ log_group_arn: PropertyRef = PropertyRef("logGroupArn")
22
+ log_group_class: PropertyRef = PropertyRef("logGroupClass")
23
+ log_group_name: PropertyRef = PropertyRef("logGroupName")
24
+ metric_filter_count: PropertyRef = PropertyRef("metricFilterCount")
25
+ retention_in_days: PropertyRef = PropertyRef("retentionInDays")
26
+ stored_bytes: PropertyRef = PropertyRef("storedBytes")
27
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
28
+
29
+
30
+ @dataclass(frozen=True)
31
+ class CloudWatchLogGroupToAwsAccountRelProperties(CartographyRelProperties):
32
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
33
+
34
+
35
+ @dataclass(frozen=True)
36
+ class CloudWatchToAWSAccountRel(CartographyRelSchema):
37
+ target_node_label: str = "AWSAccount"
38
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
39
+ {"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
40
+ )
41
+ direction: LinkDirection = LinkDirection.INWARD
42
+ rel_label: str = "RESOURCE"
43
+ properties: CloudWatchLogGroupToAwsAccountRelProperties = (
44
+ CloudWatchLogGroupToAwsAccountRelProperties()
45
+ )
46
+
47
+
48
+ @dataclass(frozen=True)
49
+ class CloudWatchLogGroupSchema(CartographyNodeSchema):
50
+ label: str = "CloudWatchLogGroup"
51
+ properties: CloudWatchLogGroupNodeProperties = CloudWatchLogGroupNodeProperties()
52
+ sub_resource_relationship: CloudWatchToAWSAccountRel = CloudWatchToAWSAccountRel()