This can also be used to keep a pre-production environment's permissions in sync with Production.
In 2014 I was not the best at Powershell but it works :)
param ($serverName = $(throw 'please specify a TFS server name'))
function GetGroupMembership {
[CmdletBinding()]
[OutputType([System.Data.Datatable])]
PARAM (
[Parameter(Mandatory=$true, Position = 0)]
[Microsoft.TeamFoundation.Framework.Client.TeamFoundationIdentity]
$TFIdentity
)
$tabName = $TFIdentity.DisplayName + "Membership"
$table = New-Object system.Data.DataTable “$tabName”
$col1 = New-Object system.Data.DataColumn GroupName,([string])
$col2 = New-Object system.Data.DataColumn DisplayName,([string])
$col3 = New-Object system.Data.DataColumn UniqueName,([string])
#Add the Columns
$table.columns.add($col1)
$table.columns.add($col2)
$table.columns.add($col3)
#Membership
$GroupIdentity = $ims.ReadIdentity($TFIdentity.Descriptor,[Microsoft.TeamFoundation.Framework.Common.MembershipQuery]::Direct,[Microsoft.TeamFoundation.Framework.Common.ReadIdentityOptions]::TrueSid)
$members = $ims.ReadIdentities($GroupIdentity.Members,[Microsoft.TeamFoundation.Framework.Common.MembershipQuery]::Direct,[Microsoft.TeamFoundation.Framework.Common.ReadIdentityOptions]::TrueSid)
foreach($member in $members)
{
$row = $table.NewRow()
#Enter data in the row
$row.GroupName = $TFIdentity.DisplayName
$row.DisplayName = $member.DisplayName
$row.UniqueName = $member.UniqueName
#Add the row to the table
$table.Rows.Add($row)
}
return @(,$table )
}
function GetPermissions {
[CmdletBinding()]
[OutputType([System.Data.Datatable])]
PARAM (
[Parameter(Mandatory=$true, Position = 0)]
$QueryName,
[Parameter(Mandatory=$true, Position = 1)]
[Microsoft.TeamFoundation.Framework.Client.AccessControlList]
$acl,
[Parameter(Mandatory=$true, Position = 2)]
$namespace,
[Parameter(Mandatory=$true, Position = 3)]
$objectType,
[Parameter(Mandatory=$true, Position = 4)]
$objectPath
)
$PermissionstabName = $QueryName
$table = New-Object system.Data.DataTable “$PermissionstabName”
$col1 = New-Object system.Data.DataColumn ObjectPath,([string])
$col2 = New-Object system.Data.DataColumn ObjectType,([string])
$col3 = New-Object system.Data.DataColumn Name,([string])
$col4 = New-Object system.Data.DataColumn Permission,([string])
$col5 = New-Object system.Data.DataColumn Value,([string])
#Add the Columns
$table.columns.add($col1)
$table.columns.add($col2)
$table.columns.add($col3)
$table.columns.add($col4)
$table.columns.add($col5)
foreach ($ace in $acl.AccessControlEntries)
{
if ($ace.IsEmpty)
{
continue
}
$haspermission = $false
$DenyPermissions = @{}
$CalculatedPermissions = @{}
$AllowPermissions = @{}
foreach ($action in $namespace.description.Actions)
{
$allowed = ($action.bit -band $ace.Allow)
$denied = ($action.bit -band $ace.Deny)
if (-not $allowed -and -not $denied)
{
continue
}
$haspermission =$true
if ($allowed)
{
$CalculatedPermissions.Add($action.Name,"Allow")
$AllowPermissions.Add($action.Name,$action.Name)
}
else
{
$CalculatedPermissions.Add($action.Name,"Deny")
$DenyPermissions.Add($action.Name,$action.Name)
}
}
if ($haspermission)
{
$identity = $ims.ReadIdentity($ace.Descriptor,[Microsoft.TeamFoundation.Framework.Common.MembershipQuery]::None,[Microsoft.TeamFoundation.Framework.Common.ReadIdentityOptions]::IncludeReadFromSource)
$name = $identity.DisplayName
Foreach($permission in $CalculatedPermissions.GetEnumerator())
{
$row = $table.NewRow()
#Enter data in the row
$row.ObjectPath = $objectPath
$row.ObjectType = $objectType
$row.Name = $name
$row.Permission = $permission.Name
$row.Value = $permission.value
#Add the row to the table
$table.Rows.Add($row)
}
}
}
return @(,$table )
}
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.TeamFoundation.Client')
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.TeamFoundation.VersionControl.Client')
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.TeamFoundation.WorkItemTracking.Client')
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.TeamFoundation.Build.Client')
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.TeamFoundation.Build.Common')
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.TeamFoundation')
$tfs = [Microsoft.TeamFoundation.Client.TeamFoundationServerFactory]::GetServer($serverName)
$css = $tfs.GetService([Microsoft.TeamFoundation.Server.ICommonStructureService])
$auth = $tfs.GetService([Microsoft.TeamFoundation.Server.IAuthorizationService])
$gss = $tfs.GetService([Microsoft.TeamFoundation.Server.IGroupSecurityService])
$ss = $tfs.GetService([Microsoft.TeamFoundation.Framework.Client.ISecurityService])
$vcs = $tfs.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
$ims = $tfs.GetService([Microsoft.TeamFoundation.Framework.Client.IIdentityManagementService])
$wis = $tfs.GetService([Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemStore])
$cssNamespace = $ss.GetSecurityNamespace([Microsoft.TeamFoundation.Server.AuthorizationSecurityConstants]::CommonStructureNodeSecurityGuid)
$membershipds = New-Object System.Data.DataSet
$permissiondt = New-Object System.Data.DataSet
$Objectpermissiondt = New-Object System.Data.DataSet
#get all TPC Groups
$tpcGroups = $IMS.ListApplicationGroups($null, [Microsoft.TeamFoundation.Framework.Common.ReadIdentityOptions]::None)
foreach ($tpcgroup in $tpcGroups)
{
$members = GetGroupMembership $tpcgroup
if ($members.rows.count -gt 0)
{
$membershipds.Tables.Add($members)
}
}
$Namespaces = $ss.GetSecurityNamespaces()
#Get all the permissions for top level NameSpaces
foreach($namespace in $Namespaces)
{
$NameSpaceToken = ""
switch ($namespace.Description.DisplayName)
{
"Server" { $NameSpaceToken = [Microsoft.TeamFoundation.Framework.Common.FrameworkSecurity]::FrameworkNamespaceToken}
"Build" { $NameSpaceToken = [Microsoft.TeamFoundation.Build.Common.BuildSecurity]::PrivilegesToken}
"BuildAdministration" { $NameSpaceToken = [Microsoft.TeamFoundation.Build.Common.BuildSecurity]::PrivilegesToken}
"Workspaces" { $NameSpaceToken = [Microsoft.TeamFoundation.VersionControl.Common.SecurityConstants]::GlobalSecurityResource}
"Collection" {}#Namespace:
"WorkItemTrackingAdministration" {} #
"CSS" { }
"Iteration" {}
"VersionControlPrivileges" {$NameSpaceToken = [Microsoft.TeamFoundation.VersionControl.Common.SecurityConstants]::GlobalSecurityResource}
"WorkItemQueryFolders" {}
"Project" { $NameSpaceToken = [Microsoft.TeamFoundation.PermissionNamespaces]::Project}
default
{
continue
}
}
try
{
$groupAcl = $namespace.QueryAccessControlList($NameSpaceToken,$null,$false)
$table = GetPermissions $namespace.Discription.Name $groupAcl $namespace "Group" $namespace.Discription.Name
$permissiondt.Tables.Add($table)
}
Catch
{
}
}
foreach ($project in $css.ListProjects())
{
$projectGroups = $IMS.ListApplicationGroups($project.Uri,[Microsoft.TeamFoundation.Framework.Common.ReadIdentityOptions]::TrueSid)
foreach($group in $projectGroups)
{
#only get the groups we care about
if ($group.DisplayName -eq "[$($project.Name)]\Build Administrators" -or $group.DisplayName -eq "[$($project.Name)]\Project Administrators" -or $group.DisplayName -eq "[$($project.Name)]\Contributors" -or $group.DisplayName -eq "[$($project.Name)]\Readers")
{
}
else
{
continue;
}
$members = GetGroupMembership $group
if ($members.rows.count -gt 0)
{
$membershipds.Tables.Add($members)
}
$projectsecNameSpace = $ss.GetSecurityNamespace([Microsoft.TeamFoundation.Server.AuthorizationSecurityConstants]::ProjectSecurityGuid)
#Get Project Permissions
$ProjectSecurityToken = [Microsoft.TeamFoundation.Server.AuthorizationSecurityConstants]::ProjectSecurityPrefix + $project.Uri
$groupacl = $projectsecNameSpace.QueryAccessControlList($ProjectSecurityToken, [Microsoft.TeamFoundation.Framework.Client.IdentityDescriptor[]]@($group.descriptor), $false)
$table = GetPermissions $group.DisplayName $groupAcl $projectsecNameSpace "Project" $project.Name
$permissiondt.Tables.Add($table)
#Get Top Level Build Permissions for the Project
$BuildsecNameSpace = $ss.GetSecurityNamespace([Microsoft.TeamFoundation.Build.Common.BuildSecurity]::BuildNamespaceId)
$teamProjectGuid = [Microsoft.TeamFoundation.LinkingUtilities]::DecodeUri($project.Uri).ToolSpecificId
$groupacl = $BuildsecNameSpace.QueryAccessControlList($teamProjectGuid, $null, $false)
$tablename = $group.DisplayName + "Build Permissions"
$table = GetPermissions $tablename $groupAcl $BuildsecNameSpace "Build" $project.Name
$permissiondt.Tables.Add($table)
}
#Get Root Area Path Permissions
$rootAreaNodeACL = $cssNamespace.QueryAccessControlList($wis.Projects[$project.Name].AreaRootNodeUri,$null,$false)
$table = GetPermissions "$($project.Name) Root AreaPath Permissions" $rootAreaNodeACL $cssNamespace "Area Path" $wis.Projects[$project.Name].Name
$Objectpermissiondt.Tables.Add($table)
#Get Child Area Path Permissions
foreach ($area in $wis.Projects[$project.Name].AreaRootNodes)
{
$areapath = $area.Path
$areaseclist = $cssNamespace.QueryAccessControlList($area.uri, $null, $true)
$table = GetPermissions "$areapath AreaPath Permissions" $areaseclist $cssNamespace "Area Path" $areapath
$Objectpermissiondt.Tables.Add($table)
}
try
{
$vcproject = $vcs.TryGetTeamProject($project.Name)
}
catch
{
continue
}
#Get Version Control permissions on all VC objects
$vcAcls = $vcs.GetPermissions(@($vcproject.ServerItem), [Microsoft.TeamFoundation.VersionControl.Client.RecursionType]::Full)
$table = New-Object system.Data.DataTable "$($project.Name)VCPermissions"
$col1 = New-Object system.Data.DataColumn ObjectPath,([string])
$col2 = New-Object system.Data.DataColumn ObjectType,([string])
$col3 = New-Object system.Data.DataColumn Name,([string])
$col4 = New-Object system.Data.DataColumn Permission,([string])
$col5 = New-Object system.Data.DataColumn Value,([string])
#Add the Columns
$table.columns.add($col1)
$table.columns.add($col2)
$table.columns.add($col3)
$table.columns.add($col4)
$table.columns.add($col5)
foreach($perm in $vcAcls)
{
foreach($entry in $perm.Entries)
{
foreach($allow in $entry.Allow)
{
$row = $table.NewRow()
$row.ObjectPath = $perm.ServerItem
$row.ObjectType = "VC"
$row.Name = $entry.IdentityName
$row.Permission = $allow
$row.Value = "allow"
#Add the row to the table
$table.Rows.Add($row)
}
foreach($deny in $entry.Deny)
{
$row = $table.NewRow()
$row.ObjectPath = $perm.ServerItem
$row.ObjectType = "VC"
$row.Name = $entry.IdentityName
$row.Permission = $deny
$row.Value = "deny"
#Add the row to the table
$table.Rows.Add($row)
}
}
}
$Objectpermissiondt.Tables.Add($table)
}
$membershipds.Tables | Format-Table -AutoSize
$permissiondt.Tables | Format-Table -AutoSize
$Objectpermissiondt.Tables | Format-Table -AutoSize