diff --git a/src/services/sqlServers/data.ts b/src/services/sqlServers/data.ts index 3d0404f7..59e57602 100644 --- a/src/services/sqlServers/data.ts +++ b/src/services/sqlServers/data.ts @@ -1,19 +1,22 @@ import { - SqlManagementClient, - Server, + ElasticPool, + EncryptionProtector, + FailoverGroup, FirewallRule, - ServerSecurityAlertPolicy, + Server, ServerAzureADAdministrator, - EncryptionProtector, ServerBlobAuditingPolicy, + ServerSecurityAlertPolicy, ServerVulnerabilityAssessment, + SqlManagementClient, + VirtualNetworkRule, } from '@azure/arm-sql' import { PagedAsyncIterableIterator } from '@azure/core-paging' import CloudGraph from '@cloudgraph/sdk' import azureLoggerText from '../../properties/logger' import { AzureServiceInput, TagMap } from '../../types' -import { getResourceGroupFromEntity } from '../../utils/idParserUtils' import { lowerCaseLocation } from '../../utils/format' +import { getResourceGroupFromEntity } from '../../utils/idParserUtils' import { tryCatchWrapper } from '../../utils/index' const { logger } = CloudGraph @@ -24,7 +27,10 @@ export interface RawAzureServer extends Omit { region: string resourceGroupId: string Tags: TagMap + elasticPools: ElasticPool[] + failoverGroups: FailoverGroup[] firewallRules: FirewallRule[] + virtualNetworkRules: VirtualNetworkRule[] serverSecurityAlertPolicies: ServerSecurityAlertPolicy[] adAdministrators: ServerAzureADAdministrator[] encryptionProtectors: EncryptionProtector[] @@ -32,6 +38,90 @@ export interface RawAzureServer extends Omit { vulnerabilityAssessments: ServerVulnerabilityAssessment[] } +const listElasticPools = async ( + client: SqlManagementClient, + resourceGroup: string, + serverName: string +): Promise => { + const elasticPools: ElasticPool[] = [] + const elasticPoolsIterable = client.elasticPools.listByServer( + resourceGroup, + serverName + ) + await tryCatchWrapper( + async () => { + for await (const elasticPool of elasticPoolsIterable) { + if (elasticPool) { + elasticPools.push(elasticPool) + } + } + }, + { + service: serviceName, + client, + scope: 'elasticPools', + operation: 'listByServer', + } + ) + return elasticPools +} + +const listFileoverGroups = async ( + client: SqlManagementClient, + resourceGroup: string, + serverName: string +): Promise => { + const failoverGroups: FailoverGroup[] = [] + const failoverGroupsIterable = client.failoverGroups.listByServer( + resourceGroup, + serverName + ) + await tryCatchWrapper( + async () => { + for await (const failoverGroup of failoverGroupsIterable) { + if (failoverGroup) { + failoverGroups.push(failoverGroup) + } + } + }, + { + service: serviceName, + client, + scope: 'failoverGroups', + operation: 'listByServer', + } + ) + return failoverGroups +} + +const listVirtualNetworkRules = async ( + client: SqlManagementClient, + resourceGroup: string, + serverName: string +): Promise => { + const virtualNetworkRules: VirtualNetworkRule[] = [] + const virtualNetworkRulesIterable = client.virtualNetworkRules.listByServer( + resourceGroup, + serverName + ) + await tryCatchWrapper( + async () => { + for await (const virtualNetworkRule of virtualNetworkRulesIterable) { + if (virtualNetworkRule) { + virtualNetworkRules.push(virtualNetworkRule) + } + } + }, + { + service: serviceName, + client, + scope: 'virtualNetworkRules', + operation: 'listByServer', + } + ) + return virtualNetworkRules +} + const listFirewallRules = async ( client: SqlManagementClient, resourceGroup: string, @@ -143,15 +233,16 @@ const listEncryptionProtectors = async ( } const listServerVulnerabilityAssessments = async ( - client: SqlManagementClient, - resourceGroup: string, - serverName: string, + client: SqlManagementClient, + resourceGroup: string, + serverName: string ): Promise => { const databaseVulnerabilityAssessments: ServerVulnerabilityAssessment[] = [] - const vulnerabilityAssessmentIterable = client.serverVulnerabilityAssessments.listByServer( - resourceGroup, - serverName, - ) + const vulnerabilityAssessmentIterable = + client.serverVulnerabilityAssessments.listByServer( + resourceGroup, + serverName + ) await tryCatchWrapper( async () => { for await (const vulnerabilityAssessment of vulnerabilityAssessmentIterable) { @@ -171,15 +262,13 @@ const listServerVulnerabilityAssessments = async ( } const listServerBlobAuditingPolicies = async ( - client: SqlManagementClient, - resourceGroup: string, - serverName: string, + client: SqlManagementClient, + resourceGroup: string, + serverName: string ): Promise => { const serverBlobAuditingPolicies: ServerBlobAuditingPolicy[] = [] - const serverBlobAuditingPolicyIterable = client.serverBlobAuditingPolicies.listByServer( - resourceGroup, - serverName, - ) + const serverBlobAuditingPolicyIterable = + client.serverBlobAuditingPolicies.listByServer(resourceGroup, serverName) await tryCatchWrapper( async () => { for await (const policy of serverBlobAuditingPolicyIterable) { @@ -226,48 +315,66 @@ export default async ({ logger.debug(lt.foundSqlServers(sqlServers.length)) const result: { [property: string]: RawAzureServer[] } = {} - await Promise.all(sqlServers.map(async ({ name, tags, location, ...rest }) => { - const region = lowerCaseLocation(location) - if (regions.includes(region)) { - if (!result[region]) { - result[region] = [] - } - const resourceGroupId = getResourceGroupFromEntity(rest) - result[region].push({ - name, - ...rest, - resourceGroupId, - region, - Tags: tags || {}, - firewallRules: await listFirewallRules(client, resourceGroupId, name), - serverSecurityAlertPolicies: await listServerSecurityAlertPolicies( - client, - resourceGroupId, - name - ), - adAdministrators: await listADAdministrators( - client, - resourceGroupId, - name - ), - encryptionProtectors: await listEncryptionProtectors( - client, + await Promise.all( + sqlServers.map(async ({ name, tags, location, ...rest }) => { + const region = lowerCaseLocation(location) + if (regions.includes(region)) { + if (!result[region]) { + result[region] = [] + } + const resourceGroupId = getResourceGroupFromEntity(rest) + result[region].push({ + name, + ...rest, resourceGroupId, - name - ), - serverBlobAuditingPolicies: await listServerBlobAuditingPolicies( - client, - resourceGroupId, - name - ), - vulnerabilityAssessments: await listServerVulnerabilityAssessments( - client, - resourceGroupId, - name - ), - }) - } - })) + region, + Tags: tags || {}, + elasticPools: await listElasticPools(client, resourceGroupId, name), + failoverGroups: await listFileoverGroups( + client, + resourceGroupId, + name + ), + firewallRules: await listFirewallRules( + client, + resourceGroupId, + name + ), + virtualNetworkRules: await listVirtualNetworkRules( + client, + resourceGroupId, + name + ), + serverSecurityAlertPolicies: await listServerSecurityAlertPolicies( + client, + resourceGroupId, + name + ), + adAdministrators: await listADAdministrators( + client, + resourceGroupId, + name + ), + encryptionProtectors: await listEncryptionProtectors( + client, + resourceGroupId, + name + ), + serverBlobAuditingPolicies: await listServerBlobAuditingPolicies( + client, + resourceGroupId, + name + ), + vulnerabilityAssessments: await listServerVulnerabilityAssessments( + client, + resourceGroupId, + name + ), + }) + } + }) + ) + return result } catch (e) { logger.error(e) diff --git a/src/services/sqlServers/format.ts b/src/services/sqlServers/format.ts index 63531a37..470cda34 100644 --- a/src/services/sqlServers/format.ts +++ b/src/services/sqlServers/format.ts @@ -3,10 +3,13 @@ import { AzureSqlServer, AzureSqlServerAdAdministrator, AzureSqlServerBlobAuditingPolicy, + AzureSqlServerElasticPool, AzureSqlServerEncryptionProtector, + AzureSqlServerFailoverGroup, AzureSqlServerFirewallRule, AzureSqlServerPrivateEndpointConnection, AzureSqlServerSecurityAlertPolicy, + AzureSqlServerVirtualNetworkRule, AzureSqlServerVulnerabilityAssessment, } from '../../types/generated' import { formatTagsFromMap } from '../../utils/format' @@ -45,7 +48,10 @@ export default ({ workspaceFeature, restrictOutboundNetworkAccess, resourceGroupId, + elasticPools = [], + failoverGroups = [], firewallRules = [], + virtualNetworkRules = [], serverSecurityAlertPolicies = [], adAdministrators = [], encryptionProtectors = [], @@ -118,6 +124,30 @@ export default ({ workspaceFeature, restrictOutboundNetworkAccess, resourceGroupId, + elasticPools: + elasticPools?.map( + ({ + id: elasticPoolId, + name: elasticPoolName, + type: elasticPoolType, + }): AzureSqlServerElasticPool => ({ + id: elasticPoolId, + name: elasticPoolName, + type: elasticPoolType, + }) + ) ?? [], + failoverGroups: + failoverGroups?.map( + ({ + id: failoverGroupId, + name: failoverGroupName, + type: failoverGroupType, + }): AzureSqlServerFailoverGroup => ({ + id: failoverGroupId, + name: failoverGroupName, + type: failoverGroupType, + }) + ) ?? [], firewallRules: firewallRules?.map( ({ @@ -134,6 +164,18 @@ export default ({ endIpAddress, }) ) ?? [], + virtualNetworkRules: + virtualNetworkRules?.map( + ({ + id: virtualNetworkRuleId, + name: virtualNetworkRuleName, + type: virtualNetworkRuleType, + }): AzureSqlServerVirtualNetworkRule => ({ + id: virtualNetworkRuleId, + name: virtualNetworkRuleName, + type: virtualNetworkRuleType, + }) + ) ?? [], serverSecurityAlertPolicies: serverSecurityAlertPolicies?.map( ({ diff --git a/src/services/sqlServers/schema.graphql b/src/services/sqlServers/schema.graphql index f41cf8de..b498fec8 100644 --- a/src/services/sqlServers/schema.graphql +++ b/src/services/sqlServers/schema.graphql @@ -168,7 +168,10 @@ type azureSqlServer implements azureResource administrators: azureSqlServerExternalAdministrator workspaceFeature: String @search(by: [hash, regexp]) restrictOutboundNetworkAccess: String @search(by: [hash, regexp]) + elasticPools: [azureSqlServerElasticPool] + failoverGroups: [azureSqlServerFailoverGroup] firewallRules: [azureSqlServerFirewallRule] + virtualNetworkRules: [azureSqlServerVirtualNetworkRule] serverSecurityAlertPolicies: [azureSqlServerSecurityAlertPolicy] adAdministrators: [azureSqlServerADAdministrator] encryptionProtectors: [azureSqlServerEncryptionProtector] @@ -223,3 +226,39 @@ type azureSqlServerBlobAuditingPolicy storageEndpoint: String @search(by: [hash, regexp]) storageAccountSubscriptionId: String @search(by: [hash, regexp]) } + +type azureSqlServerElasticPool + @generate( + query: { get: false, query: true, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) + @key(fields: "id") { + id: String! @id @search(by: [hash]) + name: String @search(by: [hash, regexp]) + type: String @search(by: [hash, regexp]) +} + +type azureSqlServerFailoverGroup + @generate( + query: { get: false, query: true, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) + @key(fields: "id") { + id: String! @id @search(by: [hash]) + name: String @search(by: [hash, regexp]) + type: String @search(by: [hash, regexp]) +} + +type azureSqlServerVirtualNetworkRule + @generate( + query: { get: false, query: true, aggregate: false } + mutation: { add: false, delete: false } + subscription: false + ) + @key(fields: "id") { + id: String! @id @search(by: [hash]) + name: String @search(by: [hash, regexp]) + type: String @search(by: [hash, regexp]) +} \ No newline at end of file diff --git a/src/types/generated.ts b/src/types/generated.ts index 84f4520f..1e077097 100644 --- a/src/types/generated.ts +++ b/src/types/generated.ts @@ -5230,7 +5230,9 @@ export type AzureSqlServer = AzureResource & { adAdministrators?: Maybe>>; administrators?: Maybe; databaseSql?: Maybe>>; + elasticPools?: Maybe>>; encryptionProtectors?: Maybe>>; + failoverGroups?: Maybe>>; federatedClientId?: Maybe; firewallRules?: Maybe>>; fullyQualifiedDomainName?: Maybe; @@ -5247,6 +5249,7 @@ export type AzureSqlServer = AzureResource & { state?: Maybe; subscriptionId?: Maybe; version?: Maybe; + virtualNetworkRules?: Maybe>>; vulnerabilityAssessments?: Maybe>>; workspaceFeature?: Maybe; }; @@ -5275,6 +5278,12 @@ export type AzureSqlServerBlobAuditingPolicy = { type?: Maybe; }; +export type AzureSqlServerElasticPool = { + id: Scalars['String']; + name?: Maybe; + type?: Maybe; +}; + export type AzureSqlServerEncryptionProtector = { autoRotationEnabled?: Maybe; id: Scalars['String']; @@ -5298,6 +5307,12 @@ export type AzureSqlServerExternalAdministrator = { tenantId?: Maybe; }; +export type AzureSqlServerFailoverGroup = { + id: Scalars['String']; + name?: Maybe; + type?: Maybe; +}; + export type AzureSqlServerFirewallRule = { endIpAddress?: Maybe; id: Scalars['String']; @@ -5355,6 +5370,12 @@ export type AzureSqlServerUserIdentity = { principalId?: Maybe; }; +export type AzureSqlServerVirtualNetworkRule = { + id: Scalars['String']; + name?: Maybe; + type?: Maybe; +}; + export type AzureSqlServerVulnerabilityAssessment = { id: Scalars['String']; name?: Maybe;