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
|
@@ -3,131 +3,58 @@ import logging
|
|
|
3
3
|
from collections import namedtuple
|
|
4
4
|
from typing import Dict
|
|
5
5
|
from typing import List
|
|
6
|
+
from typing import Optional
|
|
6
7
|
from typing import Set
|
|
7
8
|
|
|
8
|
-
import googleapiclient.discovery
|
|
9
9
|
import neo4j
|
|
10
|
+
from google.auth.credentials import Credentials as GoogleCredentials
|
|
11
|
+
from google.cloud.asset_v1 import AssetServiceClient
|
|
12
|
+
from googleapiclient.discovery import HttpError
|
|
10
13
|
from googleapiclient.discovery import Resource
|
|
11
|
-
from oauth2client.client import ApplicationDefaultCredentialsError
|
|
12
|
-
from oauth2client.client import GoogleCredentials
|
|
13
14
|
|
|
14
15
|
from cartography.config import Config
|
|
16
|
+
from cartography.graph.job import GraphJob
|
|
17
|
+
from cartography.intel.gcp import bigtable_app_profile
|
|
18
|
+
from cartography.intel.gcp import bigtable_backup
|
|
19
|
+
from cartography.intel.gcp import bigtable_cluster
|
|
20
|
+
from cartography.intel.gcp import bigtable_instance
|
|
21
|
+
from cartography.intel.gcp import bigtable_table
|
|
22
|
+
from cartography.intel.gcp import cai
|
|
15
23
|
from cartography.intel.gcp import compute
|
|
16
|
-
from cartography.intel.gcp import crm
|
|
17
24
|
from cartography.intel.gcp import dns
|
|
18
25
|
from cartography.intel.gcp import gke
|
|
26
|
+
from cartography.intel.gcp import iam
|
|
27
|
+
from cartography.intel.gcp import permission_relationships
|
|
28
|
+
from cartography.intel.gcp import policy_bindings
|
|
19
29
|
from cartography.intel.gcp import storage
|
|
30
|
+
from cartography.intel.gcp.clients import build_asset_client
|
|
31
|
+
from cartography.intel.gcp.clients import build_client
|
|
32
|
+
from cartography.intel.gcp.clients import get_gcp_credentials
|
|
33
|
+
from cartography.intel.gcp.crm.folders import sync_gcp_folders
|
|
34
|
+
from cartography.intel.gcp.crm.orgs import sync_gcp_organizations
|
|
35
|
+
from cartography.intel.gcp.crm.projects import sync_gcp_projects
|
|
36
|
+
from cartography.models.gcp.crm.folders import GCPFolderSchema
|
|
37
|
+
from cartography.models.gcp.crm.organizations import GCPOrganizationSchema
|
|
38
|
+
from cartography.models.gcp.crm.projects import GCPProjectSchema
|
|
20
39
|
from cartography.util import run_analysis_job
|
|
21
40
|
from cartography.util import timeit
|
|
22
41
|
|
|
23
42
|
logger = logging.getLogger(__name__)
|
|
24
|
-
Resources = namedtuple('Resources', 'compute container crm_v1 crm_v2 dns storage serviceusage')
|
|
25
43
|
|
|
26
44
|
# Mapping of service short names to their full names as in docs. See https://developers.google.com/apis-explorer,
|
|
27
45
|
# and https://cloud.google.com/service-usage/docs/reference/rest/v1/services#ServiceConfig
|
|
28
|
-
Services = namedtuple(
|
|
46
|
+
Services = namedtuple("Services", "compute storage gke dns iam bigtable cai")
|
|
29
47
|
service_names = Services(
|
|
30
|
-
compute=
|
|
31
|
-
storage=
|
|
32
|
-
gke=
|
|
33
|
-
dns=
|
|
48
|
+
compute="compute.googleapis.com",
|
|
49
|
+
storage="storage.googleapis.com",
|
|
50
|
+
gke="container.googleapis.com",
|
|
51
|
+
dns="dns.googleapis.com",
|
|
52
|
+
iam="iam.googleapis.com",
|
|
53
|
+
bigtable="bigtableadmin.googleapis.com",
|
|
54
|
+
cai="cloudasset.googleapis.com",
|
|
34
55
|
)
|
|
35
56
|
|
|
36
57
|
|
|
37
|
-
def _get_crm_resource_v1(credentials: GoogleCredentials) -> Resource:
|
|
38
|
-
"""
|
|
39
|
-
Instantiates a Google Compute Resource Manager v1 resource object to call the Resource Manager API.
|
|
40
|
-
See https://cloud.google.com/resource-manager/reference/rest/.
|
|
41
|
-
:param credentials: The GoogleCredentials object
|
|
42
|
-
:return: A CRM v1 resource object
|
|
43
|
-
"""
|
|
44
|
-
# cache_discovery=False to suppress extra warnings.
|
|
45
|
-
# See https://github.com/googleapis/google-api-python-client/issues/299#issuecomment-268915510 and related issues
|
|
46
|
-
return googleapiclient.discovery.build('cloudresourcemanager', 'v1', credentials=credentials, cache_discovery=False)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def _get_crm_resource_v2(credentials: GoogleCredentials) -> Resource:
|
|
50
|
-
"""
|
|
51
|
-
Instantiates a Google Compute Resource Manager v2 resource object to call the Resource Manager API.
|
|
52
|
-
We need a v2 resource object to query for GCP folders.
|
|
53
|
-
:param credentials: The GoogleCredentials object
|
|
54
|
-
:return: A CRM v2 resource object
|
|
55
|
-
"""
|
|
56
|
-
return googleapiclient.discovery.build('cloudresourcemanager', 'v2', credentials=credentials, cache_discovery=False)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def _get_compute_resource(credentials: GoogleCredentials) -> Resource:
|
|
60
|
-
"""
|
|
61
|
-
Instantiates a Google Compute resource object to call the Compute API. This is used to pull zone, instance, and
|
|
62
|
-
networking data. See https://cloud.google.com/compute/docs/reference/rest/v1/.
|
|
63
|
-
:param credentials: The GoogleCredentials object
|
|
64
|
-
:return: A Compute resource object
|
|
65
|
-
"""
|
|
66
|
-
return googleapiclient.discovery.build('compute', 'v1', credentials=credentials, cache_discovery=False)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def _get_storage_resource(credentials: GoogleCredentials) -> Resource:
|
|
70
|
-
"""
|
|
71
|
-
Instantiates a Google Cloud Storage resource object to call the Storage API.
|
|
72
|
-
This is used to pull bucket metadata and IAM Policies
|
|
73
|
-
as well as list buckets in a specified project.
|
|
74
|
-
See https://cloud.google.com/storage/docs/json_api/.
|
|
75
|
-
:param credentials: The GoogleCredentials object
|
|
76
|
-
:return: A Storage resource object
|
|
77
|
-
"""
|
|
78
|
-
return googleapiclient.discovery.build('storage', 'v1', credentials=credentials, cache_discovery=False)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def _get_container_resource(credentials: GoogleCredentials) -> Resource:
|
|
82
|
-
"""
|
|
83
|
-
Instantiates a Google Cloud Container resource object to call the
|
|
84
|
-
Container API. See: https://cloud.google.com/kubernetes-engine/docs/reference/rest/v1/.
|
|
85
|
-
|
|
86
|
-
:param credentials: The GoogleCredentials object
|
|
87
|
-
:return: A Container resource object
|
|
88
|
-
"""
|
|
89
|
-
return googleapiclient.discovery.build('container', 'v1', credentials=credentials, cache_discovery=False)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def _get_dns_resource(credentials: GoogleCredentials) -> Resource:
|
|
93
|
-
"""
|
|
94
|
-
Instantiates a Google Cloud DNS resource object to call the
|
|
95
|
-
Container API. See: https://cloud.google.com/dns/docs/reference/v1/.
|
|
96
|
-
|
|
97
|
-
:param credentials: The GoogleCredentials object
|
|
98
|
-
:return: A DNS resource object
|
|
99
|
-
"""
|
|
100
|
-
return googleapiclient.discovery.build('dns', 'v1', credentials=credentials, cache_discovery=False)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
def _get_serviceusage_resource(credentials: GoogleCredentials) -> Resource:
|
|
104
|
-
"""
|
|
105
|
-
Instantiates a serviceusage resource object.
|
|
106
|
-
See: https://cloud.google.com/service-usage/docs/reference/rest/v1/operations/list.
|
|
107
|
-
|
|
108
|
-
:param credentials: The GoogleCredentials object
|
|
109
|
-
:return: A serviceusage resource object
|
|
110
|
-
"""
|
|
111
|
-
return googleapiclient.discovery.build('serviceusage', 'v1', credentials=credentials, cache_discovery=False)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def _initialize_resources(credentials: GoogleCredentials) -> Resource:
|
|
115
|
-
"""
|
|
116
|
-
Create namedtuple of all resource objects necessary for GCP data gathering.
|
|
117
|
-
:param credentials: The GoogleCredentials object
|
|
118
|
-
:return: namedtuple of all resource objects
|
|
119
|
-
"""
|
|
120
|
-
return Resources(
|
|
121
|
-
crm_v1=_get_crm_resource_v1(credentials),
|
|
122
|
-
crm_v2=_get_crm_resource_v2(credentials),
|
|
123
|
-
compute=_get_compute_resource(credentials),
|
|
124
|
-
storage=_get_storage_resource(credentials),
|
|
125
|
-
container=_get_container_resource(credentials),
|
|
126
|
-
serviceusage=_get_serviceusage_resource(credentials),
|
|
127
|
-
dns=_get_dns_resource(credentials),
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
|
|
131
58
|
def _services_enabled_on_project(serviceusage: Resource, project_id: str) -> Set:
|
|
132
59
|
"""
|
|
133
60
|
Return a list of all Google API services that are enabled on the given project ID.
|
|
@@ -138,16 +65,22 @@ def _services_enabled_on_project(serviceusage: Resource, project_id: str) -> Set
|
|
|
138
65
|
:return: A set of services that are enabled on the project
|
|
139
66
|
"""
|
|
140
67
|
try:
|
|
141
|
-
req = serviceusage.services().list(
|
|
68
|
+
req = serviceusage.services().list(
|
|
69
|
+
parent=f"projects/{project_id}",
|
|
70
|
+
filter="state:ENABLED",
|
|
71
|
+
)
|
|
142
72
|
services = set()
|
|
143
73
|
while req is not None:
|
|
144
74
|
res = req.execute()
|
|
145
|
-
if
|
|
146
|
-
services.update({svc[
|
|
147
|
-
req = serviceusage.services().list_next(
|
|
75
|
+
if "services" in res:
|
|
76
|
+
services.update({svc["config"]["name"] for svc in res["services"]})
|
|
77
|
+
req = serviceusage.services().list_next(
|
|
78
|
+
previous_request=req,
|
|
79
|
+
previous_response=res,
|
|
80
|
+
)
|
|
148
81
|
return services
|
|
149
|
-
except
|
|
150
|
-
http_error = json.loads(http_error.content.decode(
|
|
82
|
+
except HttpError as http_error:
|
|
83
|
+
http_error = json.loads(http_error.content.decode("utf-8"))
|
|
151
84
|
# This is set to log-level `info` because Google creates many projects under the hood that cartography cannot
|
|
152
85
|
# audit (e.g. adding a script to a Google spreadsheet causes a project to get created) and we don't need to emit
|
|
153
86
|
# a warning for these projects.
|
|
@@ -159,112 +92,385 @@ def _services_enabled_on_project(serviceusage: Resource, project_id: str) -> Set
|
|
|
159
92
|
return set()
|
|
160
93
|
|
|
161
94
|
|
|
162
|
-
def
|
|
163
|
-
neo4j_session: neo4j.Session,
|
|
95
|
+
def _sync_project_resources(
|
|
96
|
+
neo4j_session: neo4j.Session,
|
|
97
|
+
projects: List[Dict],
|
|
98
|
+
gcp_update_tag: int,
|
|
164
99
|
common_job_parameters: Dict,
|
|
100
|
+
credentials: GoogleCredentials,
|
|
165
101
|
) -> None:
|
|
166
102
|
"""
|
|
167
|
-
|
|
103
|
+
Syncs GCP service-specific resources (Compute, Storage, GKE, DNS, IAM) for each project.
|
|
168
104
|
:param neo4j_session: The Neo4j session
|
|
169
|
-
:param
|
|
170
|
-
:param project_id: The project ID number to sync. See the `projectId` field in
|
|
171
|
-
https://cloud.google.com/resource-manager/reference/rest/v1/projects
|
|
105
|
+
:param projects: A list of projects containing at minimum a "projectId" field.
|
|
172
106
|
:param gcp_update_tag: The timestamp value to set our new Neo4j nodes with
|
|
173
107
|
:param common_job_parameters: Other parameters sent to Neo4j
|
|
108
|
+
:param credentials: GCP credentials to use for API calls.
|
|
174
109
|
:return: Nothing
|
|
175
110
|
"""
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
This is the returned data from `crm.get_gcp_projects()`.
|
|
199
|
-
See https://cloud.google.com/resource-manager/reference/rest/v1/projects.
|
|
200
|
-
:param gcp_update_tag: The timestamp value to set our new Neo4j nodes with
|
|
201
|
-
:param common_job_parameters: Other parameters sent to Neo4j
|
|
202
|
-
:return: Nothing
|
|
203
|
-
"""
|
|
204
|
-
logger.info("Syncing %d GCP projects.", len(projects))
|
|
205
|
-
crm.sync_gcp_projects(neo4j_session, projects, gcp_update_tag, common_job_parameters)
|
|
111
|
+
logger.info("Syncing resources for %d GCP projects.", len(projects))
|
|
112
|
+
|
|
113
|
+
# Cloud Asset Inventory (CAI) clients are lazily initialized and reused across all projects.
|
|
114
|
+
# CAI is used for:
|
|
115
|
+
# 1. Fallback IAM sync when IAM API is disabled on target projects (cai_rest_client)
|
|
116
|
+
# 2. Policy bindings sync (cai_grpc_client)
|
|
117
|
+
#
|
|
118
|
+
# Note: We do NOT explicitly set a quota project for CAI clients. Google's default behavior
|
|
119
|
+
# will use the service account's host project for quota/billing, which doesn't require
|
|
120
|
+
# the serviceusage.serviceUsageConsumer permission.
|
|
121
|
+
cai_rest_client: Optional[Resource] = None # REST client for asset listing
|
|
122
|
+
cai_grpc_client: Optional[AssetServiceClient] = None # gRPC client for policy APIs
|
|
123
|
+
cai_enabled_on_first_project: Optional[bool] = (
|
|
124
|
+
None # Cached check for CAI enablement
|
|
125
|
+
)
|
|
126
|
+
policy_bindings_permission_ok: Optional[bool] = (
|
|
127
|
+
None # Track if we have permission for policy bindings
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Predefined roles are global (not project-specific), so we fetch them once
|
|
131
|
+
# and reuse them for all target projects that use the CAI fallback.
|
|
132
|
+
predefined_roles: Optional[List[Dict]] = None
|
|
206
133
|
|
|
134
|
+
# Per-project sync across services
|
|
207
135
|
for project in projects:
|
|
208
|
-
project_id = project[
|
|
209
|
-
|
|
210
|
-
|
|
136
|
+
project_id = project["projectId"]
|
|
137
|
+
common_job_parameters["PROJECT_ID"] = project_id
|
|
138
|
+
enabled_services = _services_enabled_on_project(
|
|
139
|
+
build_client("serviceusage", "v1", credentials=credentials),
|
|
140
|
+
project_id,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
if service_names.compute in enabled_services:
|
|
144
|
+
logger.info("Syncing GCP project %s for Compute.", project_id)
|
|
145
|
+
compute_cred = build_client("compute", "v1", credentials=credentials)
|
|
146
|
+
compute.sync(
|
|
147
|
+
neo4j_session,
|
|
148
|
+
compute_cred,
|
|
149
|
+
project_id,
|
|
150
|
+
gcp_update_tag,
|
|
151
|
+
common_job_parameters,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
if service_names.storage in enabled_services:
|
|
155
|
+
logger.info("Syncing GCP project %s for Storage.", project_id)
|
|
156
|
+
storage_cred = build_client("storage", "v1", credentials=credentials)
|
|
157
|
+
storage.sync_gcp_buckets(
|
|
158
|
+
neo4j_session,
|
|
159
|
+
storage_cred,
|
|
160
|
+
project_id,
|
|
161
|
+
gcp_update_tag,
|
|
162
|
+
common_job_parameters,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
if service_names.gke in enabled_services:
|
|
166
|
+
logger.info("Syncing GCP project %s for GKE.", project_id)
|
|
167
|
+
container_cred = build_client("container", "v1", credentials=credentials)
|
|
168
|
+
gke.sync_gke_clusters(
|
|
169
|
+
neo4j_session,
|
|
170
|
+
container_cred,
|
|
171
|
+
project_id,
|
|
172
|
+
gcp_update_tag,
|
|
173
|
+
common_job_parameters,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
if service_names.dns in enabled_services:
|
|
177
|
+
logger.info("Syncing GCP project %s for DNS.", project_id)
|
|
178
|
+
dns_cred = build_client("dns", "v1", credentials=credentials)
|
|
179
|
+
dns.sync(
|
|
180
|
+
neo4j_session,
|
|
181
|
+
dns_cred,
|
|
182
|
+
project_id,
|
|
183
|
+
gcp_update_tag,
|
|
184
|
+
common_job_parameters,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
if service_names.iam in enabled_services:
|
|
188
|
+
logger.info("Syncing GCP project %s for IAM.", project_id)
|
|
189
|
+
iam_cred = build_client("iam", "v1", credentials=credentials)
|
|
190
|
+
iam.sync(
|
|
191
|
+
neo4j_session,
|
|
192
|
+
iam_cred,
|
|
193
|
+
project_id,
|
|
194
|
+
gcp_update_tag,
|
|
195
|
+
common_job_parameters,
|
|
196
|
+
)
|
|
197
|
+
else:
|
|
198
|
+
# Fallback to Cloud Asset Inventory even if the target project does not have the IAM API enabled.
|
|
199
|
+
# CAI uses the service account's host project for quota by default (no explicit quota project needed).
|
|
200
|
+
# Lazily initialize the CAI REST client once and reuse it for all projects.
|
|
201
|
+
if cai_rest_client is None:
|
|
202
|
+
cai_rest_client = build_client(
|
|
203
|
+
"cloudasset",
|
|
204
|
+
"v1",
|
|
205
|
+
credentials=credentials,
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
# Fetch predefined roles once for CAI fallback (they're global, not project-specific)
|
|
209
|
+
if predefined_roles is None:
|
|
210
|
+
logger.info("Fetching predefined IAM roles for CAI fallback")
|
|
211
|
+
iam_client = build_client("iam", "v1", credentials=credentials)
|
|
212
|
+
predefined_roles = iam.get_gcp_predefined_roles(iam_client)
|
|
213
|
+
logger.info(
|
|
214
|
+
"Fetched %d predefined IAM roles",
|
|
215
|
+
len(predefined_roles),
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
logger.info(
|
|
219
|
+
"IAM API not enabled. Attempting IAM sync for project %s via Cloud Asset Inventory.",
|
|
220
|
+
project_id,
|
|
221
|
+
)
|
|
222
|
+
try:
|
|
223
|
+
cai.sync(
|
|
224
|
+
neo4j_session,
|
|
225
|
+
cai_rest_client,
|
|
226
|
+
project_id,
|
|
227
|
+
gcp_update_tag,
|
|
228
|
+
common_job_parameters,
|
|
229
|
+
predefined_roles=predefined_roles,
|
|
230
|
+
)
|
|
231
|
+
except HttpError as e:
|
|
232
|
+
if e.resp.status == 403:
|
|
233
|
+
logger.warning(
|
|
234
|
+
"CAI fallback skipped for project %s: %s. "
|
|
235
|
+
"Ensure Cloud Asset API is enabled and roles/cloudasset.viewer is granted.",
|
|
236
|
+
project_id,
|
|
237
|
+
e.reason,
|
|
238
|
+
)
|
|
239
|
+
else:
|
|
240
|
+
raise
|
|
241
|
+
if service_names.bigtable in enabled_services:
|
|
242
|
+
logger.info(f"Syncing GCP project {project_id} for Bigtable.")
|
|
243
|
+
bigtable_client = build_client(
|
|
244
|
+
"bigtableadmin", "v2", credentials=credentials
|
|
245
|
+
)
|
|
246
|
+
instances_raw = bigtable_instance.sync_bigtable_instances(
|
|
247
|
+
neo4j_session,
|
|
248
|
+
bigtable_client,
|
|
249
|
+
project_id,
|
|
250
|
+
gcp_update_tag,
|
|
251
|
+
common_job_parameters,
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
if instances_raw:
|
|
255
|
+
clusters_raw = bigtable_cluster.sync_bigtable_clusters(
|
|
256
|
+
neo4j_session,
|
|
257
|
+
bigtable_client,
|
|
258
|
+
instances_raw,
|
|
259
|
+
project_id,
|
|
260
|
+
gcp_update_tag,
|
|
261
|
+
common_job_parameters,
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
bigtable_table.sync_bigtable_tables(
|
|
265
|
+
neo4j_session,
|
|
266
|
+
bigtable_client,
|
|
267
|
+
instances_raw,
|
|
268
|
+
project_id,
|
|
269
|
+
gcp_update_tag,
|
|
270
|
+
common_job_parameters,
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
bigtable_app_profile.sync_bigtable_app_profiles(
|
|
274
|
+
neo4j_session,
|
|
275
|
+
bigtable_client,
|
|
276
|
+
instances_raw,
|
|
277
|
+
project_id,
|
|
278
|
+
gcp_update_tag,
|
|
279
|
+
common_job_parameters,
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
if clusters_raw:
|
|
283
|
+
bigtable_backup.sync_bigtable_backups(
|
|
284
|
+
neo4j_session,
|
|
285
|
+
bigtable_client,
|
|
286
|
+
clusters_raw,
|
|
287
|
+
project_id,
|
|
288
|
+
gcp_update_tag,
|
|
289
|
+
common_job_parameters,
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
# Policy bindings sync uses CAI gRPC client.
|
|
293
|
+
# We attempt policy bindings for all projects unless we've already encountered a permission error.
|
|
294
|
+
# CAI uses the service account's host project for quota by default.
|
|
295
|
+
if policy_bindings_permission_ok is not False:
|
|
296
|
+
# Check if CAI is enabled (cached after first check on first project)
|
|
297
|
+
if cai_enabled_on_first_project is None:
|
|
298
|
+
first_project_services = _services_enabled_on_project(
|
|
299
|
+
build_client("serviceusage", "v1", credentials=credentials),
|
|
300
|
+
project_id,
|
|
301
|
+
)
|
|
302
|
+
cai_enabled_on_first_project = (
|
|
303
|
+
service_names.cai in first_project_services
|
|
304
|
+
)
|
|
305
|
+
if cai_enabled_on_first_project:
|
|
306
|
+
logger.info(
|
|
307
|
+
"CAI enabled, will sync policy bindings for all projects.",
|
|
308
|
+
)
|
|
309
|
+
else:
|
|
310
|
+
logger.info(
|
|
311
|
+
"CAI not enabled on project %s, skipping policy bindings sync. "
|
|
312
|
+
"Enable the Cloud Asset Inventory API to sync IAM policy bindings.",
|
|
313
|
+
project_id,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
if cai_enabled_on_first_project:
|
|
317
|
+
# Lazily initialize CAI gRPC client for policy bindings.
|
|
318
|
+
if cai_grpc_client is None:
|
|
319
|
+
cai_grpc_client = build_asset_client(
|
|
320
|
+
credentials=credentials,
|
|
321
|
+
)
|
|
322
|
+
logger.info(
|
|
323
|
+
"Syncing IAM policies for GCP project %s.",
|
|
324
|
+
project_id,
|
|
325
|
+
)
|
|
326
|
+
success = policy_bindings.sync(
|
|
327
|
+
neo4j_session,
|
|
328
|
+
project_id,
|
|
329
|
+
gcp_update_tag,
|
|
330
|
+
common_job_parameters,
|
|
331
|
+
cai_grpc_client,
|
|
332
|
+
)
|
|
333
|
+
# Track if we have permission. Once set to False (permission denied),
|
|
334
|
+
# the outer condition will skip policy_bindings for remaining projects.
|
|
335
|
+
if not success:
|
|
336
|
+
policy_bindings_permission_ok = False
|
|
337
|
+
|
|
338
|
+
permission_relationships.sync(
|
|
339
|
+
neo4j_session,
|
|
340
|
+
project_id,
|
|
341
|
+
gcp_update_tag,
|
|
342
|
+
common_job_parameters,
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
del common_job_parameters["PROJECT_ID"]
|
|
211
346
|
|
|
212
347
|
|
|
213
348
|
@timeit
|
|
214
|
-
def start_gcp_ingestion(
|
|
349
|
+
def start_gcp_ingestion(
|
|
350
|
+
neo4j_session: neo4j.Session,
|
|
351
|
+
config: Config,
|
|
352
|
+
credentials: Optional[GoogleCredentials] = None,
|
|
353
|
+
) -> None:
|
|
215
354
|
"""
|
|
216
355
|
Starts the GCP ingestion process by initializing Google Application Default Credentials, creating the necessary
|
|
217
356
|
resource objects, listing all GCP organizations and projects available to the GCP identity, and supplying that
|
|
218
357
|
context to all intel modules.
|
|
219
358
|
:param neo4j_session: The Neo4j session
|
|
220
359
|
:param config: A `cartography.config` object
|
|
360
|
+
:param credentials: Optional GCP credentials. If not provided, ADC will be used.
|
|
221
361
|
:return: Nothing
|
|
222
362
|
"""
|
|
363
|
+
# Initialize credentials from ADC if not provided. This ensures we have a single
|
|
364
|
+
# credentials object used consistently across all API clients.
|
|
365
|
+
if credentials is None:
|
|
366
|
+
credentials = get_gcp_credentials()
|
|
367
|
+
if credentials is None:
|
|
368
|
+
raise RuntimeError(
|
|
369
|
+
"GCP credentials are not available; cannot start GCP ingestion."
|
|
370
|
+
)
|
|
371
|
+
|
|
223
372
|
common_job_parameters = {
|
|
224
373
|
"UPDATE_TAG": config.update_tag,
|
|
374
|
+
"gcp_permission_relationships_file": config.gcp_permission_relationships_file,
|
|
225
375
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
376
|
+
|
|
377
|
+
# IMPORTANT: We defer cleanup for hierarchical resources (orgs, folders, projects) and run them
|
|
378
|
+
# in reverse order. This prevents orphaned nodes when a parent is deleted.
|
|
379
|
+
# Without this, deleting an org would break its relationships to projects/folders, leaving them
|
|
380
|
+
# disconnected and unable to be cleaned up by their own cleanup jobs.
|
|
381
|
+
#
|
|
382
|
+
# Order of operations:
|
|
383
|
+
# 1. Sync all orgs
|
|
384
|
+
# 2. For each org:
|
|
385
|
+
# a. Sync folders and projects
|
|
386
|
+
# b. Sync project resources (with immediate cleanup)
|
|
387
|
+
# c. Clean up projects and folders for this org
|
|
388
|
+
# 3. Clean up all orgs at the end
|
|
389
|
+
#
|
|
390
|
+
# This ensures children are cleaned up before their parents.
|
|
391
|
+
|
|
392
|
+
orgs = sync_gcp_organizations(
|
|
393
|
+
neo4j_session,
|
|
394
|
+
config.update_tag,
|
|
395
|
+
common_job_parameters,
|
|
396
|
+
credentials=credentials,
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
# Track org cleanup jobs to run at the very end
|
|
400
|
+
org_cleanup_jobs = []
|
|
401
|
+
|
|
402
|
+
# For each org, sync its folders and projects (as sub-resources), then ingest per-project services
|
|
403
|
+
for org in orgs:
|
|
404
|
+
org_resource_name = org.get("name", "") # e.g., organizations/123456789012
|
|
405
|
+
if not org_resource_name or "/" not in org_resource_name:
|
|
406
|
+
logger.error(f"Invalid org resource name: {org_resource_name}")
|
|
407
|
+
continue
|
|
408
|
+
|
|
409
|
+
# Store the full resource name for cleanup operations
|
|
410
|
+
common_job_parameters["ORG_RESOURCE_NAME"] = org_resource_name
|
|
411
|
+
|
|
412
|
+
# Sync folders under org
|
|
413
|
+
folders = sync_gcp_folders(
|
|
414
|
+
neo4j_session,
|
|
415
|
+
config.update_tag,
|
|
416
|
+
common_job_parameters,
|
|
417
|
+
org_resource_name,
|
|
418
|
+
credentials=credentials,
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
# Sync projects under org and each folder
|
|
422
|
+
projects = sync_gcp_projects(
|
|
423
|
+
neo4j_session,
|
|
424
|
+
org_resource_name,
|
|
425
|
+
folders,
|
|
426
|
+
config.update_tag,
|
|
427
|
+
common_job_parameters,
|
|
428
|
+
credentials=credentials,
|
|
241
429
|
)
|
|
242
|
-
return
|
|
243
430
|
|
|
244
|
-
|
|
431
|
+
# Ingest per-project resources (these run their own cleanup immediately since they're leaf nodes)
|
|
432
|
+
_sync_project_resources(
|
|
433
|
+
neo4j_session,
|
|
434
|
+
projects,
|
|
435
|
+
config.update_tag,
|
|
436
|
+
common_job_parameters,
|
|
437
|
+
credentials=credentials,
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
# Clean up projects and folders for this org (children before parents)
|
|
441
|
+
logger.debug(f"Running cleanup for projects and folders in {org_resource_name}")
|
|
442
|
+
GraphJob.from_node_schema(GCPProjectSchema(), common_job_parameters).run(
|
|
443
|
+
neo4j_session
|
|
444
|
+
)
|
|
445
|
+
GraphJob.from_node_schema(GCPFolderSchema(), common_job_parameters).run(
|
|
446
|
+
neo4j_session
|
|
447
|
+
)
|
|
245
448
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
crm.sync_gcp_folders(neo4j_session, resources.crm_v2, config.update_tag, common_job_parameters)
|
|
449
|
+
# Save org cleanup job for later
|
|
450
|
+
org_cleanup_jobs.append((GCPOrganizationSchema, dict(common_job_parameters)))
|
|
249
451
|
|
|
250
|
-
|
|
452
|
+
# Remove org ID from common job parameters after processing
|
|
453
|
+
del common_job_parameters["ORG_RESOURCE_NAME"]
|
|
251
454
|
|
|
252
|
-
|
|
455
|
+
# Run all org cleanup jobs at the very end, after all children have been cleaned up
|
|
456
|
+
logger.info("Running cleanup for GCP organizations")
|
|
457
|
+
for schema_class, params in org_cleanup_jobs:
|
|
458
|
+
GraphJob.from_node_schema(schema_class(), params).run(neo4j_session)
|
|
253
459
|
|
|
254
460
|
run_analysis_job(
|
|
255
|
-
|
|
461
|
+
"gcp_compute_asset_inet_exposure.json",
|
|
256
462
|
neo4j_session,
|
|
257
463
|
common_job_parameters,
|
|
258
464
|
)
|
|
259
465
|
|
|
260
466
|
run_analysis_job(
|
|
261
|
-
|
|
467
|
+
"gcp_gke_asset_exposure.json",
|
|
262
468
|
neo4j_session,
|
|
263
469
|
common_job_parameters,
|
|
264
470
|
)
|
|
265
471
|
|
|
266
472
|
run_analysis_job(
|
|
267
|
-
|
|
473
|
+
"gcp_gke_basic_auth.json",
|
|
268
474
|
neo4j_session,
|
|
269
475
|
common_job_parameters,
|
|
270
476
|
)
|