cartography 0.105.0__py3-none-any.whl → 0.106.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 +78 -2
- cartography/client/core/tx.py +62 -0
- cartography/config.py +24 -0
- cartography/data/indexes.cypher +0 -34
- cartography/driftdetect/cli.py +3 -2
- cartography/graph/cleanupbuilder.py +47 -0
- cartography/graph/job.py +42 -0
- cartography/graph/querybuilder.py +136 -2
- cartography/graph/statement.py +1 -1
- 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/codebuild.py +132 -0
- cartography/intel/aws/ecs.py +228 -380
- cartography/intel/aws/efs.py +261 -0
- cartography/intel/aws/identitycenter.py +14 -3
- cartography/intel/aws/inspector.py +96 -53
- cartography/intel/aws/rds.py +2 -1
- cartography/intel/aws/resources.py +4 -0
- cartography/intel/entra/__init__.py +11 -0
- cartography/intel/entra/applications.py +366 -0
- cartography/intel/entra/users.py +84 -42
- cartography/intel/kubernetes/__init__.py +30 -14
- cartography/intel/kubernetes/clusters.py +86 -0
- cartography/intel/kubernetes/namespaces.py +59 -57
- cartography/intel/kubernetes/pods.py +140 -77
- cartography/intel/kubernetes/secrets.py +95 -45
- cartography/intel/kubernetes/services.py +131 -67
- cartography/intel/kubernetes/util.py +125 -14
- 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/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/codebuild/__init__.py +0 -0
- cartography/models/aws/codebuild/project.py +49 -0
- cartography/models/aws/ecs/__init__.py +0 -0
- cartography/models/aws/ecs/clusters.py +64 -0
- cartography/models/aws/ecs/container_definitions.py +93 -0
- cartography/models/aws/ecs/container_instances.py +84 -0
- cartography/models/aws/ecs/containers.py +99 -0
- cartography/models/aws/ecs/services.py +117 -0
- cartography/models/aws/ecs/task_definitions.py +135 -0
- cartography/models/aws/ecs/tasks.py +110 -0
- cartography/models/aws/efs/__init__.py +0 -0
- cartography/models/aws/efs/access_point.py +77 -0
- cartography/models/aws/efs/file_system.py +60 -0
- cartography/models/aws/efs/mount_target.py +79 -0
- cartography/models/core/common.py +1 -0
- cartography/models/core/relationships.py +44 -0
- cartography/models/entra/app_role_assignment.py +115 -0
- cartography/models/entra/application.py +47 -0
- cartography/models/entra/user.py +17 -51
- cartography/models/kubernetes/__init__.py +0 -0
- cartography/models/kubernetes/clusters.py +26 -0
- cartography/models/kubernetes/containers.py +108 -0
- cartography/models/kubernetes/namespaces.py +51 -0
- cartography/models/kubernetes/pods.py +80 -0
- cartography/models/kubernetes/secrets.py +79 -0
- cartography/models/kubernetes/services.py +108 -0
- 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/sync.py +8 -4
- cartography/util.py +15 -10
- {cartography-0.105.0.dist-info → cartography-0.106.0.dist-info}/METADATA +5 -2
- {cartography-0.105.0.dist-info → cartography-0.106.0.dist-info}/RECORD +107 -35
- cartography/data/jobs/cleanup/kubernetes_import_cleanup.json +0 -70
- {cartography-0.105.0.dist-info → cartography-0.106.0.dist-info}/WHEEL +0 -0
- {cartography-0.105.0.dist-info → cartography-0.106.0.dist-info}/entry_points.txt +0 -0
- {cartography-0.105.0.dist-info → cartography-0.106.0.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.105.0.dist-info → cartography-0.106.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import neo4j
|
|
4
|
+
|
|
5
|
+
import cartography.intel.airbyte.connections
|
|
6
|
+
import cartography.intel.airbyte.destinations
|
|
7
|
+
import cartography.intel.airbyte.organizations
|
|
8
|
+
import cartography.intel.airbyte.sources
|
|
9
|
+
import cartography.intel.airbyte.tags
|
|
10
|
+
import cartography.intel.airbyte.users
|
|
11
|
+
import cartography.intel.airbyte.workspaces
|
|
12
|
+
from cartography.config import Config
|
|
13
|
+
from cartography.intel.airbyte.util import AirbyteClient
|
|
14
|
+
from cartography.util import timeit
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@timeit
|
|
20
|
+
def start_airbyte_ingestion(neo4j_session: neo4j.Session, config: Config) -> None:
|
|
21
|
+
"""
|
|
22
|
+
If this module is configured, perform ingestion of Airbyte data. Otherwise warn and exit
|
|
23
|
+
:param neo4j_session: Neo4J session for database interface
|
|
24
|
+
:param config: A cartography.config object
|
|
25
|
+
:return: None
|
|
26
|
+
"""
|
|
27
|
+
if (
|
|
28
|
+
not config.airbyte_api_url
|
|
29
|
+
or not config.airbyte_client_id
|
|
30
|
+
or not config.airbyte_client_secret
|
|
31
|
+
):
|
|
32
|
+
logger.info(
|
|
33
|
+
"Airbyte import is not configured - skipping this module. "
|
|
34
|
+
"See docs to configure.",
|
|
35
|
+
)
|
|
36
|
+
return
|
|
37
|
+
|
|
38
|
+
# Create api session
|
|
39
|
+
api_client = AirbyteClient(
|
|
40
|
+
base_url=config.airbyte_api_url,
|
|
41
|
+
client_id=config.airbyte_client_id,
|
|
42
|
+
client_secret=config.airbyte_client_secret,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
common_job_parameters = {
|
|
46
|
+
"UPDATE_TAG": config.update_tag,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
organizations = cartography.intel.airbyte.organizations.sync(
|
|
50
|
+
neo4j_session,
|
|
51
|
+
api_client,
|
|
52
|
+
common_job_parameters,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
for organization in organizations:
|
|
56
|
+
org_common_job_parameters = {
|
|
57
|
+
"UPDATE_TAG": config.update_tag,
|
|
58
|
+
"ORG_ID": organization["organizationId"],
|
|
59
|
+
}
|
|
60
|
+
workspaces = cartography.intel.airbyte.workspaces.sync(
|
|
61
|
+
neo4j_session,
|
|
62
|
+
api_client,
|
|
63
|
+
organization["organizationId"],
|
|
64
|
+
org_common_job_parameters,
|
|
65
|
+
)
|
|
66
|
+
workspace_ids = [workspace["workspaceId"] for workspace in workspaces]
|
|
67
|
+
|
|
68
|
+
cartography.intel.airbyte.users.sync(
|
|
69
|
+
neo4j_session,
|
|
70
|
+
api_client,
|
|
71
|
+
organization["organizationId"],
|
|
72
|
+
org_common_job_parameters,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
cartography.intel.airbyte.sources.sync(
|
|
76
|
+
neo4j_session,
|
|
77
|
+
api_client,
|
|
78
|
+
organization["organizationId"],
|
|
79
|
+
workspace_ids,
|
|
80
|
+
org_common_job_parameters,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
cartography.intel.airbyte.destinations.sync(
|
|
84
|
+
neo4j_session,
|
|
85
|
+
api_client,
|
|
86
|
+
organization["organizationId"],
|
|
87
|
+
workspace_ids,
|
|
88
|
+
org_common_job_parameters,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
cartography.intel.airbyte.tags.sync(
|
|
92
|
+
neo4j_session,
|
|
93
|
+
api_client,
|
|
94
|
+
organization["organizationId"],
|
|
95
|
+
workspace_ids,
|
|
96
|
+
org_common_job_parameters,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
cartography.intel.airbyte.connections.sync(
|
|
100
|
+
neo4j_session,
|
|
101
|
+
api_client,
|
|
102
|
+
organization["organizationId"],
|
|
103
|
+
workspace_ids,
|
|
104
|
+
org_common_job_parameters,
|
|
105
|
+
)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from typing import List
|
|
5
|
+
from typing import Tuple
|
|
6
|
+
|
|
7
|
+
import neo4j
|
|
8
|
+
|
|
9
|
+
from cartography.client.core.tx import load
|
|
10
|
+
from cartography.graph.job import GraphJob
|
|
11
|
+
from cartography.intel.airbyte.util import AirbyteClient
|
|
12
|
+
from cartography.intel.airbyte.util import list_to_string
|
|
13
|
+
from cartography.models.airbyte.connection import AirbyteConnectionSchema
|
|
14
|
+
from cartography.models.airbyte.stream import AirbyteStreamSchema
|
|
15
|
+
from cartography.util import timeit
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@timeit
|
|
21
|
+
def sync(
|
|
22
|
+
neo4j_session: neo4j.Session,
|
|
23
|
+
api_session: AirbyteClient,
|
|
24
|
+
org_id: str,
|
|
25
|
+
workspace_ids: List[str],
|
|
26
|
+
common_job_parameters: Dict[str, Any],
|
|
27
|
+
) -> None:
|
|
28
|
+
connections = get(api_session, workspace_ids)
|
|
29
|
+
transformed_connections, transformed_streams = transform(connections)
|
|
30
|
+
load_connections(
|
|
31
|
+
neo4j_session,
|
|
32
|
+
transformed_connections,
|
|
33
|
+
org_id,
|
|
34
|
+
common_job_parameters["UPDATE_TAG"],
|
|
35
|
+
)
|
|
36
|
+
load_streams(
|
|
37
|
+
neo4j_session, transformed_streams, org_id, common_job_parameters["UPDATE_TAG"]
|
|
38
|
+
)
|
|
39
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@timeit
|
|
43
|
+
def get(
|
|
44
|
+
api_session: AirbyteClient,
|
|
45
|
+
workspace_ids: List[str],
|
|
46
|
+
) -> List[Dict[str, Any]]:
|
|
47
|
+
return api_session.get(
|
|
48
|
+
"/connections",
|
|
49
|
+
{"workspaceIds": ",".join(workspace_ids)} if workspace_ids else None,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def transform(
|
|
54
|
+
connections: List[Dict[str, Any]],
|
|
55
|
+
) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]:
|
|
56
|
+
transformed_connections = []
|
|
57
|
+
transformed_streams = []
|
|
58
|
+
for connection in connections:
|
|
59
|
+
connection["tags_ids"] = [tag["tagId"] for tag in connection.get("tags", [])]
|
|
60
|
+
transformed_connections.append(connection)
|
|
61
|
+
for stream in connection.get("configurations", {}).get("streams", []):
|
|
62
|
+
formated_stream = {
|
|
63
|
+
"connectionId": connection["connectionId"],
|
|
64
|
+
"streamId": f"{connection['connectionId']}_{stream['name']}",
|
|
65
|
+
"name": stream["name"],
|
|
66
|
+
"syncMode": stream["syncMode"],
|
|
67
|
+
"cursorField": list_to_string(stream.get("cursorField", [])),
|
|
68
|
+
"primaryKey": list_to_string(stream.get("primaryKey", [])),
|
|
69
|
+
"includeFiles": stream.get("includeFiles", False),
|
|
70
|
+
"selectedFields": list_to_string(stream.get("selectedFields", [])),
|
|
71
|
+
"mappers": list_to_string(stream.get("mappers", [])),
|
|
72
|
+
}
|
|
73
|
+
transformed_streams.append(formated_stream)
|
|
74
|
+
return transformed_connections, transformed_streams
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@timeit
|
|
78
|
+
def load_connections(
|
|
79
|
+
neo4j_session: neo4j.Session,
|
|
80
|
+
data: List[Dict[str, Any]],
|
|
81
|
+
org_id: str,
|
|
82
|
+
update_tag: int,
|
|
83
|
+
) -> None:
|
|
84
|
+
logger.info("Loading %d Airbyte Connections into Neo4j.", len(data))
|
|
85
|
+
load(
|
|
86
|
+
neo4j_session,
|
|
87
|
+
AirbyteConnectionSchema(),
|
|
88
|
+
data,
|
|
89
|
+
lastupdated=update_tag,
|
|
90
|
+
ORG_ID=org_id,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@timeit
|
|
95
|
+
def load_streams(
|
|
96
|
+
neo4j_session: neo4j.Session,
|
|
97
|
+
data: List[Dict[str, Any]],
|
|
98
|
+
org_id: str,
|
|
99
|
+
update_tag: int,
|
|
100
|
+
) -> None:
|
|
101
|
+
logger.info("Loading %d Airbyte Streams into Neo4j.", len(data))
|
|
102
|
+
load(
|
|
103
|
+
neo4j_session,
|
|
104
|
+
AirbyteStreamSchema(),
|
|
105
|
+
data,
|
|
106
|
+
lastupdated=update_tag,
|
|
107
|
+
ORG_ID=org_id,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@timeit
|
|
112
|
+
def cleanup(
|
|
113
|
+
neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
|
|
114
|
+
) -> None:
|
|
115
|
+
GraphJob.from_node_schema(AirbyteStreamSchema(), common_job_parameters).run(
|
|
116
|
+
neo4j_session
|
|
117
|
+
)
|
|
118
|
+
GraphJob.from_node_schema(AirbyteConnectionSchema(), common_job_parameters).run(
|
|
119
|
+
neo4j_session
|
|
120
|
+
)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
import neo4j
|
|
7
|
+
|
|
8
|
+
from cartography.client.core.tx import load
|
|
9
|
+
from cartography.graph.job import GraphJob
|
|
10
|
+
from cartography.intel.airbyte.util import AirbyteClient
|
|
11
|
+
from cartography.intel.airbyte.util import normalize_airbyte_config
|
|
12
|
+
from cartography.models.airbyte.destination import AirbyteDestinationSchema
|
|
13
|
+
from cartography.util import timeit
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@timeit
|
|
19
|
+
def sync(
|
|
20
|
+
neo4j_session: neo4j.Session,
|
|
21
|
+
api_session: AirbyteClient,
|
|
22
|
+
org_id: str,
|
|
23
|
+
workspace_ids: List[str],
|
|
24
|
+
common_job_parameters: Dict[str, Any],
|
|
25
|
+
) -> None:
|
|
26
|
+
destinations = get(api_session, workspace_ids)
|
|
27
|
+
transformed_destinations = transform(destinations)
|
|
28
|
+
load_destinations(
|
|
29
|
+
neo4j_session,
|
|
30
|
+
transformed_destinations,
|
|
31
|
+
org_id,
|
|
32
|
+
common_job_parameters["UPDATE_TAG"],
|
|
33
|
+
)
|
|
34
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@timeit
|
|
38
|
+
def get(
|
|
39
|
+
api_session: AirbyteClient,
|
|
40
|
+
workspace_ids: List[str],
|
|
41
|
+
) -> List[Dict[str, Any]]:
|
|
42
|
+
return api_session.get(
|
|
43
|
+
"/destinations",
|
|
44
|
+
params={"workspaceIds": ",".join(workspace_ids)} if workspace_ids else None,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def transform(destinations: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
|
49
|
+
transformed_destinations = []
|
|
50
|
+
for destination in destinations:
|
|
51
|
+
destination["configuration"] = normalize_airbyte_config(
|
|
52
|
+
destination.get("configuration", {})
|
|
53
|
+
)
|
|
54
|
+
transformed_destinations.append(destination)
|
|
55
|
+
return transformed_destinations
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@timeit
|
|
59
|
+
def load_destinations(
|
|
60
|
+
neo4j_session: neo4j.Session,
|
|
61
|
+
data: List[Dict[str, Any]],
|
|
62
|
+
org_id: str,
|
|
63
|
+
update_tag: int,
|
|
64
|
+
) -> None:
|
|
65
|
+
logger.info("Loading %d Airbyte Destinations into Neo4j.", len(data))
|
|
66
|
+
load(
|
|
67
|
+
neo4j_session,
|
|
68
|
+
AirbyteDestinationSchema(),
|
|
69
|
+
data,
|
|
70
|
+
lastupdated=update_tag,
|
|
71
|
+
ORG_ID=org_id,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@timeit
|
|
76
|
+
def cleanup(
|
|
77
|
+
neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
|
|
78
|
+
) -> None:
|
|
79
|
+
GraphJob.from_node_schema(AirbyteDestinationSchema(), common_job_parameters).run(
|
|
80
|
+
neo4j_session
|
|
81
|
+
)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
import neo4j
|
|
7
|
+
|
|
8
|
+
from cartography.client.core.tx import load
|
|
9
|
+
from cartography.graph.job import GraphJob
|
|
10
|
+
from cartography.intel.airbyte.util import AirbyteClient
|
|
11
|
+
from cartography.models.airbyte.organization import AirbyteOrganizationSchema
|
|
12
|
+
from cartography.util import timeit
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@timeit
|
|
18
|
+
def sync(
|
|
19
|
+
neo4j_session: neo4j.Session,
|
|
20
|
+
api_session: AirbyteClient,
|
|
21
|
+
common_job_parameters: Dict[str, Any],
|
|
22
|
+
) -> List[Dict]:
|
|
23
|
+
organizations = get(api_session)
|
|
24
|
+
load_organizations(
|
|
25
|
+
neo4j_session, organizations, common_job_parameters["UPDATE_TAG"]
|
|
26
|
+
)
|
|
27
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
28
|
+
return organizations
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@timeit
|
|
32
|
+
def get(
|
|
33
|
+
api_session: AirbyteClient,
|
|
34
|
+
) -> List[Dict[str, Any]]:
|
|
35
|
+
return api_session.get("/organizations")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@timeit
|
|
39
|
+
def load_organizations(
|
|
40
|
+
neo4j_session: neo4j.Session,
|
|
41
|
+
data: List[Dict[str, Any]],
|
|
42
|
+
update_tag: int,
|
|
43
|
+
) -> None:
|
|
44
|
+
logger.info("Loading %d Airbyte Organizations into Neo4j.", len(data))
|
|
45
|
+
load(
|
|
46
|
+
neo4j_session,
|
|
47
|
+
AirbyteOrganizationSchema(),
|
|
48
|
+
data,
|
|
49
|
+
lastupdated=update_tag,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@timeit
|
|
54
|
+
def cleanup(
|
|
55
|
+
neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
|
|
56
|
+
) -> None:
|
|
57
|
+
GraphJob.from_node_schema(AirbyteOrganizationSchema(), common_job_parameters).run(
|
|
58
|
+
neo4j_session
|
|
59
|
+
)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
import neo4j
|
|
7
|
+
|
|
8
|
+
from cartography.client.core.tx import load
|
|
9
|
+
from cartography.graph.job import GraphJob
|
|
10
|
+
from cartography.intel.airbyte.util import AirbyteClient
|
|
11
|
+
from cartography.intel.airbyte.util import normalize_airbyte_config
|
|
12
|
+
from cartography.models.airbyte.source import AirbyteSourceSchema
|
|
13
|
+
from cartography.util import timeit
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@timeit
|
|
19
|
+
def sync(
|
|
20
|
+
neo4j_session: neo4j.Session,
|
|
21
|
+
api_session: AirbyteClient,
|
|
22
|
+
org_id: str,
|
|
23
|
+
workspace_ids: List[str],
|
|
24
|
+
common_job_parameters: Dict[str, Any],
|
|
25
|
+
) -> None:
|
|
26
|
+
sources = get(api_session, workspace_ids)
|
|
27
|
+
transformed_sources = transform(sources)
|
|
28
|
+
load_sources(
|
|
29
|
+
neo4j_session, transformed_sources, org_id, common_job_parameters["UPDATE_TAG"]
|
|
30
|
+
)
|
|
31
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@timeit
|
|
35
|
+
def get(
|
|
36
|
+
api_session: AirbyteClient,
|
|
37
|
+
workspace_ids: List[str],
|
|
38
|
+
) -> List[Dict[str, Any]]:
|
|
39
|
+
return api_session.get(
|
|
40
|
+
"/sources",
|
|
41
|
+
params={"workspaceIds": ",".join(workspace_ids)} if workspace_ids else None,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def transform(sources: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
|
46
|
+
transformed_sources = []
|
|
47
|
+
for source in sources:
|
|
48
|
+
source["configuration"] = normalize_airbyte_config(
|
|
49
|
+
source.get("configuration", {})
|
|
50
|
+
)
|
|
51
|
+
transformed_sources.append(source)
|
|
52
|
+
return transformed_sources
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@timeit
|
|
56
|
+
def load_sources(
|
|
57
|
+
neo4j_session: neo4j.Session,
|
|
58
|
+
data: List[Dict[str, Any]],
|
|
59
|
+
org_id: str,
|
|
60
|
+
update_tag: int,
|
|
61
|
+
) -> None:
|
|
62
|
+
logger.info("Loading %d Airbyte Sources into Neo4j.", len(data))
|
|
63
|
+
load(
|
|
64
|
+
neo4j_session,
|
|
65
|
+
AirbyteSourceSchema(),
|
|
66
|
+
data,
|
|
67
|
+
lastupdated=update_tag,
|
|
68
|
+
ORG_ID=org_id,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@timeit
|
|
73
|
+
def cleanup(
|
|
74
|
+
neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
|
|
75
|
+
) -> None:
|
|
76
|
+
GraphJob.from_node_schema(AirbyteSourceSchema(), common_job_parameters).run(
|
|
77
|
+
neo4j_session
|
|
78
|
+
)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
import neo4j
|
|
7
|
+
|
|
8
|
+
from cartography.client.core.tx import load
|
|
9
|
+
from cartography.graph.job import GraphJob
|
|
10
|
+
from cartography.intel.airbyte.util import AirbyteClient
|
|
11
|
+
from cartography.models.airbyte.tag import AirbyteTagSchema
|
|
12
|
+
from cartography.util import timeit
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@timeit
|
|
18
|
+
def sync(
|
|
19
|
+
neo4j_session: neo4j.Session,
|
|
20
|
+
api_session: AirbyteClient,
|
|
21
|
+
org_id: str,
|
|
22
|
+
workspace_ids: List[str],
|
|
23
|
+
common_job_parameters: Dict[str, Any],
|
|
24
|
+
) -> None:
|
|
25
|
+
tags = get(api_session, workspace_ids)
|
|
26
|
+
load_tags(neo4j_session, tags, org_id, common_job_parameters["UPDATE_TAG"])
|
|
27
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@timeit
|
|
31
|
+
def get(
|
|
32
|
+
api_session: AirbyteClient,
|
|
33
|
+
workspace_ids: List[str],
|
|
34
|
+
) -> List[Dict[str, Any]]:
|
|
35
|
+
return api_session.get(
|
|
36
|
+
"/tags",
|
|
37
|
+
params={"workspaceIds": ",".join(workspace_ids)} if workspace_ids else None,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@timeit
|
|
42
|
+
def load_tags(
|
|
43
|
+
neo4j_session: neo4j.Session,
|
|
44
|
+
data: List[Dict[str, Any]],
|
|
45
|
+
org_id: str,
|
|
46
|
+
update_tag: int,
|
|
47
|
+
) -> None:
|
|
48
|
+
logger.info("Loading %d Airbyte Tags into Neo4j.", len(data))
|
|
49
|
+
load(
|
|
50
|
+
neo4j_session,
|
|
51
|
+
AirbyteTagSchema(),
|
|
52
|
+
data,
|
|
53
|
+
lastupdated=update_tag,
|
|
54
|
+
ORG_ID=org_id,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@timeit
|
|
59
|
+
def cleanup(
|
|
60
|
+
neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
|
|
61
|
+
) -> None:
|
|
62
|
+
GraphJob.from_node_schema(AirbyteTagSchema(), common_job_parameters).run(
|
|
63
|
+
neo4j_session
|
|
64
|
+
)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from typing import List
|
|
5
|
+
from typing import Tuple
|
|
6
|
+
|
|
7
|
+
import neo4j
|
|
8
|
+
|
|
9
|
+
from cartography.client.core.tx import load
|
|
10
|
+
from cartography.graph.job import GraphJob
|
|
11
|
+
from cartography.intel.airbyte.util import AirbyteClient
|
|
12
|
+
from cartography.models.airbyte.user import AirbyteUserSchema
|
|
13
|
+
from cartography.util import timeit
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@timeit
|
|
19
|
+
def sync(
|
|
20
|
+
neo4j_session: neo4j.Session,
|
|
21
|
+
api_session: AirbyteClient,
|
|
22
|
+
org_id: str,
|
|
23
|
+
common_job_parameters: Dict[str, Any],
|
|
24
|
+
) -> None:
|
|
25
|
+
users = get(api_session, org_id=org_id)
|
|
26
|
+
for user in users:
|
|
27
|
+
permissions = get_permissions(api_session, user["id"], org_id=org_id)
|
|
28
|
+
org_admin, workspace_admin, workspace_member = transform_permissions(
|
|
29
|
+
permissions
|
|
30
|
+
)
|
|
31
|
+
user["adminOfOrganization"] = org_admin
|
|
32
|
+
user["adminOfWorkspace"] = workspace_admin
|
|
33
|
+
user["memberOfWorkspace"] = workspace_member
|
|
34
|
+
load_users(neo4j_session, users, org_id, common_job_parameters["UPDATE_TAG"])
|
|
35
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@timeit
|
|
39
|
+
def get(
|
|
40
|
+
api_session: AirbyteClient,
|
|
41
|
+
org_id: str,
|
|
42
|
+
) -> List[Dict[str, Any]]:
|
|
43
|
+
return api_session.get("/users", params={"organizationId": org_id})
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@timeit
|
|
47
|
+
def get_permissions(
|
|
48
|
+
api_session: AirbyteClient,
|
|
49
|
+
user_id: str,
|
|
50
|
+
org_id: str,
|
|
51
|
+
) -> List[Dict[str, Any]]:
|
|
52
|
+
return api_session.get(
|
|
53
|
+
"/permissions",
|
|
54
|
+
params={"organizationId": org_id, "userId": user_id},
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@timeit
|
|
59
|
+
def transform_permissions(
|
|
60
|
+
permissions: List[Dict[str, Any]],
|
|
61
|
+
) -> Tuple[
|
|
62
|
+
List[str], # org_admin
|
|
63
|
+
List[str], # workspace_admin
|
|
64
|
+
List[str], # workspace_member
|
|
65
|
+
]:
|
|
66
|
+
org_admin: list[str] = []
|
|
67
|
+
workspace_admin: list[str] = []
|
|
68
|
+
workspace_member: list[str] = []
|
|
69
|
+
|
|
70
|
+
for permission in permissions:
|
|
71
|
+
# workspace
|
|
72
|
+
if permission["scope"] == "workspace":
|
|
73
|
+
if permission["permissionType"] in ("workspace_owner", "workspace_admin"):
|
|
74
|
+
workspace_admin.append(permission["scopeId"])
|
|
75
|
+
workspace_member.append(permission["scopeId"])
|
|
76
|
+
# organization
|
|
77
|
+
elif permission["scope"] == "organization":
|
|
78
|
+
if permission["permissionType"] in ("organization_admin",):
|
|
79
|
+
org_admin.append(permission["scopeId"])
|
|
80
|
+
return org_admin, workspace_admin, workspace_member
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@timeit
|
|
84
|
+
def load_users(
|
|
85
|
+
neo4j_session: neo4j.Session,
|
|
86
|
+
data: List[Dict[str, Any]],
|
|
87
|
+
org_id: str,
|
|
88
|
+
update_tag: int,
|
|
89
|
+
) -> None:
|
|
90
|
+
logger.info("Loading %d Airbyte Users into Neo4j.", len(data))
|
|
91
|
+
load(
|
|
92
|
+
neo4j_session,
|
|
93
|
+
AirbyteUserSchema(),
|
|
94
|
+
data,
|
|
95
|
+
ORG_ID=org_id,
|
|
96
|
+
lastupdated=update_tag,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@timeit
|
|
101
|
+
def cleanup(
|
|
102
|
+
neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
|
|
103
|
+
) -> None:
|
|
104
|
+
GraphJob.from_node_schema(AirbyteUserSchema(), common_job_parameters).run(
|
|
105
|
+
neo4j_session
|
|
106
|
+
)
|