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/compute.py
CHANGED
|
@@ -11,14 +11,23 @@ from typing import Optional
|
|
|
11
11
|
from typing import Set
|
|
12
12
|
|
|
13
13
|
import neo4j
|
|
14
|
-
from googleapiclient.discovery import HttpError
|
|
15
14
|
from googleapiclient.discovery import Resource
|
|
15
|
+
from googleapiclient.errors import HttpError
|
|
16
16
|
|
|
17
|
+
from cartography.client.core.tx import execute_write_with_retry
|
|
18
|
+
from cartography.client.core.tx import load
|
|
19
|
+
from cartography.client.core.tx import run_write_query
|
|
20
|
+
from cartography.graph.job import GraphJob
|
|
21
|
+
from cartography.models.gcp.compute.vpc import GCPVpcSchema
|
|
17
22
|
from cartography.util import run_cleanup_job
|
|
18
23
|
from cartography.util import timeit
|
|
19
24
|
|
|
20
25
|
logger = logging.getLogger(__name__)
|
|
21
|
-
InstanceUriPrefix = namedtuple(
|
|
26
|
+
InstanceUriPrefix = namedtuple("InstanceUriPrefix", "zone_name project_id")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# Maximum number of retries for Google API requests
|
|
30
|
+
GOOGLE_API_NUM_RETRIES = 5
|
|
22
31
|
|
|
23
32
|
|
|
24
33
|
def _get_error_reason(http_error: HttpError) -> str:
|
|
@@ -33,19 +42,23 @@ def _get_error_reason(http_error: HttpError) -> str:
|
|
|
33
42
|
:return: The error reason as a string
|
|
34
43
|
"""
|
|
35
44
|
try:
|
|
36
|
-
data = json.loads(http_error.content.decode(
|
|
45
|
+
data = json.loads(http_error.content.decode("utf-8"))
|
|
37
46
|
if isinstance(data, dict):
|
|
38
|
-
reason = data[
|
|
47
|
+
reason = data["error"]["errors"][0]["reason"]
|
|
39
48
|
else:
|
|
40
|
-
reason = data[0][
|
|
49
|
+
reason = data[0]["error"]["errors"]["reason"]
|
|
41
50
|
except (UnicodeDecodeError, ValueError, KeyError):
|
|
42
51
|
logger.warning(f"HttpError: {data}")
|
|
43
|
-
return
|
|
52
|
+
return ""
|
|
44
53
|
return reason
|
|
45
54
|
|
|
46
55
|
|
|
47
56
|
@timeit
|
|
48
|
-
def get_zones_in_project(
|
|
57
|
+
def get_zones_in_project(
|
|
58
|
+
project_id: str,
|
|
59
|
+
compute: Resource,
|
|
60
|
+
max_results: Optional[int] = None,
|
|
61
|
+
) -> Optional[List[Dict]]:
|
|
49
62
|
"""
|
|
50
63
|
Return the zones where the Compute Engine API is enabled for the given project_id.
|
|
51
64
|
See https://cloud.google.com/compute/docs/reference/rest/v1/zones and
|
|
@@ -59,11 +72,11 @@ def get_zones_in_project(project_id: str, compute: Resource, max_results: Option
|
|
|
59
72
|
"""
|
|
60
73
|
try:
|
|
61
74
|
req = compute.zones().list(project=project_id, maxResults=max_results)
|
|
62
|
-
res = req.execute()
|
|
63
|
-
return res[
|
|
75
|
+
res = req.execute(num_retries=GOOGLE_API_NUM_RETRIES)
|
|
76
|
+
return res["items"]
|
|
64
77
|
except HttpError as e:
|
|
65
78
|
reason = _get_error_reason(e)
|
|
66
|
-
if reason ==
|
|
79
|
+
if reason == "accessNotConfigured":
|
|
67
80
|
logger.info(
|
|
68
81
|
(
|
|
69
82
|
"Google Compute Engine API access is not configured for project %s; skipping. "
|
|
@@ -73,17 +86,14 @@ def get_zones_in_project(project_id: str, compute: Resource, max_results: Option
|
|
|
73
86
|
e,
|
|
74
87
|
)
|
|
75
88
|
return None
|
|
76
|
-
elif reason ==
|
|
89
|
+
elif reason == "notFound":
|
|
77
90
|
logger.info(
|
|
78
|
-
(
|
|
79
|
-
"Project %s returned a 404 not found error. "
|
|
80
|
-
"Full details: %s"
|
|
81
|
-
),
|
|
91
|
+
("Project %s returned a 404 not found error. " "Full details: %s"),
|
|
82
92
|
project_id,
|
|
83
93
|
e,
|
|
84
94
|
)
|
|
85
95
|
return None
|
|
86
|
-
elif reason ==
|
|
96
|
+
elif reason == "forbidden":
|
|
87
97
|
logger.info(
|
|
88
98
|
(
|
|
89
99
|
"Your GCP identity does not have the compute.zones.list permission for project %s; skipping "
|
|
@@ -98,7 +108,11 @@ def get_zones_in_project(project_id: str, compute: Resource, max_results: Option
|
|
|
98
108
|
|
|
99
109
|
|
|
100
110
|
@timeit
|
|
101
|
-
def get_gcp_instance_responses(
|
|
111
|
+
def get_gcp_instance_responses(
|
|
112
|
+
project_id: str,
|
|
113
|
+
zones: Optional[List[Dict]],
|
|
114
|
+
compute: Resource,
|
|
115
|
+
) -> List[Resource]:
|
|
102
116
|
"""
|
|
103
117
|
Return list of GCP instance response objects for a given project and list of zones
|
|
104
118
|
:param project_id: The project ID
|
|
@@ -111,23 +125,54 @@ def get_gcp_instance_responses(project_id: str, zones: Optional[List[Dict]], com
|
|
|
111
125
|
return []
|
|
112
126
|
response_objects: List[Resource] = []
|
|
113
127
|
for zone in zones:
|
|
114
|
-
req = compute.instances().list(project=project_id, zone=zone[
|
|
115
|
-
|
|
116
|
-
|
|
128
|
+
req = compute.instances().list(project=project_id, zone=zone["name"])
|
|
129
|
+
try:
|
|
130
|
+
res = req.execute(num_retries=GOOGLE_API_NUM_RETRIES)
|
|
131
|
+
response_objects.append(res)
|
|
132
|
+
except HttpError as e:
|
|
133
|
+
reason = _get_error_reason(e)
|
|
134
|
+
if reason in {"backendError", "rateLimitExceeded", "internalError"}:
|
|
135
|
+
logger.warning(
|
|
136
|
+
"Transient error listing instances for project %s zone %s: %s; skipping this zone.",
|
|
137
|
+
project_id,
|
|
138
|
+
zone.get("name"),
|
|
139
|
+
e,
|
|
140
|
+
)
|
|
141
|
+
continue
|
|
142
|
+
raise
|
|
117
143
|
return response_objects
|
|
118
144
|
|
|
119
145
|
|
|
120
146
|
@timeit
|
|
121
|
-
def get_gcp_subnets(projectid: str, region: str, compute: Resource) ->
|
|
147
|
+
def get_gcp_subnets(projectid: str, region: str, compute: Resource) -> Dict:
|
|
122
148
|
"""
|
|
123
|
-
Return list of all subnets in the given projectid and region
|
|
124
|
-
|
|
149
|
+
Return list of all subnets in the given projectid and region. If the API
|
|
150
|
+
call times out mid-pagination, return any subnets gathered so far rather than
|
|
151
|
+
bubbling the error up to the caller.
|
|
152
|
+
:param projectid: The project ID
|
|
125
153
|
:param region: The region to pull subnets from
|
|
126
154
|
:param compute: The compute resource object created by googleapiclient.discovery.build()
|
|
127
155
|
:return: Response object containing data on all GCP subnets for a given project
|
|
128
156
|
"""
|
|
129
157
|
req = compute.subnetworks().list(project=projectid, region=region)
|
|
130
|
-
|
|
158
|
+
items: List[Dict] = []
|
|
159
|
+
response_id = f"projects/{projectid}/regions/{region}/subnetworks"
|
|
160
|
+
while req is not None:
|
|
161
|
+
try:
|
|
162
|
+
res = req.execute(num_retries=GOOGLE_API_NUM_RETRIES)
|
|
163
|
+
except TimeoutError:
|
|
164
|
+
logger.warning(
|
|
165
|
+
"GCP: subnetworks.list for project %s region %s timed out; continuing with partial data.",
|
|
166
|
+
projectid,
|
|
167
|
+
region,
|
|
168
|
+
)
|
|
169
|
+
break
|
|
170
|
+
items.extend(res.get("items", []))
|
|
171
|
+
response_id = res.get("id", response_id)
|
|
172
|
+
req = compute.subnetworks().list_next(
|
|
173
|
+
previous_request=req, previous_response=res
|
|
174
|
+
)
|
|
175
|
+
return {"id": response_id, "items": items}
|
|
131
176
|
|
|
132
177
|
|
|
133
178
|
@timeit
|
|
@@ -139,11 +184,15 @@ def get_gcp_vpcs(projectid: str, compute: Resource) -> Resource:
|
|
|
139
184
|
:return: VPC response object
|
|
140
185
|
"""
|
|
141
186
|
req = compute.networks().list(project=projectid)
|
|
142
|
-
return req.execute()
|
|
187
|
+
return req.execute(num_retries=GOOGLE_API_NUM_RETRIES)
|
|
143
188
|
|
|
144
189
|
|
|
145
190
|
@timeit
|
|
146
|
-
def get_gcp_regional_forwarding_rules(
|
|
191
|
+
def get_gcp_regional_forwarding_rules(
|
|
192
|
+
project_id: str,
|
|
193
|
+
region: str,
|
|
194
|
+
compute: Resource,
|
|
195
|
+
) -> Resource:
|
|
147
196
|
"""
|
|
148
197
|
Return list of all regional forwarding rules in the given project_id and region
|
|
149
198
|
:param project_id: The project ID
|
|
@@ -152,7 +201,7 @@ def get_gcp_regional_forwarding_rules(project_id: str, region: str, compute: Res
|
|
|
152
201
|
:return: Response object containing data on all GCP forwarding rules for a given project
|
|
153
202
|
"""
|
|
154
203
|
req = compute.forwardingRules().list(project=project_id, region=region)
|
|
155
|
-
return req.execute()
|
|
204
|
+
return req.execute(num_retries=GOOGLE_API_NUM_RETRIES)
|
|
156
205
|
|
|
157
206
|
|
|
158
207
|
@timeit
|
|
@@ -164,7 +213,7 @@ def get_gcp_global_forwarding_rules(project_id: str, compute: Resource) -> Resou
|
|
|
164
213
|
:return: Response object containing data on all GCP forwarding rules for a given project
|
|
165
214
|
"""
|
|
166
215
|
req = compute.globalForwardingRules().list(project=project_id)
|
|
167
|
-
return req.execute()
|
|
216
|
+
return req.execute(num_retries=GOOGLE_API_NUM_RETRIES)
|
|
168
217
|
|
|
169
218
|
|
|
170
219
|
@timeit
|
|
@@ -176,7 +225,7 @@ def get_gcp_firewall_ingress_rules(project_id: str, compute: Resource) -> Resour
|
|
|
176
225
|
:return: Firewall response object
|
|
177
226
|
"""
|
|
178
227
|
req = compute.firewalls().list(project=project_id, filter='(direction="INGRESS")')
|
|
179
|
-
return req.execute()
|
|
228
|
+
return req.execute(num_retries=GOOGLE_API_NUM_RETRIES)
|
|
180
229
|
|
|
181
230
|
|
|
182
231
|
@timeit
|
|
@@ -189,17 +238,21 @@ def transform_gcp_instances(response_objects: List[Dict]) -> List[Dict]:
|
|
|
189
238
|
"""
|
|
190
239
|
instance_list = []
|
|
191
240
|
for res in response_objects:
|
|
192
|
-
prefix = res[
|
|
241
|
+
prefix = res["id"]
|
|
193
242
|
prefix_fields = _parse_instance_uri_prefix(prefix)
|
|
194
243
|
|
|
195
|
-
for instance in res.get(
|
|
196
|
-
instance[
|
|
197
|
-
instance[
|
|
198
|
-
instance[
|
|
244
|
+
for instance in res.get("items", []):
|
|
245
|
+
instance["partial_uri"] = f"{prefix}/{instance['name']}"
|
|
246
|
+
instance["project_id"] = prefix_fields.project_id
|
|
247
|
+
instance["zone_name"] = prefix_fields.zone_name
|
|
199
248
|
|
|
200
|
-
for nic in instance.get(
|
|
201
|
-
nic[
|
|
202
|
-
|
|
249
|
+
for nic in instance.get("networkInterfaces", []):
|
|
250
|
+
nic["subnet_partial_uri"] = _parse_compute_full_uri_to_partial_uri(
|
|
251
|
+
nic["subnetwork"],
|
|
252
|
+
)
|
|
253
|
+
nic["vpc_partial_uri"] = _parse_compute_full_uri_to_partial_uri(
|
|
254
|
+
nic["network"],
|
|
255
|
+
)
|
|
203
256
|
|
|
204
257
|
instance_list.append(instance)
|
|
205
258
|
return instance_list
|
|
@@ -211,7 +264,7 @@ def _parse_instance_uri_prefix(prefix: str) -> InstanceUriPrefix:
|
|
|
211
264
|
:param prefix: String of the form `projects/{project}/zones/{zone}/instances`
|
|
212
265
|
:return: namedtuple with fields project_id and zone_name
|
|
213
266
|
"""
|
|
214
|
-
split_list = prefix.split(
|
|
267
|
+
split_list = prefix.split("/")
|
|
215
268
|
|
|
216
269
|
return InstanceUriPrefix(
|
|
217
270
|
project_id=split_list[1],
|
|
@@ -219,7 +272,7 @@ def _parse_instance_uri_prefix(prefix: str) -> InstanceUriPrefix:
|
|
|
219
272
|
)
|
|
220
273
|
|
|
221
274
|
|
|
222
|
-
def _parse_compute_full_uri_to_partial_uri(full_uri: str, version: str =
|
|
275
|
+
def _parse_compute_full_uri_to_partial_uri(full_uri: str, version: str = "v1") -> str:
|
|
223
276
|
"""
|
|
224
277
|
Take a GCP Compute object's self_link of the form
|
|
225
278
|
`https://www.googleapis.com/compute/{version}/projects/{project}/{location specifier}/{subtype}/{resource name}`
|
|
@@ -229,7 +282,7 @@ def _parse_compute_full_uri_to_partial_uri(full_uri: str, version: str = 'v1') -
|
|
|
229
282
|
:param version: The version number; default to v1 since at the time of this writing v1 is the only Compute API.
|
|
230
283
|
:return: Partial URI `{project}/{location specifier}/{subtype}/{resource name}`
|
|
231
284
|
"""
|
|
232
|
-
return full_uri.split(f
|
|
285
|
+
return full_uri.split(f"compute/{version}/")[1]
|
|
233
286
|
|
|
234
287
|
|
|
235
288
|
def _create_gcp_network_tag_id(vpc_partial_uri: str, tag: str) -> str:
|
|
@@ -251,19 +304,22 @@ def transform_gcp_vpcs(vpc_res: Dict) -> List[Dict]:
|
|
|
251
304
|
vpc_list = []
|
|
252
305
|
|
|
253
306
|
# prefix has the form `projects/{project ID}/global/networks`
|
|
254
|
-
prefix = vpc_res[
|
|
255
|
-
projectid = prefix.split(
|
|
256
|
-
for v in vpc_res.get(
|
|
307
|
+
prefix = vpc_res["id"]
|
|
308
|
+
projectid = prefix.split("/")[1]
|
|
309
|
+
for v in vpc_res.get("items", []):
|
|
257
310
|
vpc = {}
|
|
258
311
|
partial_uri = f"{prefix}/{v['name']}"
|
|
259
312
|
|
|
260
|
-
vpc[
|
|
261
|
-
vpc[
|
|
262
|
-
vpc[
|
|
263
|
-
vpc[
|
|
264
|
-
vpc[
|
|
265
|
-
vpc[
|
|
266
|
-
vpc[
|
|
313
|
+
vpc["partial_uri"] = partial_uri
|
|
314
|
+
vpc["name"] = v["name"]
|
|
315
|
+
vpc["self_link"] = v["selfLink"]
|
|
316
|
+
vpc["project_id"] = projectid
|
|
317
|
+
vpc["auto_create_subnetworks"] = v.get("autoCreateSubnetworks", None)
|
|
318
|
+
vpc["description"] = v.get("description", None)
|
|
319
|
+
vpc["routing_config_routing_mode"] = v.get("routingConfig", {}).get(
|
|
320
|
+
"routingMode",
|
|
321
|
+
None,
|
|
322
|
+
)
|
|
267
323
|
|
|
268
324
|
vpc_list.append(vpc)
|
|
269
325
|
return vpc_list
|
|
@@ -278,29 +334,29 @@ def transform_gcp_subnets(subnet_res: Dict) -> List[Dict]:
|
|
|
278
334
|
"""
|
|
279
335
|
# The `id` in the response object has the form `projects/{project}/regions/{region}/subnetworks`.
|
|
280
336
|
# We can include this in each subnet object in the list to form the partial_uri later on.
|
|
281
|
-
prefix = subnet_res[
|
|
282
|
-
projectid = prefix.split(
|
|
337
|
+
prefix = subnet_res["id"]
|
|
338
|
+
projectid = prefix.split("/")[1]
|
|
283
339
|
subnet_list: List[Dict] = []
|
|
284
|
-
for s in subnet_res.get(
|
|
340
|
+
for s in subnet_res.get("items", []):
|
|
285
341
|
subnet = {}
|
|
286
342
|
|
|
287
343
|
# Has the form `projects/{project}/regions/{region}/subnetworks/{subnet_name}`
|
|
288
344
|
partial_uri = f"{prefix}/{s['name']}"
|
|
289
|
-
subnet[
|
|
290
|
-
subnet[
|
|
345
|
+
subnet["id"] = partial_uri
|
|
346
|
+
subnet["partial_uri"] = partial_uri
|
|
291
347
|
|
|
292
348
|
# Let's maintain an on-node reference to the VPC that this subnet belongs to.
|
|
293
|
-
subnet[
|
|
294
|
-
subnet[
|
|
349
|
+
subnet["vpc_self_link"] = s["network"]
|
|
350
|
+
subnet["vpc_partial_uri"] = _parse_compute_full_uri_to_partial_uri(s["network"])
|
|
295
351
|
|
|
296
|
-
subnet[
|
|
297
|
-
subnet[
|
|
352
|
+
subnet["name"] = s["name"]
|
|
353
|
+
subnet["project_id"] = projectid
|
|
298
354
|
# Region looks like "https://www.googleapis.com/compute/v1/projects/{project}/regions/{region name}"
|
|
299
|
-
subnet[
|
|
300
|
-
subnet[
|
|
301
|
-
subnet[
|
|
302
|
-
subnet[
|
|
303
|
-
subnet[
|
|
355
|
+
subnet["region"] = s["region"].split("/")[-1]
|
|
356
|
+
subnet["gateway_address"] = s.get("gatewayAddress", None)
|
|
357
|
+
subnet["ip_cidr_range"] = s.get("ipCidrRange", None)
|
|
358
|
+
subnet["self_link"] = s["selfLink"]
|
|
359
|
+
subnet["private_ip_google_access"] = s.get("privateIpGoogleAccess", None)
|
|
304
360
|
|
|
305
361
|
subnet_list.append(subnet)
|
|
306
362
|
return subnet_list
|
|
@@ -314,43 +370,47 @@ def transform_gcp_forwarding_rules(fwd_response: Resource) -> List[Dict]:
|
|
|
314
370
|
:return: A transformed fwd_response
|
|
315
371
|
"""
|
|
316
372
|
fwd_list: List[Dict] = []
|
|
317
|
-
prefix = fwd_response[
|
|
318
|
-
project_id = prefix.split(
|
|
319
|
-
for fwd in fwd_response.get(
|
|
373
|
+
prefix = fwd_response["id"]
|
|
374
|
+
project_id = prefix.split("/")[1]
|
|
375
|
+
for fwd in fwd_response.get("items", []):
|
|
320
376
|
forwarding_rule: Dict[str, Any] = {}
|
|
321
377
|
|
|
322
378
|
fwd_partial_uri = f"{prefix}/{fwd['name']}"
|
|
323
|
-
forwarding_rule[
|
|
324
|
-
forwarding_rule[
|
|
379
|
+
forwarding_rule["id"] = fwd_partial_uri
|
|
380
|
+
forwarding_rule["partial_uri"] = fwd_partial_uri
|
|
325
381
|
|
|
326
|
-
forwarding_rule[
|
|
382
|
+
forwarding_rule["project_id"] = project_id
|
|
327
383
|
# Region looks like "https://www.googleapis.com/compute/v1/projects/{project}/regions/{region name}"
|
|
328
|
-
region = fwd.get(
|
|
329
|
-
forwarding_rule[
|
|
330
|
-
forwarding_rule[
|
|
331
|
-
forwarding_rule[
|
|
332
|
-
forwarding_rule[
|
|
333
|
-
|
|
334
|
-
forwarding_rule[
|
|
335
|
-
forwarding_rule[
|
|
336
|
-
forwarding_rule[
|
|
337
|
-
forwarding_rule[
|
|
338
|
-
forwarding_rule[
|
|
339
|
-
target = fwd.get(
|
|
384
|
+
region = fwd.get("region", None)
|
|
385
|
+
forwarding_rule["region"] = region.split("/")[-1] if region else None
|
|
386
|
+
forwarding_rule["ip_address"] = fwd.get("IPAddress", None)
|
|
387
|
+
forwarding_rule["ip_protocol"] = fwd.get("IPProtocol", None)
|
|
388
|
+
forwarding_rule["allow_global_access"] = fwd.get("allowGlobalAccess", None)
|
|
389
|
+
|
|
390
|
+
forwarding_rule["load_balancing_scheme"] = fwd.get("loadBalancingScheme", None)
|
|
391
|
+
forwarding_rule["name"] = fwd.get("name", None)
|
|
392
|
+
forwarding_rule["port_range"] = fwd.get("portRange", None)
|
|
393
|
+
forwarding_rule["ports"] = fwd.get("ports", None)
|
|
394
|
+
forwarding_rule["self_link"] = fwd.get("selfLink", None)
|
|
395
|
+
target = fwd.get("target", None)
|
|
340
396
|
if target:
|
|
341
|
-
forwarding_rule[
|
|
397
|
+
forwarding_rule["target"] = _parse_compute_full_uri_to_partial_uri(target)
|
|
342
398
|
else:
|
|
343
|
-
forwarding_rule[
|
|
399
|
+
forwarding_rule["target"] = None
|
|
344
400
|
|
|
345
|
-
network = fwd.get(
|
|
401
|
+
network = fwd.get("network", None)
|
|
346
402
|
if network:
|
|
347
|
-
forwarding_rule[
|
|
348
|
-
forwarding_rule[
|
|
403
|
+
forwarding_rule["network"] = network
|
|
404
|
+
forwarding_rule["network_partial_uri"] = (
|
|
405
|
+
_parse_compute_full_uri_to_partial_uri(network)
|
|
406
|
+
)
|
|
349
407
|
|
|
350
|
-
subnetwork = fwd.get(
|
|
408
|
+
subnetwork = fwd.get("subnetwork", None)
|
|
351
409
|
if subnetwork:
|
|
352
|
-
forwarding_rule[
|
|
353
|
-
forwarding_rule[
|
|
410
|
+
forwarding_rule["subnetwork"] = subnetwork
|
|
411
|
+
forwarding_rule["subnetwork_partial_uri"] = (
|
|
412
|
+
_parse_compute_full_uri_to_partial_uri(subnetwork)
|
|
413
|
+
)
|
|
354
414
|
|
|
355
415
|
fwd_list.append(forwarding_rule)
|
|
356
416
|
return fwd_list
|
|
@@ -365,31 +425,45 @@ def transform_gcp_firewall(fw_response: Resource) -> List[Dict]:
|
|
|
365
425
|
:return: List of transformed firewall rule objects.
|
|
366
426
|
"""
|
|
367
427
|
fw_list: List[Dict] = []
|
|
368
|
-
prefix = fw_response[
|
|
369
|
-
for fw in fw_response.get(
|
|
428
|
+
prefix = fw_response["id"]
|
|
429
|
+
for fw in fw_response.get("items", []):
|
|
370
430
|
fw_partial_uri = f"{prefix}/{fw['name']}"
|
|
371
|
-
fw[
|
|
372
|
-
fw[
|
|
431
|
+
fw["id"] = fw_partial_uri
|
|
432
|
+
fw["vpc_partial_uri"] = _parse_compute_full_uri_to_partial_uri(fw["network"])
|
|
373
433
|
|
|
374
|
-
fw[
|
|
375
|
-
fw[
|
|
434
|
+
fw["transformed_allow_list"] = []
|
|
435
|
+
fw["transformed_deny_list"] = []
|
|
376
436
|
# Mark whether this FW is defined on a target service account.
|
|
377
437
|
# In future we will need to ingest GCP IAM objects but for now we simply mark the presence of svc accounts here.
|
|
378
|
-
fw[
|
|
438
|
+
fw["has_target_service_accounts"] = (
|
|
439
|
+
True if "targetServiceAccounts" in fw else False
|
|
440
|
+
)
|
|
379
441
|
|
|
380
|
-
for allow_rule in fw.get(
|
|
381
|
-
transformed_allow_rules = _transform_fw_entry(
|
|
382
|
-
|
|
442
|
+
for allow_rule in fw.get("allowed", []):
|
|
443
|
+
transformed_allow_rules = _transform_fw_entry(
|
|
444
|
+
allow_rule,
|
|
445
|
+
fw_partial_uri,
|
|
446
|
+
is_allow_rule=True,
|
|
447
|
+
)
|
|
448
|
+
fw["transformed_allow_list"].extend(transformed_allow_rules)
|
|
383
449
|
|
|
384
|
-
for deny_rule in fw.get(
|
|
385
|
-
transformed_deny_rules = _transform_fw_entry(
|
|
386
|
-
|
|
450
|
+
for deny_rule in fw.get("denied", []):
|
|
451
|
+
transformed_deny_rules = _transform_fw_entry(
|
|
452
|
+
deny_rule,
|
|
453
|
+
fw_partial_uri,
|
|
454
|
+
is_allow_rule=False,
|
|
455
|
+
)
|
|
456
|
+
fw["transformed_deny_list"].extend(transformed_deny_rules)
|
|
387
457
|
|
|
388
458
|
fw_list.append(fw)
|
|
389
459
|
return fw_list
|
|
390
460
|
|
|
391
461
|
|
|
392
|
-
def _transform_fw_entry(
|
|
462
|
+
def _transform_fw_entry(
|
|
463
|
+
rule: Dict,
|
|
464
|
+
fw_partial_uri: str,
|
|
465
|
+
is_allow_rule: bool,
|
|
466
|
+
) -> List[Dict]:
|
|
393
467
|
"""
|
|
394
468
|
Takes a rule entry from a GCP firewall object's allow or deny list and converts it to a list of one or more
|
|
395
469
|
dicts representing a firewall rule for each port and port range. This format is easier to load into Neo4j.
|
|
@@ -415,21 +489,31 @@ def _transform_fw_entry(rule: Dict, fw_partial_uri: str, is_allow_rule: bool) ->
|
|
|
415
489
|
"""
|
|
416
490
|
result: List[Dict] = []
|
|
417
491
|
# rule['ruleid'] = f"{fw_partial_uri}/"
|
|
418
|
-
protocol = rule[
|
|
492
|
+
protocol = rule["IPProtocol"]
|
|
419
493
|
|
|
420
494
|
# If the protocol covered is TCP or UDP then we need to handle ports
|
|
421
|
-
if protocol ==
|
|
495
|
+
if protocol == "tcp" or protocol == "udp":
|
|
422
496
|
|
|
423
497
|
# If ports are specified then create rules for each port and range
|
|
424
|
-
if
|
|
425
|
-
for port in rule[
|
|
426
|
-
rule = _parse_port_string_to_rule(
|
|
498
|
+
if "ports" in rule:
|
|
499
|
+
for port in rule["ports"]:
|
|
500
|
+
rule = _parse_port_string_to_rule(
|
|
501
|
+
port,
|
|
502
|
+
protocol,
|
|
503
|
+
fw_partial_uri,
|
|
504
|
+
is_allow_rule,
|
|
505
|
+
)
|
|
427
506
|
result.append(rule)
|
|
428
507
|
return result
|
|
429
508
|
|
|
430
509
|
# If ports are not specified then the rule applies to every port
|
|
431
510
|
else:
|
|
432
|
-
rule = _parse_port_string_to_rule(
|
|
511
|
+
rule = _parse_port_string_to_rule(
|
|
512
|
+
"0-65535",
|
|
513
|
+
protocol,
|
|
514
|
+
fw_partial_uri,
|
|
515
|
+
is_allow_rule,
|
|
516
|
+
)
|
|
433
517
|
result.append(rule)
|
|
434
518
|
return result
|
|
435
519
|
|
|
@@ -440,7 +524,12 @@ def _transform_fw_entry(rule: Dict, fw_partial_uri: str, is_allow_rule: bool) ->
|
|
|
440
524
|
return result
|
|
441
525
|
|
|
442
526
|
|
|
443
|
-
def _parse_port_string_to_rule(
|
|
527
|
+
def _parse_port_string_to_rule(
|
|
528
|
+
port: Optional[str],
|
|
529
|
+
protocol: str,
|
|
530
|
+
fw_partial_uri: str,
|
|
531
|
+
is_allow_rule: bool,
|
|
532
|
+
) -> Dict:
|
|
444
533
|
"""
|
|
445
534
|
Takes a string argument representing a GCP firewall rule port or port range and returns a dict that is easier to
|
|
446
535
|
load into Neo4j.
|
|
@@ -467,13 +556,13 @@ def _parse_port_string_to_rule(port: Optional[str], protocol: str, fw_partial_ur
|
|
|
467
556
|
|
|
468
557
|
if port is None:
|
|
469
558
|
# Keep the port range as the empty string
|
|
470
|
-
port_range_str =
|
|
559
|
+
port_range_str = ""
|
|
471
560
|
fromport = None
|
|
472
561
|
toport = None
|
|
473
562
|
else:
|
|
474
563
|
# Case 1 - port range: '12345-12349'.split('-') => ['12345','12349'].
|
|
475
564
|
# Case 2 - single port: '22'.split('-') => ['22'].
|
|
476
|
-
port_split = port.split(
|
|
565
|
+
port_split = port.split("-")
|
|
477
566
|
|
|
478
567
|
# Port range
|
|
479
568
|
if len(port_split) == 2:
|
|
@@ -486,18 +575,22 @@ def _parse_port_string_to_rule(port: Optional[str], protocol: str, fw_partial_ur
|
|
|
486
575
|
fromport = int(port_split[0])
|
|
487
576
|
toport = int(port_split[0])
|
|
488
577
|
|
|
489
|
-
rule_type =
|
|
578
|
+
rule_type = "allow" if is_allow_rule else "deny"
|
|
490
579
|
|
|
491
580
|
return {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
581
|
+
"ruleid": f"{fw_partial_uri}/{rule_type}/{port_range_str}{protocol}",
|
|
582
|
+
"fromport": fromport,
|
|
583
|
+
"toport": toport,
|
|
584
|
+
"protocol": protocol,
|
|
496
585
|
}
|
|
497
586
|
|
|
498
587
|
|
|
499
588
|
@timeit
|
|
500
|
-
def load_gcp_instances(
|
|
589
|
+
def load_gcp_instances(
|
|
590
|
+
neo4j_session: neo4j.Session,
|
|
591
|
+
data: List[Dict],
|
|
592
|
+
gcp_update_tag: int,
|
|
593
|
+
) -> None:
|
|
501
594
|
"""
|
|
502
595
|
Ingest GCP instance objects to Neo4j
|
|
503
596
|
:param neo4j_session: The Neo4j session object
|
|
@@ -528,115 +621,71 @@ def load_gcp_instances(neo4j_session: neo4j.Session, data: List[Dict], gcp_updat
|
|
|
528
621
|
SET r.lastupdated = $gcp_update_tag
|
|
529
622
|
"""
|
|
530
623
|
for instance in data:
|
|
531
|
-
|
|
624
|
+
run_write_query(
|
|
625
|
+
neo4j_session,
|
|
532
626
|
query,
|
|
533
|
-
ProjectId=instance[
|
|
534
|
-
PartialUri=instance[
|
|
535
|
-
SelfLink=instance[
|
|
536
|
-
InstanceName=instance[
|
|
537
|
-
ZoneName=instance[
|
|
538
|
-
Hostname=instance.get(
|
|
539
|
-
Status=instance[
|
|
627
|
+
ProjectId=instance["project_id"],
|
|
628
|
+
PartialUri=instance["partial_uri"],
|
|
629
|
+
SelfLink=instance["selfLink"],
|
|
630
|
+
InstanceName=instance["name"],
|
|
631
|
+
ZoneName=instance["zone_name"],
|
|
632
|
+
Hostname=instance.get("hostname", None),
|
|
633
|
+
Status=instance["status"],
|
|
540
634
|
gcp_update_tag=gcp_update_tag,
|
|
541
635
|
)
|
|
542
636
|
_attach_instance_tags(neo4j_session, instance, gcp_update_tag)
|
|
543
637
|
_attach_gcp_nics(neo4j_session, instance, gcp_update_tag)
|
|
544
|
-
_attach_gcp_vpc(neo4j_session, instance[
|
|
638
|
+
_attach_gcp_vpc(neo4j_session, instance["partial_uri"], gcp_update_tag)
|
|
545
639
|
|
|
546
640
|
|
|
547
641
|
@timeit
|
|
548
|
-
def load_gcp_vpcs(
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
:
|
|
552
|
-
:
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
MERGE(vpc:GCPVpc{id:$PartialUri})
|
|
562
|
-
ON CREATE SET vpc.firstseen = timestamp(),
|
|
563
|
-
vpc.partial_uri = $PartialUri
|
|
564
|
-
SET vpc.self_link = $SelfLink,
|
|
565
|
-
vpc.name = $VpcName,
|
|
566
|
-
vpc.project_id = $ProjectId,
|
|
567
|
-
vpc.auto_create_subnetworks = $AutoCreateSubnetworks,
|
|
568
|
-
vpc.routing_config_routing_mode = $RoutingMode,
|
|
569
|
-
vpc.description = $Description,
|
|
570
|
-
vpc.lastupdated = $gcp_update_tag
|
|
571
|
-
|
|
572
|
-
MERGE (p)-[r:RESOURCE]->(vpc)
|
|
573
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
574
|
-
SET r.lastupdated = $gcp_update_tag
|
|
575
|
-
"""
|
|
576
|
-
for vpc in vpcs:
|
|
577
|
-
neo4j_session.run(
|
|
578
|
-
query,
|
|
579
|
-
ProjectId=vpc['project_id'],
|
|
580
|
-
PartialUri=vpc['partial_uri'],
|
|
581
|
-
SelfLink=vpc['self_link'],
|
|
582
|
-
VpcName=vpc['name'],
|
|
583
|
-
AutoCreateSubnetworks=vpc['auto_create_subnetworks'],
|
|
584
|
-
RoutingMode=vpc['routing_config_routing_mode'],
|
|
585
|
-
Description=vpc['description'],
|
|
586
|
-
gcp_update_tag=gcp_update_tag,
|
|
587
|
-
)
|
|
642
|
+
def load_gcp_vpcs(
|
|
643
|
+
neo4j_session: neo4j.Session,
|
|
644
|
+
vpcs: list[dict[str, Any]],
|
|
645
|
+
gcp_update_tag: int,
|
|
646
|
+
project_id: str,
|
|
647
|
+
) -> None:
|
|
648
|
+
load(
|
|
649
|
+
neo4j_session,
|
|
650
|
+
GCPVpcSchema(),
|
|
651
|
+
vpcs,
|
|
652
|
+
PROJECT_ID=project_id,
|
|
653
|
+
LASTUPDATED=gcp_update_tag,
|
|
654
|
+
)
|
|
588
655
|
|
|
589
656
|
|
|
590
657
|
@timeit
|
|
591
|
-
def load_gcp_subnets(
|
|
658
|
+
def load_gcp_subnets(
|
|
659
|
+
neo4j_session: neo4j.Session,
|
|
660
|
+
subnets: List[Dict],
|
|
661
|
+
gcp_update_tag: int,
|
|
662
|
+
project_id: str,
|
|
663
|
+
) -> None:
|
|
592
664
|
"""
|
|
593
|
-
Ingest GCP subnet data to Neo4j
|
|
665
|
+
Ingest GCP subnet data to Neo4j using the data model
|
|
594
666
|
:param neo4j_session: The Neo4j session
|
|
595
667
|
:param subnets: List of the subnets
|
|
596
668
|
:param gcp_update_tag: The timestamp to set these Neo4j nodes with
|
|
669
|
+
:param project_id: The project ID
|
|
597
670
|
:return: Nothing
|
|
598
671
|
"""
|
|
599
|
-
|
|
600
|
-
MERGE(vpc:GCPVpc{id:$VpcPartialUri})
|
|
601
|
-
ON CREATE SET vpc.firstseen = timestamp(),
|
|
602
|
-
vpc.partial_uri = $VpcPartialUri
|
|
672
|
+
from cartography.models.gcp.compute.subnet import GCPSubnetSchema
|
|
603
673
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
subnet.gateway_address = $GatewayAddress,
|
|
612
|
-
subnet.ip_cidr_range = $IpCidrRange,
|
|
613
|
-
subnet.private_ip_google_access = $PrivateIpGoogleAccess,
|
|
614
|
-
subnet.vpc_partial_uri = $VpcPartialUri,
|
|
615
|
-
subnet.lastupdated = $gcp_update_tag
|
|
616
|
-
|
|
617
|
-
MERGE (vpc)-[r:RESOURCE]->(subnet)
|
|
618
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
619
|
-
SET r.lastupdated = $gcp_update_tag
|
|
620
|
-
"""
|
|
621
|
-
for s in subnets:
|
|
622
|
-
neo4j_session.run(
|
|
623
|
-
query,
|
|
624
|
-
VpcPartialUri=s['vpc_partial_uri'],
|
|
625
|
-
VpcSelfLink=s['vpc_self_link'],
|
|
626
|
-
PartialUri=s['partial_uri'],
|
|
627
|
-
SubnetSelfLink=s['self_link'],
|
|
628
|
-
ProjectId=s['project_id'],
|
|
629
|
-
SubnetName=s['name'],
|
|
630
|
-
Region=s['region'],
|
|
631
|
-
GatewayAddress=s['gateway_address'],
|
|
632
|
-
IpCidrRange=s['ip_cidr_range'],
|
|
633
|
-
PrivateIpGoogleAccess=s['private_ip_google_access'],
|
|
634
|
-
gcp_update_tag=gcp_update_tag,
|
|
635
|
-
)
|
|
674
|
+
load(
|
|
675
|
+
neo4j_session,
|
|
676
|
+
GCPSubnetSchema(),
|
|
677
|
+
subnets,
|
|
678
|
+
lastupdated=gcp_update_tag,
|
|
679
|
+
PROJECT_ID=project_id,
|
|
680
|
+
)
|
|
636
681
|
|
|
637
682
|
|
|
638
683
|
@timeit
|
|
639
|
-
def load_gcp_forwarding_rules(
|
|
684
|
+
def load_gcp_forwarding_rules(
|
|
685
|
+
neo4j_session: neo4j.Session,
|
|
686
|
+
fwd_rules: List[Dict],
|
|
687
|
+
gcp_update_tag: int,
|
|
688
|
+
) -> None:
|
|
640
689
|
"""
|
|
641
690
|
Ingest GCP forwarding rules data to Neo4j
|
|
642
691
|
:param neo4j_session: The Neo4j session
|
|
@@ -665,26 +714,27 @@ def load_gcp_forwarding_rules(neo4j_session: neo4j.Session, fwd_rules: List[Dict
|
|
|
665
714
|
"""
|
|
666
715
|
|
|
667
716
|
for fwd in fwd_rules:
|
|
668
|
-
network = fwd.get(
|
|
669
|
-
subnetwork = fwd.get(
|
|
717
|
+
network = fwd.get("network", None)
|
|
718
|
+
subnetwork = fwd.get("subnetwork", None)
|
|
670
719
|
|
|
671
|
-
|
|
720
|
+
run_write_query(
|
|
721
|
+
neo4j_session,
|
|
672
722
|
query,
|
|
673
|
-
PartialUri=fwd[
|
|
674
|
-
IPAddress=fwd[
|
|
675
|
-
IPProtocol=fwd[
|
|
676
|
-
LoadBalancingScheme=fwd[
|
|
677
|
-
Name=fwd[
|
|
723
|
+
PartialUri=fwd["partial_uri"],
|
|
724
|
+
IPAddress=fwd["ip_address"],
|
|
725
|
+
IPProtocol=fwd["ip_protocol"],
|
|
726
|
+
LoadBalancingScheme=fwd["load_balancing_scheme"],
|
|
727
|
+
Name=fwd["name"],
|
|
678
728
|
Network=network,
|
|
679
|
-
NetworkPartialUri=fwd.get(
|
|
680
|
-
PortRange=fwd.get(
|
|
681
|
-
Ports=fwd.get(
|
|
682
|
-
ProjectId=fwd[
|
|
683
|
-
Region=fwd.get(
|
|
684
|
-
SelfLink=fwd[
|
|
729
|
+
NetworkPartialUri=fwd.get("network_partial_uri", None),
|
|
730
|
+
PortRange=fwd.get("port_range", None),
|
|
731
|
+
Ports=fwd.get("ports", None),
|
|
732
|
+
ProjectId=fwd["project_id"],
|
|
733
|
+
Region=fwd.get("region", None),
|
|
734
|
+
SelfLink=fwd["self_link"],
|
|
685
735
|
SubNetwork=subnetwork,
|
|
686
|
-
SubNetworkPartialUri=fwd.get(
|
|
687
|
-
TargetPartialUri=fwd[
|
|
736
|
+
SubNetworkPartialUri=fwd.get("subnetwork_partial_uri", None),
|
|
737
|
+
TargetPartialUri=fwd["target"],
|
|
688
738
|
gcp_update_tag=gcp_update_tag,
|
|
689
739
|
)
|
|
690
740
|
|
|
@@ -695,7 +745,11 @@ def load_gcp_forwarding_rules(neo4j_session: neo4j.Session, fwd_rules: List[Dict
|
|
|
695
745
|
|
|
696
746
|
|
|
697
747
|
@timeit
|
|
698
|
-
def _attach_fwd_rule_to_subnet(
|
|
748
|
+
def _attach_fwd_rule_to_subnet(
|
|
749
|
+
neo4j_session: neo4j.Session,
|
|
750
|
+
fwd: Dict,
|
|
751
|
+
gcp_update_tag: int,
|
|
752
|
+
) -> None:
|
|
699
753
|
query = """
|
|
700
754
|
MERGE(subnet:GCPSubnet{id:$SubNetworkPartialUri})
|
|
701
755
|
ON CREATE SET subnet.firstseen = timestamp(),
|
|
@@ -710,16 +764,21 @@ def _attach_fwd_rule_to_subnet(neo4j_session: neo4j.Session, fwd: Dict, gcp_upda
|
|
|
710
764
|
SET p.lastupdated = $gcp_update_tag
|
|
711
765
|
"""
|
|
712
766
|
|
|
713
|
-
|
|
767
|
+
run_write_query(
|
|
768
|
+
neo4j_session,
|
|
714
769
|
query,
|
|
715
|
-
PartialUri=fwd[
|
|
716
|
-
SubNetworkPartialUri=fwd.get(
|
|
770
|
+
PartialUri=fwd["partial_uri"],
|
|
771
|
+
SubNetworkPartialUri=fwd.get("subnetwork_partial_uri", None),
|
|
717
772
|
gcp_update_tag=gcp_update_tag,
|
|
718
773
|
)
|
|
719
774
|
|
|
720
775
|
|
|
721
776
|
@timeit
|
|
722
|
-
def _attach_fwd_rule_to_vpc(
|
|
777
|
+
def _attach_fwd_rule_to_vpc(
|
|
778
|
+
neo4j_session: neo4j.Session,
|
|
779
|
+
fwd: Dict,
|
|
780
|
+
gcp_update_tag: int,
|
|
781
|
+
) -> None:
|
|
723
782
|
query = """
|
|
724
783
|
MERGE (vpc:GCPVpc{id:$NetworkPartialUri})
|
|
725
784
|
ON CREATE SET vpc.firstseen = timestamp(),
|
|
@@ -733,16 +792,21 @@ def _attach_fwd_rule_to_vpc(neo4j_session: neo4j.Session, fwd: Dict, gcp_update_
|
|
|
733
792
|
SET r.lastupdated = $gcp_update_tag
|
|
734
793
|
"""
|
|
735
794
|
|
|
736
|
-
|
|
795
|
+
run_write_query(
|
|
796
|
+
neo4j_session,
|
|
737
797
|
query,
|
|
738
|
-
PartialUri=fwd[
|
|
739
|
-
NetworkPartialUri=fwd.get(
|
|
798
|
+
PartialUri=fwd["partial_uri"],
|
|
799
|
+
NetworkPartialUri=fwd.get("network_partial_uri", None),
|
|
740
800
|
gcp_update_tag=gcp_update_tag,
|
|
741
801
|
)
|
|
742
802
|
|
|
743
803
|
|
|
744
804
|
@timeit
|
|
745
|
-
def _attach_instance_tags(
|
|
805
|
+
def _attach_instance_tags(
|
|
806
|
+
neo4j_session: neo4j.Session,
|
|
807
|
+
instance: Resource,
|
|
808
|
+
gcp_update_tag: int,
|
|
809
|
+
) -> None:
|
|
746
810
|
"""
|
|
747
811
|
Attach tags to GCP instance and to the VPCs that they are defined in.
|
|
748
812
|
:param neo4j_session: The session
|
|
@@ -770,21 +834,26 @@ def _attach_instance_tags(neo4j_session: neo4j.Session, instance: Resource, gcp_
|
|
|
770
834
|
ON CREATE SET d.firstseen = timestamp()
|
|
771
835
|
SET d.lastupdated = $gcp_update_tag
|
|
772
836
|
"""
|
|
773
|
-
for tag in instance.get(
|
|
774
|
-
for nic in instance.get(
|
|
775
|
-
tag_id = _create_gcp_network_tag_id(nic[
|
|
776
|
-
|
|
837
|
+
for tag in instance.get("tags", {}).get("items", []):
|
|
838
|
+
for nic in instance.get("networkInterfaces", []):
|
|
839
|
+
tag_id = _create_gcp_network_tag_id(nic["vpc_partial_uri"], tag)
|
|
840
|
+
run_write_query(
|
|
841
|
+
neo4j_session,
|
|
777
842
|
query,
|
|
778
|
-
InstanceId=instance[
|
|
843
|
+
InstanceId=instance["partial_uri"],
|
|
779
844
|
TagId=tag_id,
|
|
780
845
|
TagValue=tag,
|
|
781
|
-
VpcPartialUri=nic[
|
|
846
|
+
VpcPartialUri=nic["vpc_partial_uri"],
|
|
782
847
|
gcp_update_tag=gcp_update_tag,
|
|
783
848
|
)
|
|
784
849
|
|
|
785
850
|
|
|
786
851
|
@timeit
|
|
787
|
-
def _attach_gcp_nics(
|
|
852
|
+
def _attach_gcp_nics(
|
|
853
|
+
neo4j_session: neo4j.Session,
|
|
854
|
+
instance: Resource,
|
|
855
|
+
gcp_update_tag: int,
|
|
856
|
+
) -> None:
|
|
788
857
|
"""
|
|
789
858
|
Attach GCP Network Interfaces to GCP Instances and GCP Subnets.
|
|
790
859
|
Then, attach GCP Instances directly to VPCs.
|
|
@@ -815,24 +884,28 @@ def _attach_gcp_nics(neo4j_session: neo4j.Session, instance: Resource, gcp_updat
|
|
|
815
884
|
ON CREATE SET p.firstseen = timestamp()
|
|
816
885
|
SET p.lastupdated = $gcp_update_tag
|
|
817
886
|
"""
|
|
818
|
-
for nic in instance.get(
|
|
887
|
+
for nic in instance.get("networkInterfaces", []):
|
|
819
888
|
# Make an ID for GCPNetworkInterface nodes because GCP doesn't define one but we need to uniquely identify them
|
|
820
889
|
nic_id = f"{instance['partial_uri']}/networkinterfaces/{nic['name']}"
|
|
821
|
-
|
|
890
|
+
run_write_query(
|
|
891
|
+
neo4j_session,
|
|
822
892
|
query,
|
|
823
|
-
InstanceId=instance[
|
|
893
|
+
InstanceId=instance["partial_uri"],
|
|
824
894
|
NicId=nic_id,
|
|
825
|
-
NetworkIP=nic.get(
|
|
826
|
-
NicName=nic[
|
|
895
|
+
NetworkIP=nic.get("networkIP"),
|
|
896
|
+
NicName=nic["name"],
|
|
827
897
|
gcp_update_tag=gcp_update_tag,
|
|
828
|
-
SubnetPartialUri=nic[
|
|
898
|
+
SubnetPartialUri=nic["subnet_partial_uri"],
|
|
829
899
|
)
|
|
830
900
|
_attach_gcp_nic_access_configs(neo4j_session, nic_id, nic, gcp_update_tag)
|
|
831
901
|
|
|
832
902
|
|
|
833
903
|
@timeit
|
|
834
904
|
def _attach_gcp_nic_access_configs(
|
|
835
|
-
neo4j_session: neo4j.Session,
|
|
905
|
+
neo4j_session: neo4j.Session,
|
|
906
|
+
nic_id: str,
|
|
907
|
+
nic: Resource,
|
|
908
|
+
gcp_update_tag: int,
|
|
836
909
|
) -> None:
|
|
837
910
|
"""
|
|
838
911
|
Attach an access configuration to the GCP NIC.
|
|
@@ -858,25 +931,30 @@ def _attach_gcp_nic_access_configs(
|
|
|
858
931
|
ON CREATE SET r.firstseen = timestamp()
|
|
859
932
|
SET r.lastupdated = $gcp_update_tag
|
|
860
933
|
"""
|
|
861
|
-
for ac in nic.get(
|
|
934
|
+
for ac in nic.get("accessConfigs", []):
|
|
862
935
|
# Make an ID for GCPNicAccessConfig nodes because GCP doesn't define one but we need to uniquely identify them
|
|
863
936
|
access_config_id = f"{nic_id}/accessconfigs/{ac['type']}"
|
|
864
|
-
|
|
937
|
+
run_write_query(
|
|
938
|
+
neo4j_session,
|
|
865
939
|
query,
|
|
866
940
|
NicId=nic_id,
|
|
867
941
|
AccessConfigId=access_config_id,
|
|
868
|
-
Type=ac[
|
|
869
|
-
Name=ac[
|
|
870
|
-
NatIP=ac.get(
|
|
871
|
-
SetPublicPtr=ac.get(
|
|
872
|
-
PublicPtrDomainName=ac.get(
|
|
873
|
-
NetworkTier=ac.get(
|
|
942
|
+
Type=ac["type"],
|
|
943
|
+
Name=ac["name"],
|
|
944
|
+
NatIP=ac.get("natIP", None),
|
|
945
|
+
SetPublicPtr=ac.get("setPublicPtr", None),
|
|
946
|
+
PublicPtrDomainName=ac.get("publicPtrDomainName", None),
|
|
947
|
+
NetworkTier=ac.get("networkTier", None),
|
|
874
948
|
gcp_update_tag=gcp_update_tag,
|
|
875
949
|
)
|
|
876
950
|
|
|
877
951
|
|
|
878
952
|
@timeit
|
|
879
|
-
def _attach_gcp_vpc(
|
|
953
|
+
def _attach_gcp_vpc(
|
|
954
|
+
neo4j_session: neo4j.Session,
|
|
955
|
+
instance_id: str,
|
|
956
|
+
gcp_update_tag: int,
|
|
957
|
+
) -> None:
|
|
880
958
|
"""
|
|
881
959
|
Attach a GCP instance directly to a VPC
|
|
882
960
|
:param neo4j_session: neo4j_session
|
|
@@ -886,12 +964,13 @@ def _attach_gcp_vpc(neo4j_session: neo4j.Session, instance_id: str, gcp_update_t
|
|
|
886
964
|
"""
|
|
887
965
|
query = """
|
|
888
966
|
MATCH (i:GCPInstance{id:$InstanceId})-[:NETWORK_INTERFACE]->(nic:GCPNetworkInterface)
|
|
889
|
-
-[p:PART_OF_SUBNET]->(sn:GCPSubnet)<-[r:
|
|
967
|
+
-[p:PART_OF_SUBNET]->(sn:GCPSubnet)<-[r:HAS]-(vpc:GCPVpc)
|
|
890
968
|
MERGE (i)-[m:MEMBER_OF_GCP_VPC]->(vpc)
|
|
891
969
|
ON CREATE SET m.firstseen = timestamp()
|
|
892
970
|
SET m.lastupdated = $gcp_update_tag
|
|
893
971
|
"""
|
|
894
|
-
|
|
972
|
+
run_write_query(
|
|
973
|
+
neo4j_session,
|
|
895
974
|
query,
|
|
896
975
|
InstanceId=instance_id,
|
|
897
976
|
gcp_update_tag=gcp_update_tag,
|
|
@@ -899,12 +978,29 @@ def _attach_gcp_vpc(neo4j_session: neo4j.Session, instance_id: str, gcp_update_t
|
|
|
899
978
|
|
|
900
979
|
|
|
901
980
|
@timeit
|
|
902
|
-
def load_gcp_ingress_firewalls(
|
|
981
|
+
def load_gcp_ingress_firewalls(
|
|
982
|
+
neo4j_session: neo4j.Session,
|
|
983
|
+
fw_list: List[Resource],
|
|
984
|
+
gcp_update_tag: int,
|
|
985
|
+
) -> None:
|
|
903
986
|
"""
|
|
904
|
-
Load the firewall list to Neo4j
|
|
987
|
+
Load the firewall list to Neo4j with retry logic for transient errors.
|
|
905
988
|
:param fw_list: The transformed list of firewalls
|
|
906
989
|
:return: Nothing
|
|
907
990
|
"""
|
|
991
|
+
execute_write_with_retry(
|
|
992
|
+
neo4j_session,
|
|
993
|
+
_load_gcp_ingress_firewalls_tx,
|
|
994
|
+
fw_list,
|
|
995
|
+
gcp_update_tag,
|
|
996
|
+
)
|
|
997
|
+
|
|
998
|
+
|
|
999
|
+
def _load_gcp_ingress_firewalls_tx(
|
|
1000
|
+
tx: neo4j.Transaction,
|
|
1001
|
+
fw_list: List[Resource],
|
|
1002
|
+
gcp_update_tag: int,
|
|
1003
|
+
) -> None:
|
|
908
1004
|
query = """
|
|
909
1005
|
MERGE (fw:GCPFirewall{id:$FwPartialUri})
|
|
910
1006
|
ON CREATE SET fw.firstseen = timestamp(),
|
|
@@ -927,32 +1023,37 @@ def load_gcp_ingress_firewalls(neo4j_session: neo4j.Session, fw_list: List[Resou
|
|
|
927
1023
|
SET r.lastupdated = $gcp_update_tag
|
|
928
1024
|
"""
|
|
929
1025
|
for fw in fw_list:
|
|
930
|
-
|
|
1026
|
+
tx.run(
|
|
931
1027
|
query,
|
|
932
|
-
FwPartialUri=fw[
|
|
933
|
-
Direction=fw[
|
|
934
|
-
Disabled=fw[
|
|
935
|
-
Name=fw[
|
|
936
|
-
Priority=fw[
|
|
937
|
-
SelfLink=fw[
|
|
938
|
-
VpcPartialUri=fw[
|
|
939
|
-
HasTargetServiceAccounts=fw[
|
|
1028
|
+
FwPartialUri=fw["id"],
|
|
1029
|
+
Direction=fw["direction"],
|
|
1030
|
+
Disabled=fw["disabled"],
|
|
1031
|
+
Name=fw["name"],
|
|
1032
|
+
Priority=fw["priority"],
|
|
1033
|
+
SelfLink=fw["selfLink"],
|
|
1034
|
+
VpcPartialUri=fw["vpc_partial_uri"],
|
|
1035
|
+
HasTargetServiceAccounts=fw["has_target_service_accounts"],
|
|
940
1036
|
gcp_update_tag=gcp_update_tag,
|
|
941
|
-
)
|
|
942
|
-
_attach_firewall_rules(
|
|
943
|
-
_attach_target_tags(
|
|
1037
|
+
).consume()
|
|
1038
|
+
_attach_firewall_rules(tx, fw, gcp_update_tag)
|
|
1039
|
+
_attach_target_tags(tx, fw, gcp_update_tag)
|
|
944
1040
|
|
|
945
1041
|
|
|
946
1042
|
@timeit
|
|
947
|
-
def _attach_firewall_rules(
|
|
1043
|
+
def _attach_firewall_rules(
|
|
1044
|
+
tx: neo4j.Transaction,
|
|
1045
|
+
fw: Resource,
|
|
1046
|
+
gcp_update_tag: int,
|
|
1047
|
+
) -> None:
|
|
948
1048
|
"""
|
|
949
1049
|
Attach the allow_rules to the Firewall object
|
|
950
|
-
:param
|
|
1050
|
+
:param tx: The Neo4j transaction
|
|
951
1051
|
:param fw: The Firewall object
|
|
952
1052
|
:param gcp_update_tag: The timestamp
|
|
953
1053
|
:return: Nothing
|
|
954
1054
|
"""
|
|
955
|
-
template = Template(
|
|
1055
|
+
template = Template(
|
|
1056
|
+
"""
|
|
956
1057
|
MATCH (fw:GCPFirewall{id:$FwPartialUri})
|
|
957
1058
|
|
|
958
1059
|
MERGE (rule:IpRule:IpPermissionInbound:GCPIpRule{id:$RuleId})
|
|
@@ -975,9 +1076,10 @@ def _attach_firewall_rules(neo4j_session: neo4j.Session, fw: Resource, gcp_updat
|
|
|
975
1076
|
MERGE (fw)<-[r:$fw_rule_relationship_label]-(rule)
|
|
976
1077
|
ON CREATE SET r.firstseen = timestamp()
|
|
977
1078
|
SET r.lastupdated = $gcp_update_tag
|
|
978
|
-
"""
|
|
979
|
-
|
|
980
|
-
|
|
1079
|
+
""",
|
|
1080
|
+
)
|
|
1081
|
+
for list_type in "transformed_allow_list", "transformed_deny_list":
|
|
1082
|
+
if list_type == "transformed_allow_list":
|
|
981
1083
|
label = "ALLOWED_BY"
|
|
982
1084
|
else:
|
|
983
1085
|
label = "DENIED_BY"
|
|
@@ -985,24 +1087,28 @@ def _attach_firewall_rules(neo4j_session: neo4j.Session, fw: Resource, gcp_updat
|
|
|
985
1087
|
# It is possible for sourceRanges to not be specified for this rule
|
|
986
1088
|
# If sourceRanges is not specified then the rule must specify sourceTags.
|
|
987
1089
|
# Since an IP range cannot have a tag applied to it, it is ok if we don't ingest this rule.
|
|
988
|
-
for ip_range in fw.get(
|
|
989
|
-
|
|
1090
|
+
for ip_range in fw.get("sourceRanges", []):
|
|
1091
|
+
tx.run(
|
|
990
1092
|
template.safe_substitute(fw_rule_relationship_label=label),
|
|
991
|
-
FwPartialUri=fw[
|
|
992
|
-
RuleId=rule[
|
|
993
|
-
Protocol=rule[
|
|
994
|
-
FromPort=rule.get(
|
|
995
|
-
ToPort=rule.get(
|
|
1093
|
+
FwPartialUri=fw["id"],
|
|
1094
|
+
RuleId=rule["ruleid"],
|
|
1095
|
+
Protocol=rule["protocol"],
|
|
1096
|
+
FromPort=rule.get("fromport"),
|
|
1097
|
+
ToPort=rule.get("toport"),
|
|
996
1098
|
Range=ip_range,
|
|
997
1099
|
gcp_update_tag=gcp_update_tag,
|
|
998
|
-
)
|
|
1100
|
+
).consume()
|
|
999
1101
|
|
|
1000
1102
|
|
|
1001
1103
|
@timeit
|
|
1002
|
-
def _attach_target_tags(
|
|
1104
|
+
def _attach_target_tags(
|
|
1105
|
+
tx: neo4j.Transaction,
|
|
1106
|
+
fw: Resource,
|
|
1107
|
+
gcp_update_tag: int,
|
|
1108
|
+
) -> None:
|
|
1003
1109
|
"""
|
|
1004
1110
|
Attach target tags to the firewall object
|
|
1005
|
-
:param
|
|
1111
|
+
:param tx: The neo4j transaction
|
|
1006
1112
|
:param fw: The firewall object
|
|
1007
1113
|
:param gcp_update_tag: The timestamp
|
|
1008
1114
|
:return: Nothing
|
|
@@ -1020,26 +1126,33 @@ def _attach_target_tags(neo4j_session: neo4j.Session, fw: Resource, gcp_update_t
|
|
|
1020
1126
|
ON CREATE SET h.firstseen = timestamp()
|
|
1021
1127
|
SET h.lastupdated = $gcp_update_tag
|
|
1022
1128
|
"""
|
|
1023
|
-
for tag in fw.get(
|
|
1024
|
-
tag_id = _create_gcp_network_tag_id(fw[
|
|
1025
|
-
|
|
1129
|
+
for tag in fw.get("targetTags", []):
|
|
1130
|
+
tag_id = _create_gcp_network_tag_id(fw["vpc_partial_uri"], tag)
|
|
1131
|
+
tx.run(
|
|
1026
1132
|
query,
|
|
1027
|
-
FwPartialUri=fw[
|
|
1133
|
+
FwPartialUri=fw["id"],
|
|
1028
1134
|
TagId=tag_id,
|
|
1029
1135
|
TagValue=tag,
|
|
1030
1136
|
gcp_update_tag=gcp_update_tag,
|
|
1031
|
-
)
|
|
1137
|
+
).consume()
|
|
1032
1138
|
|
|
1033
1139
|
|
|
1034
1140
|
@timeit
|
|
1035
|
-
def cleanup_gcp_instances(
|
|
1141
|
+
def cleanup_gcp_instances(
|
|
1142
|
+
neo4j_session: neo4j.Session,
|
|
1143
|
+
common_job_parameters: Dict,
|
|
1144
|
+
) -> None:
|
|
1036
1145
|
"""
|
|
1037
1146
|
Delete out-of-date GCP instance nodes and relationships
|
|
1038
1147
|
:param neo4j_session: The Neo4j session
|
|
1039
1148
|
:param common_job_parameters: dict of other job parameters to pass to Neo4j
|
|
1040
1149
|
:return: Nothing
|
|
1041
1150
|
"""
|
|
1042
|
-
run_cleanup_job(
|
|
1151
|
+
run_cleanup_job(
|
|
1152
|
+
"gcp_compute_instance_cleanup.json",
|
|
1153
|
+
neo4j_session,
|
|
1154
|
+
common_job_parameters,
|
|
1155
|
+
)
|
|
1043
1156
|
|
|
1044
1157
|
|
|
1045
1158
|
@timeit
|
|
@@ -1050,46 +1163,81 @@ def cleanup_gcp_vpcs(neo4j_session: neo4j.Session, common_job_parameters: Dict)
|
|
|
1050
1163
|
:param common_job_parameters: dict of other job parameters to pass to Neo4j
|
|
1051
1164
|
:return: Nothing
|
|
1052
1165
|
"""
|
|
1053
|
-
|
|
1166
|
+
GraphJob.from_node_schema(
|
|
1167
|
+
GCPVpcSchema(),
|
|
1168
|
+
common_job_parameters,
|
|
1169
|
+
).run(neo4j_session)
|
|
1170
|
+
|
|
1171
|
+
# TODO: remove this once we refactor GCP instances and add the instance to vpc rel as an object
|
|
1172
|
+
run_cleanup_job(
|
|
1173
|
+
"gcp_compute_vpc_cleanup.json",
|
|
1174
|
+
neo4j_session,
|
|
1175
|
+
common_job_parameters,
|
|
1176
|
+
)
|
|
1054
1177
|
|
|
1055
1178
|
|
|
1056
1179
|
@timeit
|
|
1057
|
-
def cleanup_gcp_subnets(
|
|
1180
|
+
def cleanup_gcp_subnets(
|
|
1181
|
+
neo4j_session: neo4j.Session,
|
|
1182
|
+
common_job_parameters: Dict,
|
|
1183
|
+
) -> None:
|
|
1058
1184
|
"""
|
|
1059
|
-
Delete out-of-date GCP VPC subnet nodes and relationships
|
|
1185
|
+
Delete out-of-date GCP VPC subnet nodes and relationships using data model
|
|
1060
1186
|
:param neo4j_session: The Neo4j session
|
|
1061
1187
|
:param common_job_parameters: dict of other job parameters to pass to Neo4j
|
|
1062
1188
|
:return: Nothing
|
|
1063
1189
|
"""
|
|
1064
|
-
|
|
1190
|
+
from cartography.models.gcp.compute.subnet import GCPSubnetSchema
|
|
1191
|
+
|
|
1192
|
+
GraphJob.from_node_schema(GCPSubnetSchema(), common_job_parameters).run(
|
|
1193
|
+
neo4j_session
|
|
1194
|
+
)
|
|
1065
1195
|
|
|
1066
1196
|
|
|
1067
1197
|
@timeit
|
|
1068
|
-
def cleanup_gcp_forwarding_rules(
|
|
1198
|
+
def cleanup_gcp_forwarding_rules(
|
|
1199
|
+
neo4j_session: neo4j.Session,
|
|
1200
|
+
common_job_parameters: Dict,
|
|
1201
|
+
) -> None:
|
|
1069
1202
|
"""
|
|
1070
1203
|
Delete out-of-date GCP forwarding rules and relationships
|
|
1071
1204
|
:param neo4j_session: The Neo4j session
|
|
1072
1205
|
:param common_job_parameters: dict of other job parameters to pass to Neo4j
|
|
1073
1206
|
:return: Nothing
|
|
1074
1207
|
"""
|
|
1075
|
-
run_cleanup_job(
|
|
1208
|
+
run_cleanup_job(
|
|
1209
|
+
"gcp_compute_forwarding_rules_cleanup.json",
|
|
1210
|
+
neo4j_session,
|
|
1211
|
+
common_job_parameters,
|
|
1212
|
+
)
|
|
1076
1213
|
|
|
1077
1214
|
|
|
1078
1215
|
@timeit
|
|
1079
|
-
def cleanup_gcp_firewall_rules(
|
|
1216
|
+
def cleanup_gcp_firewall_rules(
|
|
1217
|
+
neo4j_session: neo4j.Session,
|
|
1218
|
+
common_job_parameters: Dict,
|
|
1219
|
+
) -> None:
|
|
1080
1220
|
"""
|
|
1081
1221
|
Delete out of date GCP firewalls and their relationships
|
|
1082
1222
|
:param neo4j_session: The Neo4j session
|
|
1083
1223
|
:param common_job_parameters: dict of other job parameters to pass to Neo4j
|
|
1084
1224
|
:return: Nothing
|
|
1085
1225
|
"""
|
|
1086
|
-
run_cleanup_job(
|
|
1226
|
+
run_cleanup_job(
|
|
1227
|
+
"gcp_compute_firewall_cleanup.json",
|
|
1228
|
+
neo4j_session,
|
|
1229
|
+
common_job_parameters,
|
|
1230
|
+
)
|
|
1087
1231
|
|
|
1088
1232
|
|
|
1089
1233
|
@timeit
|
|
1090
1234
|
def sync_gcp_instances(
|
|
1091
|
-
neo4j_session: neo4j.Session,
|
|
1092
|
-
|
|
1235
|
+
neo4j_session: neo4j.Session,
|
|
1236
|
+
compute: Resource,
|
|
1237
|
+
project_id: str,
|
|
1238
|
+
zones: Optional[List[Dict]],
|
|
1239
|
+
gcp_update_tag: int,
|
|
1240
|
+
common_job_parameters: Dict,
|
|
1093
1241
|
) -> None:
|
|
1094
1242
|
"""
|
|
1095
1243
|
Get GCP instances using the Compute resource object, ingest to Neo4j, and clean up old data.
|
|
@@ -1106,13 +1254,16 @@ def sync_gcp_instances(
|
|
|
1106
1254
|
instance_responses = get_gcp_instance_responses(project_id, zones, compute)
|
|
1107
1255
|
instance_list = transform_gcp_instances(instance_responses)
|
|
1108
1256
|
load_gcp_instances(neo4j_session, instance_list, gcp_update_tag)
|
|
1109
|
-
# TODO scope the cleanup to the current project - https://github.com/
|
|
1257
|
+
# TODO scope the cleanup to the current project - https://github.com/cartography-cncf/cartography/issues/381
|
|
1110
1258
|
cleanup_gcp_instances(neo4j_session, common_job_parameters)
|
|
1111
1259
|
|
|
1112
1260
|
|
|
1113
1261
|
@timeit
|
|
1114
1262
|
def sync_gcp_vpcs(
|
|
1115
|
-
neo4j_session: neo4j.Session,
|
|
1263
|
+
neo4j_session: neo4j.Session,
|
|
1264
|
+
compute: Resource,
|
|
1265
|
+
project_id: str,
|
|
1266
|
+
gcp_update_tag: int,
|
|
1116
1267
|
common_job_parameters: Dict,
|
|
1117
1268
|
) -> None:
|
|
1118
1269
|
"""
|
|
@@ -1126,28 +1277,34 @@ def sync_gcp_vpcs(
|
|
|
1126
1277
|
"""
|
|
1127
1278
|
vpc_res = get_gcp_vpcs(project_id, compute)
|
|
1128
1279
|
vpcs = transform_gcp_vpcs(vpc_res)
|
|
1129
|
-
load_gcp_vpcs(neo4j_session, vpcs, gcp_update_tag)
|
|
1130
|
-
# TODO scope the cleanup to the current project - https://github.com/lyft/cartography/issues/381
|
|
1280
|
+
load_gcp_vpcs(neo4j_session, vpcs, gcp_update_tag, project_id)
|
|
1131
1281
|
cleanup_gcp_vpcs(neo4j_session, common_job_parameters)
|
|
1132
1282
|
|
|
1133
1283
|
|
|
1134
1284
|
@timeit
|
|
1135
1285
|
def sync_gcp_subnets(
|
|
1136
|
-
neo4j_session: neo4j.Session,
|
|
1286
|
+
neo4j_session: neo4j.Session,
|
|
1287
|
+
compute: Resource,
|
|
1288
|
+
project_id: str,
|
|
1289
|
+
regions: List[str],
|
|
1290
|
+
gcp_update_tag: int,
|
|
1137
1291
|
common_job_parameters: Dict,
|
|
1138
1292
|
) -> None:
|
|
1139
1293
|
for r in regions:
|
|
1140
1294
|
subnet_res = get_gcp_subnets(project_id, r, compute)
|
|
1141
1295
|
subnets = transform_gcp_subnets(subnet_res)
|
|
1142
|
-
load_gcp_subnets(neo4j_session, subnets, gcp_update_tag)
|
|
1143
|
-
# TODO scope the cleanup to the current project - https://github.com/
|
|
1296
|
+
load_gcp_subnets(neo4j_session, subnets, gcp_update_tag, project_id)
|
|
1297
|
+
# TODO scope the cleanup to the current project - https://github.com/cartography-cncf/cartography/issues/381
|
|
1144
1298
|
cleanup_gcp_subnets(neo4j_session, common_job_parameters)
|
|
1145
1299
|
|
|
1146
1300
|
|
|
1147
1301
|
@timeit
|
|
1148
1302
|
def sync_gcp_forwarding_rules(
|
|
1149
|
-
neo4j_session: neo4j.Session,
|
|
1150
|
-
|
|
1303
|
+
neo4j_session: neo4j.Session,
|
|
1304
|
+
compute: Resource,
|
|
1305
|
+
project_id: str,
|
|
1306
|
+
regions: List[str],
|
|
1307
|
+
gcp_update_tag: int,
|
|
1151
1308
|
common_job_parameters: Dict,
|
|
1152
1309
|
) -> None:
|
|
1153
1310
|
"""
|
|
@@ -1163,20 +1320,23 @@ def sync_gcp_forwarding_rules(
|
|
|
1163
1320
|
global_fwd_response = get_gcp_global_forwarding_rules(project_id, compute)
|
|
1164
1321
|
forwarding_rules = transform_gcp_forwarding_rules(global_fwd_response)
|
|
1165
1322
|
load_gcp_forwarding_rules(neo4j_session, forwarding_rules, gcp_update_tag)
|
|
1166
|
-
# TODO scope the cleanup to the current project - https://github.com/
|
|
1323
|
+
# TODO scope the cleanup to the current project - https://github.com/cartography-cncf/cartography/issues/381
|
|
1167
1324
|
cleanup_gcp_forwarding_rules(neo4j_session, common_job_parameters)
|
|
1168
1325
|
|
|
1169
1326
|
for r in regions:
|
|
1170
1327
|
fwd_response = get_gcp_regional_forwarding_rules(project_id, r, compute)
|
|
1171
1328
|
forwarding_rules = transform_gcp_forwarding_rules(fwd_response)
|
|
1172
1329
|
load_gcp_forwarding_rules(neo4j_session, forwarding_rules, gcp_update_tag)
|
|
1173
|
-
# TODO scope the cleanup to the current project - https://github.com/
|
|
1330
|
+
# TODO scope the cleanup to the current project - https://github.com/cartography-cncf/cartography/issues/381
|
|
1174
1331
|
cleanup_gcp_forwarding_rules(neo4j_session, common_job_parameters)
|
|
1175
1332
|
|
|
1176
1333
|
|
|
1177
1334
|
@timeit
|
|
1178
1335
|
def sync_gcp_firewall_rules(
|
|
1179
|
-
neo4j_session: neo4j.Session,
|
|
1336
|
+
neo4j_session: neo4j.Session,
|
|
1337
|
+
compute: Resource,
|
|
1338
|
+
project_id: str,
|
|
1339
|
+
gcp_update_tag: int,
|
|
1180
1340
|
common_job_parameters: Dict,
|
|
1181
1341
|
) -> None:
|
|
1182
1342
|
"""
|
|
@@ -1190,7 +1350,7 @@ def sync_gcp_firewall_rules(
|
|
|
1190
1350
|
fw_response = get_gcp_firewall_ingress_rules(project_id, compute)
|
|
1191
1351
|
fw_list = transform_gcp_firewall(fw_response)
|
|
1192
1352
|
load_gcp_ingress_firewalls(neo4j_session, fw_list, gcp_update_tag)
|
|
1193
|
-
# TODO scope the cleanup to the current project - https://github.com/
|
|
1353
|
+
# TODO scope the cleanup to the current project - https://github.com/cartography-cncf/cartography/issues/381
|
|
1194
1354
|
cleanup_gcp_firewall_rules(neo4j_session, common_job_parameters)
|
|
1195
1355
|
|
|
1196
1356
|
|
|
@@ -1203,13 +1363,16 @@ def _zones_to_regions(zones: List[str]) -> List[Set]:
|
|
|
1203
1363
|
regions = set()
|
|
1204
1364
|
for zone in zones:
|
|
1205
1365
|
# Chop off the last 2 chars to turn the zone to a region
|
|
1206
|
-
region = zone[
|
|
1366
|
+
region = zone["name"][:-2] # type: ignore
|
|
1207
1367
|
regions.add(region)
|
|
1208
|
-
return list(regions)
|
|
1368
|
+
return list(regions) # type: ignore
|
|
1209
1369
|
|
|
1210
1370
|
|
|
1211
1371
|
def sync(
|
|
1212
|
-
neo4j_session: neo4j.Session,
|
|
1372
|
+
neo4j_session: neo4j.Session,
|
|
1373
|
+
compute: Resource,
|
|
1374
|
+
project_id: str,
|
|
1375
|
+
gcp_update_tag: int,
|
|
1213
1376
|
common_job_parameters: dict,
|
|
1214
1377
|
) -> None:
|
|
1215
1378
|
"""
|
|
@@ -1230,8 +1393,41 @@ def sync(
|
|
|
1230
1393
|
return
|
|
1231
1394
|
else:
|
|
1232
1395
|
regions = _zones_to_regions(zones)
|
|
1233
|
-
sync_gcp_vpcs(
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1396
|
+
sync_gcp_vpcs(
|
|
1397
|
+
neo4j_session,
|
|
1398
|
+
compute,
|
|
1399
|
+
project_id,
|
|
1400
|
+
gcp_update_tag,
|
|
1401
|
+
common_job_parameters,
|
|
1402
|
+
)
|
|
1403
|
+
sync_gcp_firewall_rules(
|
|
1404
|
+
neo4j_session,
|
|
1405
|
+
compute,
|
|
1406
|
+
project_id,
|
|
1407
|
+
gcp_update_tag,
|
|
1408
|
+
common_job_parameters,
|
|
1409
|
+
)
|
|
1410
|
+
sync_gcp_subnets(
|
|
1411
|
+
neo4j_session,
|
|
1412
|
+
compute,
|
|
1413
|
+
project_id,
|
|
1414
|
+
regions,
|
|
1415
|
+
gcp_update_tag,
|
|
1416
|
+
common_job_parameters,
|
|
1417
|
+
)
|
|
1418
|
+
sync_gcp_instances(
|
|
1419
|
+
neo4j_session,
|
|
1420
|
+
compute,
|
|
1421
|
+
project_id,
|
|
1422
|
+
zones,
|
|
1423
|
+
gcp_update_tag,
|
|
1424
|
+
common_job_parameters,
|
|
1425
|
+
)
|
|
1426
|
+
sync_gcp_forwarding_rules(
|
|
1427
|
+
neo4j_session,
|
|
1428
|
+
compute,
|
|
1429
|
+
project_id,
|
|
1430
|
+
regions,
|
|
1431
|
+
gcp_update_tag,
|
|
1432
|
+
common_job_parameters,
|
|
1433
|
+
)
|