cartography 0.104.0rc3__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 +104 -3
- cartography/client/aws/__init__.py +19 -0
- cartography/client/aws/ecr.py +51 -0
- cartography/client/core/tx.py +62 -0
- cartography/config.py +32 -0
- cartography/data/indexes.cypher +0 -37
- cartography/data/jobs/cleanup/aws_import_lambda_cleanup.json +1 -1
- cartography/driftdetect/cli.py +3 -2
- cartography/graph/cleanupbuilder.py +198 -41
- 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/acm.py +124 -0
- cartography/intel/aws/cloudtrail.py +3 -38
- cartography/intel/aws/codebuild.py +132 -0
- cartography/intel/aws/ecr.py +8 -2
- cartography/intel/aws/ecs.py +228 -380
- cartography/intel/aws/efs.py +179 -11
- cartography/intel/aws/iam.py +1 -1
- cartography/intel/aws/identitycenter.py +14 -3
- cartography/intel/aws/inspector.py +96 -53
- cartography/intel/aws/lambda_function.py +1 -1
- cartography/intel/aws/rds.py +2 -1
- cartography/intel/aws/resources.py +4 -0
- cartography/intel/aws/s3.py +195 -4
- cartography/intel/aws/sqs.py +36 -90
- cartography/intel/entra/__init__.py +22 -0
- cartography/intel/entra/applications.py +366 -0
- cartography/intel/entra/groups.py +151 -0
- cartography/intel/entra/ou.py +21 -5
- 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/intel/trivy/__init__.py +161 -0
- cartography/intel/trivy/scanner.py +363 -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/acm/__init__.py +0 -0
- cartography/models/aws/acm/certificate.py +75 -0
- cartography/models/aws/cloudtrail/trail.py +24 -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/access_point.py +77 -0
- cartography/models/aws/efs/file_system.py +60 -0
- cartography/models/aws/efs/mount_target.py +29 -2
- cartography/models/aws/s3/notification.py +24 -0
- cartography/models/aws/secretsmanager/secret_version.py +0 -2
- cartography/models/aws/sqs/__init__.py +0 -0
- cartography/models/aws/sqs/queue.py +89 -0
- cartography/models/core/common.py +1 -0
- cartography/models/core/nodes.py +15 -2
- 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/group.py +91 -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/models/trivy/__init__.py +0 -0
- cartography/models/trivy/findings.py +66 -0
- cartography/models/trivy/fix.py +66 -0
- cartography/models/trivy/package.py +71 -0
- cartography/sync.py +10 -4
- cartography/util.py +15 -10
- {cartography-0.104.0rc3.dist-info → cartography-0.106.0.dist-info}/METADATA +6 -2
- {cartography-0.104.0rc3.dist-info → cartography-0.106.0.dist-info}/RECORD +133 -49
- cartography/data/jobs/cleanup/kubernetes_import_cleanup.json +0 -70
- {cartography-0.104.0rc3.dist-info → cartography-0.106.0.dist-info}/WHEEL +0 -0
- {cartography-0.104.0rc3.dist-info → cartography-0.106.0.dist-info}/entry_points.txt +0 -0
- {cartography-0.104.0rc3.dist-info → cartography-0.106.0.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.104.0rc3.dist-info → cartography-0.106.0.dist-info}/top_level.txt +0 -0
cartography/_version.py
CHANGED
|
@@ -17,5 +17,5 @@ __version__: str
|
|
|
17
17
|
__version_tuple__: VERSION_TUPLE
|
|
18
18
|
version_tuple: VERSION_TUPLE
|
|
19
19
|
|
|
20
|
-
__version__ = version = '0.
|
|
21
|
-
__version_tuple__ = version_tuple = (0,
|
|
20
|
+
__version__ = version = '0.106.0'
|
|
21
|
+
__version_tuple__ = version_tuple = (0, 106, 0)
|
cartography/cli.py
CHANGED
|
@@ -71,8 +71,8 @@ class CLI:
|
|
|
71
71
|
default="bolt://localhost:7687",
|
|
72
72
|
help=(
|
|
73
73
|
"A valid Neo4j URI to sync against. See "
|
|
74
|
-
"https://neo4j.com/docs/
|
|
75
|
-
"structure of a Neo4j URI."
|
|
74
|
+
"https://neo4j.com/docs/browser-manual/current/operations/dbms-connection/#uri-scheme for complete "
|
|
75
|
+
"documentation on the structure of a Neo4j URI."
|
|
76
76
|
),
|
|
77
77
|
)
|
|
78
78
|
parser.add_argument(
|
|
@@ -637,6 +637,78 @@ class CLI:
|
|
|
637
637
|
"Required if you are using the Anthropic intel module. Ignored otherwise."
|
|
638
638
|
),
|
|
639
639
|
)
|
|
640
|
+
parser.add_argument(
|
|
641
|
+
"--airbyte-client-id",
|
|
642
|
+
type=str,
|
|
643
|
+
default=None,
|
|
644
|
+
help=(
|
|
645
|
+
"The Airbyte client ID to use for authentication. "
|
|
646
|
+
"Required if you are using the Airbyte intel module. Ignored otherwise."
|
|
647
|
+
),
|
|
648
|
+
)
|
|
649
|
+
parser.add_argument(
|
|
650
|
+
"--airbyte-client-secret-env-var",
|
|
651
|
+
type=str,
|
|
652
|
+
default=None,
|
|
653
|
+
help=(
|
|
654
|
+
"The name of an environment variable containing the Airbyte client secret for authentication. "
|
|
655
|
+
"Required if you are using the Airbyte intel module. Ignored otherwise."
|
|
656
|
+
),
|
|
657
|
+
)
|
|
658
|
+
parser.add_argument(
|
|
659
|
+
"--airbyte-api-url",
|
|
660
|
+
type=str,
|
|
661
|
+
default="https://api.airbyte.com/v1",
|
|
662
|
+
help=(
|
|
663
|
+
"The base URL for the Airbyte API (default is the public Airbyte Cloud API). "
|
|
664
|
+
"Required if you are using the Airbyte intel module. Ignored otherwise."
|
|
665
|
+
),
|
|
666
|
+
)
|
|
667
|
+
parser.add_argument(
|
|
668
|
+
"--trivy-s3-bucket",
|
|
669
|
+
type=str,
|
|
670
|
+
default=None,
|
|
671
|
+
help=(
|
|
672
|
+
"The S3 bucket name containing Trivy scan results. "
|
|
673
|
+
"Required if you are using the Trivy module. Ignored otherwise."
|
|
674
|
+
),
|
|
675
|
+
)
|
|
676
|
+
parser.add_argument(
|
|
677
|
+
"--trivy-s3-prefix",
|
|
678
|
+
type=str,
|
|
679
|
+
default=None,
|
|
680
|
+
help=(
|
|
681
|
+
"The S3 prefix path containing Trivy scan results. "
|
|
682
|
+
"Required if you are using the Trivy module. Ignored otherwise."
|
|
683
|
+
),
|
|
684
|
+
)
|
|
685
|
+
parser.add_argument(
|
|
686
|
+
"--scaleway-org",
|
|
687
|
+
type=str,
|
|
688
|
+
default=None,
|
|
689
|
+
help=(
|
|
690
|
+
"The Scaleway organization ID to sync. "
|
|
691
|
+
"Required if you are using the Scaleway intel module. Ignored otherwise."
|
|
692
|
+
),
|
|
693
|
+
)
|
|
694
|
+
parser.add_argument(
|
|
695
|
+
"--scaleway-access-key",
|
|
696
|
+
type=str,
|
|
697
|
+
default=None,
|
|
698
|
+
help=(
|
|
699
|
+
"The Scaleway access key to use for authentication. "
|
|
700
|
+
"Required if you are using the Scaleway intel module. Ignored otherwise."
|
|
701
|
+
),
|
|
702
|
+
)
|
|
703
|
+
parser.add_argument(
|
|
704
|
+
"--scaleway-secret-key-env-var",
|
|
705
|
+
type=str,
|
|
706
|
+
default=None,
|
|
707
|
+
help=(
|
|
708
|
+
"The name of an environment variable containing the Scaleway secret key for authentication. "
|
|
709
|
+
"Required if you are using the Scaleway intel module. Ignored otherwise."
|
|
710
|
+
),
|
|
711
|
+
)
|
|
640
712
|
|
|
641
713
|
return parser
|
|
642
714
|
|
|
@@ -914,7 +986,7 @@ class CLI:
|
|
|
914
986
|
config.snipeit_token = os.environ.get("SNIPEIT_TOKEN")
|
|
915
987
|
else:
|
|
916
988
|
logger.warning("A SnipeIT base URI was provided but a token was not.")
|
|
917
|
-
config.
|
|
989
|
+
config.snipeit_token = None
|
|
918
990
|
else:
|
|
919
991
|
logger.warning("A SnipeIT base URI was not provided.")
|
|
920
992
|
config.snipeit_base_uri = None
|
|
@@ -955,6 +1027,35 @@ class CLI:
|
|
|
955
1027
|
else:
|
|
956
1028
|
config.anthropic_apikey = None
|
|
957
1029
|
|
|
1030
|
+
# Airbyte config
|
|
1031
|
+
if config.airbyte_client_id and config.airbyte_client_secret_env_var:
|
|
1032
|
+
logger.debug(
|
|
1033
|
+
f"Reading Airbyte client secret from environment variable {config.airbyte_client_secret_env_var}",
|
|
1034
|
+
)
|
|
1035
|
+
config.airbyte_client_secret = os.environ.get(
|
|
1036
|
+
config.airbyte_client_secret_env_var,
|
|
1037
|
+
)
|
|
1038
|
+
else:
|
|
1039
|
+
config.airbyte_client_secret = None
|
|
1040
|
+
|
|
1041
|
+
# Trivy config
|
|
1042
|
+
if config.trivy_s3_bucket:
|
|
1043
|
+
logger.debug(f"Trivy S3 bucket: {config.trivy_s3_bucket}")
|
|
1044
|
+
|
|
1045
|
+
if config.trivy_s3_prefix:
|
|
1046
|
+
logger.debug(f"Trivy S3 prefix: {config.trivy_s3_prefix}")
|
|
1047
|
+
|
|
1048
|
+
# Scaleway config
|
|
1049
|
+
if config.scaleway_secret_key_env_var:
|
|
1050
|
+
logger.debug(
|
|
1051
|
+
f"Reading Scaleway secret key from environment variable {config.scaleway_secret_key_env_var}",
|
|
1052
|
+
)
|
|
1053
|
+
config.scaleway_secret_key = os.environ.get(
|
|
1054
|
+
config.scaleway_secret_key_env_var,
|
|
1055
|
+
)
|
|
1056
|
+
else:
|
|
1057
|
+
config.scaleway_secret_key = None
|
|
1058
|
+
|
|
958
1059
|
# Run cartography
|
|
959
1060
|
try:
|
|
960
1061
|
return cartography.sync.run_with_config(self.sync, config)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
import neo4j
|
|
4
|
+
|
|
5
|
+
from cartography.client.core.tx import read_list_of_values_tx
|
|
6
|
+
from cartography.util import timeit
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@timeit
|
|
10
|
+
def list_accounts(neo4j_session: neo4j.Session) -> List[str]:
|
|
11
|
+
"""
|
|
12
|
+
:param neo4j_session: The neo4j session object.
|
|
13
|
+
:return: A list of all AWS account IDs in the graph
|
|
14
|
+
"""
|
|
15
|
+
# See https://community.neo4j.com/t/extract-list-of-nodes-and-labels-from-path/13665/4
|
|
16
|
+
query = """
|
|
17
|
+
MATCH (a:AWSAccount) RETURN a.id
|
|
18
|
+
"""
|
|
19
|
+
return neo4j_session.read_transaction(read_list_of_values_tx, query)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from typing import Set
|
|
2
|
+
from typing import Tuple
|
|
3
|
+
|
|
4
|
+
import neo4j
|
|
5
|
+
|
|
6
|
+
from cartography.client.core.tx import read_list_of_tuples_tx
|
|
7
|
+
from cartography.util import timeit
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@timeit
|
|
11
|
+
def get_ecr_images(
|
|
12
|
+
neo4j_session: neo4j.Session, aws_account_id: str
|
|
13
|
+
) -> Set[Tuple[str, str, str, str, str]]:
|
|
14
|
+
"""
|
|
15
|
+
Queries the graph for all ECR images and their parent images.
|
|
16
|
+
Returns 5-tuples of ECR repository regions, tags, URIs, names, and binary digests. This is used to identify which
|
|
17
|
+
images to scan.
|
|
18
|
+
:param neo4j_session: The neo4j session object.
|
|
19
|
+
:param aws_account_id: The AWS account ID to get ECR repo data for.
|
|
20
|
+
:return: 5-tuples of repo region, image tag, image URI, repo_name, and image_digest.
|
|
21
|
+
"""
|
|
22
|
+
# See https://community.neo4j.com/t/extract-list-of-nodes-and-labels-from-path/13665/4
|
|
23
|
+
query = """
|
|
24
|
+
MATCH (e1:ECRRepositoryImage)<-[:REPO_IMAGE]-(repo:ECRRepository)
|
|
25
|
+
MATCH (repo)<-[:RESOURCE]-(:AWSAccount {id: $AWS_ID})
|
|
26
|
+
|
|
27
|
+
// OPTIONAL traversal of parent hierarchy
|
|
28
|
+
OPTIONAL MATCH path = (e1)-[:PARENT*1..]->(ancestor:ECRRepositoryImage)
|
|
29
|
+
WITH e1,
|
|
30
|
+
CASE
|
|
31
|
+
WHEN path IS NULL THEN [e1]
|
|
32
|
+
ELSE [n IN nodes(path) | n] + [e1]
|
|
33
|
+
END AS repo_img_collection_unflattened
|
|
34
|
+
|
|
35
|
+
// Flatten and dedupe
|
|
36
|
+
UNWIND repo_img_collection_unflattened AS repo_img
|
|
37
|
+
WITH DISTINCT repo_img
|
|
38
|
+
|
|
39
|
+
// Match image metadata
|
|
40
|
+
MATCH (er:ECRRepository)-[:REPO_IMAGE]->(repo_img)-[:IMAGE]->(img:ECRImage)
|
|
41
|
+
|
|
42
|
+
RETURN DISTINCT
|
|
43
|
+
er.region AS region,
|
|
44
|
+
repo_img.tag AS tag,
|
|
45
|
+
repo_img.id AS uri,
|
|
46
|
+
er.name AS repo_name,
|
|
47
|
+
img.digest AS digest
|
|
48
|
+
"""
|
|
49
|
+
return neo4j_session.read_transaction(
|
|
50
|
+
read_list_of_tuples_tx, query, AWS_ID=aws_account_id
|
|
51
|
+
)
|
cartography/client/core/tx.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from typing import Any
|
|
2
3
|
from typing import Dict
|
|
3
4
|
from typing import List
|
|
@@ -8,10 +9,15 @@ from typing import Union
|
|
|
8
9
|
import neo4j
|
|
9
10
|
|
|
10
11
|
from cartography.graph.querybuilder import build_create_index_queries
|
|
12
|
+
from cartography.graph.querybuilder import build_create_index_queries_for_matchlink
|
|
11
13
|
from cartography.graph.querybuilder import build_ingestion_query
|
|
14
|
+
from cartography.graph.querybuilder import build_matchlink_query
|
|
12
15
|
from cartography.models.core.nodes import CartographyNodeSchema
|
|
16
|
+
from cartography.models.core.relationships import CartographyRelSchema
|
|
13
17
|
from cartography.util import batch
|
|
14
18
|
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
15
21
|
|
|
16
22
|
def read_list_of_values_tx(
|
|
17
23
|
tx: neo4j.Transaction,
|
|
@@ -255,6 +261,25 @@ def ensure_indexes(
|
|
|
255
261
|
neo4j_session.run(query)
|
|
256
262
|
|
|
257
263
|
|
|
264
|
+
def ensure_indexes_for_matchlinks(
|
|
265
|
+
neo4j_session: neo4j.Session,
|
|
266
|
+
rel_schema: CartographyRelSchema,
|
|
267
|
+
) -> None:
|
|
268
|
+
"""
|
|
269
|
+
Creates indexes for node fields if they don't exist for the given CartographyRelSchema object.
|
|
270
|
+
This is only used for load_rels() where we match on and connect existing nodes.
|
|
271
|
+
This is not used for CartographyNodeSchema objects.
|
|
272
|
+
"""
|
|
273
|
+
queries = build_create_index_queries_for_matchlink(rel_schema)
|
|
274
|
+
logger.debug(f"CREATE INDEX queries for {rel_schema.rel_label}: {queries}")
|
|
275
|
+
for query in queries:
|
|
276
|
+
if not query.startswith("CREATE INDEX IF NOT EXISTS"):
|
|
277
|
+
raise ValueError(
|
|
278
|
+
'Query provided to `ensure_indexes_for_matchlinks()` does not start with "CREATE INDEX IF NOT EXISTS".',
|
|
279
|
+
)
|
|
280
|
+
neo4j_session.run(query)
|
|
281
|
+
|
|
282
|
+
|
|
258
283
|
def load(
|
|
259
284
|
neo4j_session: neo4j.Session,
|
|
260
285
|
node_schema: CartographyNodeSchema,
|
|
@@ -276,3 +301,40 @@ def load(
|
|
|
276
301
|
ensure_indexes(neo4j_session, node_schema)
|
|
277
302
|
ingestion_query = build_ingestion_query(node_schema)
|
|
278
303
|
load_graph_data(neo4j_session, ingestion_query, dict_list, **kwargs)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def load_matchlinks(
|
|
307
|
+
neo4j_session: neo4j.Session,
|
|
308
|
+
rel_schema: CartographyRelSchema,
|
|
309
|
+
dict_list: list[dict[str, Any]],
|
|
310
|
+
**kwargs,
|
|
311
|
+
) -> None:
|
|
312
|
+
"""
|
|
313
|
+
Main entrypoint for intel modules to write relationships to the graph between two existing nodes.
|
|
314
|
+
:param neo4j_session: The Neo4j session
|
|
315
|
+
:param rel_schema: The CartographyRelSchema object to generate a query.
|
|
316
|
+
:param dict_list: The data to load to the graph represented as a list of dicts. The dicts must contain the source and
|
|
317
|
+
target node ids.
|
|
318
|
+
:param kwargs: Allows additional keyword args to be supplied to the Neo4j query.
|
|
319
|
+
:return: None
|
|
320
|
+
"""
|
|
321
|
+
if len(dict_list) == 0:
|
|
322
|
+
# If there is no data to load, save some time.
|
|
323
|
+
return
|
|
324
|
+
|
|
325
|
+
# Validate that required kwargs are provided for cleanup queries
|
|
326
|
+
if "_sub_resource_label" not in kwargs:
|
|
327
|
+
raise ValueError(
|
|
328
|
+
f"Required kwarg '_sub_resource_label' not provided for {rel_schema.rel_label}. "
|
|
329
|
+
"This is needed for cleanup queries."
|
|
330
|
+
)
|
|
331
|
+
if "_sub_resource_id" not in kwargs:
|
|
332
|
+
raise ValueError(
|
|
333
|
+
f"Required kwarg '_sub_resource_id' not provided for {rel_schema.rel_label}. "
|
|
334
|
+
"This is needed for cleanup queries."
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
ensure_indexes_for_matchlinks(neo4j_session, rel_schema)
|
|
338
|
+
matchlink_query = build_matchlink_query(rel_schema)
|
|
339
|
+
logger.debug(f"Matchlink query: {matchlink_query}")
|
|
340
|
+
load_graph_data(neo4j_session, matchlink_query, dict_list, **kwargs)
|
cartography/config.py
CHANGED
|
@@ -137,6 +137,22 @@ class Config:
|
|
|
137
137
|
:param openai_org_id: OpenAI organization id. Optional.
|
|
138
138
|
:type anthropic_apikey: string
|
|
139
139
|
:param anthropic_apikey: Anthropic API key. Optional.
|
|
140
|
+
:type airbyte_client_id: str
|
|
141
|
+
:param airbyte_client_id: Airbyte client ID for API authentication. Optional.
|
|
142
|
+
:type airbyte_client_secret: str
|
|
143
|
+
:param airbyte_client_secret: Airbyte client secret for API authentication. Optional.
|
|
144
|
+
:type airbyte_api_url: str
|
|
145
|
+
:param airbyte_api_url: Airbyte API base URL, e.g. https://api.airbyte.com/v1. Optional.
|
|
146
|
+
:type trivy_s3_bucket: str
|
|
147
|
+
:param trivy_s3_bucket: The S3 bucket name containing Trivy scan results. Optional.
|
|
148
|
+
:type trivy_s3_prefix: str
|
|
149
|
+
:param trivy_s3_prefix: The S3 prefix path containing Trivy scan results. Optional.
|
|
150
|
+
:type scaleway_access_key: str
|
|
151
|
+
:param scaleway_access_key: Scaleway access key. Optional.
|
|
152
|
+
:type scaleway_secret_key: str
|
|
153
|
+
:param scaleway_secret_key: Scaleway secret key. Optional.
|
|
154
|
+
:type scaleway_org: str
|
|
155
|
+
:param scaleway_org: Scaleway organization id. Optional.
|
|
140
156
|
"""
|
|
141
157
|
|
|
142
158
|
def __init__(
|
|
@@ -209,6 +225,14 @@ class Config:
|
|
|
209
225
|
openai_apikey=None,
|
|
210
226
|
openai_org_id=None,
|
|
211
227
|
anthropic_apikey=None,
|
|
228
|
+
airbyte_client_id=None,
|
|
229
|
+
airbyte_client_secret=None,
|
|
230
|
+
airbyte_api_url=None,
|
|
231
|
+
trivy_s3_bucket=None,
|
|
232
|
+
trivy_s3_prefix=None,
|
|
233
|
+
scaleway_access_key=None,
|
|
234
|
+
scaleway_secret_key=None,
|
|
235
|
+
scaleway_org=None,
|
|
212
236
|
):
|
|
213
237
|
self.neo4j_uri = neo4j_uri
|
|
214
238
|
self.neo4j_user = neo4j_user
|
|
@@ -278,3 +302,11 @@ class Config:
|
|
|
278
302
|
self.openai_apikey = openai_apikey
|
|
279
303
|
self.openai_org_id = openai_org_id
|
|
280
304
|
self.anthropic_apikey = anthropic_apikey
|
|
305
|
+
self.airbyte_client_id = airbyte_client_id
|
|
306
|
+
self.airbyte_client_secret = airbyte_client_secret
|
|
307
|
+
self.airbyte_api_url = airbyte_api_url
|
|
308
|
+
self.trivy_s3_bucket = trivy_s3_bucket
|
|
309
|
+
self.trivy_s3_prefix = trivy_s3_prefix
|
|
310
|
+
self.scaleway_access_key = scaleway_access_key
|
|
311
|
+
self.scaleway_secret_key = scaleway_secret_key
|
|
312
|
+
self.scaleway_org = scaleway_org
|
cartography/data/indexes.cypher
CHANGED
|
@@ -99,21 +99,6 @@ CREATE INDEX IF NOT EXISTS FOR (n:ECRRepositoryImage) ON (n.tag);
|
|
|
99
99
|
CREATE INDEX IF NOT EXISTS FOR (n:ECRRepositoryImage) ON (n.lastupdated);
|
|
100
100
|
CREATE INDEX IF NOT EXISTS FOR (n:ECRScanFinding) ON (n.id);
|
|
101
101
|
CREATE INDEX IF NOT EXISTS FOR (n:ECRScanFinding) ON (n.lastupdated);
|
|
102
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSCluster) ON (n.id);
|
|
103
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSCluster) ON (n.lastupdated);
|
|
104
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSContainerInstance) ON (n.id);
|
|
105
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSContainerInstance) ON (n.lastupdated);
|
|
106
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSService) ON (n.id);
|
|
107
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSService) ON (n.lastupdated);
|
|
108
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSTaskDefinition) ON (n.id);
|
|
109
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSTaskDefinition) ON (n.arn);
|
|
110
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSTaskDefinition) ON (n.lastupdated);
|
|
111
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSTask) ON (n.id);
|
|
112
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSTask) ON (n.lastupdated);
|
|
113
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSContainerDefinition) ON (n.id);
|
|
114
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSContainerDefinition) ON (n.lastupdated);
|
|
115
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSContainer) ON (n.id);
|
|
116
|
-
CREATE INDEX IF NOT EXISTS FOR (n:ECSContainer) ON (n.lastupdated);
|
|
117
102
|
CREATE INDEX IF NOT EXISTS FOR (n:ElasticacheCluster) ON (n.id);
|
|
118
103
|
CREATE INDEX IF NOT EXISTS FOR (n:ElasticacheCluster) ON (n.arn);
|
|
119
104
|
CREATE INDEX IF NOT EXISTS FOR (n:ElasticacheCluster) ON (n.lastupdated);
|
|
@@ -227,9 +212,6 @@ CREATE INDEX IF NOT EXISTS FOR (n:OCITenancy) ON (n.lastupdated);
|
|
|
227
212
|
CREATE INDEX IF NOT EXISTS FOR (n:OCIUser) ON (n.ocid);
|
|
228
213
|
CREATE INDEX IF NOT EXISTS FOR (n:OCIUser) ON (n.name);
|
|
229
214
|
CREATE INDEX IF NOT EXISTS FOR (n:OCIUser) ON (n.lastupdated);
|
|
230
|
-
CREATE INDEX IF NOT EXISTS FOR (n:Package) ON (n.id);
|
|
231
|
-
CREATE INDEX IF NOT EXISTS FOR (n:Package) ON (n.name);
|
|
232
|
-
CREATE INDEX IF NOT EXISTS FOR (n:Package) ON (n.lastupdated);
|
|
233
215
|
CREATE INDEX IF NOT EXISTS FOR (n:PagerDutyEscalationPolicy) ON (n.id);
|
|
234
216
|
CREATE INDEX IF NOT EXISTS FOR (n:PagerDutyEscalationPolicy) ON (n.name);
|
|
235
217
|
CREATE INDEX IF NOT EXISTS FOR (n:PagerDutyEscalationPolicy) ON (n.lastupdated);
|
|
@@ -378,22 +360,3 @@ CREATE INDEX IF NOT EXISTS FOR (n:AzureDisk) ON (n.id);
|
|
|
378
360
|
CREATE INDEX IF NOT EXISTS FOR (n:AzureDisk) ON (n.lastupdated);
|
|
379
361
|
CREATE INDEX IF NOT EXISTS FOR (n:AzureSnapshot) ON (n.id);
|
|
380
362
|
CREATE INDEX IF NOT EXISTS FOR (n:AzureSnapshot) ON (n.lastupdated);
|
|
381
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesCluster) ON (n.id);
|
|
382
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesCluster) ON (n.name);
|
|
383
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesCluster) ON (n.lastupdated);
|
|
384
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesNamespace) ON (n.id);
|
|
385
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesNamespace) ON (n.name);
|
|
386
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesNamespace) ON (n.lastupdated);
|
|
387
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesPod) ON (n.id);
|
|
388
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesPod) ON (n.name);
|
|
389
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesPod) ON (n.lastupdated);
|
|
390
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesContainer) ON (n.id);
|
|
391
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesContainer) ON (n.name);
|
|
392
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesContainer) ON (n.image);
|
|
393
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesContainer) ON (n.lastupdated);
|
|
394
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesSecret) ON (n.id);
|
|
395
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesSecret) ON (n.name);
|
|
396
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesSecret) ON (n.lastupdated);
|
|
397
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesService) ON (n.id);
|
|
398
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesService) ON (n.name);
|
|
399
|
-
CREATE INDEX IF NOT EXISTS FOR (n:KubernetesService) ON (n.lastupdated);
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"iterationsize": 100
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
|
-
"query": "MATCH (:AWSAccount{id: $AWS_ID})-[:RESOURCE]->(:AWSLambda)-[r:
|
|
34
|
+
"query": "MATCH (:AWSAccount{id: $AWS_ID})-[:RESOURCE]->(:AWSLambda)-[r:STS_ASSUMEROLE_ALLOW]->(:AWSPrincipal) WHERE r.lastupdated <> $UPDATE_TAG WITH r LIMIT $LIMIT_SIZE DELETE r",
|
|
35
35
|
"iterative": true,
|
|
36
36
|
"iterationsize": 100
|
|
37
37
|
},
|
cartography/driftdetect/cli.py
CHANGED
|
@@ -63,8 +63,9 @@ class CLI:
|
|
|
63
63
|
default="bolt://localhost:7687",
|
|
64
64
|
help=(
|
|
65
65
|
"A valid Neo4j URI to sync against. See "
|
|
66
|
-
"https://neo4j.com/docs/
|
|
67
|
-
"structure of a Neo4j URI
|
|
66
|
+
"https://neo4j.com/docs/browser-manual/current/operations/dbms-connection/#uri-scheme for "
|
|
67
|
+
"documentation on the structure of a Neo4j URI, and "
|
|
68
|
+
"https://neo4j.com/docs/api/python-driver/current/ for complete documentation on the Python driver."
|
|
68
69
|
),
|
|
69
70
|
)
|
|
70
71
|
parser_get_state.add_argument(
|