diff --git a/avm/res/sql/server/README.md b/avm/res/sql/server/README.md index 4f73df2fa8..874c590b74 100644 --- a/avm/res/sql/server/README.md +++ b/avm/res/sql/server/README.md @@ -1139,6 +1139,7 @@ module server 'br/public:avm/res/sql/server:' = { | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`encryptionProtectorObj`](#parameter-encryptionprotectorobj) | object | The encryption protection configuration. | | [`firewallRules`](#parameter-firewallrules) | array | The firewall rules to create in the server. | +| [`isIPv6Enabled`](#parameter-isipv6enabled) | string | Whether or not to enable IPv6 support for this server. | | [`keys`](#parameter-keys) | array | The keys to configure. | | [`location`](#parameter-location) | string | Location for all resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | @@ -1336,6 +1337,21 @@ The firewall rules to create in the server. - Type: array - Default: `[]` +### Parameter: `isIPv6Enabled` + +Whether or not to enable IPv6 support for this server. + +- Required: No +- Type: string +- Default: `'Disabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + ### Parameter: `keys` The keys to configure. @@ -1429,6 +1445,7 @@ Minimal TLS version allowed. '1.0' '1.1' '1.2' + '1.3' ] ``` @@ -1851,6 +1868,7 @@ Whether or not public network access is allowed for this resource. For security '' 'Disabled' 'Enabled' + 'SecuredByPerimeter' ] ``` diff --git a/avm/res/sql/server/database/main.bicep b/avm/res/sql/server/database/main.bicep index f26259ab84..f57f1b049e 100644 --- a/avm/res/sql/server/database/main.bicep +++ b/avm/res/sql/server/database/main.bicep @@ -211,12 +211,8 @@ module database_backupShortTermRetentionPolicy 'backup-short-term-retention-poli params: { serverName: serverName databaseName: database.name - diffBackupIntervalInHours: contains(backupShortTermRetentionPolicy, 'diffBackupIntervalInHours') - ? backupShortTermRetentionPolicy.diffBackupIntervalInHours - : 24 - retentionDays: contains(backupShortTermRetentionPolicy, 'retentionDays') - ? backupShortTermRetentionPolicy.retentionDays - : 7 + diffBackupIntervalInHours: backupShortTermRetentionPolicy.?diffBackupIntervalInHours ?? 24 + retentionDays: backupShortTermRetentionPolicy.?retentionDays ?? 7 } } @@ -225,16 +221,10 @@ module database_backupLongTermRetentionPolicy 'backup-long-term-retention-policy params: { serverName: serverName databaseName: database.name - weeklyRetention: contains(backupLongTermRetentionPolicy, 'weeklyRetention') - ? backupLongTermRetentionPolicy.weeklyRetention - : '' - monthlyRetention: contains(backupLongTermRetentionPolicy, 'monthlyRetention') - ? backupLongTermRetentionPolicy.monthlyRetention - : '' - yearlyRetention: contains(backupLongTermRetentionPolicy, 'yearlyRetention') - ? backupLongTermRetentionPolicy.yearlyRetention - : '' - weekOfYear: contains(backupLongTermRetentionPolicy, 'weekOfYear') ? backupLongTermRetentionPolicy.weekOfYear : 1 + weeklyRetention: backupLongTermRetentionPolicy.?weeklyRetention ?? '' + monthlyRetention: backupLongTermRetentionPolicy.?monthlyRetention ?? '' + yearlyRetention: backupLongTermRetentionPolicy.?yearlyRetention ?? '' + weekOfYear: backupLongTermRetentionPolicy.?weekOfYear ?? 1 } } diff --git a/avm/res/sql/server/database/main.json b/avm/res/sql/server/database/main.json index a28b55efe8..a52b9b9427 100644 --- a/avm/res/sql/server/database/main.json +++ b/avm/res/sql/server/database/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.29.47.4906", - "templateHash": "6019999815954957727" + "templateHash": "1805182723135951408" }, "name": "SQL Server Database", "description": "This module deploys an Azure SQL Server Database.", @@ -474,8 +474,12 @@ "databaseName": { "value": "[parameters('name')]" }, - "diffBackupIntervalInHours": "[if(contains(parameters('backupShortTermRetentionPolicy'), 'diffBackupIntervalInHours'), createObject('value', parameters('backupShortTermRetentionPolicy').diffBackupIntervalInHours), createObject('value', 24))]", - "retentionDays": "[if(contains(parameters('backupShortTermRetentionPolicy'), 'retentionDays'), createObject('value', parameters('backupShortTermRetentionPolicy').retentionDays), createObject('value', 7))]" + "diffBackupIntervalInHours": { + "value": "[coalesce(tryGet(parameters('backupShortTermRetentionPolicy'), 'diffBackupIntervalInHours'), 24)]" + }, + "retentionDays": { + "value": "[coalesce(tryGet(parameters('backupShortTermRetentionPolicy'), 'retentionDays'), 7)]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -574,10 +578,18 @@ "databaseName": { "value": "[parameters('name')]" }, - "weeklyRetention": "[if(contains(parameters('backupLongTermRetentionPolicy'), 'weeklyRetention'), createObject('value', parameters('backupLongTermRetentionPolicy').weeklyRetention), createObject('value', ''))]", - "monthlyRetention": "[if(contains(parameters('backupLongTermRetentionPolicy'), 'monthlyRetention'), createObject('value', parameters('backupLongTermRetentionPolicy').monthlyRetention), createObject('value', ''))]", - "yearlyRetention": "[if(contains(parameters('backupLongTermRetentionPolicy'), 'yearlyRetention'), createObject('value', parameters('backupLongTermRetentionPolicy').yearlyRetention), createObject('value', ''))]", - "weekOfYear": "[if(contains(parameters('backupLongTermRetentionPolicy'), 'weekOfYear'), createObject('value', parameters('backupLongTermRetentionPolicy').weekOfYear), createObject('value', 1))]" + "weeklyRetention": { + "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'weeklyRetention'), '')]" + }, + "monthlyRetention": { + "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'monthlyRetention'), '')]" + }, + "yearlyRetention": { + "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'yearlyRetention'), '')]" + }, + "weekOfYear": { + "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'weekOfYear'), 1)]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", diff --git a/avm/res/sql/server/main.bicep b/avm/res/sql/server/main.bicep index e628668146..7e20d5b142 100644 --- a/avm/res/sql/server/main.bicep +++ b/avm/res/sql/server/main.bicep @@ -58,10 +58,18 @@ param administrators object = {} '1.0' '1.1' '1.2' + '1.3' ]) @description('Optional. Minimal TLS version allowed.') param minimalTlsVersion string = '1.2' +@allowed([ + 'Disabled' + 'Enabled' +]) +@description('Optional. Whether or not to enable IPv6 support for this server.') +param isIPv6Enabled string = 'Disabled' + @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') param privateEndpoints privateEndpointType @@ -70,6 +78,7 @@ param privateEndpoints privateEndpointType '' 'Enabled' 'Disabled' + 'SecuredByPerimeter' ]) param publicNetworkAccess string = '' @@ -199,9 +208,10 @@ resource server 'Microsoft.Sql/servers@2023-08-01-preview' = { minimalTlsVersion: minimalTlsVersion primaryUserAssignedIdentityId: !empty(primaryUserAssignedIdentityId) ? primaryUserAssignedIdentityId : null publicNetworkAccess: !empty(publicNetworkAccess) - ? any(publicNetworkAccess) + ? publicNetworkAccess : (!empty(privateEndpoints) && empty(firewallRules) && empty(virtualNetworkRules) ? 'Disabled' : null) restrictOutboundNetworkAccess: !empty(restrictOutboundNetworkAccess) ? restrictOutboundNetworkAccess : null + isIPv6Enabled: isIPv6Enabled } } @@ -238,48 +248,34 @@ module server_databases 'database/main.bicep' = [ params: { name: database.name serverName: server.name - skuTier: contains(database, 'skuTier') ? database.skuTier : 'GeneralPurpose' - skuName: contains(database, 'skuName') ? database.skuName : 'GP_Gen5_2' + skuTier: database.?skuTier ?? 'GeneralPurpose' + skuName: database.?skuName ?? 'GP_Gen5_2' skuCapacity: database.?skuCapacity - skuFamily: contains(database, 'skuFamily') ? database.skuFamily : '' - skuSize: contains(database, 'skuSize') ? database.skuSize : '' - collation: contains(database, 'collation') ? database.collation : 'SQL_Latin1_General_CP1_CI_AS' - maxSizeBytes: contains(database, 'maxSizeBytes') ? database.maxSizeBytes : 34359738368 - autoPauseDelay: contains(database, 'autoPauseDelay') ? database.autoPauseDelay : 0 + skuFamily: database.?skuFamily ?? '' + skuSize: database.?skuSize ?? '' + collation: database.?collation ?? 'SQL_Latin1_General_CP1_CI_AS' + maxSizeBytes: database.?maxSizeBytes ?? 34359738368 + autoPauseDelay: database.?autoPauseDelay ?? 0 diagnosticSettings: database.?diagnosticSettings - isLedgerOn: contains(database, 'isLedgerOn') ? database.isLedgerOn : false + isLedgerOn: database.?isLedgerOn ?? false location: location - licenseType: contains(database, 'licenseType') ? database.licenseType : '' - maintenanceConfigurationId: contains(database, 'maintenanceConfigurationId') - ? database.maintenanceConfigurationId - : '' - minCapacity: contains(database, 'minCapacity') ? database.minCapacity : '' - highAvailabilityReplicaCount: contains(database, 'highAvailabilityReplicaCount') - ? database.highAvailabilityReplicaCount - : 0 - readScale: contains(database, 'readScale') ? database.readScale : 'Disabled' - requestedBackupStorageRedundancy: contains(database, 'requestedBackupStorageRedundancy') - ? database.requestedBackupStorageRedundancy - : '' - sampleName: contains(database, 'sampleName') ? database.sampleName : '' + licenseType: database.?licenseType ?? '' + maintenanceConfigurationId: database.?maintenanceConfigurationId ?? '' + minCapacity: database.?minCapacity ?? '' + highAvailabilityReplicaCount: database.?highAvailabilityReplicaCount ?? 0 + readScale: database.?readScale ?? 'Disabled' + requestedBackupStorageRedundancy: database.?requestedBackupStorageRedundancy ?? '' + sampleName: database.?sampleName ?? '' tags: database.?tags ?? tags - zoneRedundant: contains(database, 'zoneRedundant') ? database.zoneRedundant : true - elasticPoolId: contains(database, 'elasticPoolId') ? database.elasticPoolId : '' - backupShortTermRetentionPolicy: contains(database, 'backupShortTermRetentionPolicy') - ? database.backupShortTermRetentionPolicy - : {} - backupLongTermRetentionPolicy: contains(database, 'backupLongTermRetentionPolicy') - ? database.backupLongTermRetentionPolicy - : {} - createMode: contains(database, 'createMode') ? database.createMode : 'Default' - sourceDatabaseResourceId: contains(database, 'sourceDatabaseResourceId') ? database.sourceDatabaseResourceId : '' - sourceDatabaseDeletionDate: contains(database, 'sourceDatabaseDeletionDate') - ? database.sourceDatabaseDeletionDate - : '' - recoveryServicesRecoveryPointResourceId: contains(database, 'recoveryServicesRecoveryPointResourceId') - ? database.recoveryServicesRecoveryPointResourceId - : '' - restorePointInTime: contains(database, 'restorePointInTime') ? database.restorePointInTime : '' + zoneRedundant: database.?zoneRedundant ?? true + elasticPoolId: database.?elasticPoolId ?? '' + backupShortTermRetentionPolicy: database.?backupShortTermRetentionPolicy ?? {} + backupLongTermRetentionPolicy: database.?backupLongTermRetentionPolicy ?? {} + createMode: database.?createMode ?? 'Default' + sourceDatabaseResourceId: database.?sourceDatabaseResourceId ?? '' + sourceDatabaseDeletionDate: database.?sourceDatabaseDeletionDate ?? '' + recoveryServicesRecoveryPointResourceId: database.?recoveryServicesRecoveryPointResourceId ?? '' + restorePointInTime: database.?restorePointInTime ?? '' } dependsOn: [ server_elasticPools // Enables us to add databases to existing elastic pools @@ -293,19 +289,17 @@ module server_elasticPools 'elastic-pool/main.bicep' = [ params: { name: elasticPool.name serverName: server.name - databaseMaxCapacity: contains(elasticPool, 'databaseMaxCapacity') ? elasticPool.databaseMaxCapacity : 2 - databaseMinCapacity: contains(elasticPool, 'databaseMinCapacity') ? elasticPool.databaseMinCapacity : 0 + databaseMaxCapacity: elasticPool.?databaseMaxCapacity ?? 2 + databaseMinCapacity: elasticPool.?databaseMinCapacity ?? 0 highAvailabilityReplicaCount: elasticPool.?highAvailabilityReplicaCount - licenseType: contains(elasticPool, 'licenseType') ? elasticPool.licenseType : 'LicenseIncluded' - maintenanceConfigurationId: contains(elasticPool, 'maintenanceConfigurationId') - ? elasticPool.maintenanceConfigurationId - : '' - maxSizeBytes: contains(elasticPool, 'maxSizeBytes') ? elasticPool.maxSizeBytes : 34359738368 + licenseType: elasticPool.?licenseType ?? 'LicenseIncluded' + maintenanceConfigurationId: elasticPool.?maintenanceConfigurationId ?? '' + maxSizeBytes: elasticPool.?maxSizeBytes ?? 34359738368 minCapacity: elasticPool.?minCapacity - skuCapacity: contains(elasticPool, 'skuCapacity') ? elasticPool.skuCapacity : 2 - skuName: contains(elasticPool, 'skuName') ? elasticPool.skuName : 'GP_Gen5' - skuTier: contains(elasticPool, 'skuTier') ? elasticPool.skuTier : 'GeneralPurpose' - zoneRedundant: contains(elasticPool, 'zoneRedundant') ? elasticPool.zoneRedundant : true + skuCapacity: elasticPool.?skuCapacity ?? 2 + skuName: elasticPool.?skuName ?? 'GP_Gen5' + skuTier: elasticPool.?skuTier ?? 'GeneralPurpose' + zoneRedundant: elasticPool.?zoneRedundant ?? true location: location tags: elasticPool.?tags ?? tags } @@ -370,8 +364,8 @@ module server_firewallRules 'firewall-rule/main.bicep' = [ params: { name: firewallRule.name serverName: server.name - endIpAddress: contains(firewallRule, 'endIpAddress') ? firewallRule.endIpAddress : '0.0.0.0' - startIpAddress: contains(firewallRule, 'startIpAddress') ? firewallRule.startIpAddress : '0.0.0.0' + endIpAddress: firewallRule.?endIpAddress ?? '0.0.0.0' + startIpAddress: firewallRule.?startIpAddress ?? '0.0.0.0' } } ] @@ -382,9 +376,7 @@ module server_virtualNetworkRules 'virtual-network-rule/main.bicep' = [ params: { name: virtualNetworkRule.name serverName: server.name - ignoreMissingVnetServiceEndpoint: contains(virtualNetworkRule, 'ignoreMissingVnetServiceEndpoint') - ? virtualNetworkRule.ignoreMissingVnetServiceEndpoint - : false + ignoreMissingVnetServiceEndpoint: virtualNetworkRule.?ignoreMissingVnetServiceEndpoint ?? false virtualNetworkSubnetId: virtualNetworkRule.virtualNetworkSubnetId } } @@ -396,17 +388,13 @@ module server_securityAlertPolicies 'security-alert-policy/main.bicep' = [ params: { name: securityAlertPolicy.name serverName: server.name - disabledAlerts: contains(securityAlertPolicy, 'disabledAlerts') ? securityAlertPolicy.disabledAlerts : [] - emailAccountAdmins: contains(securityAlertPolicy, 'emailAccountAdmins') - ? securityAlertPolicy.emailAccountAdmins - : false - emailAddresses: contains(securityAlertPolicy, 'emailAddresses') ? securityAlertPolicy.emailAddresses : [] - retentionDays: contains(securityAlertPolicy, 'retentionDays') ? securityAlertPolicy.retentionDays : 0 - state: contains(securityAlertPolicy, 'state') ? securityAlertPolicy.state : 'Disabled' - storageAccountAccessKey: contains(securityAlertPolicy, 'storageAccountAccessKey') - ? securityAlertPolicy.storageAccountAccessKey - : '' - storageEndpoint: contains(securityAlertPolicy, 'storageEndpoint') ? securityAlertPolicy.storageEndpoint : '' + disabledAlerts: securityAlertPolicy.?disabledAlerts ?? [] + emailAccountAdmins: securityAlertPolicy.?emailAccountAdmins ?? false + emailAddresses: securityAlertPolicy.?emailAddresses ?? [] + retentionDays: securityAlertPolicy.?retentionDays ?? 0 + state: securityAlertPolicy.?state ?? 'Disabled' + storageAccountAccessKey: securityAlertPolicy.?storageAccountAccessKey ?? '' + storageEndpoint: securityAlertPolicy.?storageEndpoint ?? '' } } ] @@ -416,25 +404,12 @@ module server_vulnerabilityAssessment 'vulnerability-assessment/main.bicep' = if params: { serverName: server.name name: vulnerabilityAssessmentsObj.name - recurringScansEmails: contains(vulnerabilityAssessmentsObj, 'recurringScansEmails') - ? vulnerabilityAssessmentsObj.recurringScansEmails - : [] - recurringScansEmailSubscriptionAdmins: contains( - vulnerabilityAssessmentsObj, - 'recurringScansEmailSubscriptionAdmins' - ) - ? vulnerabilityAssessmentsObj.recurringScansEmailSubscriptionAdmins - : false - recurringScansIsEnabled: contains(vulnerabilityAssessmentsObj, 'recurringScansIsEnabled') - ? vulnerabilityAssessmentsObj.recurringScansIsEnabled - : false + recurringScansEmails: vulnerabilityAssessmentsObj.?recurringScansEmails ?? [] + recurringScansEmailSubscriptionAdmins: vulnerabilityAssessmentsObj.?recurringScansEmailSubscriptionAdmins ?? false + recurringScansIsEnabled: vulnerabilityAssessmentsObj.?recurringScansIsEnabled ?? false storageAccountResourceId: vulnerabilityAssessmentsObj.storageAccountResourceId - useStorageAccountAccessKey: contains(vulnerabilityAssessmentsObj, 'useStorageAccountAccessKey') - ? vulnerabilityAssessmentsObj.useStorageAccountAccessKey - : false - createStorageRoleAssignment: contains(vulnerabilityAssessmentsObj, 'createStorageRoleAssignment') - ? vulnerabilityAssessmentsObj.createStorageRoleAssignment - : true + useStorageAccountAccessKey: vulnerabilityAssessmentsObj.?useStorageAccountAccessKey ?? false + createStorageRoleAssignment: vulnerabilityAssessmentsObj.?createStorageRoleAssignment ?? true } dependsOn: [ server_securityAlertPolicies @@ -447,8 +422,8 @@ module server_keys 'key/main.bicep' = [ params: { name: key.?name serverName: server.name - serverKeyType: contains(key, 'serverKeyType') ? key.serverKeyType : 'ServiceManaged' - uri: contains(key, 'uri') ? key.uri : '' + serverKeyType: key.?serverKeyType ?? 'ServiceManaged' + uri: key.?uri ?? '' } } ] @@ -458,12 +433,8 @@ module server_encryptionProtector 'encryption-protector/main.bicep' = if (!empty params: { sqlServerName: server.name serverKeyName: encryptionProtectorObj.serverKeyName - serverKeyType: contains(encryptionProtectorObj, 'serverKeyType') - ? encryptionProtectorObj.serverKeyType - : 'ServiceManaged' - autoRotationEnabled: contains(encryptionProtectorObj, 'autoRotationEnabled') - ? encryptionProtectorObj.autoRotationEnabled - : true + serverKeyType: encryptionProtectorObj.?serverKeyType ?? 'ServiceManaged' + autoRotationEnabled: encryptionProtectorObj.?autoRotationEnabled ?? true } dependsOn: [ server_keys diff --git a/avm/res/sql/server/main.json b/avm/res/sql/server/main.json index b13a78c08f..f3dcbf9d07 100644 --- a/avm/res/sql/server/main.json +++ b/avm/res/sql/server/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.29.47.4906", - "templateHash": "13031224188572751832" + "templateHash": "12193891383187993365" }, "name": "Azure SQL Servers", "description": "This module deploys an Azure SQL Server.", @@ -558,12 +558,24 @@ "allowedValues": [ "1.0", "1.1", - "1.2" + "1.2", + "1.3" ], "metadata": { "description": "Optional. Minimal TLS version allowed." } }, + "isIPv6Enabled": { + "type": "string", + "defaultValue": "Disabled", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "metadata": { + "description": "Optional. Whether or not to enable IPv6 support for this server." + } + }, "privateEndpoints": { "$ref": "#/definitions/privateEndpointType", "metadata": { @@ -576,7 +588,8 @@ "allowedValues": [ "", "Enabled", - "Disabled" + "Disabled", + "SecuredByPerimeter" ], "metadata": { "description": "Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set and neither firewall rules nor virtual network rules are set." @@ -677,7 +690,8 @@ "minimalTlsVersion": "[parameters('minimalTlsVersion')]", "primaryUserAssignedIdentityId": "[if(not(empty(parameters('primaryUserAssignedIdentityId'))), parameters('primaryUserAssignedIdentityId'), null())]", "publicNetworkAccess": "[if(not(empty(parameters('publicNetworkAccess'))), parameters('publicNetworkAccess'), if(and(and(not(empty(parameters('privateEndpoints'))), empty(parameters('firewallRules'))), empty(parameters('virtualNetworkRules'))), 'Disabled', null()))]", - "restrictOutboundNetworkAccess": "[if(not(empty(parameters('restrictOutboundNetworkAccess'))), parameters('restrictOutboundNetworkAccess'), null())]" + "restrictOutboundNetworkAccess": "[if(not(empty(parameters('restrictOutboundNetworkAccess'))), parameters('restrictOutboundNetworkAccess'), null())]", + "isIPv6Enabled": "[parameters('isIPv6Enabled')]" } }, "server_lock": { @@ -736,42 +750,90 @@ "serverName": { "value": "[parameters('name')]" }, - "skuTier": "[if(contains(parameters('databases')[copyIndex()], 'skuTier'), createObject('value', parameters('databases')[copyIndex()].skuTier), createObject('value', 'GeneralPurpose'))]", - "skuName": "[if(contains(parameters('databases')[copyIndex()], 'skuName'), createObject('value', parameters('databases')[copyIndex()].skuName), createObject('value', 'GP_Gen5_2'))]", + "skuTier": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'skuTier'), 'GeneralPurpose')]" + }, + "skuName": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'skuName'), 'GP_Gen5_2')]" + }, "skuCapacity": { "value": "[tryGet(parameters('databases')[copyIndex()], 'skuCapacity')]" }, - "skuFamily": "[if(contains(parameters('databases')[copyIndex()], 'skuFamily'), createObject('value', parameters('databases')[copyIndex()].skuFamily), createObject('value', ''))]", - "skuSize": "[if(contains(parameters('databases')[copyIndex()], 'skuSize'), createObject('value', parameters('databases')[copyIndex()].skuSize), createObject('value', ''))]", - "collation": "[if(contains(parameters('databases')[copyIndex()], 'collation'), createObject('value', parameters('databases')[copyIndex()].collation), createObject('value', 'SQL_Latin1_General_CP1_CI_AS'))]", - "maxSizeBytes": "[if(contains(parameters('databases')[copyIndex()], 'maxSizeBytes'), createObject('value', parameters('databases')[copyIndex()].maxSizeBytes), createObject('value', json('34359738368')))]", - "autoPauseDelay": "[if(contains(parameters('databases')[copyIndex()], 'autoPauseDelay'), createObject('value', parameters('databases')[copyIndex()].autoPauseDelay), createObject('value', 0))]", + "skuFamily": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'skuFamily'), '')]" + }, + "skuSize": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'skuSize'), '')]" + }, + "collation": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'collation'), 'SQL_Latin1_General_CP1_CI_AS')]" + }, + "maxSizeBytes": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'maxSizeBytes'), json('34359738368'))]" + }, + "autoPauseDelay": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'autoPauseDelay'), 0)]" + }, "diagnosticSettings": { "value": "[tryGet(parameters('databases')[copyIndex()], 'diagnosticSettings')]" }, - "isLedgerOn": "[if(contains(parameters('databases')[copyIndex()], 'isLedgerOn'), createObject('value', parameters('databases')[copyIndex()].isLedgerOn), createObject('value', false()))]", + "isLedgerOn": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'isLedgerOn'), false())]" + }, "location": { "value": "[parameters('location')]" }, - "licenseType": "[if(contains(parameters('databases')[copyIndex()], 'licenseType'), createObject('value', parameters('databases')[copyIndex()].licenseType), createObject('value', ''))]", - "maintenanceConfigurationId": "[if(contains(parameters('databases')[copyIndex()], 'maintenanceConfigurationId'), createObject('value', parameters('databases')[copyIndex()].maintenanceConfigurationId), createObject('value', ''))]", - "minCapacity": "[if(contains(parameters('databases')[copyIndex()], 'minCapacity'), createObject('value', parameters('databases')[copyIndex()].minCapacity), createObject('value', ''))]", - "highAvailabilityReplicaCount": "[if(contains(parameters('databases')[copyIndex()], 'highAvailabilityReplicaCount'), createObject('value', parameters('databases')[copyIndex()].highAvailabilityReplicaCount), createObject('value', 0))]", - "readScale": "[if(contains(parameters('databases')[copyIndex()], 'readScale'), createObject('value', parameters('databases')[copyIndex()].readScale), createObject('value', 'Disabled'))]", - "requestedBackupStorageRedundancy": "[if(contains(parameters('databases')[copyIndex()], 'requestedBackupStorageRedundancy'), createObject('value', parameters('databases')[copyIndex()].requestedBackupStorageRedundancy), createObject('value', ''))]", - "sampleName": "[if(contains(parameters('databases')[copyIndex()], 'sampleName'), createObject('value', parameters('databases')[copyIndex()].sampleName), createObject('value', ''))]", + "licenseType": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'licenseType'), '')]" + }, + "maintenanceConfigurationId": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'maintenanceConfigurationId'), '')]" + }, + "minCapacity": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'minCapacity'), '')]" + }, + "highAvailabilityReplicaCount": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'highAvailabilityReplicaCount'), 0)]" + }, + "readScale": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'readScale'), 'Disabled')]" + }, + "requestedBackupStorageRedundancy": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'requestedBackupStorageRedundancy'), '')]" + }, + "sampleName": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'sampleName'), '')]" + }, "tags": { "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'tags'), parameters('tags'))]" }, - "zoneRedundant": "[if(contains(parameters('databases')[copyIndex()], 'zoneRedundant'), createObject('value', parameters('databases')[copyIndex()].zoneRedundant), createObject('value', true()))]", - "elasticPoolId": "[if(contains(parameters('databases')[copyIndex()], 'elasticPoolId'), createObject('value', parameters('databases')[copyIndex()].elasticPoolId), createObject('value', ''))]", - "backupShortTermRetentionPolicy": "[if(contains(parameters('databases')[copyIndex()], 'backupShortTermRetentionPolicy'), createObject('value', parameters('databases')[copyIndex()].backupShortTermRetentionPolicy), createObject('value', createObject()))]", - "backupLongTermRetentionPolicy": "[if(contains(parameters('databases')[copyIndex()], 'backupLongTermRetentionPolicy'), createObject('value', parameters('databases')[copyIndex()].backupLongTermRetentionPolicy), createObject('value', createObject()))]", - "createMode": "[if(contains(parameters('databases')[copyIndex()], 'createMode'), createObject('value', parameters('databases')[copyIndex()].createMode), createObject('value', 'Default'))]", - "sourceDatabaseResourceId": "[if(contains(parameters('databases')[copyIndex()], 'sourceDatabaseResourceId'), createObject('value', parameters('databases')[copyIndex()].sourceDatabaseResourceId), createObject('value', ''))]", - "sourceDatabaseDeletionDate": "[if(contains(parameters('databases')[copyIndex()], 'sourceDatabaseDeletionDate'), createObject('value', parameters('databases')[copyIndex()].sourceDatabaseDeletionDate), createObject('value', ''))]", - "recoveryServicesRecoveryPointResourceId": "[if(contains(parameters('databases')[copyIndex()], 'recoveryServicesRecoveryPointResourceId'), createObject('value', parameters('databases')[copyIndex()].recoveryServicesRecoveryPointResourceId), createObject('value', ''))]", - "restorePointInTime": "[if(contains(parameters('databases')[copyIndex()], 'restorePointInTime'), createObject('value', parameters('databases')[copyIndex()].restorePointInTime), createObject('value', ''))]" + "zoneRedundant": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'zoneRedundant'), true())]" + }, + "elasticPoolId": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'elasticPoolId'), '')]" + }, + "backupShortTermRetentionPolicy": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'backupShortTermRetentionPolicy'), createObject())]" + }, + "backupLongTermRetentionPolicy": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'backupLongTermRetentionPolicy'), createObject())]" + }, + "createMode": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'createMode'), 'Default')]" + }, + "sourceDatabaseResourceId": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'sourceDatabaseResourceId'), '')]" + }, + "sourceDatabaseDeletionDate": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'sourceDatabaseDeletionDate'), '')]" + }, + "recoveryServicesRecoveryPointResourceId": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'recoveryServicesRecoveryPointResourceId'), '')]" + }, + "restorePointInTime": { + "value": "[coalesce(tryGet(parameters('databases')[copyIndex()], 'restorePointInTime'), '')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -781,7 +843,7 @@ "_generator": { "name": "bicep", "version": "0.29.47.4906", - "templateHash": "6019999815954957727" + "templateHash": "1805182723135951408" }, "name": "SQL Server Database", "description": "This module deploys an Azure SQL Server Database.", @@ -1249,8 +1311,12 @@ "databaseName": { "value": "[parameters('name')]" }, - "diffBackupIntervalInHours": "[if(contains(parameters('backupShortTermRetentionPolicy'), 'diffBackupIntervalInHours'), createObject('value', parameters('backupShortTermRetentionPolicy').diffBackupIntervalInHours), createObject('value', 24))]", - "retentionDays": "[if(contains(parameters('backupShortTermRetentionPolicy'), 'retentionDays'), createObject('value', parameters('backupShortTermRetentionPolicy').retentionDays), createObject('value', 7))]" + "diffBackupIntervalInHours": { + "value": "[coalesce(tryGet(parameters('backupShortTermRetentionPolicy'), 'diffBackupIntervalInHours'), 24)]" + }, + "retentionDays": { + "value": "[coalesce(tryGet(parameters('backupShortTermRetentionPolicy'), 'retentionDays'), 7)]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -1349,10 +1415,18 @@ "databaseName": { "value": "[parameters('name')]" }, - "weeklyRetention": "[if(contains(parameters('backupLongTermRetentionPolicy'), 'weeklyRetention'), createObject('value', parameters('backupLongTermRetentionPolicy').weeklyRetention), createObject('value', ''))]", - "monthlyRetention": "[if(contains(parameters('backupLongTermRetentionPolicy'), 'monthlyRetention'), createObject('value', parameters('backupLongTermRetentionPolicy').monthlyRetention), createObject('value', ''))]", - "yearlyRetention": "[if(contains(parameters('backupLongTermRetentionPolicy'), 'yearlyRetention'), createObject('value', parameters('backupLongTermRetentionPolicy').yearlyRetention), createObject('value', ''))]", - "weekOfYear": "[if(contains(parameters('backupLongTermRetentionPolicy'), 'weekOfYear'), createObject('value', parameters('backupLongTermRetentionPolicy').weekOfYear), createObject('value', 1))]" + "weeklyRetention": { + "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'weeklyRetention'), '')]" + }, + "monthlyRetention": { + "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'monthlyRetention'), '')]" + }, + "yearlyRetention": { + "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'yearlyRetention'), '')]" + }, + "weekOfYear": { + "value": "[coalesce(tryGet(parameters('backupLongTermRetentionPolicy'), 'weekOfYear'), 1)]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -1509,21 +1583,39 @@ "serverName": { "value": "[parameters('name')]" }, - "databaseMaxCapacity": "[if(contains(parameters('elasticPools')[copyIndex()], 'databaseMaxCapacity'), createObject('value', parameters('elasticPools')[copyIndex()].databaseMaxCapacity), createObject('value', 2))]", - "databaseMinCapacity": "[if(contains(parameters('elasticPools')[copyIndex()], 'databaseMinCapacity'), createObject('value', parameters('elasticPools')[copyIndex()].databaseMinCapacity), createObject('value', 0))]", + "databaseMaxCapacity": { + "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'databaseMaxCapacity'), 2)]" + }, + "databaseMinCapacity": { + "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'databaseMinCapacity'), 0)]" + }, "highAvailabilityReplicaCount": { "value": "[tryGet(parameters('elasticPools')[copyIndex()], 'highAvailabilityReplicaCount')]" }, - "licenseType": "[if(contains(parameters('elasticPools')[copyIndex()], 'licenseType'), createObject('value', parameters('elasticPools')[copyIndex()].licenseType), createObject('value', 'LicenseIncluded'))]", - "maintenanceConfigurationId": "[if(contains(parameters('elasticPools')[copyIndex()], 'maintenanceConfigurationId'), createObject('value', parameters('elasticPools')[copyIndex()].maintenanceConfigurationId), createObject('value', ''))]", - "maxSizeBytes": "[if(contains(parameters('elasticPools')[copyIndex()], 'maxSizeBytes'), createObject('value', parameters('elasticPools')[copyIndex()].maxSizeBytes), createObject('value', json('34359738368')))]", + "licenseType": { + "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'licenseType'), 'LicenseIncluded')]" + }, + "maintenanceConfigurationId": { + "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'maintenanceConfigurationId'), '')]" + }, + "maxSizeBytes": { + "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'maxSizeBytes'), json('34359738368'))]" + }, "minCapacity": { "value": "[tryGet(parameters('elasticPools')[copyIndex()], 'minCapacity')]" }, - "skuCapacity": "[if(contains(parameters('elasticPools')[copyIndex()], 'skuCapacity'), createObject('value', parameters('elasticPools')[copyIndex()].skuCapacity), createObject('value', 2))]", - "skuName": "[if(contains(parameters('elasticPools')[copyIndex()], 'skuName'), createObject('value', parameters('elasticPools')[copyIndex()].skuName), createObject('value', 'GP_Gen5'))]", - "skuTier": "[if(contains(parameters('elasticPools')[copyIndex()], 'skuTier'), createObject('value', parameters('elasticPools')[copyIndex()].skuTier), createObject('value', 'GeneralPurpose'))]", - "zoneRedundant": "[if(contains(parameters('elasticPools')[copyIndex()], 'zoneRedundant'), createObject('value', parameters('elasticPools')[copyIndex()].zoneRedundant), createObject('value', true()))]", + "skuCapacity": { + "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'skuCapacity'), 2)]" + }, + "skuName": { + "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'skuName'), 'GP_Gen5')]" + }, + "skuTier": { + "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'skuTier'), 'GeneralPurpose')]" + }, + "zoneRedundant": { + "value": "[coalesce(tryGet(parameters('elasticPools')[copyIndex()], 'zoneRedundant'), true())]" + }, "location": { "value": "[parameters('location')]" }, @@ -2511,8 +2603,12 @@ "serverName": { "value": "[parameters('name')]" }, - "endIpAddress": "[if(contains(parameters('firewallRules')[copyIndex()], 'endIpAddress'), createObject('value', parameters('firewallRules')[copyIndex()].endIpAddress), createObject('value', '0.0.0.0'))]", - "startIpAddress": "[if(contains(parameters('firewallRules')[copyIndex()], 'startIpAddress'), createObject('value', parameters('firewallRules')[copyIndex()].startIpAddress), createObject('value', '0.0.0.0'))]" + "endIpAddress": { + "value": "[coalesce(tryGet(parameters('firewallRules')[copyIndex()], 'endIpAddress'), '0.0.0.0')]" + }, + "startIpAddress": { + "value": "[coalesce(tryGet(parameters('firewallRules')[copyIndex()], 'startIpAddress'), '0.0.0.0')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -2615,7 +2711,9 @@ "serverName": { "value": "[parameters('name')]" }, - "ignoreMissingVnetServiceEndpoint": "[if(contains(parameters('virtualNetworkRules')[copyIndex()], 'ignoreMissingVnetServiceEndpoint'), createObject('value', parameters('virtualNetworkRules')[copyIndex()].ignoreMissingVnetServiceEndpoint), createObject('value', false()))]", + "ignoreMissingVnetServiceEndpoint": { + "value": "[coalesce(tryGet(parameters('virtualNetworkRules')[copyIndex()], 'ignoreMissingVnetServiceEndpoint'), false())]" + }, "virtualNetworkSubnetId": { "value": "[parameters('virtualNetworkRules')[copyIndex()].virtualNetworkSubnetId]" } @@ -2720,13 +2818,27 @@ "serverName": { "value": "[parameters('name')]" }, - "disabledAlerts": "[if(contains(parameters('securityAlertPolicies')[copyIndex()], 'disabledAlerts'), createObject('value', parameters('securityAlertPolicies')[copyIndex()].disabledAlerts), createObject('value', createArray()))]", - "emailAccountAdmins": "[if(contains(parameters('securityAlertPolicies')[copyIndex()], 'emailAccountAdmins'), createObject('value', parameters('securityAlertPolicies')[copyIndex()].emailAccountAdmins), createObject('value', false()))]", - "emailAddresses": "[if(contains(parameters('securityAlertPolicies')[copyIndex()], 'emailAddresses'), createObject('value', parameters('securityAlertPolicies')[copyIndex()].emailAddresses), createObject('value', createArray()))]", - "retentionDays": "[if(contains(parameters('securityAlertPolicies')[copyIndex()], 'retentionDays'), createObject('value', parameters('securityAlertPolicies')[copyIndex()].retentionDays), createObject('value', 0))]", - "state": "[if(contains(parameters('securityAlertPolicies')[copyIndex()], 'state'), createObject('value', parameters('securityAlertPolicies')[copyIndex()].state), createObject('value', 'Disabled'))]", - "storageAccountAccessKey": "[if(contains(parameters('securityAlertPolicies')[copyIndex()], 'storageAccountAccessKey'), createObject('value', parameters('securityAlertPolicies')[copyIndex()].storageAccountAccessKey), createObject('value', ''))]", - "storageEndpoint": "[if(contains(parameters('securityAlertPolicies')[copyIndex()], 'storageEndpoint'), createObject('value', parameters('securityAlertPolicies')[copyIndex()].storageEndpoint), createObject('value', ''))]" + "disabledAlerts": { + "value": "[coalesce(tryGet(parameters('securityAlertPolicies')[copyIndex()], 'disabledAlerts'), createArray())]" + }, + "emailAccountAdmins": { + "value": "[coalesce(tryGet(parameters('securityAlertPolicies')[copyIndex()], 'emailAccountAdmins'), false())]" + }, + "emailAddresses": { + "value": "[coalesce(tryGet(parameters('securityAlertPolicies')[copyIndex()], 'emailAddresses'), createArray())]" + }, + "retentionDays": { + "value": "[coalesce(tryGet(parameters('securityAlertPolicies')[copyIndex()], 'retentionDays'), 0)]" + }, + "state": { + "value": "[coalesce(tryGet(parameters('securityAlertPolicies')[copyIndex()], 'state'), 'Disabled')]" + }, + "storageAccountAccessKey": { + "value": "[coalesce(tryGet(parameters('securityAlertPolicies')[copyIndex()], 'storageAccountAccessKey'), '')]" + }, + "storageEndpoint": { + "value": "[coalesce(tryGet(parameters('securityAlertPolicies')[copyIndex()], 'storageEndpoint'), '')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -2870,14 +2982,24 @@ "name": { "value": "[parameters('vulnerabilityAssessmentsObj').name]" }, - "recurringScansEmails": "[if(contains(parameters('vulnerabilityAssessmentsObj'), 'recurringScansEmails'), createObject('value', parameters('vulnerabilityAssessmentsObj').recurringScansEmails), createObject('value', createArray()))]", - "recurringScansEmailSubscriptionAdmins": "[if(contains(parameters('vulnerabilityAssessmentsObj'), 'recurringScansEmailSubscriptionAdmins'), createObject('value', parameters('vulnerabilityAssessmentsObj').recurringScansEmailSubscriptionAdmins), createObject('value', false()))]", - "recurringScansIsEnabled": "[if(contains(parameters('vulnerabilityAssessmentsObj'), 'recurringScansIsEnabled'), createObject('value', parameters('vulnerabilityAssessmentsObj').recurringScansIsEnabled), createObject('value', false()))]", + "recurringScansEmails": { + "value": "[coalesce(tryGet(parameters('vulnerabilityAssessmentsObj'), 'recurringScansEmails'), createArray())]" + }, + "recurringScansEmailSubscriptionAdmins": { + "value": "[coalesce(tryGet(parameters('vulnerabilityAssessmentsObj'), 'recurringScansEmailSubscriptionAdmins'), false())]" + }, + "recurringScansIsEnabled": { + "value": "[coalesce(tryGet(parameters('vulnerabilityAssessmentsObj'), 'recurringScansIsEnabled'), false())]" + }, "storageAccountResourceId": { "value": "[parameters('vulnerabilityAssessmentsObj').storageAccountResourceId]" }, - "useStorageAccountAccessKey": "[if(contains(parameters('vulnerabilityAssessmentsObj'), 'useStorageAccountAccessKey'), createObject('value', parameters('vulnerabilityAssessmentsObj').useStorageAccountAccessKey), createObject('value', false()))]", - "createStorageRoleAssignment": "[if(contains(parameters('vulnerabilityAssessmentsObj'), 'createStorageRoleAssignment'), createObject('value', parameters('vulnerabilityAssessmentsObj').createStorageRoleAssignment), createObject('value', true()))]" + "useStorageAccountAccessKey": { + "value": "[coalesce(tryGet(parameters('vulnerabilityAssessmentsObj'), 'useStorageAccountAccessKey'), false())]" + }, + "createStorageRoleAssignment": { + "value": "[coalesce(tryGet(parameters('vulnerabilityAssessmentsObj'), 'createStorageRoleAssignment'), true())]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -3067,8 +3189,12 @@ "serverName": { "value": "[parameters('name')]" }, - "serverKeyType": "[if(contains(parameters('keys')[copyIndex()], 'serverKeyType'), createObject('value', parameters('keys')[copyIndex()].serverKeyType), createObject('value', 'ServiceManaged'))]", - "uri": "[if(contains(parameters('keys')[copyIndex()], 'uri'), createObject('value', parameters('keys')[copyIndex()].uri), createObject('value', ''))]" + "serverKeyType": { + "value": "[coalesce(tryGet(parameters('keys')[copyIndex()], 'serverKeyType'), 'ServiceManaged')]" + }, + "uri": { + "value": "[coalesce(tryGet(parameters('keys')[copyIndex()], 'uri'), '')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -3187,8 +3313,12 @@ "serverKeyName": { "value": "[parameters('encryptionProtectorObj').serverKeyName]" }, - "serverKeyType": "[if(contains(parameters('encryptionProtectorObj'), 'serverKeyType'), createObject('value', parameters('encryptionProtectorObj').serverKeyType), createObject('value', 'ServiceManaged'))]", - "autoRotationEnabled": "[if(contains(parameters('encryptionProtectorObj'), 'autoRotationEnabled'), createObject('value', parameters('encryptionProtectorObj').autoRotationEnabled), createObject('value', true()))]" + "serverKeyType": { + "value": "[coalesce(tryGet(parameters('encryptionProtectorObj'), 'serverKeyType'), 'ServiceManaged')]" + }, + "autoRotationEnabled": { + "value": "[coalesce(tryGet(parameters('encryptionProtectorObj'), 'autoRotationEnabled'), true())]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",