diff --git a/.github/scripts/Invoke-PSDocsAzure.ps1 b/.github/scripts/Invoke-PSDocsAzure.ps1 index ed7016fc..71a99ccf 100644 --- a/.github/scripts/Invoke-PSDocsAzure.ps1 +++ b/.github/scripts/Invoke-PSDocsAzure.ps1 @@ -44,7 +44,7 @@ Get-AzDocTemplateFile -InputPath $docsToGenerate | ForEach-Object { # Generate markdown Write-Information -InformationAction Continue "====> Creating MD file using PSDocs.Azure for: $template" - Invoke-PSDocument -Module PSDocs.Azure -OutputPath $docOutputPath -InputObject $template.FullName -InstanceName $docName -Culture 'en-US' + Invoke-PSDocument -Module PSDocs.Azure -OutputPath $docOutputPath -InputObject $template.FullName -InstanceName $docName -Culture 'en-US' -Option (New-PSDocumentOption -Option @{ 'CONFIGURATION.AZURE_BICEP_REGISTRY_MODULES_METADATA_SCHEMA_ENABLED' = $True }) } # Remove JSON files that were temporarily created diff --git a/main.bicep b/main.bicep index f0d2255f..56f00602 100644 --- a/main.bicep +++ b/main.bicep @@ -4,7 +4,9 @@ targetScope = 'managementGroup' metadata name = '`main.bicep` Parameters' -metadata description = '''These are the input parameters for the Bicep module: [`main.bicep`](./main.bicep) +metadata description = 'This module is designed to accelerate deployment of landing zones (aka Subscriptions) within an Azure AD Tenant.' + +metadata details = '''These are the input parameters for the Bicep module: [`main.bicep`](./main.bicep) This is the orchestration module that is used and called by a consumer of the module to deploy a Landing Zone Subscription and its associated resources, based on the parameter input values that are provided to it at deployment time. @@ -85,6 +87,32 @@ param subscriptionBillingScope string = '' ''') param subscriptionWorkload string = 'Production' +@metadata({ + example: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' +}) +@maxLength(36) +@sys.description('''The Azure Active Directory Tenant ID (GUID) to which the Subscription should be attached to. + +> **Leave blank unless following this scenario only [Programmatically create MCA subscriptions across Azure Active Directory tenants](https://learn.microsoft.com/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement-across-tenants).** + +- Type: String +- Default value: `''` *(empty string)* +''') +param subscriptionTenantId string = '' + +@metadata({ + example: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' +}) +@maxLength(36) +@sys.description('''The Azure Active Directory principals object ID (GUID) to whom should be the Subscription Owner. + +> **Leave blank unless following this scenario only [Programmatically create MCA subscriptions across Azure Active Directory tenants](https://learn.microsoft.com/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement-across-tenants).** + +- Type: String +- Default value: `''` *(empty string)* +''') +param subscriptionOwnerId string = '' + @metadata({ example: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' }) @@ -448,6 +476,8 @@ module createSubscription 'src/self/Microsoft.Subscription/aliases/deploy.bicep' subscriptionAliasName: subscriptionAliasName subscriptionDisplayName: subscriptionDisplayName subscriptionWorkload: subscriptionWorkload + subscriptionTenantId: subscriptionTenantId + subscriptionOwnerId: subscriptionOwnerId } } @@ -488,3 +518,9 @@ output subscriptionId string = (subscriptionAliasEnabled && empty(existingSubscr @sys.description('The Subscription Resource ID that has been created or provided.') output subscriptionResourceId string = (subscriptionAliasEnabled && empty(existingSubscriptionId)) ? createSubscription.outputs.subscriptionResourceId : contains(existingSubscriptionIDEmptyCheck, 'No Subscription ID Provided') ? existingSubscriptionIDEmptyCheck : '/subscriptions/${existingSubscriptionId}' + +@sys.description('The Subscription Owner State. Only used when creating MCA Subscriptions across tenants') +output subscriptionAcceptOwnershipState string = (subscriptionAliasEnabled && empty(existingSubscriptionId) && !empty(subscriptionTenantId) && !empty(subscriptionOwnerId)) ? createSubscription.outputs.subscriptionAcceptOwnershipState : 'N/A' + +@sys.description('The Subscription Ownership URL. Only used when creating MCA Subscriptions across tenants') +output subscriptionAcceptOwnershipUrl string = (subscriptionAliasEnabled && empty(existingSubscriptionId) && !empty(subscriptionTenantId) && !empty(subscriptionOwnerId)) ? createSubscription.outputs.subscriptionAcceptOwnershipUrl : 'N/A' diff --git a/main.bicep.parameters.md b/main.bicep.parameters.md index 4e67db51..833dcb9e 100644 --- a/main.bicep.parameters.md +++ b/main.bicep.parameters.md @@ -1,5 +1,7 @@ # `main.bicep` Parameters +This module is designed to accelerate deployment of landing zones (aka Subscriptions) within an Azure AD Tenant. + These are the input parameters for the Bicep module: [`main.bicep`](./main.bicep) This is the orchestration module that is used and called by a consumer of the module to deploy a Landing Zone Subscription and its associated resources, based on the parameter input values that are provided to it at deployment time. @@ -15,6 +17,8 @@ subscriptionDisplayName | No | The name of the subscription alias. The str subscriptionAliasName | No | The name of the Subscription Alias, that will be created by this module. The string must be comprised of `a-z`, `A-Z`, `0-9`, `-`, `_` and ` ` (space). The maximum length is 63 characters. > **Not required when providing an existing Subscription ID via the parameter `existingSubscriptionId`** - Type: String - Default value: `''` *(empty string)* subscriptionBillingScope | No | The Billing Scope for the new Subscription alias, that will be created by this module. A valid Billing Scope starts with `/providers/Microsoft.Billing/billingAccounts/` and is case sensitive. > See below [example in parameter file](#parameter-file) for an example > **Not required when providing an existing Subscription ID via the parameter `existingSubscriptionId`** - Type: String - Default value: `''` *(empty string)* subscriptionWorkload | No | The workload type can be either `Production` or `DevTest` and is case sensitive. > **Not required when providing an existing Subscription ID via the parameter `existingSubscriptionId`** - Type: String +subscriptionTenantId | No | The Azure Active Directory Tenant ID (GUID) to which the Subscription should be attached to. > **Leave blank unless following this scenario only [Programmatically create MCA subscriptions across Azure Active Directory tenants](https://learn.microsoft.com/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement-across-tenants).** - Type: String - Default value: `''` *(empty string)* +subscriptionOwnerId | No | The Azure Active Directory principals object ID (GUID) to whom should be the Subscription Owner. > **Leave blank unless following this scenario only [Programmatically create MCA subscriptions across Azure Active Directory tenants](https://learn.microsoft.com/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement-across-tenants).** - Type: String - Default value: `''` *(empty string)* existingSubscriptionId | No | An existing subscription ID. Use this when you do not want the module to create a new subscription. But do want to manage the management group membership. A subscription ID should be provided in the example format `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`. - Type: String - Default value: `''` *(empty string)* subscriptionManagementGroupAssociationEnabled | No | Whether to move the Subscription to the specified Management Group supplied in the parameter `subscriptionManagementGroupId`. - Type: Boolean subscriptionManagementGroupId | No | The destination Management Group ID for the new Subscription that will be created by this module (or the existing one provided in the parameter `existingSubscriptionId`). **IMPORTANT:** Do not supply the display name of the Management Group. The Management Group ID forms part of the Azure Resource ID. e.g., `/providers/Microsoft.Management/managementGroups/{managementGroupId}`. > See below [example in parameter file](#parameter-file) for an example - Type: String - Default value: `''` *(empty string)* @@ -49,7 +53,11 @@ Whether to create a new Subscription using the Subscription Alias resource. If ` - Type: Boolean -- Default value: `True` +**Default value** + +```text +True +``` ### subscriptionDisplayName @@ -108,9 +116,42 @@ The workload type can be either `Production` or `DevTest` and is case sensitive. - Type: String -- Default value: `Production` +**Default value** + +```text +Production +``` + +**Allowed values** + +```text +DevTest +Production +``` + +### subscriptionTenantId + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +The Azure Active Directory Tenant ID (GUID) to which the Subscription should be attached to. + +> **Leave blank unless following this scenario only [Programmatically create MCA subscriptions across Azure Active Directory tenants](https://learn.microsoft.com/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement-across-tenants).** + +- Type: String +- Default value: `''` *(empty string)* + + +### subscriptionOwnerId + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +The Azure Active Directory principals object ID (GUID) to whom should be the Subscription Owner. + +> **Leave blank unless following this scenario only [Programmatically create MCA subscriptions across Azure Active Directory tenants](https://learn.microsoft.com/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement-across-tenants).** + +- Type: String +- Default value: `''` *(empty string)* -- Allowed values: `DevTest`, `Production` ### existingSubscriptionId @@ -131,7 +172,11 @@ Whether to move the Subscription to the specified Management Group supplied in t - Type: Boolean -- Default value: `True` +**Default value** + +```text +True +``` ### subscriptionManagementGroupId @@ -178,7 +223,11 @@ If set to `true` ensure you also provide values for the following parameters at - Type: Boolean -- Default value: `False` +**Default value** + +```text +False +``` ### virtualNetworkResourceGroupName @@ -211,7 +260,11 @@ Enables the deployment of a `CanNotDelete` resource locks to the Virtual Network - Type: Boolean -- Default value: `True` +**Default value** + +```text +True +``` ### virtualNetworkLocation @@ -222,7 +275,11 @@ The location of the virtual network. Use region shortnames e.g. `uksouth`, `east - Type: String -- Default value: `[deployment().location]` +**Default value** + +```text +[deployment().location] +``` ### virtualNetworkName @@ -289,7 +346,11 @@ Whether to enable peering/connection with the supplied hub Virtual Network or Vi - Type: Boolean -- Default value: `False` +**Default value** + +```text +False +``` ### hubNetworkResourceId @@ -317,7 +378,11 @@ Enables the use of remote gateways in the specified hub virtual network. - Type: Boolean -- Default value: `True` +**Default value** + +```text +True +``` ### virtualNetworkVwanEnableInternetSecurity @@ -328,7 +393,11 @@ Enables the ability for the Virtual WAN Hub Connection to learn the default rout - Type: Boolean -- Default value: `True` +**Default value** + +```text +True +``` ### virtualNetworkVwanAssociatedRouteTableResourceId @@ -377,7 +446,11 @@ Whether to create role assignments or not. If true, supply the array of role ass - Type: Boolean -- Default value: `False` +**Default value** + +```text +False +``` ### roleAssignments @@ -407,7 +480,11 @@ Disable telemetry collection by this module. For more information on the telemetry collected by this module, that is controlled by this parameter, see this page in the wiki: [Telemetry Tracking Using Customer Usage Attribution (PID)](https://github.com/Azure/bicep-lz-vending/wiki/Telemetry) -- Default value: `False` +**Default value** + +```text +False +``` ## Outputs @@ -415,6 +492,8 @@ Name | Type | Description ---- | ---- | ----------- subscriptionId | string | The Subscription ID that has been created or provided. subscriptionResourceId | string | The Subscription Resource ID that has been created or provided. +subscriptionAcceptOwnershipState | string | The Subscription Owner State. Only used when creating MCA Subscriptions across tenants +subscriptionAcceptOwnershipUrl | string | The Subscription Ownership URL. Only used when creating MCA Subscriptions across tenants ## Snippets @@ -425,7 +504,7 @@ subscriptionResourceId | string | The Subscription Resource ID that has been cre "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "metadata": { - "template": "main.json" + "template": null }, "parameters": { "subscriptionAliasEnabled": { @@ -443,6 +522,12 @@ subscriptionResourceId | string | The Subscription Resource ID that has been cre "subscriptionWorkload": { "value": "Production" }, + "subscriptionTenantId": { + "value": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + }, + "subscriptionOwnerId": { + "value": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + }, "existingSubscriptionId": { "value": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }, diff --git a/src/self/Microsoft.Subscription/aliases/deploy.bicep b/src/self/Microsoft.Subscription/aliases/deploy.bicep index 10f88d4b..cffa3d41 100644 --- a/src/self/Microsoft.Subscription/aliases/deploy.bicep +++ b/src/self/Microsoft.Subscription/aliases/deploy.bicep @@ -18,6 +18,14 @@ param subscriptionBillingScope string @description('The workload type can be either `Production` or `DevTest` and is case sensitive.') param subscriptionWorkload string = 'Production' +@maxLength(36) +@description('''The Azure Active Directory Tenant ID (GUID) to which the Subscription should be attached to. Leave blank unless following this scenario only [Programmatically create MCA subscriptions across Azure Active Directory tenants](https://learn.microsoft.com/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement-across-tenants).''') +param subscriptionTenantId string = '' + +@maxLength(36) +@description('''The Azure Active Directory principals object ID (GUID) to whom should be the Subscription Owner. Leave blank unless following this scenario only [Programmatically create MCA subscriptions across Azure Active Directory tenants](https://learn.microsoft.com/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement-across-tenants).''') +param subscriptionOwnerId string = '' + resource subscriptionAlias 'Microsoft.Subscription/aliases@2021-10-01' = { scope: tenant() name: subscriptionAliasName @@ -25,8 +33,14 @@ resource subscriptionAlias 'Microsoft.Subscription/aliases@2021-10-01' = { workload: subscriptionWorkload displayName: subscriptionDisplayName billingScope: subscriptionBillingScope + additionalProperties: (!empty(subscriptionTenantId) && !empty(subscriptionOwnerId)) ? { + subscriptionTenantId: subscriptionTenantId + subscriptionOwnerId: subscriptionOwnerId + } : {} } } output subscriptionId string = subscriptionAlias.properties.subscriptionId output subscriptionResourceId string = '/subscriptions/${subscriptionAlias.properties.subscriptionId}' +output subscriptionAcceptOwnershipState string = (!empty(subscriptionTenantId) && !empty(subscriptionOwnerId)) ? subscriptionAlias.properties.acceptOwnershipState : 'N/A' +output subscriptionAcceptOwnershipUrl string = (!empty(subscriptionTenantId) && !empty(subscriptionOwnerId)) ? subscriptionAlias.properties.acceptOwnershipUrl : 'N/A' diff --git a/src/self/subResourceWrapper/deploy.bicep b/src/self/subResourceWrapper/deploy.bicep index 797071bb..8d2f64f6 100644 --- a/src/self/subResourceWrapper/deploy.bicep +++ b/src/self/subResourceWrapper/deploy.bicep @@ -4,7 +4,9 @@ targetScope = 'managementGroup' metadata name = '`/subResourcesWrapper/deploy.bicep` Parameters' -metadata description = '''These are the input parameters for the Bicep module: [`deploy.bicep`](./deploy.bicep) +metadata description = 'This module is used by the [`bicep-lz-vending`](https://aka.ms/sub-vending/bicep) module to help orchestrate the deployment' + +metadata details = '''These are the input parameters for the Bicep module: [`deploy.bicep`](./deploy.bicep) This is the sub-orchestration module that is used and called by the [`main.bicep`](../../../main.bicep) module to deploy the resources into the subscription that has been created (or an existing one provided), based on the parameter input values that are provided to it at deployment time from the `main.bicep` orchestration module. diff --git a/src/self/subResourceWrapper/readme.md b/src/self/subResourceWrapper/readme.md index a1790565..63ad4db9 100644 --- a/src/self/subResourceWrapper/readme.md +++ b/src/self/subResourceWrapper/readme.md @@ -1,5 +1,7 @@ # `/subResourcesWrapper/deploy.bicep` Parameters +This module is used by the [`bicep-lz-vending`](https://aka.ms/sub-vending/bicep) module to help orchestrate the deployment + These are the input parameters for the Bicep module: [`deploy.bicep`](./deploy.bicep) This is the sub-orchestration module that is used and called by the [`main.bicep`](../../../main.bicep) module to deploy the resources into the subscription that has been created (or an existing one provided), based on the parameter input values that are provided to it at deployment time from the `main.bicep` orchestration module. @@ -47,7 +49,11 @@ disableTelemetry | No | Disable telemetry collection by this module. For m Whether to move the subscription to the specified management group supplied in the pararmeter subscriptionManagementGroupId. -- Default value: `True` +**Default value** + +```text +True +``` ### subscriptionManagementGroupId @@ -67,7 +73,11 @@ An object of tag key/value pairs to be appended to a subscription. NOTE: Tags wi Whether to create a virtual network or not. -- Default value: `False` +**Default value** + +```text +False +``` ### virtualNetworkResourceGroupName @@ -81,7 +91,11 @@ The name of the resource group to create the virtual network in. Enables the deployment of a `CanNotDelete` resource locks to the virtual networks resource group. -- Default value: `True` +**Default value** + +```text +True +``` ### virtualNetworkResourceGroupTags @@ -95,7 +109,11 @@ An object of tag key/value pairs to be appended to the Resource Group that the V The location of the virtual network. Use region shortnames e.g. uksouth, eastus, etc. -- Default value: `[deployment().location]` +**Default value** + +```text +[deployment().location] +``` ### virtualNetworkName @@ -133,7 +151,11 @@ The resoruce ID of an existing DDoS Network Protection Plan that you wish to lin Whether to enable peering/connection with the supplied hub virtual network or virtual hub. -- Default value: `False` +**Default value** + +```text +False +``` ### hubNetworkResourceId @@ -147,7 +169,11 @@ The resource ID of the virtual network or virtual wan hub in the hub to which th Enables the use of remote gateways in the spefcified hub virtual network. If no gateways exsit in the hub virtual network, set this to `false`, otherwise peering will fail to create. Set this to `false` for virtual wan hub connections. -- Default value: `True` +**Default value** + +```text +True +``` ### virtualNetworkVwanEnableInternetSecurity @@ -155,7 +181,11 @@ Enables the use of remote gateways in the spefcified hub virtual network. If no Enables the ability for the Virtual WAN Hub Connection to learn the default route 0.0.0.0/0 from the Hub. -- Default value: `True` +**Default value** + +```text +True +``` ### virtualNetworkVwanAssociatedRouteTableResourceId @@ -181,7 +211,11 @@ An array of virtual hub route table labels to propogate routes to. If left blank Whether to create role assignments or not. If true, supply the array of role assignment objects in the parameter called `roleAssignments`. -- Default value: `False` +**Default value** + +```text +False +``` ### roleAssignments @@ -195,7 +229,11 @@ Supply an array of objects containing the details of the role assignments to cre Disable telemetry collection by this module. For more information on the telemetry collected by this module, that is controlled by this parameter, see this page in the wiki: [Telemetry Tracking Using Customer Usage Attribution (PID)](https://github.com/Azure/bicep-lz-vending/wiki/Telemetry) -- Default value: `False` +**Default value** + +```text +False +``` ## Snippets @@ -206,7 +244,7 @@ Disable telemetry collection by this module. For more information on the telemet "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "metadata": { - "template": "src/self/subResourceWrapper/deploy.json" + "template": null }, "parameters": { "subscriptionId": { @@ -233,9 +271,6 @@ Disable telemetry collection by this module. For more information on the telemet "virtualNetworkResourceGroupTags": { "value": {} }, - "virtualNetworkLocation": { - "value": "[deployment().location]" - }, "virtualNetworkName": { "value": "" },