Skip to content

Commit

Permalink
Release 0.3.1 (#6)
Browse files Browse the repository at this point in the history
* Release 0.3.1

* Release 0.3.1

* Release 0.3.1

---------

Co-authored-by: Microsoft Open Source <[email protected]>
  • Loading branch information
ugreg and microsoftopensource authored Oct 19, 2023
1 parent c34a1a4 commit 212ce7f
Show file tree
Hide file tree
Showing 36 changed files with 885 additions and 81 deletions.
3 changes: 3 additions & 0 deletions bicepconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"enabled": true,
"verbose": false,
"rules": {
"no-deployments-resources": {
"level": "off"
},
"adminusername-should-not-be-literal": {
"level": "warning"
},
Expand Down
43 changes: 39 additions & 4 deletions dependencies/infra-as-code/bicep/CRML/subscriptionAlias/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Module: Subscription Alias

> **IMPORTANT:** We recommend moving to using the [Bicep Subscription Vending Module](https://aka.ms/sub-vending/bicep) instead of this module!
> ⚠️⚠️ **IMPORTANT:** We recommend moving to using the [Bicep Subscription Vending Module](https://aka.ms/sub-vending/bicep) instead of this module! ⚠️⚠️
The Subscription Alias module deploys an Azure Subscription into an existing billing scope that can be from an EA, MCA or MPA as documented in [Create Azure subscriptions programmatically](https://learn.microsoft.com/azure/cost-management-billing/manage/programmatically-create-subscription).

Expand All @@ -10,7 +10,8 @@ The Subscription will be created and placed under the Tenant Root Group, unless

## Parameters

- [Parameters for Azure Commercial Cloud](generateddocs/subscriptionAlias.bicep.md)
- [Parameters for `subscriptionAlias.bicep` Azure Commercial Cloud](generateddocs/subscriptionAlias.bicep.md)
- [Parameters for `subscriptionAliasScopeEscape.bicep` Azure Commercial Cloud](generateddocs/subscriptionAliasScopeEscape.bicep.md)

## Outputs

Expand All @@ -29,7 +30,8 @@ In this example, the Subscription is created upon an EA Account through a tenant

> For the below examples we assume you have downloaded or cloned the Git repo as-is and are in the root of the repository as your selected directory in your terminal of choice.
### Azure CLI
### Azure CLI - `subscriptionAlias.bicep`

```bash

dateYMD=$(date +%Y%m%dT%H%M%S%NZ)
Expand All @@ -41,7 +43,23 @@ TEMPLATEFILE="infra-as-code/bicep/CRML/subscriptionAlias/subscriptionAlias.bicep
az deployment tenant create --name ${NAME:0:63} --location $LOCATION --template-file $TEMPLATEFILE --parameters $PARAMETERS
```

### PowerShell
### Azure CLI - `subscriptionAliasScopeEscape.bicep`

Use this module if you do not want to grant Tenant Root Management Group Deployment permissions.

```bash

dateYMD=$(date +%Y%m%dT%H%M%S%NZ)
NAME="alz-SubscriptionAlias-${dateYMD}"
LOCATION="eastus"
PARAMETERS="@infra-as-code/bicep/CRML/subscriptionAlias/parameters/subscriptionAlias.parameters.all.json"
TEMPLATEFILE="infra-as-code/bicep/CRML/subscriptionAlias/subscriptionAliasScopeEscape.bicep"
MGID="alz"

az deployment mg create --name ${NAME:0:63} --location $LOCATION --template-file $TEMPLATEFILE --parameters $PARAMETERS --management-group-id $MGID
```

### PowerShell - `subscriptionAlias.bicep`

```powershell
Expand All @@ -55,6 +73,23 @@ $inputObject = @{
New-AzTenantDeployment @inputObject
```

### PowerShell - `subscriptionAliasScopeEscape.bicep`

Use this module if you do not want to grant Tenant Root Management Group Deployment permissions.

```powershell
$inputObject = @{
DeploymentName = 'alz-SubscriptionAlias-{0}' -f (-join (Get-Date -Format 'yyyyMMddTHHMMssffffZ')[0..63])
TemplateParameterFile = 'infra-as-code/bicep/CRML/subscriptionAlias/parameters/subscriptionAlias.parameters.all.json'
Location = 'EastUS'
TemplateFile = "infra-as-code/bicep/CRML/subscriptionAlias/subscriptionAliasScopeEscape.bicep"
ManagementGroupId = 'alz'
}
New-AzManagementGroupDeployment @inputObject
```

### Output Screenshot

![Example Deployment Output](media/exampleDeploymentOutput.png "Example Deployment Output")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ parSubscriptionName | Yes | Name of the subscription to be created. Will al
parSubscriptionBillingScope | Yes | The full resource ID of billing scope associated to the EA, MCA or MPA account you wish to create the subscription in.
parTags | No | Tags you would like to be applied.
parManagementGroupId | No | The ID of the existing management group where the subscription will be placed. Also known as its parent management group. (Optional)
parSubscriptionOwnerId | No | The object ID of a responsible user, AAD group or service principal. (Optional)
parSubscriptionOwnerId | No | The object ID of a responsible user, Microsoft Entra group or service principal. (Optional)
parSubscriptionOfferType | No | The offer type of the EA, MCA or MPA subscription to be created. Defaults to = Production
parTenantId | No | The ID of the tenant. Defaults to = tenant().tenantId

Expand Down Expand Up @@ -42,7 +42,7 @@ The ID of the existing management group where the subscription will be placed. A

![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square)

The object ID of a responsible user, AAD group or service principal. (Optional)
The object ID of a responsible user, Microsoft Entra group or service principal. (Optional)

### parSubscriptionOfferType

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# ALZ Bicep CRML - Subscription Alias Module with Scope Escape

Module to deploy an Azure Subscription into an existing billing scope that can be from an EA, MCA or MPA, using Scope Escaping feature of ARM to allow deployment not requiring tenant root scope access.

## Parameters

Parameter name | Required | Description
-------------- | -------- | -----------
parSubscriptionName | Yes | Name of the subscription to be created. Will also be used as the alias name. Whilst you can use any name you like we recommend it to be: all lowercase, no spaces, alphanumeric and hyphens only.
parSubscriptionBillingScope | Yes | The full resource ID of billing scope associated to the EA, MCA or MPA account you wish to create the subscription in.
parTags | No | Tags you would like to be applied.
parManagementGroupId | No | The ID of the existing management group where the subscription will be placed. Also known as its parent management group. (Optional)
parSubscriptionOwnerId | No | The object ID of a responsible user, Microsoft Entra group or service principal. (Optional)
parSubscriptionOfferType | No | The offer type of the EA, MCA or MPA subscription to be created. Defaults to = Production
parTenantId | No | The ID of the tenant. Defaults to = tenant().tenantId

### parSubscriptionName

![Parameter Setting](https://img.shields.io/badge/parameter-required-orange?style=flat-square)

Name of the subscription to be created. Will also be used as the alias name. Whilst you can use any name you like we recommend it to be: all lowercase, no spaces, alphanumeric and hyphens only.

### parSubscriptionBillingScope

![Parameter Setting](https://img.shields.io/badge/parameter-required-orange?style=flat-square)

The full resource ID of billing scope associated to the EA, MCA or MPA account you wish to create the subscription in.

### parTags

![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square)

Tags you would like to be applied.

### parManagementGroupId

![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square)

The ID of the existing management group where the subscription will be placed. Also known as its parent management group. (Optional)

### parSubscriptionOwnerId

![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square)

The object ID of a responsible user, Microsoft Entra group or service principal. (Optional)

### parSubscriptionOfferType

![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square)

The offer type of the EA, MCA or MPA subscription to be created. Defaults to = Production

- Default value: `Production`

- Allowed values: `DevTest`, `Production`

### parTenantId

![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square)

The ID of the tenant. Defaults to = tenant().tenantId

- Default value: `[tenant().tenantId]`

## Outputs

Name | Type | Description
---- | ---- | -----------
outSubscriptionName | string |
outSubscriptionId | string |

## Snippets

### Parameter file

```json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"template": "infra-as-code/bicep/CRML/subscriptionAlias/subscriptionAliasScopeEscape.json"
},
"parameters": {
"parSubscriptionName": {
"value": ""
},
"parSubscriptionBillingScope": {
"value": ""
},
"parTags": {
"value": {}
},
"parManagementGroupId": {
"value": ""
},
"parSubscriptionOwnerId": {
"value": ""
},
"parSubscriptionOfferType": {
"value": "Production"
},
"parTenantId": {
"value": "[tenant().tenantId]"
}
}
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ param parTags object = {}
@sys.description('The ID of the existing management group where the subscription will be placed. Also known as its parent management group. (Optional)')
param parManagementGroupId string = ''

@sys.description('The object ID of a responsible user, AAD group or service principal. (Optional)')
@sys.description('The object ID of a responsible user, Microsoft Entra group or service principal. (Optional)')
param parSubscriptionOwnerId string = ''

@allowed([
Expand All @@ -42,7 +42,7 @@ resource resSubscription 'Microsoft.Subscription/aliases@2021-10-01' = {
properties: {
additionalProperties: {
tags: parTags
managementGroupId: empty(parManagementGroupId) ? null : managementGroup(parManagementGroupId)
managementGroupId: empty(parManagementGroupId) ? null : contains(toLower(parManagementGroupId), toLower('/providers/Microsoft.Management/managementGroups/')) ? parManagementGroupId : '/providers/Microsoft.Management/managementGroups/${parManagementGroupId}'
subscriptionOwnerId: empty(parSubscriptionOwnerId) ? null : parSubscriptionOwnerId
subscriptionTenantId: parTenantId
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
targetScope = 'managementGroup'

metadata name = 'ALZ Bicep CRML - Subscription Alias Module with Scope Escape'
metadata description = 'Module to deploy an Azure Subscription into an existing billing scope that can be from an EA, MCA or MPA, using Scope Escaping feature of ARM to allow deployment not requiring tenant root scope access.'

@sys.description('Name of the subscription to be created. Will also be used as the alias name. Whilst you can use any name you like we recommend it to be: all lowercase, no spaces, alphanumeric and hyphens only.')
param parSubscriptionName string

@sys.description('The full resource ID of billing scope associated to the EA, MCA or MPA account you wish to create the subscription in.')
param parSubscriptionBillingScope string

@sys.description('Tags you would like to be applied.')
param parTags object = {}

@sys.description('The ID of the existing management group where the subscription will be placed. Also known as its parent management group. (Optional)')
param parManagementGroupId string = ''

@sys.description('The object ID of a responsible user, Microsoft Entra group or service principal. (Optional)')
param parSubscriptionOwnerId string = ''

@allowed([
'DevTest'
'Production'
])
@sys.description('The offer type of the EA, MCA or MPA subscription to be created. Defaults to = Production')
param parSubscriptionOfferType string = 'Production'

@sys.description('The ID of the tenant. Defaults to = tenant().tenantId')
param parTenantId string = tenant().tenantId

resource resSubscription 'Microsoft.Subscription/aliases@2021-10-01' = {
scope: tenant()
name: parSubscriptionName
properties: {
additionalProperties: {
tags: parTags
managementGroupId: empty(parManagementGroupId) ? null : contains(toLower(parManagementGroupId), toLower('/providers/Microsoft.Management/managementGroups/')) ? parManagementGroupId : '/providers/Microsoft.Management/managementGroups/${parManagementGroupId}'
subscriptionOwnerId: empty(parSubscriptionOwnerId) ? null : parSubscriptionOwnerId
subscriptionTenantId: parTenantId
}
displayName: parSubscriptionName
billingScope: parSubscriptionBillingScope
workload: parSubscriptionOfferType
}
}

output outSubscriptionName string = resSubscription.name
output outSubscriptionId string = resSubscription.properties.subscriptionId
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ The Management Groups module deploys a management group hierarchy in a customer'

## Parameters

- [Link to Parameters](generateddocs/managementGroups.bicep.md)
- [Link to `managementGroup.bicep` Parameters](generateddocs/managementGroups.bicep.md)
- [Link to `managementGroupsScopeEscape.bicep` Parameters](generateddocs/managementGroupsScopeEscape.bicep.md)

### Child Platform & Landing Zone Management Groups Flexibility

Expand Down Expand Up @@ -141,7 +142,7 @@ In this example, the management groups are created at the `Tenant Root Group` th

> For the examples below we assume you have downloaded or cloned the Git repo as-is and are in the root of the repository as your selected directory in your terminal of choice.
### Azure CLI
### Azure CLI - `managementGroups.bicep`

```bash
# For Azure global regions
Expand All @@ -167,7 +168,37 @@ PARAMETERS="@infra-as-code/bicep/modules/managementGroups/parameters/managementG
az deployment tenant create --name ${NAME:0:63} --location $LOCATION --template-file $TEMPLATEFILE --parameters $PARAMETERS
```

### PowerShell
### Azure CLI - `managementGroupsScopeEscape.bicep`

Use this module if you do not want to grant Tenant Root Management Group Deployment permissions.

```bash
# For Azure global regions

dateYMD=$(date +%Y%m%dT%H%M%S%NZ)
NAME="alz-MGDeployment-${dateYMD}"
LOCATION="eastus"
TEMPLATEFILE="infra-as-code/bicep/modules/managementGroups/managementGroupsScopeEscape.bicep"
PARAMETERS="@infra-as-code/bicep/modules/managementGroups/parameters/managementGroups.parameters.all.json"
MGID="alz"

az deployment tenant create --name ${NAME:0:63} --location $LOCATION --template-file $TEMPLATEFILE --parameters $PARAMETERS --management-group-id $MGID
```
OR
```bash
# For Azure China regions

dateYMD=$(date +%Y%m%dT%H%M%S%NZ)
NAME="alz-MGDeployment-${dateYMD}"
LOCATION="chinaeast2"
TEMPLATEFILE="infra-as-code/bicep/modules/managementGroups/managementGroupsScopeEscape.bicep"
PARAMETERS="@infra-as-code/bicep/modules/managementGroups/parameters/managementGroups.parameters.all.json"
MGID="alz"

az deployment tenant create --name ${NAME:0:63} --location $LOCATION --template-file $TEMPLATEFILE --parameters $PARAMETERS --management-group-id $MGID
```

### PowerShell - `managementGroups.bicep`

```powershell
# For Azure global regions
Expand All @@ -193,6 +224,36 @@ $inputObject = @{
New-AzTenantDeployment @inputObject
```

### PowerShell - `managementGroupsScopeEscape.bicep`

Use this module if you do not want to grant Tenant Root Management Group Deployment permissions.

```powershell
# For Azure global regions
$inputObject = @{
DeploymentName = 'alz-MGDeployment-{0}' -f (-join (Get-Date -Format 'yyyyMMddTHHMMssffffZ')[0..63])
Location = 'EastUS'
TemplateFile = "infra-as-code/bicep/modules/managementGroups/managementGroupsScopeEscape.bicep"
TemplateParameterFile = 'infra-as-code/bicep/modules/managementGroups/parameters/managementGroups.parameters.all.json'
ManagementGroupId = 'alz'
}
New-AzManagementGroupDeployment @inputObject
```
OR
```powershell
# For Azure China regions
$inputObject = @{
DeploymentName = 'alz-MGDeployment-{0}' -f (-join (Get-Date -Format 'yyyyMMddTHHMMssffffZ')[0..63])
Location = 'chinaeast2'
TemplateFile = "infra-as-code/bicep/modules/managementGroups/managementGroupsScopeEscape.bicep"
TemplateParameterFile = 'infra-as-code/bicep/modules/managementGroups/parameters/managementGroups.parameters.all.json'
ManagementGroupId = 'alz'
}
New-AzManagementGroupDeployment @inputObject
```

![Example Deployment Output](media/exampleDeploymentOutput.png "Example Deployment Output")

## Bicep Visualizer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ALZ Bicep Module to set up Management Group structure

Parameter name | Required | Description
-------------- | -------- | -----------
parTopLevelManagementGroupPrefix | No | Prefix for the management group hierarchy. This management group will be created as part of the deployment.
parTopLevelManagementGroupPrefix | No | Prefix used for the management group hierarchy. This management group will be created as part of the deployment.
parTopLevelManagementGroupSuffix | No | Optional suffix for the management group hierarchy. This suffix will be appended to management group names/IDs. Include a preceding dash if required. Example: -suffix
parTopLevelManagementGroupDisplayName | No | Display name for top level management group. This name will be applied to the management group prefix defined in parTopLevelManagementGroupPrefix parameter.
parTopLevelManagementGroupParentId | No | Optional parent for Management Group hierarchy, used as intermediate root Management Group parent, if specified. If empty, default, will deploy beneath Tenant Root Management Group.
Expand All @@ -21,7 +21,7 @@ parTelemetryOptOut | No | Set Parameter to true to Opt-out of deployment t

![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square)

Prefix for the management group hierarchy. This management group will be created as part of the deployment.
Prefix used for the management group hierarchy. This management group will be created as part of the deployment.

- Default value: `alz`

Expand Down
Loading

0 comments on commit 212ce7f

Please sign in to comment.