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/azure/sql.py
CHANGED
|
@@ -2,6 +2,7 @@ import logging
|
|
|
2
2
|
from typing import Any
|
|
3
3
|
from typing import Dict
|
|
4
4
|
from typing import Generator
|
|
5
|
+
from typing import Iterable
|
|
5
6
|
from typing import List
|
|
6
7
|
from typing import Tuple
|
|
7
8
|
|
|
@@ -14,10 +15,34 @@ from azure.mgmt.sql.models import SecurityAlertPolicyName
|
|
|
14
15
|
from azure.mgmt.sql.models import TransparentDataEncryptionName
|
|
15
16
|
from msrestazure.azure_exceptions import CloudError
|
|
16
17
|
|
|
17
|
-
from .
|
|
18
|
-
from cartography.
|
|
18
|
+
from cartography.client.core.tx import load
|
|
19
|
+
from cartography.graph.job import GraphJob
|
|
20
|
+
from cartography.models.azure.sql.databasethreatdetectionpolicy import (
|
|
21
|
+
AzureDatabaseThreatDetectionPolicySchema,
|
|
22
|
+
)
|
|
23
|
+
from cartography.models.azure.sql.elasticpool import AzureElasticPoolSchema
|
|
24
|
+
from cartography.models.azure.sql.failovergroup import AzureFailoverGroupSchema
|
|
25
|
+
from cartography.models.azure.sql.recoverabledatabase import (
|
|
26
|
+
AzureRecoverableDatabaseSchema,
|
|
27
|
+
)
|
|
28
|
+
from cartography.models.azure.sql.replicationlink import AzureReplicationLinkSchema
|
|
29
|
+
from cartography.models.azure.sql.restorabledroppeddatabase import (
|
|
30
|
+
AzureRestorableDroppedDatabaseSchema,
|
|
31
|
+
)
|
|
32
|
+
from cartography.models.azure.sql.restorepoint import AzureRestorePointSchema
|
|
33
|
+
from cartography.models.azure.sql.serveradadministrator import (
|
|
34
|
+
AzureServerADAdministratorSchema,
|
|
35
|
+
)
|
|
36
|
+
from cartography.models.azure.sql.serverdnsalias import AzureServerDNSAliasSchema
|
|
37
|
+
from cartography.models.azure.sql.sqldatabase import AzureSQLDatabaseSchema
|
|
38
|
+
from cartography.models.azure.sql.sqlserver import AzureSQLServerSchema
|
|
39
|
+
from cartography.models.azure.sql.transparentdataencryption import (
|
|
40
|
+
AzureTransparentDataEncryptionSchema,
|
|
41
|
+
)
|
|
19
42
|
from cartography.util import timeit
|
|
20
43
|
|
|
44
|
+
from .util.credentials import Credentials
|
|
45
|
+
|
|
21
46
|
logger = logging.getLogger(__name__)
|
|
22
47
|
|
|
23
48
|
|
|
@@ -51,57 +76,45 @@ def get_server_list(credentials: Credentials, subscription_id: str) -> List[Dict
|
|
|
51
76
|
return []
|
|
52
77
|
|
|
53
78
|
for server in server_list:
|
|
54
|
-
x = server[
|
|
55
|
-
server[
|
|
79
|
+
x = server["id"].split("/")
|
|
80
|
+
server["resourceGroup"] = x[x.index("resourceGroups") + 1]
|
|
56
81
|
|
|
57
82
|
return server_list
|
|
58
83
|
|
|
59
84
|
|
|
60
85
|
@timeit
|
|
61
86
|
def load_server_data(
|
|
62
|
-
|
|
63
|
-
|
|
87
|
+
neo4j_session: neo4j.Session,
|
|
88
|
+
subscription_id: str,
|
|
89
|
+
server_list: List[Dict],
|
|
90
|
+
azure_update_tag: int,
|
|
64
91
|
) -> None:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
MERGE (s:AzureSQLServer{id: server.id})
|
|
71
|
-
ON CREATE SET s.firstseen = timestamp(),
|
|
72
|
-
s.resourcegroup = server.resourceGroup, s.location = server.location
|
|
73
|
-
SET s.lastupdated = $azure_update_tag,
|
|
74
|
-
s.name = server.name,
|
|
75
|
-
s.kind = server.kind,
|
|
76
|
-
s.state = server.state,
|
|
77
|
-
s.version = server.version
|
|
78
|
-
WITH s
|
|
79
|
-
MATCH (owner:AzureSubscription{id: $AZURE_SUBSCRIPTION_ID})
|
|
80
|
-
MERGE (owner)-[r:RESOURCE]->(s)
|
|
81
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
82
|
-
SET r.lastupdated = $azure_update_tag
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
neo4j_session.run(
|
|
86
|
-
ingest_server,
|
|
87
|
-
server_list=server_list,
|
|
92
|
+
load(
|
|
93
|
+
neo4j_session,
|
|
94
|
+
AzureSQLServerSchema(),
|
|
95
|
+
server_list,
|
|
96
|
+
lastupdated=azure_update_tag,
|
|
88
97
|
AZURE_SUBSCRIPTION_ID=subscription_id,
|
|
89
|
-
azure_update_tag=azure_update_tag,
|
|
90
98
|
)
|
|
91
99
|
|
|
92
100
|
|
|
93
101
|
@timeit
|
|
94
102
|
def sync_server_details(
|
|
95
|
-
|
|
96
|
-
|
|
103
|
+
neo4j_session: neo4j.Session,
|
|
104
|
+
credentials: Credentials,
|
|
105
|
+
subscription_id: str,
|
|
106
|
+
server_list: List[Dict],
|
|
107
|
+
sync_tag: int,
|
|
97
108
|
) -> None:
|
|
98
109
|
details = get_server_details(credentials, subscription_id, server_list)
|
|
99
|
-
load_server_details(neo4j_session, credentials, subscription_id, details, sync_tag)
|
|
110
|
+
load_server_details(neo4j_session, credentials, subscription_id, details, sync_tag)
|
|
100
111
|
|
|
101
112
|
|
|
102
113
|
@timeit
|
|
103
114
|
def get_server_details(
|
|
104
|
-
|
|
115
|
+
credentials: Credentials,
|
|
116
|
+
subscription_id: str,
|
|
117
|
+
server_list: List[Dict],
|
|
105
118
|
) -> Generator[Any, Any, Any]:
|
|
106
119
|
"""
|
|
107
120
|
Iterate over each servers to get its resource details.
|
|
@@ -110,17 +123,25 @@ def get_server_details(
|
|
|
110
123
|
dns_alias = get_dns_aliases(credentials, subscription_id, server)
|
|
111
124
|
ad_admins = get_ad_admins(credentials, subscription_id, server)
|
|
112
125
|
r_databases = get_recoverable_databases(credentials, subscription_id, server)
|
|
113
|
-
rd_databases = get_restorable_dropped_databases(
|
|
126
|
+
rd_databases = get_restorable_dropped_databases(
|
|
127
|
+
credentials,
|
|
128
|
+
subscription_id,
|
|
129
|
+
server,
|
|
130
|
+
)
|
|
114
131
|
fgs = get_failover_groups(credentials, subscription_id, server)
|
|
115
132
|
elastic_pools = get_elastic_pools(credentials, subscription_id, server)
|
|
116
133
|
databases = get_databases(credentials, subscription_id, server)
|
|
117
|
-
yield server[
|
|
118
|
-
|
|
134
|
+
yield server["id"], server["name"], server[
|
|
135
|
+
"resourceGroup"
|
|
119
136
|
], dns_alias, ad_admins, r_databases, rd_databases, fgs, elastic_pools, databases
|
|
120
137
|
|
|
121
138
|
|
|
122
139
|
@timeit
|
|
123
|
-
def get_dns_aliases(
|
|
140
|
+
def get_dns_aliases(
|
|
141
|
+
credentials: Credentials,
|
|
142
|
+
subscription_id: str,
|
|
143
|
+
server: Dict,
|
|
144
|
+
) -> List[Dict]:
|
|
124
145
|
"""
|
|
125
146
|
Returns details of the DNS aliases in a server.
|
|
126
147
|
"""
|
|
@@ -129,12 +150,17 @@ def get_dns_aliases(credentials: Credentials, subscription_id: str, server: Dict
|
|
|
129
150
|
dns_aliases = list(
|
|
130
151
|
map(
|
|
131
152
|
lambda x: x.as_dict(),
|
|
132
|
-
client.server_dns_aliases.list_by_server(
|
|
153
|
+
client.server_dns_aliases.list_by_server(
|
|
154
|
+
server["resourceGroup"],
|
|
155
|
+
server["name"],
|
|
156
|
+
),
|
|
133
157
|
),
|
|
134
158
|
)
|
|
135
159
|
|
|
136
160
|
except ClientAuthenticationError as e:
|
|
137
|
-
logger.warning(
|
|
161
|
+
logger.warning(
|
|
162
|
+
f"Client Authentication Error while retrieving DNS Aliases - {e}",
|
|
163
|
+
)
|
|
138
164
|
return []
|
|
139
165
|
except ResourceNotFoundError as e:
|
|
140
166
|
logger.warning(f"DNS Alias resource not found error - {e}")
|
|
@@ -147,7 +173,11 @@ def get_dns_aliases(credentials: Credentials, subscription_id: str, server: Dict
|
|
|
147
173
|
|
|
148
174
|
|
|
149
175
|
@timeit
|
|
150
|
-
def get_ad_admins(
|
|
176
|
+
def get_ad_admins(
|
|
177
|
+
credentials: Credentials,
|
|
178
|
+
subscription_id: str,
|
|
179
|
+
server: Dict,
|
|
180
|
+
) -> List[Dict]:
|
|
151
181
|
"""
|
|
152
182
|
Returns details of the Server AD Administrators in a server.
|
|
153
183
|
"""
|
|
@@ -157,14 +187,16 @@ def get_ad_admins(credentials: Credentials, subscription_id: str, server: Dict)
|
|
|
157
187
|
map(
|
|
158
188
|
lambda x: x.as_dict(),
|
|
159
189
|
client.server_azure_ad_administrators.list_by_server(
|
|
160
|
-
server[
|
|
161
|
-
server[
|
|
190
|
+
server["resourceGroup"],
|
|
191
|
+
server["name"],
|
|
162
192
|
),
|
|
163
193
|
),
|
|
164
194
|
)
|
|
165
195
|
|
|
166
196
|
except ClientAuthenticationError as e:
|
|
167
|
-
logger.warning(
|
|
197
|
+
logger.warning(
|
|
198
|
+
f"Client Authentication Error while retrieving Azure AD Administrators - {e}",
|
|
199
|
+
)
|
|
168
200
|
return []
|
|
169
201
|
except ResourceNotFoundError as e:
|
|
170
202
|
logger.warning(f"Azure AD Administrators resource not found error - {e}")
|
|
@@ -177,7 +209,11 @@ def get_ad_admins(credentials: Credentials, subscription_id: str, server: Dict)
|
|
|
177
209
|
|
|
178
210
|
|
|
179
211
|
@timeit
|
|
180
|
-
def get_recoverable_databases(
|
|
212
|
+
def get_recoverable_databases(
|
|
213
|
+
credentials: Credentials,
|
|
214
|
+
subscription_id: str,
|
|
215
|
+
server: Dict,
|
|
216
|
+
) -> List[Dict]:
|
|
181
217
|
"""
|
|
182
218
|
Returns details of the Recoverable databases in a server.
|
|
183
219
|
"""
|
|
@@ -187,8 +223,8 @@ def get_recoverable_databases(credentials: Credentials, subscription_id: str, se
|
|
|
187
223
|
map(
|
|
188
224
|
lambda x: x.as_dict(),
|
|
189
225
|
client.recoverable_databases.list_by_server(
|
|
190
|
-
server[
|
|
191
|
-
server[
|
|
226
|
+
server["resourceGroup"],
|
|
227
|
+
server["name"],
|
|
192
228
|
),
|
|
193
229
|
),
|
|
194
230
|
)
|
|
@@ -197,7 +233,9 @@ def get_recoverable_databases(credentials: Credentials, subscription_id: str, se
|
|
|
197
233
|
# The API returns a '404 CloudError: Not Found for url: <url>' if no recoverable databases are present.
|
|
198
234
|
return []
|
|
199
235
|
except ClientAuthenticationError as e:
|
|
200
|
-
logger.warning(
|
|
236
|
+
logger.warning(
|
|
237
|
+
f"Client Authentication Error while retrieving recoverable databases - {e}",
|
|
238
|
+
)
|
|
201
239
|
return []
|
|
202
240
|
except ResourceNotFoundError as e:
|
|
203
241
|
logger.warning(f"Recoverable databases resource not found error - {e}")
|
|
@@ -210,7 +248,11 @@ def get_recoverable_databases(credentials: Credentials, subscription_id: str, se
|
|
|
210
248
|
|
|
211
249
|
|
|
212
250
|
@timeit
|
|
213
|
-
def get_restorable_dropped_databases(
|
|
251
|
+
def get_restorable_dropped_databases(
|
|
252
|
+
credentials: Credentials,
|
|
253
|
+
subscription_id: str,
|
|
254
|
+
server: Dict,
|
|
255
|
+
) -> List[Dict]:
|
|
214
256
|
"""
|
|
215
257
|
Returns details of the Restorable Dropped Databases in a server.
|
|
216
258
|
"""
|
|
@@ -220,13 +262,16 @@ def get_restorable_dropped_databases(credentials: Credentials, subscription_id:
|
|
|
220
262
|
map(
|
|
221
263
|
lambda x: x.as_dict(),
|
|
222
264
|
client.restorable_dropped_databases.list_by_server(
|
|
223
|
-
server[
|
|
265
|
+
server["resourceGroup"],
|
|
266
|
+
server["name"],
|
|
224
267
|
),
|
|
225
268
|
),
|
|
226
269
|
)
|
|
227
270
|
|
|
228
271
|
except ClientAuthenticationError as e:
|
|
229
|
-
logger.warning(
|
|
272
|
+
logger.warning(
|
|
273
|
+
f"Client Authentication Error while retrieving Restorable Dropped Databases - {e}",
|
|
274
|
+
)
|
|
230
275
|
return []
|
|
231
276
|
except ResourceNotFoundError as e:
|
|
232
277
|
logger.warning(f"Restorable Dropped Databases resource not found error - {e}")
|
|
@@ -239,18 +284,30 @@ def get_restorable_dropped_databases(credentials: Credentials, subscription_id:
|
|
|
239
284
|
|
|
240
285
|
|
|
241
286
|
@timeit
|
|
242
|
-
def get_failover_groups(
|
|
287
|
+
def get_failover_groups(
|
|
288
|
+
credentials: Credentials,
|
|
289
|
+
subscription_id: str,
|
|
290
|
+
server: Dict,
|
|
291
|
+
) -> List[Dict]:
|
|
243
292
|
"""
|
|
244
293
|
Returns details of Failover groups in a server.
|
|
245
294
|
"""
|
|
246
295
|
try:
|
|
247
296
|
client = get_client(credentials, subscription_id)
|
|
248
297
|
failover_groups = list(
|
|
249
|
-
map(
|
|
298
|
+
map(
|
|
299
|
+
lambda x: x.as_dict(),
|
|
300
|
+
client.failover_groups.list_by_server(
|
|
301
|
+
server["resourceGroup"],
|
|
302
|
+
server["name"],
|
|
303
|
+
),
|
|
304
|
+
),
|
|
250
305
|
)
|
|
251
306
|
|
|
252
307
|
except ClientAuthenticationError as e:
|
|
253
|
-
logger.warning(
|
|
308
|
+
logger.warning(
|
|
309
|
+
f"Client Authentication Error while retrieving Failover groups - {e}",
|
|
310
|
+
)
|
|
254
311
|
return []
|
|
255
312
|
except ResourceNotFoundError as e:
|
|
256
313
|
logger.warning(f"Failover groups resource not found error - {e}")
|
|
@@ -263,18 +320,30 @@ def get_failover_groups(credentials: Credentials, subscription_id: str, server:
|
|
|
263
320
|
|
|
264
321
|
|
|
265
322
|
@timeit
|
|
266
|
-
def get_elastic_pools(
|
|
323
|
+
def get_elastic_pools(
|
|
324
|
+
credentials: Credentials,
|
|
325
|
+
subscription_id: str,
|
|
326
|
+
server: Dict,
|
|
327
|
+
) -> List[Dict]:
|
|
267
328
|
"""
|
|
268
329
|
Returns details of Elastic Pools in a server.
|
|
269
330
|
"""
|
|
270
331
|
try:
|
|
271
332
|
client = get_client(credentials, subscription_id)
|
|
272
333
|
elastic_pools = list(
|
|
273
|
-
map(
|
|
334
|
+
map(
|
|
335
|
+
lambda x: x.as_dict(),
|
|
336
|
+
client.elastic_pools.list_by_server(
|
|
337
|
+
server["resourceGroup"],
|
|
338
|
+
server["name"],
|
|
339
|
+
),
|
|
340
|
+
),
|
|
274
341
|
)
|
|
275
342
|
|
|
276
343
|
except ClientAuthenticationError as e:
|
|
277
|
-
logger.warning(
|
|
344
|
+
logger.warning(
|
|
345
|
+
f"Client Authentication Error while retrieving Elastic Pools - {e}",
|
|
346
|
+
)
|
|
278
347
|
return []
|
|
279
348
|
except ResourceNotFoundError as e:
|
|
280
349
|
logger.warning(f"Elastic Pools resource not found error - {e}")
|
|
@@ -287,18 +356,30 @@ def get_elastic_pools(credentials: Credentials, subscription_id: str, server: Di
|
|
|
287
356
|
|
|
288
357
|
|
|
289
358
|
@timeit
|
|
290
|
-
def get_databases(
|
|
359
|
+
def get_databases(
|
|
360
|
+
credentials: Credentials,
|
|
361
|
+
subscription_id: str,
|
|
362
|
+
server: Dict,
|
|
363
|
+
) -> List[Dict]:
|
|
291
364
|
"""
|
|
292
365
|
Returns details of Databases in a SQL server.
|
|
293
366
|
"""
|
|
294
367
|
try:
|
|
295
368
|
client = get_client(credentials, subscription_id)
|
|
296
369
|
databases = list(
|
|
297
|
-
map(
|
|
370
|
+
map(
|
|
371
|
+
lambda x: x.as_dict(),
|
|
372
|
+
client.databases.list_by_server(
|
|
373
|
+
server["resourceGroup"],
|
|
374
|
+
server["name"],
|
|
375
|
+
),
|
|
376
|
+
),
|
|
298
377
|
)
|
|
299
378
|
|
|
300
379
|
except ClientAuthenticationError as e:
|
|
301
|
-
logger.warning(
|
|
380
|
+
logger.warning(
|
|
381
|
+
f"Client Authentication Error while retrieving SQL databases - {e}",
|
|
382
|
+
)
|
|
302
383
|
return []
|
|
303
384
|
except ResourceNotFoundError as e:
|
|
304
385
|
logger.warning(f"SQL databases resource not found error - {e}")
|
|
@@ -312,12 +393,12 @@ def get_databases(credentials: Credentials, subscription_id: str, server: Dict)
|
|
|
312
393
|
|
|
313
394
|
@timeit
|
|
314
395
|
def load_server_details(
|
|
315
|
-
|
|
316
|
-
|
|
396
|
+
neo4j_session: neo4j.Session,
|
|
397
|
+
credentials: Credentials,
|
|
398
|
+
subscription_id: str,
|
|
399
|
+
details: Iterable[Tuple[Any, Any, Any, Any, Any, Any, Any, Any, Any, Any]],
|
|
400
|
+
update_tag: int,
|
|
317
401
|
) -> None:
|
|
318
|
-
"""
|
|
319
|
-
Create dictionaries for every resource in the server so we can import them in a single query
|
|
320
|
-
"""
|
|
321
402
|
dns_aliases = []
|
|
322
403
|
ad_admins = []
|
|
323
404
|
recoverable_databases = []
|
|
@@ -326,311 +407,267 @@ def load_server_details(
|
|
|
326
407
|
elastic_pools = []
|
|
327
408
|
databases = []
|
|
328
409
|
|
|
329
|
-
for
|
|
410
|
+
for (
|
|
411
|
+
server_id,
|
|
412
|
+
name,
|
|
413
|
+
rg,
|
|
414
|
+
dns_alias,
|
|
415
|
+
ad_admin,
|
|
416
|
+
r_database,
|
|
417
|
+
rd_database,
|
|
418
|
+
fg,
|
|
419
|
+
elastic_pool,
|
|
420
|
+
database,
|
|
421
|
+
) in details:
|
|
330
422
|
if len(dns_alias) > 0:
|
|
331
423
|
for alias in dns_alias:
|
|
332
|
-
alias[
|
|
333
|
-
alias[
|
|
424
|
+
alias["server_name"] = name
|
|
425
|
+
alias["server_id"] = server_id
|
|
334
426
|
dns_aliases.append(alias)
|
|
335
427
|
|
|
336
428
|
if len(ad_admin) > 0:
|
|
337
429
|
for admin in ad_admin:
|
|
338
|
-
admin[
|
|
339
|
-
admin[
|
|
430
|
+
admin["server_name"] = name
|
|
431
|
+
admin["server_id"] = server_id
|
|
340
432
|
ad_admins.append(admin)
|
|
341
433
|
|
|
342
434
|
if len(r_database) > 0:
|
|
343
435
|
for rdb in r_database:
|
|
344
|
-
rdb[
|
|
345
|
-
rdb[
|
|
436
|
+
rdb["server_name"] = name
|
|
437
|
+
rdb["server_id"] = server_id
|
|
346
438
|
recoverable_databases.append(rdb)
|
|
347
439
|
|
|
348
440
|
if len(rd_database) > 0:
|
|
349
441
|
for rddb in rd_database:
|
|
350
|
-
rddb[
|
|
351
|
-
rddb[
|
|
442
|
+
rddb["server_name"] = name
|
|
443
|
+
rddb["server_id"] = server_id
|
|
352
444
|
restorable_dropped_databases.append(rddb)
|
|
353
445
|
|
|
354
446
|
if len(fg) > 0:
|
|
355
447
|
for group in fg:
|
|
356
|
-
group[
|
|
357
|
-
group[
|
|
448
|
+
group["server_name"] = name
|
|
449
|
+
group["server_id"] = server_id
|
|
358
450
|
failover_groups.append(group)
|
|
359
451
|
|
|
360
452
|
if len(elastic_pool) > 0:
|
|
361
453
|
for pool in elastic_pool:
|
|
362
|
-
pool[
|
|
363
|
-
pool[
|
|
454
|
+
pool["server_name"] = name
|
|
455
|
+
pool["server_id"] = server_id
|
|
364
456
|
elastic_pools.append(pool)
|
|
365
457
|
|
|
366
458
|
if len(database) > 0:
|
|
367
459
|
for db in database:
|
|
368
|
-
db[
|
|
369
|
-
db[
|
|
370
|
-
db[
|
|
460
|
+
db["server_name"] = name
|
|
461
|
+
db["server_id"] = server_id
|
|
462
|
+
db["resource_group_name"] = rg
|
|
371
463
|
databases.append(db)
|
|
372
464
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
465
|
+
_load_elastic_pools(neo4j_session, elastic_pools, subscription_id, update_tag)
|
|
466
|
+
_load_failover_groups(neo4j_session, failover_groups, subscription_id, update_tag)
|
|
467
|
+
_load_databases(neo4j_session, databases, subscription_id, update_tag)
|
|
468
|
+
_load_recoverable_databases(
|
|
469
|
+
neo4j_session, recoverable_databases, subscription_id, update_tag
|
|
470
|
+
)
|
|
471
|
+
_load_restorable_dropped_databases(
|
|
472
|
+
neo4j_session,
|
|
473
|
+
restorable_dropped_databases,
|
|
474
|
+
subscription_id,
|
|
475
|
+
update_tag,
|
|
476
|
+
)
|
|
477
|
+
_load_server_dns_aliases(neo4j_session, dns_aliases, subscription_id, update_tag)
|
|
478
|
+
_load_server_ad_admins(neo4j_session, ad_admins, subscription_id, update_tag)
|
|
479
|
+
|
|
480
|
+
sync_database_details(
|
|
481
|
+
neo4j_session,
|
|
482
|
+
credentials,
|
|
483
|
+
subscription_id,
|
|
484
|
+
databases,
|
|
485
|
+
update_tag,
|
|
486
|
+
)
|
|
382
487
|
|
|
383
488
|
|
|
384
489
|
@timeit
|
|
385
490
|
def _load_server_dns_aliases(
|
|
386
|
-
|
|
491
|
+
neo4j_session: neo4j.Session,
|
|
492
|
+
dns_aliases: List[Dict],
|
|
493
|
+
subscription_id: str,
|
|
494
|
+
update_tag: int,
|
|
387
495
|
) -> None:
|
|
388
496
|
"""
|
|
389
497
|
Ingest the DNS Alias details into neo4j.
|
|
390
498
|
"""
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
alias.lastupdated = $azure_update_tag
|
|
398
|
-
WITH alias, dns_alias
|
|
399
|
-
MATCH (s:AzureSQLServer{id: dns_alias.server_id})
|
|
400
|
-
MERGE (s)-[r:USED_BY]->(alias)
|
|
401
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
402
|
-
SET r.lastupdated = $azure_update_tag
|
|
403
|
-
"""
|
|
404
|
-
|
|
405
|
-
neo4j_session.run(
|
|
406
|
-
ingest_dns_aliases,
|
|
407
|
-
dns_aliases_list=dns_aliases,
|
|
408
|
-
azure_update_tag=update_tag,
|
|
499
|
+
load(
|
|
500
|
+
neo4j_session,
|
|
501
|
+
AzureServerDNSAliasSchema(),
|
|
502
|
+
dns_aliases,
|
|
503
|
+
lastupdated=update_tag,
|
|
504
|
+
AZURE_SUBSCRIPTION_ID=subscription_id,
|
|
409
505
|
)
|
|
410
506
|
|
|
411
507
|
|
|
412
508
|
@timeit
|
|
413
509
|
def _load_server_ad_admins(
|
|
414
|
-
|
|
510
|
+
neo4j_session: neo4j.Session,
|
|
511
|
+
ad_admins: List[Dict],
|
|
512
|
+
subscription_id: str,
|
|
513
|
+
update_tag: int,
|
|
415
514
|
) -> None:
|
|
416
515
|
"""
|
|
417
516
|
Ingest the Server AD Administrators details into neo4j.
|
|
418
517
|
"""
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
a.login = ad_admin.login,
|
|
426
|
-
a.lastupdated = $azure_update_tag
|
|
427
|
-
WITH a, ad_admin
|
|
428
|
-
MATCH (s:AzureSQLServer{id: ad_admin.server_id})
|
|
429
|
-
MERGE (s)-[r:ADMINISTERED_BY]->(a)
|
|
430
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
431
|
-
SET r.lastupdated = $azure_update_tag
|
|
432
|
-
"""
|
|
433
|
-
|
|
434
|
-
neo4j_session.run(
|
|
435
|
-
ingest_ad_admins,
|
|
436
|
-
ad_admins_list=ad_admins,
|
|
437
|
-
azure_update_tag=update_tag,
|
|
518
|
+
load(
|
|
519
|
+
neo4j_session,
|
|
520
|
+
AzureServerADAdministratorSchema(),
|
|
521
|
+
ad_admins,
|
|
522
|
+
lastupdated=update_tag,
|
|
523
|
+
AZURE_SUBSCRIPTION_ID=subscription_id,
|
|
438
524
|
)
|
|
439
525
|
|
|
440
526
|
|
|
441
527
|
@timeit
|
|
442
528
|
def _load_recoverable_databases(
|
|
443
|
-
|
|
529
|
+
neo4j_session: neo4j.Session,
|
|
530
|
+
recoverable_databases: List[Dict],
|
|
531
|
+
subscription_id: str,
|
|
532
|
+
update_tag: int,
|
|
444
533
|
) -> None:
|
|
445
534
|
"""
|
|
446
535
|
Ingest the recoverable database details into neo4j.
|
|
447
536
|
"""
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
rd.servicelevelobjective = rec_db.service_level_objective,
|
|
455
|
-
rd.lastbackupdate = rec_db.last_available_backup_date,
|
|
456
|
-
rd.lastupdated = $azure_update_tag
|
|
457
|
-
WITH rd, rec_db
|
|
458
|
-
MATCH (s:AzureSQLServer{id: rec_db.server_id})
|
|
459
|
-
MERGE (s)-[r:RESOURCE]->(rd)
|
|
460
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
461
|
-
SET r.lastupdated = $azure_update_tag
|
|
462
|
-
"""
|
|
463
|
-
|
|
464
|
-
neo4j_session.run(
|
|
465
|
-
ingest_recoverable_databases,
|
|
466
|
-
recoverable_databases_list=recoverable_databases,
|
|
467
|
-
azure_update_tag=update_tag,
|
|
537
|
+
load(
|
|
538
|
+
neo4j_session,
|
|
539
|
+
AzureRecoverableDatabaseSchema(),
|
|
540
|
+
recoverable_databases,
|
|
541
|
+
lastupdated=update_tag,
|
|
542
|
+
AZURE_SUBSCRIPTION_ID=subscription_id,
|
|
468
543
|
)
|
|
469
544
|
|
|
470
545
|
|
|
471
546
|
@timeit
|
|
472
547
|
def _load_restorable_dropped_databases(
|
|
473
|
-
|
|
548
|
+
neo4j_session: neo4j.Session,
|
|
549
|
+
restorable_dropped_databases: List[Dict],
|
|
550
|
+
subscription_id: str,
|
|
551
|
+
update_tag: int,
|
|
474
552
|
) -> None:
|
|
475
553
|
"""
|
|
476
554
|
Ingest the restorable dropped database details into neo4j.
|
|
477
555
|
"""
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
rdd.creationdate = res_dropped_db.creation_date,
|
|
485
|
-
rdd.deletiondate = res_dropped_db.deletion_date,
|
|
486
|
-
rdd.restoredate = res_dropped_db.earliest_restore_date,
|
|
487
|
-
rdd.edition = res_dropped_db.edition,
|
|
488
|
-
rdd.servicelevelobjective = res_dropped_db.service_level_objective,
|
|
489
|
-
rdd.maxsizebytes = res_dropped_db.max_size_bytes,
|
|
490
|
-
rdd.lastupdated = $azure_update_tag
|
|
491
|
-
WITH rdd, res_dropped_db
|
|
492
|
-
MATCH (s:AzureSQLServer{id: res_dropped_db.server_id})
|
|
493
|
-
MERGE (s)-[r:RESOURCE]->(rdd)
|
|
494
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
495
|
-
SET r.lastupdated = $azure_update_tag
|
|
496
|
-
"""
|
|
497
|
-
|
|
498
|
-
neo4j_session.run(
|
|
499
|
-
ingest_restorable_dropped_databases,
|
|
500
|
-
restorable_dropped_databases_list=restorable_dropped_databases,
|
|
501
|
-
azure_update_tag=update_tag,
|
|
556
|
+
load(
|
|
557
|
+
neo4j_session,
|
|
558
|
+
AzureRestorableDroppedDatabaseSchema(),
|
|
559
|
+
restorable_dropped_databases,
|
|
560
|
+
lastupdated=update_tag,
|
|
561
|
+
AZURE_SUBSCRIPTION_ID=subscription_id,
|
|
502
562
|
)
|
|
503
563
|
|
|
504
564
|
|
|
505
565
|
@timeit
|
|
506
566
|
def _load_failover_groups(
|
|
507
|
-
|
|
567
|
+
neo4j_session: neo4j.Session,
|
|
568
|
+
failover_groups: List[Dict],
|
|
569
|
+
subscription_id: str,
|
|
570
|
+
update_tag: int,
|
|
508
571
|
) -> None:
|
|
509
572
|
"""
|
|
510
573
|
Ingest the failover groups details into neo4j.
|
|
511
574
|
"""
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
f.replicationstate = fg.replication_state,
|
|
519
|
-
f.lastupdated = $azure_update_tag
|
|
520
|
-
WITH f, fg
|
|
521
|
-
MATCH (s:AzureSQLServer{id: fg.server_id})
|
|
522
|
-
MERGE (s)-[r:RESOURCE]->(f)
|
|
523
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
524
|
-
SET r.lastupdated = $azure_update_tag
|
|
525
|
-
"""
|
|
526
|
-
|
|
527
|
-
neo4j_session.run(
|
|
528
|
-
ingest_failover_groups,
|
|
529
|
-
failover_groups_list=failover_groups,
|
|
530
|
-
azure_update_tag=update_tag,
|
|
575
|
+
load(
|
|
576
|
+
neo4j_session,
|
|
577
|
+
AzureFailoverGroupSchema(),
|
|
578
|
+
failover_groups,
|
|
579
|
+
lastupdated=update_tag,
|
|
580
|
+
AZURE_SUBSCRIPTION_ID=subscription_id,
|
|
531
581
|
)
|
|
532
582
|
|
|
533
583
|
|
|
534
584
|
@timeit
|
|
535
585
|
def _load_elastic_pools(
|
|
536
|
-
|
|
586
|
+
neo4j_session: neo4j.Session,
|
|
587
|
+
elastic_pools: List[Dict],
|
|
588
|
+
subscription_id: str,
|
|
589
|
+
update_tag: int,
|
|
537
590
|
) -> None:
|
|
538
591
|
"""
|
|
539
592
|
Ingest the elastic pool details into neo4j.
|
|
540
593
|
"""
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
e.creationdate = ep.creation_date,
|
|
548
|
-
e.state = ep.state,
|
|
549
|
-
e.maxsizebytes = ep.max_size_bytes,
|
|
550
|
-
e.licensetype = ep.license_type,
|
|
551
|
-
e.zoneredundant = ep.zone_redundant,
|
|
552
|
-
e.lastupdated = $azure_update_tag
|
|
553
|
-
WITH e, ep
|
|
554
|
-
MATCH (s:AzureSQLServer{id: ep.server_id})
|
|
555
|
-
MERGE (s)-[r:RESOURCE]->(e)
|
|
556
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
557
|
-
SET r.lastupdated = $azure_update_tag
|
|
558
|
-
"""
|
|
559
|
-
|
|
560
|
-
neo4j_session.run(
|
|
561
|
-
ingest_elastic_pools,
|
|
562
|
-
elastic_pools_list=elastic_pools,
|
|
563
|
-
azure_update_tag=update_tag,
|
|
594
|
+
load(
|
|
595
|
+
neo4j_session,
|
|
596
|
+
AzureElasticPoolSchema(),
|
|
597
|
+
elastic_pools,
|
|
598
|
+
lastupdated=update_tag,
|
|
599
|
+
AZURE_SUBSCRIPTION_ID=subscription_id,
|
|
564
600
|
)
|
|
565
601
|
|
|
566
602
|
|
|
567
603
|
@timeit
|
|
568
604
|
def _load_databases(
|
|
569
|
-
|
|
605
|
+
neo4j_session: neo4j.Session,
|
|
606
|
+
databases: List[Dict],
|
|
607
|
+
subscription_id: str,
|
|
608
|
+
update_tag: int,
|
|
570
609
|
) -> None:
|
|
571
610
|
"""
|
|
572
611
|
Ingest the database details into neo4j.
|
|
573
612
|
"""
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
d.creationdate = az_database.creation_date,
|
|
581
|
-
d.databaseid = az_database.database_id,
|
|
582
|
-
d.maxsizebytes = az_database.max_size_bytes,
|
|
583
|
-
d.licensetype = az_database.license_type,
|
|
584
|
-
d.secondarylocation = az_database.default_secondary_location,
|
|
585
|
-
d.elasticpoolid = az_database.elastic_pool_id,
|
|
586
|
-
d.collation = az_database.collation,
|
|
587
|
-
d.failovergroupid = az_database.failover_group_id,
|
|
588
|
-
d.zoneredundant = az_database.zone_redundant,
|
|
589
|
-
d.restorabledroppeddbid = az_database.restorable_dropped_database_id,
|
|
590
|
-
d.recoverabledbid = az_database.recoverable_database_id,
|
|
591
|
-
d.lastupdated = $azure_update_tag
|
|
592
|
-
WITH d, az_database
|
|
593
|
-
MATCH (s:AzureSQLServer{id: az_database.server_id})
|
|
594
|
-
MERGE (s)-[r:RESOURCE]->(d)
|
|
595
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
596
|
-
SET r.lastupdated = $azure_update_tag
|
|
597
|
-
"""
|
|
598
|
-
|
|
599
|
-
neo4j_session.run(
|
|
600
|
-
ingest_databases,
|
|
601
|
-
databases_list=databases,
|
|
602
|
-
azure_update_tag=update_tag,
|
|
613
|
+
load(
|
|
614
|
+
neo4j_session,
|
|
615
|
+
AzureSQLDatabaseSchema(),
|
|
616
|
+
databases,
|
|
617
|
+
lastupdated=update_tag,
|
|
618
|
+
AZURE_SUBSCRIPTION_ID=subscription_id,
|
|
603
619
|
)
|
|
604
620
|
|
|
605
621
|
|
|
606
622
|
@timeit
|
|
607
623
|
def sync_database_details(
|
|
608
|
-
|
|
609
|
-
|
|
624
|
+
neo4j_session: neo4j.Session,
|
|
625
|
+
credentials: Credentials,
|
|
626
|
+
subscription_id: str,
|
|
627
|
+
databases: List[Dict],
|
|
628
|
+
update_tag: int,
|
|
610
629
|
) -> None:
|
|
611
630
|
db_details = get_database_details(credentials, subscription_id, databases)
|
|
612
|
-
load_database_details(neo4j_session, db_details, update_tag) # type: ignore
|
|
631
|
+
load_database_details(neo4j_session, db_details, subscription_id, update_tag) # type: ignore
|
|
613
632
|
|
|
614
633
|
|
|
615
634
|
@timeit
|
|
616
635
|
def get_database_details(
|
|
617
|
-
|
|
636
|
+
credentials: Credentials,
|
|
637
|
+
subscription_id: str,
|
|
638
|
+
databases: List[Dict],
|
|
618
639
|
) -> Generator[Any, Any, Any]:
|
|
619
640
|
"""
|
|
620
641
|
Iterate over the databases to get the details of resources in it.
|
|
621
642
|
"""
|
|
622
643
|
for database in databases:
|
|
623
|
-
replication_links = get_replication_links(
|
|
624
|
-
|
|
644
|
+
replication_links = get_replication_links(
|
|
645
|
+
credentials,
|
|
646
|
+
subscription_id,
|
|
647
|
+
database,
|
|
648
|
+
)
|
|
649
|
+
db_threat_detection_policies = get_db_threat_detection_policies(
|
|
650
|
+
credentials,
|
|
651
|
+
subscription_id,
|
|
652
|
+
database,
|
|
653
|
+
)
|
|
625
654
|
restore_points = get_restore_points(credentials, subscription_id, database)
|
|
626
|
-
transparent_data_encryptions = get_transparent_data_encryptions(
|
|
655
|
+
transparent_data_encryptions = get_transparent_data_encryptions(
|
|
656
|
+
credentials,
|
|
657
|
+
subscription_id,
|
|
658
|
+
database,
|
|
659
|
+
)
|
|
627
660
|
yield database[
|
|
628
|
-
|
|
661
|
+
"id"
|
|
629
662
|
], replication_links, db_threat_detection_policies, restore_points, transparent_data_encryptions
|
|
630
663
|
|
|
631
664
|
|
|
632
665
|
@timeit
|
|
633
|
-
def get_replication_links(
|
|
666
|
+
def get_replication_links(
|
|
667
|
+
credentials: Credentials,
|
|
668
|
+
subscription_id: str,
|
|
669
|
+
database: Dict,
|
|
670
|
+
) -> List[Dict]:
|
|
634
671
|
"""
|
|
635
672
|
Returns the details of replication links in a database.
|
|
636
673
|
"""
|
|
@@ -640,15 +677,17 @@ def get_replication_links(credentials: Credentials, subscription_id: str, databa
|
|
|
640
677
|
map(
|
|
641
678
|
lambda x: x.as_dict(),
|
|
642
679
|
client.replication_links.list_by_database(
|
|
643
|
-
database[
|
|
644
|
-
database[
|
|
645
|
-
database[
|
|
680
|
+
database["resource_group_name"],
|
|
681
|
+
database["server_name"],
|
|
682
|
+
database["name"],
|
|
646
683
|
),
|
|
647
684
|
),
|
|
648
685
|
)
|
|
649
686
|
|
|
650
687
|
except ClientAuthenticationError as e:
|
|
651
|
-
logger.warning(
|
|
688
|
+
logger.warning(
|
|
689
|
+
f"Client Authentication Error while retrieving replication links - {e}",
|
|
690
|
+
)
|
|
652
691
|
return []
|
|
653
692
|
except ResourceNotFoundError as e:
|
|
654
693
|
logger.warning(f"Replication links resource not found error - {e}")
|
|
@@ -661,33 +700,45 @@ def get_replication_links(credentials: Credentials, subscription_id: str, databa
|
|
|
661
700
|
|
|
662
701
|
|
|
663
702
|
@timeit
|
|
664
|
-
def get_db_threat_detection_policies(
|
|
703
|
+
def get_db_threat_detection_policies(
|
|
704
|
+
credentials: Credentials,
|
|
705
|
+
subscription_id: str,
|
|
706
|
+
database: Dict,
|
|
707
|
+
) -> List[Dict]:
|
|
665
708
|
"""
|
|
666
709
|
Returns the threat detection policy of a database.
|
|
667
710
|
"""
|
|
668
711
|
try:
|
|
669
712
|
client = get_client(credentials, subscription_id)
|
|
670
713
|
db_threat_detection_policies = client.database_threat_detection_policies.get(
|
|
671
|
-
database[
|
|
672
|
-
database[
|
|
673
|
-
database[
|
|
714
|
+
database["resource_group_name"],
|
|
715
|
+
database["server_name"],
|
|
716
|
+
database["name"],
|
|
674
717
|
SecurityAlertPolicyName.DEFAULT,
|
|
675
718
|
).as_dict()
|
|
676
719
|
except ClientAuthenticationError as e:
|
|
677
|
-
logger.warning(
|
|
720
|
+
logger.warning(
|
|
721
|
+
f"Client Authentication Error while retrieving threat detection policy - {e}",
|
|
722
|
+
)
|
|
678
723
|
return []
|
|
679
724
|
except ResourceNotFoundError as e:
|
|
680
725
|
logger.warning(f"Threat detection policy resource not found error - {e}")
|
|
681
726
|
return []
|
|
682
727
|
except HttpResponseError as e:
|
|
683
|
-
logger.warning(
|
|
728
|
+
logger.warning(
|
|
729
|
+
f"Error while retrieving database threat detection policies - {e}",
|
|
730
|
+
)
|
|
684
731
|
return []
|
|
685
732
|
|
|
686
733
|
return db_threat_detection_policies
|
|
687
734
|
|
|
688
735
|
|
|
689
736
|
@timeit
|
|
690
|
-
def get_restore_points(
|
|
737
|
+
def get_restore_points(
|
|
738
|
+
credentials: Credentials,
|
|
739
|
+
subscription_id: str,
|
|
740
|
+
database: Dict,
|
|
741
|
+
) -> List[Dict]:
|
|
691
742
|
"""
|
|
692
743
|
Returns the details of restore points in a database.
|
|
693
744
|
"""
|
|
@@ -697,15 +748,17 @@ def get_restore_points(credentials: Credentials, subscription_id: str, database:
|
|
|
697
748
|
map(
|
|
698
749
|
lambda x: x.as_dict(),
|
|
699
750
|
client.restore_points.list_by_database(
|
|
700
|
-
database[
|
|
701
|
-
database[
|
|
702
|
-
database[
|
|
751
|
+
database["resource_group_name"],
|
|
752
|
+
database["server_name"],
|
|
753
|
+
database["name"],
|
|
703
754
|
),
|
|
704
755
|
),
|
|
705
756
|
)
|
|
706
757
|
|
|
707
758
|
except ClientAuthenticationError as e:
|
|
708
|
-
logger.warning(
|
|
759
|
+
logger.warning(
|
|
760
|
+
f"Client Authentication Error while retrieving restore points - {e}",
|
|
761
|
+
)
|
|
709
762
|
return []
|
|
710
763
|
except ResourceNotFoundError as e:
|
|
711
764
|
logger.warning(f"Restore points resource not found error - {e}")
|
|
@@ -718,20 +771,26 @@ def get_restore_points(credentials: Credentials, subscription_id: str, database:
|
|
|
718
771
|
|
|
719
772
|
|
|
720
773
|
@timeit
|
|
721
|
-
def get_transparent_data_encryptions(
|
|
774
|
+
def get_transparent_data_encryptions(
|
|
775
|
+
credentials: Credentials,
|
|
776
|
+
subscription_id: str,
|
|
777
|
+
database: Dict,
|
|
778
|
+
) -> List[Dict]:
|
|
722
779
|
"""
|
|
723
780
|
Returns the details of transparent data encryptions in a database.
|
|
724
781
|
"""
|
|
725
782
|
try:
|
|
726
783
|
client = get_client(credentials, subscription_id)
|
|
727
784
|
transparent_data_encryptions_list = client.transparent_data_encryptions.get(
|
|
728
|
-
database[
|
|
729
|
-
database[
|
|
730
|
-
database[
|
|
785
|
+
database["resource_group_name"],
|
|
786
|
+
database["server_name"],
|
|
787
|
+
database["name"],
|
|
731
788
|
TransparentDataEncryptionName.CURRENT,
|
|
732
789
|
).as_dict()
|
|
733
790
|
except ClientAuthenticationError as e:
|
|
734
|
-
logger.warning(
|
|
791
|
+
logger.warning(
|
|
792
|
+
f"Client Authentication Error while retrieving transparent data encryptions - {e}",
|
|
793
|
+
)
|
|
735
794
|
return []
|
|
736
795
|
except ResourceNotFoundError as e:
|
|
737
796
|
logger.warning(f"Transparent data encryptions resource not found error - {e}")
|
|
@@ -745,7 +804,10 @@ def get_transparent_data_encryptions(credentials: Credentials, subscription_id:
|
|
|
745
804
|
|
|
746
805
|
@timeit
|
|
747
806
|
def load_database_details(
|
|
748
|
-
|
|
807
|
+
neo4j_session: neo4j.Session,
|
|
808
|
+
details: List[Tuple[Any, Any, Any, Any, Any]],
|
|
809
|
+
subscription_id: str,
|
|
810
|
+
update_tag: int,
|
|
749
811
|
) -> None:
|
|
750
812
|
"""
|
|
751
813
|
Create dictionaries for every resource in a database so we can import them in a single query
|
|
@@ -755,180 +817,162 @@ def load_database_details(
|
|
|
755
817
|
restore_points = []
|
|
756
818
|
encryptions_list = []
|
|
757
819
|
|
|
758
|
-
for
|
|
820
|
+
for (
|
|
821
|
+
databaseId,
|
|
822
|
+
replication_link,
|
|
823
|
+
db_threat_detection_policy,
|
|
824
|
+
restore_point,
|
|
825
|
+
transparent_data_encryption,
|
|
826
|
+
) in details:
|
|
759
827
|
if len(replication_link) > 0:
|
|
760
828
|
for link in replication_link:
|
|
761
|
-
link[
|
|
829
|
+
link["database_id"] = databaseId
|
|
762
830
|
replication_links.append(link)
|
|
763
831
|
|
|
764
832
|
if len(db_threat_detection_policy) > 0:
|
|
765
|
-
db_threat_detection_policy[
|
|
833
|
+
db_threat_detection_policy["database_id"] = databaseId
|
|
766
834
|
threat_detection_policies.append(db_threat_detection_policy)
|
|
767
835
|
|
|
768
836
|
if len(restore_point) > 0:
|
|
769
837
|
for point in restore_point:
|
|
770
|
-
point[
|
|
838
|
+
point["database_id"] = databaseId
|
|
771
839
|
restore_points.append(point)
|
|
772
840
|
|
|
773
841
|
if len(transparent_data_encryption) > 0:
|
|
774
|
-
transparent_data_encryption[
|
|
842
|
+
transparent_data_encryption["database_id"] = databaseId
|
|
775
843
|
encryptions_list.append(transparent_data_encryption)
|
|
776
844
|
|
|
777
|
-
_load_replication_links(
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
845
|
+
_load_replication_links(
|
|
846
|
+
neo4j_session, replication_links, subscription_id, update_tag
|
|
847
|
+
)
|
|
848
|
+
_load_db_threat_detection_policies(
|
|
849
|
+
neo4j_session,
|
|
850
|
+
threat_detection_policies,
|
|
851
|
+
subscription_id,
|
|
852
|
+
update_tag,
|
|
853
|
+
)
|
|
854
|
+
_load_restore_points(neo4j_session, restore_points, subscription_id, update_tag)
|
|
855
|
+
_load_transparent_data_encryptions(
|
|
856
|
+
neo4j_session, encryptions_list, subscription_id, update_tag
|
|
857
|
+
)
|
|
781
858
|
|
|
782
859
|
|
|
783
860
|
@timeit
|
|
784
861
|
def _load_replication_links(
|
|
785
|
-
|
|
862
|
+
neo4j_session: neo4j.Session,
|
|
863
|
+
replication_links: List[Dict],
|
|
864
|
+
subscription_id: str,
|
|
865
|
+
update_tag: int,
|
|
786
866
|
) -> None:
|
|
787
867
|
"""
|
|
788
868
|
Ingest replication links into neo4j.
|
|
789
869
|
"""
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
rl.partnerdatabase = replication_link.partner_database,
|
|
797
|
-
rl.partnerlocation = replication_link.partner_location,
|
|
798
|
-
rl.partnerrole = replication_link.partner_role,
|
|
799
|
-
rl.partnerserver = replication_link.partner_server,
|
|
800
|
-
rl.mode = replication_link.replication_mode,
|
|
801
|
-
rl.state = replication_link.replication_state,
|
|
802
|
-
rl.percentcomplete = replication_link.percent_complete,
|
|
803
|
-
rl.role = replication_link.role,
|
|
804
|
-
rl.starttime = replication_link.start_time,
|
|
805
|
-
rl.terminationallowed = replication_link.is_termination_allowed,
|
|
806
|
-
rl.lastupdated = $azure_update_tag
|
|
807
|
-
WITH rl, replication_link
|
|
808
|
-
MATCH (d:AzureSQLDatabase{id: replication_link.database_id})
|
|
809
|
-
MERGE (d)-[r:CONTAINS]->(rl)
|
|
810
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
811
|
-
SET r.lastupdated = $azure_update_tag
|
|
812
|
-
"""
|
|
813
|
-
|
|
814
|
-
neo4j_session.run(
|
|
815
|
-
ingest_replication_links,
|
|
816
|
-
replication_links_list=replication_links,
|
|
817
|
-
azure_update_tag=update_tag,
|
|
870
|
+
load(
|
|
871
|
+
neo4j_session,
|
|
872
|
+
AzureReplicationLinkSchema(),
|
|
873
|
+
replication_links,
|
|
874
|
+
lastupdated=update_tag,
|
|
875
|
+
AZURE_SUBSCRIPTION_ID=subscription_id,
|
|
818
876
|
)
|
|
819
877
|
|
|
820
878
|
|
|
821
879
|
@timeit
|
|
822
880
|
def _load_db_threat_detection_policies(
|
|
823
|
-
|
|
881
|
+
neo4j_session: neo4j.Session,
|
|
882
|
+
threat_detection_policies: List[Dict],
|
|
883
|
+
subscription_id: str,
|
|
884
|
+
update_tag: int,
|
|
824
885
|
) -> None:
|
|
825
886
|
"""
|
|
826
887
|
Ingest threat detection policy into neo4j.
|
|
827
888
|
"""
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
policy.location = tdp.location,
|
|
835
|
-
policy.kind = tdp.kind,
|
|
836
|
-
policy.emailadmins = tdp.email_account_admins,
|
|
837
|
-
policy.emailaddresses = tdp.email_addresses,
|
|
838
|
-
policy.retentiondays = tdp.retention_days,
|
|
839
|
-
policy.state = tdp.state,
|
|
840
|
-
policy.storageendpoint = tdp.storage_endpoint,
|
|
841
|
-
policy.useserverdefault = tdp.use_server_default,
|
|
842
|
-
policy.disabledalerts = tdp.disabled_alerts,
|
|
843
|
-
policy.lastupdated = $azure_update_tag
|
|
844
|
-
WITH policy, tdp
|
|
845
|
-
MATCH (d:AzureSQLDatabase{id: tdp.database_id})
|
|
846
|
-
MERGE (d)-[r:CONTAINS]->(policy)
|
|
847
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
848
|
-
SET r.lastupdated = $azure_update_tag
|
|
849
|
-
"""
|
|
850
|
-
|
|
851
|
-
neo4j_session.run(
|
|
852
|
-
ingest_threat_detection_policies,
|
|
853
|
-
threat_detection_policies_list=threat_detection_policies,
|
|
854
|
-
azure_update_tag=update_tag,
|
|
889
|
+
load(
|
|
890
|
+
neo4j_session,
|
|
891
|
+
AzureDatabaseThreatDetectionPolicySchema(),
|
|
892
|
+
threat_detection_policies,
|
|
893
|
+
lastupdated=update_tag,
|
|
894
|
+
AZURE_SUBSCRIPTION_ID=subscription_id,
|
|
855
895
|
)
|
|
856
896
|
|
|
857
897
|
|
|
858
898
|
@timeit
|
|
859
899
|
def _load_restore_points(
|
|
860
|
-
|
|
900
|
+
neo4j_session: neo4j.Session,
|
|
901
|
+
restore_points: List[Dict],
|
|
902
|
+
subscription_id: str,
|
|
903
|
+
update_tag: int,
|
|
861
904
|
) -> None:
|
|
862
905
|
"""
|
|
863
906
|
Ingest restore points into neo4j.
|
|
864
907
|
"""
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
point.restoredate = rp.earliest_restore_date,
|
|
872
|
-
point.restorepointtype = rp.restore_point_type,
|
|
873
|
-
point.creationdate = rp.restore_point_creation_date,
|
|
874
|
-
point.lastupdated = $azure_update_tag
|
|
875
|
-
WITH point, rp
|
|
876
|
-
MATCH (d:AzureSQLDatabase{id: rp.database_id})
|
|
877
|
-
MERGE (d)-[r:CONTAINS]->(point)
|
|
878
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
879
|
-
SET r.lastupdated = $azure_update_tag
|
|
880
|
-
"""
|
|
881
|
-
|
|
882
|
-
neo4j_session.run(
|
|
883
|
-
ingest_restore_points,
|
|
884
|
-
restore_points_list=restore_points,
|
|
885
|
-
azure_update_tag=update_tag,
|
|
908
|
+
load(
|
|
909
|
+
neo4j_session,
|
|
910
|
+
AzureRestorePointSchema(),
|
|
911
|
+
restore_points,
|
|
912
|
+
lastupdated=update_tag,
|
|
913
|
+
AZURE_SUBSCRIPTION_ID=subscription_id,
|
|
886
914
|
)
|
|
887
915
|
|
|
888
916
|
|
|
889
917
|
@timeit
|
|
890
918
|
def _load_transparent_data_encryptions(
|
|
891
|
-
|
|
919
|
+
neo4j_session: neo4j.Session,
|
|
920
|
+
encryptions_list: List[Dict],
|
|
921
|
+
subscription_id: str,
|
|
922
|
+
update_tag: int,
|
|
892
923
|
) -> None:
|
|
893
924
|
"""
|
|
894
925
|
Ingest transparent data encryptions into neo4j.
|
|
895
926
|
"""
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
tae.status = e.status,
|
|
903
|
-
tae.lastupdated = $azure_update_tag
|
|
904
|
-
WITH tae, e
|
|
905
|
-
MATCH (d:AzureSQLDatabase{id: e.database_id})
|
|
906
|
-
MERGE (d)-[r:CONTAINS]->(tae)
|
|
907
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
908
|
-
SET r.lastupdated = $azure_update_tag
|
|
909
|
-
"""
|
|
910
|
-
|
|
911
|
-
neo4j_session.run(
|
|
912
|
-
ingest_data_encryptions,
|
|
913
|
-
transparent_data_encryptions_list=encryptions_list,
|
|
914
|
-
azure_update_tag=update_tag,
|
|
927
|
+
load(
|
|
928
|
+
neo4j_session,
|
|
929
|
+
AzureTransparentDataEncryptionSchema(),
|
|
930
|
+
encryptions_list,
|
|
931
|
+
lastupdated=update_tag,
|
|
932
|
+
AZURE_SUBSCRIPTION_ID=subscription_id,
|
|
915
933
|
)
|
|
916
934
|
|
|
917
935
|
|
|
918
936
|
@timeit
|
|
919
937
|
def cleanup_azure_sql_servers(
|
|
920
|
-
|
|
938
|
+
neo4j_session: neo4j.Session,
|
|
939
|
+
common_job_parameters: Dict,
|
|
921
940
|
) -> None:
|
|
922
|
-
|
|
941
|
+
for node in [
|
|
942
|
+
AzureSQLServerSchema,
|
|
943
|
+
AzureServerDNSAliasSchema,
|
|
944
|
+
AzureServerADAdministratorSchema,
|
|
945
|
+
AzureReplicationLinkSchema,
|
|
946
|
+
AzureRestorePointSchema,
|
|
947
|
+
AzureTransparentDataEncryptionSchema,
|
|
948
|
+
AzureDatabaseThreatDetectionPolicySchema,
|
|
949
|
+
AzureSQLDatabaseSchema,
|
|
950
|
+
AzureElasticPoolSchema,
|
|
951
|
+
AzureFailoverGroupSchema,
|
|
952
|
+
AzureRecoverableDatabaseSchema,
|
|
953
|
+
AzureRestorableDroppedDatabaseSchema,
|
|
954
|
+
]:
|
|
955
|
+
GraphJob.from_node_schema(node(), common_job_parameters).run(
|
|
956
|
+
neo4j_session,
|
|
957
|
+
)
|
|
923
958
|
|
|
924
959
|
|
|
925
960
|
@timeit
|
|
926
961
|
def sync(
|
|
927
|
-
|
|
928
|
-
|
|
962
|
+
neo4j_session: neo4j.Session,
|
|
963
|
+
credentials: Credentials,
|
|
964
|
+
subscription_id: str,
|
|
965
|
+
sync_tag: int,
|
|
966
|
+
common_job_parameters: Dict,
|
|
929
967
|
) -> None:
|
|
930
968
|
logger.info("Syncing Azure SQL for subscription '%s'.", subscription_id)
|
|
931
969
|
server_list = get_server_list(credentials, subscription_id)
|
|
932
970
|
load_server_data(neo4j_session, subscription_id, server_list, sync_tag)
|
|
933
|
-
sync_server_details(
|
|
971
|
+
sync_server_details(
|
|
972
|
+
neo4j_session,
|
|
973
|
+
credentials,
|
|
974
|
+
subscription_id,
|
|
975
|
+
server_list,
|
|
976
|
+
sync_tag,
|
|
977
|
+
)
|
|
934
978
|
cleanup_azure_sql_servers(neo4j_session, common_job_parameters)
|