cartography 0.113.0__py3-none-any.whl → 0.115.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 -2
- cartography/client/core/tx.py +11 -0
- cartography/config.py +4 -0
- cartography/data/indexes.cypher +0 -27
- cartography/intel/aws/config.py +7 -3
- cartography/intel/aws/ecr.py +9 -9
- cartography/intel/aws/iam.py +741 -492
- cartography/intel/aws/identitycenter.py +240 -13
- cartography/intel/aws/lambda_function.py +69 -2
- cartography/intel/aws/organizations.py +10 -9
- cartography/intel/aws/permission_relationships.py +7 -17
- cartography/intel/aws/redshift.py +9 -4
- cartography/intel/aws/route53.py +53 -3
- cartography/intel/aws/securityhub.py +3 -1
- cartography/intel/azure/__init__.py +24 -0
- cartography/intel/azure/app_service.py +105 -0
- cartography/intel/azure/functions.py +124 -0
- cartography/intel/azure/logic_apps.py +101 -0
- cartography/intel/create_indexes.py +2 -1
- cartography/intel/dns.py +5 -2
- cartography/intel/entra/__init__.py +31 -0
- cartography/intel/entra/app_role_assignments.py +277 -0
- cartography/intel/entra/applications.py +4 -238
- cartography/intel/entra/federation/__init__.py +0 -0
- cartography/intel/entra/federation/aws_identity_center.py +77 -0
- cartography/intel/entra/service_principals.py +217 -0
- cartography/intel/gcp/__init__.py +136 -440
- cartography/intel/gcp/clients.py +65 -0
- cartography/intel/gcp/compute.py +18 -44
- cartography/intel/gcp/crm/__init__.py +0 -0
- cartography/intel/gcp/crm/folders.py +108 -0
- cartography/intel/gcp/crm/orgs.py +65 -0
- cartography/intel/gcp/crm/projects.py +109 -0
- cartography/intel/gcp/dns.py +2 -1
- cartography/intel/gcp/gke.py +72 -113
- cartography/intel/github/__init__.py +41 -0
- cartography/intel/github/commits.py +423 -0
- cartography/intel/github/repos.py +76 -45
- cartography/intel/gsuite/api.py +17 -4
- cartography/intel/okta/applications.py +9 -4
- cartography/intel/okta/awssaml.py +5 -2
- cartography/intel/okta/factors.py +3 -1
- cartography/intel/okta/groups.py +5 -2
- cartography/intel/okta/organization.py +3 -1
- cartography/intel/okta/origins.py +3 -1
- cartography/intel/okta/roles.py +5 -2
- cartography/intel/okta/users.py +3 -1
- cartography/models/aws/iam/access_key.py +103 -0
- cartography/models/aws/iam/account_role.py +24 -0
- cartography/models/aws/iam/federated_principal.py +60 -0
- cartography/models/aws/iam/group.py +60 -0
- cartography/models/aws/iam/group_membership.py +26 -0
- cartography/models/aws/iam/inline_policy.py +78 -0
- cartography/models/aws/iam/managed_policy.py +51 -0
- cartography/models/aws/iam/policy_statement.py +57 -0
- cartography/models/aws/iam/role.py +83 -0
- cartography/models/aws/iam/root_principal.py +52 -0
- cartography/models/aws/iam/service_principal.py +30 -0
- cartography/models/aws/iam/sts_assumerole_allow.py +38 -0
- cartography/models/aws/iam/user.py +54 -0
- cartography/models/aws/identitycenter/awspermissionset.py +24 -1
- cartography/models/aws/identitycenter/awssogroup.py +70 -0
- cartography/models/aws/identitycenter/awsssouser.py +37 -1
- cartography/models/aws/lambda_function/lambda_function.py +2 -0
- cartography/models/azure/__init__.py +0 -0
- cartography/models/azure/app_service.py +59 -0
- cartography/models/azure/function_app.py +59 -0
- cartography/models/azure/logic_apps.py +56 -0
- cartography/models/entra/entra_user_to_aws_sso.py +41 -0
- cartography/models/entra/service_principal.py +104 -0
- cartography/models/entra/user.py +18 -0
- cartography/models/gcp/compute/subnet.py +74 -0
- cartography/models/gcp/crm/__init__.py +0 -0
- cartography/models/gcp/crm/folders.py +98 -0
- cartography/models/gcp/crm/organizations.py +21 -0
- cartography/models/gcp/crm/projects.py +100 -0
- cartography/models/gcp/gke.py +69 -0
- cartography/models/github/commits.py +63 -0
- {cartography-0.113.0.dist-info → cartography-0.115.0.dist-info}/METADATA +8 -5
- {cartography-0.113.0.dist-info → cartography-0.115.0.dist-info}/RECORD +85 -56
- cartography/data/jobs/cleanup/aws_import_account_access_key_cleanup.json +0 -17
- cartography/data/jobs/cleanup/aws_import_groups_cleanup.json +0 -13
- cartography/data/jobs/cleanup/aws_import_principals_cleanup.json +0 -30
- cartography/data/jobs/cleanup/aws_import_roles_cleanup.json +0 -13
- cartography/data/jobs/cleanup/aws_import_users_cleanup.json +0 -8
- cartography/data/jobs/cleanup/gcp_compute_vpc_subnet_cleanup.json +0 -35
- cartography/data/jobs/cleanup/gcp_crm_folder_cleanup.json +0 -23
- cartography/data/jobs/cleanup/gcp_crm_organization_cleanup.json +0 -17
- cartography/data/jobs/cleanup/gcp_crm_project_cleanup.json +0 -23
- cartography/data/jobs/cleanup/gcp_gke_cluster_cleanup.json +0 -17
- cartography/intel/gcp/crm.py +0 -355
- {cartography-0.113.0.dist-info → cartography-0.115.0.dist-info}/WHEEL +0 -0
- {cartography-0.113.0.dist-info → cartography-0.115.0.dist-info}/entry_points.txt +0 -0
- {cartography-0.113.0.dist-info → cartography-0.115.0.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.113.0.dist-info → cartography-0.115.0.dist-info}/top_level.txt +0 -0
cartography/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.
|
|
32
|
-
__version_tuple__ = version_tuple = (0,
|
|
31
|
+
__version__ = version = '0.115.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 115, 0)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
cartography/cli.py
CHANGED
|
@@ -328,6 +328,14 @@ class CLI:
|
|
|
328
328
|
"Required if you are using the GitHub intel module. Ignored otherwise."
|
|
329
329
|
),
|
|
330
330
|
)
|
|
331
|
+
parser.add_argument(
|
|
332
|
+
"--github-commit-lookback-days",
|
|
333
|
+
type=int,
|
|
334
|
+
default=30,
|
|
335
|
+
help=(
|
|
336
|
+
"Number of days to look back for tracking GitHub users committing to repositories. Defaults to 30 days."
|
|
337
|
+
),
|
|
338
|
+
)
|
|
331
339
|
parser.add_argument(
|
|
332
340
|
"--digitalocean-token-env-var",
|
|
333
341
|
type=str,
|
|
@@ -959,8 +967,8 @@ class CLI:
|
|
|
959
967
|
logger.warning("A Kandji base URI was provided but a token was not.")
|
|
960
968
|
config.kandji_token = None
|
|
961
969
|
else:
|
|
962
|
-
logger.warning("A Kandji base URI was not provided.")
|
|
963
970
|
config.kandji_base_uri = None
|
|
971
|
+
config.kandji_token = None
|
|
964
972
|
|
|
965
973
|
if config.statsd_enabled:
|
|
966
974
|
logger.debug(
|
|
@@ -1088,8 +1096,8 @@ class CLI:
|
|
|
1088
1096
|
logger.warning("A SnipeIT base URI was provided but a token was not.")
|
|
1089
1097
|
config.snipeit_token = None
|
|
1090
1098
|
else:
|
|
1091
|
-
logger.warning("A SnipeIT base URI was not provided.")
|
|
1092
1099
|
config.snipeit_base_uri = None
|
|
1100
|
+
config.snipeit_token = None
|
|
1093
1101
|
|
|
1094
1102
|
# Tailscale config
|
|
1095
1103
|
if config.tailscale_token_env_var:
|
cartography/client/core/tx.py
CHANGED
|
@@ -19,6 +19,17 @@ from cartography.util import batch
|
|
|
19
19
|
logger = logging.getLogger(__name__)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
def run_write_query(
|
|
23
|
+
neo4j_session: neo4j.Session, query: str, **parameters: Any
|
|
24
|
+
) -> None:
|
|
25
|
+
"""Execute a write query inside a managed transaction."""
|
|
26
|
+
|
|
27
|
+
def _run_query_tx(tx: neo4j.Transaction) -> None:
|
|
28
|
+
tx.run(query, **parameters).consume()
|
|
29
|
+
|
|
30
|
+
neo4j_session.execute_write(_run_query_tx)
|
|
31
|
+
|
|
32
|
+
|
|
22
33
|
def read_list_of_values_tx(
|
|
23
34
|
tx: neo4j.Transaction,
|
|
24
35
|
query: str,
|
cartography/config.py
CHANGED
|
@@ -70,6 +70,8 @@ class Config:
|
|
|
70
70
|
:param okta_saml_role_regex: The regex used to map okta groups to AWS roles. Optional.
|
|
71
71
|
:type github_config: str
|
|
72
72
|
:param github_config: Base64 encoded config object for GitHub ingestion. Optional.
|
|
73
|
+
:type github_commit_lookback_days: int
|
|
74
|
+
:param github_commit_lookback_days: Number of days to look back for GitHub commit tracking. Optional.
|
|
73
75
|
:type digitalocean_token: str
|
|
74
76
|
:param digitalocean_token: DigitalOcean access token. Optional.
|
|
75
77
|
:type permission_relationships_file: str
|
|
@@ -210,6 +212,7 @@ class Config:
|
|
|
210
212
|
okta_api_key=None,
|
|
211
213
|
okta_saml_role_regex=None,
|
|
212
214
|
github_config=None,
|
|
215
|
+
github_commit_lookback_days=30,
|
|
213
216
|
digitalocean_token=None,
|
|
214
217
|
permission_relationships_file=None,
|
|
215
218
|
jamf_base_uri=None,
|
|
@@ -301,6 +304,7 @@ class Config:
|
|
|
301
304
|
self.okta_api_key = okta_api_key
|
|
302
305
|
self.okta_saml_role_regex = okta_saml_role_regex
|
|
303
306
|
self.github_config = github_config
|
|
307
|
+
self.github_commit_lookback_days = github_commit_lookback_days
|
|
304
308
|
self.digitalocean_token = digitalocean_token
|
|
305
309
|
self.permission_relationships_file = permission_relationships_file
|
|
306
310
|
self.jamf_base_uri = jamf_base_uri
|
cartography/data/indexes.cypher
CHANGED
|
@@ -21,23 +21,12 @@ CREATE INDEX IF NOT EXISTS FOR (n:AWSDNSRecord) ON (n.lastupdated);
|
|
|
21
21
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSDNSZone) ON (n.name);
|
|
22
22
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSDNSZone) ON (n.zoneid);
|
|
23
23
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSDNSZone) ON (n.lastupdated);
|
|
24
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSGroup) ON (n.arn);
|
|
25
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSGroup) ON (n.lastupdated);
|
|
26
24
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSInternetGateway) ON (n.id);
|
|
27
25
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSInternetGateway) ON (n.lastupdated);
|
|
28
26
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSIpv4CidrBlock) ON (n.id);
|
|
29
27
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSIpv4CidrBlock) ON (n.lastupdated);
|
|
30
28
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSIpv6CidrBlock) ON (n.id);
|
|
31
29
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSIpv6CidrBlock) ON (n.lastupdated);
|
|
32
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSPolicy) ON (n.id);
|
|
33
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSPolicy) ON (n.name);
|
|
34
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSPolicy) ON (n.lastupdated);
|
|
35
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSPolicyStatement) ON (n.id);
|
|
36
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSPolicyStatement) ON (n.lastupdated);
|
|
37
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSPrincipal) ON (n.arn);
|
|
38
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSPrincipal) ON (n.lastupdated);
|
|
39
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSRole) ON (n.arn);
|
|
40
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSRole) ON (n.lastupdated);
|
|
41
30
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSTag) ON (n.id);
|
|
42
31
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSTag) ON (n.key);
|
|
43
32
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSTag) ON (n.lastupdated);
|
|
@@ -46,11 +35,6 @@ CREATE INDEX IF NOT EXISTS FOR (n:AWSTransitGateway) ON (n.id);
|
|
|
46
35
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSTransitGateway) ON (n.lastupdated);
|
|
47
36
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSTransitGatewayAttachment) ON (n.id);
|
|
48
37
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSTransitGatewayAttachment) ON (n.lastupdated);
|
|
49
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSUser) ON (n.arn);
|
|
50
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSUser) ON (n.name);
|
|
51
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSUser) ON (n.lastupdated);
|
|
52
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AccountAccessKey) ON (n.accesskeyid);
|
|
53
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AccountAccessKey) ON (n.lastupdated);
|
|
54
38
|
CREATE INDEX IF NOT EXISTS FOR (n:AutoScalingGroup) ON (n.arn);
|
|
55
39
|
CREATE INDEX IF NOT EXISTS FOR (n:AutoScalingGroup) ON (n.lastupdated);
|
|
56
40
|
CREATE INDEX IF NOT EXISTS FOR (n:CVE) ON (n.id);
|
|
@@ -100,8 +84,6 @@ CREATE INDEX IF NOT EXISTS FOR (n:ESDomain) ON (n.arn);
|
|
|
100
84
|
CREATE INDEX IF NOT EXISTS FOR (n:ESDomain) ON (n.id);
|
|
101
85
|
CREATE INDEX IF NOT EXISTS FOR (n:ESDomain) ON (n.name);
|
|
102
86
|
CREATE INDEX IF NOT EXISTS FOR (n:ESDomain) ON (n.lastupdated);
|
|
103
|
-
CREATE INDEX IF NOT EXISTS FOR (n:GCPFolder) ON (n.id);
|
|
104
|
-
CREATE INDEX IF NOT EXISTS FOR (n:GCPFolder) ON (n.lastupdated);
|
|
105
87
|
CREATE INDEX IF NOT EXISTS FOR (n:GCPForwardingRule) ON (n.id);
|
|
106
88
|
CREATE INDEX IF NOT EXISTS FOR (n:GCPForwardingRule) ON (n.lastupdated);
|
|
107
89
|
CREATE INDEX IF NOT EXISTS FOR (n:GCPInstance) ON (n.id);
|
|
@@ -112,23 +94,14 @@ CREATE INDEX IF NOT EXISTS FOR (n:GCPNetworkTag) ON (n.id);
|
|
|
112
94
|
CREATE INDEX IF NOT EXISTS FOR (n:GCPNetworkTag) ON (n.lastupdated);
|
|
113
95
|
CREATE INDEX IF NOT EXISTS FOR (n:GCPNicAccessConfig) ON (n.id);
|
|
114
96
|
CREATE INDEX IF NOT EXISTS FOR (n:GCPNicAccessConfig) ON (n.lastupdated);
|
|
115
|
-
CREATE INDEX IF NOT EXISTS FOR (n:GCPOrganization) ON (n.id);
|
|
116
|
-
CREATE INDEX IF NOT EXISTS FOR (n:GCPOrganization) ON (n.lastupdated);
|
|
117
|
-
CREATE INDEX IF NOT EXISTS FOR (n:GCPProject) ON (n.id);
|
|
118
|
-
CREATE INDEX IF NOT EXISTS FOR (n:GCPProject) ON (n.projectnumber);
|
|
119
|
-
CREATE INDEX IF NOT EXISTS FOR (n:GCPProject) ON (n.lastupdated);
|
|
120
97
|
CREATE INDEX IF NOT EXISTS FOR (n:GCPBucket) ON (n.id);
|
|
121
98
|
CREATE INDEX IF NOT EXISTS FOR (n:GCPBucket) ON (n.lastupdated);
|
|
122
99
|
CREATE INDEX IF NOT EXISTS FOR (n:GCPBucketLabel) ON (n.key);
|
|
123
100
|
CREATE INDEX IF NOT EXISTS FOR (n:GCPBucketLabel) ON (n.lastupdated);
|
|
124
|
-
CREATE INDEX IF NOT EXISTS FOR (n:GCPSubnet) ON (n.id);
|
|
125
|
-
CREATE INDEX IF NOT EXISTS FOR (n:GCPSubnet) ON (n.lastupdated);
|
|
126
101
|
CREATE INDEX IF NOT EXISTS FOR (n:GCPVpc) ON (n.id);
|
|
127
102
|
CREATE INDEX IF NOT EXISTS FOR (n:GCPVpc) ON (n.lastupdated);
|
|
128
103
|
CREATE INDEX IF NOT EXISTS FOR (n:GitHubRepository) ON (n.id);
|
|
129
104
|
CREATE INDEX IF NOT EXISTS FOR (n:GitHubRepository) ON (n.lastupdated);
|
|
130
|
-
CREATE INDEX IF NOT EXISTS FOR (n:GKECluster) ON (n.id);
|
|
131
|
-
CREATE INDEX IF NOT EXISTS FOR (n:GKECluster) ON (n.lastupdated);
|
|
132
105
|
CREATE INDEX IF NOT EXISTS FOR (n:GSuiteGroup) ON (n.email);
|
|
133
106
|
CREATE INDEX IF NOT EXISTS FOR (n:GSuiteGroup) ON (n.id);
|
|
134
107
|
CREATE INDEX IF NOT EXISTS FOR (n:GSuiteGroup) ON (n.lastupdated);
|
cartography/intel/aws/config.py
CHANGED
|
@@ -5,6 +5,7 @@ from typing import List
|
|
|
5
5
|
import boto3
|
|
6
6
|
import neo4j
|
|
7
7
|
|
|
8
|
+
from cartography.client.core.tx import run_write_query
|
|
8
9
|
from cartography.util import aws_handle_regions
|
|
9
10
|
from cartography.util import run_cleanup_job
|
|
10
11
|
from cartography.util import timeit
|
|
@@ -80,7 +81,8 @@ def load_configuration_recorders(
|
|
|
80
81
|
for recorder in data:
|
|
81
82
|
recorder["_id"] = f'{recorder["name"]}:{current_aws_account_id}:{region}'
|
|
82
83
|
|
|
83
|
-
|
|
84
|
+
run_write_query(
|
|
85
|
+
neo4j_session,
|
|
84
86
|
ingest_configuration_recorders,
|
|
85
87
|
Recorders=data,
|
|
86
88
|
Region=region,
|
|
@@ -120,7 +122,8 @@ def load_delivery_channels(
|
|
|
120
122
|
for channel in data:
|
|
121
123
|
channel["_id"] = f'{channel["name"]}:{current_aws_account_id}:{region}'
|
|
122
124
|
|
|
123
|
-
|
|
125
|
+
run_write_query(
|
|
126
|
+
neo4j_session,
|
|
124
127
|
ingest_delivery_channels,
|
|
125
128
|
Channels=data,
|
|
126
129
|
Region=region,
|
|
@@ -167,7 +170,8 @@ def load_config_rules(
|
|
|
167
170
|
for detail in rule["Source"]["SourceDetails"]:
|
|
168
171
|
details.append(f"{detail}")
|
|
169
172
|
rule["_source_details"] = details
|
|
170
|
-
|
|
173
|
+
run_write_query(
|
|
174
|
+
neo4j_session,
|
|
171
175
|
ingest_config_rules,
|
|
172
176
|
Rules=data,
|
|
173
177
|
Region=region,
|
cartography/intel/aws/ecr.py
CHANGED
|
@@ -57,15 +57,15 @@ def get_ecr_repository_images(
|
|
|
57
57
|
)
|
|
58
58
|
for response in describe_response:
|
|
59
59
|
image_details = response["imageDetails"]
|
|
60
|
-
|
|
61
|
-
(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
60
|
+
for detail in image_details:
|
|
61
|
+
tags = detail.get("imageTags") or []
|
|
62
|
+
if tags:
|
|
63
|
+
for tag in tags:
|
|
64
|
+
image_detail = {**detail, "imageTag": tag}
|
|
65
|
+
image_detail.pop("imageTags", None)
|
|
66
|
+
ecr_repository_images.append(image_detail)
|
|
67
|
+
else:
|
|
68
|
+
ecr_repository_images.append({**detail})
|
|
69
69
|
return ecr_repository_images
|
|
70
70
|
|
|
71
71
|
|