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.
- cartography/_version.py +2 -2
- cartography/cli.py +131 -2
- cartography/config.py +42 -0
- cartography/driftdetect/cli.py +3 -2
- cartography/intel/airbyte/__init__.py +105 -0
- cartography/intel/airbyte/connections.py +120 -0
- cartography/intel/airbyte/destinations.py +81 -0
- cartography/intel/airbyte/organizations.py +59 -0
- cartography/intel/airbyte/sources.py +78 -0
- cartography/intel/airbyte/tags.py +64 -0
- cartography/intel/airbyte/users.py +106 -0
- cartography/intel/airbyte/util.py +122 -0
- cartography/intel/airbyte/workspaces.py +63 -0
- cartography/intel/aws/__init__.py +1 -0
- cartography/intel/aws/cloudtrail_management_events.py +364 -0
- cartography/intel/aws/cloudwatch.py +77 -0
- cartography/intel/aws/codebuild.py +132 -0
- cartography/intel/aws/ec2/subnets.py +1 -1
- cartography/intel/aws/ecs.py +17 -0
- cartography/intel/aws/inspector.py +77 -48
- cartography/intel/aws/resources.py +4 -0
- cartography/intel/aws/sns.py +62 -2
- cartography/intel/entra/users.py +84 -42
- cartography/intel/scaleway/__init__.py +127 -0
- cartography/intel/scaleway/iam/__init__.py +0 -0
- cartography/intel/scaleway/iam/apikeys.py +71 -0
- cartography/intel/scaleway/iam/applications.py +71 -0
- cartography/intel/scaleway/iam/groups.py +71 -0
- cartography/intel/scaleway/iam/users.py +71 -0
- cartography/intel/scaleway/instances/__init__.py +0 -0
- cartography/intel/scaleway/instances/flexibleips.py +86 -0
- cartography/intel/scaleway/instances/instances.py +92 -0
- cartography/intel/scaleway/projects.py +79 -0
- cartography/intel/scaleway/storage/__init__.py +0 -0
- cartography/intel/scaleway/storage/snapshots.py +86 -0
- cartography/intel/scaleway/storage/volumes.py +84 -0
- cartography/intel/scaleway/utils.py +37 -0
- cartography/intel/sentinelone/__init__.py +69 -0
- cartography/intel/sentinelone/account.py +140 -0
- cartography/intel/sentinelone/agent.py +139 -0
- cartography/intel/sentinelone/api.py +113 -0
- cartography/intel/sentinelone/application.py +248 -0
- cartography/intel/sentinelone/utils.py +28 -0
- cartography/models/airbyte/__init__.py +0 -0
- cartography/models/airbyte/connection.py +138 -0
- cartography/models/airbyte/destination.py +75 -0
- cartography/models/airbyte/organization.py +19 -0
- cartography/models/airbyte/source.py +75 -0
- cartography/models/airbyte/stream.py +74 -0
- cartography/models/airbyte/tag.py +69 -0
- cartography/models/airbyte/user.py +111 -0
- cartography/models/airbyte/workspace.py +46 -0
- cartography/models/aws/cloudtrail/management_events.py +64 -0
- cartography/models/aws/cloudwatch/log_metric_filter.py +79 -0
- cartography/models/aws/codebuild/__init__.py +0 -0
- cartography/models/aws/codebuild/project.py +49 -0
- cartography/models/aws/ec2/networkinterfaces.py +2 -0
- cartography/models/aws/ec2/subnet_instance.py +2 -0
- cartography/models/aws/ec2/subnet_networkinterface.py +2 -0
- cartography/models/aws/ecs/containers.py +19 -0
- cartography/models/aws/ecs/task_definitions.py +38 -0
- cartography/models/aws/ecs/tasks.py +24 -1
- cartography/models/aws/inspector/findings.py +37 -0
- cartography/models/aws/inspector/packages.py +1 -31
- cartography/models/aws/sns/topic_subscription.py +74 -0
- cartography/models/entra/user.py +17 -51
- cartography/models/scaleway/__init__.py +0 -0
- cartography/models/scaleway/iam/__init__.py +0 -0
- cartography/models/scaleway/iam/apikey.py +96 -0
- cartography/models/scaleway/iam/application.py +52 -0
- cartography/models/scaleway/iam/group.py +95 -0
- cartography/models/scaleway/iam/user.py +60 -0
- cartography/models/scaleway/instance/__init__.py +0 -0
- cartography/models/scaleway/instance/flexibleip.py +52 -0
- cartography/models/scaleway/instance/instance.py +118 -0
- cartography/models/scaleway/organization.py +19 -0
- cartography/models/scaleway/project.py +48 -0
- cartography/models/scaleway/storage/__init__.py +0 -0
- cartography/models/scaleway/storage/snapshot.py +78 -0
- cartography/models/scaleway/storage/volume.py +51 -0
- cartography/models/sentinelone/__init__.py +1 -0
- cartography/models/sentinelone/account.py +40 -0
- cartography/models/sentinelone/agent.py +50 -0
- cartography/models/sentinelone/application.py +44 -0
- cartography/models/sentinelone/application_version.py +96 -0
- cartography/sync.py +11 -4
- {cartography-0.106.0rc2.dist-info → cartography-0.107.0.dist-info}/METADATA +20 -16
- {cartography-0.106.0rc2.dist-info → cartography-0.107.0.dist-info}/RECORD +92 -28
- {cartography-0.106.0rc2.dist-info → cartography-0.107.0.dist-info}/WHEEL +0 -0
- {cartography-0.106.0rc2.dist-info → cartography-0.107.0.dist-info}/entry_points.txt +0 -0
- {cartography-0.106.0rc2.dist-info → cartography-0.107.0.dist-info}/licenses/LICENSE +0 -0
- {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
|
+
)
|