cartography 0.102.0rc2__py3-none-any.whl → 0.103.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.
Potentially problematic release.
This version of cartography might be problematic. Click here for more details.
- cartography/__main__.py +1 -2
- cartography/_version.py +2 -2
- cartography/cli.py +376 -249
- cartography/client/core/tx.py +39 -18
- cartography/config.py +28 -0
- cartography/driftdetect/__main__.py +1 -2
- cartography/driftdetect/add_shortcut.py +10 -2
- cartography/driftdetect/cli.py +71 -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 +35 -15
- cartography/graph/job.py +46 -17
- cartography/graph/querybuilder.py +165 -80
- cartography/graph/statement.py +35 -26
- cartography/intel/analysis.py +4 -1
- cartography/intel/aws/__init__.py +114 -55
- cartography/intel/aws/apigateway.py +134 -63
- cartography/intel/aws/cloudtrail.py +127 -0
- cartography/intel/aws/cloudwatch.py +93 -0
- cartography/intel/aws/config.py +56 -20
- cartography/intel/aws/dynamodb.py +108 -40
- cartography/intel/aws/ec2/__init__.py +2 -2
- cartography/intel/aws/ec2/auto_scaling_groups.py +181 -78
- cartography/intel/aws/ec2/elastic_ip_addresses.py +41 -13
- cartography/intel/aws/ec2/images.py +49 -20
- cartography/intel/aws/ec2/instances.py +234 -136
- cartography/intel/aws/ec2/internet_gateways.py +40 -11
- cartography/intel/aws/ec2/key_pairs.py +44 -20
- cartography/intel/aws/ec2/launch_templates.py +101 -59
- cartography/intel/aws/ec2/load_balancer_v2s.py +104 -39
- cartography/intel/aws/ec2/load_balancers.py +82 -42
- cartography/intel/aws/ec2/network_acls.py +89 -65
- cartography/intel/aws/ec2/network_interfaces.py +146 -87
- cartography/intel/aws/ec2/reserved_instances.py +45 -16
- cartography/intel/aws/ec2/route_tables.py +138 -98
- cartography/intel/aws/ec2/security_groups.py +71 -21
- cartography/intel/aws/ec2/snapshots.py +61 -22
- cartography/intel/aws/ec2/subnets.py +54 -18
- cartography/intel/aws/ec2/tgw.py +100 -34
- cartography/intel/aws/ec2/util.py +1 -1
- cartography/intel/aws/ec2/volumes.py +69 -41
- cartography/intel/aws/ec2/vpc.py +37 -12
- cartography/intel/aws/ec2/vpc_peerings.py +83 -24
- cartography/intel/aws/ecr.py +88 -32
- cartography/intel/aws/ecs.py +83 -47
- cartography/intel/aws/efs.py +93 -0
- cartography/intel/aws/eks.py +55 -29
- cartography/intel/aws/elasticache.py +42 -18
- cartography/intel/aws/elasticsearch.py +57 -20
- cartography/intel/aws/emr.py +61 -23
- cartography/intel/aws/iam.py +401 -145
- cartography/intel/aws/iam_instance_profiles.py +22 -22
- cartography/intel/aws/identitycenter.py +71 -37
- cartography/intel/aws/inspector.py +159 -89
- cartography/intel/aws/kms.py +92 -38
- cartography/intel/aws/lambda_function.py +103 -34
- cartography/intel/aws/organizations.py +30 -10
- cartography/intel/aws/permission_relationships.py +133 -51
- cartography/intel/aws/rds.py +249 -85
- cartography/intel/aws/redshift.py +107 -46
- cartography/intel/aws/resourcegroupstaggingapi.py +120 -66
- cartography/intel/aws/resources.py +57 -46
- cartography/intel/aws/route53.py +108 -61
- cartography/intel/aws/s3.py +168 -83
- cartography/intel/aws/s3accountpublicaccessblock.py +157 -0
- cartography/intel/aws/secretsmanager.py +24 -12
- cartography/intel/aws/securityhub.py +20 -9
- cartography/intel/aws/sns.py +166 -0
- cartography/intel/aws/sqs.py +60 -28
- cartography/intel/aws/ssm.py +70 -30
- cartography/intel/aws/util/arns.py +7 -7
- cartography/intel/aws/util/common.py +31 -4
- cartography/intel/azure/__init__.py +78 -19
- cartography/intel/azure/compute.py +101 -27
- cartography/intel/azure/cosmosdb.py +496 -170
- cartography/intel/azure/sql.py +296 -105
- cartography/intel/azure/storage.py +322 -113
- cartography/intel/azure/subscription.py +39 -23
- cartography/intel/azure/tenant.py +13 -4
- cartography/intel/azure/util/credentials.py +95 -55
- 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 +3 -2
- cartography/intel/crowdstrike/__init__.py +11 -9
- cartography/intel/crowdstrike/endpoints.py +5 -1
- cartography/intel/crowdstrike/spotlight.py +8 -3
- cartography/intel/cve/__init__.py +46 -13
- cartography/intel/cve/feed.py +48 -12
- 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 +36 -10
- 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 +25 -7
- cartography/intel/entra/ou.py +112 -0
- cartography/intel/entra/users.py +69 -63
- cartography/intel/gcp/__init__.py +185 -49
- cartography/intel/gcp/compute.py +418 -231
- cartography/intel/gcp/crm.py +96 -43
- cartography/intel/gcp/dns.py +60 -19
- cartography/intel/gcp/gke.py +72 -38
- cartography/intel/gcp/iam.py +61 -41
- cartography/intel/gcp/storage.py +84 -55
- cartography/intel/github/__init__.py +13 -11
- cartography/intel/github/repos.py +270 -137
- cartography/intel/github/teams.py +170 -88
- cartography/intel/github/users.py +70 -39
- cartography/intel/github/util.py +36 -34
- cartography/intel/gsuite/__init__.py +47 -26
- cartography/intel/gsuite/api.py +73 -30
- cartography/intel/jamf/__init__.py +19 -1
- cartography/intel/jamf/computers.py +30 -7
- cartography/intel/jamf/util.py +7 -2
- cartography/intel/kandji/__init__.py +6 -3
- cartography/intel/kandji/devices.py +14 -8
- cartography/intel/kubernetes/namespaces.py +7 -4
- cartography/intel/kubernetes/pods.py +7 -4
- cartography/intel/kubernetes/services.py +8 -4
- 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 +134 -38
- cartography/intel/oci/organizations.py +13 -6
- cartography/intel/oci/utils.py +43 -20
- cartography/intel/okta/__init__.py +66 -15
- cartography/intel/okta/applications.py +42 -20
- cartography/intel/okta/awssaml.py +93 -33
- cartography/intel/okta/factors.py +16 -4
- cartography/intel/okta/groups.py +56 -29
- cartography/intel/okta/organization.py +5 -1
- cartography/intel/okta/origins.py +6 -2
- cartography/intel/okta/roles.py +15 -5
- cartography/intel/okta/users.py +20 -8
- cartography/intel/okta/utils.py +6 -4
- cartography/intel/openai/__init__.py +86 -0
- cartography/intel/openai/adminapikeys.py +90 -0
- cartography/intel/openai/apikeys.py +96 -0
- cartography/intel/openai/projects.py +94 -0
- cartography/intel/openai/serviceaccounts.py +82 -0
- cartography/intel/openai/users.py +78 -0
- cartography/intel/openai/util.py +29 -0
- cartography/intel/pagerduty/__init__.py +8 -7
- cartography/intel/pagerduty/escalation_policies.py +18 -6
- cartography/intel/pagerduty/schedules.py +12 -4
- cartography/intel/pagerduty/services.py +11 -4
- cartography/intel/pagerduty/teams.py +8 -3
- cartography/intel/pagerduty/users.py +3 -1
- cartography/intel/pagerduty/vendors.py +3 -1
- cartography/intel/semgrep/__init__.py +24 -6
- cartography/intel/semgrep/dependencies.py +50 -28
- cartography/intel/semgrep/deployment.py +3 -1
- cartography/intel/semgrep/findings.py +42 -18
- cartography/intel/snipeit/__init__.py +17 -3
- cartography/intel/snipeit/asset.py +12 -6
- cartography/intel/snipeit/user.py +8 -5
- cartography/intel/snipeit/util.py +9 -4
- 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/models/aws/apigateway.py +21 -17
- cartography/models/aws/apigatewaycertificate.py +28 -22
- cartography/models/aws/apigatewayresource.py +28 -20
- cartography/models/aws/apigatewaystage.py +33 -25
- cartography/models/aws/cloudtrail/__init__.py +0 -0
- cartography/models/aws/cloudtrail/trail.py +61 -0
- cartography/models/aws/cloudwatch/__init__.py +0 -0
- cartography/models/aws/cloudwatch/loggroup.py +52 -0
- cartography/models/aws/dynamodb/gsi.py +30 -22
- cartography/models/aws/dynamodb/tables.py +25 -17
- cartography/models/aws/ec2/auto_scaling_groups.py +102 -82
- cartography/models/aws/ec2/images.py +36 -34
- cartography/models/aws/ec2/instances.py +51 -45
- cartography/models/aws/ec2/keypair.py +21 -16
- cartography/models/aws/ec2/keypair_instance.py +28 -21
- cartography/models/aws/ec2/launch_configurations.py +30 -26
- 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 +27 -23
- cartography/models/aws/ec2/load_balancers.py +47 -37
- cartography/models/aws/ec2/network_acl_rules.py +38 -30
- cartography/models/aws/ec2/network_acls.py +38 -29
- cartography/models/aws/ec2/networkinterface_instance.py +52 -39
- cartography/models/aws/ec2/networkinterfaces.py +53 -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 +44 -34
- cartography/models/aws/ec2/route_tables.py +50 -43
- cartography/models/aws/ec2/routes.py +45 -37
- cartography/models/aws/ec2/securitygroup_instance.py +29 -20
- cartography/models/aws/ec2/securitygroup_networkinterface.py +24 -15
- cartography/models/aws/ec2/subnet_instance.py +24 -19
- cartography/models/aws/ec2/subnet_networkinterface.py +40 -31
- cartography/models/aws/ec2/volumes.py +47 -40
- cartography/models/aws/efs/__init__.py +0 -0
- cartography/models/aws/efs/mount_target.py +52 -0
- cartography/models/aws/eks/clusters.py +23 -21
- cartography/models/aws/emr.py +32 -30
- cartography/models/aws/iam/instanceprofile.py +33 -24
- cartography/models/aws/identitycenter/awsidentitycenter.py +18 -14
- cartography/models/aws/identitycenter/awspermissionset.py +37 -29
- cartography/models/aws/identitycenter/awsssouser.py +23 -21
- cartography/models/aws/inspector/findings.py +77 -65
- cartography/models/aws/inspector/packages.py +35 -29
- cartography/models/aws/s3/__init__.py +0 -0
- cartography/models/aws/s3/account_public_access_block.py +51 -0
- cartography/models/aws/sns/__init__.py +0 -0
- cartography/models/aws/sns/topic.py +50 -0
- cartography/models/aws/ssm/instance_information.py +51 -39
- cartography/models/aws/ssm/instance_patch.py +32 -26
- 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 +82 -0
- cartography/models/cloudflare/role.py +44 -0
- cartography/models/cloudflare/zone.py +59 -0
- cartography/models/core/common.py +12 -10
- cartography/models/core/nodes.py +5 -2
- cartography/models/core/relationships.py +14 -6
- cartography/models/crowdstrike/hosts.py +37 -35
- 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 +56 -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 +46 -44
- cartography/models/duo/web_authn_credential.py +27 -19
- cartography/models/entra/ou.py +48 -0
- cartography/models/entra/tenant.py +24 -18
- cartography/models/entra/user.py +64 -48
- cartography/models/gcp/iam.py +23 -23
- cartography/models/github/orgs.py +5 -4
- cartography/models/github/teams.py +37 -31
- cartography/models/github/users.py +34 -23
- cartography/models/kandji/device.py +22 -16
- cartography/models/kandji/tenant.py +6 -4
- cartography/models/lastpass/tenant.py +3 -3
- cartography/models/lastpass/user.py +32 -28
- cartography/models/openai/__init__.py +0 -0
- cartography/models/openai/adminapikey.py +90 -0
- cartography/models/openai/apikey.py +84 -0
- cartography/models/openai/organization.py +17 -0
- cartography/models/openai/project.py +70 -0
- cartography/models/openai/serviceaccount.py +50 -0
- cartography/models/openai/user.py +49 -0
- cartography/models/semgrep/dependencies.py +36 -24
- cartography/models/semgrep/deployment.py +5 -5
- cartography/models/semgrep/findings.py +58 -42
- cartography/models/semgrep/locations.py +27 -21
- cartography/models/snipeit/asset.py +30 -21
- cartography/models/snipeit/tenant.py +6 -4
- cartography/models/snipeit/user.py +19 -12
- cartography/models/tailscale/__init__.py +0 -0
- cartography/models/tailscale/device.py +95 -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 +52 -0
- cartography/stats.py +3 -3
- cartography/sync.py +113 -31
- cartography/util.py +84 -62
- {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/METADATA +8 -15
- cartography-0.103.0.dist-info/RECORD +442 -0
- {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/WHEEL +1 -1
- cartography-0.102.0rc2.dist-info/RECORD +0 -381
- {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/entry_points.txt +0 -0
- {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/top_level.txt +0 -0
cartography/intel/azure/sql.py
CHANGED
|
@@ -14,10 +14,11 @@ from azure.mgmt.sql.models import SecurityAlertPolicyName
|
|
|
14
14
|
from azure.mgmt.sql.models import TransparentDataEncryptionName
|
|
15
15
|
from msrestazure.azure_exceptions import CloudError
|
|
16
16
|
|
|
17
|
-
from .util.credentials import Credentials
|
|
18
17
|
from cartography.util import run_cleanup_job
|
|
19
18
|
from cartography.util import timeit
|
|
20
19
|
|
|
20
|
+
from .util.credentials import Credentials
|
|
21
|
+
|
|
21
22
|
logger = logging.getLogger(__name__)
|
|
22
23
|
|
|
23
24
|
|
|
@@ -51,16 +52,18 @@ def get_server_list(credentials: Credentials, subscription_id: str) -> List[Dict
|
|
|
51
52
|
return []
|
|
52
53
|
|
|
53
54
|
for server in server_list:
|
|
54
|
-
x = server[
|
|
55
|
-
server[
|
|
55
|
+
x = server["id"].split("/")
|
|
56
|
+
server["resourceGroup"] = x[x.index("resourceGroups") + 1]
|
|
56
57
|
|
|
57
58
|
return server_list
|
|
58
59
|
|
|
59
60
|
|
|
60
61
|
@timeit
|
|
61
62
|
def load_server_data(
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
neo4j_session: neo4j.Session,
|
|
64
|
+
subscription_id: str,
|
|
65
|
+
server_list: List[Dict],
|
|
66
|
+
azure_update_tag: int,
|
|
64
67
|
) -> None:
|
|
65
68
|
"""
|
|
66
69
|
Ingest the server details into neo4j.
|
|
@@ -92,8 +95,11 @@ def load_server_data(
|
|
|
92
95
|
|
|
93
96
|
@timeit
|
|
94
97
|
def sync_server_details(
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
neo4j_session: neo4j.Session,
|
|
99
|
+
credentials: Credentials,
|
|
100
|
+
subscription_id: str,
|
|
101
|
+
server_list: List[Dict],
|
|
102
|
+
sync_tag: int,
|
|
97
103
|
) -> None:
|
|
98
104
|
details = get_server_details(credentials, subscription_id, server_list)
|
|
99
105
|
load_server_details(neo4j_session, credentials, subscription_id, details, sync_tag) # type: ignore
|
|
@@ -101,7 +107,9 @@ def sync_server_details(
|
|
|
101
107
|
|
|
102
108
|
@timeit
|
|
103
109
|
def get_server_details(
|
|
104
|
-
|
|
110
|
+
credentials: Credentials,
|
|
111
|
+
subscription_id: str,
|
|
112
|
+
server_list: List[Dict],
|
|
105
113
|
) -> Generator[Any, Any, Any]:
|
|
106
114
|
"""
|
|
107
115
|
Iterate over each servers to get its resource details.
|
|
@@ -110,17 +118,25 @@ def get_server_details(
|
|
|
110
118
|
dns_alias = get_dns_aliases(credentials, subscription_id, server)
|
|
111
119
|
ad_admins = get_ad_admins(credentials, subscription_id, server)
|
|
112
120
|
r_databases = get_recoverable_databases(credentials, subscription_id, server)
|
|
113
|
-
rd_databases = get_restorable_dropped_databases(
|
|
121
|
+
rd_databases = get_restorable_dropped_databases(
|
|
122
|
+
credentials,
|
|
123
|
+
subscription_id,
|
|
124
|
+
server,
|
|
125
|
+
)
|
|
114
126
|
fgs = get_failover_groups(credentials, subscription_id, server)
|
|
115
127
|
elastic_pools = get_elastic_pools(credentials, subscription_id, server)
|
|
116
128
|
databases = get_databases(credentials, subscription_id, server)
|
|
117
|
-
yield server[
|
|
118
|
-
|
|
129
|
+
yield server["id"], server["name"], server[
|
|
130
|
+
"resourceGroup"
|
|
119
131
|
], dns_alias, ad_admins, r_databases, rd_databases, fgs, elastic_pools, databases
|
|
120
132
|
|
|
121
133
|
|
|
122
134
|
@timeit
|
|
123
|
-
def get_dns_aliases(
|
|
135
|
+
def get_dns_aliases(
|
|
136
|
+
credentials: Credentials,
|
|
137
|
+
subscription_id: str,
|
|
138
|
+
server: Dict,
|
|
139
|
+
) -> List[Dict]:
|
|
124
140
|
"""
|
|
125
141
|
Returns details of the DNS aliases in a server.
|
|
126
142
|
"""
|
|
@@ -129,12 +145,17 @@ def get_dns_aliases(credentials: Credentials, subscription_id: str, server: Dict
|
|
|
129
145
|
dns_aliases = list(
|
|
130
146
|
map(
|
|
131
147
|
lambda x: x.as_dict(),
|
|
132
|
-
client.server_dns_aliases.list_by_server(
|
|
148
|
+
client.server_dns_aliases.list_by_server(
|
|
149
|
+
server["resourceGroup"],
|
|
150
|
+
server["name"],
|
|
151
|
+
),
|
|
133
152
|
),
|
|
134
153
|
)
|
|
135
154
|
|
|
136
155
|
except ClientAuthenticationError as e:
|
|
137
|
-
logger.warning(
|
|
156
|
+
logger.warning(
|
|
157
|
+
f"Client Authentication Error while retrieving DNS Aliases - {e}",
|
|
158
|
+
)
|
|
138
159
|
return []
|
|
139
160
|
except ResourceNotFoundError as e:
|
|
140
161
|
logger.warning(f"DNS Alias resource not found error - {e}")
|
|
@@ -147,7 +168,11 @@ def get_dns_aliases(credentials: Credentials, subscription_id: str, server: Dict
|
|
|
147
168
|
|
|
148
169
|
|
|
149
170
|
@timeit
|
|
150
|
-
def get_ad_admins(
|
|
171
|
+
def get_ad_admins(
|
|
172
|
+
credentials: Credentials,
|
|
173
|
+
subscription_id: str,
|
|
174
|
+
server: Dict,
|
|
175
|
+
) -> List[Dict]:
|
|
151
176
|
"""
|
|
152
177
|
Returns details of the Server AD Administrators in a server.
|
|
153
178
|
"""
|
|
@@ -157,14 +182,16 @@ def get_ad_admins(credentials: Credentials, subscription_id: str, server: Dict)
|
|
|
157
182
|
map(
|
|
158
183
|
lambda x: x.as_dict(),
|
|
159
184
|
client.server_azure_ad_administrators.list_by_server(
|
|
160
|
-
server[
|
|
161
|
-
server[
|
|
185
|
+
server["resourceGroup"],
|
|
186
|
+
server["name"],
|
|
162
187
|
),
|
|
163
188
|
),
|
|
164
189
|
)
|
|
165
190
|
|
|
166
191
|
except ClientAuthenticationError as e:
|
|
167
|
-
logger.warning(
|
|
192
|
+
logger.warning(
|
|
193
|
+
f"Client Authentication Error while retrieving Azure AD Administrators - {e}",
|
|
194
|
+
)
|
|
168
195
|
return []
|
|
169
196
|
except ResourceNotFoundError as e:
|
|
170
197
|
logger.warning(f"Azure AD Administrators resource not found error - {e}")
|
|
@@ -177,7 +204,11 @@ def get_ad_admins(credentials: Credentials, subscription_id: str, server: Dict)
|
|
|
177
204
|
|
|
178
205
|
|
|
179
206
|
@timeit
|
|
180
|
-
def get_recoverable_databases(
|
|
207
|
+
def get_recoverable_databases(
|
|
208
|
+
credentials: Credentials,
|
|
209
|
+
subscription_id: str,
|
|
210
|
+
server: Dict,
|
|
211
|
+
) -> List[Dict]:
|
|
181
212
|
"""
|
|
182
213
|
Returns details of the Recoverable databases in a server.
|
|
183
214
|
"""
|
|
@@ -187,8 +218,8 @@ def get_recoverable_databases(credentials: Credentials, subscription_id: str, se
|
|
|
187
218
|
map(
|
|
188
219
|
lambda x: x.as_dict(),
|
|
189
220
|
client.recoverable_databases.list_by_server(
|
|
190
|
-
server[
|
|
191
|
-
server[
|
|
221
|
+
server["resourceGroup"],
|
|
222
|
+
server["name"],
|
|
192
223
|
),
|
|
193
224
|
),
|
|
194
225
|
)
|
|
@@ -197,7 +228,9 @@ def get_recoverable_databases(credentials: Credentials, subscription_id: str, se
|
|
|
197
228
|
# The API returns a '404 CloudError: Not Found for url: <url>' if no recoverable databases are present.
|
|
198
229
|
return []
|
|
199
230
|
except ClientAuthenticationError as e:
|
|
200
|
-
logger.warning(
|
|
231
|
+
logger.warning(
|
|
232
|
+
f"Client Authentication Error while retrieving recoverable databases - {e}",
|
|
233
|
+
)
|
|
201
234
|
return []
|
|
202
235
|
except ResourceNotFoundError as e:
|
|
203
236
|
logger.warning(f"Recoverable databases resource not found error - {e}")
|
|
@@ -210,7 +243,11 @@ def get_recoverable_databases(credentials: Credentials, subscription_id: str, se
|
|
|
210
243
|
|
|
211
244
|
|
|
212
245
|
@timeit
|
|
213
|
-
def get_restorable_dropped_databases(
|
|
246
|
+
def get_restorable_dropped_databases(
|
|
247
|
+
credentials: Credentials,
|
|
248
|
+
subscription_id: str,
|
|
249
|
+
server: Dict,
|
|
250
|
+
) -> List[Dict]:
|
|
214
251
|
"""
|
|
215
252
|
Returns details of the Restorable Dropped Databases in a server.
|
|
216
253
|
"""
|
|
@@ -220,13 +257,16 @@ def get_restorable_dropped_databases(credentials: Credentials, subscription_id:
|
|
|
220
257
|
map(
|
|
221
258
|
lambda x: x.as_dict(),
|
|
222
259
|
client.restorable_dropped_databases.list_by_server(
|
|
223
|
-
server[
|
|
260
|
+
server["resourceGroup"],
|
|
261
|
+
server["name"],
|
|
224
262
|
),
|
|
225
263
|
),
|
|
226
264
|
)
|
|
227
265
|
|
|
228
266
|
except ClientAuthenticationError as e:
|
|
229
|
-
logger.warning(
|
|
267
|
+
logger.warning(
|
|
268
|
+
f"Client Authentication Error while retrieving Restorable Dropped Databases - {e}",
|
|
269
|
+
)
|
|
230
270
|
return []
|
|
231
271
|
except ResourceNotFoundError as e:
|
|
232
272
|
logger.warning(f"Restorable Dropped Databases resource not found error - {e}")
|
|
@@ -239,18 +279,30 @@ def get_restorable_dropped_databases(credentials: Credentials, subscription_id:
|
|
|
239
279
|
|
|
240
280
|
|
|
241
281
|
@timeit
|
|
242
|
-
def get_failover_groups(
|
|
282
|
+
def get_failover_groups(
|
|
283
|
+
credentials: Credentials,
|
|
284
|
+
subscription_id: str,
|
|
285
|
+
server: Dict,
|
|
286
|
+
) -> List[Dict]:
|
|
243
287
|
"""
|
|
244
288
|
Returns details of Failover groups in a server.
|
|
245
289
|
"""
|
|
246
290
|
try:
|
|
247
291
|
client = get_client(credentials, subscription_id)
|
|
248
292
|
failover_groups = list(
|
|
249
|
-
map(
|
|
293
|
+
map(
|
|
294
|
+
lambda x: x.as_dict(),
|
|
295
|
+
client.failover_groups.list_by_server(
|
|
296
|
+
server["resourceGroup"],
|
|
297
|
+
server["name"],
|
|
298
|
+
),
|
|
299
|
+
),
|
|
250
300
|
)
|
|
251
301
|
|
|
252
302
|
except ClientAuthenticationError as e:
|
|
253
|
-
logger.warning(
|
|
303
|
+
logger.warning(
|
|
304
|
+
f"Client Authentication Error while retrieving Failover groups - {e}",
|
|
305
|
+
)
|
|
254
306
|
return []
|
|
255
307
|
except ResourceNotFoundError as e:
|
|
256
308
|
logger.warning(f"Failover groups resource not found error - {e}")
|
|
@@ -263,18 +315,30 @@ def get_failover_groups(credentials: Credentials, subscription_id: str, server:
|
|
|
263
315
|
|
|
264
316
|
|
|
265
317
|
@timeit
|
|
266
|
-
def get_elastic_pools(
|
|
318
|
+
def get_elastic_pools(
|
|
319
|
+
credentials: Credentials,
|
|
320
|
+
subscription_id: str,
|
|
321
|
+
server: Dict,
|
|
322
|
+
) -> List[Dict]:
|
|
267
323
|
"""
|
|
268
324
|
Returns details of Elastic Pools in a server.
|
|
269
325
|
"""
|
|
270
326
|
try:
|
|
271
327
|
client = get_client(credentials, subscription_id)
|
|
272
328
|
elastic_pools = list(
|
|
273
|
-
map(
|
|
329
|
+
map(
|
|
330
|
+
lambda x: x.as_dict(),
|
|
331
|
+
client.elastic_pools.list_by_server(
|
|
332
|
+
server["resourceGroup"],
|
|
333
|
+
server["name"],
|
|
334
|
+
),
|
|
335
|
+
),
|
|
274
336
|
)
|
|
275
337
|
|
|
276
338
|
except ClientAuthenticationError as e:
|
|
277
|
-
logger.warning(
|
|
339
|
+
logger.warning(
|
|
340
|
+
f"Client Authentication Error while retrieving Elastic Pools - {e}",
|
|
341
|
+
)
|
|
278
342
|
return []
|
|
279
343
|
except ResourceNotFoundError as e:
|
|
280
344
|
logger.warning(f"Elastic Pools resource not found error - {e}")
|
|
@@ -287,18 +351,30 @@ def get_elastic_pools(credentials: Credentials, subscription_id: str, server: Di
|
|
|
287
351
|
|
|
288
352
|
|
|
289
353
|
@timeit
|
|
290
|
-
def get_databases(
|
|
354
|
+
def get_databases(
|
|
355
|
+
credentials: Credentials,
|
|
356
|
+
subscription_id: str,
|
|
357
|
+
server: Dict,
|
|
358
|
+
) -> List[Dict]:
|
|
291
359
|
"""
|
|
292
360
|
Returns details of Databases in a SQL server.
|
|
293
361
|
"""
|
|
294
362
|
try:
|
|
295
363
|
client = get_client(credentials, subscription_id)
|
|
296
364
|
databases = list(
|
|
297
|
-
map(
|
|
365
|
+
map(
|
|
366
|
+
lambda x: x.as_dict(),
|
|
367
|
+
client.databases.list_by_server(
|
|
368
|
+
server["resourceGroup"],
|
|
369
|
+
server["name"],
|
|
370
|
+
),
|
|
371
|
+
),
|
|
298
372
|
)
|
|
299
373
|
|
|
300
374
|
except ClientAuthenticationError as e:
|
|
301
|
-
logger.warning(
|
|
375
|
+
logger.warning(
|
|
376
|
+
f"Client Authentication Error while retrieving SQL databases - {e}",
|
|
377
|
+
)
|
|
302
378
|
return []
|
|
303
379
|
except ResourceNotFoundError as e:
|
|
304
380
|
logger.warning(f"SQL databases resource not found error - {e}")
|
|
@@ -312,8 +388,11 @@ def get_databases(credentials: Credentials, subscription_id: str, server: Dict)
|
|
|
312
388
|
|
|
313
389
|
@timeit
|
|
314
390
|
def load_server_details(
|
|
315
|
-
|
|
316
|
-
|
|
391
|
+
neo4j_session: neo4j.Session,
|
|
392
|
+
credentials: Credentials,
|
|
393
|
+
subscription_id: str,
|
|
394
|
+
details: List[Tuple[Any, Any, Any, Any, Any, Any, Any, Any, Any, Any]],
|
|
395
|
+
update_tag: int,
|
|
317
396
|
) -> None:
|
|
318
397
|
"""
|
|
319
398
|
Create dictionaries for every resource in the server so we can import them in a single query
|
|
@@ -326,64 +405,87 @@ def load_server_details(
|
|
|
326
405
|
elastic_pools = []
|
|
327
406
|
databases = []
|
|
328
407
|
|
|
329
|
-
for
|
|
408
|
+
for (
|
|
409
|
+
server_id,
|
|
410
|
+
name,
|
|
411
|
+
rg,
|
|
412
|
+
dns_alias,
|
|
413
|
+
ad_admin,
|
|
414
|
+
r_database,
|
|
415
|
+
rd_database,
|
|
416
|
+
fg,
|
|
417
|
+
elastic_pool,
|
|
418
|
+
database,
|
|
419
|
+
) in details:
|
|
330
420
|
if len(dns_alias) > 0:
|
|
331
421
|
for alias in dns_alias:
|
|
332
|
-
alias[
|
|
333
|
-
alias[
|
|
422
|
+
alias["server_name"] = name
|
|
423
|
+
alias["server_id"] = server_id
|
|
334
424
|
dns_aliases.append(alias)
|
|
335
425
|
|
|
336
426
|
if len(ad_admin) > 0:
|
|
337
427
|
for admin in ad_admin:
|
|
338
|
-
admin[
|
|
339
|
-
admin[
|
|
428
|
+
admin["server_name"] = name
|
|
429
|
+
admin["server_id"] = server_id
|
|
340
430
|
ad_admins.append(admin)
|
|
341
431
|
|
|
342
432
|
if len(r_database) > 0:
|
|
343
433
|
for rdb in r_database:
|
|
344
|
-
rdb[
|
|
345
|
-
rdb[
|
|
434
|
+
rdb["server_name"] = name
|
|
435
|
+
rdb["server_id"] = server_id
|
|
346
436
|
recoverable_databases.append(rdb)
|
|
347
437
|
|
|
348
438
|
if len(rd_database) > 0:
|
|
349
439
|
for rddb in rd_database:
|
|
350
|
-
rddb[
|
|
351
|
-
rddb[
|
|
440
|
+
rddb["server_name"] = name
|
|
441
|
+
rddb["server_id"] = server_id
|
|
352
442
|
restorable_dropped_databases.append(rddb)
|
|
353
443
|
|
|
354
444
|
if len(fg) > 0:
|
|
355
445
|
for group in fg:
|
|
356
|
-
group[
|
|
357
|
-
group[
|
|
446
|
+
group["server_name"] = name
|
|
447
|
+
group["server_id"] = server_id
|
|
358
448
|
failover_groups.append(group)
|
|
359
449
|
|
|
360
450
|
if len(elastic_pool) > 0:
|
|
361
451
|
for pool in elastic_pool:
|
|
362
|
-
pool[
|
|
363
|
-
pool[
|
|
452
|
+
pool["server_name"] = name
|
|
453
|
+
pool["server_id"] = server_id
|
|
364
454
|
elastic_pools.append(pool)
|
|
365
455
|
|
|
366
456
|
if len(database) > 0:
|
|
367
457
|
for db in database:
|
|
368
|
-
db[
|
|
369
|
-
db[
|
|
370
|
-
db[
|
|
458
|
+
db["server_name"] = name
|
|
459
|
+
db["server_id"] = server_id
|
|
460
|
+
db["resource_group_name"] = rg
|
|
371
461
|
databases.append(db)
|
|
372
462
|
|
|
373
463
|
_load_server_dns_aliases(neo4j_session, dns_aliases, update_tag)
|
|
374
464
|
_load_server_ad_admins(neo4j_session, ad_admins, update_tag)
|
|
375
465
|
_load_recoverable_databases(neo4j_session, recoverable_databases, update_tag)
|
|
376
|
-
_load_restorable_dropped_databases(
|
|
466
|
+
_load_restorable_dropped_databases(
|
|
467
|
+
neo4j_session,
|
|
468
|
+
restorable_dropped_databases,
|
|
469
|
+
update_tag,
|
|
470
|
+
)
|
|
377
471
|
_load_failover_groups(neo4j_session, failover_groups, update_tag)
|
|
378
472
|
_load_elastic_pools(neo4j_session, elastic_pools, update_tag)
|
|
379
473
|
_load_databases(neo4j_session, databases, update_tag)
|
|
380
474
|
|
|
381
|
-
sync_database_details(
|
|
475
|
+
sync_database_details(
|
|
476
|
+
neo4j_session,
|
|
477
|
+
credentials,
|
|
478
|
+
subscription_id,
|
|
479
|
+
databases,
|
|
480
|
+
update_tag,
|
|
481
|
+
)
|
|
382
482
|
|
|
383
483
|
|
|
384
484
|
@timeit
|
|
385
485
|
def _load_server_dns_aliases(
|
|
386
|
-
|
|
486
|
+
neo4j_session: neo4j.Session,
|
|
487
|
+
dns_aliases: List[Dict],
|
|
488
|
+
update_tag: int,
|
|
387
489
|
) -> None:
|
|
388
490
|
"""
|
|
389
491
|
Ingest the DNS Alias details into neo4j.
|
|
@@ -411,7 +513,9 @@ def _load_server_dns_aliases(
|
|
|
411
513
|
|
|
412
514
|
@timeit
|
|
413
515
|
def _load_server_ad_admins(
|
|
414
|
-
|
|
516
|
+
neo4j_session: neo4j.Session,
|
|
517
|
+
ad_admins: List[Dict],
|
|
518
|
+
update_tag: int,
|
|
415
519
|
) -> None:
|
|
416
520
|
"""
|
|
417
521
|
Ingest the Server AD Administrators details into neo4j.
|
|
@@ -440,7 +544,9 @@ def _load_server_ad_admins(
|
|
|
440
544
|
|
|
441
545
|
@timeit
|
|
442
546
|
def _load_recoverable_databases(
|
|
443
|
-
|
|
547
|
+
neo4j_session: neo4j.Session,
|
|
548
|
+
recoverable_databases: List[Dict],
|
|
549
|
+
update_tag: int,
|
|
444
550
|
) -> None:
|
|
445
551
|
"""
|
|
446
552
|
Ingest the recoverable database details into neo4j.
|
|
@@ -470,7 +576,9 @@ def _load_recoverable_databases(
|
|
|
470
576
|
|
|
471
577
|
@timeit
|
|
472
578
|
def _load_restorable_dropped_databases(
|
|
473
|
-
|
|
579
|
+
neo4j_session: neo4j.Session,
|
|
580
|
+
restorable_dropped_databases: List[Dict],
|
|
581
|
+
update_tag: int,
|
|
474
582
|
) -> None:
|
|
475
583
|
"""
|
|
476
584
|
Ingest the restorable dropped database details into neo4j.
|
|
@@ -504,7 +612,9 @@ def _load_restorable_dropped_databases(
|
|
|
504
612
|
|
|
505
613
|
@timeit
|
|
506
614
|
def _load_failover_groups(
|
|
507
|
-
|
|
615
|
+
neo4j_session: neo4j.Session,
|
|
616
|
+
failover_groups: List[Dict],
|
|
617
|
+
update_tag: int,
|
|
508
618
|
) -> None:
|
|
509
619
|
"""
|
|
510
620
|
Ingest the failover groups details into neo4j.
|
|
@@ -533,7 +643,9 @@ def _load_failover_groups(
|
|
|
533
643
|
|
|
534
644
|
@timeit
|
|
535
645
|
def _load_elastic_pools(
|
|
536
|
-
|
|
646
|
+
neo4j_session: neo4j.Session,
|
|
647
|
+
elastic_pools: List[Dict],
|
|
648
|
+
update_tag: int,
|
|
537
649
|
) -> None:
|
|
538
650
|
"""
|
|
539
651
|
Ingest the elastic pool details into neo4j.
|
|
@@ -566,7 +678,9 @@ def _load_elastic_pools(
|
|
|
566
678
|
|
|
567
679
|
@timeit
|
|
568
680
|
def _load_databases(
|
|
569
|
-
|
|
681
|
+
neo4j_session: neo4j.Session,
|
|
682
|
+
databases: List[Dict],
|
|
683
|
+
update_tag: int,
|
|
570
684
|
) -> None:
|
|
571
685
|
"""
|
|
572
686
|
Ingest the database details into neo4j.
|
|
@@ -605,8 +719,11 @@ def _load_databases(
|
|
|
605
719
|
|
|
606
720
|
@timeit
|
|
607
721
|
def sync_database_details(
|
|
608
|
-
|
|
609
|
-
|
|
722
|
+
neo4j_session: neo4j.Session,
|
|
723
|
+
credentials: Credentials,
|
|
724
|
+
subscription_id: str,
|
|
725
|
+
databases: List[Dict],
|
|
726
|
+
update_tag: int,
|
|
610
727
|
) -> None:
|
|
611
728
|
db_details = get_database_details(credentials, subscription_id, databases)
|
|
612
729
|
load_database_details(neo4j_session, db_details, update_tag) # type: ignore
|
|
@@ -614,23 +731,41 @@ def sync_database_details(
|
|
|
614
731
|
|
|
615
732
|
@timeit
|
|
616
733
|
def get_database_details(
|
|
617
|
-
|
|
734
|
+
credentials: Credentials,
|
|
735
|
+
subscription_id: str,
|
|
736
|
+
databases: List[Dict],
|
|
618
737
|
) -> Generator[Any, Any, Any]:
|
|
619
738
|
"""
|
|
620
739
|
Iterate over the databases to get the details of resources in it.
|
|
621
740
|
"""
|
|
622
741
|
for database in databases:
|
|
623
|
-
replication_links = get_replication_links(
|
|
624
|
-
|
|
742
|
+
replication_links = get_replication_links(
|
|
743
|
+
credentials,
|
|
744
|
+
subscription_id,
|
|
745
|
+
database,
|
|
746
|
+
)
|
|
747
|
+
db_threat_detection_policies = get_db_threat_detection_policies(
|
|
748
|
+
credentials,
|
|
749
|
+
subscription_id,
|
|
750
|
+
database,
|
|
751
|
+
)
|
|
625
752
|
restore_points = get_restore_points(credentials, subscription_id, database)
|
|
626
|
-
transparent_data_encryptions = get_transparent_data_encryptions(
|
|
753
|
+
transparent_data_encryptions = get_transparent_data_encryptions(
|
|
754
|
+
credentials,
|
|
755
|
+
subscription_id,
|
|
756
|
+
database,
|
|
757
|
+
)
|
|
627
758
|
yield database[
|
|
628
|
-
|
|
759
|
+
"id"
|
|
629
760
|
], replication_links, db_threat_detection_policies, restore_points, transparent_data_encryptions
|
|
630
761
|
|
|
631
762
|
|
|
632
763
|
@timeit
|
|
633
|
-
def get_replication_links(
|
|
764
|
+
def get_replication_links(
|
|
765
|
+
credentials: Credentials,
|
|
766
|
+
subscription_id: str,
|
|
767
|
+
database: Dict,
|
|
768
|
+
) -> List[Dict]:
|
|
634
769
|
"""
|
|
635
770
|
Returns the details of replication links in a database.
|
|
636
771
|
"""
|
|
@@ -640,15 +775,17 @@ def get_replication_links(credentials: Credentials, subscription_id: str, databa
|
|
|
640
775
|
map(
|
|
641
776
|
lambda x: x.as_dict(),
|
|
642
777
|
client.replication_links.list_by_database(
|
|
643
|
-
database[
|
|
644
|
-
database[
|
|
645
|
-
database[
|
|
778
|
+
database["resource_group_name"],
|
|
779
|
+
database["server_name"],
|
|
780
|
+
database["name"],
|
|
646
781
|
),
|
|
647
782
|
),
|
|
648
783
|
)
|
|
649
784
|
|
|
650
785
|
except ClientAuthenticationError as e:
|
|
651
|
-
logger.warning(
|
|
786
|
+
logger.warning(
|
|
787
|
+
f"Client Authentication Error while retrieving replication links - {e}",
|
|
788
|
+
)
|
|
652
789
|
return []
|
|
653
790
|
except ResourceNotFoundError as e:
|
|
654
791
|
logger.warning(f"Replication links resource not found error - {e}")
|
|
@@ -661,33 +798,45 @@ def get_replication_links(credentials: Credentials, subscription_id: str, databa
|
|
|
661
798
|
|
|
662
799
|
|
|
663
800
|
@timeit
|
|
664
|
-
def get_db_threat_detection_policies(
|
|
801
|
+
def get_db_threat_detection_policies(
|
|
802
|
+
credentials: Credentials,
|
|
803
|
+
subscription_id: str,
|
|
804
|
+
database: Dict,
|
|
805
|
+
) -> List[Dict]:
|
|
665
806
|
"""
|
|
666
807
|
Returns the threat detection policy of a database.
|
|
667
808
|
"""
|
|
668
809
|
try:
|
|
669
810
|
client = get_client(credentials, subscription_id)
|
|
670
811
|
db_threat_detection_policies = client.database_threat_detection_policies.get(
|
|
671
|
-
database[
|
|
672
|
-
database[
|
|
673
|
-
database[
|
|
812
|
+
database["resource_group_name"],
|
|
813
|
+
database["server_name"],
|
|
814
|
+
database["name"],
|
|
674
815
|
SecurityAlertPolicyName.DEFAULT,
|
|
675
816
|
).as_dict()
|
|
676
817
|
except ClientAuthenticationError as e:
|
|
677
|
-
logger.warning(
|
|
818
|
+
logger.warning(
|
|
819
|
+
f"Client Authentication Error while retrieving threat detection policy - {e}",
|
|
820
|
+
)
|
|
678
821
|
return []
|
|
679
822
|
except ResourceNotFoundError as e:
|
|
680
823
|
logger.warning(f"Threat detection policy resource not found error - {e}")
|
|
681
824
|
return []
|
|
682
825
|
except HttpResponseError as e:
|
|
683
|
-
logger.warning(
|
|
826
|
+
logger.warning(
|
|
827
|
+
f"Error while retrieving database threat detection policies - {e}",
|
|
828
|
+
)
|
|
684
829
|
return []
|
|
685
830
|
|
|
686
831
|
return db_threat_detection_policies
|
|
687
832
|
|
|
688
833
|
|
|
689
834
|
@timeit
|
|
690
|
-
def get_restore_points(
|
|
835
|
+
def get_restore_points(
|
|
836
|
+
credentials: Credentials,
|
|
837
|
+
subscription_id: str,
|
|
838
|
+
database: Dict,
|
|
839
|
+
) -> List[Dict]:
|
|
691
840
|
"""
|
|
692
841
|
Returns the details of restore points in a database.
|
|
693
842
|
"""
|
|
@@ -697,15 +846,17 @@ def get_restore_points(credentials: Credentials, subscription_id: str, database:
|
|
|
697
846
|
map(
|
|
698
847
|
lambda x: x.as_dict(),
|
|
699
848
|
client.restore_points.list_by_database(
|
|
700
|
-
database[
|
|
701
|
-
database[
|
|
702
|
-
database[
|
|
849
|
+
database["resource_group_name"],
|
|
850
|
+
database["server_name"],
|
|
851
|
+
database["name"],
|
|
703
852
|
),
|
|
704
853
|
),
|
|
705
854
|
)
|
|
706
855
|
|
|
707
856
|
except ClientAuthenticationError as e:
|
|
708
|
-
logger.warning(
|
|
857
|
+
logger.warning(
|
|
858
|
+
f"Client Authentication Error while retrieving restore points - {e}",
|
|
859
|
+
)
|
|
709
860
|
return []
|
|
710
861
|
except ResourceNotFoundError as e:
|
|
711
862
|
logger.warning(f"Restore points resource not found error - {e}")
|
|
@@ -718,20 +869,26 @@ def get_restore_points(credentials: Credentials, subscription_id: str, database:
|
|
|
718
869
|
|
|
719
870
|
|
|
720
871
|
@timeit
|
|
721
|
-
def get_transparent_data_encryptions(
|
|
872
|
+
def get_transparent_data_encryptions(
|
|
873
|
+
credentials: Credentials,
|
|
874
|
+
subscription_id: str,
|
|
875
|
+
database: Dict,
|
|
876
|
+
) -> List[Dict]:
|
|
722
877
|
"""
|
|
723
878
|
Returns the details of transparent data encryptions in a database.
|
|
724
879
|
"""
|
|
725
880
|
try:
|
|
726
881
|
client = get_client(credentials, subscription_id)
|
|
727
882
|
transparent_data_encryptions_list = client.transparent_data_encryptions.get(
|
|
728
|
-
database[
|
|
729
|
-
database[
|
|
730
|
-
database[
|
|
883
|
+
database["resource_group_name"],
|
|
884
|
+
database["server_name"],
|
|
885
|
+
database["name"],
|
|
731
886
|
TransparentDataEncryptionName.CURRENT,
|
|
732
887
|
).as_dict()
|
|
733
888
|
except ClientAuthenticationError as e:
|
|
734
|
-
logger.warning(
|
|
889
|
+
logger.warning(
|
|
890
|
+
f"Client Authentication Error while retrieving transparent data encryptions - {e}",
|
|
891
|
+
)
|
|
735
892
|
return []
|
|
736
893
|
except ResourceNotFoundError as e:
|
|
737
894
|
logger.warning(f"Transparent data encryptions resource not found error - {e}")
|
|
@@ -745,7 +902,9 @@ def get_transparent_data_encryptions(credentials: Credentials, subscription_id:
|
|
|
745
902
|
|
|
746
903
|
@timeit
|
|
747
904
|
def load_database_details(
|
|
748
|
-
|
|
905
|
+
neo4j_session: neo4j.Session,
|
|
906
|
+
details: List[Tuple[Any, Any, Any, Any, Any]],
|
|
907
|
+
update_tag: int,
|
|
749
908
|
) -> None:
|
|
750
909
|
"""
|
|
751
910
|
Create dictionaries for every resource in a database so we can import them in a single query
|
|
@@ -755,34 +914,46 @@ def load_database_details(
|
|
|
755
914
|
restore_points = []
|
|
756
915
|
encryptions_list = []
|
|
757
916
|
|
|
758
|
-
for
|
|
917
|
+
for (
|
|
918
|
+
databaseId,
|
|
919
|
+
replication_link,
|
|
920
|
+
db_threat_detection_policy,
|
|
921
|
+
restore_point,
|
|
922
|
+
transparent_data_encryption,
|
|
923
|
+
) in details:
|
|
759
924
|
if len(replication_link) > 0:
|
|
760
925
|
for link in replication_link:
|
|
761
|
-
link[
|
|
926
|
+
link["database_id"] = databaseId
|
|
762
927
|
replication_links.append(link)
|
|
763
928
|
|
|
764
929
|
if len(db_threat_detection_policy) > 0:
|
|
765
|
-
db_threat_detection_policy[
|
|
930
|
+
db_threat_detection_policy["database_id"] = databaseId
|
|
766
931
|
threat_detection_policies.append(db_threat_detection_policy)
|
|
767
932
|
|
|
768
933
|
if len(restore_point) > 0:
|
|
769
934
|
for point in restore_point:
|
|
770
|
-
point[
|
|
935
|
+
point["database_id"] = databaseId
|
|
771
936
|
restore_points.append(point)
|
|
772
937
|
|
|
773
938
|
if len(transparent_data_encryption) > 0:
|
|
774
|
-
transparent_data_encryption[
|
|
939
|
+
transparent_data_encryption["database_id"] = databaseId
|
|
775
940
|
encryptions_list.append(transparent_data_encryption)
|
|
776
941
|
|
|
777
942
|
_load_replication_links(neo4j_session, replication_links, update_tag)
|
|
778
|
-
_load_db_threat_detection_policies(
|
|
943
|
+
_load_db_threat_detection_policies(
|
|
944
|
+
neo4j_session,
|
|
945
|
+
threat_detection_policies,
|
|
946
|
+
update_tag,
|
|
947
|
+
)
|
|
779
948
|
_load_restore_points(neo4j_session, restore_points, update_tag)
|
|
780
949
|
_load_transparent_data_encryptions(neo4j_session, encryptions_list, update_tag)
|
|
781
950
|
|
|
782
951
|
|
|
783
952
|
@timeit
|
|
784
953
|
def _load_replication_links(
|
|
785
|
-
|
|
954
|
+
neo4j_session: neo4j.Session,
|
|
955
|
+
replication_links: List[Dict],
|
|
956
|
+
update_tag: int,
|
|
786
957
|
) -> None:
|
|
787
958
|
"""
|
|
788
959
|
Ingest replication links into neo4j.
|
|
@@ -820,7 +991,9 @@ def _load_replication_links(
|
|
|
820
991
|
|
|
821
992
|
@timeit
|
|
822
993
|
def _load_db_threat_detection_policies(
|
|
823
|
-
|
|
994
|
+
neo4j_session: neo4j.Session,
|
|
995
|
+
threat_detection_policies: List[Dict],
|
|
996
|
+
update_tag: int,
|
|
824
997
|
) -> None:
|
|
825
998
|
"""
|
|
826
999
|
Ingest threat detection policy into neo4j.
|
|
@@ -857,7 +1030,9 @@ def _load_db_threat_detection_policies(
|
|
|
857
1030
|
|
|
858
1031
|
@timeit
|
|
859
1032
|
def _load_restore_points(
|
|
860
|
-
|
|
1033
|
+
neo4j_session: neo4j.Session,
|
|
1034
|
+
restore_points: List[Dict],
|
|
1035
|
+
update_tag: int,
|
|
861
1036
|
) -> None:
|
|
862
1037
|
"""
|
|
863
1038
|
Ingest restore points into neo4j.
|
|
@@ -888,7 +1063,9 @@ def _load_restore_points(
|
|
|
888
1063
|
|
|
889
1064
|
@timeit
|
|
890
1065
|
def _load_transparent_data_encryptions(
|
|
891
|
-
|
|
1066
|
+
neo4j_session: neo4j.Session,
|
|
1067
|
+
encryptions_list: List[Dict],
|
|
1068
|
+
update_tag: int,
|
|
892
1069
|
) -> None:
|
|
893
1070
|
"""
|
|
894
1071
|
Ingest transparent data encryptions into neo4j.
|
|
@@ -917,18 +1094,32 @@ def _load_transparent_data_encryptions(
|
|
|
917
1094
|
|
|
918
1095
|
@timeit
|
|
919
1096
|
def cleanup_azure_sql_servers(
|
|
920
|
-
|
|
1097
|
+
neo4j_session: neo4j.Session,
|
|
1098
|
+
common_job_parameters: Dict,
|
|
921
1099
|
) -> None:
|
|
922
|
-
run_cleanup_job(
|
|
1100
|
+
run_cleanup_job(
|
|
1101
|
+
"azure_sql_server_cleanup.json",
|
|
1102
|
+
neo4j_session,
|
|
1103
|
+
common_job_parameters,
|
|
1104
|
+
)
|
|
923
1105
|
|
|
924
1106
|
|
|
925
1107
|
@timeit
|
|
926
1108
|
def sync(
|
|
927
|
-
|
|
928
|
-
|
|
1109
|
+
neo4j_session: neo4j.Session,
|
|
1110
|
+
credentials: Credentials,
|
|
1111
|
+
subscription_id: str,
|
|
1112
|
+
sync_tag: int,
|
|
1113
|
+
common_job_parameters: Dict,
|
|
929
1114
|
) -> None:
|
|
930
1115
|
logger.info("Syncing Azure SQL for subscription '%s'.", subscription_id)
|
|
931
1116
|
server_list = get_server_list(credentials, subscription_id)
|
|
932
1117
|
load_server_data(neo4j_session, subscription_id, server_list, sync_tag)
|
|
933
|
-
sync_server_details(
|
|
1118
|
+
sync_server_details(
|
|
1119
|
+
neo4j_session,
|
|
1120
|
+
credentials,
|
|
1121
|
+
subscription_id,
|
|
1122
|
+
server_list,
|
|
1123
|
+
sync_tag,
|
|
1124
|
+
)
|
|
934
1125
|
cleanup_azure_sql_servers(neo4j_session, common_job_parameters)
|