-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
Is there an existing issue for this?
- I have searched the existing issues
Azure.DevOps.PSModule version
0.2.2
Related function
Get-AdoMembership, Add-AdoGroupMember, Remove-AdoMembership (proposed)
Use case
As a DevOps Engineer managing Azure DevOps organization identity and access management
I want a generic Add-AdoMembership cmdlet that directly uses subject and container descriptors to create membership relationships
So that I can have a consistent, descriptor-based API surface that aligns with Get-AdoMembership and Remove-AdoMembership, enabling more flexible membership management workflows without needing to know origin IDs
Notes
- Currently,
Add-AdoGroupMemberexists but uses a different API endpoint (/graph/groups) and requires an OriginId parameter - The Memberships API (
/graph/memberships/{subjectDescriptor}/{containerDescriptor}) provides a more direct approach using descriptors - Having
Get-AdoMembership,Add-AdoMembership, andRemove-AdoMembershipcreates a consistent, intuitive cmdlet family - The descriptor-based approach is more flexible as it works with any subject/container relationship
- Users already have descriptors from
Get-AdoGroup,Get-AdoDescriptor, or other cmdlets - no need to track origin IDs - Enables symmetrical operations: if you can GET and REMOVE memberships by descriptor, you should be able to ADD them the same way
Proposed solution
Create an Add-AdoMembership cmdlet that complements the existing membership management cmdlets:
Cmdlet Signature
function Add-AdoMembership {
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')]
param (
[Parameter(ValueFromPipelineByPropertyName)]
[ValidateScript({ Confirm-CollectionUri -Uri $_ })]
[string]$CollectionUri = ($env:DefaultAdoCollectionUri -replace 'https://', 'https://vssps.'),
[Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)]
[string[]]$SubjectDescriptor,
[Parameter(Mandatory, ValueFromPipelineByPropertyName)]
[string]$ContainerDescriptor,
[Parameter()]
[Alias('ApiVersion')]
[ValidateSet('7.1-preview.1', '7.2-preview.1')]
[string]$Version = '7.1-preview.1'
)
}Key Features
- PUT HTTP Method: Calls the Azure DevOps Graph API using PUT method
- Descriptor-Based: Works directly with subject and container descriptors (no origin ID needed)
- Pipeline Support: Accept
SubjectDescriptorfrom pipeline for bulk operations - Confirmation Prompts: Include
-WhatIfand-Confirmsupport for safe operations - Descriptor Validation: Validate descriptor format before API calls
- Error Handling: Clear error messages for invalid descriptors or existing memberships
- Consistency: Matches parameter patterns with
Get-AdoMembershipandRemove-AdoMembership - Idempotency: Handle cases where membership already exists gracefully
API Endpoint
PUT https://vssps.dev.azure.com/{organization}/_apis/graph/memberships/{subjectDescriptor}/{containerDescriptor}?api-version=7.1-preview.1
Example Usage
# Add a single membership using descriptors
$params = @{
CollectionUri = 'https://vssps.dev.azure.com/my-org'
SubjectDescriptor = 'aadgp.00000000-0000-0000-0000-000000000000'
ContainerDescriptor = 'vssgp.00000000-0000-0000-0000-000000000001'
}
Add-AdoMembership @params
# Add multiple users to a group via pipeline
$userDescriptors = @(
'aad.MDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAy',
'aad.MDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAz'
)
$userDescriptors | Add-AdoMembership @params
# Retrieve group members and add them to another group
$params = @{
CollectionUri = 'https://vssps.dev.azure.com/my-org'
}
$sourceGroup = Get-AdoGroup @params -GroupName 'Developers'
$targetGroup = Get-AdoGroup @params -GroupName 'Contributors'
Get-AdoMembership @params -ContainerDescriptor $sourceGroup.descriptor |
Add-AdoMembership @params -ContainerDescriptor $targetGroup.descriptor
# Preview changes without executing
Add-AdoMembership @params -WhatIf
# Add without confirmation prompt (automation scenarios)
Add-AdoMembership @params -Confirm:$falseComparison: Add-AdoGroupMember vs Add-AdoMembership
| Aspect | Add-AdoGroupMember | Add-AdoMembership |
|---|---|---|
| API Endpoint | /graph/groups |
/graph/memberships |
| HTTP Method | POST | PUT |
| Primary Parameter | OriginId (GUID) | SubjectDescriptor (string) |
| Use Case | Add Entra ID groups by origin ID | Add any subject by descriptor |
| Requires | Knowledge of origin ID | Only descriptor (from Get cmdlets) |
| Naming Pattern | Group-specific operation | Generic membership operation |
| Consistency | Different from Get/Remove | Matches Get-AdoMembership pattern |
Implementation Checklist
- Create
Add-AdoMembership.ps1insrc/Azure.DevOps.PSModule/Public/Graph/Memberships/ - Implement comprehensive Pester tests in
src/Azure.DevOps.PSModule/Tests/Graph/Memberships/Add-AdoMembership.Tests.ps1 - Generate PlatyPS documentation in
docs/Add-AdoMembership.md - Update module manifest to export the new cmdlet
- Add usage examples to README
- Update CHANGELOG with new feature
- Document relationship with existing
Add-AdoGroupMembercmdlet
Benefits
- Consistency: Creates a unified membership management API surface (Get, Add, Remove)
- Flexibility: Works with descriptors from any source, not just origin IDs
- Discoverability: Intuitive naming - users looking for membership operations find all related cmdlets
- Simplicity: Simpler workflows when descriptors are already available from other cmdlets
- Pipeline-Friendly: Enables chaining operations with other descriptor-based cmdlets
- Completeness: Provides full CRUD operations for membership management
Relationship with Add-AdoGroupMember
Add-AdoGroupMemberremains valuable for specific Entra ID group scenarios where origin ID is readily availableAdd-AdoMembershipprovides a more generic, descriptor-based alternative- Both cmdlets can coexist, serving different use cases
- Consider
Add-AdoGroupMemberas a specialized convenience wrapper Add-AdoMembershipaligns better with the Get/Remove cmdlet patterns
Testing Scenarios
- Successfully add a valid membership relationship
- Handle existing membership gracefully (idempotency)
- Validate proper error handling for invalid descriptors
- Confirm pipeline input processing for bulk operations
- Verify
-WhatIfand-Confirmbehavior - Test with AAD, AADGP, and VSSGP descriptor types
- Validate API version parameter functionality
- Test subject-to-subject and subject-to-container relationships
- Verify error handling for insufficient permissions
- Test edge cases (self-referencing, circular dependencies)
Migration Path
For users currently using Add-AdoGroupMember, provide guidance:
# Old pattern (using Add-AdoGroupMember with OriginId)
Add-AdoGroupMember -GroupDescriptor $groupDesc -OriginId $originId
# New pattern (using Add-AdoMembership with SubjectDescriptor)
# First get the descriptor from origin ID if needed
$subject = Get-AdoGroup -OriginId $originId
Add-AdoMembership -SubjectDescriptor $subject.descriptor -ContainerDescriptor $groupDesc
# Or even better - pipe directly
Get-AdoGroup -OriginId $originId |
Add-AdoMembership -ContainerDescriptor $groupDescReactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Type
Projects
Status
Backlog