Proposed Pull Request Change

title description author ms.author ms.service ms.topic ms.date
Manage Azure Service Group membership at scale Learn how to create, manage, and update membership for Azure Service Groups at scale kenieva kenieva azure-policy how-to 10/28/2025
📄 Document Links
GitHub View on GitHub Microsoft Learn View on Microsoft Learn
Content Truncation Detected
The generated rewrite appears to be incomplete.
Original lines: -
Output lines: -
Ratio: -
Raw New Markdown
Generating updated version of doc...
Rendered New Markdown
Generating updated version of doc...
+0 -0
+0 -0
--- title: "Manage Azure Service Group membership at scale" description: "Learn how to create, manage, and update membership for Azure Service Groups at scale" author: kenieva ms.author: kenieva ms.service: azure-policy ms.topic: how-to ms.date: 10/28/2025 --- # Manage Azure Service Group Membership at scale Azure **Service Groups** provide a flexible way to organize and manage resources. Memberships within a Service Group are represented as extension resource of type 'Microsoft.Relationship/serviceGroupMember'. These extension resources follow the lifecycle of the associated member resource and reference the target Service Group through the `targetId` property. To explore this further or create a Service Group member, review the [available REST APIs](./manage-service-groups.md#create-a-service-group-member) and the [QuickStart guide for adding members in the portal](./create-service-group-member-portal.md). Memberships can be managed individually or at scale. By automating membership management through code and deploying Service Groups with predefined memberships, organizations can streamline scenarios that depend on Service Groups. This guide provides a starting point to ease membership management across one or multiple Service Groups. ## Sample consolidated template for creating Service Group and Members Organizations that manage resource lifecycles using a CI/CD approach can couple service group and membership creation within the same deployment template. The following Bicep template deploys two storage accounts, creates a new service group, and adds the storage accounts as members of that group. >[!Note] > To run this template, the user must have [Service Group Administrator role](../../role-based-access-control/built-in-roles/management-and-governance.md) on the parent Service Group and have storage account creation permissions at the desired scope. ```bicep param serviceGroupId string = 'SGID' param parentServiceGroupId string = 'SGParent' //Must be owner on parentServiceGroupId to run this bicep successfully in one run param storageCount int = 2 resource storage 'Microsoft.Storage/storageAccounts@2022-09-01' = [for i in range(0, storageCount): { name: '${serviceGroupId}num${i}' location: 'eastus2' sku: { name: 'Standard_LRS' } kind: 'StorageV2' properties: { allowSharedKeyAccess: false } }] resource sg1 'Microsoft.Management/serviceGroups@2024-02-01-preview' = { scope: tenant() name: serviceGroupId properties: { displayName: serviceGroupId parent: { resourceId: '/providers/Microsoft.Management/serviceGroups/${parentServiceGroupId}' } } } resource rel0 'Microsoft.Relationships/serviceGroupMember@2023-09-01-preview' = [for i in range(0, storageCount): { scope: storage[i] name: 'rel-${i}' properties: { targetId: sg1.id } }] ``` ## Using Azure Policy for automatic membership Service Group membership can be defined by a rule. Common examples are resources following a naming convention that contains `appCode` or resource having a tag with a specific `costCode` values. To automate the creation of service group membership, you can define an **Azure Policy definition** that can deploy the Service Group memberships relationships based on the rule. >[!Note] > Azure Policy will not delete relationships for resources that do not meet the rule. ```json { "properties": { "displayName": "Deploy Memberships for Tagged Resources", "policyType": "Custom", "mode": "Indexed", "description": "Deploy Microsoft.Relationships/serviceGroupMember for resources with specific tag.", "parameters": { "tagName": { "type": "String", "metadata": { "description": "Name of the tag to check." } }, "tagValue": { "type": "String", "metadata": { "description": "Value of the tag to match." } } }, "policyRule": { "if": { "allOf": [ { "field": "[concat('tags[', parameters('tagName'), ']')]", "equals": "[parameters('tagValue')]" } ] }, "then": { "effect": "deployIfNotExists", "details": { "type": "Microsoft.Relationships/serviceGroupMember", "roleDefinitionIds": [ "/providers/Microsoft.Management/serviceGroups/{Insert SG ID}/providers/Microsoft.Authorization/roleDefinitions/32e6a4ec-6095-4e37-b54b-12aa350ba81f", "/subscriptions/{Insert Subscription}/providers/Microsoft.Authorization/roleDefinitions/05b1aaf9-00c9-477b-b0e8-2da660b78c51" ], "deployment": { "properties": { "mode": "incremental", "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "fullName": { "type": "string" }, "fullType": { "type": "string" } }, "resources": [ { "type": "Microsoft.Relationships/serviceGroupMember", "apiVersion": "2023-09-01-preview", "name": "[concat('sgm-', parameters('fullName'))]", "scope": "[resourceId(subscription().subscriptionId, resourceGroup().name, parameters('fullType'), parameters('fullName'))]", "properties": { "targetId": "/providers/Microsoft.Management/serviceGroups/{SG-ID}", "targetTenant": "{TenantID}" } } ] }, "parameters": { "fullName": { "value": "[field('name')]" }, "fullType": { "value": "[field('type')]" } } } } } } } } } ``` ## Creating memberships based on a Resource Graph query Service Group memberships can be created in bulk using results from an Azure Resource Graph (ARG) query. For example, resources required for a job to be done may need to be grouped together, and these resources can be detected using ARG. The example below groups storage accounts that need to enable soft delete. The script first runs an ARG query to select the storage accounts that should become members of the Service Group based on their tag values. Then it loops through each resource identified in the query and deploys a 'Microsoft.Relationships/serviceGroupMember' to represent the membership. >[!Note] > This is an example powershell command on how to use a Resource Group query to create Service Groups members for that point in time. ```ps1 # Requires -Modules Az.ResourceGraph <# .SYNOPSIS This script deploys service group members to resources in Azure based on a query that checks for a specified tag. .DESCRIPTION This script uses Az.ResourceGraph to query resources with a specific tag across a given subscription and tenant. It then deploys a service group member relationship for each of these resources using an ARM template. The user must have owner permissions on the Service Group to add members. This script can bring in resource from different subscriptions if they exist in the same tenant. However the user will be prompted to login to each subscription the resources exist in. .PARAMETER TagName The name of the tag to filter resources. .PARAMETER subscriptionId The ID of the subscription to login. This parameter is only used to authenticate with Connect-AzAccount. Resources from other subscriptions in the same tenant will also be found. .PARAMETER tenantId The ID of the tenant to filter resources. .PARAMETER ServiceGroupId The ID of the service group to which the members will be added. Description of what this parameter does. Repeat for each parameter. .EXAMPLE PS> .\New-ServiceGroupMembershipFromTags.ps1 -TagName "Environment" -tenantId "MyTenant" -subscription "MySub" -ServiceGroupId "MyServiceGroup" #> param( [Parameter(Mandatory = $true)] [string]$TagName, # [INPUT HERE] Tag name to filter resources [Parameter(Mandatory = $true)] [string]$subscription, # [INPUT HERE] Subscription ID or name to login [Parameter(Mandatory = $true)] [string]$tenantId, # [INPUT HERE] Tenant ID to filter resources [Parameter(Mandatory = $true)] [string]$ServiceGroupId # [INPUT HERE] Service Group ID ) # Authenticate Connect-AzAccount -TenantId $tenantId -Subscription $subscription # Query ARG for resources with the specified tag # This should find anything with the tag, under any subscription in the tenant # This query can be updated to the desired scenario $query = @" Resources | where isnotnull(tags['$TagName']) "@ $resources = Search-AzGraph -UseTenantScope -Query $query if ($resources.Count -eq 0) { Write-Host "No resources found with tag '$TagName'." exit } Write-Host "Found $($resources.Count) resources with tag '$TagName'." Write-Host "Resources: $($resources | Format-Table | Out-String)" $i = 0 $lastSubscriptionId = (Get-AzContext).Subscription.id foreach ($resource in $resources) { $resourceId = $resource.id $resourceSubscriptionId = $resource.subscriptionId $resourceGroup = $resource.resourceGroup Write-Host "Deploying serviceGroupMember for resource: $($resource.name) of type $($resource.type) in subscription: $resourceSubscriptionId in resource group: $resourceGroup" # ARM template $template = @" { "`$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "resources": [ { "type": "Microsoft.Relationships/serviceGroupMember", "scope": "$resourceId", "apiVersion": "2023-09-01-preview", "name": "$ServiceGroupId-relation-$i", "properties": { "targetId": "/providers/Microsoft.Management/serviceGroups/$ServiceGroupId" } } ] } "@ $i++ Write-Host "Using template: $template" # Save template to temporary file # Using temp files to keep it Powershell 5 compatible # Using -TemplateBody with `ConvertTo-Json -AsHashtable` requires powershell 6 $tempFile = [System.IO.Path]::GetTempFileName() + ".json" # Deploy template try { $template | Out-File -FilePath $tempFile -Encoding utf8 # Change subscription if needed. if ($lastSubscriptionId -ne $resourceSubscriptionId) { Write-Host "Switching to subscription: $resourceSubscriptionId" Connect-AzAccount -SubscriptionId $resourceSubscriptionId -WarningAction Ignore $lastSubscriptionId = $resourceSubscriptionId Get-AzContext } New-AzResourceGroupDeployment ` -ResourceGroupName $resourceGroup ` -TemplateFile $tempFile ` -Mode Incremental Write-Host "Successfully deployed serviceGroupMember for $($resource.name)." } catch { Write-Warning "Failed to deploy for $($resource.name): $_" } finally { # Clean up temp file if (Test-Path $tempFile) { Remove-Item $tempFile } } } ``` The parameter `$query` can be updated to the desired query. Here is an example response: ```txt PS C:\> .\src\New-ServiceGroupMembershipFromTags.ps1 -TagName "TagName" -tenantId "XXXXXXXXXXXXXX" -ServiceGroupId "XXXXXXXX" -Subscription "XXXXXXXXXXXX" Please select the account you want to login with. Retrieving subscriptions for the selection... Found 4 resources with tag 'TagName'. Resources: id name type -- ---- ---- /subscriptions/{subID}/resourceGroups/{RGName}/providers/Microsoft.Storage/storageAccounts/storageAcccountnum1 storageAccountnum1 microsoft.... /subscriptions/{subID}/resourceGroups/{RGName}/providers/Microsoft.Storage/storageAccounts/storageAcccountnum2 storageAccountnum2 microsoft.... /subscriptions/{subID}/resourceGroups/{RGName}/providers/Microsoft.Storage/storageAccounts/storageAcccountnum3 storageAcccountnum3 microsoft.... /subscriptions/{subID}/resourceGroups/{RGName}/providers/Microsoft.Storage/storageAccounts/storageAccountnum4 storageAccountnum4 microsoft.... Deploying serviceGroupMember for resource: storageAcccountnum1 of type microsoft.storage/storageaccounts in subscription: XXXXXXXXXXXXXXXXX in resource group: XXXXXXXXXXXXX Using template: { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "resources": [ { "type": "Microsoft.Relationships/serviceGroupMember", "scope": "/subscriptions/{subID}/resourceGroups/{RGName}/providers/Microsoft.Storage/storageAccounts/storageAcccountnum1", "apiVersion": "2023-09-01-preview", "name": "sgm-0", "properties": { "targetId": "/providers/Microsoft.Management/serviceGroups/XXXXXXXXXXXXX" } } ] } Subscription name Tenant ----------------- ------ {subscription name} {Tenant Name} ResourceGroupName : RG Name OnErrorDeployment : DeploymentName : tmp9832.tmp CorrelationId : 123456 ProvisioningState : Succeeded Timestamp : 10/30/2025 8:44:18 PM Mode : Incremental TemplateLink : TemplateLinkString : DeploymentDebugLogLevel : Parameters : Tags : ParametersString : Outputs : OutputsString : Successfully deployed serviceGroupMember for storageAcccountnum1. Deploying serviceGroupMember for resource: storageAcccountnum2 of type microsoft.storage/storageaccounts in subscription: XXXXXXXXXX in resource group: RGName Using template: { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "resources": [ { "type": "Microsoft.Relationships/serviceGroupMember", "scope": "/subscriptions/{subID}/resourceGroups/{RGName}/providers/Microsoft.Storage/storageAccounts/storageAcccountnum2", "apiVersion": "2023-09-01-preview", "name": "sgm-1", "properties": { "targetId": "/providers/Microsoft.Management/serviceGroups/XXXXXXXXXX" } } ] } ResourceGroupName : RGName OnErrorDeployment : DeploymentName : tmpF70C.tmp CorrelationId : 1234567 ProvisioningState : Succeeded Timestamp : 10/30/2025 8:44:41 PM Mode : Incremental TemplateLink : TemplateLinkString : DeploymentDebugLogLevel : Parameters : Tags : ParametersString : Outputs : OutputsString : Successfully deployed serviceGroupMember for storageAcccountnum2. Deploying serviceGroupMember for resource: storageAcccountnum3 of type microsoft.storage/storageaccounts in subscription: XXXXXXXXXXXX in resource group: RGName Using template: { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "resources": [ { "type": "Microsoft.Relationships/serviceGroupMember", "scope": "/subscriptions/XXXXXXXXXXXXXX/resourceGroups/{RGName}/providers/Microsoft.Storage/storageAccounts/storageAcccountnum3", "apiVersion": "2023-09-01-preview", "name": "sgm-2", "properties": { "targetId": "/providers/Microsoft.Management/serviceGroups/XXXXXXXXXXX" } } ] } Switching to subscription: XXXXXXXXXXXXX Please select the account you want to login with. Retrieving subscriptions for the selection... Subscription Name Microsoft Name : Subscription Name (SubID) - Tenant ID - User ID Subscription : XXXXXXXXXXXXXXXX Account : user@microsoft.com Environment : AzureCloud Tenant : XXXXXXXXXXXXXXXX TokenCache : VersionProfile : ExtendedProperties : {} ResourceGroupName : RGName OnErrorDeployment : DeploymentName : tmp55E7.tmp CorrelationId : 12345678 ProvisioningState : Succeeded Timestamp : 10/30/2025 8:51:43 PM Mode : Incremental TemplateLink : TemplateLinkString : DeploymentDebugLogLevel : Parameters : Tags : ParametersString : Outputs : OutputsString : Successfully deployed serviceGroupMember for storageAcccountnum3. Deploying serviceGroupMember for resource: storageAcccountnum4 of type microsoft.storage/storageaccounts in subscription: XXXXXXXXXXX in resource group: RGName Using template: { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "resources": [ { "type": "Microsoft.Relationships/serviceGroupMember", "scope": "/subscriptions/XXXXXXXXXXXXXX/resourceGroups/{RGName}/providers/Microsoft.Storage/storageAccounts/storageAcccountnum4", "apiVersion": "2023-09-01-preview", "name": "sgm-3", "properties": { "targetId": "/providers/Microsoft.Management/serviceGroups/XXXXXXXXXXXXX" } } ] } ResourceGroupName : RGName OnErrorDeployment : DeploymentName : tmpBB4C.tmp CorrelationId : 123456789 ProvisioningState : Succeeded Timestamp : 10/30/2025 8:52:03 PM Mode : Incremental TemplateLink : TemplateLinkString : DeploymentDebugLogLevel : Parameters : Tags : ParametersString : Outputs : OutputsString : Successfully deployed serviceGroupMember for storageAcccountnum4. ``` ## Related content * [What are Azure Service Groups?](overview.md) * [Review available rest APIs for Service Group Members](manage-service-groups.md#create-a-service-group-member) * [Quickstart: Create a service group (preview) with REST API](create-service-group-rest-api.md) * [Quickstart: Connect resources or resource containers to service groups with Service Group Member Relationships](create-service-group-member-rest-api.md)
Success! Branch created successfully. Create Pull Request on GitHub
Error: