cartography 0.93.0rc1__py3-none-any.whl → 0.123.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.
- cartography/__main__.py +1 -2
- cartography/_version.py +34 -0
- cartography/cli.py +903 -225
- cartography/client/aws/__init__.py +19 -0
- cartography/client/aws/ecr.py +51 -0
- cartography/client/core/tx.py +400 -27
- cartography/config.py +215 -10
- cartography/data/azure_permission_relationships.yaml +20 -0
- cartography/data/gcp_permission_relationships.yaml +21 -0
- cartography/data/indexes.cypher +1 -200
- cartography/data/jobs/analysis/aws_ec2_asset_exposure.json +17 -2
- cartography/data/jobs/analysis/aws_ec2_keypair_analysis.json +2 -2
- cartography/data/jobs/analysis/gcp_compute_asset_inet_exposure.json +1 -1
- cartography/data/jobs/analysis/keycloak_inheritance.json +30 -0
- cartography/data/jobs/cleanup/crowdstrike_import_cleanup.json +0 -5
- cartography/data/jobs/cleanup/gcp_compute_vpc_cleanup.json +0 -12
- cartography/data/jobs/cleanup/github_repos_cleanup.json +27 -0
- cartography/data/jobs/scoped_analysis/aws_ec2_iaminstanceprofile.json +15 -0
- cartography/data/jobs/scoped_analysis/semgrep_sca_risk_analysis.json +13 -13
- cartography/driftdetect/__main__.py +1 -2
- cartography/driftdetect/add_shortcut.py +10 -2
- cartography/driftdetect/cli.py +72 -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 +255 -35
- cartography/graph/job.py +104 -20
- cartography/graph/querybuilder.py +689 -91
- cartography/graph/statement.py +49 -36
- 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/analysis.py +4 -1
- cartography/intel/anthropic/__init__.py +62 -0
- cartography/intel/anthropic/apikeys.py +72 -0
- cartography/intel/anthropic/users.py +75 -0
- cartography/intel/anthropic/util.py +51 -0
- cartography/intel/anthropic/workspaces.py +95 -0
- cartography/intel/aws/__init__.py +137 -59
- cartography/intel/aws/acm.py +124 -0
- cartography/intel/aws/apigateway.py +482 -217
- cartography/intel/aws/apigatewayv2.py +116 -0
- cartography/intel/aws/cloudtrail.py +105 -0
- cartography/intel/aws/cloudtrail_management_events.py +962 -0
- cartography/intel/aws/cloudwatch.py +239 -0
- cartography/intel/aws/codebuild.py +132 -0
- cartography/intel/aws/cognito.py +201 -0
- cartography/intel/aws/config.py +63 -23
- cartography/intel/aws/dynamodb.py +108 -40
- cartography/intel/aws/ec2/__init__.py +2 -2
- cartography/intel/aws/ec2/auto_scaling_groups.py +254 -189
- cartography/intel/aws/ec2/elastic_ip_addresses.py +44 -14
- cartography/intel/aws/ec2/images.py +74 -39
- cartography/intel/aws/ec2/instances.py +262 -137
- cartography/intel/aws/ec2/internet_gateways.py +44 -13
- cartography/intel/aws/ec2/key_pairs.py +72 -39
- cartography/intel/aws/ec2/launch_templates.py +143 -66
- cartography/intel/aws/ec2/load_balancer_v2s.py +119 -45
- cartography/intel/aws/ec2/load_balancers.py +165 -147
- cartography/intel/aws/ec2/network_acls.py +233 -0
- cartography/intel/aws/ec2/network_interfaces.py +150 -87
- cartography/intel/aws/ec2/reserved_instances.py +48 -17
- cartography/intel/aws/ec2/route_tables.py +327 -0
- cartography/intel/aws/ec2/security_groups.py +189 -121
- cartography/intel/aws/ec2/snapshots.py +93 -91
- cartography/intel/aws/ec2/subnets.py +70 -58
- cartography/intel/aws/ec2/tgw.py +111 -39
- cartography/intel/aws/ec2/util.py +1 -1
- cartography/intel/aws/ec2/volumes.py +69 -41
- cartography/intel/aws/ec2/vpc.py +157 -116
- cartography/intel/aws/ec2/vpc_peerings.py +317 -121
- cartography/intel/aws/ecr.py +336 -93
- cartography/intel/aws/ecr_image_layers.py +923 -0
- cartography/intel/aws/ecs.py +310 -403
- cartography/intel/aws/efs.py +261 -0
- cartography/intel/aws/eks.py +55 -29
- cartography/intel/aws/elasticache.py +130 -83
- cartography/intel/aws/elasticsearch.py +70 -24
- cartography/intel/aws/emr.py +61 -23
- cartography/intel/aws/eventbridge.py +164 -0
- cartography/intel/aws/glue.py +181 -0
- cartography/intel/aws/guardduty.py +443 -0
- cartography/intel/aws/iam.py +978 -464
- cartography/intel/aws/iam_instance_profiles.py +73 -0
- cartography/intel/aws/identitycenter.py +847 -0
- cartography/intel/aws/inspector.py +330 -133
- cartography/intel/aws/kms.py +235 -209
- cartography/intel/aws/lambda_function.py +328 -176
- cartography/intel/aws/organizations.py +40 -19
- cartography/intel/aws/permission_relationships.py +144 -68
- cartography/intel/aws/rds.py +467 -412
- cartography/intel/aws/redshift.py +116 -50
- cartography/intel/aws/resourcegroupstaggingapi.py +198 -82
- cartography/intel/aws/resources.py +80 -42
- cartography/intel/aws/route53.py +419 -318
- cartography/intel/aws/s3.py +489 -96
- cartography/intel/aws/s3accountpublicaccessblock.py +157 -0
- cartography/intel/aws/secretsmanager.py +217 -40
- cartography/intel/aws/securityhub.py +23 -10
- cartography/intel/aws/sns.py +226 -0
- cartography/intel/aws/sqs.py +74 -96
- cartography/intel/aws/ssm.py +142 -33
- cartography/intel/aws/util/arns.py +7 -7
- cartography/intel/aws/util/common.py +31 -4
- cartography/intel/azure/__init__.py +259 -46
- cartography/intel/azure/aks.py +175 -0
- cartography/intel/azure/app_service.py +105 -0
- cartography/intel/azure/compute.py +141 -120
- cartography/intel/azure/container_instances.py +95 -0
- cartography/intel/azure/cosmosdb.py +706 -519
- cartography/intel/azure/data_factory.py +85 -0
- cartography/intel/azure/data_factory_dataset.py +128 -0
- cartography/intel/azure/data_factory_linked_service.py +119 -0
- cartography/intel/azure/data_factory_pipeline.py +142 -0
- cartography/intel/azure/data_lake.py +124 -0
- cartography/intel/azure/event_grid.py +94 -0
- cartography/intel/azure/functions.py +124 -0
- cartography/intel/azure/load_balancers.py +263 -0
- cartography/intel/azure/logic_apps.py +101 -0
- cartography/intel/azure/monitor.py +105 -0
- cartography/intel/azure/network.py +467 -0
- cartography/intel/azure/permission_relationships.py +466 -0
- cartography/intel/azure/rbac.py +309 -0
- cartography/intel/azure/resource_groups.py +82 -0
- cartography/intel/azure/security_center.py +106 -0
- cartography/intel/azure/sql.py +436 -392
- cartography/intel/azure/storage.py +467 -335
- cartography/intel/azure/subscription.py +49 -55
- cartography/intel/azure/tenant.py +46 -28
- cartography/intel/azure/util/common.py +13 -0
- cartography/intel/azure/util/credentials.py +58 -143
- cartography/intel/azure/util/tag.py +41 -0
- 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 +5 -3
- cartography/intel/crowdstrike/__init__.py +26 -12
- cartography/intel/crowdstrike/endpoints.py +17 -45
- cartography/intel/crowdstrike/spotlight.py +13 -5
- cartography/intel/cve/__init__.py +91 -26
- cartography/intel/cve/feed.py +77 -56
- 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 +41 -12
- 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 +160 -0
- cartography/intel/entra/app_role_assignments.py +284 -0
- cartography/intel/entra/applications.py +182 -0
- cartography/intel/entra/federation/__init__.py +0 -0
- cartography/intel/entra/federation/aws_identity_center.py +77 -0
- cartography/intel/entra/groups.py +198 -0
- cartography/intel/entra/ou.py +136 -0
- cartography/intel/entra/service_principals.py +217 -0
- cartography/intel/entra/users.py +259 -0
- cartography/intel/gcp/__init__.py +381 -175
- cartography/intel/gcp/bigtable_app_profile.py +101 -0
- cartography/intel/gcp/bigtable_backup.py +91 -0
- cartography/intel/gcp/bigtable_cluster.py +93 -0
- cartography/intel/gcp/bigtable_instance.py +86 -0
- cartography/intel/gcp/bigtable_table.py +87 -0
- cartography/intel/gcp/cai.py +292 -0
- cartography/intel/gcp/clients.py +112 -0
- cartography/intel/gcp/compute.py +521 -325
- cartography/intel/gcp/crm/__init__.py +0 -0
- cartography/intel/gcp/crm/folders.py +114 -0
- cartography/intel/gcp/crm/orgs.py +70 -0
- cartography/intel/gcp/crm/projects.py +120 -0
- cartography/intel/gcp/dns.py +134 -179
- cartography/intel/gcp/gke.py +100 -107
- cartography/intel/gcp/iam.py +262 -0
- cartography/intel/gcp/permission_relationships.py +394 -0
- cartography/intel/gcp/policy_bindings.py +225 -0
- cartography/intel/gcp/storage.py +103 -158
- cartography/intel/github/__init__.py +66 -27
- cartography/intel/github/commits.py +423 -0
- cartography/intel/github/repos.py +871 -160
- cartography/intel/github/teams.py +386 -53
- cartography/intel/github/users.py +214 -49
- cartography/intel/github/util.py +50 -35
- cartography/intel/googleworkspace/__init__.py +193 -0
- cartography/intel/googleworkspace/devices.py +254 -0
- cartography/intel/googleworkspace/groups.py +568 -0
- cartography/intel/googleworkspace/oauth_apps.py +259 -0
- cartography/intel/googleworkspace/tenant.py +85 -0
- cartography/intel/googleworkspace/users.py +138 -0
- cartography/intel/gsuite/__init__.py +101 -42
- cartography/intel/gsuite/groups.py +291 -0
- cartography/intel/gsuite/users.py +142 -0
- cartography/intel/jamf/__init__.py +19 -1
- cartography/intel/jamf/computers.py +37 -8
- cartography/intel/jamf/util.py +7 -2
- cartography/intel/kandji/__init__.py +6 -3
- cartography/intel/kandji/devices.py +40 -10
- cartography/intel/keycloak/__init__.py +153 -0
- cartography/intel/keycloak/authenticationexecutions.py +322 -0
- cartography/intel/keycloak/authenticationflows.py +77 -0
- cartography/intel/keycloak/clients.py +187 -0
- cartography/intel/keycloak/groups.py +126 -0
- cartography/intel/keycloak/identityproviders.py +94 -0
- cartography/intel/keycloak/organizations.py +163 -0
- cartography/intel/keycloak/realms.py +61 -0
- cartography/intel/keycloak/roles.py +202 -0
- cartography/intel/keycloak/scopes.py +73 -0
- cartography/intel/keycloak/users.py +70 -0
- cartography/intel/keycloak/util.py +47 -0
- cartography/intel/kubernetes/__init__.py +60 -14
- cartography/intel/kubernetes/clusters.py +86 -0
- cartography/intel/kubernetes/eks.py +402 -0
- cartography/intel/kubernetes/namespaces.py +60 -55
- cartography/intel/kubernetes/pods.py +171 -75
- cartography/intel/kubernetes/rbac.py +597 -0
- cartography/intel/kubernetes/secrets.py +95 -45
- cartography/intel/kubernetes/services.py +131 -63
- cartography/intel/kubernetes/util.py +142 -14
- 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 +157 -47
- cartography/intel/oci/organizations.py +16 -7
- cartography/intel/oci/utils.py +71 -25
- cartography/intel/okta/__init__.py +66 -15
- cartography/intel/okta/applications.py +57 -25
- cartography/intel/okta/awssaml.py +105 -41
- cartography/intel/okta/factors.py +19 -5
- cartography/intel/okta/groups.py +61 -31
- cartography/intel/okta/organization.py +8 -2
- cartography/intel/okta/origins.py +9 -3
- cartography/intel/okta/roles.py +20 -7
- cartography/intel/okta/users.py +31 -10
- cartography/intel/okta/utils.py +6 -4
- cartography/intel/ontology/__init__.py +44 -0
- cartography/intel/ontology/devices.py +54 -0
- cartography/intel/ontology/users.py +54 -0
- cartography/intel/ontology/utils.py +176 -0
- cartography/intel/openai/__init__.py +86 -0
- cartography/intel/openai/adminapikeys.py +89 -0
- cartography/intel/openai/apikeys.py +96 -0
- cartography/intel/openai/projects.py +97 -0
- cartography/intel/openai/serviceaccounts.py +82 -0
- cartography/intel/openai/users.py +75 -0
- cartography/intel/openai/util.py +45 -0
- cartography/intel/pagerduty/__init__.py +8 -7
- cartography/intel/pagerduty/escalation_policies.py +31 -12
- cartography/intel/pagerduty/schedules.py +21 -8
- cartography/intel/pagerduty/services.py +18 -7
- cartography/intel/pagerduty/teams.py +13 -5
- cartography/intel/pagerduty/users.py +6 -2
- cartography/intel/pagerduty/vendors.py +6 -2
- 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/semgrep/__init__.py +30 -5
- cartography/intel/semgrep/dependencies.py +255 -0
- cartography/intel/semgrep/deployment.py +69 -0
- cartography/intel/semgrep/findings.py +157 -117
- cartography/intel/sentinelone/__init__.py +75 -0
- cartography/intel/sentinelone/account.py +140 -0
- cartography/intel/sentinelone/agent.py +139 -0
- cartography/intel/sentinelone/api.py +124 -0
- cartography/intel/sentinelone/application.py +248 -0
- cartography/intel/sentinelone/cve.py +119 -0
- cartography/intel/sentinelone/utils.py +28 -0
- cartography/intel/slack/__init__.py +78 -0
- cartography/intel/slack/channels.py +80 -0
- cartography/intel/slack/groups.py +90 -0
- cartography/intel/slack/teams.py +65 -0
- cartography/intel/slack/users.py +57 -0
- cartography/intel/slack/utils.py +29 -0
- cartography/intel/snipeit/__init__.py +44 -0
- cartography/intel/snipeit/asset.py +80 -0
- cartography/intel/snipeit/user.py +78 -0
- cartography/intel/snipeit/util.py +40 -0
- cartography/intel/spacelift/__init__.py +161 -0
- cartography/intel/spacelift/account.py +73 -0
- cartography/intel/spacelift/ec2_ownership.py +280 -0
- cartography/intel/spacelift/runs.py +463 -0
- cartography/intel/spacelift/spaces.py +112 -0
- cartography/intel/spacelift/stacks.py +119 -0
- cartography/intel/spacelift/util.py +122 -0
- cartography/intel/spacelift/workerpools.py +131 -0
- cartography/intel/spacelift/workers.py +128 -0
- 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/intel/trivy/__init__.py +272 -0
- cartography/intel/trivy/scanner.py +386 -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 +115 -0
- cartography/models/airbyte/workspace.py +46 -0
- cartography/models/anthropic/__init__.py +0 -0
- cartography/models/anthropic/apikey.py +94 -0
- cartography/models/anthropic/organization.py +19 -0
- cartography/models/anthropic/user.py +52 -0
- cartography/models/anthropic/workspace.py +90 -0
- cartography/models/aws/acm/__init__.py +0 -0
- cartography/models/aws/acm/certificate.py +75 -0
- cartography/models/aws/apigateway/__init__.py +0 -0
- cartography/models/aws/apigateway/apigateway.py +51 -0
- cartography/models/aws/apigateway/apigatewaycertificate.py +72 -0
- cartography/models/aws/apigateway/apigatewaydeployment.py +74 -0
- cartography/models/aws/apigateway/apigatewayintegration.py +79 -0
- cartography/models/aws/apigateway/apigatewaymethod.py +74 -0
- cartography/models/aws/apigateway/apigatewayresource.py +70 -0
- cartography/models/aws/apigateway/apigatewaystage.py +75 -0
- cartography/models/aws/apigatewayv2/__init__.py +0 -0
- cartography/models/aws/apigatewayv2/apigatewayv2.py +53 -0
- cartography/models/aws/cloudtrail/__init__.py +0 -0
- cartography/models/aws/cloudtrail/management_events.py +153 -0
- cartography/models/aws/cloudtrail/trail.py +106 -0
- cartography/models/aws/cloudwatch/__init__.py +0 -0
- cartography/models/aws/cloudwatch/log_metric_filter.py +79 -0
- cartography/models/aws/cloudwatch/loggroup.py +52 -0
- cartography/models/aws/cloudwatch/metric_alarm.py +53 -0
- cartography/models/aws/codebuild/__init__.py +0 -0
- cartography/models/aws/codebuild/project.py +49 -0
- cartography/models/aws/cognito/__init__.py +0 -0
- cartography/models/aws/cognito/identity_pool.py +70 -0
- cartography/models/aws/cognito/user_pool.py +47 -0
- cartography/models/aws/dynamodb/gsi.py +30 -22
- cartography/models/aws/dynamodb/tables.py +27 -17
- cartography/models/aws/ec2/auto_scaling_groups.py +224 -0
- cartography/models/aws/ec2/images.py +36 -34
- cartography/models/aws/ec2/instances.py +85 -38
- cartography/models/aws/ec2/keypair.py +59 -0
- cartography/models/aws/ec2/keypair_instance.py +76 -0
- cartography/models/aws/ec2/launch_configurations.py +59 -0
- 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 +72 -0
- cartography/models/aws/ec2/load_balancers.py +112 -0
- cartography/models/aws/ec2/network_acl_rules.py +106 -0
- cartography/models/aws/ec2/network_acls.py +95 -0
- cartography/models/aws/ec2/networkinterface_instance.py +52 -39
- cartography/models/aws/ec2/networkinterfaces.py +57 -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 +97 -0
- cartography/models/aws/ec2/route_tables.py +128 -0
- cartography/models/aws/ec2/routes.py +85 -0
- cartography/models/aws/ec2/security_group_rules.py +109 -0
- cartography/models/aws/ec2/security_groups.py +90 -0
- cartography/models/aws/ec2/securitygroup_instance.py +29 -20
- cartography/models/aws/ec2/securitygroup_networkinterface.py +24 -15
- cartography/models/aws/ec2/snapshots.py +58 -0
- cartography/models/aws/ec2/subnet_instance.py +26 -19
- cartography/models/aws/ec2/subnet_networkinterface.py +42 -31
- cartography/models/aws/ec2/subnets.py +65 -0
- cartography/models/aws/ec2/volumes.py +67 -40
- cartography/models/aws/ec2/vpc.py +46 -0
- cartography/models/aws/ec2/vpc_cidr.py +102 -0
- cartography/models/aws/ec2/vpc_peering.py +157 -0
- cartography/models/aws/ecr/__init__.py +0 -0
- cartography/models/aws/ecr/image.py +146 -0
- cartography/models/aws/ecr/image_layer.py +107 -0
- cartography/models/aws/ecr/repository.py +72 -0
- cartography/models/aws/ecr/repository_image.py +95 -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 +101 -0
- cartography/models/aws/ecs/services.py +134 -0
- cartography/models/aws/ecs/task_definitions.py +135 -0
- cartography/models/aws/ecs/tasks.py +134 -0
- cartography/models/aws/efs/__init__.py +0 -0
- cartography/models/aws/efs/access_point.py +77 -0
- cartography/models/aws/efs/file_system.py +60 -0
- cartography/models/aws/efs/mount_target.py +79 -0
- cartography/models/aws/eks/clusters.py +23 -21
- 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/emr.py +32 -30
- cartography/models/aws/eventbridge/__init__.py +0 -0
- cartography/models/aws/eventbridge/rule.py +77 -0
- cartography/models/aws/eventbridge/target.py +71 -0
- cartography/models/aws/glue/__init__.py +0 -0
- cartography/models/aws/glue/connection.py +51 -0
- cartography/models/aws/glue/job.py +69 -0
- cartography/models/aws/guardduty/__init__.py +1 -0
- cartography/models/aws/guardduty/detectors.py +50 -0
- cartography/models/aws/guardduty/findings.py +121 -0
- cartography/models/aws/iam/__init__.py +0 -0
- 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 +27 -0
- cartography/models/aws/iam/inline_policy.py +78 -0
- cartography/models/aws/iam/instanceprofile.py +76 -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 +59 -0
- cartography/models/aws/identitycenter/__init__.py +0 -0
- cartography/models/aws/identitycenter/awsidentitycenter.py +49 -0
- cartography/models/aws/identitycenter/awspermissionset.py +162 -0
- cartography/models/aws/identitycenter/awssogroup.py +70 -0
- cartography/models/aws/identitycenter/awsssouser.py +110 -0
- cartography/models/aws/inspector/findings.py +124 -58
- cartography/models/aws/inspector/packages.py +18 -42
- cartography/models/aws/kms/__init__.py +0 -0
- cartography/models/aws/kms/aliases.py +86 -0
- cartography/models/aws/kms/grants.py +65 -0
- cartography/models/aws/kms/keys.py +88 -0
- cartography/models/aws/lambda_function/__init__.py +0 -0
- cartography/models/aws/lambda_function/alias.py +74 -0
- cartography/models/aws/lambda_function/event_source_mapping.py +88 -0
- cartography/models/aws/lambda_function/lambda_function.py +91 -0
- cartography/models/aws/lambda_function/layer.py +72 -0
- cartography/models/aws/rds/__init__.py +0 -0
- cartography/models/aws/rds/cluster.py +91 -0
- cartography/models/aws/rds/event_subscription.py +146 -0
- cartography/models/aws/rds/instance.py +156 -0
- cartography/models/aws/rds/snapshot.py +108 -0
- cartography/models/aws/rds/subnet_group.py +101 -0
- cartography/models/aws/route53/__init__.py +0 -0
- cartography/models/aws/route53/dnsrecord.py +235 -0
- cartography/models/aws/route53/nameserver.py +63 -0
- cartography/models/aws/route53/subzone.py +40 -0
- cartography/models/aws/route53/zone.py +47 -0
- cartography/models/aws/s3/__init__.py +0 -0
- cartography/models/aws/s3/account_public_access_block.py +51 -0
- cartography/models/aws/s3/notification.py +24 -0
- cartography/models/aws/secretsmanager/__init__.py +0 -0
- cartography/models/aws/secretsmanager/secret.py +106 -0
- cartography/models/aws/secretsmanager/secret_version.py +114 -0
- cartography/models/aws/sns/__init__.py +0 -0
- cartography/models/aws/sns/topic.py +50 -0
- cartography/models/aws/sns/topic_subscription.py +74 -0
- cartography/models/aws/sqs/__init__.py +0 -0
- cartography/models/aws/sqs/queue.py +89 -0
- cartography/models/aws/ssm/instance_information.py +51 -39
- cartography/models/aws/ssm/instance_patch.py +32 -26
- cartography/models/aws/ssm/parameters.py +84 -0
- cartography/models/azure/__init__.py +0 -0
- cartography/models/azure/aks_cluster.py +54 -0
- cartography/models/azure/aks_nodepool.py +54 -0
- cartography/models/azure/app_service.py +59 -0
- cartography/models/azure/container_instance.py +57 -0
- cartography/models/azure/cosmosdb/__init__.py +0 -0
- cartography/models/azure/cosmosdb/account.py +77 -0
- cartography/models/azure/cosmosdb/accountfailoverpolicy.py +77 -0
- cartography/models/azure/cosmosdb/cassandrakeyspace.py +82 -0
- cartography/models/azure/cosmosdb/cassandratable.py +81 -0
- cartography/models/azure/cosmosdb/corspolicy.py +74 -0
- cartography/models/azure/cosmosdb/dblocation.py +120 -0
- cartography/models/azure/cosmosdb/mongodbcollection.py +82 -0
- cartography/models/azure/cosmosdb/mongodbdatabase.py +78 -0
- cartography/models/azure/cosmosdb/privateendpointconnection.py +81 -0
- cartography/models/azure/cosmosdb/sqlcontainer.py +88 -0
- cartography/models/azure/cosmosdb/sqldatabase.py +78 -0
- cartography/models/azure/cosmosdb/tableresource.py +76 -0
- cartography/models/azure/cosmosdb/virtualnetworkrule.py +78 -0
- cartography/models/azure/data_factory/__init__.py +0 -0
- cartography/models/azure/data_factory/data_factory.py +51 -0
- cartography/models/azure/data_factory/data_factory_dataset.py +94 -0
- cartography/models/azure/data_factory/data_factory_linked_service.py +78 -0
- cartography/models/azure/data_factory/data_factory_pipeline.py +93 -0
- cartography/models/azure/data_lake_filesystem.py +51 -0
- cartography/models/azure/event_grid_topic.py +57 -0
- cartography/models/azure/function_app.py +59 -0
- cartography/models/azure/load_balancer/__init__.py +0 -0
- cartography/models/azure/load_balancer/load_balancer.py +49 -0
- cartography/models/azure/load_balancer/load_balancer_backend_pool.py +73 -0
- cartography/models/azure/load_balancer/load_balancer_frontend_ip.py +75 -0
- cartography/models/azure/load_balancer/load_balancer_inbound_nat_rule.py +78 -0
- cartography/models/azure/load_balancer/load_balancer_rule.py +108 -0
- cartography/models/azure/logic_apps.py +56 -0
- cartography/models/azure/monitor.py +54 -0
- cartography/models/azure/network_interface.py +112 -0
- cartography/models/azure/network_security_group.py +50 -0
- cartography/models/azure/permission_relationships.py +60 -0
- cartography/models/azure/principal.py +41 -0
- cartography/models/azure/public_ip_address.py +50 -0
- cartography/models/azure/rbac.py +268 -0
- cartography/models/azure/resource_groups.py +52 -0
- cartography/models/azure/security_center.py +50 -0
- cartography/models/azure/sql/__init__.py +0 -0
- cartography/models/azure/sql/databasethreatdetectionpolicy.py +85 -0
- cartography/models/azure/sql/elasticpool.py +77 -0
- cartography/models/azure/sql/failovergroup.py +73 -0
- cartography/models/azure/sql/recoverabledatabase.py +75 -0
- cartography/models/azure/sql/replicationlink.py +81 -0
- cartography/models/azure/sql/restorabledroppeddatabase.py +82 -0
- cartography/models/azure/sql/restorepoint.py +74 -0
- cartography/models/azure/sql/serveradadministrator.py +74 -0
- cartography/models/azure/sql/serverdnsalias.py +71 -0
- cartography/models/azure/sql/sqldatabase.py +85 -0
- cartography/models/azure/sql/sqlserver.py +50 -0
- cartography/models/azure/sql/transparentdataencryption.py +76 -0
- cartography/models/azure/storage/__init__.py +0 -0
- cartography/models/azure/storage/account.py +59 -0
- cartography/models/azure/storage/blobcontainer.py +85 -0
- cartography/models/azure/storage/blobservice.py +71 -0
- cartography/models/azure/storage/fileservice.py +71 -0
- cartography/models/azure/storage/fileshare.py +82 -0
- cartography/models/azure/storage/queue.py +71 -0
- cartography/models/azure/storage/queueservice.py +73 -0
- cartography/models/azure/storage/table.py +72 -0
- cartography/models/azure/storage/tableservice.py +73 -0
- cartography/models/azure/subnet.py +101 -0
- cartography/models/azure/subscription.py +47 -0
- cartography/models/azure/tags/__init__.py +0 -0
- cartography/models/azure/tags/storage_tag.py +40 -0
- cartography/models/azure/tags/tag.py +37 -0
- cartography/models/azure/tenant.py +17 -0
- cartography/models/azure/virtual_network.py +49 -0
- cartography/models/azure/vm/__init__.py +0 -0
- cartography/models/azure/vm/datadisk.py +80 -0
- cartography/models/azure/vm/disk.py +55 -0
- cartography/models/azure/vm/snapshot.py +56 -0
- cartography/models/azure/vm/virtualmachine.py +59 -0
- 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 +86 -0
- cartography/models/cloudflare/role.py +44 -0
- cartography/models/cloudflare/zone.py +59 -0
- cartography/models/core/common.py +53 -2
- cartography/models/core/nodes.py +20 -4
- cartography/models/core/relationships.py +58 -6
- cartography/models/crowdstrike/__init__.py +0 -0
- cartography/models/crowdstrike/hosts.py +51 -0
- 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 +58 -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 +50 -44
- cartography/models/duo/web_authn_credential.py +27 -19
- cartography/models/entra/__init__.py +0 -0
- cartography/models/entra/app_role_assignment.py +115 -0
- cartography/models/entra/application.py +49 -0
- cartography/models/entra/entra_user_to_aws_sso.py +41 -0
- cartography/models/entra/group.py +117 -0
- cartography/models/entra/ou.py +48 -0
- cartography/models/entra/service_principal.py +104 -0
- cartography/models/entra/tenant.py +39 -0
- cartography/models/entra/user.py +90 -0
- cartography/models/gcp/__init__.py +0 -0
- cartography/models/gcp/bigtable/__init__.py +0 -0
- cartography/models/gcp/bigtable/app_profile.py +94 -0
- cartography/models/gcp/bigtable/backup.py +91 -0
- cartography/models/gcp/bigtable/cluster.py +73 -0
- cartography/models/gcp/bigtable/instance.py +52 -0
- cartography/models/gcp/bigtable/table.py +69 -0
- cartography/models/gcp/compute/__init__.py +0 -0
- cartography/models/gcp/compute/subnet.py +74 -0
- cartography/models/gcp/compute/vpc.py +50 -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/dns.py +109 -0
- cartography/models/gcp/gke.py +69 -0
- cartography/models/gcp/iam.py +73 -0
- cartography/models/gcp/permission_relationships.py +61 -0
- cartography/models/gcp/policy_bindings.py +93 -0
- cartography/models/gcp/storage/__init__.py +0 -0
- cartography/models/gcp/storage/bucket.py +119 -0
- cartography/models/github/commits.py +63 -0
- cartography/models/github/dependencies.py +73 -0
- cartography/models/github/manifests.py +49 -0
- cartography/models/github/orgs.py +27 -0
- cartography/models/github/teams.py +74 -22
- cartography/models/github/users.py +149 -0
- cartography/models/googleworkspace/__init__.py +0 -0
- cartography/models/googleworkspace/device.py +132 -0
- cartography/models/googleworkspace/group.py +382 -0
- cartography/models/googleworkspace/oauth_app.py +124 -0
- cartography/models/googleworkspace/tenant.py +30 -0
- cartography/models/googleworkspace/user.py +113 -0
- cartography/models/gsuite/__init__.py +0 -0
- cartography/models/gsuite/group.py +218 -0
- cartography/models/gsuite/tenant.py +29 -0
- cartography/models/gsuite/user.py +107 -0
- cartography/models/kandji/device.py +22 -17
- cartography/models/kandji/tenant.py +6 -4
- cartography/models/keycloak/__init__.py +0 -0
- cartography/models/keycloak/authenticationexecution.py +160 -0
- cartography/models/keycloak/authenticationflow.py +54 -0
- cartography/models/keycloak/client.py +179 -0
- cartography/models/keycloak/group.py +101 -0
- cartography/models/keycloak/identityprovider.py +89 -0
- cartography/models/keycloak/organization.py +116 -0
- cartography/models/keycloak/organizationdomain.py +73 -0
- cartography/models/keycloak/realm.py +173 -0
- cartography/models/keycloak/role.py +126 -0
- cartography/models/keycloak/scope.py +73 -0
- cartography/models/keycloak/user.py +55 -0
- cartography/models/kubernetes/__init__.py +0 -0
- cartography/models/kubernetes/clusterrolebindings.py +138 -0
- cartography/models/kubernetes/clusterroles.py +52 -0
- cartography/models/kubernetes/clusters.py +26 -0
- cartography/models/kubernetes/containers.py +133 -0
- cartography/models/kubernetes/groups.py +107 -0
- cartography/models/kubernetes/namespaces.py +51 -0
- cartography/models/kubernetes/oidc.py +51 -0
- cartography/models/kubernetes/pods.py +80 -0
- cartography/models/kubernetes/rolebindings.py +159 -0
- cartography/models/kubernetes/roles.py +76 -0
- cartography/models/kubernetes/secrets.py +79 -0
- cartography/models/kubernetes/serviceaccounts.py +77 -0
- cartography/models/kubernetes/services.py +108 -0
- cartography/models/kubernetes/users.py +105 -0
- cartography/models/lastpass/tenant.py +3 -3
- cartography/models/lastpass/user.py +36 -28
- cartography/models/ontology/__init__.py +0 -0
- cartography/models/ontology/device.py +137 -0
- cartography/models/ontology/mapping/__init__.py +76 -0
- cartography/models/ontology/mapping/data/__init__.py +0 -0
- cartography/models/ontology/mapping/data/apikeys.py +93 -0
- cartography/models/ontology/mapping/data/computeinstance.py +95 -0
- cartography/models/ontology/mapping/data/containers.py +88 -0
- cartography/models/ontology/mapping/data/databases.py +182 -0
- cartography/models/ontology/mapping/data/devices.py +194 -0
- cartography/models/ontology/mapping/data/thirdpartyapps.py +140 -0
- cartography/models/ontology/mapping/data/useraccounts.py +416 -0
- cartography/models/ontology/mapping/data/users.py +63 -0
- cartography/models/ontology/mapping/specs.py +85 -0
- cartography/models/ontology/user.py +51 -0
- cartography/models/openai/__init__.py +0 -0
- cartography/models/openai/adminapikey.py +94 -0
- cartography/models/openai/apikey.py +88 -0
- cartography/models/openai/organization.py +17 -0
- cartography/models/openai/project.py +89 -0
- cartography/models/openai/serviceaccount.py +50 -0
- cartography/models/openai/user.py +53 -0
- cartography/models/scaleway/__init__.py +0 -0
- cartography/models/scaleway/iam/__init__.py +0 -0
- cartography/models/scaleway/iam/apikey.py +100 -0
- cartography/models/scaleway/iam/application.py +52 -0
- cartography/models/scaleway/iam/group.py +95 -0
- cartography/models/scaleway/iam/user.py +64 -0
- cartography/models/scaleway/instance/__init__.py +0 -0
- cartography/models/scaleway/instance/flexibleip.py +52 -0
- cartography/models/scaleway/instance/instance.py +120 -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/semgrep/dependencies.py +102 -0
- cartography/models/semgrep/deployment.py +5 -5
- cartography/models/semgrep/findings.py +58 -40
- cartography/models/semgrep/locations.py +27 -21
- cartography/models/sentinelone/__init__.py +1 -0
- cartography/models/sentinelone/account.py +40 -0
- cartography/models/sentinelone/agent.py +50 -0
- cartography/models/sentinelone/application.py +44 -0
- cartography/models/sentinelone/application_version.py +96 -0
- cartography/models/sentinelone/cve.py +73 -0
- cartography/models/slack/__init__.py +0 -0
- cartography/models/slack/channels.py +92 -0
- cartography/models/slack/group.py +129 -0
- cartography/models/slack/team.py +22 -0
- cartography/models/slack/user.py +62 -0
- cartography/models/snipeit/__init__.py +0 -0
- cartography/models/snipeit/asset.py +92 -0
- cartography/models/snipeit/tenant.py +19 -0
- cartography/models/snipeit/user.py +60 -0
- cartography/models/spacelift/__init__.py +0 -0
- cartography/models/spacelift/cloudtrailevent.py +120 -0
- cartography/models/spacelift/run.py +162 -0
- cartography/models/spacelift/space.py +131 -0
- cartography/models/spacelift/spaceliftaccount.py +31 -0
- cartography/models/spacelift/spaceliftgitcommit.py +157 -0
- cartography/models/spacelift/stack.py +96 -0
- cartography/models/spacelift/user.py +63 -0
- cartography/models/spacelift/worker.py +97 -0
- cartography/models/spacelift/workerpool.py +90 -0
- cartography/models/tailscale/__init__.py +0 -0
- cartography/models/tailscale/device.py +96 -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 +57 -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/rules/README.md +1 -0
- cartography/rules/__init__.py +0 -0
- cartography/rules/cli.py +261 -0
- cartography/rules/data/__init__.py +0 -0
- cartography/rules/data/rules/__init__.py +46 -0
- cartography/rules/data/rules/cloud_security_product_deactivated.py +49 -0
- cartography/rules/data/rules/compute_instance_exposed.py +51 -0
- cartography/rules/data/rules/database_instance_exposed.py +53 -0
- cartography/rules/data/rules/delegation_boundary_modifiable.py +90 -0
- cartography/rules/data/rules/identity_administration_privileges.py +100 -0
- cartography/rules/data/rules/inactive_user_active_accounts.py +48 -0
- cartography/rules/data/rules/malicious_npm_dependencies_shai_hulud.py +2222 -0
- cartography/rules/data/rules/mfa_missing.py +46 -0
- cartography/rules/data/rules/object_storage_public.py +100 -0
- cartography/rules/data/rules/policy_administration_privileges.py +104 -0
- cartography/rules/data/rules/unmanaged_accounts.py +43 -0
- cartography/rules/data/rules/workload_identity_admin_capabilities.py +193 -0
- cartography/rules/formatters.py +108 -0
- cartography/rules/runners.py +216 -0
- cartography/rules/spec/__init__.py +0 -0
- cartography/rules/spec/model.py +267 -0
- cartography/rules/spec/result.py +38 -0
- cartography/stats.py +4 -4
- cartography/sync.py +137 -31
- cartography/util.py +187 -77
- cartography-0.123.0.dist-info/METADATA +230 -0
- cartography-0.123.0.dist-info/RECORD +856 -0
- {cartography-0.93.0rc1.dist-info → cartography-0.123.0.dist-info}/WHEEL +1 -1
- {cartography-0.93.0rc1.dist-info → cartography-0.123.0.dist-info}/entry_points.txt +1 -0
- {cartography-0.93.0rc1.dist-info → cartography-0.123.0.dist-info/licenses}/LICENSE +1 -1
- cartography/data/jobs/analysis/aws_ec2_iaminstance.json +0 -10
- cartography/data/jobs/analysis/aws_ec2_iaminstanceprofile.json +0 -10
- cartography/data/jobs/cleanup/aws_apigateway_details.json +0 -10
- cartography/data/jobs/cleanup/aws_dns_cleanup.json +0 -65
- cartography/data/jobs/cleanup/aws_import_account_access_key_cleanup.json +0 -17
- cartography/data/jobs/cleanup/aws_import_apigateway_cleanup.json +0 -45
- cartography/data/jobs/cleanup/aws_import_ec2_security_groupinfo_cleanup.json +0 -24
- cartography/data/jobs/cleanup/aws_import_groups_cleanup.json +0 -13
- cartography/data/jobs/cleanup/aws_import_lambda_cleanup.json +0 -50
- cartography/data/jobs/cleanup/aws_import_principals_cleanup.json +0 -30
- cartography/data/jobs/cleanup/aws_import_rds_clusters_cleanup.json +0 -23
- cartography/data/jobs/cleanup/aws_import_rds_instances_cleanup.json +0 -47
- cartography/data/jobs/cleanup/aws_import_rds_snapshots_cleanup.json +0 -23
- cartography/data/jobs/cleanup/aws_import_roles_cleanup.json +0 -13
- cartography/data/jobs/cleanup/aws_import_secrets_cleanup.json +0 -8
- cartography/data/jobs/cleanup/aws_import_snapshots_cleanup.json +0 -30
- cartography/data/jobs/cleanup/aws_import_users_cleanup.json +0 -8
- cartography/data/jobs/cleanup/aws_import_vpc_cleanup.json +0 -23
- cartography/data/jobs/cleanup/aws_import_vpc_peering_cleanup.json +0 -45
- cartography/data/jobs/cleanup/aws_kms_details.json +0 -10
- cartography/data/jobs/cleanup/azure_cosmosdb_cassandra_keyspace_cleanup.json +0 -25
- cartography/data/jobs/cleanup/azure_cosmosdb_cors_details.json +0 -15
- cartography/data/jobs/cleanup/azure_cosmosdb_mongodb_database_cleanup.json +0 -25
- cartography/data/jobs/cleanup/azure_cosmosdb_sql_database_cleanup.json +0 -25
- cartography/data/jobs/cleanup/azure_cosmosdb_table_resources_cleanup.json +0 -15
- cartography/data/jobs/cleanup/azure_database_account_cleanup.json +0 -85
- cartography/data/jobs/cleanup/azure_import_disks_cleanup.json +0 -15
- cartography/data/jobs/cleanup/azure_import_snapshots_cleanup.json +0 -15
- cartography/data/jobs/cleanup/azure_import_virtual_machines_cleanup.json +0 -25
- cartography/data/jobs/cleanup/azure_sql_server_cleanup.json +0 -125
- cartography/data/jobs/cleanup/azure_storage_account_cleanup.json +0 -95
- cartography/data/jobs/cleanup/azure_subscriptions_cleanup.json +0 -14
- cartography/data/jobs/cleanup/azure_tenant_cleanup.json +0 -9
- cartography/data/jobs/cleanup/crxcavator_import_cleanup.json +0 -18
- 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_dns_cleanup.json +0 -29
- cartography/data/jobs/cleanup/gcp_gke_cluster_cleanup.json +0 -17
- cartography/data/jobs/cleanup/gcp_storage_bucket_cleanup.json +0 -29
- cartography/data/jobs/cleanup/github_users_cleanup.json +0 -23
- cartography/data/jobs/cleanup/gsuite_ingest_groups_cleanup.json +0 -23
- cartography/data/jobs/cleanup/gsuite_ingest_users_cleanup.json +0 -11
- cartography/data/jobs/cleanup/kubernetes_import_cleanup.json +0 -70
- cartography/intel/crxcavator/__init__.py +0 -44
- cartography/intel/crxcavator/crxcavator.py +0 -329
- cartography/intel/gcp/crm.py +0 -302
- cartography/intel/gsuite/api.py +0 -284
- cartography/models/aws/ec2/keypairs.py +0 -64
- cartography-0.93.0rc1.dist-info/METADATA +0 -55
- cartography-0.93.0rc1.dist-info/NOTICE +0 -4
- cartography-0.93.0rc1.dist-info/RECORD +0 -341
- /cartography/data/jobs/{analysis → scoped_analysis}/aws_s3acl_analysis.json +0 -0
- {cartography-0.93.0rc1.dist-info → cartography-0.123.0.dist-info}/top_level.txt +0 -0
cartography/intel/gcp/crm.py
DELETED
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
# Google Compute Resource Manager
|
|
2
|
-
# https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy
|
|
3
|
-
import logging
|
|
4
|
-
from string import Template
|
|
5
|
-
from typing import Dict
|
|
6
|
-
from typing import List
|
|
7
|
-
|
|
8
|
-
import neo4j
|
|
9
|
-
from googleapiclient.discovery import HttpError
|
|
10
|
-
from googleapiclient.discovery import Resource
|
|
11
|
-
|
|
12
|
-
from cartography.util import run_cleanup_job
|
|
13
|
-
from cartography.util import timeit
|
|
14
|
-
|
|
15
|
-
logger = logging.getLogger(__name__)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@timeit
|
|
19
|
-
def get_gcp_organizations(crm_v1: Resource) -> List[Resource]:
|
|
20
|
-
"""
|
|
21
|
-
Return list of GCP organizations that the crm_v1 resource object has permissions to access.
|
|
22
|
-
Returns empty list if we are unable to enumerate organizations for any reason.
|
|
23
|
-
:param crm_v1: The Compute Resource Manager v1 resource object created by `googleapiclient.discovery.build()`.
|
|
24
|
-
See https://googleapis.github.io/google-api-python-client/docs/epy/googleapiclient.discovery-module.html#build.
|
|
25
|
-
:return: List of GCP Organizations. See https://cloud.google.com/resource-manager/reference/rest/v1/organizations.
|
|
26
|
-
"""
|
|
27
|
-
try:
|
|
28
|
-
req = crm_v1.organizations().search(body={})
|
|
29
|
-
res = req.execute()
|
|
30
|
-
return res.get('organizations', [])
|
|
31
|
-
except HttpError as e:
|
|
32
|
-
logger.warning("HttpError occurred in crm.get_gcp_organizations(), returning empty list. Details: %r", e)
|
|
33
|
-
return []
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
@timeit
|
|
37
|
-
def get_gcp_folders(crm_v2: Resource) -> List[Resource]:
|
|
38
|
-
"""
|
|
39
|
-
Return list of GCP folders that the crm_v2 resource object has permissions to access.
|
|
40
|
-
Returns empty list if we are unable to enumerate folders for any reason.
|
|
41
|
-
:param crm_v2: The Compute Resource Manager v2 resource object created by `googleapiclient.discovery.build()`.
|
|
42
|
-
See https://googleapis.github.io/google-api-python-client/docs/epy/googleapiclient.discovery-module.html#build.
|
|
43
|
-
:return: List of GCP folders. See https://cloud.google.com/resource-manager/reference/rest/v2/folders/list.
|
|
44
|
-
"""
|
|
45
|
-
try:
|
|
46
|
-
req = crm_v2.folders().search(body={})
|
|
47
|
-
res = req.execute()
|
|
48
|
-
return res.get('folders', [])
|
|
49
|
-
except HttpError as e:
|
|
50
|
-
logger.warning("HttpError occurred in crm.get_gcp_folders(), returning empty list. Details: %r", e)
|
|
51
|
-
return []
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
@timeit
|
|
55
|
-
def get_gcp_projects(crm_v1: Resource) -> List[Resource]:
|
|
56
|
-
"""
|
|
57
|
-
Return list of GCP projects that the crm_v1 resource object has permissions to access.
|
|
58
|
-
Returns empty list if we are unable to enumerate projects for any reason.
|
|
59
|
-
:param crm_v1: The Compute Resource Manager v1 resource object created by `googleapiclient.discovery.build()`.
|
|
60
|
-
See https://googleapis.github.io/google-api-python-client/docs/epy/googleapiclient.discovery-module.html#build.
|
|
61
|
-
:return: List of GCP projects. See https://cloud.google.com/resource-manager/reference/rest/v2/projects/list.
|
|
62
|
-
"""
|
|
63
|
-
try:
|
|
64
|
-
projects: List[Resource] = []
|
|
65
|
-
req = crm_v1.projects().list(filter="lifecycleState:ACTIVE")
|
|
66
|
-
while req is not None:
|
|
67
|
-
res = req.execute()
|
|
68
|
-
page = res.get('projects', [])
|
|
69
|
-
projects.extend(page)
|
|
70
|
-
req = crm_v1.projects().list_next(previous_request=req, previous_response=res)
|
|
71
|
-
return projects
|
|
72
|
-
except HttpError as e:
|
|
73
|
-
logger.warning("HttpError occurred in crm.get_gcp_projects(), returning empty list. Details: %r", e)
|
|
74
|
-
return []
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
@timeit
|
|
78
|
-
def load_gcp_organizations(neo4j_session: neo4j.Session, data: List[Dict], gcp_update_tag: int) -> None:
|
|
79
|
-
"""
|
|
80
|
-
Ingest the GCP organizations to Neo4j
|
|
81
|
-
:param neo4j_session: The Neo4j session
|
|
82
|
-
:param data: List of organizations; output from crm.get_gcp_organizations()
|
|
83
|
-
:param gcp_update_tag: The timestamp value to set our new Neo4j nodes with
|
|
84
|
-
:return: Nothing
|
|
85
|
-
"""
|
|
86
|
-
query = """
|
|
87
|
-
MERGE (org:GCPOrganization{id:$OrgName})
|
|
88
|
-
ON CREATE SET org.firstseen = timestamp()
|
|
89
|
-
SET org.orgname = $OrgName,
|
|
90
|
-
org.displayname = $DisplayName,
|
|
91
|
-
org.lifecyclestate = $LifecycleState,
|
|
92
|
-
org.lastupdated = $gcp_update_tag
|
|
93
|
-
"""
|
|
94
|
-
for org_object in data:
|
|
95
|
-
neo4j_session.run(
|
|
96
|
-
query,
|
|
97
|
-
OrgName=org_object['name'],
|
|
98
|
-
DisplayName=org_object.get('displayName', None),
|
|
99
|
-
LifecycleState=org_object.get('lifecycleState', None),
|
|
100
|
-
gcp_update_tag=gcp_update_tag,
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
@timeit
|
|
105
|
-
def load_gcp_folders(neo4j_session: neo4j.Session, data: List[Dict], gcp_update_tag: int) -> None:
|
|
106
|
-
"""
|
|
107
|
-
Ingest the GCP folders to Neo4j
|
|
108
|
-
:param neo4j_session: The Neo4j session
|
|
109
|
-
:param data: List of folders; output from crm.get_gcp_folders()
|
|
110
|
-
:param gcp_update_tag: The timestamp value to set our new Neo4j nodes with
|
|
111
|
-
:return: Nothing
|
|
112
|
-
"""
|
|
113
|
-
for folder in data:
|
|
114
|
-
# Get the correct parent type.
|
|
115
|
-
# Parents of folders can only be GCPOrganizations or other folders, see
|
|
116
|
-
# https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy
|
|
117
|
-
if folder['parent'].startswith("organizations"):
|
|
118
|
-
query = "MATCH (parent:GCPOrganization{id:$ParentId})"
|
|
119
|
-
elif folder['parent'].startswith("folders"):
|
|
120
|
-
query = """
|
|
121
|
-
MERGE (parent:GCPFolder{id:$ParentId})
|
|
122
|
-
ON CREATE SET parent.firstseen = timestamp()
|
|
123
|
-
"""
|
|
124
|
-
query += """
|
|
125
|
-
MERGE (folder:GCPFolder{id:$FolderName})
|
|
126
|
-
ON CREATE SET folder.firstseen = timestamp()
|
|
127
|
-
SET folder.foldername = $FolderName,
|
|
128
|
-
folder.displayname = $DisplayName,
|
|
129
|
-
folder.lifecyclestate = $LifecycleState,
|
|
130
|
-
folder.lastupdated = $gcp_update_tag
|
|
131
|
-
WITH parent, folder
|
|
132
|
-
MERGE (parent)-[r:RESOURCE]->(folder)
|
|
133
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
134
|
-
SET r.lastupdated = $gcp_update_tag
|
|
135
|
-
"""
|
|
136
|
-
neo4j_session.run(
|
|
137
|
-
query,
|
|
138
|
-
ParentId=folder['parent'],
|
|
139
|
-
FolderName=folder['name'],
|
|
140
|
-
DisplayName=folder.get('displayName', None),
|
|
141
|
-
LifecycleState=folder.get('lifecycleState', None),
|
|
142
|
-
gcp_update_tag=gcp_update_tag,
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
@timeit
|
|
147
|
-
def load_gcp_projects(neo4j_session: neo4j.Session, data: List[Dict], gcp_update_tag: int) -> None:
|
|
148
|
-
"""
|
|
149
|
-
Ingest the GCP projects to Neo4j
|
|
150
|
-
:param neo4j_session: The Neo4j session
|
|
151
|
-
:param data: List of GCP projects; output from crm.get_gcp_projects()
|
|
152
|
-
:param gcp_update_tag: The timestamp value to set our new Neo4j nodes with
|
|
153
|
-
:return: Nothing
|
|
154
|
-
"""
|
|
155
|
-
query = """
|
|
156
|
-
MERGE (project:GCPProject{id:$ProjectId})
|
|
157
|
-
ON CREATE SET project.firstseen = timestamp()
|
|
158
|
-
SET project.projectid = $ProjectId,
|
|
159
|
-
project.projectnumber = $ProjectNumber,
|
|
160
|
-
project.displayname = $DisplayName,
|
|
161
|
-
project.lifecyclestate = $LifecycleState,
|
|
162
|
-
project.lastupdated = $gcp_update_tag
|
|
163
|
-
"""
|
|
164
|
-
|
|
165
|
-
for project in data:
|
|
166
|
-
neo4j_session.run(
|
|
167
|
-
query,
|
|
168
|
-
ProjectId=project['projectId'],
|
|
169
|
-
ProjectNumber=project['projectNumber'],
|
|
170
|
-
DisplayName=project.get('name', None),
|
|
171
|
-
LifecycleState=project.get('lifecycleState', None),
|
|
172
|
-
gcp_update_tag=gcp_update_tag,
|
|
173
|
-
)
|
|
174
|
-
if project.get('parent'):
|
|
175
|
-
_attach_gcp_project_parent(neo4j_session, project, gcp_update_tag)
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
@timeit
|
|
179
|
-
def _attach_gcp_project_parent(neo4j_session: neo4j.Session, project: Dict, gcp_update_tag: int) -> None:
|
|
180
|
-
"""
|
|
181
|
-
Attach a project to its respective parent, as in the Resource Hierarchy -
|
|
182
|
-
https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy
|
|
183
|
-
"""
|
|
184
|
-
if project['parent']['type'] == 'organization':
|
|
185
|
-
parent_label = 'GCPOrganization'
|
|
186
|
-
elif project['parent']['type'] == 'folder':
|
|
187
|
-
parent_label = 'GCPFolder'
|
|
188
|
-
else:
|
|
189
|
-
raise NotImplementedError(
|
|
190
|
-
"Ingestion of GCP {}s as parent nodes is currently not supported. "
|
|
191
|
-
"Please file an issue at https://github.com/lyft/cartography/issues.".format(
|
|
192
|
-
project['parent']['type'],
|
|
193
|
-
),
|
|
194
|
-
)
|
|
195
|
-
parent_id = f"{project['parent']['type']}s/{project['parent']['id']}"
|
|
196
|
-
INGEST_PARENT_TEMPLATE = Template("""
|
|
197
|
-
MATCH (project:GCPProject{id:$ProjectId})
|
|
198
|
-
|
|
199
|
-
MERGE (parent:$parent_label{id:$ParentId})
|
|
200
|
-
ON CREATE SET parent.firstseen = timestamp()
|
|
201
|
-
|
|
202
|
-
MERGE (parent)-[r:RESOURCE]->(project)
|
|
203
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
204
|
-
SET r.lastupdated = $gcp_update_tag
|
|
205
|
-
""")
|
|
206
|
-
neo4j_session.run(
|
|
207
|
-
INGEST_PARENT_TEMPLATE.safe_substitute(parent_label=parent_label),
|
|
208
|
-
ParentId=parent_id,
|
|
209
|
-
ProjectId=project['projectId'],
|
|
210
|
-
gcp_update_tag=gcp_update_tag,
|
|
211
|
-
)
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
@timeit
|
|
215
|
-
def cleanup_gcp_organizations(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
|
|
216
|
-
"""
|
|
217
|
-
Remove stale GCP organizations and their relationships
|
|
218
|
-
:param neo4j_session: The Neo4j session
|
|
219
|
-
:param common_job_parameters: Parameters to carry to the cleanup job
|
|
220
|
-
:return: Nothing
|
|
221
|
-
"""
|
|
222
|
-
run_cleanup_job('gcp_crm_organization_cleanup.json', neo4j_session, common_job_parameters)
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
@timeit
|
|
226
|
-
def cleanup_gcp_folders(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
|
|
227
|
-
"""
|
|
228
|
-
Remove stale GCP folders and their relationships
|
|
229
|
-
:param neo4j_session: The Neo4j session
|
|
230
|
-
:param common_job_parameters: Parameters to carry to the cleanup job
|
|
231
|
-
:return: Nothing
|
|
232
|
-
"""
|
|
233
|
-
run_cleanup_job('gcp_crm_folder_cleanup.json', neo4j_session, common_job_parameters)
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
@timeit
|
|
237
|
-
def cleanup_gcp_projects(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
|
|
238
|
-
"""
|
|
239
|
-
Remove stale GCP projects and their relationships
|
|
240
|
-
:param neo4j_session: The Neo4j session
|
|
241
|
-
:param common_job_parameters: Parameters to carry to the cleanup job
|
|
242
|
-
:return: Nothing
|
|
243
|
-
"""
|
|
244
|
-
run_cleanup_job('gcp_crm_project_cleanup.json', neo4j_session, common_job_parameters)
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
@timeit
|
|
248
|
-
def sync_gcp_organizations(
|
|
249
|
-
neo4j_session: neo4j.Session, crm_v1: Resource, gcp_update_tag: int,
|
|
250
|
-
common_job_parameters: Dict,
|
|
251
|
-
) -> None:
|
|
252
|
-
"""
|
|
253
|
-
Get GCP organization data using the CRM v1 resource object, load the data to Neo4j, and clean up stale nodes.
|
|
254
|
-
:param neo4j_session: The Neo4j session
|
|
255
|
-
:param crm_v1: The Compute Resource Manager v1 resource object created by `googleapiclient.discovery.build()`.
|
|
256
|
-
See https://googleapis.github.io/google-api-python-client/docs/epy/googleapiclient.discovery-module.html#build.
|
|
257
|
-
:param gcp_update_tag: The timestamp value to set our new Neo4j nodes with
|
|
258
|
-
:param common_job_parameters: Parameters to carry to the Neo4j jobs
|
|
259
|
-
:return: Nothing
|
|
260
|
-
"""
|
|
261
|
-
logger.debug("Syncing GCP organizations")
|
|
262
|
-
data = get_gcp_organizations(crm_v1)
|
|
263
|
-
load_gcp_organizations(neo4j_session, data, gcp_update_tag)
|
|
264
|
-
cleanup_gcp_organizations(neo4j_session, common_job_parameters)
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
@timeit
|
|
268
|
-
def sync_gcp_folders(
|
|
269
|
-
neo4j_session: neo4j.Session, crm_v2: Resource, gcp_update_tag: int,
|
|
270
|
-
common_job_parameters: Dict,
|
|
271
|
-
) -> None:
|
|
272
|
-
"""
|
|
273
|
-
Get GCP folder data using the CRM v2 resource object, load the data to Neo4j, and clean up stale nodes.
|
|
274
|
-
:param neo4j_session: The Neo4j session
|
|
275
|
-
:param crm_v2: The Compute Resource Manager v2 resource object created by `googleapiclient.discovery.build()`.
|
|
276
|
-
See https://googleapis.github.io/google-api-python-client/docs/epy/googleapiclient.discovery-module.html#build.
|
|
277
|
-
:param gcp_update_tag: The timestamp value to set our new Neo4j nodes with
|
|
278
|
-
:param common_job_parameters: Parameters to carry to the Neo4j jobs
|
|
279
|
-
:return: Nothing
|
|
280
|
-
"""
|
|
281
|
-
logger.debug("Syncing GCP folders")
|
|
282
|
-
folders = get_gcp_folders(crm_v2)
|
|
283
|
-
load_gcp_folders(neo4j_session, folders, gcp_update_tag)
|
|
284
|
-
cleanup_gcp_folders(neo4j_session, common_job_parameters)
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
@timeit
|
|
288
|
-
def sync_gcp_projects(
|
|
289
|
-
neo4j_session: neo4j.Session, projects: List[Dict], gcp_update_tag: int,
|
|
290
|
-
common_job_parameters: Dict,
|
|
291
|
-
) -> None:
|
|
292
|
-
"""
|
|
293
|
-
Load a given list of GCP project data to Neo4j and clean up stale nodes.
|
|
294
|
-
:param neo4j_session: The Neo4j session
|
|
295
|
-
:param projects: List of GCP projects; output from crm.get_gcp_projects()
|
|
296
|
-
:param gcp_update_tag: The timestamp value to set our new Neo4j nodes with
|
|
297
|
-
:param common_job_parameters: Parameters to carry to the Neo4j jobs
|
|
298
|
-
:return: Nothing
|
|
299
|
-
"""
|
|
300
|
-
logger.debug("Syncing GCP projects")
|
|
301
|
-
load_gcp_projects(neo4j_session, projects, gcp_update_tag)
|
|
302
|
-
cleanup_gcp_projects(neo4j_session, common_job_parameters)
|
cartography/intel/gsuite/api.py
DELETED
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from typing import Dict
|
|
3
|
-
from typing import List
|
|
4
|
-
|
|
5
|
-
import neo4j
|
|
6
|
-
from googleapiclient.discovery import Resource
|
|
7
|
-
|
|
8
|
-
from cartography.util import run_cleanup_job
|
|
9
|
-
from cartography.util import timeit
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
logger = logging.getLogger(__name__)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
GOOGLE_API_NUM_RETRIES = 5
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@timeit
|
|
19
|
-
def get_all_groups(admin: Resource) -> List[Dict]:
|
|
20
|
-
"""
|
|
21
|
-
Return list of Google Groups in your organization
|
|
22
|
-
Returns empty list if we are unable to enumerate the groups for any reasons
|
|
23
|
-
|
|
24
|
-
googleapiclient.discovery.build('admin', 'directory_v1', credentials=credentials, cache_discovery=False)
|
|
25
|
-
|
|
26
|
-
:param admin: google's apiclient discovery resource object. From googleapiclient.discovery.build
|
|
27
|
-
See https://googleapis.github.io/google-api-python-client/docs/epy/googleapiclient.discovery-module.html#build.
|
|
28
|
-
:return: List of Google groups in domain
|
|
29
|
-
"""
|
|
30
|
-
request = admin.groups().list(customer='my_customer', maxResults=20, orderBy='email')
|
|
31
|
-
response_objects = []
|
|
32
|
-
while request is not None:
|
|
33
|
-
resp = request.execute(num_retries=GOOGLE_API_NUM_RETRIES)
|
|
34
|
-
response_objects.append(resp)
|
|
35
|
-
request = admin.groups().list_next(request, resp)
|
|
36
|
-
return response_objects
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
@timeit
|
|
40
|
-
def transform_groups(response_objects: List[Dict]) -> List[Dict]:
|
|
41
|
-
""" Strips list of API response objects to return list of group objects only
|
|
42
|
-
|
|
43
|
-
:param response_objects:
|
|
44
|
-
:return: list of dictionary objects as defined in /docs/schema/gsuite.md
|
|
45
|
-
"""
|
|
46
|
-
groups: List[Dict] = []
|
|
47
|
-
for response_object in response_objects:
|
|
48
|
-
for group in response_object['groups']:
|
|
49
|
-
groups.append(group)
|
|
50
|
-
return groups
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
@timeit
|
|
54
|
-
def transform_users(response_objects: List[Dict]) -> List[Dict]:
|
|
55
|
-
""" Strips list of API response objects to return list of group objects only
|
|
56
|
-
:param response_objects:
|
|
57
|
-
:return: list of dictionary objects as defined in /docs/schema/gsuite.md
|
|
58
|
-
"""
|
|
59
|
-
users: List[Dict] = []
|
|
60
|
-
for response_object in response_objects:
|
|
61
|
-
for user in response_object['users']:
|
|
62
|
-
users.append(user)
|
|
63
|
-
return users
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
@timeit
|
|
67
|
-
def get_all_groups_for_email(admin: Resource, email: str) -> List[Dict]:
|
|
68
|
-
""" Fetch all groups of which the given group is a member
|
|
69
|
-
|
|
70
|
-
Arguments:
|
|
71
|
-
email: A string representing the email address for the group
|
|
72
|
-
|
|
73
|
-
Returns a list of Group models
|
|
74
|
-
Throws GoogleException
|
|
75
|
-
"""
|
|
76
|
-
request = admin.groups().list(userKey=email, maxResults=500)
|
|
77
|
-
groups: List[Dict] = []
|
|
78
|
-
while request is not None:
|
|
79
|
-
resp = request.execute(num_retries=GOOGLE_API_NUM_RETRIES)
|
|
80
|
-
groups = groups + resp.get('groups', [])
|
|
81
|
-
request = admin.groups().list_next(request, resp)
|
|
82
|
-
return groups
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
@timeit
|
|
86
|
-
def get_members_for_group(admin: Resource, group_email: str) -> List[Dict]:
|
|
87
|
-
""" Get all members for a google group
|
|
88
|
-
|
|
89
|
-
:param group_email: A string representing the email address for the group
|
|
90
|
-
|
|
91
|
-
:return: List of dictionaries representing Users or Groups.
|
|
92
|
-
"""
|
|
93
|
-
request = admin.members().list(
|
|
94
|
-
groupKey=group_email,
|
|
95
|
-
maxResults=500,
|
|
96
|
-
)
|
|
97
|
-
members: List[Dict] = []
|
|
98
|
-
while request is not None:
|
|
99
|
-
resp = request.execute(num_retries=GOOGLE_API_NUM_RETRIES)
|
|
100
|
-
members = members + resp.get('members', [])
|
|
101
|
-
request = admin.members().list_next(request, resp)
|
|
102
|
-
|
|
103
|
-
return members
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
@timeit
|
|
107
|
-
def get_all_users(admin: Resource) -> List[Dict]:
|
|
108
|
-
"""
|
|
109
|
-
Return list of Google Users in your organization
|
|
110
|
-
Returns empty list if we are unable to enumerate the groups for any reasons
|
|
111
|
-
https://developers.google.com/admin-sdk/directory/v1/guides/manage-users
|
|
112
|
-
|
|
113
|
-
:param admin: apiclient discovery resource object
|
|
114
|
-
see
|
|
115
|
-
:return: List of Google users in domain
|
|
116
|
-
see https://developers.google.com/admin-sdk/directory/v1/guides/manage-users#get_all_domain_users
|
|
117
|
-
"""
|
|
118
|
-
request = admin.users().list(customer='my_customer', maxResults=500, orderBy='email')
|
|
119
|
-
response_objects = []
|
|
120
|
-
while request is not None:
|
|
121
|
-
resp = request.execute(num_retries=GOOGLE_API_NUM_RETRIES)
|
|
122
|
-
response_objects.append(resp)
|
|
123
|
-
request = admin.users().list_next(request, resp)
|
|
124
|
-
return response_objects
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
@timeit
|
|
128
|
-
def load_gsuite_groups(neo4j_session: neo4j.Session, groups: List[Dict], gsuite_update_tag: int) -> None:
|
|
129
|
-
ingestion_qry = """
|
|
130
|
-
UNWIND $GroupData as group
|
|
131
|
-
MERGE (g:GSuiteGroup{id: group.id})
|
|
132
|
-
ON CREATE SET
|
|
133
|
-
g.firstseen = $UpdateTag,
|
|
134
|
-
g.group_id = group.id
|
|
135
|
-
SET
|
|
136
|
-
g.admin_created = group.adminCreated,
|
|
137
|
-
g.description = group.description,
|
|
138
|
-
g.direct_members_count = group.directMembersCount,
|
|
139
|
-
g.email = group.email,
|
|
140
|
-
g.etag = group.etag,
|
|
141
|
-
g.kind = group.kind,
|
|
142
|
-
g.name = group.name,
|
|
143
|
-
g.lastupdated = $UpdateTag
|
|
144
|
-
"""
|
|
145
|
-
logger.info(f'Ingesting {len(groups)} gsuite groups')
|
|
146
|
-
neo4j_session.run(ingestion_qry, GroupData=groups, UpdateTag=gsuite_update_tag)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
@timeit
|
|
150
|
-
def load_gsuite_users(neo4j_session: neo4j.Session, users: List[Dict], gsuite_update_tag: int) -> None:
|
|
151
|
-
ingestion_qry = """
|
|
152
|
-
UNWIND $UserData as user
|
|
153
|
-
MERGE (u:GSuiteUser{id: user.id})
|
|
154
|
-
ON CREATE SET
|
|
155
|
-
u.user_id = user.id,
|
|
156
|
-
u.firstseen = $UpdateTag
|
|
157
|
-
SET
|
|
158
|
-
u.agreed_to_terms = user.agreedToTerms,
|
|
159
|
-
u.archived = user.archived,
|
|
160
|
-
u.change_password_at_next_login = user.changePasswordAtNextLogin,
|
|
161
|
-
u.creation_time = user.creationTime,
|
|
162
|
-
u.customer_id = user.customerId,
|
|
163
|
-
u.etag = user.etag,
|
|
164
|
-
u.include_in_global_address_list = user.includeInGlobalAddressList,
|
|
165
|
-
u.ip_whitelisted = user.ipWhitelisted,
|
|
166
|
-
u.is_admin = user.isAdmin,
|
|
167
|
-
u.is_delegated_admin = user.isDelegatedAdmin,
|
|
168
|
-
u.is_enforced_in_2_sv = user.isEnforcedIn2Sv,
|
|
169
|
-
u.is_enrolled_in_2_sv = user.isEnrolledIn2Sv,
|
|
170
|
-
u.is_mailbox_setup = user.isMailboxSetup,
|
|
171
|
-
u.kind = user.kind,
|
|
172
|
-
u.last_login_time = user.lastLoginTime,
|
|
173
|
-
u.name = user.name.fullName,
|
|
174
|
-
u.family_name = user.name.familyName,
|
|
175
|
-
u.given_name = user.name.givenName,
|
|
176
|
-
u.org_unit_path = user.orgUnitPath,
|
|
177
|
-
u.primary_email = user.primaryEmail,
|
|
178
|
-
u.email = user.primaryEmail,
|
|
179
|
-
u.suspended = user.suspended,
|
|
180
|
-
u.thumbnail_photo_etag = user.thumbnailPhotoEtag,
|
|
181
|
-
u.thumbnail_photo_url = user.thumbnailPhotoUrl,
|
|
182
|
-
u.lastupdated = $UpdateTag
|
|
183
|
-
"""
|
|
184
|
-
logger.info(f'Ingesting {len(users)} gsuite users')
|
|
185
|
-
neo4j_session.run(ingestion_qry, UserData=users, UpdateTag=gsuite_update_tag)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
@timeit
|
|
189
|
-
def load_gsuite_members(neo4j_session: neo4j.Session, group: Dict, members: List[Dict], gsuite_update_tag: int) -> None:
|
|
190
|
-
ingestion_qry = """
|
|
191
|
-
UNWIND $MemberData as member
|
|
192
|
-
MATCH (user:GSuiteUser {id: member.id}),(group:GSuiteGroup {id: $GroupID })
|
|
193
|
-
MERGE (user)-[r:MEMBER_GSUITE_GROUP]->(group)
|
|
194
|
-
ON CREATE SET
|
|
195
|
-
r.firstseen = $UpdateTag
|
|
196
|
-
SET
|
|
197
|
-
r.lastupdated = $UpdateTag
|
|
198
|
-
"""
|
|
199
|
-
neo4j_session.run(
|
|
200
|
-
ingestion_qry,
|
|
201
|
-
MemberData=members,
|
|
202
|
-
GroupID=group.get("id"),
|
|
203
|
-
UpdateTag=gsuite_update_tag,
|
|
204
|
-
)
|
|
205
|
-
membership_qry = """
|
|
206
|
-
UNWIND $MemberData as member
|
|
207
|
-
MATCH(group_1: GSuiteGroup{id: member.id}), (group_2:GSuiteGroup {id: $GroupID})
|
|
208
|
-
MERGE (group_1)-[r:MEMBER_GSUITE_GROUP]->(group_2)
|
|
209
|
-
ON CREATE SET
|
|
210
|
-
r.firstseen = $UpdateTag
|
|
211
|
-
SET
|
|
212
|
-
r.lastupdated = $UpdateTag
|
|
213
|
-
"""
|
|
214
|
-
neo4j_session.run(membership_qry, MemberData=members, GroupID=group.get("id"), UpdateTag=gsuite_update_tag)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
@timeit
|
|
218
|
-
def cleanup_gsuite_users(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
|
|
219
|
-
run_cleanup_job(
|
|
220
|
-
'gsuite_ingest_users_cleanup.json',
|
|
221
|
-
neo4j_session,
|
|
222
|
-
common_job_parameters,
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
@timeit
|
|
227
|
-
def cleanup_gsuite_groups(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
|
|
228
|
-
run_cleanup_job(
|
|
229
|
-
'gsuite_ingest_groups_cleanup.json',
|
|
230
|
-
neo4j_session,
|
|
231
|
-
common_job_parameters,
|
|
232
|
-
)
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
@timeit
|
|
236
|
-
def sync_gsuite_users(
|
|
237
|
-
neo4j_session: neo4j.Session, admin: Resource, gsuite_update_tag: int, common_job_parameters: Dict,
|
|
238
|
-
) -> None:
|
|
239
|
-
"""
|
|
240
|
-
GET GSuite user objects using the google admin api resource, load the data into Neo4j and clean up stale nodes.
|
|
241
|
-
|
|
242
|
-
:param session: The Neo4j session
|
|
243
|
-
:param admin: Google admin resource object created by `googleapiclient.discovery.build()`.
|
|
244
|
-
See https://googleapis.github.io/google-api-python-client/docs/epy/googleapiclient.discovery-module.html#build.
|
|
245
|
-
:param gcp_update_tag: The timestamp value to set our new Neo4j nodes with
|
|
246
|
-
:param common_job_parameters: Parameters to carry to the Neo4j jobs
|
|
247
|
-
:return: Nothing
|
|
248
|
-
"""
|
|
249
|
-
logger.debug('Syncing GSuite Users')
|
|
250
|
-
resp_objs = get_all_users(admin)
|
|
251
|
-
users = transform_users(resp_objs)
|
|
252
|
-
load_gsuite_users(neo4j_session, users, gsuite_update_tag)
|
|
253
|
-
cleanup_gsuite_users(neo4j_session, common_job_parameters)
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
@timeit
|
|
257
|
-
def sync_gsuite_groups(
|
|
258
|
-
neo4j_session: neo4j.Session, admin: Resource, gsuite_update_tag: int, common_job_parameters: Dict,
|
|
259
|
-
) -> None:
|
|
260
|
-
"""
|
|
261
|
-
GET GSuite group objects using the google admin api resource, load the data into Neo4j and clean up stale nodes.
|
|
262
|
-
|
|
263
|
-
:param neo4j_session: The Neo4j session
|
|
264
|
-
:param admin: Google admin resource object created by `googleapiclient.discovery.build()`.
|
|
265
|
-
See https://googleapis.github.io/google-api-python-client/docs/epy/googleapiclient.discovery-module.html#build.
|
|
266
|
-
:param gcp_update_tag: The timestamp value to set our new Neo4j nodes with
|
|
267
|
-
:param common_job_parameters: Parameters to carry to the Neo4j jobs
|
|
268
|
-
:return: Nothing
|
|
269
|
-
"""
|
|
270
|
-
logger.debug('Syncing GSuite Groups')
|
|
271
|
-
resp_objs = get_all_groups(admin)
|
|
272
|
-
groups = transform_groups(resp_objs)
|
|
273
|
-
load_gsuite_groups(neo4j_session, groups, gsuite_update_tag)
|
|
274
|
-
cleanup_gsuite_groups(neo4j_session, common_job_parameters)
|
|
275
|
-
sync_gsuite_members(groups, neo4j_session, admin, gsuite_update_tag)
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
@timeit
|
|
279
|
-
def sync_gsuite_members(
|
|
280
|
-
groups: List[Dict], neo4j_session: neo4j.Session, admin: Resource, gsuite_update_tag: int,
|
|
281
|
-
) -> None:
|
|
282
|
-
for group in groups:
|
|
283
|
-
members = get_members_for_group(admin, group['email'])
|
|
284
|
-
load_gsuite_members(neo4j_session, group, members, gsuite_update_tag)
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
|
-
|
|
3
|
-
from cartography.models.core.common import PropertyRef
|
|
4
|
-
from cartography.models.core.nodes import CartographyNodeProperties
|
|
5
|
-
from cartography.models.core.nodes import CartographyNodeSchema
|
|
6
|
-
from cartography.models.core.relationships import CartographyRelProperties
|
|
7
|
-
from cartography.models.core.relationships import CartographyRelSchema
|
|
8
|
-
from cartography.models.core.relationships import LinkDirection
|
|
9
|
-
from cartography.models.core.relationships import make_target_node_matcher
|
|
10
|
-
from cartography.models.core.relationships import OtherRelationships
|
|
11
|
-
from cartography.models.core.relationships import TargetNodeMatcher
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@dataclass(frozen=True)
|
|
15
|
-
class EC2KeyPairNodeProperties(CartographyNodeProperties):
|
|
16
|
-
id: PropertyRef = PropertyRef('KeyPairArn')
|
|
17
|
-
arn: PropertyRef = PropertyRef('KeyPairArn', extra_index=True)
|
|
18
|
-
keyname: PropertyRef = PropertyRef('KeyName')
|
|
19
|
-
region: PropertyRef = PropertyRef('Region', set_in_kwargs=True)
|
|
20
|
-
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@dataclass(frozen=True)
|
|
24
|
-
class EC2KeyPairToAwsAccountRelProperties(CartographyRelProperties):
|
|
25
|
-
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
@dataclass(frozen=True)
|
|
29
|
-
class EC2KeyPairToAWSAccount(CartographyRelSchema):
|
|
30
|
-
target_node_label: str = 'AWSAccount'
|
|
31
|
-
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
32
|
-
{'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
|
|
33
|
-
)
|
|
34
|
-
direction: LinkDirection = LinkDirection.INWARD
|
|
35
|
-
rel_label: str = "RESOURCE"
|
|
36
|
-
properties: EC2KeyPairToAwsAccountRelProperties = EC2KeyPairToAwsAccountRelProperties()
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
@dataclass(frozen=True)
|
|
40
|
-
class EC2KeyPairToEC2InstanceRelProperties(CartographyRelProperties):
|
|
41
|
-
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
@dataclass(frozen=True)
|
|
45
|
-
class EC2KeyPairToEC2Instance(CartographyRelSchema):
|
|
46
|
-
target_node_label: str = 'EC2Instance'
|
|
47
|
-
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
48
|
-
{'id': PropertyRef('InstanceId')},
|
|
49
|
-
)
|
|
50
|
-
direction: LinkDirection = LinkDirection.OUTWARD
|
|
51
|
-
rel_label: str = "SSH_LOGIN_TO"
|
|
52
|
-
properties: EC2KeyPairToEC2InstanceRelProperties = EC2KeyPairToEC2InstanceRelProperties()
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
@dataclass(frozen=True)
|
|
56
|
-
class EC2KeyPairSchema(CartographyNodeSchema):
|
|
57
|
-
label: str = 'EC2KeyPair'
|
|
58
|
-
properties: EC2KeyPairNodeProperties = EC2KeyPairNodeProperties()
|
|
59
|
-
sub_resource_relationship: EC2KeyPairToAWSAccount = EC2KeyPairToAWSAccount()
|
|
60
|
-
other_relationships: OtherRelationships = OtherRelationships(
|
|
61
|
-
[
|
|
62
|
-
EC2KeyPairToEC2Instance(),
|
|
63
|
-
],
|
|
64
|
-
)
|