diff --git a/research-spoke/ResearchSpoke.Doc.ps1 b/research-spoke/ResearchSpoke.Doc.ps1 index 369338d..a1af3ca 100644 --- a/research-spoke/ResearchSpoke.Doc.ps1 +++ b/research-spoke/ResearchSpoke.Doc.ps1 @@ -11,11 +11,26 @@ function global:GetTemplateParameter { $template = Get-Content $Path | ConvertFrom-Json; foreach ($property in $template.parameters.PSObject.Properties) { [PSCustomObject]@{ - Name = $property.Name - Description = $property.Value.metadata.description - Type = $property.Value.type - Required = !("defaultValue" -in $property.Value.PSObject.Properties.Name -or $property.Value.nullable) - DefaultValue = $property.Value.defaultValue + Name = $property.Name + Description = $property.Value.metadata.description + Type = $property.Value.type + Required = !("defaultValue" -in $property.Value.PSObject.Properties.Name -or $property.Value.nullable) + DefaultValue = if ("defaultValue" -in $property.Value.PSObject.Properties.Name) { + if ($property.Value.defaultValue) { $property.Value.defaultValue } else { + switch ($property.Value.type) { + 'string' { '''''' } + 'object' { '{ }' } + 'array' { '()' } + 'bool' { 'false' } + 'securestring' { '''''' } + } + } + } + AllowedValues = if ($property.Value.allowedValues) { + "``$($property.Value.allowedValues -join '`, `')``" + } + MinLength = $property.Value.minLength + MaxLength = $property.Value.maxLength } } } @@ -86,9 +101,33 @@ Document Research-Spoke { "![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square)" } $_.Description - $Details = "- Type: ``$($_.Type)``" + # $Details = "- Type: ``$($_.Type)``" + # if ($_.DefaultValue) { + # $Details += "`n- Default value: ``$($_.DefaultValue)``" + # } + # if ($_.AllowedValues) { + # $Details += "`n- Allowed values: $($_.AllowedValues)" + # } + # if ($_.MinLength) { + # $Details += "`n- Minimum length: $($_.MinLength)" + # } + # if ($_.MaxLength) { + # $Details += "`n- Maximum length: $($_.MaxLength)" + # } + # $Details + + $Details = "Metadata | Value`n---- | ----`nType | $($_.Type)" if ($_.DefaultValue) { - $Details += "`n- Default value: ``$($_.DefaultValue)``" + $Details += "`nDefault value | ``$($_.DefaultValue)``" + } + if ($_.AllowedValues) { + $Details += "`nAllowed values | $($_.AllowedValues)" + } + if ($_.MinLength) { + $Details += "`nMinimum length | $($_.MinLength)" + } + if ($_.MaxLength) { + $Details += "`nMaximum length | $($_.MaxLength)" } $Details } diff --git a/research-spoke/docs/Research-Spoke.md b/research-spoke/docs/Research-Spoke.md index 6ace436..4c7516b 100644 --- a/research-spoke/docs/Research-Spoke.md +++ b/research-spoke/docs/Research-Spoke.md @@ -68,7 +68,9 @@ Parameter name | Required | Description The Azure region where the spoke will be deployed. -- Type: `string` +Metadata | Value +---- | ---- +Type | string ### workloadName @@ -76,7 +78,9 @@ The Azure region where the spoke will be deployed. The name of the research project for the spoke. -- Type: `string` +Metadata | Value +---- | ---- +Type | string ### environment @@ -84,8 +88,12 @@ The name of the research project for the spoke. A maximum four-letter moniker for the environment type, such as 'dev', 'test', etc. -- Type: `string` -- Default value: `dev` +Metadata | Value +---- | ---- +Type | string +Default value | `dev` +Allowed values | `dev`, `test`, `demo`, `prod` +Maximum length | 4 ### tags @@ -93,8 +101,10 @@ A maximum four-letter moniker for the environment type, such as 'dev', 'test', e Tags to apply to each deployed Azure resource. -- Type: `object` -- Default value: `` +Metadata | Value +---- | ---- +Type | object +Default value | `` ### sequence @@ -102,8 +112,10 @@ Tags to apply to each deployed Azure resource. The deployment sequence. Each new sequence number will create a new deployment. -- Type: `int` -- Default value: `1` +Metadata | Value +---- | ---- +Type | int +Default value | `1` ### namingConvention @@ -111,15 +123,19 @@ The deployment sequence. Each new sequence number will create a new deployment. The naming convention to use for Azure resource names. Can contain placeholders for {rtype}, {workloadName}, {location}, {env}, and {seq}. The only supported segment separator is '-'. -- Type: `string` -- Default value: `{workloadName}-{subWorkloadName}-{env}-{rtype}-{loc}-{seq}` +Metadata | Value +---- | ---- +Type | string +Default value | `{workloadName}-{subWorkloadName}-{env}-{rtype}-{loc}-{seq}` ### deploymentTime ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -- Type: `string` -- Default value: `[utcNow()]` +Metadata | Value +---- | ---- +Type | string +Default value | `[utcNow()]` ### encryptionKeyExpirySeed @@ -127,8 +143,10 @@ The naming convention to use for Azure resource names. Can contain placeholders The date and time seed for the expiration of the encryption keys. -- Type: `string` -- Default value: `[utcNow()]` +Metadata | Value +---- | ---- +Type | string +Default value | `[utcNow()]` ### networkAddressSpaces @@ -136,7 +154,10 @@ The date and time seed for the expiration of the encryption keys. Format: [ "192.168.0.0/24", "192.168.10.0/24" ] -- Type: `array` +Metadata | Value +---- | ---- +Type | array +Minimum length | 1 ### hubFirewallIp @@ -144,7 +165,9 @@ Format: [ "192.168.0.0/24", "192.168.10.0/24" ] The private IP address of the hub firewall. -- Type: `string` +Metadata | Value +---- | ---- +Type | string ### customDnsIps @@ -152,8 +175,10 @@ The private IP address of the hub firewall. The DNS IP addresses to use for the virtual network. Defaults to the hub firewall IP. -- Type: `array` -- Default value: `[parameters('hubFirewallIp')]` +Metadata | Value +---- | ---- +Type | array +Default value | `[parameters('hubFirewallIp')]` ### hubVNetResourceId @@ -161,7 +186,9 @@ The DNS IP addresses to use for the virtual network. Defaults to the hub firewal The Azure resource ID of the hub virtual network to peer with. -- Type: `string` +Metadata | Value +---- | ---- +Type | string ### hubPrivateDnsZonesResourceGroupId @@ -169,7 +196,9 @@ The Azure resource ID of the hub virtual network to peer with. The resource ID of the resource group in the hub subscription where storage account-related private DNS zones live. -- Type: `string` +Metadata | Value +---- | ---- +Type | string ### additionalSubnets @@ -177,7 +206,10 @@ The resource ID of the resource group in the hub subscription where storage acco The definition of additional subnets that have been manually created. -- Type: `array` +Metadata | Value +---- | ---- +Type | array +Default value | `()` ### desktopAppGroupFriendlyName @@ -185,8 +217,10 @@ The definition of additional subnets that have been manually created. Name of the Desktop application group shown to users in the AVD client. -- Type: `string` -- Default value: `N/A` +Metadata | Value +---- | ---- +Type | string +Default value | `N/A` ### workspaceFriendlyName @@ -194,8 +228,10 @@ Name of the Desktop application group shown to users in the AVD client. Name of the Workspace shown to users in the AVD client. -- Type: `string` -- Default value: `N/A` +Metadata | Value +---- | ---- +Type | string +Default value | `N/A` ### createPolicyExemptions @@ -203,7 +239,10 @@ Name of the Workspace shown to users in the AVD client. If true, will create policy exemptions for resources and policy definitions that are not compliant due to issues with common Azure built-in compliance policy initiatives. -- Type: `bool` +Metadata | Value +---- | ---- +Type | bool +Default value | `false` ### policyAssignmentId @@ -211,19 +250,28 @@ If true, will create policy exemptions for resources and policy definitions that Required if policy exemptions must be created. -- Type: `string` +Metadata | Value +---- | ---- +Type | string +Default value | `''` ### sessionHostLocalAdminUsername ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -- Type: `securestring` +Metadata | Value +---- | ---- +Type | securestring +Default value | `''` ### sessionHostLocalAdminPassword ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -- Type: `securestring` +Metadata | Value +---- | ---- +Type | securestring +Default value | `''` ### logonType @@ -231,7 +279,10 @@ Required if policy exemptions must be created. Specifies if logons to virtual machines should use AD or Entra ID. -- Type: `string` +Metadata | Value +---- | ---- +Type | string +Allowed values | `ad`, `entraID` ### domainJoinUsername @@ -239,7 +290,10 @@ Specifies if logons to virtual machines should use AD or Entra ID. The username of a domain user or service account to use to join the Active Directory domain. Use UPN notation. Required if using AD join. -- Type: `securestring` +Metadata | Value +---- | ---- +Type | securestring +Default value | `''` ### domainJoinPassword @@ -247,13 +301,19 @@ The username of a domain user or service account to use to join the Active Direc The password of the domain user or service account to use to join the Active Directory domain. Required if using AD join. -- Type: `securestring` +Metadata | Value +---- | ---- +Type | securestring +Default value | `''` ### filesIdentityType ![Parameter Setting](https://img.shields.io/badge/parameter-required-orange?style=flat-square) -- Type: `string` +Metadata | Value +---- | ---- +Type | string +Allowed values | `AADKERB`, `AADDS`, `None` ### adDomainFqdn @@ -261,7 +321,10 @@ The password of the domain user or service account to use to join the Active Dir The fully qualified DNS name of the Active Directory domain to join. Required if using AD join. -- Type: `string` +Metadata | Value +---- | ---- +Type | string +Default value | `''` ### adOuPath @@ -269,7 +332,10 @@ The fully qualified DNS name of the Active Directory domain to join. Required if Optional. The OU path in LDAP notation to use when joining the session hosts. -- Type: `string` +Metadata | Value +---- | ---- +Type | string +Default value | `''` ### storageAccountOuPath @@ -277,8 +343,10 @@ Optional. The OU path in LDAP notation to use when joining the session hosts. Optional. The OU Path in LDAP notation to use when joining the storage account. Defaults to the same OU as the session hosts. -- Type: `string` -- Default value: `[parameters('adOuPath')]` +Metadata | Value +---- | ---- +Type | string +Default value | `[parameters('adOuPath')]` ### sessionHostCount @@ -286,8 +354,10 @@ Optional. The OU Path in LDAP notation to use when joining the storage account. Optional. The number of Azure Virtual Desktop session hosts to create in the pool. Defaults to 1. -- Type: `int` -- Default value: `1` +Metadata | Value +---- | ---- +Type | int +Default value | `1` ### sessionHostNamePrefix @@ -295,8 +365,11 @@ Optional. The number of Azure Virtual Desktop session hosts to create in the poo The prefix used for the computer names of the session host(s). Maximum 11 characters. -- Type: `string` -- Default value: `N/A` +Metadata | Value +---- | ---- +Type | string +Default value | `N/A` +Maximum length | 11 ### sessionHostSize @@ -304,8 +377,10 @@ The prefix used for the computer names of the session host(s). Maximum 11 charac A valid Azure Virtual Machine size. Use `az vm list-sizes --location ""` to retrieve a list for the selected location -- Type: `string` -- Default value: `N/A` +Metadata | Value +---- | ---- +Type | string +Default value | `N/A` ### useSessionHostAsResearchVm @@ -313,8 +388,10 @@ A valid Azure Virtual Machine size. Use `az vm list-sizes --location ""` If true, will configure the deployment of AVD to make the AVD session hosts usable as research VMs. This will give full desktop access, flow the AVD traffic through the firewall, etc. -- Type: `bool` -- Default value: `True` +Metadata | Value +---- | ---- +Type | bool +Default value | `True` ### researcherEntraIdObjectId @@ -322,7 +399,9 @@ If true, will configure the deployment of AVD to make the AVD session hosts usab Entra ID object ID of the user or group (researchers) to assign permissions to access the AVD application groups and storage. -- Type: `string` +Metadata | Value +---- | ---- +Type | string ### adminEntraIdObjectId @@ -330,7 +409,9 @@ Entra ID object ID of the user or group (researchers) to assign permissions to a Entra ID object ID of the admin user or group to assign permissions to administer the AVD session hosts, storage, etc. -- Type: `string` +Metadata | Value +---- | ---- +Type | string ### isAirlockReviewCentralized @@ -338,7 +419,10 @@ Entra ID object ID of the admin user or group to assign permissions to administe If true, airlock reviews will take place centralized in the hub. If true, the hub* parameters must be specified also. -- Type: `bool` +Metadata | Value +---- | ---- +Type | bool +Default value | `false` ### airlockApproverEmail @@ -346,7 +430,9 @@ If true, airlock reviews will take place centralized in the hub. If true, the hu The email address of the reviewer for this project. -- Type: `string` +Metadata | Value +---- | ---- +Type | string ### allowedIngestFileExtensions @@ -354,7 +440,10 @@ The email address of the reviewer for this project. The allowed file extensions for ingest. -- Type: `array` +Metadata | Value +---- | ---- +Type | array +Default value | `()` ### centralAirlockStorageAccountId @@ -362,7 +451,9 @@ The allowed file extensions for ingest. The full Azure resource ID of the hub's airlock review storage account. -- Type: `string` +Metadata | Value +---- | ---- +Type | string ### centralAirlockFileShareName @@ -370,7 +461,9 @@ The full Azure resource ID of the hub's airlock review storage account. The file share name for airlock reviews. -- Type: `string` +Metadata | Value +---- | ---- +Type | string ### centralAirlockKeyVaultId @@ -378,7 +471,9 @@ The file share name for airlock reviews. The name of the Key Vault in the research hub containing the airlock review storage account's connection string as a secret. -- Type: `string` +Metadata | Value +---- | ---- +Type | string ### publicStorageAccountAllowedIPs @@ -386,7 +481,10 @@ The name of the Key Vault in the research hub containing the airlock review stor The list of allowed IP addresses or ranges for ingest and approved export pickup purposes. -- Type: `array` +Metadata | Value +---- | ---- +Type | array +Default value | `()` ### complianceTarget @@ -394,38 +492,56 @@ The list of allowed IP addresses or ranges for ingest and approved export pickup The Azure built-in regulatory compliance framework to target. This will affect whether or not customer-managed keys, private endpoints, etc. are used. This will *not* deploy a policy assignment. -- Type: `string` -- Default value: `NIST80053R5` +Metadata | Value +---- | ---- +Type | string +Default value | `NIST80053R5` +Allowed values | `NIST80053R5`, `HIPAAHITRUST`, `CMMC2L2`, `NIST800171R2` ### hubManagementVmId ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -- Type: `string` +Metadata | Value +---- | ---- +Type | string +Default value | `''` ### hubManagementVmUamiPrincipalId ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -- Type: `string` +Metadata | Value +---- | ---- +Type | string +Default value | `''` ### hubManagementVmUamiClientId ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -- Type: `string` +Metadata | Value +---- | ---- +Type | string +Default value | `''` ### debugMode ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -- Type: `bool` +Metadata | Value +---- | ---- +Type | bool +Default value | `false` ### debugRemoteIp ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -- Type: `string` +Metadata | Value +---- | ---- +Type | string +Default value | `''` ### debugPrincipalId @@ -433,8 +549,10 @@ The Azure built-in regulatory compliance framework to target. This will affect w The object ID of the user or group to assign permissions. Only used when `debugMode = true`. -- Type: `string` -- Default value: `[deployer().objectId]` +Metadata | Value +---- | ---- +Type | string +Default value | `[deployer().objectId]` ## Outputs diff --git a/research-spoke/main.bicep b/research-spoke/main.bicep index 173242e..71162bd 100644 --- a/research-spoke/main.bicep +++ b/research-spoke/main.bicep @@ -34,7 +34,7 @@ param deploymentTime string = utcNow() param encryptionKeyExpirySeed string = utcNow() // Network parameters -@description('Format: [ "192.168.0.0/24", "192.168.10.0/24" ]') +@description('Format: `[ "192.168.0.0/24", "192.168.10.0/24" ]`') @minLength(1) param networkAddressSpaces array @description('The private IP address of the hub firewall.') @@ -61,7 +61,7 @@ param workspaceFriendlyName string = 'N/A' // @description('The Azure resource ID of the standalone image to use for new session hosts. If blank, will use the Windows 11 23H2 O365 Gen 2 Marketplace image.') // param sessionHostVmImageResourceId string = '' -@description('If true, will create policy exemptions for resources and policy definitions that are not compliant due to issues with common Azure built-in compliance policy initiatives.') +@description('Experimental. If true, will create policy exemptions for resources and policy definitions that are not compliant due to issues with common Azure built-in compliance policy initiatives.') param createPolicyExemptions bool = false @description('Required if policy exemptions must be created.') param policyAssignmentId string = ''