From 426a9ba40a528e8dcc7610c4977f200def394aa7 Mon Sep 17 00:00:00 2001 From: Peter Budai Date: Fri, 29 Nov 2024 12:31:28 +0100 Subject: [PATCH] feat: Add UDT for all `avm/res/sql/server` submodules (#3807) ## Description This PR adds the remaining UDTs for al SQL submodules ## Pipeline Reference | Pipeline | | -------- | | [![avm.res.sql.server](https://github.com/peterbud/bicep-registry-modules/actions/workflows/avm.res.sql.server.yml/badge.svg)](https://github.com/peterbud/bicep-registry-modules/actions/workflows/avm.res.sql.server.yml) | Pls note that WAF fails due to missing maintenance window in my subscription. ## Type of Change - [ ] Update to CI Environment or utilities (Non-module affecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards-compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [x] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/sql/server/README.md | 469 +++++++++++++-- avm/res/sql/server/audit-settings/main.json | 8 +- .../main.json | 4 +- .../main.json | 4 +- avm/res/sql/server/database/main.json | 12 +- avm/res/sql/server/elastic-pool/main.json | 4 +- .../sql/server/encryption-protector/README.md | 6 +- .../server/encryption-protector/main.bicep | 4 +- .../sql/server/encryption-protector/main.json | 8 +- avm/res/sql/server/firewall-rule/main.json | 4 +- avm/res/sql/server/key/README.md | 8 +- avm/res/sql/server/key/main.bicep | 4 +- avm/res/sql/server/key/main.json | 8 +- avm/res/sql/server/main.bicep | 162 ++++- avm/res/sql/server/main.json | 554 ++++++++++++++---- .../server/security-alert-policy/README.md | 21 +- .../server/security-alert-policy/main.bicep | 24 +- .../server/security-alert-policy/main.json | 48 +- .../tests/e2e/elasticPool/main.test.bicep | 2 + .../tests/e2e/kvSecrets/main.test.bicep | 1 + .../sql/server/tests/e2e/max/main.test.bicep | 14 +- .../tests/e2e/secondary/main.test.bicep | 1 + .../server/tests/e2e/vulnAssm/main.test.bicep | 14 +- .../tests/e2e/waf-aligned/main.test.bicep | 14 +- avm/res/sql/server/version.json | 2 +- .../sql/server/virtual-network-rule/main.json | 4 +- .../server/vulnerability-assessment/README.md | 45 +- .../vulnerability-assessment/main.bicep | 32 +- .../server/vulnerability-assessment/main.json | 100 ++-- 29 files changed, 1237 insertions(+), 344 deletions(-) diff --git a/avm/res/sql/server/README.md b/avm/res/sql/server/README.md index 5540a01906..e7ef975f8a 100644 --- a/avm/res/sql/server/README.md +++ b/avm/res/sql/server/README.md @@ -334,6 +334,7 @@ module server 'br/public:avm/res/sql/server:' = { elasticPools: [ { name: 'ssep-ep-001' + zoneRedundant: false } { name: 'ssep-ep-002' @@ -346,6 +347,7 @@ module server 'br/public:avm/res/sql/server:' = { name: 'GP_Gen5' tier: 'GeneralPurpose' } + zoneRedundant: false } ] location: '' @@ -379,7 +381,8 @@ module server 'br/public:avm/res/sql/server:' = { "elasticPools": { "value": [ { - "name": "ssep-ep-001" + "name": "ssep-ep-001", + "zoneRedundant": false }, { "name": "ssep-ep-002", @@ -391,7 +394,8 @@ module server 'br/public:avm/res/sql/server:' = { "capacity": 4, "name": "GP_Gen5", "tier": "GeneralPurpose" - } + }, + "zoneRedundant": false } ] }, @@ -420,6 +424,7 @@ param administratorLoginPassword = '' param elasticPools = [ { name: 'ssep-ep-001' + zoneRedundant: false } { name: 'ssep-ep-002' @@ -432,6 +437,7 @@ param elasticPools = [ name: 'GP_Gen5' tier: 'GeneralPurpose' } + zoneRedundant: false } ] param location = '' @@ -461,6 +467,7 @@ module server 'br/public:avm/res/sql/server:' = { databases: [ { name: 'myDatabase' + zoneRedundant: false } ] location: '' @@ -499,7 +506,8 @@ module server 'br/public:avm/res/sql/server:' = { "databases": { "value": [ { - "name": "myDatabase" + "name": "myDatabase", + "zoneRedundant": false } ] }, @@ -535,6 +543,7 @@ param administratorLoginPassword = '' param databases = [ { name: 'myDatabase' + zoneRedundant: false } ] param location = '' @@ -702,13 +711,15 @@ module server 'br/public:avm/res/sql/server:' = { } ] vulnerabilityAssessmentsObj: { - emailSubscriptionAdmins: true name: 'default' - recurringScansEmails: [ - 'test1@contoso.com' - 'test2@contoso.com' - ] - recurringScansIsEnabled: true + recurringScans: { + emails: [ + 'test1@contoso.com' + 'test2@contoso.com' + ] + emailSubscriptionAdmins: true + isEnabled: true + } storageAccountResourceId: '' } } @@ -903,13 +914,15 @@ module server 'br/public:avm/res/sql/server:' = { }, "vulnerabilityAssessmentsObj": { "value": { - "emailSubscriptionAdmins": true, "name": "default", - "recurringScansEmails": [ - "test1@contoso.com", - "test2@contoso.com" - ], - "recurringScansIsEnabled": true, + "recurringScans": { + "emails": [ + "test1@contoso.com", + "test2@contoso.com" + ], + "emailSubscriptionAdmins": true, + "isEnabled": true + }, "storageAccountResourceId": "" } } @@ -1068,13 +1081,15 @@ param virtualNetworkRules = [ } ] param vulnerabilityAssessmentsObj = { - emailSubscriptionAdmins: true name: 'default' - recurringScansEmails: [ - 'test1@contoso.com' - 'test2@contoso.com' - ] - recurringScansIsEnabled: true + recurringScans: { + emails: [ + 'test1@contoso.com' + 'test2@contoso.com' + ] + emailSubscriptionAdmins: true + isEnabled: true + } storageAccountResourceId: '' } ``` @@ -1110,6 +1125,7 @@ module server 'br/public:avm/res/sql/server:' = { tier: 'Basic' } sourceDatabaseResourceId: '' + zoneRedundant: false } ] location: '' @@ -1155,7 +1171,8 @@ module server 'br/public:avm/res/sql/server:' = { "name": "Basic", "tier": "Basic" }, - "sourceDatabaseResourceId": "" + "sourceDatabaseResourceId": "", + "zoneRedundant": false } ] }, @@ -1198,6 +1215,7 @@ param databases = [ tier: 'Basic' } sourceDatabaseResourceId: '' + zoneRedundant: false } ] param location = '' @@ -1251,13 +1269,15 @@ module server 'br/public:avm/res/sql/server:' = { } vulnerabilityAssessmentsObj: { createStorageRoleAssignment: true - emailSubscriptionAdmins: true name: 'default' - recurringScansEmails: [ - 'test1@contoso.com' - 'test2@contoso.com' - ] - recurringScansIsEnabled: true + recurringScans: { + emails: [ + 'test1@contoso.com' + 'test2@contoso.com' + ] + emailSubscriptionAdmins: true + isEnabled: true + } storageAccountResourceId: '' useStorageAccountAccessKey: false } @@ -1321,13 +1341,15 @@ module server 'br/public:avm/res/sql/server:' = { "vulnerabilityAssessmentsObj": { "value": { "createStorageRoleAssignment": true, - "emailSubscriptionAdmins": true, "name": "default", - "recurringScansEmails": [ - "test1@contoso.com", - "test2@contoso.com" - ], - "recurringScansIsEnabled": true, + "recurringScans": { + "emails": [ + "test1@contoso.com", + "test2@contoso.com" + ], + "emailSubscriptionAdmins": true, + "isEnabled": true + }, "storageAccountResourceId": "", "useStorageAccountAccessKey": false } @@ -1373,13 +1395,15 @@ param tags = { } param vulnerabilityAssessmentsObj = { createStorageRoleAssignment: true - emailSubscriptionAdmins: true name: 'default' - recurringScansEmails: [ - 'test1@contoso.com' - 'test2@contoso.com' - ] - recurringScansIsEnabled: true + recurringScans: { + emails: [ + 'test1@contoso.com' + 'test2@contoso.com' + ] + emailSubscriptionAdmins: true + isEnabled: true + } storageAccountResourceId: '' useStorageAccountAccessKey: false } @@ -1508,13 +1532,15 @@ module server 'br/public:avm/res/sql/server:' = { } ] vulnerabilityAssessmentsObj: { - emailSubscriptionAdmins: true name: 'default' - recurringScansEmails: [ - 'test1@contoso.com' - 'test2@contoso.com' - ] - recurringScansIsEnabled: true + recurringScans: { + emails: [ + 'test1@contoso.com' + 'test2@contoso.com' + ] + emailSubscriptionAdmins: true + isEnabled: true + } storageAccountResourceId: '' } } @@ -1667,13 +1693,15 @@ module server 'br/public:avm/res/sql/server:' = { }, "vulnerabilityAssessmentsObj": { "value": { - "emailSubscriptionAdmins": true, "name": "default", - "recurringScansEmails": [ - "test1@contoso.com", - "test2@contoso.com" - ], - "recurringScansIsEnabled": true, + "recurringScans": { + "emails": [ + "test1@contoso.com", + "test2@contoso.com" + ], + "emailSubscriptionAdmins": true, + "isEnabled": true + }, "storageAccountResourceId": "" } } @@ -1798,13 +1826,15 @@ param virtualNetworkRules = [ } ] param vulnerabilityAssessmentsObj = { - emailSubscriptionAdmins: true name: 'default' - recurringScansEmails: [ - 'test1@contoso.com' - 'test2@contoso.com' - ] - recurringScansIsEnabled: true + recurringScans: { + emails: [ + 'test1@contoso.com' + 'test2@contoso.com' + ] + emailSubscriptionAdmins: true + isEnabled: true + } storageAccountResourceId: '' } ``` @@ -2996,7 +3026,47 @@ The encryption protection configuration. - Required: No - Type: object -- Default: `{}` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`serverKeyName`](#parameter-encryptionprotectorobjserverkeyname) | string | The name of the server key. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`autoRotationEnabled`](#parameter-encryptionprotectorobjautorotationenabled) | bool | Key auto rotation opt-in flag. | +| [`serverKeyType`](#parameter-encryptionprotectorobjserverkeytype) | string | The encryption protector type. | + +### Parameter: `encryptionProtectorObj.serverKeyName` + +The name of the server key. + +- Required: Yes +- Type: string + +### Parameter: `encryptionProtectorObj.autoRotationEnabled` + +Key auto rotation opt-in flag. + +- Required: No +- Type: bool + +### Parameter: `encryptionProtectorObj.serverKeyType` + +The encryption protector type. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AzureKeyVault' + 'ServiceManaged' + ] + ``` ### Parameter: `federatedClientId` @@ -3013,6 +3083,40 @@ The firewall rules to create in the server. - Type: array - Default: `[]` +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-firewallrulesname) | string | The name of the firewall rule. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`endIpAddress`](#parameter-firewallrulesendipaddress) | string | The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress. Use value '0.0.0.0' for all Azure-internal IP addresses. | +| [`startIpAddress`](#parameter-firewallrulesstartipaddress) | string | The start IP address of the firewall rule. Must be IPv4 format. Use value '0.0.0.0' for all Azure-internal IP addresses. | + +### Parameter: `firewallRules.name` + +The name of the firewall rule. + +- Required: Yes +- Type: string + +### Parameter: `firewallRules.endIpAddress` + +The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress. Use value '0.0.0.0' for all Azure-internal IP addresses. + +- Required: No +- Type: string + +### Parameter: `firewallRules.startIpAddress` + +The start IP address of the firewall rule. Must be IPv4 format. Use value '0.0.0.0' for all Azure-internal IP addresses. + +- Required: No +- Type: string + ### Parameter: `isIPv6Enabled` Whether or not to enable IPv6 support for this server. @@ -3043,6 +3147,42 @@ The keys to configure. - Type: array - Default: `[]` +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-keysname) | string | The name of the key. Must follow the [__] pattern. | +| [`serverKeyType`](#parameter-keysserverkeytype) | string | The server key type. | +| [`uri`](#parameter-keysuri) | string | The URI of the server key. If the ServerKeyType is AzureKeyVault, then the URI is required. The AKV URI is required to be in this format: 'https://YourVaultName.azure.net/keys/YourKeyName/YourKeyVersion'. | + +### Parameter: `keys.name` + +The name of the key. Must follow the [__] pattern. + +- Required: No +- Type: string + +### Parameter: `keys.serverKeyType` + +The server key type. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AzureKeyVault' + 'ServiceManaged' + ] + ``` + +### Parameter: `keys.uri` + +The URI of the server key. If the ServerKeyType is AzureKeyVault, then the URI is required. The AKV URI is required to be in this format: 'https://YourVaultName.azure.net/keys/YourKeyName/YourKeyVersion'. + +- Required: No +- Type: string + ### Parameter: `location` Location for all resources. @@ -3735,6 +3875,98 @@ The security alert policies to create in the server. - Type: array - Default: `[]` +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-securityalertpoliciesname) | string | The name of the Security Alert Policy. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`disabledAlerts`](#parameter-securityalertpoliciesdisabledalerts) | array | Alerts to disable. | +| [`emailAccountAdmins`](#parameter-securityalertpoliciesemailaccountadmins) | bool | Specifies that the alert is sent to the account administrators. | +| [`emailAddresses`](#parameter-securityalertpoliciesemailaddresses) | array | Specifies an array of email addresses to which the alert is sent. | +| [`retentionDays`](#parameter-securityalertpoliciesretentiondays) | int | Specifies the number of days to keep in the Threat Detection audit logs. | +| [`state`](#parameter-securityalertpoliciesstate) | string | Specifies the state of the policy, whether it is enabled or disabled or a policy has not been applied yet on the specific database. | +| [`storageAccountAccessKey`](#parameter-securityalertpoliciesstorageaccountaccesskey) | string | Specifies the identifier key of the Threat Detection audit storage account. | +| [`storageEndpoint`](#parameter-securityalertpoliciesstorageendpoint) | string | Specifies the blob storage endpoint. This blob storage will hold all Threat Detection audit logs. | + +### Parameter: `securityAlertPolicies.name` + +The name of the Security Alert Policy. + +- Required: Yes +- Type: string + +### Parameter: `securityAlertPolicies.disabledAlerts` + +Alerts to disable. + +- Required: No +- Type: array +- Allowed: + ```Bicep + [ + 'Access_Anomaly' + 'Brute_Force' + 'Data_Exfiltration' + 'Sql_Injection' + 'Sql_Injection_Vulnerability' + 'Unsafe_Action' + ] + ``` + +### Parameter: `securityAlertPolicies.emailAccountAdmins` + +Specifies that the alert is sent to the account administrators. + +- Required: No +- Type: bool + +### Parameter: `securityAlertPolicies.emailAddresses` + +Specifies an array of email addresses to which the alert is sent. + +- Required: No +- Type: array + +### Parameter: `securityAlertPolicies.retentionDays` + +Specifies the number of days to keep in the Threat Detection audit logs. + +- Required: No +- Type: int + +### Parameter: `securityAlertPolicies.state` + +Specifies the state of the policy, whether it is enabled or disabled or a policy has not been applied yet on the specific database. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `securityAlertPolicies.storageAccountAccessKey` + +Specifies the identifier key of the Threat Detection audit storage account. + +- Required: No +- Type: string + +### Parameter: `securityAlertPolicies.storageEndpoint` + +Specifies the blob storage endpoint. This blob storage will hold all Threat Detection audit logs. + +- Required: No +- Type: string + ### Parameter: `tags` Tags of the resource. @@ -3750,13 +3982,130 @@ The virtual network rules to create in the server. - Type: array - Default: `[]` +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-virtualnetworkrulesname) | string | The name of the Server Virtual Network Rule. | +| [`virtualNetworkSubnetId`](#parameter-virtualnetworkrulesvirtualnetworksubnetid) | string | The resource ID of the virtual network subnet. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`ignoreMissingVnetServiceEndpoint`](#parameter-virtualnetworkrulesignoremissingvnetserviceendpoint) | bool | Allow creating a firewall rule before the virtual network has vnet service endpoint enabled. | + +### Parameter: `virtualNetworkRules.name` + +The name of the Server Virtual Network Rule. + +- Required: Yes +- Type: string + +### Parameter: `virtualNetworkRules.virtualNetworkSubnetId` + +The resource ID of the virtual network subnet. + +- Required: Yes +- Type: string + +### Parameter: `virtualNetworkRules.ignoreMissingVnetServiceEndpoint` + +Allow creating a firewall rule before the virtual network has vnet service endpoint enabled. + +- Required: No +- Type: bool + ### Parameter: `vulnerabilityAssessmentsObj` The vulnerability assessment configuration. - Required: No - Type: object -- Default: `{}` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-vulnerabilityassessmentsobjname) | string | The name of the vulnerability assessment. | +| [`storageAccountResourceId`](#parameter-vulnerabilityassessmentsobjstorageaccountresourceid) | string | The resource ID of the storage account to store the scan reports. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`createStorageRoleAssignment`](#parameter-vulnerabilityassessmentsobjcreatestorageroleassignment) | bool | Specifies whether to create a role assignment for the storage account. | +| [`recurringScans`](#parameter-vulnerabilityassessmentsobjrecurringscans) | object | The recurring scans settings. | +| [`useStorageAccountAccessKey`](#parameter-vulnerabilityassessmentsobjusestorageaccountaccesskey) | bool | Specifies whether to use the storage account access key to access the storage account. | + +### Parameter: `vulnerabilityAssessmentsObj.name` + +The name of the vulnerability assessment. + +- Required: Yes +- Type: string + +### Parameter: `vulnerabilityAssessmentsObj.storageAccountResourceId` + +The resource ID of the storage account to store the scan reports. + +- Required: Yes +- Type: string + +### Parameter: `vulnerabilityAssessmentsObj.createStorageRoleAssignment` + +Specifies whether to create a role assignment for the storage account. + +- Required: No +- Type: bool + +### Parameter: `vulnerabilityAssessmentsObj.recurringScans` + +The recurring scans settings. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`emails`](#parameter-vulnerabilityassessmentsobjrecurringscansemails) | array | Specifies an array of e-mail addresses to which the scan notification is sent. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`emailSubscriptionAdmins`](#parameter-vulnerabilityassessmentsobjrecurringscansemailsubscriptionadmins) | bool | Specifies that the schedule scan notification will be sent to the subscription administrators. | +| [`isEnabled`](#parameter-vulnerabilityassessmentsobjrecurringscansisenabled) | bool | Recurring scans state. | + +### Parameter: `vulnerabilityAssessmentsObj.recurringScans.emails` + +Specifies an array of e-mail addresses to which the scan notification is sent. + +- Required: Yes +- Type: array + +### Parameter: `vulnerabilityAssessmentsObj.recurringScans.emailSubscriptionAdmins` + +Specifies that the schedule scan notification will be sent to the subscription administrators. + +- Required: No +- Type: bool + +### Parameter: `vulnerabilityAssessmentsObj.recurringScans.isEnabled` + +Recurring scans state. + +- Required: No +- Type: bool + +### Parameter: `vulnerabilityAssessmentsObj.useStorageAccountAccessKey` + +Specifies whether to use the storage account access key to access the storage account. + +- Required: No +- Type: bool ## Outputs diff --git a/avm/res/sql/server/audit-settings/main.json b/avm/res/sql/server/audit-settings/main.json index 4c12fe1854..bc4622ef3b 100644 --- a/avm/res/sql/server/audit-settings/main.json +++ b/avm/res/sql/server/audit-settings/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "6303070680265885029" + "version": "0.31.92.45157", + "templateHash": "4626140114742164628" }, "name": "Azure SQL Server Audit Settings", "description": "This module deploys an Azure SQL Server Audit Settings.", @@ -152,8 +152,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "13956215614091387428" + "version": "0.31.92.45157", + "templateHash": "2903956714854050681" } }, "parameters": { diff --git a/avm/res/sql/server/database/backup-long-term-retention-policy/main.json b/avm/res/sql/server/database/backup-long-term-retention-policy/main.json index aa4ac7652a..9ca0defd7f 100644 --- a/avm/res/sql/server/database/backup-long-term-retention-policy/main.json +++ b/avm/res/sql/server/database/backup-long-term-retention-policy/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "841731129374883266" + "version": "0.31.92.45157", + "templateHash": "3060709558343951533" }, "name": "SQL Server Database Long Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Long-Term Backup Retention Policy.", diff --git a/avm/res/sql/server/database/backup-short-term-retention-policy/main.json b/avm/res/sql/server/database/backup-short-term-retention-policy/main.json index 9b5484f2d3..9ee0400fe2 100644 --- a/avm/res/sql/server/database/backup-short-term-retention-policy/main.json +++ b/avm/res/sql/server/database/backup-short-term-retention-policy/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "14890409200962565555" + "version": "0.31.92.45157", + "templateHash": "1465086214783345027" }, "name": "Azure SQL Server Database Short Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Short-Term Backup Retention Policy.", diff --git a/avm/res/sql/server/database/main.json b/avm/res/sql/server/database/main.json index 1e9d3badae..cb0d743aea 100644 --- a/avm/res/sql/server/database/main.json +++ b/avm/res/sql/server/database/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "18018827030977470456" + "version": "0.31.92.45157", + "templateHash": "10088627667414343400" }, "name": "SQL Server Database", "description": "This module deploys an Azure SQL Server Database.", @@ -721,8 +721,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "14890409200962565555" + "version": "0.31.92.45157", + "templateHash": "1465086214783345027" }, "name": "Azure SQL Server Database Short Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Short-Term Backup Retention Policy.", @@ -839,8 +839,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "841731129374883266" + "version": "0.31.92.45157", + "templateHash": "3060709558343951533" }, "name": "SQL Server Database Long Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Long-Term Backup Retention Policy.", diff --git a/avm/res/sql/server/elastic-pool/main.json b/avm/res/sql/server/elastic-pool/main.json index d74f427cbe..a18c568bcd 100644 --- a/avm/res/sql/server/elastic-pool/main.json +++ b/avm/res/sql/server/elastic-pool/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "10024079638382167120" + "version": "0.31.92.45157", + "templateHash": "9050866823207809352" }, "name": "SQL Server Elastic Pool", "description": "This module deploys an Azure SQL Server Elastic Pool.", diff --git a/avm/res/sql/server/encryption-protector/README.md b/avm/res/sql/server/encryption-protector/README.md index 25e4e2a34d..d2daaf2f96 100644 --- a/avm/res/sql/server/encryption-protector/README.md +++ b/avm/res/sql/server/encryption-protector/README.md @@ -32,7 +32,7 @@ This module deploys an Azure SQL Server Encryption Protector. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`autoRotationEnabled`](#parameter-autorotationenabled) | bool | Key auto rotation opt-in. | +| [`autoRotationEnabled`](#parameter-autorotationenabled) | bool | Key auto rotation opt-in flag. | | [`serverKeyType`](#parameter-serverkeytype) | string | The encryption protector type. | ### Parameter: `serverKeyName` @@ -51,11 +51,11 @@ The name of the sql server. Required if the template is used in a standalone dep ### Parameter: `autoRotationEnabled` -Key auto rotation opt-in. +Key auto rotation opt-in flag. - Required: No - Type: bool -- Default: `False` +- Default: `True` ### Parameter: `serverKeyType` diff --git a/avm/res/sql/server/encryption-protector/main.bicep b/avm/res/sql/server/encryption-protector/main.bicep index a156241c85..be6ed61417 100644 --- a/avm/res/sql/server/encryption-protector/main.bicep +++ b/avm/res/sql/server/encryption-protector/main.bicep @@ -8,8 +8,8 @@ param sqlServerName string @description('Required. The name of the server key.') param serverKeyName string -@description('Optional. Key auto rotation opt-in.') -param autoRotationEnabled bool = false +@description('Optional. Key auto rotation opt-in flag.') +param autoRotationEnabled bool = true @description('Optional. The encryption protector type.') @allowed([ diff --git a/avm/res/sql/server/encryption-protector/main.json b/avm/res/sql/server/encryption-protector/main.json index 2191d5c1ae..b6e43da350 100644 --- a/avm/res/sql/server/encryption-protector/main.json +++ b/avm/res/sql/server/encryption-protector/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "11473914706327458055" + "version": "0.31.92.45157", + "templateHash": "3436938593239210559" }, "name": "Azure SQL Server Encryption Protector", "description": "This module deploys an Azure SQL Server Encryption Protector.", @@ -26,9 +26,9 @@ }, "autoRotationEnabled": { "type": "bool", - "defaultValue": false, + "defaultValue": true, "metadata": { - "description": "Optional. Key auto rotation opt-in." + "description": "Optional. Key auto rotation opt-in flag." } }, "serverKeyType": { diff --git a/avm/res/sql/server/firewall-rule/main.json b/avm/res/sql/server/firewall-rule/main.json index fb23b82744..4fd36122c5 100644 --- a/avm/res/sql/server/firewall-rule/main.json +++ b/avm/res/sql/server/firewall-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "6449556555046717103" + "version": "0.31.92.45157", + "templateHash": "16725482503837347177" }, "name": "Azure SQL Server Firewall Rule", "description": "This module deploys an Azure SQL Server Firewall Rule.", diff --git a/avm/res/sql/server/key/README.md b/avm/res/sql/server/key/README.md index c18102a482..99f0e22b1d 100644 --- a/avm/res/sql/server/key/README.md +++ b/avm/res/sql/server/key/README.md @@ -27,8 +27,8 @@ This module deploys an Azure SQL Server Key. | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | The name of the key. Must follow the [__] pattern. | -| [`serverKeyType`](#parameter-serverkeytype) | string | The encryption protector type like "ServiceManaged", "AzureKeyVault". | -| [`uri`](#parameter-uri) | string | The URI of the key. If the ServerKeyType is AzureKeyVault, then either the URI or the keyVaultName/keyName combination is required. | +| [`serverKeyType`](#parameter-serverkeytype) | string | The server key type. | +| [`uri`](#parameter-uri) | string | The URI of the server key. If the ServerKeyType is AzureKeyVault, then the URI is required. The AKV URI is required to be in this format: 'https://YourVaultName.azure.net/keys/YourKeyName/YourKeyVersion'. | ### Parameter: `serverName` @@ -46,7 +46,7 @@ The name of the key. Must follow the [__] pat ### Parameter: `serverKeyType` -The encryption protector type like "ServiceManaged", "AzureKeyVault". +The server key type. - Required: No - Type: string @@ -61,7 +61,7 @@ The encryption protector type like "ServiceManaged", "AzureKeyVault". ### Parameter: `uri` -The URI of the key. If the ServerKeyType is AzureKeyVault, then either the URI or the keyVaultName/keyName combination is required. +The URI of the server key. If the ServerKeyType is AzureKeyVault, then the URI is required. The AKV URI is required to be in this format: 'https://YourVaultName.azure.net/keys/YourKeyName/YourKeyVersion'. - Required: No - Type: string diff --git a/avm/res/sql/server/key/main.bicep b/avm/res/sql/server/key/main.bicep index e52ebf8e49..9944b68424 100644 --- a/avm/res/sql/server/key/main.bicep +++ b/avm/res/sql/server/key/main.bicep @@ -8,14 +8,14 @@ param name string? @description('Conditional. The name of the parent SQL server. Required if the template is used in a standalone deployment.') param serverName string -@description('Optional. The encryption protector type like "ServiceManaged", "AzureKeyVault".') +@description('Optional. The server key type.') @allowed([ 'AzureKeyVault' 'ServiceManaged' ]) param serverKeyType string = 'ServiceManaged' -@description('Optional. The URI of the key. If the ServerKeyType is AzureKeyVault, then either the URI or the keyVaultName/keyName combination is required.') +@description('Optional. The URI of the server key. If the ServerKeyType is AzureKeyVault, then the URI is required. The AKV URI is required to be in this format: \'https://YourVaultName.azure.net/keys/YourKeyName/YourKeyVersion\'.') param uri string = '' var splittedKeyUri = split(uri, '/') diff --git a/avm/res/sql/server/key/main.json b/avm/res/sql/server/key/main.json index 78220cdf1f..0d108b281b 100644 --- a/avm/res/sql/server/key/main.json +++ b/avm/res/sql/server/key/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "17839617504395216689" + "version": "0.31.92.45157", + "templateHash": "16457177770650062823" }, "name": "Azure SQL Server Keys", "description": "This module deploys an Azure SQL Server Key.", @@ -34,14 +34,14 @@ "ServiceManaged" ], "metadata": { - "description": "Optional. The encryption protector type like \"ServiceManaged\", \"AzureKeyVault\"." + "description": "Optional. The server key type." } }, "uri": { "type": "string", "defaultValue": "", "metadata": { - "description": "Optional. The URI of the key. If the ServerKeyType is AzureKeyVault, then either the URI or the keyVaultName/keyName combination is required." + "description": "Optional. The URI of the server key. If the ServerKeyType is AzureKeyVault, then the URI is required. The AKV URI is required to be in this format: 'https://YourVaultName.azure.net/keys/YourKeyName/YourKeyVersion'." } } }, diff --git a/avm/res/sql/server/main.bicep b/avm/res/sql/server/main.bicep index 8115aa75d6..a7fa9551ca 100644 --- a/avm/res/sql/server/main.bicep +++ b/avm/res/sql/server/main.bicep @@ -43,16 +43,16 @@ param databases databasePropertyType[] = [] param elasticPools elasticPoolPropertyType[] = [] @description('Optional. The firewall rules to create in the server.') -param firewallRules array = [] +param firewallRules firewallRuleType[] = [] @description('Optional. The virtual network rules to create in the server.') -param virtualNetworkRules array = [] +param virtualNetworkRules virtualNetworkRuleType[] = [] @description('Optional. The security alert policies to create in the server.') -param securityAlertPolicies array = [] +param securityAlertPolicies securityAlerPolicyType[] = [] @description('Optional. The keys to configure.') -param keys array = [] +param keys keyType[] = [] @description('Conditional. The Azure Active Directory (AAD) administrator authentication. Required if no `administratorLogin` & `administratorLoginPassword` is provided.') param administrators serverExternalAdministratorType? @@ -118,10 +118,10 @@ var identity = !empty(managedIdentities) : null @description('Optional. The encryption protection configuration.') -param encryptionProtectorObj object = {} +param encryptionProtectorObj encryptionProtectorType? @description('Optional. The vulnerability assessment configuration.') -param vulnerabilityAssessmentsObj object = {} +param vulnerabilityAssessmentsObj vulnerabilityAssessmentType? @description('Optional. The audit settings configuration.') param auditSettings auditSettingsType = {} //Use the defaults from the child module @@ -394,8 +394,8 @@ module server_firewallRules 'firewall-rule/main.bicep' = [ params: { name: firewallRule.name serverName: server.name - endIpAddress: firewallRule.?endIpAddress ?? '0.0.0.0' - startIpAddress: firewallRule.?startIpAddress ?? '0.0.0.0' + endIpAddress: firewallRule.?endIpAddress + startIpAddress: firewallRule.?startIpAddress } } ] @@ -404,9 +404,9 @@ module server_virtualNetworkRules 'virtual-network-rule/main.bicep' = [ for (virtualNetworkRule, index) in virtualNetworkRules: { name: '${uniqueString(deployment().name, location)}-Sql-VirtualNetworkRules-${index}' params: { - name: virtualNetworkRule.name serverName: server.name - ignoreMissingVnetServiceEndpoint: virtualNetworkRule.?ignoreMissingVnetServiceEndpoint ?? false + name: virtualNetworkRule.name + ignoreMissingVnetServiceEndpoint: virtualNetworkRule.?ignoreMissingVnetServiceEndpoint virtualNetworkSubnetId: virtualNetworkRule.virtualNetworkSubnetId } } @@ -418,28 +418,26 @@ module server_securityAlertPolicies 'security-alert-policy/main.bicep' = [ params: { name: securityAlertPolicy.name serverName: server.name - disabledAlerts: securityAlertPolicy.?disabledAlerts ?? [] - emailAccountAdmins: securityAlertPolicy.?emailAccountAdmins ?? false - emailAddresses: securityAlertPolicy.?emailAddresses ?? [] - retentionDays: securityAlertPolicy.?retentionDays ?? 0 - state: securityAlertPolicy.?state ?? 'Disabled' - storageAccountAccessKey: securityAlertPolicy.?storageAccountAccessKey ?? '' - storageEndpoint: securityAlertPolicy.?storageEndpoint ?? '' + disabledAlerts: securityAlertPolicy.?disabledAlerts + emailAccountAdmins: securityAlertPolicy.?emailAccountAdmins + emailAddresses: securityAlertPolicy.?emailAddresses + retentionDays: securityAlertPolicy.?retentionDays + state: securityAlertPolicy.?state + storageAccountAccessKey: securityAlertPolicy.?storageAccountAccessKey + storageEndpoint: securityAlertPolicy.?storageEndpoint } } ] -module server_vulnerabilityAssessment 'vulnerability-assessment/main.bicep' = if (!empty(vulnerabilityAssessmentsObj)) { +module server_vulnerabilityAssessment 'vulnerability-assessment/main.bicep' = if (vulnerabilityAssessmentsObj != null) { name: '${uniqueString(deployment().name, location)}-Sql-VulnAssessm' params: { serverName: server.name - name: vulnerabilityAssessmentsObj.name - recurringScansEmails: vulnerabilityAssessmentsObj.?recurringScansEmails ?? [] - recurringScansEmailSubscriptionAdmins: vulnerabilityAssessmentsObj.?recurringScansEmailSubscriptionAdmins ?? false - recurringScansIsEnabled: vulnerabilityAssessmentsObj.?recurringScansIsEnabled ?? false - storageAccountResourceId: vulnerabilityAssessmentsObj.storageAccountResourceId - useStorageAccountAccessKey: vulnerabilityAssessmentsObj.?useStorageAccountAccessKey ?? false - createStorageRoleAssignment: vulnerabilityAssessmentsObj.?createStorageRoleAssignment ?? true + name: vulnerabilityAssessmentsObj!.name + recurringScans: vulnerabilityAssessmentsObj.?recurringScans + storageAccountResourceId: vulnerabilityAssessmentsObj!.storageAccountResourceId + useStorageAccountAccessKey: vulnerabilityAssessmentsObj.?useStorageAccountAccessKey + createStorageRoleAssignment: vulnerabilityAssessmentsObj.?createStorageRoleAssignment } dependsOn: [ server_securityAlertPolicies @@ -450,21 +448,21 @@ module server_keys 'key/main.bicep' = [ for (key, index) in keys: { name: '${uniqueString(deployment().name, location)}-Sql-Key-${index}' params: { - name: key.?name serverName: server.name - serverKeyType: key.?serverKeyType ?? 'ServiceManaged' - uri: key.?uri ?? '' + name: key.?name + serverKeyType: key.?serverKeyType + uri: key.?uri } } ] -module server_encryptionProtector 'encryption-protector/main.bicep' = if (!empty(encryptionProtectorObj)) { +module server_encryptionProtector 'encryption-protector/main.bicep' = if (encryptionProtectorObj != null) { name: '${uniqueString(deployment().name, location)}-Sql-EncryProtector' params: { sqlServerName: server.name - serverKeyName: encryptionProtectorObj.serverKeyName - serverKeyType: encryptionProtectorObj.?serverKeyType ?? 'ServiceManaged' - autoRotationEnabled: encryptionProtectorObj.?autoRotationEnabled ?? true + serverKeyName: encryptionProtectorObj!.serverKeyName + serverKeyType: encryptionProtectorObj.?serverKeyType + autoRotationEnabled: encryptionProtectorObj.?autoRotationEnabled } dependsOn: [ server_keys @@ -557,6 +555,7 @@ output privateEndpoints array = [ import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.2.1' import { elasticPoolPerDatabaseSettingsType, elasticPoolSkuType } from 'elastic-pool/main.bicep' import { databaseSkuType, shortTermBackupRetentionPolicyType, longTermBackupRetentionPolicyType } from 'database/main.bicep' +import { recurringScansType } from 'vulnerability-assessment/main.bicep' @export() type auditSettingsType = { @@ -799,3 +798,102 @@ type elasticPoolPropertyType = { @description('Optional. Whether or not this elastic pool is zone redundant, which means the replicas of this elastic pool will be spread across multiple availability zones.') zoneRedundant: bool? } + +@export() +type encryptionProtectorType = { + @description('Required. The name of the server key.') + serverKeyName: string + + @description('Optional. The encryption protector type.') + serverKeyType: 'ServiceManaged' | 'AzureKeyVault'? + + @description('Optional. Key auto rotation opt-in flag.') + autoRotationEnabled: bool? +} + +@export() +type vulnerabilityAssessmentType = { + @description('Required. The name of the vulnerability assessment.') + name: string + + @description('Optional. The recurring scans settings.') + recurringScans: recurringScansType? + + @description('Required. The resource ID of the storage account to store the scan reports.') + storageAccountResourceId: string + + @description('Optional. Specifies whether to use the storage account access key to access the storage account.') + useStorageAccountAccessKey: bool? + + @description('Optional. Specifies whether to create a role assignment for the storage account.') + createStorageRoleAssignment: bool? +} + +@export() +type firewallRuleType = { + @description('Required. The name of the firewall rule.') + name: string + + @description('Optional. The start IP address of the firewall rule. Must be IPv4 format. Use value \'0.0.0.0\' for all Azure-internal IP addresses.') + startIpAddress: string? + + @description('Optional. The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress. Use value \'0.0.0.0\' for all Azure-internal IP addresses.') + endIpAddress: string? +} + +@export() +type keyType = { + @description('Optional. The name of the key. Must follow the [__] pattern.') + name: string? + + @description('Optional. The server key type.') + serverKeyType: 'ServiceManaged' | 'AzureKeyVault'? + + @description('Optional. The URI of the server key. If the ServerKeyType is AzureKeyVault, then the URI is required. The AKV URI is required to be in this format: \'https://YourVaultName.azure.net/keys/YourKeyName/YourKeyVersion\'.') + uri: string? +} + +@export() +type virtualNetworkRuleType = { + @description('Required. The name of the Server Virtual Network Rule.') + name: string + + @description('Required. The resource ID of the virtual network subnet.') + virtualNetworkSubnetId: string + + @description('Optional. Allow creating a firewall rule before the virtual network has vnet service endpoint enabled.') + ignoreMissingVnetServiceEndpoint: bool? +} + +@export() +type securityAlerPolicyType = { + @description('Required. The name of the Security Alert Policy.') + name: string + + @description('Optional. Alerts to disable.') + disabledAlerts: ( + | 'Sql_Injection' + | 'Sql_Injection_Vulnerability' + | 'Access_Anomaly' + | 'Data_Exfiltration' + | 'Unsafe_Action' + | 'Brute_Force')[]? + + @description('Optional. Specifies that the alert is sent to the account administrators.') + emailAccountAdmins: bool? + + @description('Optional. Specifies an array of email addresses to which the alert is sent.') + emailAddresses: string[]? + + @description('Optional. Specifies the number of days to keep in the Threat Detection audit logs.') + retentionDays: int? + + @description('Optional. Specifies the state of the policy, whether it is enabled or disabled or a policy has not been applied yet on the specific database.') + state: 'Enabled' | 'Disabled'? + + @description('Optional. Specifies the identifier key of the Threat Detection audit storage account.') + storageAccountAccessKey: string? + + @description('Optional. Specifies the blob storage endpoint. This blob storage will hold all Threat Detection audit logs.') + storageEndpoint: string? +} diff --git a/avm/res/sql/server/main.json b/avm/res/sql/server/main.json index 0434d51bda..dbdc62dc23 100644 --- a/avm/res/sql/server/main.json +++ b/avm/res/sql/server/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "14327182870559615261" + "version": "0.31.92.45157", + "templateHash": "1261593764623972732" }, "name": "Azure SQL Servers", "description": "This module deploys an Azure SQL Server.", @@ -622,6 +622,245 @@ "__bicep_export!": true } }, + "encryptionProtectorType": { + "type": "object", + "properties": { + "serverKeyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the server key." + } + }, + "serverKeyType": { + "type": "string", + "allowedValues": [ + "AzureKeyVault", + "ServiceManaged" + ], + "nullable": true, + "metadata": { + "description": "Optional. The encryption protector type." + } + }, + "autoRotationEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Key auto rotation opt-in flag." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "vulnerabilityAssessmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the vulnerability assessment." + } + }, + "recurringScans": { + "$ref": "#/definitions/recurringScansType", + "nullable": true, + "metadata": { + "description": "Optional. The recurring scans settings." + } + }, + "storageAccountResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the storage account to store the scan reports." + } + }, + "useStorageAccountAccessKey": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Specifies whether to use the storage account access key to access the storage account." + } + }, + "createStorageRoleAssignment": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Specifies whether to create a role assignment for the storage account." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "firewallRuleType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the firewall rule." + } + }, + "startIpAddress": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The start IP address of the firewall rule. Must be IPv4 format. Use value '0.0.0.0' for all Azure-internal IP addresses." + } + }, + "endIpAddress": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress. Use value '0.0.0.0' for all Azure-internal IP addresses." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "keyType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the key. Must follow the [__] pattern." + } + }, + "serverKeyType": { + "type": "string", + "allowedValues": [ + "AzureKeyVault", + "ServiceManaged" + ], + "nullable": true, + "metadata": { + "description": "Optional. The server key type." + } + }, + "uri": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The URI of the server key. If the ServerKeyType is AzureKeyVault, then the URI is required. The AKV URI is required to be in this format: 'https://YourVaultName.azure.net/keys/YourKeyName/YourKeyVersion'." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "virtualNetworkRuleType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Server Virtual Network Rule." + } + }, + "virtualNetworkSubnetId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the virtual network subnet." + } + }, + "ignoreMissingVnetServiceEndpoint": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Allow creating a firewall rule before the virtual network has vnet service endpoint enabled." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "securityAlerPolicyType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Security Alert Policy." + } + }, + "disabledAlerts": { + "type": "array", + "allowedValues": [ + "Access_Anomaly", + "Brute_Force", + "Data_Exfiltration", + "Sql_Injection", + "Sql_Injection_Vulnerability", + "Unsafe_Action" + ], + "nullable": true, + "metadata": { + "description": "Optional. Alerts to disable." + } + }, + "emailAccountAdmins": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Specifies that the alert is sent to the account administrators." + } + }, + "emailAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Specifies an array of email addresses to which the alert is sent." + } + }, + "retentionDays": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Specifies the number of days to keep in the Threat Detection audit logs." + } + }, + "state": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specifies the state of the policy, whether it is enabled or disabled or a policy has not been applied yet on the specific database." + } + }, + "storageAccountAccessKey": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specifies the identifier key of the Threat Detection audit storage account." + } + }, + "storageEndpoint": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specifies the blob storage endpoint. This blob storage will hold all Threat Detection audit logs." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, "_1.privateEndpointCustomDnsConfigType": { "type": "object", "properties": { @@ -1273,6 +1512,39 @@ } } }, + "recurringScansType": { + "type": "object", + "properties": { + "emails": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. Specifies an array of e-mail addresses to which the scan notification is sent." + } + }, + "emailSubscriptionAdmins": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Specifies that the schedule scan notification will be sent to the subscription administrators." + } + }, + "isEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Recurring scans state." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "vulnerability-assessment/main.bicep" + } + } + }, "roleAssignmentType": { "type": "object", "properties": { @@ -1485,6 +1757,9 @@ }, "firewallRules": { "type": "array", + "items": { + "$ref": "#/definitions/firewallRuleType" + }, "defaultValue": [], "metadata": { "description": "Optional. The firewall rules to create in the server." @@ -1492,6 +1767,9 @@ }, "virtualNetworkRules": { "type": "array", + "items": { + "$ref": "#/definitions/virtualNetworkRuleType" + }, "defaultValue": [], "metadata": { "description": "Optional. The virtual network rules to create in the server." @@ -1499,6 +1777,9 @@ }, "securityAlertPolicies": { "type": "array", + "items": { + "$ref": "#/definitions/securityAlerPolicyType" + }, "defaultValue": [], "metadata": { "description": "Optional. The security alert policies to create in the server." @@ -1506,6 +1787,9 @@ }, "keys": { "type": "array", + "items": { + "$ref": "#/definitions/keyType" + }, "defaultValue": [], "metadata": { "description": "Optional. The keys to configure." @@ -1594,15 +1878,15 @@ } }, "encryptionProtectorObj": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/encryptionProtectorType", + "nullable": true, "metadata": { "description": "Optional. The encryption protection configuration." } }, "vulnerabilityAssessmentsObj": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/vulnerabilityAssessmentType", + "nullable": true, "metadata": { "description": "Optional. The vulnerability assessment configuration." } @@ -1870,8 +2154,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "18018827030977470456" + "version": "0.31.92.45157", + "templateHash": "10088627667414343400" }, "name": "SQL Server Database", "description": "This module deploys an Azure SQL Server Database.", @@ -2586,8 +2870,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "14890409200962565555" + "version": "0.31.92.45157", + "templateHash": "1465086214783345027" }, "name": "Azure SQL Server Database Short Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Short-Term Backup Retention Policy.", @@ -2704,8 +2988,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "841731129374883266" + "version": "0.31.92.45157", + "templateHash": "3060709558343951533" }, "name": "SQL Server Database Long Term Backup Retention Policies", "description": "This module deploys an Azure SQL Server Database Long-Term Backup Retention Policy.", @@ -2938,8 +3222,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "10024079638382167120" + "version": "0.31.92.45157", + "templateHash": "9050866823207809352" }, "name": "SQL Server Elastic Pool", "description": "This module deploys an Azure SQL Server Elastic Pool.", @@ -4013,10 +4297,10 @@ "value": "[parameters('name')]" }, "endIpAddress": { - "value": "[coalesce(tryGet(parameters('firewallRules')[copyIndex()], 'endIpAddress'), '0.0.0.0')]" + "value": "[tryGet(parameters('firewallRules')[copyIndex()], 'endIpAddress')]" }, "startIpAddress": { - "value": "[coalesce(tryGet(parameters('firewallRules')[copyIndex()], 'startIpAddress'), '0.0.0.0')]" + "value": "[tryGet(parameters('firewallRules')[copyIndex()], 'startIpAddress')]" } }, "template": { @@ -4025,8 +4309,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "6449556555046717103" + "version": "0.31.92.45157", + "templateHash": "16725482503837347177" }, "name": "Azure SQL Server Firewall Rule", "description": "This module deploys an Azure SQL Server Firewall Rule.", @@ -4114,14 +4398,14 @@ }, "mode": "Incremental", "parameters": { - "name": { - "value": "[parameters('virtualNetworkRules')[copyIndex()].name]" - }, "serverName": { "value": "[parameters('name')]" }, + "name": { + "value": "[parameters('virtualNetworkRules')[copyIndex()].name]" + }, "ignoreMissingVnetServiceEndpoint": { - "value": "[coalesce(tryGet(parameters('virtualNetworkRules')[copyIndex()], 'ignoreMissingVnetServiceEndpoint'), false())]" + "value": "[tryGet(parameters('virtualNetworkRules')[copyIndex()], 'ignoreMissingVnetServiceEndpoint')]" }, "virtualNetworkSubnetId": { "value": "[parameters('virtualNetworkRules')[copyIndex()].virtualNetworkSubnetId]" @@ -4133,8 +4417,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "4969955763304077350" + "version": "0.31.92.45157", + "templateHash": "11325013625158751172" }, "name": "Azure SQL Server Virtual Network Rules", "description": "This module deploys an Azure SQL Server Virtual Network Rule.", @@ -4228,35 +4512,36 @@ "value": "[parameters('name')]" }, "disabledAlerts": { - "value": "[coalesce(tryGet(parameters('securityAlertPolicies')[copyIndex()], 'disabledAlerts'), createArray())]" + "value": "[tryGet(parameters('securityAlertPolicies')[copyIndex()], 'disabledAlerts')]" }, "emailAccountAdmins": { - "value": "[coalesce(tryGet(parameters('securityAlertPolicies')[copyIndex()], 'emailAccountAdmins'), false())]" + "value": "[tryGet(parameters('securityAlertPolicies')[copyIndex()], 'emailAccountAdmins')]" }, "emailAddresses": { - "value": "[coalesce(tryGet(parameters('securityAlertPolicies')[copyIndex()], 'emailAddresses'), createArray())]" + "value": "[tryGet(parameters('securityAlertPolicies')[copyIndex()], 'emailAddresses')]" }, "retentionDays": { - "value": "[coalesce(tryGet(parameters('securityAlertPolicies')[copyIndex()], 'retentionDays'), 0)]" + "value": "[tryGet(parameters('securityAlertPolicies')[copyIndex()], 'retentionDays')]" }, "state": { - "value": "[coalesce(tryGet(parameters('securityAlertPolicies')[copyIndex()], 'state'), 'Disabled')]" + "value": "[tryGet(parameters('securityAlertPolicies')[copyIndex()], 'state')]" }, "storageAccountAccessKey": { - "value": "[coalesce(tryGet(parameters('securityAlertPolicies')[copyIndex()], 'storageAccountAccessKey'), '')]" + "value": "[tryGet(parameters('securityAlertPolicies')[copyIndex()], 'storageAccountAccessKey')]" }, "storageEndpoint": { - "value": "[coalesce(tryGet(parameters('securityAlertPolicies')[copyIndex()], 'storageEndpoint'), '')]" + "value": "[tryGet(parameters('securityAlertPolicies')[copyIndex()], 'storageEndpoint')]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "15406914222375641032" + "version": "0.31.92.45157", + "templateHash": "15381579869855736341" }, "name": "Azure SQL Server Security Alert Policies", "description": "This module deploys an Azure SQL Server Security Alert Policy.", @@ -4271,9 +4556,20 @@ }, "disabledAlerts": { "type": "array", + "items": { + "type": "string" + }, "defaultValue": [], + "allowedValues": [ + "Sql_Injection", + "Sql_Injection_Vulnerability", + "Access_Anomaly", + "Data_Exfiltration", + "Unsafe_Action", + "Brute_Force" + ], "metadata": { - "description": "Optional. Specifies an array of alerts that are disabled. Allowed values are: Sql_Injection, Sql_Injection_Vulnerability, Access_Anomaly, Data_Exfiltration, Unsafe_Action, Brute_Force." + "description": "Optional. Alerts to disable." } }, "emailAccountAdmins": { @@ -4285,6 +4581,9 @@ }, "emailAddresses": { "type": "array", + "items": { + "type": "string" + }, "defaultValue": [], "metadata": { "description": "Optional. Specifies an array of email addresses to which the alert is sent." @@ -4310,14 +4609,14 @@ }, "storageAccountAccessKey": { "type": "securestring", - "defaultValue": "", + "nullable": true, "metadata": { - "description": "Optional. Specifies the identifier key of the Threat Detection audit storage account.." + "description": "Optional. Specifies the identifier key of the Threat Detection audit storage account." } }, "storageEndpoint": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Specifies the blob storage endpoint. This blob storage will hold all Threat Detection audit logs." } @@ -4329,8 +4628,14 @@ } } }, - "resources": [ - { + "resources": { + "server": { + "existing": true, + "type": "Microsoft.Sql/servers", + "apiVersion": "2023-08-01-preview", + "name": "[parameters('serverName')]" + }, + "securityAlertPolicy": { "type": "Microsoft.Sql/servers/securityAlertPolicies", "apiVersion": "2023-08-01-preview", "name": "[format('{0}/{1}', parameters('serverName'), parameters('name'))]", @@ -4340,11 +4645,14 @@ "emailAddresses": "[parameters('emailAddresses')]", "retentionDays": "[parameters('retentionDays')]", "state": "[parameters('state')]", - "storageAccountAccessKey": "[if(empty(parameters('storageAccountAccessKey')), null(), parameters('storageAccountAccessKey'))]", - "storageEndpoint": "[if(empty(parameters('storageEndpoint')), null(), parameters('storageEndpoint'))]" - } + "storageAccountAccessKey": "[parameters('storageAccountAccessKey')]", + "storageEndpoint": "[parameters('storageEndpoint')]" + }, + "dependsOn": [ + "server" + ] } - ], + }, "outputs": { "name": { "type": "string", @@ -4375,7 +4683,7 @@ ] }, "server_vulnerabilityAssessment": { - "condition": "[not(empty(parameters('vulnerabilityAssessmentsObj')))]", + "condition": "[not(equals(parameters('vulnerabilityAssessmentsObj'), null()))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", "name": "[format('{0}-Sql-VulnAssessm', uniqueString(deployment().name, parameters('location')))]", @@ -4391,38 +4699,66 @@ "name": { "value": "[parameters('vulnerabilityAssessmentsObj').name]" }, - "recurringScansEmails": { - "value": "[coalesce(tryGet(parameters('vulnerabilityAssessmentsObj'), 'recurringScansEmails'), createArray())]" - }, - "recurringScansEmailSubscriptionAdmins": { - "value": "[coalesce(tryGet(parameters('vulnerabilityAssessmentsObj'), 'recurringScansEmailSubscriptionAdmins'), false())]" - }, - "recurringScansIsEnabled": { - "value": "[coalesce(tryGet(parameters('vulnerabilityAssessmentsObj'), 'recurringScansIsEnabled'), false())]" + "recurringScans": { + "value": "[tryGet(parameters('vulnerabilityAssessmentsObj'), 'recurringScans')]" }, "storageAccountResourceId": { "value": "[parameters('vulnerabilityAssessmentsObj').storageAccountResourceId]" }, "useStorageAccountAccessKey": { - "value": "[coalesce(tryGet(parameters('vulnerabilityAssessmentsObj'), 'useStorageAccountAccessKey'), false())]" + "value": "[tryGet(parameters('vulnerabilityAssessmentsObj'), 'useStorageAccountAccessKey')]" }, "createStorageRoleAssignment": { - "value": "[coalesce(tryGet(parameters('vulnerabilityAssessmentsObj'), 'createStorageRoleAssignment'), true())]" + "value": "[tryGet(parameters('vulnerabilityAssessmentsObj'), 'createStorageRoleAssignment')]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "11004049200994426011" + "version": "0.31.92.45157", + "templateHash": "12724764985088418792" }, "name": "Azure SQL Server Vulnerability Assessments", "description": "This module deploys an Azure SQL Server Vulnerability Assessment.", "owner": "Azure/module-maintainers" }, + "definitions": { + "recurringScansType": { + "type": "object", + "properties": { + "emails": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. Specifies an array of e-mail addresses to which the scan notification is sent." + } + }, + "emailSubscriptionAdmins": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Specifies that the schedule scan notification will be sent to the subscription administrators." + } + }, + "isEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Recurring scans state." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "name": { "type": "string", @@ -4436,25 +4772,15 @@ "description": "Conditional. The Name of SQL Server. Required if the template is used in a standalone deployment." } }, - "recurringScansIsEnabled": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Recurring scans state." - } - }, - "recurringScansEmailSubscriptionAdmins": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Specifies that the schedule scan notification will be is sent to the subscription administrators." - } - }, - "recurringScansEmails": { - "type": "array", - "defaultValue": [], + "recurringScans": { + "$ref": "#/definitions/recurringScansType", + "defaultValue": { + "emails": [], + "emailSubscriptionAdmins": false, + "isEnabled": false + }, "metadata": { - "description": "Optional. Specifies an array of email addresses to which the scan notification is sent." + "description": "Optional. The recurring scans settings." } }, "storageAccountResourceId": { @@ -4478,22 +4804,27 @@ } } }, - "resources": [ - { + "resources": { + "server": { + "existing": true, + "type": "Microsoft.Sql/servers", + "apiVersion": "2023-08-01-preview", + "name": "[parameters('serverName')]" + }, + "vulnerabilityAssessment": { "type": "Microsoft.Sql/servers/vulnerabilityAssessments", "apiVersion": "2023-08-01-preview", "name": "[format('{0}/{1}', parameters('serverName'), parameters('name'))]", "properties": { "storageContainerPath": "[format('https://{0}.blob.{1}/vulnerability-assessment/', last(split(parameters('storageAccountResourceId'), '/')), environment().suffixes.storage)]", "storageAccountAccessKey": "[if(parameters('useStorageAccountAccessKey'), listKeys(parameters('storageAccountResourceId'), '2019-06-01').keys[0].value, null())]", - "recurringScans": { - "isEnabled": "[parameters('recurringScansIsEnabled')]", - "emailSubscriptionAdmins": "[parameters('recurringScansEmailSubscriptionAdmins')]", - "emails": "[parameters('recurringScansEmails')]" - } - } + "recurringScans": "[parameters('recurringScans')]" + }, + "dependsOn": [ + "server" + ] }, - { + "storageAccount_sbdc_rbac": { "condition": "[and(not(parameters('useStorageAccountAccessKey')), parameters('createStorageRoleAssignment'))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -4510,7 +4841,7 @@ "value": "[last(split(parameters('storageAccountResourceId'), '/'))]" }, "managedInstanceIdentityPrincipalId": { - "value": "[reference(resourceId('Microsoft.Sql/servers', parameters('serverName')), '2023-08-01-preview', 'full').identity.principalId]" + "value": "[reference('server', '2023-08-01-preview', 'full').identity.principalId]" } }, "template": { @@ -4519,8 +4850,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "13956215614091387428" + "version": "0.31.92.45157", + "templateHash": "2903956714854050681" } }, "parameters": { @@ -4545,9 +4876,12 @@ } ] } - } + }, + "dependsOn": [ + "server" + ] } - ], + }, "outputs": { "name": { "type": "string", @@ -4592,17 +4926,17 @@ }, "mode": "Incremental", "parameters": { - "name": { - "value": "[tryGet(parameters('keys')[copyIndex()], 'name')]" - }, "serverName": { "value": "[parameters('name')]" }, + "name": { + "value": "[tryGet(parameters('keys')[copyIndex()], 'name')]" + }, "serverKeyType": { - "value": "[coalesce(tryGet(parameters('keys')[copyIndex()], 'serverKeyType'), 'ServiceManaged')]" + "value": "[tryGet(parameters('keys')[copyIndex()], 'serverKeyType')]" }, "uri": { - "value": "[coalesce(tryGet(parameters('keys')[copyIndex()], 'uri'), '')]" + "value": "[tryGet(parameters('keys')[copyIndex()], 'uri')]" } }, "template": { @@ -4612,8 +4946,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "17839617504395216689" + "version": "0.31.92.45157", + "templateHash": "16457177770650062823" }, "name": "Azure SQL Server Keys", "description": "This module deploys an Azure SQL Server Key.", @@ -4641,14 +4975,14 @@ "ServiceManaged" ], "metadata": { - "description": "Optional. The encryption protector type like \"ServiceManaged\", \"AzureKeyVault\"." + "description": "Optional. The server key type." } }, "uri": { "type": "string", "defaultValue": "", "metadata": { - "description": "Optional. The URI of the key. If the ServerKeyType is AzureKeyVault, then either the URI or the keyVaultName/keyName combination is required." + "description": "Optional. The URI of the server key. If the ServerKeyType is AzureKeyVault, then the URI is required. The AKV URI is required to be in this format: 'https://YourVaultName.azure.net/keys/YourKeyName/YourKeyVersion'." } } }, @@ -4706,7 +5040,7 @@ ] }, "server_encryptionProtector": { - "condition": "[not(empty(parameters('encryptionProtectorObj')))]", + "condition": "[not(equals(parameters('encryptionProtectorObj'), null()))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", "name": "[format('{0}-Sql-EncryProtector', uniqueString(deployment().name, parameters('location')))]", @@ -4723,10 +5057,10 @@ "value": "[parameters('encryptionProtectorObj').serverKeyName]" }, "serverKeyType": { - "value": "[coalesce(tryGet(parameters('encryptionProtectorObj'), 'serverKeyType'), 'ServiceManaged')]" + "value": "[tryGet(parameters('encryptionProtectorObj'), 'serverKeyType')]" }, "autoRotationEnabled": { - "value": "[coalesce(tryGet(parameters('encryptionProtectorObj'), 'autoRotationEnabled'), true())]" + "value": "[tryGet(parameters('encryptionProtectorObj'), 'autoRotationEnabled')]" } }, "template": { @@ -4735,8 +5069,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "11473914706327458055" + "version": "0.31.92.45157", + "templateHash": "3436938593239210559" }, "name": "Azure SQL Server Encryption Protector", "description": "This module deploys an Azure SQL Server Encryption Protector.", @@ -4757,9 +5091,9 @@ }, "autoRotationEnabled": { "type": "bool", - "defaultValue": false, + "defaultValue": true, "metadata": { - "description": "Optional. Key auto rotation opt-in." + "description": "Optional. Key auto rotation opt-in flag." } }, "serverKeyType": { @@ -4868,8 +5202,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "6303070680265885029" + "version": "0.31.92.45157", + "templateHash": "4626140114742164628" }, "name": "Azure SQL Server Audit Settings", "description": "This module deploys an Azure SQL Server Audit Settings.", @@ -5015,8 +5349,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "13956215614091387428" + "version": "0.31.92.45157", + "templateHash": "2903956714854050681" } }, "parameters": { @@ -5103,8 +5437,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "13150358169332921706" + "version": "0.31.92.45157", + "templateHash": "17763074267065683265" } }, "definitions": { diff --git a/avm/res/sql/server/security-alert-policy/README.md b/avm/res/sql/server/security-alert-policy/README.md index 4b42b0f9f6..822cc94cca 100644 --- a/avm/res/sql/server/security-alert-policy/README.md +++ b/avm/res/sql/server/security-alert-policy/README.md @@ -32,12 +32,12 @@ This module deploys an Azure SQL Server Security Alert Policy. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`disabledAlerts`](#parameter-disabledalerts) | array | Specifies an array of alerts that are disabled. Allowed values are: Sql_Injection, Sql_Injection_Vulnerability, Access_Anomaly, Data_Exfiltration, Unsafe_Action, Brute_Force. | +| [`disabledAlerts`](#parameter-disabledalerts) | array | Alerts to disable. | | [`emailAccountAdmins`](#parameter-emailaccountadmins) | bool | Specifies that the alert is sent to the account administrators. | | [`emailAddresses`](#parameter-emailaddresses) | array | Specifies an array of email addresses to which the alert is sent. | | [`retentionDays`](#parameter-retentiondays) | int | Specifies the number of days to keep in the Threat Detection audit logs. | | [`state`](#parameter-state) | string | Specifies the state of the policy, whether it is enabled or disabled or a policy has not been applied yet on the specific database. | -| [`storageAccountAccessKey`](#parameter-storageaccountaccesskey) | securestring | Specifies the identifier key of the Threat Detection audit storage account.. | +| [`storageAccountAccessKey`](#parameter-storageaccountaccesskey) | securestring | Specifies the identifier key of the Threat Detection audit storage account. | | [`storageEndpoint`](#parameter-storageendpoint) | string | Specifies the blob storage endpoint. This blob storage will hold all Threat Detection audit logs. | ### Parameter: `name` @@ -56,11 +56,22 @@ The name of the parent SQL Server. Required if the template is used in a standal ### Parameter: `disabledAlerts` -Specifies an array of alerts that are disabled. Allowed values are: Sql_Injection, Sql_Injection_Vulnerability, Access_Anomaly, Data_Exfiltration, Unsafe_Action, Brute_Force. +Alerts to disable. - Required: No - Type: array - Default: `[]` +- Allowed: + ```Bicep + [ + 'Access_Anomaly' + 'Brute_Force' + 'Data_Exfiltration' + 'Sql_Injection' + 'Sql_Injection_Vulnerability' + 'Unsafe_Action' + ] + ``` ### Parameter: `emailAccountAdmins` @@ -103,11 +114,10 @@ Specifies the state of the policy, whether it is enabled or disabled or a policy ### Parameter: `storageAccountAccessKey` -Specifies the identifier key of the Threat Detection audit storage account.. +Specifies the identifier key of the Threat Detection audit storage account. - Required: No - Type: securestring -- Default: `''` ### Parameter: `storageEndpoint` @@ -115,7 +125,6 @@ Specifies the blob storage endpoint. This blob storage will hold all Threat Dete - Required: No - Type: string -- Default: `''` ## Outputs diff --git a/avm/res/sql/server/security-alert-policy/main.bicep b/avm/res/sql/server/security-alert-policy/main.bicep index d654b4609a..cad883e041 100644 --- a/avm/res/sql/server/security-alert-policy/main.bicep +++ b/avm/res/sql/server/security-alert-policy/main.bicep @@ -5,14 +5,22 @@ metadata owner = 'Azure/module-maintainers' @description('Required. The name of the Security Alert Policy.') param name string -@description('Optional. Specifies an array of alerts that are disabled. Allowed values are: Sql_Injection, Sql_Injection_Vulnerability, Access_Anomaly, Data_Exfiltration, Unsafe_Action, Brute_Force.') -param disabledAlerts array = [] +@description('Optional. Alerts to disable.') +@allowed([ + 'Sql_Injection' + 'Sql_Injection_Vulnerability' + 'Access_Anomaly' + 'Data_Exfiltration' + 'Unsafe_Action' + 'Brute_Force' +]) +param disabledAlerts string[] = [] @description('Optional. Specifies that the alert is sent to the account administrators.') param emailAccountAdmins bool = false @description('Optional. Specifies an array of email addresses to which the alert is sent.') -param emailAddresses array = [] +param emailAddresses string[] = [] @description('Optional. Specifies the number of days to keep in the Threat Detection audit logs.') param retentionDays int = 0 @@ -24,12 +32,12 @@ param retentionDays int = 0 ]) param state string = 'Disabled' -@description('Optional. Specifies the identifier key of the Threat Detection audit storage account..') +@description('Optional. Specifies the identifier key of the Threat Detection audit storage account.') @secure() -param storageAccountAccessKey string = '' +param storageAccountAccessKey string? @description('Optional. Specifies the blob storage endpoint. This blob storage will hold all Threat Detection audit logs.') -param storageEndpoint string = '' +param storageEndpoint string? @description('Conditional. The name of the parent SQL Server. Required if the template is used in a standalone deployment.') param serverName string @@ -47,8 +55,8 @@ resource securityAlertPolicy 'Microsoft.Sql/servers/securityAlertPolicies@2023-0 emailAddresses: emailAddresses retentionDays: retentionDays state: state - storageAccountAccessKey: empty(storageAccountAccessKey) ? null : storageAccountAccessKey - storageEndpoint: empty(storageEndpoint) ? null : storageEndpoint + storageAccountAccessKey: storageAccountAccessKey + storageEndpoint: storageEndpoint } } diff --git a/avm/res/sql/server/security-alert-policy/main.json b/avm/res/sql/server/security-alert-policy/main.json index 08cdceaee6..af541d3817 100644 --- a/avm/res/sql/server/security-alert-policy/main.json +++ b/avm/res/sql/server/security-alert-policy/main.json @@ -1,11 +1,12 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "15406914222375641032" + "version": "0.31.92.45157", + "templateHash": "15381579869855736341" }, "name": "Azure SQL Server Security Alert Policies", "description": "This module deploys an Azure SQL Server Security Alert Policy.", @@ -20,9 +21,20 @@ }, "disabledAlerts": { "type": "array", + "items": { + "type": "string" + }, "defaultValue": [], + "allowedValues": [ + "Sql_Injection", + "Sql_Injection_Vulnerability", + "Access_Anomaly", + "Data_Exfiltration", + "Unsafe_Action", + "Brute_Force" + ], "metadata": { - "description": "Optional. Specifies an array of alerts that are disabled. Allowed values are: Sql_Injection, Sql_Injection_Vulnerability, Access_Anomaly, Data_Exfiltration, Unsafe_Action, Brute_Force." + "description": "Optional. Alerts to disable." } }, "emailAccountAdmins": { @@ -34,6 +46,9 @@ }, "emailAddresses": { "type": "array", + "items": { + "type": "string" + }, "defaultValue": [], "metadata": { "description": "Optional. Specifies an array of email addresses to which the alert is sent." @@ -59,14 +74,14 @@ }, "storageAccountAccessKey": { "type": "securestring", - "defaultValue": "", + "nullable": true, "metadata": { - "description": "Optional. Specifies the identifier key of the Threat Detection audit storage account.." + "description": "Optional. Specifies the identifier key of the Threat Detection audit storage account." } }, "storageEndpoint": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. Specifies the blob storage endpoint. This blob storage will hold all Threat Detection audit logs." } @@ -78,8 +93,14 @@ } } }, - "resources": [ - { + "resources": { + "server": { + "existing": true, + "type": "Microsoft.Sql/servers", + "apiVersion": "2023-08-01-preview", + "name": "[parameters('serverName')]" + }, + "securityAlertPolicy": { "type": "Microsoft.Sql/servers/securityAlertPolicies", "apiVersion": "2023-08-01-preview", "name": "[format('{0}/{1}', parameters('serverName'), parameters('name'))]", @@ -89,11 +110,14 @@ "emailAddresses": "[parameters('emailAddresses')]", "retentionDays": "[parameters('retentionDays')]", "state": "[parameters('state')]", - "storageAccountAccessKey": "[if(empty(parameters('storageAccountAccessKey')), null(), parameters('storageAccountAccessKey'))]", - "storageEndpoint": "[if(empty(parameters('storageEndpoint')), null(), parameters('storageEndpoint'))]" - } + "storageAccountAccessKey": "[parameters('storageAccountAccessKey')]", + "storageEndpoint": "[parameters('storageEndpoint')]" + }, + "dependsOn": [ + "server" + ] } - ], + }, "outputs": { "name": { "type": "string", diff --git a/avm/res/sql/server/tests/e2e/elasticPool/main.test.bicep b/avm/res/sql/server/tests/e2e/elasticPool/main.test.bicep index 9202a2fe6c..99153efae4 100644 --- a/avm/res/sql/server/tests/e2e/elasticPool/main.test.bicep +++ b/avm/res/sql/server/tests/e2e/elasticPool/main.test.bicep @@ -53,6 +53,7 @@ module testDeployment '../../../main.bicep' = [ // bare minimum elastic pool: only a name is specified { name: '${namePrefix}-${serviceShort}-ep-001' + zoneRedundant: false } // more complex elastic pool with non-default SKU and per database settings { @@ -66,6 +67,7 @@ module testDeployment '../../../main.bicep' = [ minCapacity: '0.5' maxCapacity: '4' } + zoneRedundant: false } ] } diff --git a/avm/res/sql/server/tests/e2e/kvSecrets/main.test.bicep b/avm/res/sql/server/tests/e2e/kvSecrets/main.test.bicep index 31e94ee0a9..06f60cb743 100644 --- a/avm/res/sql/server/tests/e2e/kvSecrets/main.test.bicep +++ b/avm/res/sql/server/tests/e2e/kvSecrets/main.test.bicep @@ -66,6 +66,7 @@ module testDeployment '../../../main.bicep' = [ databases: [ { name: 'myDatabase' + zoneRedundant: false } ] } diff --git a/avm/res/sql/server/tests/e2e/max/main.test.bicep b/avm/res/sql/server/tests/e2e/max/main.test.bicep index 232c88c9cb..2bdc6768fb 100644 --- a/avm/res/sql/server/tests/e2e/max/main.test.bicep +++ b/avm/res/sql/server/tests/e2e/max/main.test.bicep @@ -106,12 +106,14 @@ module testDeployment '../../../main.bicep' = { ] vulnerabilityAssessmentsObj: { name: 'default' - emailSubscriptionAdmins: true - recurringScansIsEnabled: true - recurringScansEmails: [ - 'test1@contoso.com' - 'test2@contoso.com' - ] + recurringScans: { + emailSubscriptionAdmins: true + isEnabled: true + emails: [ + 'test1@contoso.com' + 'test2@contoso.com' + ] + } storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId } elasticPools: [ diff --git a/avm/res/sql/server/tests/e2e/secondary/main.test.bicep b/avm/res/sql/server/tests/e2e/secondary/main.test.bicep index d2b8cfab0f..9b1cd8e5ea 100644 --- a/avm/res/sql/server/tests/e2e/secondary/main.test.bicep +++ b/avm/res/sql/server/tests/e2e/secondary/main.test.bicep @@ -66,6 +66,7 @@ module testDeployment '../../../main.bicep' = { maxSizeBytes: 2147483648 createMode: 'Secondary' sourceDatabaseResourceId: nestedDependencies.outputs.databaseResourceId + zoneRedundant: false } ] tags: { diff --git a/avm/res/sql/server/tests/e2e/vulnAssm/main.test.bicep b/avm/res/sql/server/tests/e2e/vulnAssm/main.test.bicep index 3b01629f48..b49485bdee 100644 --- a/avm/res/sql/server/tests/e2e/vulnAssm/main.test.bicep +++ b/avm/res/sql/server/tests/e2e/vulnAssm/main.test.bicep @@ -59,13 +59,15 @@ module testDeployment '../../../main.bicep' = { administratorLoginPassword: password location: resourceLocation vulnerabilityAssessmentsObj: { - emailSubscriptionAdmins: true name: 'default' - recurringScansEmails: [ - 'test1@contoso.com' - 'test2@contoso.com' - ] - recurringScansIsEnabled: true + recurringScans: { + emails: [ + 'test1@contoso.com' + 'test2@contoso.com' + ] + emailSubscriptionAdmins: true + isEnabled: true + } storageAccountResourceId: nestedDependencies.outputs.storageAccountResourceId useStorageAccountAccessKey: false createStorageRoleAssignment: true diff --git a/avm/res/sql/server/tests/e2e/waf-aligned/main.test.bicep b/avm/res/sql/server/tests/e2e/waf-aligned/main.test.bicep index a8da430a58..220d704979 100644 --- a/avm/res/sql/server/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/sql/server/tests/e2e/waf-aligned/main.test.bicep @@ -81,12 +81,14 @@ module testDeployment '../../../main.bicep' = { location: enforcedLocation vulnerabilityAssessmentsObj: { name: 'default' - emailSubscriptionAdmins: true - recurringScansIsEnabled: true - recurringScansEmails: [ - 'test1@contoso.com' - 'test2@contoso.com' - ] + recurringScans: { + emailSubscriptionAdmins: true + isEnabled: true + emails: [ + 'test1@contoso.com' + 'test2@contoso.com' + ] + } storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId } elasticPools: [ diff --git a/avm/res/sql/server/version.json b/avm/res/sql/server/version.json index 9c08aae215..6a120cace8 100644 --- a/avm/res/sql/server/version.json +++ b/avm/res/sql/server/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.10", + "version": "0.11", "pathFilters": [ "./main.json" ] diff --git a/avm/res/sql/server/virtual-network-rule/main.json b/avm/res/sql/server/virtual-network-rule/main.json index 8aeb38250b..aff0572634 100644 --- a/avm/res/sql/server/virtual-network-rule/main.json +++ b/avm/res/sql/server/virtual-network-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "4969955763304077350" + "version": "0.31.92.45157", + "templateHash": "11325013625158751172" }, "name": "Azure SQL Server Virtual Network Rules", "description": "This module deploys an Azure SQL Server Virtual Network Rule.", diff --git a/avm/res/sql/server/vulnerability-assessment/README.md b/avm/res/sql/server/vulnerability-assessment/README.md index e20eaf6fee..d2a2c44b50 100644 --- a/avm/res/sql/server/vulnerability-assessment/README.md +++ b/avm/res/sql/server/vulnerability-assessment/README.md @@ -35,9 +35,7 @@ This module deploys an Azure SQL Server Vulnerability Assessment. | Parameter | Type | Description | | :-- | :-- | :-- | | [`createStorageRoleAssignment`](#parameter-createstorageroleassignment) | bool | Create the Storage Blob Data Contributor role assignment on the storage account. Note, the role assignment must not already exist on the storage account. | -| [`recurringScansEmails`](#parameter-recurringscansemails) | array | Specifies an array of email addresses to which the scan notification is sent. | -| [`recurringScansEmailSubscriptionAdmins`](#parameter-recurringscansemailsubscriptionadmins) | bool | Specifies that the schedule scan notification will be is sent to the subscription administrators. | -| [`recurringScansIsEnabled`](#parameter-recurringscansisenabled) | bool | Recurring scans state. | +| [`recurringScans`](#parameter-recurringscans) | object | The recurring scans settings. | | [`useStorageAccountAccessKey`](#parameter-usestorageaccountaccesskey) | bool | Use Access Key to access the storage account. The storage account cannot be behind a firewall or virtual network. If an access key is not used, the SQL Server system assigned managed identity must be assigned the Storage Blob Data Contributor role on the storage account. | ### Parameter: `name` @@ -69,29 +67,54 @@ Create the Storage Blob Data Contributor role assignment on the storage account. - Type: bool - Default: `True` -### Parameter: `recurringScansEmails` +### Parameter: `recurringScans` -Specifies an array of email addresses to which the scan notification is sent. +The recurring scans settings. - Required: No +- Type: object +- Default: + ```Bicep + { + emails: [] + emailSubscriptionAdmins: false + isEnabled: false + } + ``` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`emails`](#parameter-recurringscansemails) | array | Specifies an array of e-mail addresses to which the scan notification is sent. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`emailSubscriptionAdmins`](#parameter-recurringscansemailsubscriptionadmins) | bool | Specifies that the schedule scan notification will be sent to the subscription administrators. | +| [`isEnabled`](#parameter-recurringscansisenabled) | bool | Recurring scans state. | + +### Parameter: `recurringScans.emails` + +Specifies an array of e-mail addresses to which the scan notification is sent. + +- Required: Yes - Type: array -- Default: `[]` -### Parameter: `recurringScansEmailSubscriptionAdmins` +### Parameter: `recurringScans.emailSubscriptionAdmins` -Specifies that the schedule scan notification will be is sent to the subscription administrators. +Specifies that the schedule scan notification will be sent to the subscription administrators. - Required: No - Type: bool -- Default: `False` -### Parameter: `recurringScansIsEnabled` +### Parameter: `recurringScans.isEnabled` Recurring scans state. - Required: No - Type: bool -- Default: `False` ### Parameter: `useStorageAccountAccessKey` diff --git a/avm/res/sql/server/vulnerability-assessment/main.bicep b/avm/res/sql/server/vulnerability-assessment/main.bicep index 30a1af78aa..736a070a04 100644 --- a/avm/res/sql/server/vulnerability-assessment/main.bicep +++ b/avm/res/sql/server/vulnerability-assessment/main.bicep @@ -8,14 +8,12 @@ param name string @description('Conditional. The Name of SQL Server. Required if the template is used in a standalone deployment.') param serverName string -@description('Optional. Recurring scans state.') -param recurringScansIsEnabled bool = false - -@description('Optional. Specifies that the schedule scan notification will be is sent to the subscription administrators.') -param recurringScansEmailSubscriptionAdmins bool = false - -@description('Optional. Specifies an array of email addresses to which the scan notification is sent.') -param recurringScansEmails array = [] +@description('Optional. The recurring scans settings.') +param recurringScans recurringScansType = { + emails: [] + emailSubscriptionAdmins: false + isEnabled: false +} @description('Required. A blob storage to hold the scan results.') param storageAccountResourceId string @@ -48,14 +46,22 @@ resource vulnerabilityAssessment 'Microsoft.Sql/servers/vulnerabilityAssessments storageAccountAccessKey: useStorageAccountAccessKey ? listKeys(storageAccountResourceId, '2019-06-01').keys[0].value : any(null) - recurringScans: { - isEnabled: recurringScansIsEnabled - emailSubscriptionAdmins: recurringScansEmailSubscriptionAdmins - emails: recurringScansEmails - } + recurringScans: recurringScans } } +@export() +type recurringScansType = { + @description('Required. Specifies an array of e-mail addresses to which the scan notification is sent.') + emails: string[] + + @description('Optional. Specifies that the schedule scan notification will be sent to the subscription administrators.') + emailSubscriptionAdmins: bool? + + @description('Optional. Recurring scans state.') + isEnabled: bool? +} + @description('The name of the deployed vulnerability assessment.') output name string = vulnerabilityAssessment.name diff --git a/avm/res/sql/server/vulnerability-assessment/main.json b/avm/res/sql/server/vulnerability-assessment/main.json index 134adac324..672112c20b 100644 --- a/avm/res/sql/server/vulnerability-assessment/main.json +++ b/avm/res/sql/server/vulnerability-assessment/main.json @@ -1,16 +1,50 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "11004049200994426011" + "version": "0.31.92.45157", + "templateHash": "12724764985088418792" }, "name": "Azure SQL Server Vulnerability Assessments", "description": "This module deploys an Azure SQL Server Vulnerability Assessment.", "owner": "Azure/module-maintainers" }, + "definitions": { + "recurringScansType": { + "type": "object", + "properties": { + "emails": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. Specifies an array of e-mail addresses to which the scan notification is sent." + } + }, + "emailSubscriptionAdmins": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Specifies that the schedule scan notification will be sent to the subscription administrators." + } + }, + "isEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Recurring scans state." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "name": { "type": "string", @@ -24,25 +58,15 @@ "description": "Conditional. The Name of SQL Server. Required if the template is used in a standalone deployment." } }, - "recurringScansIsEnabled": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Recurring scans state." - } - }, - "recurringScansEmailSubscriptionAdmins": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Specifies that the schedule scan notification will be is sent to the subscription administrators." - } - }, - "recurringScansEmails": { - "type": "array", - "defaultValue": [], + "recurringScans": { + "$ref": "#/definitions/recurringScansType", + "defaultValue": { + "emails": [], + "emailSubscriptionAdmins": false, + "isEnabled": false + }, "metadata": { - "description": "Optional. Specifies an array of email addresses to which the scan notification is sent." + "description": "Optional. The recurring scans settings." } }, "storageAccountResourceId": { @@ -66,22 +90,27 @@ } } }, - "resources": [ - { + "resources": { + "server": { + "existing": true, + "type": "Microsoft.Sql/servers", + "apiVersion": "2023-08-01-preview", + "name": "[parameters('serverName')]" + }, + "vulnerabilityAssessment": { "type": "Microsoft.Sql/servers/vulnerabilityAssessments", "apiVersion": "2023-08-01-preview", "name": "[format('{0}/{1}', parameters('serverName'), parameters('name'))]", "properties": { "storageContainerPath": "[format('https://{0}.blob.{1}/vulnerability-assessment/', last(split(parameters('storageAccountResourceId'), '/')), environment().suffixes.storage)]", "storageAccountAccessKey": "[if(parameters('useStorageAccountAccessKey'), listKeys(parameters('storageAccountResourceId'), '2019-06-01').keys[0].value, null())]", - "recurringScans": { - "isEnabled": "[parameters('recurringScansIsEnabled')]", - "emailSubscriptionAdmins": "[parameters('recurringScansEmailSubscriptionAdmins')]", - "emails": "[parameters('recurringScansEmails')]" - } - } + "recurringScans": "[parameters('recurringScans')]" + }, + "dependsOn": [ + "server" + ] }, - { + "storageAccount_sbdc_rbac": { "condition": "[and(not(parameters('useStorageAccountAccessKey')), parameters('createStorageRoleAssignment'))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", @@ -98,7 +127,7 @@ "value": "[last(split(parameters('storageAccountResourceId'), '/'))]" }, "managedInstanceIdentityPrincipalId": { - "value": "[reference(resourceId('Microsoft.Sql/servers', parameters('serverName')), '2023-08-01-preview', 'full').identity.principalId]" + "value": "[reference('server', '2023-08-01-preview', 'full').identity.principalId]" } }, "template": { @@ -107,8 +136,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.30.23.60470", - "templateHash": "13956215614091387428" + "version": "0.31.92.45157", + "templateHash": "2903956714854050681" } }, "parameters": { @@ -133,9 +162,12 @@ } ] } - } + }, + "dependsOn": [ + "server" + ] } - ], + }, "outputs": { "name": { "type": "string",