cartography 0.107.0rc2__py3-none-any.whl → 0.108.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 +10 -0
- cartography/config.py +5 -0
- cartography/data/indexes.cypher +0 -10
- cartography/data/jobs/cleanup/github_repos_cleanup.json +2 -0
- cartography/intel/aws/__init__.py +1 -0
- cartography/intel/aws/cloudtrail.py +17 -4
- cartography/intel/aws/cloudtrail_management_events.py +560 -16
- cartography/intel/aws/cloudwatch.py +150 -4
- cartography/intel/aws/ec2/security_groups.py +140 -122
- cartography/intel/aws/ec2/snapshots.py +47 -84
- cartography/intel/aws/ec2/subnets.py +37 -63
- cartography/intel/aws/ecr.py +55 -80
- cartography/intel/aws/ecs.py +17 -0
- cartography/intel/aws/elasticache.py +102 -79
- cartography/intel/aws/guardduty.py +275 -0
- cartography/intel/aws/resources.py +2 -0
- cartography/intel/aws/secretsmanager.py +62 -44
- cartography/intel/github/repos.py +370 -28
- cartography/intel/sentinelone/__init__.py +8 -2
- cartography/intel/sentinelone/application.py +248 -0
- cartography/intel/sentinelone/utils.py +20 -1
- cartography/models/aws/cloudtrail/management_events.py +95 -6
- cartography/models/aws/cloudtrail/trail.py +21 -0
- cartography/models/aws/cloudwatch/log_metric_filter.py +79 -0
- cartography/models/aws/cloudwatch/metric_alarm.py +53 -0
- cartography/models/aws/ec2/networkinterfaces.py +2 -0
- cartography/models/aws/ec2/security_group_rules.py +109 -0
- cartography/models/aws/ec2/security_groups.py +90 -0
- cartography/models/aws/ec2/snapshots.py +58 -0
- cartography/models/aws/ec2/subnet_instance.py +2 -0
- cartography/models/aws/ec2/subnet_networkinterface.py +2 -0
- cartography/models/aws/ec2/subnets.py +65 -0
- cartography/models/aws/ec2/volumes.py +20 -0
- cartography/models/aws/ecr/__init__.py +0 -0
- cartography/models/aws/ecr/image.py +41 -0
- cartography/models/aws/ecr/repository.py +72 -0
- cartography/models/aws/ecr/repository_image.py +95 -0
- cartography/models/aws/ecs/tasks.py +24 -1
- cartography/models/aws/elasticache/__init__.py +0 -0
- cartography/models/aws/elasticache/cluster.py +65 -0
- cartography/models/aws/elasticache/topic.py +67 -0
- cartography/models/aws/guardduty/__init__.py +1 -0
- cartography/models/aws/guardduty/findings.py +102 -0
- cartography/models/aws/secretsmanager/secret.py +106 -0
- cartography/models/github/dependencies.py +74 -0
- cartography/models/github/manifests.py +49 -0
- cartography/models/sentinelone/application.py +44 -0
- cartography/models/sentinelone/application_version.py +96 -0
- {cartography-0.107.0rc2.dist-info → cartography-0.108.0.dist-info}/METADATA +3 -3
- {cartography-0.107.0rc2.dist-info → cartography-0.108.0.dist-info}/RECORD +55 -36
- cartography/data/jobs/cleanup/aws_import_ec2_security_groupinfo_cleanup.json +0 -24
- cartography/data/jobs/cleanup/aws_import_secrets_cleanup.json +0 -8
- cartography/data/jobs/cleanup/aws_import_snapshots_cleanup.json +0 -30
- {cartography-0.107.0rc2.dist-info → cartography-0.108.0.dist-info}/WHEEL +0 -0
- {cartography-0.107.0rc2.dist-info → cartography-0.108.0.dist-info}/entry_points.txt +0 -0
- {cartography-0.107.0rc2.dist-info → cartography-0.108.0.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.107.0rc2.dist-info → cartography-0.108.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.108.0'
|
|
21
|
+
__version_tuple__ = version_tuple = (0, 108, 0)
|
cartography/cli.py
CHANGED
|
@@ -264,6 +264,16 @@ class CLI:
|
|
|
264
264
|
" If not specified, cartography by default will run all AWS sync modules available."
|
|
265
265
|
),
|
|
266
266
|
)
|
|
267
|
+
parser.add_argument(
|
|
268
|
+
"--aws-guardduty-severity-threshold",
|
|
269
|
+
type=str,
|
|
270
|
+
default=None,
|
|
271
|
+
help=(
|
|
272
|
+
"GuardDuty severity threshold filter. Only findings at or above this severity level will be synced. "
|
|
273
|
+
"Valid values: LOW, MEDIUM, HIGH, CRITICAL. If not specified, all findings (except archived) will be synced. "
|
|
274
|
+
"Example: 'HIGH' will sync only HIGH and CRITICAL findings, filtering out LOW and MEDIUM severity findings."
|
|
275
|
+
),
|
|
276
|
+
)
|
|
267
277
|
parser.add_argument(
|
|
268
278
|
"--analysis-job-directory",
|
|
269
279
|
type=str,
|
cartography/config.py
CHANGED
|
@@ -53,6 +53,9 @@ class Config:
|
|
|
53
53
|
:param entra_client_secret: Client Secret for connecting in a Service Principal Authentication approach. Optional.
|
|
54
54
|
:type aws_requested_syncs: str
|
|
55
55
|
:param aws_requested_syncs: Comma-separated list of AWS resources to sync. Optional.
|
|
56
|
+
:type aws_guardduty_severity_threshold: str
|
|
57
|
+
:param aws_guardduty_severity_threshold: GuardDuty severity threshold filter. Only findings at or above this
|
|
58
|
+
severity level will be synced. Valid values: LOW, MEDIUM, HIGH, CRITICAL. Optional.
|
|
56
59
|
:type analysis_job_directory: str
|
|
57
60
|
:param analysis_job_directory: Path to a directory tree containing analysis jobs to run. Optional.
|
|
58
61
|
:type oci_sync_all_profiles: bool
|
|
@@ -185,6 +188,7 @@ class Config:
|
|
|
185
188
|
entra_client_id=None,
|
|
186
189
|
entra_client_secret=None,
|
|
187
190
|
aws_requested_syncs=None,
|
|
191
|
+
aws_guardduty_severity_threshold=None,
|
|
188
192
|
analysis_job_directory=None,
|
|
189
193
|
oci_sync_all_profiles=None,
|
|
190
194
|
okta_org_id=None,
|
|
@@ -268,6 +272,7 @@ class Config:
|
|
|
268
272
|
self.entra_client_id = entra_client_id
|
|
269
273
|
self.entra_client_secret = entra_client_secret
|
|
270
274
|
self.aws_requested_syncs = aws_requested_syncs
|
|
275
|
+
self.aws_guardduty_severity_threshold = aws_guardduty_severity_threshold
|
|
271
276
|
self.analysis_job_directory = analysis_job_directory
|
|
272
277
|
self.oci_sync_all_profiles = oci_sync_all_profiles
|
|
273
278
|
self.okta_org_id = okta_org_id
|
cartography/data/indexes.cypher
CHANGED
|
@@ -81,8 +81,6 @@ CREATE INDEX IF NOT EXISTS FOR (n:DODroplet) ON (n.id);
|
|
|
81
81
|
CREATE INDEX IF NOT EXISTS FOR (n:DODroplet) ON (n.lastupdated);
|
|
82
82
|
CREATE INDEX IF NOT EXISTS FOR (n:DOProject) ON (n.id);
|
|
83
83
|
CREATE INDEX IF NOT EXISTS FOR (n:DOProject) ON (n.lastupdated);
|
|
84
|
-
CREATE INDEX IF NOT EXISTS FOR (n:EBSSnapshot) ON (n.id);
|
|
85
|
-
CREATE INDEX IF NOT EXISTS FOR (n:EBSSnapshot) ON (n.lastupdated);
|
|
86
84
|
CREATE INDEX IF NOT EXISTS FOR (n:EC2KeyPair) ON (n.keyfingerprint);
|
|
87
85
|
CREATE INDEX IF NOT EXISTS FOR (n:EC2ReservedInstance) ON (n.id);
|
|
88
86
|
CREATE INDEX IF NOT EXISTS FOR (n:EC2ReservedInstance) ON (n.lastupdated);
|
|
@@ -156,14 +154,8 @@ CREATE INDEX IF NOT EXISTS FOR (n:GSuiteUser) ON (n.lastupdated);
|
|
|
156
154
|
CREATE INDEX IF NOT EXISTS FOR (n:Ip) ON (n.id);
|
|
157
155
|
CREATE INDEX IF NOT EXISTS FOR (n:Ip) ON (n.ip);
|
|
158
156
|
CREATE INDEX IF NOT EXISTS FOR (n:Ip) ON (n.lastupdated);
|
|
159
|
-
CREATE INDEX IF NOT EXISTS FOR (n:IpPermissionInbound) ON (n.ruleid);
|
|
160
|
-
CREATE INDEX IF NOT EXISTS FOR (n:IpPermissionInbound) ON (n.lastupdated);
|
|
161
|
-
CREATE INDEX IF NOT EXISTS FOR (n:IpPermissionsEgress) ON (n.ruleid);
|
|
162
|
-
CREATE INDEX IF NOT EXISTS FOR (n:IpPermissionsEgress) ON (n.lastupdated);
|
|
163
157
|
CREATE INDEX IF NOT EXISTS FOR (n:IpRange) ON (n.id);
|
|
164
158
|
CREATE INDEX IF NOT EXISTS FOR (n:IpRange) ON (n.lastupdated);
|
|
165
|
-
CREATE INDEX IF NOT EXISTS FOR (n:IpRule) ON (n.ruleid);
|
|
166
|
-
CREATE INDEX IF NOT EXISTS FOR (n:IpRule) ON (n.lastupdated);
|
|
167
159
|
CREATE INDEX IF NOT EXISTS FOR (n:JamfComputerGroup) ON (n.id);
|
|
168
160
|
CREATE INDEX IF NOT EXISTS FOR (n:JamfComputerGroup) ON (n.lastupdated);
|
|
169
161
|
CREATE INDEX IF NOT EXISTS FOR (n:KMSKey) ON (n.id);
|
|
@@ -267,8 +259,6 @@ CREATE INDEX IF NOT EXISTS FOR (n:S3Bucket) ON (n.id);
|
|
|
267
259
|
CREATE INDEX IF NOT EXISTS FOR (n:S3Bucket) ON (n.name);
|
|
268
260
|
CREATE INDEX IF NOT EXISTS FOR (n:S3Bucket) ON (n.arn);
|
|
269
261
|
CREATE INDEX IF NOT EXISTS FOR (n:S3Bucket) ON (n.lastupdated);
|
|
270
|
-
CREATE INDEX IF NOT EXISTS FOR (n:SecretsManagerSecret) ON (n.id);
|
|
271
|
-
CREATE INDEX IF NOT EXISTS FOR (n:SecretsManagerSecret) ON (n.lastupdated);
|
|
272
262
|
CREATE INDEX IF NOT EXISTS FOR (n:SecurityHub) ON (n.id);
|
|
273
263
|
CREATE INDEX IF NOT EXISTS FOR (n:SecurityHub) ON (n.lastupdated);
|
|
274
264
|
CREATE INDEX IF NOT EXISTS FOR (n:SpotlightVulnerability) ON (n.id);
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"iterative": true,
|
|
20
20
|
"iterationsize": 100
|
|
21
21
|
},
|
|
22
|
+
|
|
22
23
|
{
|
|
23
24
|
"query": "MATCH (:GitHubBranch)-[r:BRANCH]->(:GitHubRepository) WHERE r.lastupdated <> $UPDATE_TAG WITH r LIMIT $LIMIT_SIZE DELETE (r)",
|
|
24
25
|
"iterative": true,
|
|
@@ -39,6 +40,7 @@
|
|
|
39
40
|
"iterative": true,
|
|
40
41
|
"iterationsize": 100
|
|
41
42
|
},
|
|
43
|
+
|
|
42
44
|
{
|
|
43
45
|
"query": "MATCH (:GitHubUser)-[r:OUTSIDE_COLLAB_ADMIN]->(:GitHubRepository) WHERE r.lastupdated <> $UPDATE_TAG WITH r LIMIT $LIMIT_SIZE DELETE (r)",
|
|
44
46
|
"iterative": true,
|
|
@@ -310,6 +310,7 @@ def start_aws_ingestion(neo4j_session: neo4j.Session, config: Config) -> None:
|
|
|
310
310
|
common_job_parameters = {
|
|
311
311
|
"UPDATE_TAG": config.update_tag,
|
|
312
312
|
"permission_relationships_file": config.permission_relationships_file,
|
|
313
|
+
"aws_guardduty_severity_threshold": config.aws_guardduty_severity_threshold,
|
|
313
314
|
"aws_cloudtrail_management_events_lookback_hours": config.aws_cloudtrail_management_events_lookback_hours,
|
|
314
315
|
}
|
|
315
316
|
try:
|
|
@@ -26,13 +26,25 @@ def get_cloudtrail_trails(
|
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
trails = client.describe_trails()["trailList"]
|
|
29
|
-
|
|
30
|
-
# CloudTrail multi-region trails are shown in list_trails,
|
|
31
|
-
# but the get_trail call only works in the home region
|
|
32
29
|
trails_filtered = [trail for trail in trails if trail.get("HomeRegion") == region]
|
|
30
|
+
|
|
33
31
|
return trails_filtered
|
|
34
32
|
|
|
35
33
|
|
|
34
|
+
def transform_cloudtrail_trails(
|
|
35
|
+
trails: List[Dict[str, Any]], region: str
|
|
36
|
+
) -> List[Dict[str, Any]]:
|
|
37
|
+
"""
|
|
38
|
+
Transform CloudTrail trail data for ingestion
|
|
39
|
+
"""
|
|
40
|
+
for trail in trails:
|
|
41
|
+
arn = trail.get("CloudWatchLogsLogGroupArn")
|
|
42
|
+
if arn:
|
|
43
|
+
trail["CloudWatchLogsLogGroupArn"] = arn.split(":*")[0]
|
|
44
|
+
|
|
45
|
+
return trails
|
|
46
|
+
|
|
47
|
+
|
|
36
48
|
@timeit
|
|
37
49
|
def load_cloudtrail_trails(
|
|
38
50
|
neo4j_session: neo4j.Session,
|
|
@@ -79,7 +91,8 @@ def sync(
|
|
|
79
91
|
logger.info(
|
|
80
92
|
f"Syncing CloudTrail for region '{region}' in account '{current_aws_account_id}'.",
|
|
81
93
|
)
|
|
82
|
-
|
|
94
|
+
trails_filtered = get_cloudtrail_trails(boto3_session, region)
|
|
95
|
+
trails = transform_cloudtrail_trails(trails_filtered, region)
|
|
83
96
|
|
|
84
97
|
load_cloudtrail_trails(
|
|
85
98
|
neo4j_session,
|