diff --git a/avm/res/net-app/net-app-account/README.md b/avm/res/net-app/net-app-account/README.md index 82f4578b64..8f9e1b09f5 100644 --- a/avm/res/net-app/net-app-account/README.md +++ b/avm/res/net-app/net-app-account/README.md @@ -18,6 +18,9 @@ This module deploys an Azure NetApp File. | `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | | `Microsoft.NetApp/netAppAccounts` | [2023-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-07-01/netAppAccounts) | +| `Microsoft.NetApp/netAppAccounts/backupPolicies` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-11-01/netAppAccounts/backupPolicies) | +| `Microsoft.NetApp/netAppAccounts/backupVaults` | [2023-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-05-01-preview/netAppAccounts/backupVaults) | +| `Microsoft.NetApp/netAppAccounts/backupVaults/backups` | [2023-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-05-01-preview/netAppAccounts/backupVaults/backups) | | `Microsoft.NetApp/netAppAccounts/capacityPools` | [2023-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-07-01/netAppAccounts/capacityPools) | | `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | [2023-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-07-01/netAppAccounts/capacityPools/volumes) | @@ -685,6 +688,7 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { | Parameter | Type | Description | | :-- | :-- | :-- | +| [`adName`](#parameter-adname) | string | Name of the active directory host as part of Kerberos Realm used for Kerberos authentication. | | [`aesEncryption`](#parameter-aesencryption) | bool | Enable AES encryption on the SMB Server. | | [`capacityPools`](#parameter-capacitypools) | array | Capacity pools to create. | | [`customerManagedKey`](#parameter-customermanagedkey) | object | The customer managed key definition. | @@ -694,11 +698,15 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { | [`domainJoinUser`](#parameter-domainjoinuser) | string | Required if domainName is specified. Username of Active Directory domain administrator, with permissions to create SMB server machine account in the AD domain. | | [`domainName`](#parameter-domainname) | string | Fully Qualified Active Directory DNS Domain Name (e.g. 'contoso.com'). | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`encryptDCConnections`](#parameter-encryptdcconnections) | bool | Specifies whether encryption should be used for communication between SMB server and domain controller (DC). SMB3 only. | +| [`kdcIP`](#parameter-kdcip) | string | Kerberos Key Distribution Center (KDC) as part of Kerberos Realm used for Kerberos authentication. | +| [`ldapOverTLS`](#parameter-ldapovertls) | bool | Specifies whether to use TLS when NFS (with/without Kerberos) and SMB volumes communicate with an LDAP server. A server root CA certificate must be uploaded if enabled (serverRootCACertificate). | | [`ldapSigning`](#parameter-ldapsigning) | bool | Specifies whether or not the LDAP traffic needs to be signed. | | [`location`](#parameter-location) | string | Location for all resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | | [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | | [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`serverRootCACertificate`](#parameter-serverrootcacertificate) | string | A server Root certificate is required of ldapOverTLS is enabled. | | [`smbServerNamePrefix`](#parameter-smbservernameprefix) | string | Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes. | | [`tags`](#parameter-tags) | object | Tags for all resources. | @@ -709,6 +717,14 @@ The name of the NetApp account. - Required: Yes - Type: string +### Parameter: `adName` + +Name of the active directory host as part of Kerberos Realm used for Kerberos authentication. + +- Required: No +- Type: string +- Default: `''` + ### Parameter: `aesEncryption` Enable AES encryption on the SMB Server. @@ -822,6 +838,30 @@ Enable/Disable usage telemetry for module. - Type: bool - Default: `True` +### Parameter: `encryptDCConnections` + +Specifies whether encryption should be used for communication between SMB server and domain controller (DC). SMB3 only. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `kdcIP` + +Kerberos Key Distribution Center (KDC) as part of Kerberos Realm used for Kerberos authentication. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `ldapOverTLS` + +Specifies whether to use TLS when NFS (with/without Kerberos) and SMB volumes communicate with an LDAP server. A server root CA certificate must be uploaded if enabled (serverRootCACertificate). + +- Required: No +- Type: bool +- Default: `False` + ### Parameter: `ldapSigning` Specifies whether or not the LDAP traffic needs to be signed. @@ -983,6 +1023,14 @@ The principal type of the assigned principal ID. ] ``` +### Parameter: `serverRootCACertificate` + +A server Root certificate is required of ldapOverTLS is enabled. + +- Required: No +- Type: string +- Default: `''` + ### Parameter: `smbServerNamePrefix` Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes. @@ -1007,6 +1055,7 @@ Tags for all resources. | `name` | string | The name of the NetApp account. | | `resourceGroupName` | string | The name of the Resource Group the NetApp account was created in. | | `resourceId` | string | The Resource ID of the NetApp account. | +| `volumeResourceId` | string | The resource IDs of the volume created in the capacity pool. | ## Cross-referenced modules diff --git a/avm/res/net-app/net-app-account/capacity-pool/README.md b/avm/res/net-app/net-app-account/capacity-pool/README.md index 21dd5b6a73..b188626edf 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/README.md +++ b/avm/res/net-app/net-app-account/capacity-pool/README.md @@ -15,6 +15,9 @@ This module deploys an Azure NetApp Files Capacity Pool. | Resource Type | API Version | | :-- | :-- | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.NetApp/netAppAccounts/backupPolicies` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-11-01/netAppAccounts/backupPolicies) | +| `Microsoft.NetApp/netAppAccounts/backupVaults` | [2023-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-05-01-preview/netAppAccounts/backupVaults) | +| `Microsoft.NetApp/netAppAccounts/backupVaults/backups` | [2023-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-05-01-preview/netAppAccounts/backupVaults/backups) | | `Microsoft.NetApp/netAppAccounts/capacityPools` | [2023-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-07-01/netAppAccounts/capacityPools) | | `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | [2023-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-07-01/netAppAccounts/capacityPools/volumes) | @@ -25,6 +28,7 @@ This module deploys an Azure NetApp Files Capacity Pool. | Parameter | Type | Description | | :-- | :-- | :-- | | [`name`](#parameter-name) | string | The name of the capacity pool. | +| [`networkFeatures`](#parameter-networkfeatures) | string | Network features available to the volume, or current state of update (Basic/Standard). | | [`size`](#parameter-size) | int | Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104). | **Conditional parameters** @@ -53,6 +57,14 @@ The name of the capacity pool. - Required: Yes - Type: string +### Parameter: `networkFeatures` + +Network features available to the volume, or current state of update (Basic/Standard). + +- Required: No +- Type: string +- Default: `'Standard'` + ### Parameter: `size` Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104). @@ -243,6 +255,7 @@ List of volumnes to create in the capacity pool. | `name` | string | The name of the Capacity Pool. | | `resourceGroupName` | string | The name of the Resource Group the Capacity Pool was created in. | | `resourceId` | string | The resource ID of the Capacity Pool. | +| `volumeResourceId` | string | The resource IDs of the volume created in the capacity pool. | ## Cross-referenced modules diff --git a/avm/res/net-app/net-app-account/capacity-pool/main.bicep b/avm/res/net-app/net-app-account/capacity-pool/main.bicep index 43c4ab6fb2..689feecffe 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/main.bicep +++ b/avm/res/net-app/net-app-account/capacity-pool/main.bicep @@ -23,6 +23,9 @@ param tags object? ]) param serviceLevel string = 'Standard' +@description('Required. Network features available to the volume, or current state of update (Basic/Standard).') +param networkFeatures string = 'Standard' + @description('Required. Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104).') param size int @@ -99,6 +102,28 @@ module capacityPool_volumes 'volume/main.bicep' = [ roleAssignments: contains(volume, 'roleAssignments') ? volume.roleAssignments : [] networkFeatures: volume.?networkFeatures zones: volume.?zones + coolAccess: contains(volume, 'coolAccess') ? volume.coolAccess : false + coolAccessRetrievalPolicy: contains(volume, 'coolAccessRetrievalPolicy') + ? volume.coolAccessRetrievalPolicy + : 'Default' + coolnessPeriod: contains(volume, 'coolnessPeriod') ? volume.coolnessPeriod : 0 + endpointType: contains(volume, 'endpointType') ? volume.endpointType : '' + remoteVolumeRegion: contains(volume, 'remoteVolumeRegion') ? volume.remoteVolumeRegion : '' + remoteVolumeResourceId: contains(volume, 'remoteVolumeResourceId') ? volume.remoteVolumeResourceId : '' + replicationSchedule: contains(volume, 'replicationSchedule') ? volume.replicationSchedule : '' + backupPolicyName: contains(volume, 'backupPolicyName') ? volume.backupPolicyName : 'backupPolicy' + backupPolicyLocation: contains(volume, 'backupPolicyLocation') ? volume.backupPolicyLocation : '' + dailyBackupsToKeep: contains(volume, 'dailyBackupsToKeep') ? volume.dailyBackupsToKeep : 0 + backupEnabled: contains(volume, 'backupEnabled') ? volume.backupEnabled : false + monthlyBackupsToKeep: contains(volume, 'monthlyBackupsToKeep') ? volume.monthlyBackupsToKeep : 0 + weeklyBackupsToKeep: contains(volume, 'weeklyBackupsToKeep') ? volume.weeklyBackupsToKeep : 0 + backupVaultName: contains(volume, 'backupVaultName') ? volume.backupVaultName : 'vault' + backupVaultLocation: contains(volume, 'backupVaultLocation') ? volume.backupVaultLocation : '' + backupName: contains(volume, 'backupName') ? volume.backupName : 'backup' + backupLabel: contains(volume, 'backupLabel') ? volume.backupLabel : '' + snapshotName: contains(volume, 'snapshotName') ? volume.snapshotName : 'snapshot' + useExistingSnapshot: contains(volume, 'useExistingSnapshot') ? volume.useExistingSnapshot : false + volumeResourceId: contains(volume, 'volumeResourceId') ? volume.volumeResourceId : '' } } ] @@ -135,6 +160,9 @@ output resourceGroupName string = resourceGroup().name @description('The location the resource was deployed into.') output location string = capacityPool.location +@description('The resource IDs of the volume created in the capacity pool.') +output volumeResourceId string = (volumes != []) ? capacityPool_volumes[0].outputs.resourceId : '' + // =============== // // Definitions // // =============== // diff --git a/avm/res/net-app/net-app-account/capacity-pool/main.json b/avm/res/net-app/net-app-account/capacity-pool/main.json index c98691eab8..ac99f559bd 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/main.json +++ b/avm/res/net-app/net-app-account/capacity-pool/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.28.1.47646", - "templateHash": "11547939477420611757" + "templateHash": "17205509578682540827" }, "name": "Azure NetApp Files Capacity Pools", "description": "This module deploys an Azure NetApp Files Capacity Pool.", @@ -120,6 +120,13 @@ "description": "Optional. The pool service level." } }, + "networkFeatures": { + "type": "string", + "defaultValue": "Standard", + "metadata": { + "description": "Required. Network features available to the volume, or current state of update (Basic/Standard)." + } + }, "size": { "type": "int", "metadata": { @@ -270,7 +277,27 @@ }, "zones": { "value": "[tryGet(parameters('volumes')[copyIndex()], 'zones')]" - } + }, + "coolAccess": "[if(contains(parameters('volumes')[copyIndex()], 'coolAccess'), createObject('value', parameters('volumes')[copyIndex()].coolAccess), createObject('value', false()))]", + "coolAccessRetrievalPolicy": "[if(contains(parameters('volumes')[copyIndex()], 'coolAccessRetrievalPolicy'), createObject('value', parameters('volumes')[copyIndex()].coolAccessRetrievalPolicy), createObject('value', 'Default'))]", + "coolnessPeriod": "[if(contains(parameters('volumes')[copyIndex()], 'coolnessPeriod'), createObject('value', parameters('volumes')[copyIndex()].coolnessPeriod), createObject('value', 0))]", + "endpointType": "[if(contains(parameters('volumes')[copyIndex()], 'endpointType'), createObject('value', parameters('volumes')[copyIndex()].endpointType), createObject('value', ''))]", + "remoteVolumeRegion": "[if(contains(parameters('volumes')[copyIndex()], 'remoteVolumeRegion'), createObject('value', parameters('volumes')[copyIndex()].remoteVolumeRegion), createObject('value', ''))]", + "remoteVolumeResourceId": "[if(contains(parameters('volumes')[copyIndex()], 'remoteVolumeResourceId'), createObject('value', parameters('volumes')[copyIndex()].remoteVolumeResourceId), createObject('value', ''))]", + "replicationSchedule": "[if(contains(parameters('volumes')[copyIndex()], 'replicationSchedule'), createObject('value', parameters('volumes')[copyIndex()].replicationSchedule), createObject('value', ''))]", + "backupPolicyName": "[if(contains(parameters('volumes')[copyIndex()], 'backupPolicyName'), createObject('value', parameters('volumes')[copyIndex()].backupPolicyName), createObject('value', 'backupPolicy'))]", + "backupPolicyLocation": "[if(contains(parameters('volumes')[copyIndex()], 'backupPolicyLocation'), createObject('value', parameters('volumes')[copyIndex()].backupPolicyLocation), createObject('value', ''))]", + "dailyBackupsToKeep": "[if(contains(parameters('volumes')[copyIndex()], 'dailyBackupsToKeep'), createObject('value', parameters('volumes')[copyIndex()].dailyBackupsToKeep), createObject('value', 0))]", + "backupEnabled": "[if(contains(parameters('volumes')[copyIndex()], 'backupEnabled'), createObject('value', parameters('volumes')[copyIndex()].backupEnabled), createObject('value', false()))]", + "monthlyBackupsToKeep": "[if(contains(parameters('volumes')[copyIndex()], 'monthlyBackupsToKeep'), createObject('value', parameters('volumes')[copyIndex()].monthlyBackupsToKeep), createObject('value', 0))]", + "weeklyBackupsToKeep": "[if(contains(parameters('volumes')[copyIndex()], 'weeklyBackupsToKeep'), createObject('value', parameters('volumes')[copyIndex()].weeklyBackupsToKeep), createObject('value', 0))]", + "backupVaultName": "[if(contains(parameters('volumes')[copyIndex()], 'backupVaultName'), createObject('value', parameters('volumes')[copyIndex()].backupVaultName), createObject('value', 'vault'))]", + "backupVaultLocation": "[if(contains(parameters('volumes')[copyIndex()], 'backupVaultLocation'), createObject('value', parameters('volumes')[copyIndex()].backupVaultLocation), createObject('value', ''))]", + "backupName": "[if(contains(parameters('volumes')[copyIndex()], 'backupName'), createObject('value', parameters('volumes')[copyIndex()].backupName), createObject('value', 'backup'))]", + "backupLabel": "[if(contains(parameters('volumes')[copyIndex()], 'backupLabel'), createObject('value', parameters('volumes')[copyIndex()].backupLabel), createObject('value', ''))]", + "snapshotName": "[if(contains(parameters('volumes')[copyIndex()], 'snapshotName'), createObject('value', parameters('volumes')[copyIndex()].snapshotName), createObject('value', 'snapshot'))]", + "useExistingSnapshot": "[if(contains(parameters('volumes')[copyIndex()], 'useExistingSnapshot'), createObject('value', parameters('volumes')[copyIndex()].useExistingSnapshot), createObject('value', false()))]", + "volumeResourceId": "[if(contains(parameters('volumes')[copyIndex()], 'volumeResourceId'), createObject('value', parameters('volumes')[copyIndex()].volumeResourceId), createObject('value', ''))]" }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -280,7 +307,7 @@ "_generator": { "name": "bicep", "version": "0.28.1.47646", - "templateHash": "1750388407131447050" + "templateHash": "12491316968044537439" }, "name": "Azure NetApp Files Capacity Pool Volumes", "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", @@ -367,6 +394,132 @@ "description": "Conditional. The name of the parent capacity pool. Required if the template is used in a standalone deployment." } }, + "coolAccess": { + "type": "bool", + "metadata": { + "description": "Optional. If enabled (true) the pool can contain cool Access enabled volumes." + } + }, + "coolnessPeriod": { + "type": "int", + "metadata": { + "description": "Optional. Specifies the number of days after which data that is not accessed by clients will be tiered." + } + }, + "coolAccessRetrievalPolicy": { + "type": "string", + "defaultValue": "Default", + "metadata": { + "description": "Optional. determines the data retrieval behavior from the cool tier to standard storage based on the read pattern for cool access enabled volumes (Default/Never/Read)." + } + }, + "endpointType": { + "type": "string", + "metadata": { + "description": "Optional. Indicates whether the local volume is the source or destination for the Volume Replication (src/dst)." + } + }, + "remoteVolumeRegion": { + "type": "string", + "metadata": { + "description": "Optional. The remote region for the other end of the Volume Replication." + } + }, + "remoteVolumeResourceId": { + "type": "string", + "metadata": { + "description": "Optional. The resource ID of the remote volume." + } + }, + "replicationSchedule": { + "type": "string", + "metadata": { + "description": "Optional. The replication schedule for the volume." + } + }, + "backupEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether the backup policy is enabled." + } + }, + "backupPolicyName": { + "type": "string", + "defaultValue": "backupPolicy", + "metadata": { + "description": "Optional. The name of the backup policy." + } + }, + "backupPolicyLocation": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location of the backup policy." + } + }, + "dailyBackupsToKeep": { + "type": "int", + "metadata": { + "description": "Optional. The daily backups to keep." + } + }, + "monthlyBackupsToKeep": { + "type": "int", + "metadata": { + "description": "Optional. The monthly backups to keep." + } + }, + "weeklyBackupsToKeep": { + "type": "int", + "metadata": { + "description": "Optional. The weekly backups to keep." + } + }, + "backupVaultName": { + "type": "string", + "defaultValue": "vault", + "metadata": { + "description": "Optional. The name of the backup vault." + } + }, + "backupVaultLocation": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location of the backup vault." + } + }, + "backupName": { + "type": "string", + "metadata": { + "description": "Optional. The name of the backup." + } + }, + "backupLabel": { + "type": "string", + "metadata": { + "description": "Optional. The label of the backup." + } + }, + "useExistingSnapshot": { + "type": "bool", + "metadata": { + "description": "Optional. Indicates whether to use an existing snapshot." + } + }, + "snapshotName": { + "type": "string", + "metadata": { + "description": "Optional. The name of the snapshot." + } + }, + "volumeResourceId": { + "type": "string", + "metadata": { + "description": "Optional. The resource ID of the volume." + } + }, "name": { "type": "string", "metadata": { @@ -485,20 +638,49 @@ "apiVersion": "2023-07-01", "name": "[format('{0}/{1}/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", "location": "[parameters('location')]", - "properties": { - "serviceLevel": "[parameters('serviceLevel')]", - "creationToken": "[parameters('creationToken')]", - "usageThreshold": "[parameters('usageThreshold')]", - "protocolTypes": "[parameters('protocolTypes')]", - "subnetId": "[parameters('subnetResourceId')]", - "networkFeatures": "[parameters('networkFeatures')]", - "exportPolicy": "[if(not(empty(parameters('exportPolicyRules'))), createObject('rules', parameters('exportPolicyRules')), null())]" - }, + "properties": "[shallowMerge(createArray(createObject('coolAccess', parameters('coolAccess'), 'coolAccessRetrievalPolicy', parameters('coolAccessRetrievalPolicy'), 'coolnessPeriod', parameters('coolnessPeriod')), if(not(equals(parameters('endpointType'), '')), createObject('dataProtection', createObject('replication', createObject('endpointType', parameters('endpointType'), 'remoteVolumeRegion', parameters('remoteVolumeRegion'), 'remoteVolumeResourceId', parameters('remoteVolumeResourceId'), 'replicationSchedule', parameters('replicationSchedule')))), createObject()), createObject('networkFeatures', parameters('networkFeatures'), 'serviceLevel', parameters('serviceLevel'), 'creationToken', parameters('creationToken'), 'usageThreshold', parameters('usageThreshold'), 'protocolTypes', parameters('protocolTypes'), 'subnetId', parameters('subnetResourceId'), 'exportPolicy', if(not(empty(parameters('exportPolicyRules'))), createObject('rules', parameters('exportPolicyRules')), null()))))]", "zones": "[parameters('zones')]", "dependsOn": [ "netAppAccount::capacityPool" ] }, + "backupPolicies": { + "condition": "[parameters('backupEnabled')]", + "type": "Microsoft.NetApp/netAppAccounts/backupPolicies", + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('backupPolicyName'))]", + "location": "[parameters('backupPolicyLocation')]", + "properties": { + "dailyBackupsToKeep": "[parameters('dailyBackupsToKeep')]", + "enabled": "[parameters('backupEnabled')]", + "monthlyBackupsToKeep": "[parameters('monthlyBackupsToKeep')]", + "weeklyBackupsToKeep": "[parameters('weeklyBackupsToKeep')]" + }, + "dependsOn": [ + "netAppAccount" + ] + }, + "backupVaults": { + "condition": "[parameters('backupEnabled')]", + "type": "Microsoft.NetApp/netAppAccounts/backupVaults", + "apiVersion": "2023-05-01-preview", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('backupVaultName'))]", + "location": "[parameters('backupVaultLocation')]", + "properties": {}, + "dependsOn": [ + "netAppAccount" + ] + }, + "backups": { + "condition": "[parameters('backupEnabled')]", + "type": "Microsoft.NetApp/netAppAccounts/backupVaults/backups", + "apiVersion": "2023-05-01-preview", + "name": "[format('{0}/{1}/{2}', parameters('netAppAccountName'), parameters('backupVaultName'), parameters('backupName'))]", + "properties": "[if(parameters('backupEnabled'), createObject('label', parameters('backupLabel'), 'snapshotName', parameters('snapshotName'), 'useExistingSnapshot', parameters('useExistingSnapshot'), 'volumeResourceId', parameters('volumeResourceId')), createObject())]", + "dependsOn": [ + "backupVaults" + ] + }, "volume_roleAssignments": { "copy": { "name": "volume_roleAssignments", @@ -588,6 +770,13 @@ "description": "The location the resource was deployed into." }, "value": "[reference('capacityPool', '2023-07-01', 'full').location]" + }, + "volumeResourceId": { + "type": "string", + "metadata": { + "description": "The resource IDs of the volume created in the capacity pool." + }, + "value": "[if(not(equals(parameters('volumes'), createArray())), reference(format('capacityPool_volumes[{0}]', 0)).outputs.resourceId.value, '')]" } } } \ No newline at end of file diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/README.md b/avm/res/net-app/net-app-account/capacity-pool/volume/README.md index b410a65573..b5a0e4c246 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/volume/README.md +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/README.md @@ -15,6 +15,9 @@ This module deploys an Azure NetApp Files Capacity Pool Volume. | Resource Type | API Version | | :-- | :-- | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.NetApp/netAppAccounts/backupPolicies` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-11-01/netAppAccounts/backupPolicies) | +| `Microsoft.NetApp/netAppAccounts/backupVaults` | [2023-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-05-01-preview/netAppAccounts/backupVaults) | +| `Microsoft.NetApp/netAppAccounts/backupVaults/backups` | [2023-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-05-01-preview/netAppAccounts/backupVaults/backups) | | `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | [2023-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2023-07-01/netAppAccounts/capacityPools/volumes) | ## Parameters @@ -38,13 +41,33 @@ This module deploys an Azure NetApp Files Capacity Pool Volume. | Parameter | Type | Description | | :-- | :-- | :-- | +| [`backupEnabled`](#parameter-backupenabled) | bool | Indicates whether the backup policy is enabled. | +| [`backupLabel`](#parameter-backuplabel) | string | The label of the backup. | +| [`backupName`](#parameter-backupname) | string | The name of the backup. | +| [`backupPolicyLocation`](#parameter-backuppolicylocation) | string | The location of the backup policy. | +| [`backupPolicyName`](#parameter-backuppolicyname) | string | The name of the backup policy. | +| [`backupVaultLocation`](#parameter-backupvaultlocation) | string | The location of the backup vault. | +| [`backupVaultName`](#parameter-backupvaultname) | string | The name of the backup vault. | +| [`coolAccess`](#parameter-coolaccess) | bool | If enabled (true) the pool can contain cool Access enabled volumes. | +| [`coolAccessRetrievalPolicy`](#parameter-coolaccessretrievalpolicy) | string | determines the data retrieval behavior from the cool tier to standard storage based on the read pattern for cool access enabled volumes (Default/Never/Read). | +| [`coolnessPeriod`](#parameter-coolnessperiod) | int | Specifies the number of days after which data that is not accessed by clients will be tiered. | | [`creationToken`](#parameter-creationtoken) | string | A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription. | +| [`dailyBackupsToKeep`](#parameter-dailybackupstokeep) | int | The daily backups to keep. | +| [`endpointType`](#parameter-endpointtype) | string | Indicates whether the local volume is the source or destination for the Volume Replication (src/dst). | | [`exportPolicyRules`](#parameter-exportpolicyrules) | array | Export policy rules. | | [`location`](#parameter-location) | string | Location of the pool volume. | +| [`monthlyBackupsToKeep`](#parameter-monthlybackupstokeep) | int | The monthly backups to keep. | | [`networkFeatures`](#parameter-networkfeatures) | string | Network feature for the volume. | | [`protocolTypes`](#parameter-protocoltypes) | array | Set of protocol types. | +| [`remoteVolumeRegion`](#parameter-remotevolumeregion) | string | The remote region for the other end of the Volume Replication. | +| [`remoteVolumeResourceId`](#parameter-remotevolumeresourceid) | string | The resource ID of the remote volume. | +| [`replicationSchedule`](#parameter-replicationschedule) | string | The replication schedule for the volume. | | [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | | [`serviceLevel`](#parameter-servicelevel) | string | The pool service level. Must match the one of the parent capacity pool. | +| [`snapshotName`](#parameter-snapshotname) | string | The name of the snapshot. | +| [`useExistingSnapshot`](#parameter-useexistingsnapshot) | bool | Indicates whether to use an existing snapshot. | +| [`volumeResourceId`](#parameter-volumeresourceid) | string | The resource ID of the volume. | +| [`weeklyBackupsToKeep`](#parameter-weeklybackupstokeep) | int | The weekly backups to keep. | | [`zones`](#parameter-zones) | array | Zone where the volume will be placed. | ### Parameter: `name` @@ -82,6 +105,82 @@ The name of the parent NetApp account. Required if the template is used in a sta - Required: Yes - Type: string +### Parameter: `backupEnabled` + +Indicates whether the backup policy is enabled. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `backupLabel` + +The label of the backup. + +- Required: Yes +- Type: string + +### Parameter: `backupName` + +The name of the backup. + +- Required: Yes +- Type: string + +### Parameter: `backupPolicyLocation` + +The location of the backup policy. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `backupPolicyName` + +The name of the backup policy. + +- Required: No +- Type: string +- Default: `'backupPolicy'` + +### Parameter: `backupVaultLocation` + +The location of the backup vault. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `backupVaultName` + +The name of the backup vault. + +- Required: No +- Type: string +- Default: `'vault'` + +### Parameter: `coolAccess` + +If enabled (true) the pool can contain cool Access enabled volumes. + +- Required: Yes +- Type: bool + +### Parameter: `coolAccessRetrievalPolicy` + +determines the data retrieval behavior from the cool tier to standard storage based on the read pattern for cool access enabled volumes (Default/Never/Read). + +- Required: No +- Type: string +- Default: `'Default'` + +### Parameter: `coolnessPeriod` + +Specifies the number of days after which data that is not accessed by clients will be tiered. + +- Required: Yes +- Type: int + ### Parameter: `creationToken` A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription. @@ -90,6 +189,20 @@ A unique file path for the volume. This is the name of the volume export. A volu - Type: string - Default: `[parameters('name')]` +### Parameter: `dailyBackupsToKeep` + +The daily backups to keep. + +- Required: Yes +- Type: int + +### Parameter: `endpointType` + +Indicates whether the local volume is the source or destination for the Volume Replication (src/dst). + +- Required: Yes +- Type: string + ### Parameter: `exportPolicyRules` Export policy rules. @@ -106,6 +219,13 @@ Location of the pool volume. - Type: string - Default: `[resourceGroup().location]` +### Parameter: `monthlyBackupsToKeep` + +The monthly backups to keep. + +- Required: Yes +- Type: int + ### Parameter: `networkFeatures` Network feature for the volume. @@ -131,6 +251,27 @@ Set of protocol types. - Type: array - Default: `[]` +### Parameter: `remoteVolumeRegion` + +The remote region for the other end of the Volume Replication. + +- Required: Yes +- Type: string + +### Parameter: `remoteVolumeResourceId` + +The resource ID of the remote volume. + +- Required: Yes +- Type: string + +### Parameter: `replicationSchedule` + +The replication schedule for the volume. + +- Required: Yes +- Type: string + ### Parameter: `roleAssignments` Array of role assignments to create. @@ -237,6 +378,34 @@ The pool service level. Must match the one of the parent capacity pool. ] ``` +### Parameter: `snapshotName` + +The name of the snapshot. + +- Required: Yes +- Type: string + +### Parameter: `useExistingSnapshot` + +Indicates whether to use an existing snapshot. + +- Required: Yes +- Type: bool + +### Parameter: `volumeResourceId` + +The resource ID of the volume. + +- Required: Yes +- Type: string + +### Parameter: `weeklyBackupsToKeep` + +The weekly backups to keep. + +- Required: Yes +- Type: int + ### Parameter: `zones` Zone where the volume will be placed. diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep b/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep index 4f1a83620d..21e4920bb1 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep @@ -8,6 +8,66 @@ param netAppAccountName string @description('Conditional. The name of the parent capacity pool. Required if the template is used in a standalone deployment.') param capacityPoolName string +@description('Optional. If enabled (true) the pool can contain cool Access enabled volumes.') +param coolAccess bool + +@description('Optional. Specifies the number of days after which data that is not accessed by clients will be tiered.') +param coolnessPeriod int + +@description('Optional. determines the data retrieval behavior from the cool tier to standard storage based on the read pattern for cool access enabled volumes (Default/Never/Read).') +param coolAccessRetrievalPolicy string = 'Default' + +@description('Optional. Indicates whether the local volume is the source or destination for the Volume Replication (src/dst).') +param endpointType string + +@description('Optional. The remote region for the other end of the Volume Replication.') +param remoteVolumeRegion string + +@description('Optional. The resource ID of the remote volume.') +param remoteVolumeResourceId string + +@description('Optional. The replication schedule for the volume.') +param replicationSchedule string + +@description('Optional. Indicates whether the backup policy is enabled.') +param backupEnabled bool = false + +@description('Optional. The name of the backup policy.') +param backupPolicyName string = 'backupPolicy' + +@description('Optional. The location of the backup policy.') +param backupPolicyLocation string = resourceGroup().location + +@description('Optional. The daily backups to keep.') +param dailyBackupsToKeep int + +@description('Optional. The monthly backups to keep.') +param monthlyBackupsToKeep int + +@description('Optional. The weekly backups to keep.') +param weeklyBackupsToKeep int + +@description('Optional. The name of the backup vault.') +param backupVaultName string = 'vault' + +@description('Optional. The location of the backup vault.') +param backupVaultLocation string = resourceGroup().location + +@description('Optional. The name of the backup.') +param backupName string + +@description('Optional. The label of the backup.') +param backupLabel string + +@description('Optional. Indicates whether to use an existing snapshot.') +param useExistingSnapshot bool + +@description('Optional. The name of the snapshot.') +param snapshotName string + +@description('Optional. The resource ID of the volume.') +param volumeResourceId string + @description('Required. The name of the pool volume.') param name string @@ -80,12 +140,27 @@ resource volume 'Microsoft.NetApp/netAppAccounts/capacityPools/volumes@2023-07-0 parent: netAppAccount::capacityPool location: location properties: { + coolAccess: coolAccess + coolAccessRetrievalPolicy: coolAccessRetrievalPolicy + coolnessPeriod: coolnessPeriod + ...(endpointType != '' + ? { + dataProtection: { + replication: { + endpointType: endpointType + remoteVolumeRegion: remoteVolumeRegion + remoteVolumeResourceId: remoteVolumeResourceId + replicationSchedule: replicationSchedule + } + } + } + : {}) + networkFeatures: networkFeatures serviceLevel: serviceLevel creationToken: creationToken usageThreshold: usageThreshold protocolTypes: protocolTypes subnetId: subnetResourceId - networkFeatures: networkFeatures exportPolicy: !empty(exportPolicyRules) ? { rules: exportPolicyRules @@ -95,6 +170,38 @@ resource volume 'Microsoft.NetApp/netAppAccounts/capacityPools/volumes@2023-07-0 zones: zones } +resource backupPolicies 'Microsoft.NetApp/netAppAccounts/backupPolicies@2023-11-01' = if (backupEnabled) { + name: backupPolicyName + parent: netAppAccount + location: backupPolicyLocation + properties: { + dailyBackupsToKeep: dailyBackupsToKeep + enabled: backupEnabled + monthlyBackupsToKeep: monthlyBackupsToKeep + weeklyBackupsToKeep: weeklyBackupsToKeep + } +} + +resource backupVaults 'Microsoft.NetApp/netAppAccounts/backupVaults@2023-05-01-preview' = if (backupEnabled) { + name: backupVaultName + parent: netAppAccount + location: backupVaultLocation + properties: {} +} + +resource backups 'Microsoft.NetApp/netAppAccounts/backupVaults/backups@2023-05-01-preview' = if (backupEnabled) { + name: backupName + parent: backupVaults + properties: backupEnabled + ? { + label: backupLabel + snapshotName: snapshotName + useExistingSnapshot: useExistingSnapshot + volumeResourceId: volumeResourceId + } + : {} +} + resource volume_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ for (roleAssignment, index) in (roleAssignments ?? []): { name: guid(volume.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/main.json b/avm/res/net-app/net-app-account/capacity-pool/volume/main.json index 1ffcd03603..66659fda12 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/volume/main.json +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.28.1.47646", - "templateHash": "1750388407131447050" + "templateHash": "12491316968044537439" }, "name": "Azure NetApp Files Capacity Pool Volumes", "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", @@ -93,6 +93,132 @@ "description": "Conditional. The name of the parent capacity pool. Required if the template is used in a standalone deployment." } }, + "coolAccess": { + "type": "bool", + "metadata": { + "description": "Optional. If enabled (true) the pool can contain cool Access enabled volumes." + } + }, + "coolnessPeriod": { + "type": "int", + "metadata": { + "description": "Optional. Specifies the number of days after which data that is not accessed by clients will be tiered." + } + }, + "coolAccessRetrievalPolicy": { + "type": "string", + "defaultValue": "Default", + "metadata": { + "description": "Optional. determines the data retrieval behavior from the cool tier to standard storage based on the read pattern for cool access enabled volumes (Default/Never/Read)." + } + }, + "endpointType": { + "type": "string", + "metadata": { + "description": "Optional. Indicates whether the local volume is the source or destination for the Volume Replication (src/dst)." + } + }, + "remoteVolumeRegion": { + "type": "string", + "metadata": { + "description": "Optional. The remote region for the other end of the Volume Replication." + } + }, + "remoteVolumeResourceId": { + "type": "string", + "metadata": { + "description": "Optional. The resource ID of the remote volume." + } + }, + "replicationSchedule": { + "type": "string", + "metadata": { + "description": "Optional. The replication schedule for the volume." + } + }, + "backupEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether the backup policy is enabled." + } + }, + "backupPolicyName": { + "type": "string", + "defaultValue": "backupPolicy", + "metadata": { + "description": "Optional. The name of the backup policy." + } + }, + "backupPolicyLocation": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location of the backup policy." + } + }, + "dailyBackupsToKeep": { + "type": "int", + "metadata": { + "description": "Optional. The daily backups to keep." + } + }, + "monthlyBackupsToKeep": { + "type": "int", + "metadata": { + "description": "Optional. The monthly backups to keep." + } + }, + "weeklyBackupsToKeep": { + "type": "int", + "metadata": { + "description": "Optional. The weekly backups to keep." + } + }, + "backupVaultName": { + "type": "string", + "defaultValue": "vault", + "metadata": { + "description": "Optional. The name of the backup vault." + } + }, + "backupVaultLocation": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location of the backup vault." + } + }, + "backupName": { + "type": "string", + "metadata": { + "description": "Optional. The name of the backup." + } + }, + "backupLabel": { + "type": "string", + "metadata": { + "description": "Optional. The label of the backup." + } + }, + "useExistingSnapshot": { + "type": "bool", + "metadata": { + "description": "Optional. Indicates whether to use an existing snapshot." + } + }, + "snapshotName": { + "type": "string", + "metadata": { + "description": "Optional. The name of the snapshot." + } + }, + "volumeResourceId": { + "type": "string", + "metadata": { + "description": "Optional. The resource ID of the volume." + } + }, "name": { "type": "string", "metadata": { @@ -211,20 +337,49 @@ "apiVersion": "2023-07-01", "name": "[format('{0}/{1}/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", "location": "[parameters('location')]", - "properties": { - "serviceLevel": "[parameters('serviceLevel')]", - "creationToken": "[parameters('creationToken')]", - "usageThreshold": "[parameters('usageThreshold')]", - "protocolTypes": "[parameters('protocolTypes')]", - "subnetId": "[parameters('subnetResourceId')]", - "networkFeatures": "[parameters('networkFeatures')]", - "exportPolicy": "[if(not(empty(parameters('exportPolicyRules'))), createObject('rules', parameters('exportPolicyRules')), null())]" - }, + "properties": "[shallowMerge(createArray(createObject('coolAccess', parameters('coolAccess'), 'coolAccessRetrievalPolicy', parameters('coolAccessRetrievalPolicy'), 'coolnessPeriod', parameters('coolnessPeriod')), if(not(equals(parameters('endpointType'), '')), createObject('dataProtection', createObject('replication', createObject('endpointType', parameters('endpointType'), 'remoteVolumeRegion', parameters('remoteVolumeRegion'), 'remoteVolumeResourceId', parameters('remoteVolumeResourceId'), 'replicationSchedule', parameters('replicationSchedule')))), createObject()), createObject('networkFeatures', parameters('networkFeatures'), 'serviceLevel', parameters('serviceLevel'), 'creationToken', parameters('creationToken'), 'usageThreshold', parameters('usageThreshold'), 'protocolTypes', parameters('protocolTypes'), 'subnetId', parameters('subnetResourceId'), 'exportPolicy', if(not(empty(parameters('exportPolicyRules'))), createObject('rules', parameters('exportPolicyRules')), null()))))]", "zones": "[parameters('zones')]", "dependsOn": [ "netAppAccount::capacityPool" ] }, + "backupPolicies": { + "condition": "[parameters('backupEnabled')]", + "type": "Microsoft.NetApp/netAppAccounts/backupPolicies", + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('backupPolicyName'))]", + "location": "[parameters('backupPolicyLocation')]", + "properties": { + "dailyBackupsToKeep": "[parameters('dailyBackupsToKeep')]", + "enabled": "[parameters('backupEnabled')]", + "monthlyBackupsToKeep": "[parameters('monthlyBackupsToKeep')]", + "weeklyBackupsToKeep": "[parameters('weeklyBackupsToKeep')]" + }, + "dependsOn": [ + "netAppAccount" + ] + }, + "backupVaults": { + "condition": "[parameters('backupEnabled')]", + "type": "Microsoft.NetApp/netAppAccounts/backupVaults", + "apiVersion": "2023-05-01-preview", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('backupVaultName'))]", + "location": "[parameters('backupVaultLocation')]", + "properties": {}, + "dependsOn": [ + "netAppAccount" + ] + }, + "backups": { + "condition": "[parameters('backupEnabled')]", + "type": "Microsoft.NetApp/netAppAccounts/backupVaults/backups", + "apiVersion": "2023-05-01-preview", + "name": "[format('{0}/{1}/{2}', parameters('netAppAccountName'), parameters('backupVaultName'), parameters('backupName'))]", + "properties": "[if(parameters('backupEnabled'), createObject('label', parameters('backupLabel'), 'snapshotName', parameters('snapshotName'), 'useExistingSnapshot', parameters('useExistingSnapshot'), 'volumeResourceId', parameters('volumeResourceId')), createObject())]", + "dependsOn": [ + "backupVaults" + ] + }, "volume_roleAssignments": { "copy": { "name": "volume_roleAssignments", diff --git a/avm/res/net-app/net-app-account/main.bicep b/avm/res/net-app/net-app-account/main.bicep index d1fc1c9872..871bff5768 100644 --- a/avm/res/net-app/net-app-account/main.bicep +++ b/avm/res/net-app/net-app-account/main.bicep @@ -5,6 +5,9 @@ metadata owner = 'Azure/module-maintainers' @description('Required. The name of the NetApp account.') param name string +@description('Optional. Name of the active directory host as part of Kerberos Realm used for Kerberos authentication.') +param adName string = '' + @description('Optional. Enable AES encryption on the SMB Server.') param aesEncryption bool = false @@ -27,6 +30,9 @@ param domainJoinOU string = '' @description('Optional. Required if domainName is specified. Comma separated list of DNS server IP addresses (IPv4 only) required for the Active Directory (AD) domain join and SMB authentication operations to succeed.') param dnsServers string = '' +@description('Optional. Specifies whether encryption should be used for communication between SMB server and domain controller (DC). SMB3 only.') +param encryptDCConnections bool = false + @description('Optional. Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes.') param smbServerNamePrefix string = '' @@ -39,6 +45,12 @@ param managedIdentities managedIdentitiesType @description('Optional. Array of role assignments to create.') param roleAssignments roleAssignmentType +@description('Optional. Kerberos Key Distribution Center (KDC) as part of Kerberos Realm used for Kerberos authentication.') +param kdcIP string = '' + +@description('Optional. Specifies whether to use TLS when NFS (with/without Kerberos) and SMB volumes communicate with an LDAP server. A server root CA certificate must be uploaded if enabled (serverRootCACertificate).') +param ldapOverTLS bool = false + @description('Optional. Specifies whether or not the LDAP traffic needs to be signed.') param ldapSigning bool = false @@ -48,6 +60,9 @@ param location string = resourceGroup().location @description('Optional. The lock settings of the service.') param lock lockType +@description('Optional. A server Root certificate is required of ldapOverTLS is enabled.') +param serverRootCACertificate string = '' + @description('Optional. Tags for all resources.') param tags object? @@ -56,12 +71,17 @@ param enableTelemetry bool = true var activeDirectoryConnectionProperties = [ { + adName: !empty(domainName) ? adName : null aesEncryption: !empty(domainName) ? aesEncryption : false username: !empty(domainName) ? domainJoinUser : null password: !empty(domainName) ? domainJoinPassword : null domain: !empty(domainName) ? domainName : null dns: !empty(domainName) ? dnsServers : null + encryptDCConnections: !empty(domainName) ? encryptDCConnections : false + kdcIP: !empty(domainName) ? kdcIP : null + ldapOverTLS: !empty(domainName) ? ldapOverTLS : false ldapSigning: !empty(domainName) ? ldapSigning : false + serverRootCACertificate: !empty(domainName) ? serverRootCACertificate : null smbServerName: !empty(domainName) ? smbServerNamePrefix : null organizationalUnit: !empty(domainJoinOU) ? domainJoinOU : null } @@ -94,8 +114,7 @@ var builtInRoleNames = { ) } -#disable-next-line no-deployments-resources -resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableTelemetry) { +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.netapp-netappaccount.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' properties: { mode: 'Incremental' @@ -220,6 +239,9 @@ output resourceGroupName string = resourceGroup().name @description('The location the resource was deployed into.') output location string = netAppAccount.location +@description('The resource IDs of the volume created in the capacity pool.') +output volumeResourceId string = (capacityPools != []) ? netAppAccount_capacityPools[0].outputs.volumeResourceId : '' + // =============== // // Definitions // // =============== // diff --git a/avm/res/net-app/net-app-account/main.json b/avm/res/net-app/net-app-account/main.json index b62c97781a..1e78985149 100644 --- a/avm/res/net-app/net-app-account/main.json +++ b/avm/res/net-app/net-app-account/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.28.1.47646", - "templateHash": "9340235939890285176" + "templateHash": "818996722015925588" }, "name": "Azure NetApp Files", "description": "This module deploys an Azure NetApp File.", @@ -159,6 +159,13 @@ "description": "Required. The name of the NetApp account." } }, + "adName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the active directory host as part of Kerberos Realm used for Kerberos authentication." + } + }, "aesEncryption": { "type": "bool", "defaultValue": false, @@ -207,6 +214,13 @@ "description": "Optional. Required if domainName is specified. Comma separated list of DNS server IP addresses (IPv4 only) required for the Active Directory (AD) domain join and SMB authentication operations to succeed." } }, + "encryptDCConnections": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether encryption should be used for communication between SMB server and domain controller (DC). SMB3 only." + } + }, "smbServerNamePrefix": { "type": "string", "defaultValue": "", @@ -233,6 +247,20 @@ "description": "Optional. Array of role assignments to create." } }, + "kdcIP": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Kerberos Key Distribution Center (KDC) as part of Kerberos Realm used for Kerberos authentication." + } + }, + "ldapOverTLS": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether to use TLS when NFS (with/without Kerberos) and SMB volumes communicate with an LDAP server. A server root CA certificate must be uploaded if enabled (serverRootCACertificate)." + } + }, "ldapSigning": { "type": "bool", "defaultValue": false, @@ -253,6 +281,13 @@ "description": "Optional. The lock settings of the service." } }, + "serverRootCACertificate": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. A server Root certificate is required of ldapOverTLS is enabled." + } + }, "tags": { "type": "object", "nullable": true, @@ -271,12 +306,17 @@ "variables": { "activeDirectoryConnectionProperties": [ { + "adName": "[if(not(empty(parameters('domainName'))), parameters('adName'), null())]", "aesEncryption": "[if(not(empty(parameters('domainName'))), parameters('aesEncryption'), false())]", "username": "[if(not(empty(parameters('domainName'))), parameters('domainJoinUser'), null())]", "password": "[if(not(empty(parameters('domainName'))), parameters('domainJoinPassword'), null())]", "domain": "[if(not(empty(parameters('domainName'))), parameters('domainName'), null())]", "dns": "[if(not(empty(parameters('domainName'))), parameters('dnsServers'), null())]", + "encryptDCConnections": "[if(not(empty(parameters('domainName'))), parameters('encryptDCConnections'), false())]", + "kdcIP": "[if(not(empty(parameters('domainName'))), parameters('kdcIP'), null())]", + "ldapOverTLS": "[if(not(empty(parameters('domainName'))), parameters('ldapOverTLS'), false())]", "ldapSigning": "[if(not(empty(parameters('domainName'))), parameters('ldapSigning'), false())]", + "serverRootCACertificate": "[if(not(empty(parameters('domainName'))), parameters('serverRootCACertificate'), null())]", "smbServerName": "[if(not(empty(parameters('domainName'))), parameters('smbServerNamePrefix'), null())]", "organizationalUnit": "[if(not(empty(parameters('domainJoinOU'))), parameters('domainJoinOU'), null())]" } @@ -307,7 +347,7 @@ "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2024-03-01", + "apiVersion": "2023-07-01", "name": "[format('46d3xbcp.res.netapp-netappaccount.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", @@ -438,7 +478,7 @@ "_generator": { "name": "bicep", "version": "0.28.1.47646", - "templateHash": "11547939477420611757" + "templateHash": "17205509578682540827" }, "name": "Azure NetApp Files Capacity Pools", "description": "This module deploys an Azure NetApp Files Capacity Pool.", @@ -552,6 +592,13 @@ "description": "Optional. The pool service level." } }, + "networkFeatures": { + "type": "string", + "defaultValue": "Standard", + "metadata": { + "description": "Required. Network features available to the volume, or current state of update (Basic/Standard)." + } + }, "size": { "type": "int", "metadata": { @@ -702,7 +749,27 @@ }, "zones": { "value": "[tryGet(parameters('volumes')[copyIndex()], 'zones')]" - } + }, + "coolAccess": "[if(contains(parameters('volumes')[copyIndex()], 'coolAccess'), createObject('value', parameters('volumes')[copyIndex()].coolAccess), createObject('value', false()))]", + "coolAccessRetrievalPolicy": "[if(contains(parameters('volumes')[copyIndex()], 'coolAccessRetrievalPolicy'), createObject('value', parameters('volumes')[copyIndex()].coolAccessRetrievalPolicy), createObject('value', 'Default'))]", + "coolnessPeriod": "[if(contains(parameters('volumes')[copyIndex()], 'coolnessPeriod'), createObject('value', parameters('volumes')[copyIndex()].coolnessPeriod), createObject('value', 0))]", + "endpointType": "[if(contains(parameters('volumes')[copyIndex()], 'endpointType'), createObject('value', parameters('volumes')[copyIndex()].endpointType), createObject('value', ''))]", + "remoteVolumeRegion": "[if(contains(parameters('volumes')[copyIndex()], 'remoteVolumeRegion'), createObject('value', parameters('volumes')[copyIndex()].remoteVolumeRegion), createObject('value', ''))]", + "remoteVolumeResourceId": "[if(contains(parameters('volumes')[copyIndex()], 'remoteVolumeResourceId'), createObject('value', parameters('volumes')[copyIndex()].remoteVolumeResourceId), createObject('value', ''))]", + "replicationSchedule": "[if(contains(parameters('volumes')[copyIndex()], 'replicationSchedule'), createObject('value', parameters('volumes')[copyIndex()].replicationSchedule), createObject('value', ''))]", + "backupPolicyName": "[if(contains(parameters('volumes')[copyIndex()], 'backupPolicyName'), createObject('value', parameters('volumes')[copyIndex()].backupPolicyName), createObject('value', 'backupPolicy'))]", + "backupPolicyLocation": "[if(contains(parameters('volumes')[copyIndex()], 'backupPolicyLocation'), createObject('value', parameters('volumes')[copyIndex()].backupPolicyLocation), createObject('value', ''))]", + "dailyBackupsToKeep": "[if(contains(parameters('volumes')[copyIndex()], 'dailyBackupsToKeep'), createObject('value', parameters('volumes')[copyIndex()].dailyBackupsToKeep), createObject('value', 0))]", + "backupEnabled": "[if(contains(parameters('volumes')[copyIndex()], 'backupEnabled'), createObject('value', parameters('volumes')[copyIndex()].backupEnabled), createObject('value', false()))]", + "monthlyBackupsToKeep": "[if(contains(parameters('volumes')[copyIndex()], 'monthlyBackupsToKeep'), createObject('value', parameters('volumes')[copyIndex()].monthlyBackupsToKeep), createObject('value', 0))]", + "weeklyBackupsToKeep": "[if(contains(parameters('volumes')[copyIndex()], 'weeklyBackupsToKeep'), createObject('value', parameters('volumes')[copyIndex()].weeklyBackupsToKeep), createObject('value', 0))]", + "backupVaultName": "[if(contains(parameters('volumes')[copyIndex()], 'backupVaultName'), createObject('value', parameters('volumes')[copyIndex()].backupVaultName), createObject('value', 'vault'))]", + "backupVaultLocation": "[if(contains(parameters('volumes')[copyIndex()], 'backupVaultLocation'), createObject('value', parameters('volumes')[copyIndex()].backupVaultLocation), createObject('value', ''))]", + "backupName": "[if(contains(parameters('volumes')[copyIndex()], 'backupName'), createObject('value', parameters('volumes')[copyIndex()].backupName), createObject('value', 'backup'))]", + "backupLabel": "[if(contains(parameters('volumes')[copyIndex()], 'backupLabel'), createObject('value', parameters('volumes')[copyIndex()].backupLabel), createObject('value', ''))]", + "snapshotName": "[if(contains(parameters('volumes')[copyIndex()], 'snapshotName'), createObject('value', parameters('volumes')[copyIndex()].snapshotName), createObject('value', 'snapshot'))]", + "useExistingSnapshot": "[if(contains(parameters('volumes')[copyIndex()], 'useExistingSnapshot'), createObject('value', parameters('volumes')[copyIndex()].useExistingSnapshot), createObject('value', false()))]", + "volumeResourceId": "[if(contains(parameters('volumes')[copyIndex()], 'volumeResourceId'), createObject('value', parameters('volumes')[copyIndex()].volumeResourceId), createObject('value', ''))]" }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -712,7 +779,7 @@ "_generator": { "name": "bicep", "version": "0.28.1.47646", - "templateHash": "1750388407131447050" + "templateHash": "12491316968044537439" }, "name": "Azure NetApp Files Capacity Pool Volumes", "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", @@ -799,6 +866,132 @@ "description": "Conditional. The name of the parent capacity pool. Required if the template is used in a standalone deployment." } }, + "coolAccess": { + "type": "bool", + "metadata": { + "description": "Optional. If enabled (true) the pool can contain cool Access enabled volumes." + } + }, + "coolnessPeriod": { + "type": "int", + "metadata": { + "description": "Optional. Specifies the number of days after which data that is not accessed by clients will be tiered." + } + }, + "coolAccessRetrievalPolicy": { + "type": "string", + "defaultValue": "Default", + "metadata": { + "description": "Optional. determines the data retrieval behavior from the cool tier to standard storage based on the read pattern for cool access enabled volumes (Default/Never/Read)." + } + }, + "endpointType": { + "type": "string", + "metadata": { + "description": "Optional. Indicates whether the local volume is the source or destination for the Volume Replication (src/dst)." + } + }, + "remoteVolumeRegion": { + "type": "string", + "metadata": { + "description": "Optional. The remote region for the other end of the Volume Replication." + } + }, + "remoteVolumeResourceId": { + "type": "string", + "metadata": { + "description": "Optional. The resource ID of the remote volume." + } + }, + "replicationSchedule": { + "type": "string", + "metadata": { + "description": "Optional. The replication schedule for the volume." + } + }, + "backupEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether the backup policy is enabled." + } + }, + "backupPolicyName": { + "type": "string", + "defaultValue": "backupPolicy", + "metadata": { + "description": "Optional. The name of the backup policy." + } + }, + "backupPolicyLocation": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location of the backup policy." + } + }, + "dailyBackupsToKeep": { + "type": "int", + "metadata": { + "description": "Optional. The daily backups to keep." + } + }, + "monthlyBackupsToKeep": { + "type": "int", + "metadata": { + "description": "Optional. The monthly backups to keep." + } + }, + "weeklyBackupsToKeep": { + "type": "int", + "metadata": { + "description": "Optional. The weekly backups to keep." + } + }, + "backupVaultName": { + "type": "string", + "defaultValue": "vault", + "metadata": { + "description": "Optional. The name of the backup vault." + } + }, + "backupVaultLocation": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location of the backup vault." + } + }, + "backupName": { + "type": "string", + "metadata": { + "description": "Optional. The name of the backup." + } + }, + "backupLabel": { + "type": "string", + "metadata": { + "description": "Optional. The label of the backup." + } + }, + "useExistingSnapshot": { + "type": "bool", + "metadata": { + "description": "Optional. Indicates whether to use an existing snapshot." + } + }, + "snapshotName": { + "type": "string", + "metadata": { + "description": "Optional. The name of the snapshot." + } + }, + "volumeResourceId": { + "type": "string", + "metadata": { + "description": "Optional. The resource ID of the volume." + } + }, "name": { "type": "string", "metadata": { @@ -917,20 +1110,49 @@ "apiVersion": "2023-07-01", "name": "[format('{0}/{1}/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", "location": "[parameters('location')]", - "properties": { - "serviceLevel": "[parameters('serviceLevel')]", - "creationToken": "[parameters('creationToken')]", - "usageThreshold": "[parameters('usageThreshold')]", - "protocolTypes": "[parameters('protocolTypes')]", - "subnetId": "[parameters('subnetResourceId')]", - "networkFeatures": "[parameters('networkFeatures')]", - "exportPolicy": "[if(not(empty(parameters('exportPolicyRules'))), createObject('rules', parameters('exportPolicyRules')), null())]" - }, + "properties": "[shallowMerge(createArray(createObject('coolAccess', parameters('coolAccess'), 'coolAccessRetrievalPolicy', parameters('coolAccessRetrievalPolicy'), 'coolnessPeriod', parameters('coolnessPeriod')), if(not(equals(parameters('endpointType'), '')), createObject('dataProtection', createObject('replication', createObject('endpointType', parameters('endpointType'), 'remoteVolumeRegion', parameters('remoteVolumeRegion'), 'remoteVolumeResourceId', parameters('remoteVolumeResourceId'), 'replicationSchedule', parameters('replicationSchedule')))), createObject()), createObject('networkFeatures', parameters('networkFeatures'), 'serviceLevel', parameters('serviceLevel'), 'creationToken', parameters('creationToken'), 'usageThreshold', parameters('usageThreshold'), 'protocolTypes', parameters('protocolTypes'), 'subnetId', parameters('subnetResourceId'), 'exportPolicy', if(not(empty(parameters('exportPolicyRules'))), createObject('rules', parameters('exportPolicyRules')), null()))))]", "zones": "[parameters('zones')]", "dependsOn": [ "netAppAccount::capacityPool" ] }, + "backupPolicies": { + "condition": "[parameters('backupEnabled')]", + "type": "Microsoft.NetApp/netAppAccounts/backupPolicies", + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('backupPolicyName'))]", + "location": "[parameters('backupPolicyLocation')]", + "properties": { + "dailyBackupsToKeep": "[parameters('dailyBackupsToKeep')]", + "enabled": "[parameters('backupEnabled')]", + "monthlyBackupsToKeep": "[parameters('monthlyBackupsToKeep')]", + "weeklyBackupsToKeep": "[parameters('weeklyBackupsToKeep')]" + }, + "dependsOn": [ + "netAppAccount" + ] + }, + "backupVaults": { + "condition": "[parameters('backupEnabled')]", + "type": "Microsoft.NetApp/netAppAccounts/backupVaults", + "apiVersion": "2023-05-01-preview", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('backupVaultName'))]", + "location": "[parameters('backupVaultLocation')]", + "properties": {}, + "dependsOn": [ + "netAppAccount" + ] + }, + "backups": { + "condition": "[parameters('backupEnabled')]", + "type": "Microsoft.NetApp/netAppAccounts/backupVaults/backups", + "apiVersion": "2023-05-01-preview", + "name": "[format('{0}/{1}/{2}', parameters('netAppAccountName'), parameters('backupVaultName'), parameters('backupName'))]", + "properties": "[if(parameters('backupEnabled'), createObject('label', parameters('backupLabel'), 'snapshotName', parameters('snapshotName'), 'useExistingSnapshot', parameters('useExistingSnapshot'), 'volumeResourceId', parameters('volumeResourceId')), createObject())]", + "dependsOn": [ + "backupVaults" + ] + }, "volume_roleAssignments": { "copy": { "name": "volume_roleAssignments", @@ -1020,6 +1242,13 @@ "description": "The location the resource was deployed into." }, "value": "[reference('capacityPool', '2023-07-01', 'full').location]" + }, + "volumeResourceId": { + "type": "string", + "metadata": { + "description": "The resource IDs of the volume created in the capacity pool." + }, + "value": "[if(not(equals(parameters('volumes'), createArray())), reference(format('capacityPool_volumes[{0}]', 0)).outputs.resourceId.value, '')]" } } } @@ -1057,6 +1286,13 @@ "description": "The location the resource was deployed into." }, "value": "[reference('netAppAccount', '2023-07-01', 'full').location]" + }, + "volumeResourceId": { + "type": "string", + "metadata": { + "description": "The resource IDs of the volume created in the capacity pool." + }, + "value": "[if(not(equals(parameters('capacityPools'), createArray())), reference(format('netAppAccount_capacityPools[{0}]', 0)).outputs.volumeResourceId.value, '')]" } } } \ No newline at end of file