cartography 0.102.0rc2__py3-none-any.whl → 0.103.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/__main__.py +1 -2
- cartography/_version.py +2 -2
- cartography/cli.py +376 -249
- cartography/client/core/tx.py +39 -18
- cartography/config.py +28 -0
- cartography/driftdetect/__main__.py +1 -2
- cartography/driftdetect/add_shortcut.py +10 -2
- cartography/driftdetect/cli.py +71 -75
- cartography/driftdetect/detect_deviations.py +7 -3
- cartography/driftdetect/get_states.py +20 -8
- cartography/driftdetect/model.py +5 -5
- cartography/driftdetect/serializers.py +8 -6
- cartography/driftdetect/storage.py +2 -2
- cartography/graph/cleanupbuilder.py +35 -15
- cartography/graph/job.py +46 -17
- cartography/graph/querybuilder.py +165 -80
- cartography/graph/statement.py +35 -26
- cartography/intel/analysis.py +4 -1
- cartography/intel/aws/__init__.py +114 -55
- cartography/intel/aws/apigateway.py +134 -63
- cartography/intel/aws/cloudtrail.py +127 -0
- cartography/intel/aws/cloudwatch.py +93 -0
- cartography/intel/aws/config.py +56 -20
- cartography/intel/aws/dynamodb.py +108 -40
- cartography/intel/aws/ec2/__init__.py +2 -2
- cartography/intel/aws/ec2/auto_scaling_groups.py +181 -78
- cartography/intel/aws/ec2/elastic_ip_addresses.py +41 -13
- cartography/intel/aws/ec2/images.py +49 -20
- cartography/intel/aws/ec2/instances.py +234 -136
- cartography/intel/aws/ec2/internet_gateways.py +40 -11
- cartography/intel/aws/ec2/key_pairs.py +44 -20
- cartography/intel/aws/ec2/launch_templates.py +101 -59
- cartography/intel/aws/ec2/load_balancer_v2s.py +104 -39
- cartography/intel/aws/ec2/load_balancers.py +82 -42
- cartography/intel/aws/ec2/network_acls.py +89 -65
- cartography/intel/aws/ec2/network_interfaces.py +146 -87
- cartography/intel/aws/ec2/reserved_instances.py +45 -16
- cartography/intel/aws/ec2/route_tables.py +138 -98
- cartography/intel/aws/ec2/security_groups.py +71 -21
- cartography/intel/aws/ec2/snapshots.py +61 -22
- cartography/intel/aws/ec2/subnets.py +54 -18
- cartography/intel/aws/ec2/tgw.py +100 -34
- cartography/intel/aws/ec2/util.py +1 -1
- cartography/intel/aws/ec2/volumes.py +69 -41
- cartography/intel/aws/ec2/vpc.py +37 -12
- cartography/intel/aws/ec2/vpc_peerings.py +83 -24
- cartography/intel/aws/ecr.py +88 -32
- cartography/intel/aws/ecs.py +83 -47
- cartography/intel/aws/efs.py +93 -0
- cartography/intel/aws/eks.py +55 -29
- cartography/intel/aws/elasticache.py +42 -18
- cartography/intel/aws/elasticsearch.py +57 -20
- cartography/intel/aws/emr.py +61 -23
- cartography/intel/aws/iam.py +401 -145
- cartography/intel/aws/iam_instance_profiles.py +22 -22
- cartography/intel/aws/identitycenter.py +71 -37
- cartography/intel/aws/inspector.py +159 -89
- cartography/intel/aws/kms.py +92 -38
- cartography/intel/aws/lambda_function.py +103 -34
- cartography/intel/aws/organizations.py +30 -10
- cartography/intel/aws/permission_relationships.py +133 -51
- cartography/intel/aws/rds.py +249 -85
- cartography/intel/aws/redshift.py +107 -46
- cartography/intel/aws/resourcegroupstaggingapi.py +120 -66
- cartography/intel/aws/resources.py +57 -46
- cartography/intel/aws/route53.py +108 -61
- cartography/intel/aws/s3.py +168 -83
- cartography/intel/aws/s3accountpublicaccessblock.py +157 -0
- cartography/intel/aws/secretsmanager.py +24 -12
- cartography/intel/aws/securityhub.py +20 -9
- cartography/intel/aws/sns.py +166 -0
- cartography/intel/aws/sqs.py +60 -28
- cartography/intel/aws/ssm.py +70 -30
- cartography/intel/aws/util/arns.py +7 -7
- cartography/intel/aws/util/common.py +31 -4
- cartography/intel/azure/__init__.py +78 -19
- cartography/intel/azure/compute.py +101 -27
- cartography/intel/azure/cosmosdb.py +496 -170
- cartography/intel/azure/sql.py +296 -105
- cartography/intel/azure/storage.py +322 -113
- cartography/intel/azure/subscription.py +39 -23
- cartography/intel/azure/tenant.py +13 -4
- cartography/intel/azure/util/credentials.py +95 -55
- cartography/intel/bigfix/__init__.py +2 -2
- cartography/intel/bigfix/computers.py +93 -65
- cartography/intel/cloudflare/__init__.py +74 -0
- cartography/intel/cloudflare/accounts.py +57 -0
- cartography/intel/cloudflare/dnsrecords.py +64 -0
- cartography/intel/cloudflare/members.py +75 -0
- cartography/intel/cloudflare/roles.py +65 -0
- cartography/intel/cloudflare/zones.py +64 -0
- cartography/intel/create_indexes.py +3 -2
- cartography/intel/crowdstrike/__init__.py +11 -9
- cartography/intel/crowdstrike/endpoints.py +5 -1
- cartography/intel/crowdstrike/spotlight.py +8 -3
- cartography/intel/cve/__init__.py +46 -13
- cartography/intel/cve/feed.py +48 -12
- cartography/intel/digitalocean/__init__.py +22 -13
- cartography/intel/digitalocean/compute.py +75 -108
- cartography/intel/digitalocean/management.py +44 -80
- cartography/intel/digitalocean/platform.py +48 -43
- cartography/intel/dns.py +36 -10
- cartography/intel/duo/__init__.py +21 -16
- cartography/intel/duo/api_host.py +14 -9
- cartography/intel/duo/endpoints.py +50 -45
- cartography/intel/duo/groups.py +18 -14
- cartography/intel/duo/phones.py +37 -34
- cartography/intel/duo/tokens.py +26 -23
- cartography/intel/duo/users.py +54 -50
- cartography/intel/duo/web_authn_credentials.py +30 -25
- cartography/intel/entra/__init__.py +25 -7
- cartography/intel/entra/ou.py +112 -0
- cartography/intel/entra/users.py +69 -63
- cartography/intel/gcp/__init__.py +185 -49
- cartography/intel/gcp/compute.py +418 -231
- cartography/intel/gcp/crm.py +96 -43
- cartography/intel/gcp/dns.py +60 -19
- cartography/intel/gcp/gke.py +72 -38
- cartography/intel/gcp/iam.py +61 -41
- cartography/intel/gcp/storage.py +84 -55
- cartography/intel/github/__init__.py +13 -11
- cartography/intel/github/repos.py +270 -137
- cartography/intel/github/teams.py +170 -88
- cartography/intel/github/users.py +70 -39
- cartography/intel/github/util.py +36 -34
- cartography/intel/gsuite/__init__.py +47 -26
- cartography/intel/gsuite/api.py +73 -30
- cartography/intel/jamf/__init__.py +19 -1
- cartography/intel/jamf/computers.py +30 -7
- cartography/intel/jamf/util.py +7 -2
- cartography/intel/kandji/__init__.py +6 -3
- cartography/intel/kandji/devices.py +14 -8
- cartography/intel/kubernetes/namespaces.py +7 -4
- cartography/intel/kubernetes/pods.py +7 -4
- cartography/intel/kubernetes/services.py +8 -4
- cartography/intel/lastpass/__init__.py +2 -2
- cartography/intel/lastpass/users.py +23 -12
- cartography/intel/oci/__init__.py +44 -11
- cartography/intel/oci/iam.py +134 -38
- cartography/intel/oci/organizations.py +13 -6
- cartography/intel/oci/utils.py +43 -20
- cartography/intel/okta/__init__.py +66 -15
- cartography/intel/okta/applications.py +42 -20
- cartography/intel/okta/awssaml.py +93 -33
- cartography/intel/okta/factors.py +16 -4
- cartography/intel/okta/groups.py +56 -29
- cartography/intel/okta/organization.py +5 -1
- cartography/intel/okta/origins.py +6 -2
- cartography/intel/okta/roles.py +15 -5
- cartography/intel/okta/users.py +20 -8
- cartography/intel/okta/utils.py +6 -4
- cartography/intel/openai/__init__.py +86 -0
- cartography/intel/openai/adminapikeys.py +90 -0
- cartography/intel/openai/apikeys.py +96 -0
- cartography/intel/openai/projects.py +94 -0
- cartography/intel/openai/serviceaccounts.py +82 -0
- cartography/intel/openai/users.py +78 -0
- cartography/intel/openai/util.py +29 -0
- cartography/intel/pagerduty/__init__.py +8 -7
- cartography/intel/pagerduty/escalation_policies.py +18 -6
- cartography/intel/pagerduty/schedules.py +12 -4
- cartography/intel/pagerduty/services.py +11 -4
- cartography/intel/pagerduty/teams.py +8 -3
- cartography/intel/pagerduty/users.py +3 -1
- cartography/intel/pagerduty/vendors.py +3 -1
- cartography/intel/semgrep/__init__.py +24 -6
- cartography/intel/semgrep/dependencies.py +50 -28
- cartography/intel/semgrep/deployment.py +3 -1
- cartography/intel/semgrep/findings.py +42 -18
- cartography/intel/snipeit/__init__.py +17 -3
- cartography/intel/snipeit/asset.py +12 -6
- cartography/intel/snipeit/user.py +8 -5
- cartography/intel/snipeit/util.py +9 -4
- cartography/intel/tailscale/__init__.py +77 -0
- cartography/intel/tailscale/acls.py +146 -0
- cartography/intel/tailscale/devices.py +127 -0
- cartography/intel/tailscale/postureintegrations.py +81 -0
- cartography/intel/tailscale/tailnets.py +76 -0
- cartography/intel/tailscale/users.py +80 -0
- cartography/intel/tailscale/utils.py +132 -0
- cartography/models/aws/apigateway.py +21 -17
- cartography/models/aws/apigatewaycertificate.py +28 -22
- cartography/models/aws/apigatewayresource.py +28 -20
- cartography/models/aws/apigatewaystage.py +33 -25
- cartography/models/aws/cloudtrail/__init__.py +0 -0
- cartography/models/aws/cloudtrail/trail.py +61 -0
- cartography/models/aws/cloudwatch/__init__.py +0 -0
- cartography/models/aws/cloudwatch/loggroup.py +52 -0
- cartography/models/aws/dynamodb/gsi.py +30 -22
- cartography/models/aws/dynamodb/tables.py +25 -17
- cartography/models/aws/ec2/auto_scaling_groups.py +102 -82
- cartography/models/aws/ec2/images.py +36 -34
- cartography/models/aws/ec2/instances.py +51 -45
- cartography/models/aws/ec2/keypair.py +21 -16
- cartography/models/aws/ec2/keypair_instance.py +28 -21
- cartography/models/aws/ec2/launch_configurations.py +30 -26
- cartography/models/aws/ec2/launch_template_versions.py +48 -38
- cartography/models/aws/ec2/launch_templates.py +21 -17
- cartography/models/aws/ec2/load_balancer_listeners.py +27 -23
- cartography/models/aws/ec2/load_balancers.py +47 -37
- cartography/models/aws/ec2/network_acl_rules.py +38 -30
- cartography/models/aws/ec2/network_acls.py +38 -29
- cartography/models/aws/ec2/networkinterface_instance.py +52 -39
- cartography/models/aws/ec2/networkinterfaces.py +53 -37
- cartography/models/aws/ec2/privateip_networkinterface.py +32 -22
- cartography/models/aws/ec2/reservations.py +18 -14
- cartography/models/aws/ec2/route_table_associations.py +44 -34
- cartography/models/aws/ec2/route_tables.py +50 -43
- cartography/models/aws/ec2/routes.py +45 -37
- cartography/models/aws/ec2/securitygroup_instance.py +29 -20
- cartography/models/aws/ec2/securitygroup_networkinterface.py +24 -15
- cartography/models/aws/ec2/subnet_instance.py +24 -19
- cartography/models/aws/ec2/subnet_networkinterface.py +40 -31
- cartography/models/aws/ec2/volumes.py +47 -40
- cartography/models/aws/efs/__init__.py +0 -0
- cartography/models/aws/efs/mount_target.py +52 -0
- cartography/models/aws/eks/clusters.py +23 -21
- cartography/models/aws/emr.py +32 -30
- cartography/models/aws/iam/instanceprofile.py +33 -24
- cartography/models/aws/identitycenter/awsidentitycenter.py +18 -14
- cartography/models/aws/identitycenter/awspermissionset.py +37 -29
- cartography/models/aws/identitycenter/awsssouser.py +23 -21
- cartography/models/aws/inspector/findings.py +77 -65
- cartography/models/aws/inspector/packages.py +35 -29
- cartography/models/aws/s3/__init__.py +0 -0
- cartography/models/aws/s3/account_public_access_block.py +51 -0
- cartography/models/aws/sns/__init__.py +0 -0
- cartography/models/aws/sns/topic.py +50 -0
- cartography/models/aws/ssm/instance_information.py +51 -39
- cartography/models/aws/ssm/instance_patch.py +32 -26
- cartography/models/bigfix/bigfix_computer.py +42 -38
- cartography/models/bigfix/bigfix_root.py +3 -3
- cartography/models/cloudflare/__init__.py +0 -0
- cartography/models/cloudflare/account.py +25 -0
- cartography/models/cloudflare/dnsrecord.py +55 -0
- cartography/models/cloudflare/member.py +82 -0
- cartography/models/cloudflare/role.py +44 -0
- cartography/models/cloudflare/zone.py +59 -0
- cartography/models/core/common.py +12 -10
- cartography/models/core/nodes.py +5 -2
- cartography/models/core/relationships.py +14 -6
- cartography/models/crowdstrike/hosts.py +37 -35
- cartography/models/cve/cve.py +34 -32
- cartography/models/cve/cve_feed.py +6 -6
- cartography/models/digitalocean/__init__.py +0 -0
- cartography/models/digitalocean/account.py +21 -0
- cartography/models/digitalocean/droplet.py +56 -0
- cartography/models/digitalocean/project.py +48 -0
- cartography/models/duo/api_host.py +3 -3
- cartography/models/duo/endpoint.py +43 -41
- cartography/models/duo/group.py +14 -14
- cartography/models/duo/phone.py +27 -27
- cartography/models/duo/token.py +16 -16
- cartography/models/duo/user.py +46 -44
- cartography/models/duo/web_authn_credential.py +27 -19
- cartography/models/entra/ou.py +48 -0
- cartography/models/entra/tenant.py +24 -18
- cartography/models/entra/user.py +64 -48
- cartography/models/gcp/iam.py +23 -23
- cartography/models/github/orgs.py +5 -4
- cartography/models/github/teams.py +37 -31
- cartography/models/github/users.py +34 -23
- cartography/models/kandji/device.py +22 -16
- cartography/models/kandji/tenant.py +6 -4
- cartography/models/lastpass/tenant.py +3 -3
- cartography/models/lastpass/user.py +32 -28
- cartography/models/openai/__init__.py +0 -0
- cartography/models/openai/adminapikey.py +90 -0
- cartography/models/openai/apikey.py +84 -0
- cartography/models/openai/organization.py +17 -0
- cartography/models/openai/project.py +70 -0
- cartography/models/openai/serviceaccount.py +50 -0
- cartography/models/openai/user.py +49 -0
- cartography/models/semgrep/dependencies.py +36 -24
- cartography/models/semgrep/deployment.py +5 -5
- cartography/models/semgrep/findings.py +58 -42
- cartography/models/semgrep/locations.py +27 -21
- cartography/models/snipeit/asset.py +30 -21
- cartography/models/snipeit/tenant.py +6 -4
- cartography/models/snipeit/user.py +19 -12
- cartography/models/tailscale/__init__.py +0 -0
- cartography/models/tailscale/device.py +95 -0
- cartography/models/tailscale/group.py +86 -0
- cartography/models/tailscale/postureintegration.py +58 -0
- cartography/models/tailscale/tag.py +102 -0
- cartography/models/tailscale/tailnet.py +29 -0
- cartography/models/tailscale/user.py +52 -0
- cartography/stats.py +3 -3
- cartography/sync.py +113 -31
- cartography/util.py +84 -62
- {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/METADATA +8 -15
- cartography-0.103.0.dist-info/RECORD +442 -0
- {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/WHEEL +1 -1
- cartography-0.102.0rc2.dist-info/RECORD +0 -381
- {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/entry_points.txt +0 -0
- {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/top_level.txt +0 -0
cartography/intel/okta/roles.py
CHANGED
|
@@ -26,7 +26,7 @@ def _get_user_roles(api_client: ApiClient, user_id: str, okta_org_id: str) -> st
|
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
28
|
# https://developer.okta.com/docs/reference/api/roles/#list-roles
|
|
29
|
-
response = api_client.get_path(f
|
|
29
|
+
response = api_client.get_path(f"/{user_id}/roles")
|
|
30
30
|
check_rate_limit(response)
|
|
31
31
|
return response.text
|
|
32
32
|
|
|
@@ -42,7 +42,7 @@ def _get_group_roles(api_client: ApiClient, group_id: str, okta_org_id: str) ->
|
|
|
42
42
|
"""
|
|
43
43
|
|
|
44
44
|
# https://developer.okta.com/docs/reference/api/roles/#list-roles-assigned-to-group
|
|
45
|
-
response = api_client.get_path(f
|
|
45
|
+
response = api_client.get_path(f"/{group_id}/roles")
|
|
46
46
|
check_rate_limit(response)
|
|
47
47
|
return response.text
|
|
48
48
|
|
|
@@ -94,7 +94,12 @@ def transform_group_roles_data(data: str, okta_org_id: str) -> List[Dict]:
|
|
|
94
94
|
|
|
95
95
|
|
|
96
96
|
@timeit
|
|
97
|
-
def _load_user_role(
|
|
97
|
+
def _load_user_role(
|
|
98
|
+
neo4j_session: neo4j.Session,
|
|
99
|
+
user_id: str,
|
|
100
|
+
roles_data: List[Dict],
|
|
101
|
+
okta_update_tag: int,
|
|
102
|
+
) -> None:
|
|
98
103
|
ingest = """
|
|
99
104
|
MATCH (user:OktaUser{id: $USER_ID})<-[:RESOURCE]-(org:OktaOrganization)
|
|
100
105
|
WITH user,org
|
|
@@ -122,7 +127,9 @@ def _load_user_role(neo4j_session: neo4j.Session, user_id: str, roles_data: List
|
|
|
122
127
|
|
|
123
128
|
@timeit
|
|
124
129
|
def _load_group_role(
|
|
125
|
-
neo4j_session: neo4j.Session,
|
|
130
|
+
neo4j_session: neo4j.Session,
|
|
131
|
+
group_id: str,
|
|
132
|
+
roles_data: List[Dict],
|
|
126
133
|
okta_update_tag: int,
|
|
127
134
|
) -> None:
|
|
128
135
|
ingest = """
|
|
@@ -152,7 +159,10 @@ def _load_group_role(
|
|
|
152
159
|
|
|
153
160
|
@timeit
|
|
154
161
|
def sync_roles(
|
|
155
|
-
neo4j_session: str,
|
|
162
|
+
neo4j_session: str,
|
|
163
|
+
okta_org_id: str,
|
|
164
|
+
okta_update_tag: int,
|
|
165
|
+
okta_api_key: str,
|
|
156
166
|
sync_state: OktaSyncState,
|
|
157
167
|
) -> None:
|
|
158
168
|
"""
|
cartography/intel/okta/users.py
CHANGED
|
@@ -12,7 +12,6 @@ from cartography.intel.okta.sync_state import OktaSyncState
|
|
|
12
12
|
from cartography.intel.okta.utils import check_rate_limit
|
|
13
13
|
from cartography.util import timeit
|
|
14
14
|
|
|
15
|
-
|
|
16
15
|
logger = logging.getLogger(__name__)
|
|
17
16
|
|
|
18
17
|
|
|
@@ -56,7 +55,9 @@ def _get_okta_users(user_client: UsersClient) -> List[Dict]:
|
|
|
56
55
|
|
|
57
56
|
|
|
58
57
|
@timeit
|
|
59
|
-
def transform_okta_user_list(
|
|
58
|
+
def transform_okta_user_list(
|
|
59
|
+
okta_user_list: List[User],
|
|
60
|
+
) -> Tuple[List[Dict], List[str]]:
|
|
60
61
|
users: List[Dict] = []
|
|
61
62
|
user_ids: List[str] = []
|
|
62
63
|
|
|
@@ -91,7 +92,9 @@ def transform_okta_user(okta_user: User) -> Dict:
|
|
|
91
92
|
user_props["activated"] = None
|
|
92
93
|
|
|
93
94
|
if okta_user.statusChanged:
|
|
94
|
-
user_props["status_changed"] = okta_user.statusChanged.strftime(
|
|
95
|
+
user_props["status_changed"] = okta_user.statusChanged.strftime(
|
|
96
|
+
"%m/%d/%Y, %H:%M:%S",
|
|
97
|
+
)
|
|
95
98
|
else:
|
|
96
99
|
user_props["status_changed"] = None
|
|
97
100
|
|
|
@@ -101,12 +104,16 @@ def transform_okta_user(okta_user: User) -> Dict:
|
|
|
101
104
|
user_props["last_login"] = None
|
|
102
105
|
|
|
103
106
|
if okta_user.lastUpdated:
|
|
104
|
-
user_props["okta_last_updated"] = okta_user.lastUpdated.strftime(
|
|
107
|
+
user_props["okta_last_updated"] = okta_user.lastUpdated.strftime(
|
|
108
|
+
"%m/%d/%Y, %H:%M:%S",
|
|
109
|
+
)
|
|
105
110
|
else:
|
|
106
111
|
user_props["okta_last_updated"] = None
|
|
107
112
|
|
|
108
113
|
if okta_user.passwordChanged:
|
|
109
|
-
user_props["password_changed"] = okta_user.passwordChanged.strftime(
|
|
114
|
+
user_props["password_changed"] = okta_user.passwordChanged.strftime(
|
|
115
|
+
"%m/%d/%Y, %H:%M:%S",
|
|
116
|
+
)
|
|
110
117
|
else:
|
|
111
118
|
user_props["password_changed"] = None
|
|
112
119
|
|
|
@@ -120,7 +127,9 @@ def transform_okta_user(okta_user: User) -> Dict:
|
|
|
120
127
|
|
|
121
128
|
@timeit
|
|
122
129
|
def _load_okta_users(
|
|
123
|
-
neo4j_session: neo4j.Session,
|
|
130
|
+
neo4j_session: neo4j.Session,
|
|
131
|
+
okta_org_id: str,
|
|
132
|
+
user_list: List[Dict],
|
|
124
133
|
okta_update_tag: int,
|
|
125
134
|
) -> None:
|
|
126
135
|
"""
|
|
@@ -175,8 +184,11 @@ def _load_okta_users(
|
|
|
175
184
|
|
|
176
185
|
@timeit
|
|
177
186
|
def sync_okta_users(
|
|
178
|
-
neo4j_session: neo4j.Session,
|
|
179
|
-
|
|
187
|
+
neo4j_session: neo4j.Session,
|
|
188
|
+
okta_org_id: str,
|
|
189
|
+
okta_update_tag: int,
|
|
190
|
+
okta_api_key: str,
|
|
191
|
+
sync_state: OktaSyncState,
|
|
180
192
|
) -> None:
|
|
181
193
|
"""
|
|
182
194
|
Sync okta users
|
cartography/intel/okta/utils.py
CHANGED
|
@@ -43,9 +43,9 @@ def check_rate_limit(response: Response) -> None:
|
|
|
43
43
|
"""
|
|
44
44
|
rate_limit_threshold = 0.1
|
|
45
45
|
|
|
46
|
-
remaining = response.headers.get(
|
|
47
|
-
limit = response.headers.get(
|
|
48
|
-
reset_time = response.headers.get(
|
|
46
|
+
remaining = response.headers.get("x-rate-limit-remaining")
|
|
47
|
+
limit = response.headers.get("x-rate-limit-limit")
|
|
48
|
+
reset_time = response.headers.get("x-rate-limit-reset")
|
|
49
49
|
|
|
50
50
|
if remaining and limit and reset_time:
|
|
51
51
|
if (int(remaining) / int(limit)) < rate_limit_threshold:
|
|
@@ -58,5 +58,7 @@ def check_rate_limit(response: Response) -> None:
|
|
|
58
58
|
f"Okta API limit exceeded. Sleep time of {sleep_time_seconds} would exceed one minute. Crashing "
|
|
59
59
|
f"Okta sync to avoid blocking.",
|
|
60
60
|
)
|
|
61
|
-
logger.warning(
|
|
61
|
+
logger.warning(
|
|
62
|
+
f"Okta rate limit threshold reached. Waiting {sleep_time_seconds} seconds.",
|
|
63
|
+
)
|
|
62
64
|
time.sleep(sleep_time_seconds)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import neo4j
|
|
4
|
+
import requests
|
|
5
|
+
|
|
6
|
+
import cartography.intel.openai.adminapikeys
|
|
7
|
+
import cartography.intel.openai.apikeys
|
|
8
|
+
import cartography.intel.openai.projects
|
|
9
|
+
import cartography.intel.openai.serviceaccounts
|
|
10
|
+
import cartography.intel.openai.users
|
|
11
|
+
from cartography.config import Config
|
|
12
|
+
from cartography.util import timeit
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@timeit
|
|
18
|
+
def start_openai_ingestion(neo4j_session: neo4j.Session, config: Config) -> None:
|
|
19
|
+
"""
|
|
20
|
+
If this module is configured, perform ingestion of OpenAI data. Otherwise warn and exit
|
|
21
|
+
:param neo4j_session: Neo4J session for database interface
|
|
22
|
+
:param config: A cartography.config object
|
|
23
|
+
:return: None
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
if not config.openai_apikey or not config.openai_org_id:
|
|
27
|
+
logger.info(
|
|
28
|
+
"OpenAI import is not configured - skipping this module. "
|
|
29
|
+
"See docs to configure.",
|
|
30
|
+
)
|
|
31
|
+
return
|
|
32
|
+
|
|
33
|
+
# Create requests sessions
|
|
34
|
+
api_session = requests.session()
|
|
35
|
+
api_session.headers.update(
|
|
36
|
+
{
|
|
37
|
+
"Authorization": f"Bearer {config.openai_apikey}",
|
|
38
|
+
"OpenAI-Organization": config.openai_org_id,
|
|
39
|
+
}
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
common_job_parameters = {
|
|
43
|
+
"UPDATE_TAG": config.update_tag,
|
|
44
|
+
"BASE_URL": "https://api.openai.com/v1",
|
|
45
|
+
"ORG_ID": config.openai_org_id,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# Organization node is created during the users sync
|
|
49
|
+
cartography.intel.openai.users.sync(
|
|
50
|
+
neo4j_session,
|
|
51
|
+
api_session,
|
|
52
|
+
common_job_parameters,
|
|
53
|
+
ORG_ID=config.openai_org_id,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
for project in cartography.intel.openai.projects.sync(
|
|
57
|
+
neo4j_session,
|
|
58
|
+
api_session,
|
|
59
|
+
common_job_parameters,
|
|
60
|
+
ORG_ID=config.openai_org_id,
|
|
61
|
+
):
|
|
62
|
+
project_job_parameters = {
|
|
63
|
+
"UPDATE_TAG": config.update_tag,
|
|
64
|
+
"BASE_URL": "https://api.openai.com/v1",
|
|
65
|
+
"ORG_ID": config.openai_org_id,
|
|
66
|
+
"project_id": project["id"],
|
|
67
|
+
}
|
|
68
|
+
cartography.intel.openai.serviceaccounts.sync(
|
|
69
|
+
neo4j_session,
|
|
70
|
+
api_session,
|
|
71
|
+
project_job_parameters,
|
|
72
|
+
project_id=project["id"],
|
|
73
|
+
)
|
|
74
|
+
cartography.intel.openai.apikeys.sync(
|
|
75
|
+
neo4j_session,
|
|
76
|
+
api_session,
|
|
77
|
+
project_job_parameters,
|
|
78
|
+
project_id=project["id"],
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
cartography.intel.openai.adminapikeys.sync(
|
|
82
|
+
neo4j_session,
|
|
83
|
+
api_session,
|
|
84
|
+
common_job_parameters,
|
|
85
|
+
ORG_ID=config.openai_org_id,
|
|
86
|
+
)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
import neo4j
|
|
7
|
+
import requests
|
|
8
|
+
|
|
9
|
+
from cartography.client.core.tx import load
|
|
10
|
+
from cartography.graph.job import GraphJob
|
|
11
|
+
from cartography.intel.openai.util import paginated_get
|
|
12
|
+
from cartography.models.openai.adminapikey import OpenAIAdminApiKeySchema
|
|
13
|
+
from cartography.util import timeit
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
# Connect and read timeouts of 60 seconds each; see https://requests.readthedocs.io/en/master/user/advanced/#timeouts
|
|
17
|
+
_TIMEOUT = (60, 60)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@timeit
|
|
21
|
+
def sync(
|
|
22
|
+
neo4j_session: neo4j.Session,
|
|
23
|
+
api_session: requests.Session,
|
|
24
|
+
common_job_parameters: Dict[str, Any],
|
|
25
|
+
ORG_ID: str,
|
|
26
|
+
) -> List[Dict]:
|
|
27
|
+
adminapikeys = get(
|
|
28
|
+
api_session,
|
|
29
|
+
common_job_parameters["BASE_URL"],
|
|
30
|
+
)
|
|
31
|
+
transformed_adminapikeys = transform(adminapikeys)
|
|
32
|
+
load_adminapikeys(
|
|
33
|
+
neo4j_session,
|
|
34
|
+
transformed_adminapikeys,
|
|
35
|
+
ORG_ID,
|
|
36
|
+
common_job_parameters["UPDATE_TAG"],
|
|
37
|
+
)
|
|
38
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
39
|
+
return adminapikeys
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@timeit
|
|
43
|
+
def get(
|
|
44
|
+
api_session: requests.Session,
|
|
45
|
+
base_url: str,
|
|
46
|
+
) -> List[Dict[str, Any]]:
|
|
47
|
+
return list(
|
|
48
|
+
paginated_get(
|
|
49
|
+
api_session, f"{base_url}/organization/admin_api_keys", timeout=_TIMEOUT
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def transform(
|
|
55
|
+
adminapikeys: List[Dict[str, Any]],
|
|
56
|
+
) -> List[Dict[str, Any]]:
|
|
57
|
+
result: List[Dict[str, Any]] = []
|
|
58
|
+
for adminapikey in adminapikeys:
|
|
59
|
+
if adminapikey["owner"]["type"] == "user":
|
|
60
|
+
adminapikey["owner_user_id"] = adminapikey["owner"]["id"]
|
|
61
|
+
else:
|
|
62
|
+
adminapikey["owner_sa_id"] = adminapikey["owner"]["id"]
|
|
63
|
+
result.append(adminapikey)
|
|
64
|
+
return result
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@timeit
|
|
68
|
+
def load_adminapikeys(
|
|
69
|
+
neo4j_session: neo4j.Session,
|
|
70
|
+
data: List[Dict[str, Any]],
|
|
71
|
+
ORG_ID: str,
|
|
72
|
+
update_tag: int,
|
|
73
|
+
) -> None:
|
|
74
|
+
logger.info("Loading %d OpenAI AdminApiKey into Neo4j.", len(data))
|
|
75
|
+
load(
|
|
76
|
+
neo4j_session,
|
|
77
|
+
OpenAIAdminApiKeySchema(),
|
|
78
|
+
data,
|
|
79
|
+
lastupdated=update_tag,
|
|
80
|
+
ORG_ID=ORG_ID,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@timeit
|
|
85
|
+
def cleanup(
|
|
86
|
+
neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
|
|
87
|
+
) -> None:
|
|
88
|
+
GraphJob.from_node_schema(OpenAIAdminApiKeySchema(), common_job_parameters).run(
|
|
89
|
+
neo4j_session
|
|
90
|
+
)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
import neo4j
|
|
7
|
+
import requests
|
|
8
|
+
|
|
9
|
+
from cartography.client.core.tx import load
|
|
10
|
+
from cartography.graph.job import GraphJob
|
|
11
|
+
from cartography.intel.openai.util import paginated_get
|
|
12
|
+
from cartography.models.openai.apikey import OpenAIApiKeySchema
|
|
13
|
+
from cartography.util import timeit
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
# Connect and read timeouts of 60 seconds each; see https://requests.readthedocs.io/en/master/user/advanced/#timeouts
|
|
17
|
+
_TIMEOUT = (60, 60)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@timeit
|
|
21
|
+
def sync(
|
|
22
|
+
neo4j_session: neo4j.Session,
|
|
23
|
+
api_session: requests.Session,
|
|
24
|
+
common_job_parameters: Dict[str, Any],
|
|
25
|
+
project_id: str,
|
|
26
|
+
) -> None:
|
|
27
|
+
apikeys = get(
|
|
28
|
+
api_session,
|
|
29
|
+
common_job_parameters["BASE_URL"],
|
|
30
|
+
project_id,
|
|
31
|
+
)
|
|
32
|
+
transformed_apikeys = transform(apikeys)
|
|
33
|
+
load_apikeys(
|
|
34
|
+
neo4j_session,
|
|
35
|
+
transformed_apikeys,
|
|
36
|
+
project_id,
|
|
37
|
+
common_job_parameters["UPDATE_TAG"],
|
|
38
|
+
)
|
|
39
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@timeit
|
|
43
|
+
def get(
|
|
44
|
+
api_session: requests.Session,
|
|
45
|
+
base_url: str,
|
|
46
|
+
project_id: str,
|
|
47
|
+
) -> List[Dict[str, Any]]:
|
|
48
|
+
return list(
|
|
49
|
+
paginated_get(
|
|
50
|
+
api_session,
|
|
51
|
+
"{base_url}/organization/projects/{project_id}/api_keys".format(
|
|
52
|
+
base_url=base_url,
|
|
53
|
+
project_id=project_id,
|
|
54
|
+
),
|
|
55
|
+
timeout=_TIMEOUT,
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def transform(
|
|
61
|
+
apikeys: List[Dict[str, Any]],
|
|
62
|
+
) -> List[Dict[str, Any]]:
|
|
63
|
+
result: List[Dict[str, Any]] = []
|
|
64
|
+
for apikey in apikeys:
|
|
65
|
+
if apikey["owner"]["type"] == "user":
|
|
66
|
+
apikey["owner_user_id"] = apikey["owner"]["user"]["id"]
|
|
67
|
+
else:
|
|
68
|
+
apikey["owner_sa_id"] = apikey["owner"]["service_account"]["id"]
|
|
69
|
+
result.append(apikey)
|
|
70
|
+
return result
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@timeit
|
|
74
|
+
def load_apikeys(
|
|
75
|
+
neo4j_session: neo4j.Session,
|
|
76
|
+
data: List[Dict[str, Any]],
|
|
77
|
+
project_id: str,
|
|
78
|
+
update_tag: int,
|
|
79
|
+
) -> None:
|
|
80
|
+
logger.info("Loading %d OpenAI Project APIKey into Neo4j.", len(data))
|
|
81
|
+
load(
|
|
82
|
+
neo4j_session,
|
|
83
|
+
OpenAIApiKeySchema(),
|
|
84
|
+
data,
|
|
85
|
+
lastupdated=update_tag,
|
|
86
|
+
project_id=project_id,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@timeit
|
|
91
|
+
def cleanup(
|
|
92
|
+
neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
|
|
93
|
+
) -> None:
|
|
94
|
+
GraphJob.from_node_schema(OpenAIApiKeySchema(), common_job_parameters).run(
|
|
95
|
+
neo4j_session
|
|
96
|
+
)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
import neo4j
|
|
7
|
+
import requests
|
|
8
|
+
|
|
9
|
+
from cartography.client.core.tx import load
|
|
10
|
+
from cartography.graph.job import GraphJob
|
|
11
|
+
from cartography.intel.openai.util import paginated_get
|
|
12
|
+
from cartography.models.openai.project import OpenAIProjectSchema
|
|
13
|
+
from cartography.util import timeit
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
# Connect and read timeouts of 60 seconds each; see https://requests.readthedocs.io/en/master/user/advanced/#timeouts
|
|
17
|
+
_TIMEOUT = (60, 60)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@timeit
|
|
21
|
+
def sync(
|
|
22
|
+
neo4j_session: neo4j.Session,
|
|
23
|
+
api_session: requests.Session,
|
|
24
|
+
common_job_parameters: Dict[str, Any],
|
|
25
|
+
ORG_ID: str,
|
|
26
|
+
) -> List[Dict]:
|
|
27
|
+
projects = get(
|
|
28
|
+
api_session,
|
|
29
|
+
common_job_parameters["BASE_URL"],
|
|
30
|
+
)
|
|
31
|
+
for project in projects:
|
|
32
|
+
project["users"] = []
|
|
33
|
+
for user in get_project_users(
|
|
34
|
+
api_session,
|
|
35
|
+
common_job_parameters["BASE_URL"],
|
|
36
|
+
project["id"],
|
|
37
|
+
):
|
|
38
|
+
project["users"].append(user["id"])
|
|
39
|
+
load_projects(neo4j_session, projects, ORG_ID, common_job_parameters["UPDATE_TAG"])
|
|
40
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
41
|
+
return projects
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@timeit
|
|
45
|
+
def get(
|
|
46
|
+
api_session: requests.Session,
|
|
47
|
+
base_url: str,
|
|
48
|
+
) -> List[Dict[str, Any]]:
|
|
49
|
+
return list(
|
|
50
|
+
paginated_get(
|
|
51
|
+
api_session, f"{base_url}/organization/projects", timeout=_TIMEOUT
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@timeit
|
|
57
|
+
def get_project_users(
|
|
58
|
+
api_session: requests.Session,
|
|
59
|
+
base_url: str,
|
|
60
|
+
project_id: str,
|
|
61
|
+
) -> List[Dict[str, Any]]:
|
|
62
|
+
return list(
|
|
63
|
+
paginated_get(
|
|
64
|
+
api_session,
|
|
65
|
+
f"{base_url}/organization/projects/{project_id}/users",
|
|
66
|
+
timeout=_TIMEOUT,
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@timeit
|
|
72
|
+
def load_projects(
|
|
73
|
+
neo4j_session: neo4j.Session,
|
|
74
|
+
data: List[Dict[str, Any]],
|
|
75
|
+
ORG_ID: str,
|
|
76
|
+
update_tag: int,
|
|
77
|
+
) -> None:
|
|
78
|
+
logger.info("Loading %d OpenAIProjectSchema into Neo4j.", len(data))
|
|
79
|
+
load(
|
|
80
|
+
neo4j_session,
|
|
81
|
+
OpenAIProjectSchema(),
|
|
82
|
+
data,
|
|
83
|
+
lastupdated=update_tag,
|
|
84
|
+
ORG_ID=ORG_ID,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@timeit
|
|
89
|
+
def cleanup(
|
|
90
|
+
neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
|
|
91
|
+
) -> None:
|
|
92
|
+
GraphJob.from_node_schema(OpenAIProjectSchema(), common_job_parameters).run(
|
|
93
|
+
neo4j_session
|
|
94
|
+
)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
import neo4j
|
|
7
|
+
import requests
|
|
8
|
+
|
|
9
|
+
from cartography.client.core.tx import load
|
|
10
|
+
from cartography.graph.job import GraphJob
|
|
11
|
+
from cartography.intel.openai.util import paginated_get
|
|
12
|
+
from cartography.models.openai.serviceaccount import OpenAIServiceAccountSchema
|
|
13
|
+
from cartography.util import timeit
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
# Connect and read timeouts of 60 seconds each; see https://requests.readthedocs.io/en/master/user/advanced/#timeouts
|
|
17
|
+
_TIMEOUT = (60, 60)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@timeit
|
|
21
|
+
def sync(
|
|
22
|
+
neo4j_session: neo4j.Session,
|
|
23
|
+
api_session: requests.Session,
|
|
24
|
+
common_job_parameters: Dict[str, Any],
|
|
25
|
+
project_id: str,
|
|
26
|
+
) -> None:
|
|
27
|
+
serviceaccountss = get(
|
|
28
|
+
api_session,
|
|
29
|
+
common_job_parameters["BASE_URL"],
|
|
30
|
+
project_id,
|
|
31
|
+
)
|
|
32
|
+
load_serviceaccounts(
|
|
33
|
+
neo4j_session,
|
|
34
|
+
serviceaccountss,
|
|
35
|
+
project_id,
|
|
36
|
+
common_job_parameters["UPDATE_TAG"],
|
|
37
|
+
)
|
|
38
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@timeit
|
|
42
|
+
def get(
|
|
43
|
+
api_session: requests.Session,
|
|
44
|
+
base_url: str,
|
|
45
|
+
project_id: str,
|
|
46
|
+
) -> List[Dict[str, Any]]:
|
|
47
|
+
return list(
|
|
48
|
+
paginated_get(
|
|
49
|
+
api_session,
|
|
50
|
+
"{base_url}/organization/projects/{project_id}/service_accounts".format(
|
|
51
|
+
base_url=base_url,
|
|
52
|
+
project_id=project_id,
|
|
53
|
+
),
|
|
54
|
+
timeout=_TIMEOUT,
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@timeit
|
|
60
|
+
def load_serviceaccounts(
|
|
61
|
+
neo4j_session: neo4j.Session,
|
|
62
|
+
data: List[Dict[str, Any]],
|
|
63
|
+
project_id: str,
|
|
64
|
+
update_tag: int,
|
|
65
|
+
) -> None:
|
|
66
|
+
logger.info("Loading %d OpenAI ProjectServiceAccount into Neo4j.", len(data))
|
|
67
|
+
load(
|
|
68
|
+
neo4j_session,
|
|
69
|
+
OpenAIServiceAccountSchema(),
|
|
70
|
+
data,
|
|
71
|
+
lastupdated=update_tag,
|
|
72
|
+
project_id=project_id,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@timeit
|
|
77
|
+
def cleanup(
|
|
78
|
+
neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
|
|
79
|
+
) -> None:
|
|
80
|
+
GraphJob.from_node_schema(OpenAIServiceAccountSchema(), common_job_parameters).run(
|
|
81
|
+
neo4j_session
|
|
82
|
+
)
|
|
@@ -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
|
+
import requests
|
|
8
|
+
|
|
9
|
+
from cartography.client.core.tx import load
|
|
10
|
+
from cartography.graph.job import GraphJob
|
|
11
|
+
from cartography.intel.openai.util import paginated_get
|
|
12
|
+
from cartography.models.openai.organization import OpenAIOrganizationSchema
|
|
13
|
+
from cartography.models.openai.user import OpenAIUserSchema
|
|
14
|
+
from cartography.util import timeit
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
# Connect and read timeouts of 60 seconds each; see https://requests.readthedocs.io/en/master/user/advanced/#timeouts
|
|
18
|
+
_TIMEOUT = (60, 60)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@timeit
|
|
22
|
+
def sync(
|
|
23
|
+
neo4j_session: neo4j.Session,
|
|
24
|
+
api_session: requests.Session,
|
|
25
|
+
common_job_parameters: Dict[str, Any],
|
|
26
|
+
ORG_ID: str,
|
|
27
|
+
) -> None:
|
|
28
|
+
users = get(
|
|
29
|
+
api_session,
|
|
30
|
+
common_job_parameters["BASE_URL"],
|
|
31
|
+
)
|
|
32
|
+
load_users(neo4j_session, users, ORG_ID, common_job_parameters["UPDATE_TAG"])
|
|
33
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@timeit
|
|
37
|
+
def get(
|
|
38
|
+
api_session: requests.Session,
|
|
39
|
+
base_url: str,
|
|
40
|
+
) -> List[Dict[str, Any]]:
|
|
41
|
+
return list(
|
|
42
|
+
paginated_get(api_session, f"{base_url}/organization/users", timeout=_TIMEOUT)
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@timeit
|
|
47
|
+
def load_users(
|
|
48
|
+
neo4j_session: neo4j.Session,
|
|
49
|
+
data: List[Dict[str, Any]],
|
|
50
|
+
ORG_ID: str,
|
|
51
|
+
update_tag: int,
|
|
52
|
+
) -> None:
|
|
53
|
+
load(
|
|
54
|
+
neo4j_session,
|
|
55
|
+
OpenAIOrganizationSchema(),
|
|
56
|
+
[{"id": ORG_ID}],
|
|
57
|
+
lastupdated=update_tag,
|
|
58
|
+
)
|
|
59
|
+
logger.info("Loading %d OpenAI User into Neo4j.", len(data))
|
|
60
|
+
load(
|
|
61
|
+
neo4j_session,
|
|
62
|
+
OpenAIUserSchema(),
|
|
63
|
+
data,
|
|
64
|
+
lastupdated=update_tag,
|
|
65
|
+
ORG_ID=ORG_ID,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@timeit
|
|
70
|
+
def cleanup(
|
|
71
|
+
neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]
|
|
72
|
+
) -> None:
|
|
73
|
+
GraphJob.from_node_schema(OpenAIOrganizationSchema(), common_job_parameters).run(
|
|
74
|
+
neo4j_session
|
|
75
|
+
)
|
|
76
|
+
GraphJob.from_node_schema(OpenAIUserSchema(), common_job_parameters).run(
|
|
77
|
+
neo4j_session
|
|
78
|
+
)
|