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
|
File without changes
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Dict
|
|
3
|
+
from typing import List
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
import neo4j
|
|
7
|
+
from google.auth.credentials import Credentials as GoogleCredentials
|
|
8
|
+
from google.cloud import resourcemanager_v3
|
|
9
|
+
|
|
10
|
+
from cartography.client.core.tx import load
|
|
11
|
+
from cartography.models.gcp.crm.folders import GCPFolderSchema
|
|
12
|
+
from cartography.util import timeit
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@timeit
|
|
18
|
+
def get_gcp_folders(
|
|
19
|
+
org_resource_name: str,
|
|
20
|
+
credentials: Optional[GoogleCredentials] = None,
|
|
21
|
+
) -> List[Dict]:
|
|
22
|
+
"""
|
|
23
|
+
Return a list of all descendant GCP folders under the specified organization by traversing the folder tree.
|
|
24
|
+
|
|
25
|
+
:param org_resource_name: Full organization resource name (e.g., "organizations/123456789012")
|
|
26
|
+
:return: List of folder dicts with 'name' field containing full resource names (e.g., "folders/123456")
|
|
27
|
+
"""
|
|
28
|
+
results: List[Dict] = []
|
|
29
|
+
client = resourcemanager_v3.FoldersClient(credentials=credentials)
|
|
30
|
+
# BFS over folders starting at the org root
|
|
31
|
+
queue: List[str] = [org_resource_name]
|
|
32
|
+
seen: set[str] = set()
|
|
33
|
+
while queue:
|
|
34
|
+
parent = queue.pop(0)
|
|
35
|
+
if parent in seen:
|
|
36
|
+
continue
|
|
37
|
+
seen.add(parent)
|
|
38
|
+
|
|
39
|
+
for folder in client.list_folders(parent=parent):
|
|
40
|
+
results.append(
|
|
41
|
+
{
|
|
42
|
+
"name": folder.name,
|
|
43
|
+
"parent": parent,
|
|
44
|
+
"displayName": folder.display_name,
|
|
45
|
+
"lifecycleState": folder.state.name,
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
if folder.name:
|
|
49
|
+
queue.append(folder.name)
|
|
50
|
+
return results
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@timeit
|
|
54
|
+
def transform_gcp_folders(data: List[Dict]) -> List[Dict]:
|
|
55
|
+
"""
|
|
56
|
+
Transform GCP folder data to add parent_org or parent_folder fields based on parent type.
|
|
57
|
+
|
|
58
|
+
:param data: List of folder dicts
|
|
59
|
+
:return: List of transformed folder dicts with parent_org and parent_folder fields
|
|
60
|
+
"""
|
|
61
|
+
for folder in data:
|
|
62
|
+
folder["parent_org"] = None
|
|
63
|
+
folder["parent_folder"] = None
|
|
64
|
+
|
|
65
|
+
if folder["parent"].startswith("organizations"):
|
|
66
|
+
folder["parent_org"] = folder["parent"]
|
|
67
|
+
elif folder["parent"].startswith("folders"):
|
|
68
|
+
folder["parent_folder"] = folder["parent"]
|
|
69
|
+
else:
|
|
70
|
+
logger.warning(
|
|
71
|
+
f"Folder {folder['name']} has unexpected parent type: {folder['parent']}"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
return data
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@timeit
|
|
78
|
+
def load_gcp_folders(
|
|
79
|
+
neo4j_session: neo4j.Session,
|
|
80
|
+
data: List[Dict],
|
|
81
|
+
gcp_update_tag: int,
|
|
82
|
+
org_resource_name: str,
|
|
83
|
+
) -> None:
|
|
84
|
+
"""
|
|
85
|
+
Load GCP folders into the graph.
|
|
86
|
+
:param org_resource_name: Full organization resource name (e.g., "organizations/123456789012")
|
|
87
|
+
"""
|
|
88
|
+
transformed_data = transform_gcp_folders(data)
|
|
89
|
+
load(
|
|
90
|
+
neo4j_session,
|
|
91
|
+
GCPFolderSchema(),
|
|
92
|
+
transformed_data,
|
|
93
|
+
lastupdated=gcp_update_tag,
|
|
94
|
+
ORG_RESOURCE_NAME=org_resource_name,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@timeit
|
|
99
|
+
def sync_gcp_folders(
|
|
100
|
+
neo4j_session: neo4j.Session,
|
|
101
|
+
gcp_update_tag: int,
|
|
102
|
+
common_job_parameters: Dict,
|
|
103
|
+
org_resource_name: str,
|
|
104
|
+
credentials: Optional[GoogleCredentials] = None,
|
|
105
|
+
) -> List[Dict]:
|
|
106
|
+
"""
|
|
107
|
+
Get GCP folder data using the CRM v2 resource object and load the data to Neo4j.
|
|
108
|
+
:param org_resource_name: Full organization resource name (e.g., "organizations/123456789012")
|
|
109
|
+
:return: List of folders synced
|
|
110
|
+
"""
|
|
111
|
+
logger.debug("Syncing GCP folders")
|
|
112
|
+
folders = get_gcp_folders(org_resource_name, credentials=credentials)
|
|
113
|
+
load_gcp_folders(neo4j_session, folders, gcp_update_tag, org_resource_name)
|
|
114
|
+
return folders
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Dict
|
|
3
|
+
from typing import List
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
import neo4j
|
|
7
|
+
from google.auth.credentials import Credentials as GoogleCredentials
|
|
8
|
+
from google.cloud import resourcemanager_v3
|
|
9
|
+
|
|
10
|
+
from cartography.client.core.tx import load
|
|
11
|
+
from cartography.models.gcp.crm.organizations import GCPOrganizationSchema
|
|
12
|
+
from cartography.util import timeit
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@timeit
|
|
18
|
+
def get_gcp_organizations(
|
|
19
|
+
credentials: Optional[GoogleCredentials] = None,
|
|
20
|
+
) -> List[Dict]:
|
|
21
|
+
"""
|
|
22
|
+
Return list of GCP organizations that the authenticated principal can access using the high-level client.
|
|
23
|
+
Returns empty list on error.
|
|
24
|
+
:return: List of org dicts with keys: name, displayName, lifecycleState.
|
|
25
|
+
"""
|
|
26
|
+
client = resourcemanager_v3.OrganizationsClient(credentials=credentials)
|
|
27
|
+
orgs = []
|
|
28
|
+
for org in client.search_organizations():
|
|
29
|
+
orgs.append(
|
|
30
|
+
{
|
|
31
|
+
"name": org.name,
|
|
32
|
+
"displayName": org.display_name,
|
|
33
|
+
"lifecycleState": org.state.name,
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
return orgs
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@timeit
|
|
40
|
+
def load_gcp_organizations(
|
|
41
|
+
neo4j_session: neo4j.Session,
|
|
42
|
+
data: List[Dict],
|
|
43
|
+
gcp_update_tag: int,
|
|
44
|
+
) -> None:
|
|
45
|
+
for org in data:
|
|
46
|
+
org["id"] = org["name"]
|
|
47
|
+
|
|
48
|
+
load(
|
|
49
|
+
neo4j_session,
|
|
50
|
+
GCPOrganizationSchema(),
|
|
51
|
+
data,
|
|
52
|
+
lastupdated=gcp_update_tag,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@timeit
|
|
57
|
+
def sync_gcp_organizations(
|
|
58
|
+
neo4j_session: neo4j.Session,
|
|
59
|
+
gcp_update_tag: int,
|
|
60
|
+
common_job_parameters: Dict,
|
|
61
|
+
credentials: Optional[GoogleCredentials] = None,
|
|
62
|
+
) -> List[Dict]:
|
|
63
|
+
"""
|
|
64
|
+
Get GCP organization data using the CRM v1 resource object and load the data to Neo4j.
|
|
65
|
+
Returns the list of organizations synced.
|
|
66
|
+
"""
|
|
67
|
+
logger.debug("Syncing GCP organizations")
|
|
68
|
+
data = get_gcp_organizations(credentials=credentials)
|
|
69
|
+
load_gcp_organizations(neo4j_session, data, gcp_update_tag)
|
|
70
|
+
return data
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Dict
|
|
3
|
+
from typing import List
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
import neo4j
|
|
7
|
+
from google.auth.credentials import Credentials as GoogleCredentials
|
|
8
|
+
from google.cloud import resourcemanager_v3
|
|
9
|
+
|
|
10
|
+
from cartography.client.core.tx import load
|
|
11
|
+
from cartography.models.gcp.crm.projects import GCPProjectSchema
|
|
12
|
+
from cartography.util import timeit
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@timeit
|
|
18
|
+
def get_gcp_projects(
|
|
19
|
+
org_resource_name: str,
|
|
20
|
+
folders: List[Dict],
|
|
21
|
+
credentials: Optional[GoogleCredentials] = None,
|
|
22
|
+
) -> List[Dict]:
|
|
23
|
+
"""
|
|
24
|
+
Return list of ACTIVE GCP projects under the specified organization
|
|
25
|
+
and within the specified folders.
|
|
26
|
+
:param org_resource_name: Full organization resource name (e.g., "organizations/123456789012")
|
|
27
|
+
:param folders: List of folder dictionaries containing 'name' field with full resource names
|
|
28
|
+
"""
|
|
29
|
+
folder_names = [folder["name"] for folder in folders] if folders else []
|
|
30
|
+
# Build list of parent resources to check (org and all folders)
|
|
31
|
+
parents = set([org_resource_name] + folder_names)
|
|
32
|
+
results: List[Dict] = []
|
|
33
|
+
for parent in parents:
|
|
34
|
+
client = resourcemanager_v3.ProjectsClient(credentials=credentials)
|
|
35
|
+
for proj in client.list_projects(parent=parent):
|
|
36
|
+
# list_projects returns ACTIVE projects by default
|
|
37
|
+
name_field = proj.name # "projects/<number>"
|
|
38
|
+
project_number = name_field.split("/")[-1] if name_field else None
|
|
39
|
+
project_parent = proj.parent
|
|
40
|
+
results.append(
|
|
41
|
+
{
|
|
42
|
+
"projectId": getattr(proj, "project_id", None),
|
|
43
|
+
"projectNumber": project_number,
|
|
44
|
+
"name": getattr(proj, "display_name", None),
|
|
45
|
+
"lifecycleState": proj.state.name,
|
|
46
|
+
"parent": project_parent,
|
|
47
|
+
}
|
|
48
|
+
)
|
|
49
|
+
return results
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@timeit
|
|
53
|
+
def transform_gcp_projects(data: List[Dict]) -> List[Dict]:
|
|
54
|
+
"""
|
|
55
|
+
Transform GCP project data to add parent_org or parent_folder fields based on parent type.
|
|
56
|
+
|
|
57
|
+
:param data: List of project dicts
|
|
58
|
+
:return: List of transformed project dicts with parent_org and parent_folder fields
|
|
59
|
+
"""
|
|
60
|
+
for project in data:
|
|
61
|
+
project["parent_org"] = None
|
|
62
|
+
project["parent_folder"] = None
|
|
63
|
+
|
|
64
|
+
# Set parent fields based on parent type
|
|
65
|
+
if project["parent"].startswith("organizations"):
|
|
66
|
+
project["parent_org"] = project["parent"]
|
|
67
|
+
elif project["parent"].startswith("folders"):
|
|
68
|
+
project["parent_folder"] = project["parent"]
|
|
69
|
+
else:
|
|
70
|
+
logger.warning(
|
|
71
|
+
f"Project {project['projectId']} has unexpected parent type: {project['parent']}"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
return data
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@timeit
|
|
78
|
+
def load_gcp_projects(
|
|
79
|
+
neo4j_session: neo4j.Session,
|
|
80
|
+
data: List[Dict],
|
|
81
|
+
gcp_update_tag: int,
|
|
82
|
+
org_resource_name: str,
|
|
83
|
+
) -> None:
|
|
84
|
+
"""
|
|
85
|
+
Load GCP projects into the graph.
|
|
86
|
+
:param org_resource_name: Full organization resource name (e.g., "organizations/123456789012")
|
|
87
|
+
"""
|
|
88
|
+
transformed_data = transform_gcp_projects(data)
|
|
89
|
+
load(
|
|
90
|
+
neo4j_session,
|
|
91
|
+
GCPProjectSchema(),
|
|
92
|
+
transformed_data,
|
|
93
|
+
lastupdated=gcp_update_tag,
|
|
94
|
+
ORG_RESOURCE_NAME=org_resource_name,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@timeit
|
|
99
|
+
def sync_gcp_projects(
|
|
100
|
+
neo4j_session: neo4j.Session,
|
|
101
|
+
org_resource_name: str,
|
|
102
|
+
folders: List[Dict],
|
|
103
|
+
gcp_update_tag: int,
|
|
104
|
+
common_job_parameters: Dict,
|
|
105
|
+
credentials: Optional[GoogleCredentials] = None,
|
|
106
|
+
) -> List[Dict]:
|
|
107
|
+
"""
|
|
108
|
+
Get and sync GCP project data to Neo4j.
|
|
109
|
+
:param org_resource_name: Full organization resource name (e.g., "organizations/123456789012")
|
|
110
|
+
:param folders: List of folder dictionaries containing 'name' field with full resource names
|
|
111
|
+
:return: List of projects synced
|
|
112
|
+
"""
|
|
113
|
+
logger.debug("Syncing GCP projects")
|
|
114
|
+
projects = get_gcp_projects(
|
|
115
|
+
org_resource_name,
|
|
116
|
+
folders,
|
|
117
|
+
credentials=credentials,
|
|
118
|
+
)
|
|
119
|
+
load_gcp_projects(neo4j_session, projects, gcp_update_tag, org_resource_name)
|
|
120
|
+
return projects
|
cartography/intel/gcp/dns.py
CHANGED
|
@@ -7,235 +7,190 @@ import neo4j
|
|
|
7
7
|
from googleapiclient.discovery import HttpError
|
|
8
8
|
from googleapiclient.discovery import Resource
|
|
9
9
|
|
|
10
|
-
from cartography.
|
|
10
|
+
from cartography.client.core.tx import load
|
|
11
|
+
from cartography.graph.job import GraphJob
|
|
12
|
+
from cartography.models.gcp.dns import GCPDNSZoneSchema
|
|
13
|
+
from cartography.models.gcp.dns import GCPRecordSetSchema
|
|
11
14
|
from cartography.util import timeit
|
|
12
15
|
|
|
13
16
|
logger = logging.getLogger(__name__)
|
|
14
17
|
|
|
15
18
|
|
|
16
19
|
@timeit
|
|
17
|
-
def get_dns_zones(dns: Resource, project_id: str) -> List[
|
|
18
|
-
"""
|
|
19
|
-
Returns a list of DNS zones within the given project.
|
|
20
|
-
|
|
21
|
-
:type dns: The GCP DNS resource object
|
|
22
|
-
:param dns: The DNS resource object created by googleapiclient.discovery.build()
|
|
23
|
-
|
|
24
|
-
:type project_id: str
|
|
25
|
-
:param project_id: Current Google Project Id
|
|
26
|
-
|
|
27
|
-
:rtype: list
|
|
28
|
-
:return: List of DNS zones
|
|
29
|
-
"""
|
|
20
|
+
def get_dns_zones(dns: Resource, project_id: str) -> List[Dict]:
|
|
21
|
+
"""Returns a list of DNS zones within the given project."""
|
|
30
22
|
try:
|
|
31
|
-
zones = []
|
|
23
|
+
zones: List[Dict] = []
|
|
32
24
|
request = dns.managedZones().list(project=project_id)
|
|
33
25
|
while request is not None:
|
|
34
26
|
response = request.execute()
|
|
35
|
-
for managed_zone in response[
|
|
27
|
+
for managed_zone in response["managedZones"]:
|
|
36
28
|
zones.append(managed_zone)
|
|
37
|
-
request = dns.managedZones().list_next(
|
|
29
|
+
request = dns.managedZones().list_next(
|
|
30
|
+
previous_request=request,
|
|
31
|
+
previous_response=response,
|
|
32
|
+
)
|
|
38
33
|
return zones
|
|
39
34
|
except HttpError as e:
|
|
40
|
-
err = json.loads(e.content.decode(
|
|
41
|
-
if
|
|
35
|
+
err = json.loads(e.content.decode("utf-8"))["error"]
|
|
36
|
+
if (
|
|
37
|
+
err.get("status", "") == "PERMISSION_DENIED"
|
|
38
|
+
or err.get("message", "") == "Forbidden"
|
|
39
|
+
):
|
|
42
40
|
logger.warning(
|
|
43
41
|
(
|
|
44
|
-
"Could not retrieve DNS zones on project %s due to permissions issues.
|
|
45
|
-
|
|
42
|
+
"Could not retrieve DNS zones on project %s due to permissions issues. "
|
|
43
|
+
"Code: %s, Message: %s"
|
|
44
|
+
),
|
|
45
|
+
project_id,
|
|
46
|
+
err["code"],
|
|
47
|
+
err["message"],
|
|
46
48
|
)
|
|
47
49
|
return []
|
|
48
|
-
|
|
49
|
-
raise
|
|
50
|
+
raise
|
|
50
51
|
|
|
51
52
|
|
|
52
53
|
@timeit
|
|
53
|
-
def get_dns_rrs(dns: Resource, dns_zones: List[Dict], project_id: str) -> List[
|
|
54
|
-
"""
|
|
55
|
-
Returns a list of DNS Resource Record Sets within the given project.
|
|
56
|
-
|
|
57
|
-
:type dns: The GCP DNS resource object
|
|
58
|
-
:param dns: The DNS resource object created by googleapiclient.discovery.build()
|
|
59
|
-
|
|
60
|
-
:type dns_zones: list
|
|
61
|
-
:param dns_zones: List of DNS zones for the project
|
|
62
|
-
|
|
63
|
-
:type project_id: str
|
|
64
|
-
:param project_id: Current Google Project Id
|
|
65
|
-
|
|
66
|
-
:rtype: list
|
|
67
|
-
:return: List of Resource Record Sets
|
|
68
|
-
"""
|
|
54
|
+
def get_dns_rrs(dns: Resource, dns_zones: List[Dict], project_id: str) -> List[Dict]:
|
|
55
|
+
"""Returns a list of DNS Resource Record Sets within the given project."""
|
|
69
56
|
try:
|
|
70
|
-
rrs: List[
|
|
57
|
+
rrs: List[Dict] = []
|
|
71
58
|
for zone in dns_zones:
|
|
72
|
-
request = dns.resourceRecordSets().list(
|
|
59
|
+
request = dns.resourceRecordSets().list(
|
|
60
|
+
project=project_id,
|
|
61
|
+
managedZone=zone["id"],
|
|
62
|
+
)
|
|
73
63
|
while request is not None:
|
|
74
64
|
response = request.execute()
|
|
75
|
-
for resource_record_set in response[
|
|
76
|
-
resource_record_set[
|
|
65
|
+
for resource_record_set in response["rrsets"]:
|
|
66
|
+
resource_record_set["zone"] = zone["id"]
|
|
77
67
|
rrs.append(resource_record_set)
|
|
78
|
-
request = dns.resourceRecordSets().list_next(
|
|
68
|
+
request = dns.resourceRecordSets().list_next(
|
|
69
|
+
previous_request=request,
|
|
70
|
+
previous_response=response,
|
|
71
|
+
)
|
|
79
72
|
return rrs
|
|
80
73
|
except HttpError as e:
|
|
81
|
-
err = json.loads(e.content.decode(
|
|
82
|
-
if
|
|
74
|
+
err = json.loads(e.content.decode("utf-8"))["error"]
|
|
75
|
+
if (
|
|
76
|
+
err.get("status", "") == "PERMISSION_DENIED"
|
|
77
|
+
or err.get("message", "") == "Forbidden"
|
|
78
|
+
):
|
|
83
79
|
logger.warning(
|
|
84
80
|
(
|
|
85
|
-
"Could not retrieve DNS RRS on project %s due to permissions issues.
|
|
86
|
-
|
|
81
|
+
"Could not retrieve DNS RRS on project %s due to permissions issues. "
|
|
82
|
+
"Code: %s, Message: %s"
|
|
83
|
+
),
|
|
84
|
+
project_id,
|
|
85
|
+
err["code"],
|
|
86
|
+
err["message"],
|
|
87
87
|
)
|
|
88
88
|
return []
|
|
89
|
-
|
|
90
|
-
raise
|
|
91
|
-
raise e
|
|
89
|
+
raise
|
|
92
90
|
|
|
93
91
|
|
|
94
92
|
@timeit
|
|
95
|
-
def
|
|
96
|
-
"""
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
:return: Nothing
|
|
113
|
-
"""
|
|
114
|
-
|
|
115
|
-
ingest_records = """
|
|
116
|
-
UNWIND $records as record
|
|
117
|
-
MERGE(zone:GCPDNSZone{id:record.id})
|
|
118
|
-
ON CREATE SET
|
|
119
|
-
zone.firstseen = timestamp(),
|
|
120
|
-
zone.created_at = record.creationTime
|
|
121
|
-
SET
|
|
122
|
-
zone.name = record.name,
|
|
123
|
-
zone.dns_name = record.dnsName,
|
|
124
|
-
zone.description = record.description,
|
|
125
|
-
zone.visibility = record.visibility,
|
|
126
|
-
zone.kind = record.kind,
|
|
127
|
-
zone.nameservers = record.nameServers,
|
|
128
|
-
zone.lastupdated = $gcp_update_tag
|
|
129
|
-
WITH zone
|
|
130
|
-
MATCH (owner:GCPProject{id:$ProjectId})
|
|
131
|
-
MERGE (owner)-[r:RESOURCE]->(zone)
|
|
132
|
-
ON CREATE SET
|
|
133
|
-
r.firstseen = timestamp(),
|
|
134
|
-
r.lastupdated = $gcp_update_tag
|
|
135
|
-
"""
|
|
136
|
-
neo4j_session.run(
|
|
137
|
-
ingest_records,
|
|
138
|
-
records=dns_zones,
|
|
139
|
-
ProjectId=project_id,
|
|
140
|
-
gcp_update_tag=gcp_update_tag,
|
|
141
|
-
)
|
|
93
|
+
def transform_dns_zones(dns_zones: List[Dict]) -> List[Dict]:
|
|
94
|
+
"""Transform raw DNS zone responses into Neo4j-ready dicts."""
|
|
95
|
+
zones: List[Dict] = []
|
|
96
|
+
for z in dns_zones:
|
|
97
|
+
zones.append(
|
|
98
|
+
{
|
|
99
|
+
"id": z["id"],
|
|
100
|
+
"name": z.get("name"),
|
|
101
|
+
"dns_name": z.get("dnsName"),
|
|
102
|
+
"description": z.get("description"),
|
|
103
|
+
"visibility": z.get("visibility"),
|
|
104
|
+
"kind": z.get("kind"),
|
|
105
|
+
"nameservers": z.get("nameServers"),
|
|
106
|
+
"created_at": z.get("creationTime"),
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
return zones
|
|
142
110
|
|
|
143
111
|
|
|
144
112
|
@timeit
|
|
145
|
-
def
|
|
146
|
-
"""
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
:rtype: NoneType
|
|
162
|
-
:return: Nothing
|
|
163
|
-
"""
|
|
164
|
-
|
|
165
|
-
ingest_records = """
|
|
166
|
-
UNWIND $records as record
|
|
167
|
-
MERGE(rrs:GCPRecordSet{id:record.name})
|
|
168
|
-
ON CREATE SET
|
|
169
|
-
rrs.firstseen = timestamp()
|
|
170
|
-
SET
|
|
171
|
-
rrs.name = record.name,
|
|
172
|
-
rrs.type = record.type,
|
|
173
|
-
rrs.ttl = record.ttl,
|
|
174
|
-
rrs.data = record.rrdatas,
|
|
175
|
-
rrs.lastupdated = $gcp_update_tag
|
|
176
|
-
WITH rrs, record
|
|
177
|
-
MATCH (zone:GCPDNSZone{id:record.zone})
|
|
178
|
-
MERGE (zone)-[r:HAS_RECORD]->(rrs)
|
|
179
|
-
ON CREATE SET
|
|
180
|
-
r.firstseen = timestamp(),
|
|
181
|
-
r.lastupdated = $gcp_update_tag
|
|
182
|
-
"""
|
|
183
|
-
neo4j_session.run(
|
|
184
|
-
ingest_records,
|
|
185
|
-
records=dns_rrs,
|
|
186
|
-
gcp_update_tag=gcp_update_tag,
|
|
187
|
-
)
|
|
113
|
+
def transform_dns_rrs(dns_rrs: List[Dict]) -> List[Dict]:
|
|
114
|
+
"""Transform raw DNS record set responses into Neo4j-ready dicts."""
|
|
115
|
+
records: List[Dict] = []
|
|
116
|
+
for r in dns_rrs:
|
|
117
|
+
records.append(
|
|
118
|
+
{
|
|
119
|
+
# Compose a unique ID to avoid collisions across types and zones
|
|
120
|
+
"id": f"{r['name']}|{r.get('type')}|{r.get('zone')}",
|
|
121
|
+
"name": r["name"],
|
|
122
|
+
"type": r.get("type"),
|
|
123
|
+
"ttl": r.get("ttl"),
|
|
124
|
+
"data": r.get("rrdatas"),
|
|
125
|
+
"zone_id": r.get("zone"),
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
return records
|
|
188
129
|
|
|
189
130
|
|
|
190
131
|
@timeit
|
|
191
|
-
def
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
:
|
|
196
|
-
|
|
132
|
+
def load_dns_zones(
|
|
133
|
+
neo4j_session: neo4j.Session,
|
|
134
|
+
dns_zones: List[Dict],
|
|
135
|
+
project_id: str,
|
|
136
|
+
gcp_update_tag: int,
|
|
137
|
+
) -> None:
|
|
138
|
+
"""Ingest GCP DNS Zones into Neo4j."""
|
|
139
|
+
load(
|
|
140
|
+
neo4j_session,
|
|
141
|
+
GCPDNSZoneSchema(),
|
|
142
|
+
dns_zones,
|
|
143
|
+
lastupdated=gcp_update_tag,
|
|
144
|
+
PROJECT_ID=project_id,
|
|
145
|
+
)
|
|
197
146
|
|
|
198
|
-
:type common_job_parameters: dict
|
|
199
|
-
:param common_job_parameters: Dictionary of other job parameters to pass to Neo4j
|
|
200
147
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
148
|
+
@timeit
|
|
149
|
+
def load_rrs(
|
|
150
|
+
neo4j_session: neo4j.Session,
|
|
151
|
+
dns_rrs: List[Dict],
|
|
152
|
+
project_id: str,
|
|
153
|
+
gcp_update_tag: int,
|
|
154
|
+
) -> None:
|
|
155
|
+
"""Ingest GCP DNS Resource Record Sets into Neo4j."""
|
|
156
|
+
load(
|
|
157
|
+
neo4j_session,
|
|
158
|
+
GCPRecordSetSchema(),
|
|
159
|
+
dns_rrs,
|
|
160
|
+
lastupdated=gcp_update_tag,
|
|
161
|
+
PROJECT_ID=project_id,
|
|
162
|
+
)
|
|
205
163
|
|
|
206
164
|
|
|
207
165
|
@timeit
|
|
208
|
-
def
|
|
209
|
-
neo4j_session: neo4j.Session,
|
|
166
|
+
def cleanup_dns_records(
|
|
167
|
+
neo4j_session: neo4j.Session,
|
|
210
168
|
common_job_parameters: Dict,
|
|
211
169
|
) -> None:
|
|
212
|
-
"""
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
:type project_id: str
|
|
222
|
-
:param project_id: The project ID of the corresponding project
|
|
223
|
-
|
|
224
|
-
:type gcp_update_tag: timestamp
|
|
225
|
-
:param gcp_update_tag: The timestamp value to set our new Neo4j nodes with
|
|
170
|
+
"""Delete out-of-date GCP DNS Zones and Record Sets nodes and relationships."""
|
|
171
|
+
# Record sets depend on zones, so clean them up first.
|
|
172
|
+
GraphJob.from_node_schema(GCPRecordSetSchema(), common_job_parameters).run(
|
|
173
|
+
neo4j_session,
|
|
174
|
+
)
|
|
175
|
+
GraphJob.from_node_schema(GCPDNSZoneSchema(), common_job_parameters).run(
|
|
176
|
+
neo4j_session,
|
|
177
|
+
)
|
|
226
178
|
|
|
227
|
-
:type common_job_parameters: dict
|
|
228
|
-
:param common_job_parameters: Dictionary of other job parameters to pass to Neo4j
|
|
229
179
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
180
|
+
@timeit
|
|
181
|
+
def sync(
|
|
182
|
+
neo4j_session: neo4j.Session,
|
|
183
|
+
dns: Resource,
|
|
184
|
+
project_id: str,
|
|
185
|
+
gcp_update_tag: int,
|
|
186
|
+
common_job_parameters: Dict,
|
|
187
|
+
) -> None:
|
|
188
|
+
"""Get GCP DNS Zones and Record Sets, load them into Neo4j, and clean up old data."""
|
|
233
189
|
logger.info("Syncing DNS records for project %s.", project_id)
|
|
234
|
-
|
|
235
|
-
dns_zones =
|
|
190
|
+
dns_zones_resp = get_dns_zones(dns, project_id)
|
|
191
|
+
dns_zones = transform_dns_zones(dns_zones_resp)
|
|
236
192
|
load_dns_zones(neo4j_session, dns_zones, project_id, gcp_update_tag)
|
|
237
|
-
|
|
238
|
-
dns_rrs =
|
|
193
|
+
dns_rrs_resp = get_dns_rrs(dns, dns_zones_resp, project_id)
|
|
194
|
+
dns_rrs = transform_dns_rrs(dns_rrs_resp)
|
|
239
195
|
load_rrs(neo4j_session, dns_rrs, project_id, gcp_update_tag)
|
|
240
|
-
# TODO scope the cleanup to the current project - https://github.com/lyft/cartography/issues/381
|
|
241
196
|
cleanup_dns_records(neo4j_session, common_job_parameters)
|