cartography 0.106.0rc2__py3-none-any.whl → 0.107.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 (92) hide show
  1. cartography/_version.py +2 -2
  2. cartography/cli.py +131 -2
  3. cartography/config.py +42 -0
  4. cartography/driftdetect/cli.py +3 -2
  5. cartography/intel/airbyte/__init__.py +105 -0
  6. cartography/intel/airbyte/connections.py +120 -0
  7. cartography/intel/airbyte/destinations.py +81 -0
  8. cartography/intel/airbyte/organizations.py +59 -0
  9. cartography/intel/airbyte/sources.py +78 -0
  10. cartography/intel/airbyte/tags.py +64 -0
  11. cartography/intel/airbyte/users.py +106 -0
  12. cartography/intel/airbyte/util.py +122 -0
  13. cartography/intel/airbyte/workspaces.py +63 -0
  14. cartography/intel/aws/__init__.py +1 -0
  15. cartography/intel/aws/cloudtrail_management_events.py +364 -0
  16. cartography/intel/aws/cloudwatch.py +77 -0
  17. cartography/intel/aws/codebuild.py +132 -0
  18. cartography/intel/aws/ec2/subnets.py +1 -1
  19. cartography/intel/aws/ecs.py +17 -0
  20. cartography/intel/aws/inspector.py +77 -48
  21. cartography/intel/aws/resources.py +4 -0
  22. cartography/intel/aws/sns.py +62 -2
  23. cartography/intel/entra/users.py +84 -42
  24. cartography/intel/scaleway/__init__.py +127 -0
  25. cartography/intel/scaleway/iam/__init__.py +0 -0
  26. cartography/intel/scaleway/iam/apikeys.py +71 -0
  27. cartography/intel/scaleway/iam/applications.py +71 -0
  28. cartography/intel/scaleway/iam/groups.py +71 -0
  29. cartography/intel/scaleway/iam/users.py +71 -0
  30. cartography/intel/scaleway/instances/__init__.py +0 -0
  31. cartography/intel/scaleway/instances/flexibleips.py +86 -0
  32. cartography/intel/scaleway/instances/instances.py +92 -0
  33. cartography/intel/scaleway/projects.py +79 -0
  34. cartography/intel/scaleway/storage/__init__.py +0 -0
  35. cartography/intel/scaleway/storage/snapshots.py +86 -0
  36. cartography/intel/scaleway/storage/volumes.py +84 -0
  37. cartography/intel/scaleway/utils.py +37 -0
  38. cartography/intel/sentinelone/__init__.py +69 -0
  39. cartography/intel/sentinelone/account.py +140 -0
  40. cartography/intel/sentinelone/agent.py +139 -0
  41. cartography/intel/sentinelone/api.py +113 -0
  42. cartography/intel/sentinelone/application.py +248 -0
  43. cartography/intel/sentinelone/utils.py +28 -0
  44. cartography/models/airbyte/__init__.py +0 -0
  45. cartography/models/airbyte/connection.py +138 -0
  46. cartography/models/airbyte/destination.py +75 -0
  47. cartography/models/airbyte/organization.py +19 -0
  48. cartography/models/airbyte/source.py +75 -0
  49. cartography/models/airbyte/stream.py +74 -0
  50. cartography/models/airbyte/tag.py +69 -0
  51. cartography/models/airbyte/user.py +111 -0
  52. cartography/models/airbyte/workspace.py +46 -0
  53. cartography/models/aws/cloudtrail/management_events.py +64 -0
  54. cartography/models/aws/cloudwatch/log_metric_filter.py +79 -0
  55. cartography/models/aws/codebuild/__init__.py +0 -0
  56. cartography/models/aws/codebuild/project.py +49 -0
  57. cartography/models/aws/ec2/networkinterfaces.py +2 -0
  58. cartography/models/aws/ec2/subnet_instance.py +2 -0
  59. cartography/models/aws/ec2/subnet_networkinterface.py +2 -0
  60. cartography/models/aws/ecs/containers.py +19 -0
  61. cartography/models/aws/ecs/task_definitions.py +38 -0
  62. cartography/models/aws/ecs/tasks.py +24 -1
  63. cartography/models/aws/inspector/findings.py +37 -0
  64. cartography/models/aws/inspector/packages.py +1 -31
  65. cartography/models/aws/sns/topic_subscription.py +74 -0
  66. cartography/models/entra/user.py +17 -51
  67. cartography/models/scaleway/__init__.py +0 -0
  68. cartography/models/scaleway/iam/__init__.py +0 -0
  69. cartography/models/scaleway/iam/apikey.py +96 -0
  70. cartography/models/scaleway/iam/application.py +52 -0
  71. cartography/models/scaleway/iam/group.py +95 -0
  72. cartography/models/scaleway/iam/user.py +60 -0
  73. cartography/models/scaleway/instance/__init__.py +0 -0
  74. cartography/models/scaleway/instance/flexibleip.py +52 -0
  75. cartography/models/scaleway/instance/instance.py +118 -0
  76. cartography/models/scaleway/organization.py +19 -0
  77. cartography/models/scaleway/project.py +48 -0
  78. cartography/models/scaleway/storage/__init__.py +0 -0
  79. cartography/models/scaleway/storage/snapshot.py +78 -0
  80. cartography/models/scaleway/storage/volume.py +51 -0
  81. cartography/models/sentinelone/__init__.py +1 -0
  82. cartography/models/sentinelone/account.py +40 -0
  83. cartography/models/sentinelone/agent.py +50 -0
  84. cartography/models/sentinelone/application.py +44 -0
  85. cartography/models/sentinelone/application_version.py +96 -0
  86. cartography/sync.py +11 -4
  87. {cartography-0.106.0rc2.dist-info → cartography-0.107.0.dist-info}/METADATA +20 -16
  88. {cartography-0.106.0rc2.dist-info → cartography-0.107.0.dist-info}/RECORD +92 -28
  89. {cartography-0.106.0rc2.dist-info → cartography-0.107.0.dist-info}/WHEEL +0 -0
  90. {cartography-0.106.0rc2.dist-info → cartography-0.107.0.dist-info}/entry_points.txt +0 -0
  91. {cartography-0.106.0rc2.dist-info → cartography-0.107.0.dist-info}/licenses/LICENSE +0 -0
  92. {cartography-0.106.0rc2.dist-info → cartography-0.107.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,248 @@
1
+ import logging
2
+ from typing import Any
3
+
4
+ import neo4j
5
+
6
+ from cartography.client.core.tx import load
7
+ from cartography.graph.job import GraphJob
8
+ from cartography.intel.sentinelone.api import get_paginated_results
9
+ from cartography.intel.sentinelone.utils import get_application_id
10
+ from cartography.intel.sentinelone.utils import get_application_version_id
11
+ from cartography.models.sentinelone.application import S1ApplicationSchema
12
+ from cartography.models.sentinelone.application_version import (
13
+ S1ApplicationVersionSchema,
14
+ )
15
+ from cartography.util import timeit
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ @timeit
21
+ def get_application_data(
22
+ account_id: str, api_url: str, api_token: str
23
+ ) -> list[dict[str, Any]]:
24
+ """
25
+ Get application data from SentinelOne API
26
+ :param account_id: SentinelOne account ID
27
+ :param api_url: SentinelOne API URL
28
+ :param api_token: SentinelOne API token
29
+ :return: A list of application data dictionaries
30
+ """
31
+ logger.info(f"Retrieving SentinelOne application data for account {account_id}")
32
+ applications = get_paginated_results(
33
+ api_url=api_url,
34
+ endpoint="/web/api/v2.1/application-management/inventory",
35
+ api_token=api_token,
36
+ params={
37
+ "accountIds": account_id,
38
+ "limit": 1000,
39
+ },
40
+ )
41
+
42
+ logger.info(f"Retrieved {len(applications)} applications from SentinelOne")
43
+ return applications
44
+
45
+
46
+ @timeit
47
+ def get_application_installs(
48
+ app_inventory: list[dict[str, Any]], account_id: str, api_url: str, api_token: str
49
+ ) -> list[dict[str, Any]]:
50
+ """
51
+ Get application installs from SentinelOne API
52
+ :param app_inventory: List of applications to get installs for
53
+ :param account_id: SentinelOne account ID
54
+ :param api_url: SentinelOne API URL
55
+ :param api_token: SentinelOne API token
56
+ :return: A list of application installs data dictionaries
57
+ """
58
+ logger.info(
59
+ f"Retrieving SentinelOne application installs for "
60
+ f"{len(app_inventory)} applications in account "
61
+ f"{account_id}",
62
+ )
63
+
64
+ application_installs = []
65
+ for i, app in enumerate(app_inventory):
66
+ logger.info(
67
+ f"Retrieving SentinelOne installs for {app.get('applicationName')} "
68
+ f"{app.get('applicationVendor')} ({i + 1}/{len(app_inventory)})",
69
+ )
70
+ name = app["applicationName"]
71
+ vendor = app["applicationVendor"]
72
+ app_installs = get_paginated_results(
73
+ api_url=api_url,
74
+ endpoint="/web/api/v2.1/application-management/inventory/endpoints",
75
+ api_token=api_token,
76
+ params={
77
+ "accountIds": account_id,
78
+ "limit": 1000,
79
+ "applicationName": name,
80
+ "applicationVendor": vendor,
81
+ },
82
+ )
83
+
84
+ # Replace applicationVendor and applicationName with original values
85
+ # for consistency with the application data
86
+ for app_install in app_installs:
87
+ app_install["applicationVendor"] = vendor
88
+ app_install["applicationName"] = name
89
+ application_installs.extend(app_installs)
90
+
91
+ return application_installs
92
+
93
+
94
+ def transform_applications(
95
+ applications_list: list[dict[str, Any]],
96
+ ) -> list[dict[str, Any]]:
97
+ """
98
+ Transform SentinelOne application data for loading into Neo4j
99
+ :param applications_list: Raw application data from the API
100
+ :return: Transformed application data
101
+ """
102
+ transformed_data = []
103
+ for app in applications_list:
104
+ vendor = app["applicationVendor"].strip()
105
+ name = app["applicationName"].strip()
106
+ app_id = get_application_id(name, vendor)
107
+ transformed_app = {
108
+ "id": app_id,
109
+ "name": name,
110
+ "vendor": vendor,
111
+ }
112
+ transformed_data.append(transformed_app)
113
+
114
+ return transformed_data
115
+
116
+
117
+ def transform_application_versions(
118
+ application_installs_list: list[dict[str, Any]],
119
+ ) -> list[dict[str, Any]]:
120
+ """
121
+ Transform SentinelOne application installs for loading into Neo4j
122
+ :param application_installs_list: Raw application installs data from the API
123
+ :return: Transformed application installs data
124
+ """
125
+ transformed_data = []
126
+ for installed_version in application_installs_list:
127
+ app_name = installed_version["applicationName"]
128
+ app_vendor = installed_version["applicationVendor"]
129
+ version = installed_version["version"]
130
+
131
+ transformed_version = {
132
+ "id": get_application_version_id(
133
+ app_name,
134
+ app_vendor,
135
+ version,
136
+ ),
137
+ "application_id": get_application_id(
138
+ app_name,
139
+ app_vendor,
140
+ ),
141
+ "application_name": app_name,
142
+ "application_vendor": app_vendor,
143
+ "agent_uuid": installed_version.get("endpointUuid"),
144
+ "installation_path": installed_version.get("applicationInstallationPath"),
145
+ "installed_dt": installed_version.get("applicationInstallationDate"),
146
+ "version": version,
147
+ }
148
+ transformed_data.append(transformed_version)
149
+
150
+ return transformed_data
151
+
152
+
153
+ @timeit
154
+ def load_application_data(
155
+ neo4j_session: neo4j.Session,
156
+ data: list[dict[str, Any]],
157
+ account_id: str,
158
+ update_tag: int,
159
+ ) -> None:
160
+ """
161
+ Load SentinelOne application data into Neo4j
162
+ :param neo4j_session: Neo4j session
163
+ :param data: The transformed application data
164
+ :param account_id: The SentinelOne account ID
165
+ :param update_tag: Update tag to set on the nodes
166
+ :return: None
167
+ """
168
+ logger.info(f"Loading {len(data)} SentinelOne applications into Neo4j")
169
+ load(
170
+ neo4j_session,
171
+ S1ApplicationSchema(),
172
+ data,
173
+ lastupdated=update_tag,
174
+ S1_ACCOUNT_ID=account_id,
175
+ )
176
+
177
+
178
+ @timeit
179
+ def load_application_versions(
180
+ neo4j_session: neo4j.Session,
181
+ data: list[dict[str, Any]],
182
+ account_id: str,
183
+ update_tag: int,
184
+ ) -> None:
185
+ logger.info(f"Loading {len(data)} SentinelOne application versions into Neo4j")
186
+ load(
187
+ neo4j_session,
188
+ S1ApplicationVersionSchema(),
189
+ data,
190
+ lastupdated=update_tag,
191
+ S1_ACCOUNT_ID=account_id,
192
+ )
193
+
194
+
195
+ @timeit
196
+ def cleanup(
197
+ neo4j_session: neo4j.Session, common_job_parameters: dict[str, Any]
198
+ ) -> None:
199
+ logger.debug("Running SentinelOne S1Application cleanup")
200
+ GraphJob.from_node_schema(S1ApplicationSchema(), common_job_parameters).run(
201
+ neo4j_session
202
+ )
203
+ logger.debug("Running SentinelOne S1ApplicationVersion cleanup")
204
+ GraphJob.from_node_schema(S1ApplicationVersionSchema(), common_job_parameters).run(
205
+ neo4j_session
206
+ )
207
+
208
+
209
+ @timeit
210
+ def sync(
211
+ neo4j_session: neo4j.Session,
212
+ common_job_parameters: dict[str, Any],
213
+ ) -> None:
214
+ """
215
+ Sync SentinelOne applications
216
+ :param neo4j_session: Neo4j session
217
+ :param common_job_parameters: Common job parameters containing API_URL, API_TOKEN, etc.
218
+ :return: None
219
+ """
220
+ logger.info("Syncing SentinelOne application data")
221
+ account_id = str(common_job_parameters["S1_ACCOUNT_ID"])
222
+ api_url = str(common_job_parameters["API_URL"])
223
+ api_token = str(common_job_parameters["API_TOKEN"])
224
+
225
+ applications = get_application_data(account_id, api_url, api_token)
226
+ application_versions = get_application_installs(
227
+ applications, account_id, api_url, api_token
228
+ )
229
+ transformed_applications = transform_applications(applications)
230
+ transformed_application_versions = transform_application_versions(
231
+ application_versions
232
+ )
233
+
234
+ load_application_data(
235
+ neo4j_session,
236
+ transformed_applications,
237
+ account_id,
238
+ common_job_parameters["UPDATE_TAG"],
239
+ )
240
+
241
+ load_application_versions(
242
+ neo4j_session,
243
+ transformed_application_versions,
244
+ account_id,
245
+ common_job_parameters["UPDATE_TAG"],
246
+ )
247
+
248
+ cleanup(neo4j_session, common_job_parameters)
@@ -0,0 +1,28 @@
1
+ import re
2
+
3
+
4
+ def get_application_id(name: str, vendor: str) -> str:
5
+ """
6
+ Generate a normalized unique identifier for an application.
7
+ :param name: Application name
8
+ :param vendor: Application vendor/publisher
9
+ :return: Normalized unique identifier in format 'vendor:name'
10
+ """
11
+ name_normalized = name.strip().lower().replace(" ", "_")
12
+ vendor_normalized = vendor.strip().lower().replace(" ", "_")
13
+ name_normalized = re.sub(r"[^\w]", "", name_normalized)
14
+ vendor_normalized = re.sub(r"[^\w]", "", vendor_normalized)
15
+ return f"{vendor_normalized}:{name_normalized}"
16
+
17
+
18
+ def get_application_version_id(name: str, vendor: str, version: str) -> str:
19
+ """
20
+ Generate a unique identifier for an application version
21
+ :param name: Application name
22
+ :param vendor: Application vendor
23
+ :param version: Application version
24
+ :return: Unique identifier for the application version in format 'vendor:name:version'
25
+ """
26
+ app_id = get_application_id(name, vendor)
27
+ version_normalized = version.strip().lower().replace(" ", "_")
28
+ return f"{app_id}:{version_normalized}"
File without changes
@@ -0,0 +1,138 @@
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 OtherRelationships
11
+ from cartography.models.core.relationships import TargetNodeMatcher
12
+
13
+
14
+ @dataclass(frozen=True)
15
+ class AirbyteConnectionNodeProperties(CartographyNodeProperties):
16
+ id: PropertyRef = PropertyRef("connectionId")
17
+ name: PropertyRef = PropertyRef("name")
18
+ namespace_format: PropertyRef = PropertyRef("namespaceFormat")
19
+ prefix: PropertyRef = PropertyRef("prefix")
20
+ status: PropertyRef = PropertyRef("status")
21
+ data_residency: PropertyRef = PropertyRef("dataResidency")
22
+ non_breaking_schema_updates_behavior: PropertyRef = PropertyRef(
23
+ "nonBreakingSchemaUpdatesBehavior"
24
+ )
25
+ namespace_definition: PropertyRef = PropertyRef("namespaceDefinition")
26
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
27
+
28
+
29
+ @dataclass(frozen=True)
30
+ class AirbyteConnectionToOrganizationRelProperties(CartographyRelProperties):
31
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
32
+
33
+
34
+ @dataclass(frozen=True)
35
+ # (:AirbyteOrganization)-[:RESOURCE]->(:AirbyteConnection)
36
+ class AirbyteConnectionToOrganizationRel(CartographyRelSchema):
37
+ target_node_label: str = "AirbyteOrganization"
38
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
39
+ {"id": PropertyRef("ORG_ID", set_in_kwargs=True)},
40
+ )
41
+ direction: LinkDirection = LinkDirection.INWARD
42
+ rel_label: str = "RESOURCE"
43
+ properties: AirbyteConnectionToOrganizationRelProperties = (
44
+ AirbyteConnectionToOrganizationRelProperties()
45
+ )
46
+
47
+
48
+ @dataclass(frozen=True)
49
+ class AirbyteConnectionToWorkspaceRelProperties(CartographyRelProperties):
50
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
51
+
52
+
53
+ @dataclass(frozen=True)
54
+ # (:AirbyteWorkspace)-[:CONTAINS]->(:AirbyteConnection)
55
+ class AirbyteConnectionToWorkspaceRel(CartographyRelSchema):
56
+ target_node_label: str = "AirbyteWorkspace"
57
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
58
+ {"id": PropertyRef("workspaceId")},
59
+ )
60
+ direction: LinkDirection = LinkDirection.INWARD
61
+ rel_label: str = "CONTAINS"
62
+ properties: AirbyteConnectionToWorkspaceRelProperties = (
63
+ AirbyteConnectionToWorkspaceRelProperties()
64
+ )
65
+
66
+
67
+ @dataclass(frozen=True)
68
+ class AirbyteConnectionToSourceRelProperties(CartographyRelProperties):
69
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
70
+
71
+
72
+ @dataclass(frozen=True)
73
+ # (:AirbyteSource)<-[:SYNC_FROM]-(:AirbyteConnection)
74
+ class AirbyteConnectionToSourceRel(CartographyRelSchema):
75
+ target_node_label: str = "AirbyteSource"
76
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
77
+ {"id": PropertyRef("sourceId")},
78
+ )
79
+ direction: LinkDirection = LinkDirection.OUTWARD
80
+ rel_label: str = "SYNC_FROM"
81
+ properties: AirbyteConnectionToSourceRelProperties = (
82
+ AirbyteConnectionToSourceRelProperties()
83
+ )
84
+
85
+
86
+ @dataclass(frozen=True)
87
+ class AirbyteConnectionToDestinationRelProperties(CartographyRelProperties):
88
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
89
+
90
+
91
+ @dataclass(frozen=True)
92
+ # (:AirbyteDestination)<-[:SYNC_TO]-(:AirbyteConnection)
93
+ class AirbyteConnectionToDestinationRel(CartographyRelSchema):
94
+ target_node_label: str = "AirbyteDestination"
95
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
96
+ {"id": PropertyRef("destinationId")},
97
+ )
98
+ direction: LinkDirection = LinkDirection.OUTWARD
99
+ rel_label: str = "SYNC_TO"
100
+ properties: AirbyteConnectionToDestinationRelProperties = (
101
+ AirbyteConnectionToDestinationRelProperties()
102
+ )
103
+
104
+
105
+ @dataclass(frozen=True)
106
+ class AirbyteConnectionToTagRelProperties(CartographyRelProperties):
107
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
108
+
109
+
110
+ @dataclass(frozen=True)
111
+ # (:AirbyteTag)<-[:TAGGED]-(:AirbyteConnection)
112
+ class AirbyteConnectionToTagRel(CartographyRelSchema):
113
+ target_node_label: str = "AirbyteTag"
114
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
115
+ {"id": PropertyRef("tags_ids", one_to_many=True)},
116
+ )
117
+ direction: LinkDirection = LinkDirection.OUTWARD
118
+ rel_label: str = "TAGGED"
119
+ properties: AirbyteConnectionToTagRelProperties = (
120
+ AirbyteConnectionToTagRelProperties()
121
+ )
122
+
123
+
124
+ @dataclass(frozen=True)
125
+ class AirbyteConnectionSchema(CartographyNodeSchema):
126
+ label: str = "AirbyteConnection"
127
+ properties: AirbyteConnectionNodeProperties = AirbyteConnectionNodeProperties()
128
+ sub_resource_relationship: AirbyteConnectionToOrganizationRel = (
129
+ AirbyteConnectionToOrganizationRel()
130
+ )
131
+ other_relationships: OtherRelationships = OtherRelationships(
132
+ [
133
+ AirbyteConnectionToWorkspaceRel(),
134
+ AirbyteConnectionToSourceRel(),
135
+ AirbyteConnectionToDestinationRel(),
136
+ AirbyteConnectionToTagRel(),
137
+ ]
138
+ )
@@ -0,0 +1,75 @@
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 OtherRelationships
11
+ from cartography.models.core.relationships import TargetNodeMatcher
12
+
13
+
14
+ @dataclass(frozen=True)
15
+ class AirbyteDestinationNodeProperties(CartographyNodeProperties):
16
+ id: PropertyRef = PropertyRef("destinationId")
17
+ name: PropertyRef = PropertyRef("name")
18
+ type: PropertyRef = PropertyRef("destinationType")
19
+ config_host: PropertyRef = PropertyRef("configuration.host")
20
+ config_port: PropertyRef = PropertyRef("configuration.port")
21
+ config_name: PropertyRef = PropertyRef("configuration.name")
22
+ config_region: PropertyRef = PropertyRef("configuration.region")
23
+ config_endpoint: PropertyRef = PropertyRef("configuration.endpoint")
24
+ config_account: PropertyRef = PropertyRef("configuration.account")
25
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
26
+
27
+
28
+ @dataclass(frozen=True)
29
+ class AirbyteDestinationToOrganizationRelProperties(CartographyRelProperties):
30
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
31
+
32
+
33
+ @dataclass(frozen=True)
34
+ # (:AirbyteOrganization)-[:RESOURCE]->(:AirbyteDestination)
35
+ class AirbyteDestinationToOrganizationRel(CartographyRelSchema):
36
+ target_node_label: str = "AirbyteOrganization"
37
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
38
+ {"id": PropertyRef("ORG_ID", set_in_kwargs=True)},
39
+ )
40
+ direction: LinkDirection = LinkDirection.INWARD
41
+ rel_label: str = "RESOURCE"
42
+ properties: AirbyteDestinationToOrganizationRelProperties = (
43
+ AirbyteDestinationToOrganizationRelProperties()
44
+ )
45
+
46
+
47
+ @dataclass(frozen=True)
48
+ class AirbyteDestinationToWorkspaceRelProperties(CartographyRelProperties):
49
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
50
+
51
+
52
+ @dataclass(frozen=True)
53
+ # (:AirbyteWorkspace)-[:CONTAINS]->(:AirbyteDestination)
54
+ class AirbyteDestinationToWorkspaceRel(CartographyRelSchema):
55
+ target_node_label: str = "AirbyteWorkspace"
56
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
57
+ {"id": PropertyRef("workspaceId")},
58
+ )
59
+ direction: LinkDirection = LinkDirection.INWARD
60
+ rel_label: str = "CONTAINS"
61
+ properties: AirbyteDestinationToWorkspaceRelProperties = (
62
+ AirbyteDestinationToWorkspaceRelProperties()
63
+ )
64
+
65
+
66
+ @dataclass(frozen=True)
67
+ class AirbyteDestinationSchema(CartographyNodeSchema):
68
+ label: str = "AirbyteDestination"
69
+ properties: AirbyteDestinationNodeProperties = AirbyteDestinationNodeProperties()
70
+ sub_resource_relationship: AirbyteDestinationToOrganizationRel = (
71
+ AirbyteDestinationToOrganizationRel()
72
+ )
73
+ other_relationships: OtherRelationships = OtherRelationships(
74
+ [AirbyteDestinationToWorkspaceRel()]
75
+ )
@@ -0,0 +1,19 @@
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
+
7
+
8
+ @dataclass(frozen=True)
9
+ class AirbyteOrganizationNodeProperties(CartographyNodeProperties):
10
+ id: PropertyRef = PropertyRef("organizationId")
11
+ name: PropertyRef = PropertyRef("organizationName")
12
+ email: PropertyRef = PropertyRef("email")
13
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
14
+
15
+
16
+ @dataclass(frozen=True)
17
+ class AirbyteOrganizationSchema(CartographyNodeSchema):
18
+ label: str = "AirbyteOrganization"
19
+ properties: AirbyteOrganizationNodeProperties = AirbyteOrganizationNodeProperties()
@@ -0,0 +1,75 @@
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 OtherRelationships
11
+ from cartography.models.core.relationships import TargetNodeMatcher
12
+
13
+
14
+ @dataclass(frozen=True)
15
+ class AirbyteSourceNodeProperties(CartographyNodeProperties):
16
+ id: PropertyRef = PropertyRef("sourceId")
17
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
18
+ name: PropertyRef = PropertyRef("name")
19
+ type: PropertyRef = PropertyRef("sourceType")
20
+ config_host: PropertyRef = PropertyRef("configuration.host")
21
+ config_port: PropertyRef = PropertyRef("configuration.port")
22
+ config_name: PropertyRef = PropertyRef("configuration.name")
23
+ config_region: PropertyRef = PropertyRef("configuration.region")
24
+ config_endpoint: PropertyRef = PropertyRef("configuration.endpoint")
25
+ config_account: PropertyRef = PropertyRef("configuration.account")
26
+
27
+
28
+ @dataclass(frozen=True)
29
+ class AirbyteSourceToOrganizationRelProperties(CartographyRelProperties):
30
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
31
+
32
+
33
+ @dataclass(frozen=True)
34
+ # (:AirbyteOrganization)-[:RESOURCE]->(:AirbyteSource)
35
+ class AirbyteSourceToOrganizationRel(CartographyRelSchema):
36
+ target_node_label: str = "AirbyteOrganization"
37
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
38
+ {"id": PropertyRef("ORG_ID", set_in_kwargs=True)},
39
+ )
40
+ direction: LinkDirection = LinkDirection.INWARD
41
+ rel_label: str = "RESOURCE"
42
+ properties: AirbyteSourceToOrganizationRelProperties = (
43
+ AirbyteSourceToOrganizationRelProperties()
44
+ )
45
+
46
+
47
+ @dataclass(frozen=True)
48
+ class AirbyteSourceToWorkspaceRelProperties(CartographyRelProperties):
49
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
50
+
51
+
52
+ @dataclass(frozen=True)
53
+ # (:AirbyteWorkspace)-[:CONTAINS]->(:AirbyteSource)
54
+ class AirbyteSourceToWorkspaceRel(CartographyRelSchema):
55
+ target_node_label: str = "AirbyteWorkspace"
56
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
57
+ {"id": PropertyRef("workspaceId")},
58
+ )
59
+ direction: LinkDirection = LinkDirection.INWARD
60
+ rel_label: str = "CONTAINS"
61
+ properties: AirbyteSourceToWorkspaceRelProperties = (
62
+ AirbyteSourceToWorkspaceRelProperties()
63
+ )
64
+
65
+
66
+ @dataclass(frozen=True)
67
+ class AirbyteSourceSchema(CartographyNodeSchema):
68
+ label: str = "AirbyteSource"
69
+ properties: AirbyteSourceNodeProperties = AirbyteSourceNodeProperties()
70
+ sub_resource_relationship: AirbyteSourceToOrganizationRel = (
71
+ AirbyteSourceToOrganizationRel()
72
+ )
73
+ other_relationships: OtherRelationships = OtherRelationships(
74
+ [AirbyteSourceToWorkspaceRel()]
75
+ )
@@ -0,0 +1,74 @@
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 OtherRelationships
11
+ from cartography.models.core.relationships import TargetNodeMatcher
12
+
13
+
14
+ @dataclass(frozen=True)
15
+ class AirbyteStreamNodeProperties(CartographyNodeProperties):
16
+ id: PropertyRef = PropertyRef("streamId")
17
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
18
+ name: PropertyRef = PropertyRef("name")
19
+ sync_mode: PropertyRef = PropertyRef("syncMode")
20
+ cursor_field: PropertyRef = PropertyRef("cursorField")
21
+ primary_key: PropertyRef = PropertyRef("primaryKey")
22
+ include_files: PropertyRef = PropertyRef("includeFiles")
23
+ selected_fields: PropertyRef = PropertyRef("selectedFields")
24
+ mappers: PropertyRef = PropertyRef("mappers")
25
+
26
+
27
+ @dataclass(frozen=True)
28
+ class AirbyteStreamToOrganizationRelProperties(CartographyRelProperties):
29
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
30
+
31
+
32
+ @dataclass(frozen=True)
33
+ # (:AirbyteOrganization)-[:RESOURCE]->(:AirbyteStream)
34
+ class AirbyteStreamToOrganizationRel(CartographyRelSchema):
35
+ target_node_label: str = "AirbyteOrganization"
36
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
37
+ {"id": PropertyRef("ORG_ID", set_in_kwargs=True)},
38
+ )
39
+ direction: LinkDirection = LinkDirection.INWARD
40
+ rel_label: str = "RESOURCE"
41
+ properties: AirbyteStreamToOrganizationRelProperties = (
42
+ AirbyteStreamToOrganizationRelProperties()
43
+ )
44
+
45
+
46
+ @dataclass(frozen=True)
47
+ class AirbyteStreamToConnectionRelProperties(CartographyRelProperties):
48
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
49
+
50
+
51
+ @dataclass(frozen=True)
52
+ # (:AirbyteConnection)-[:HAS]->(:AirbyteStream)
53
+ class AirbyteStreamToConnectionRel(CartographyRelSchema):
54
+ target_node_label: str = "AirbyteConnection"
55
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
56
+ {"id": PropertyRef("connectionId")},
57
+ )
58
+ direction: LinkDirection = LinkDirection.INWARD
59
+ rel_label: str = "HAS"
60
+ properties: AirbyteStreamToOrganizationRelProperties = (
61
+ AirbyteStreamToOrganizationRelProperties()
62
+ )
63
+
64
+
65
+ @dataclass(frozen=True)
66
+ class AirbyteStreamSchema(CartographyNodeSchema):
67
+ label: str = "AirbyteStream"
68
+ properties: AirbyteStreamNodeProperties = AirbyteStreamNodeProperties()
69
+ sub_resource_relationship: AirbyteStreamToOrganizationRel = (
70
+ AirbyteStreamToOrganizationRel()
71
+ )
72
+ other_relationships: OtherRelationships = OtherRelationships(
73
+ [AirbyteStreamToConnectionRel()]
74
+ )