protected static void ProcessCollection(TfsTeamProjectCollection collection)
        {
            Console.WriteLine(String.Format("Processing collection {0}", collection.DisplayName));
            Console.WriteLine(String.Empty);

            // Get Core, security, and identity services
            ISecurityService            securityService = collection.GetService <ISecurityService>();
            SecurityNamespace           hooksSecurity   = securityService.GetSecurityNamespace(ServiceHooksSecurityNamespaceId);
            IIdentityManagementService2 identityService = collection.GetService <IIdentityManagementService2>();
            ProjectHttpClient           projectClient   = collection.GetClient <ProjectHttpClient>();

            IEnumerable <TeamProjectReference> projects = projectClient.GetProjects(stateFilter: Microsoft.TeamFoundation.Common.ProjectState.WellFormed).Result;

            // Iterate over each project, check SH permissions, and grant if needed
            foreach (var project in projects)
            {
                Console.WriteLine(String.Format("Project {0} ({1})", project.Name, project.Id));

                var groups = identityService.ListApplicationGroups(project.Id.ToString(), ReadIdentityOptions.None, null, Microsoft.TeamFoundation.Framework.Common.IdentityPropertyScope.Both);

                String adminGroupName = String.Format("vstfs:///Classification/TeamProject/{0}\\Project Administrators", project.Id);

                try
                {
                    TeamFoundationIdentity adminGroup = groups.First(g => String.Equals(g.UniqueName, adminGroupName, StringComparison.InvariantCultureIgnoreCase));

                    Console.WriteLine(" - Checking Project Administrators group permissions");

                    AccessControlEntry ace           = new AccessControlEntry(adminGroup.Descriptor, 7, 0); // 7 = view, create, delete
                    String             securityToken = "PublisherSecurity/" + project.Id;

                    bool hasPermission = hooksSecurity.HasPermission(securityToken, adminGroup.Descriptor, 7, false);

                    if (!hasPermission)
                    {
                        Console.WriteLine(" - Missing. Granting...");

                        hooksSecurity.SetAccessControlEntry(securityToken, ace, true);

                        // check permission again after granting
                        hasPermission = hooksSecurity.HasPermission(securityToken, adminGroup.Descriptor, 7, false);
                        if (hasPermission)
                        {
                            Console.WriteLine(" - Granted");
                        }
                        else
                        {
                            Console.WriteLine(" - Still does not have permission. Check to make sure it has not been explicitly denied.");
                        }
                    }
                    else
                    {
                        Console.WriteLine(" - Already has permission");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(String.Format("Admin group: Not found! ({0})", ex.Message));
                }

                Console.WriteLine("");
            }
        }
Beispiel #2
0
        public static object Run(ExportADGroupsOptions opts, string logPath)
        {
            Telemetry.Current.TrackEvent("Run-ExportADGroupsCommand");
            string exportPath = CreateExportPath(logPath, "ExportADGroups");

            Trace.Listeners.Add(new TextWriterTraceListener(Path.Combine(exportPath, "ExportADGroups.log"), "ExportADGroupsCommand"));
            Stopwatch stopwatch = Stopwatch.StartNew();
            //////////////////////////////////////////////////

            StreamWriter sw = File.CreateText(Path.Combine(exportPath, "AzureADGroups.csv"));

            sw.AutoFlush = true;
            using (var csv = new CsvWriter(sw))
            {
                csv.WriteHeader <AzureAdGroupItem>();

                TfsTeamProjectCollection sourceCollection = new TfsTeamProjectCollection(opts.CollectionURL);
                sourceCollection.EnsureAuthenticated();
                IIdentityManagementService2 sourceIMS2         = (IIdentityManagementService2)sourceCollection.GetService(typeof(IIdentityManagementService2));
                List <CatalogNode>          sourceTeamProjects = sourceCollection.CatalogNode.QueryChildren(new[] { CatalogResourceTypes.TeamProject }, false, CatalogQueryOptions.None).ToList();
                if (opts.TeamProject != null)
                {
                    sourceTeamProjects = sourceTeamProjects.Where(x => x.Resource.DisplayName == opts.TeamProject).ToList();
                }
                int current = sourceTeamProjects.Count();
                foreach (CatalogNode sourceTeamProject in sourceTeamProjects)
                {
                    Trace.WriteLine(string.Format("---------------{0}\\{1}", current, sourceTeamProjects.Count()));
                    Trace.WriteLine(string.Format("{0}, {1}", sourceTeamProject.Resource.DisplayName, sourceTeamProject.Resource.Identifier));
                    string projectUri = sourceTeamProject.Resource.Properties["ProjectUri"];
                    TeamFoundationIdentity[] appGroups = sourceIMS2.ListApplicationGroups(projectUri, ReadIdentityOptions.None);
                    foreach (TeamFoundationIdentity appGroup in appGroups.Where(x => !x.DisplayName.EndsWith("\\Project Valid Users")))
                    {
                        Trace.WriteLine(string.Format("    {0}", appGroup.DisplayName));
                        TeamFoundationIdentity sourceAppGroup = sourceIMS2.ReadIdentity(appGroup.Descriptor, MembershipQuery.Expanded, ReadIdentityOptions.None);
                        foreach (IdentityDescriptor child in sourceAppGroup.Members.Where(x => x.IdentityType == "Microsoft.TeamFoundation.Identity"))
                        {
                            TeamFoundationIdentity sourceChildIdentity = sourceIMS2.ReadIdentity(IdentitySearchFactor.Identifier, child.Identifier, MembershipQuery.None, ReadIdentityOptions.ExtendedProperties);

                            if ((string)sourceChildIdentity.GetProperty("SpecialType") == "AzureActiveDirectoryApplicationGroup")
                            {
                                Trace.WriteLine(string.Format("     Suspected AD Group {0}", sourceChildIdentity.DisplayName));
                                csv.WriteRecord <AzureAdGroupItem>(new AzureAdGroupItem
                                {
                                    TeamProject      = sourceTeamProject.Resource.DisplayName,
                                    ApplciationGroup = sourceTeamProject.Resource.DisplayName,
                                    Account          = (string)sourceChildIdentity.GetProperty("Account"),
                                    Mail             = (string)sourceChildIdentity.GetProperty("Mail"),
                                    DirectoryAlias   = (string)sourceChildIdentity.GetProperty("DirectoryAlias")
                                });
                            }
                        }
                    }
                    current--;
                    sw.Flush();
                }
            }
            sw.Close();
            //    current--;
            //}



            //////////////////////////////////////////////////
            stopwatch.Stop();
            Trace.WriteLine(string.Format(@"DONE in {0:%h} hours {0:%m} minutes {0:s\:fff} seconds", stopwatch.Elapsed));
            Trace.Listeners.Remove("ExportADGroupsCommand");
            return(0);
        }
        private static readonly string SpecialGroupName = "Service Hooks Administrators"; // assumed to be a collection-level group containing people that will have management permissions for SH in each project

        public void Run(Uri collectionUri)
        {
            Console.WriteLine("Utility to remove Service Hooks management permissions from the Project Administrators groups.");
            Console.WriteLine("");
            Console.WriteLine(" All projects in account/collection: " + collectionUri);
            Console.WriteLine("");

            Console.WriteLine("WARNING! This operation will remove the permissions.\n\n  Are you sure you want to continue (Y/N)?");
            int confirmChar = Console.In.Read();

            if (confirmChar != 'y' || confirmChar != 'Y')
            {
                return;
            }

            if (collectionUri != null)
            {
                TfsTeamProjectCollection connection = new TfsTeamProjectCollection(collectionUri);

                // Get Core, security, and identity services
                ISecurityService            securityService = connection.GetService <ISecurityService>();
                SecurityNamespace           hooksSecurity   = securityService.GetSecurityNamespace(ServiceHooksSecurityNamespaceId);
                IIdentityManagementService2 identityService = connection.GetService <IIdentityManagementService2>();
                ProjectHttpClient           projectClient   = connection.GetClient <ProjectHttpClient>();

                IEnumerable <TeamProjectReference> projects = projectClient.GetProjects(stateFilter: Microsoft.TeamFoundation.Common.ProjectState.WellFormed).Result;

                // Iterate over each project, check SH permissions, and remove if the project administrators group has access
                foreach (var project in projects)
                {
                    // Remove manage permissions from the project's administrators group (but leave it "view" access)
                    Console.WriteLine(String.Format("Project {0} ({1})", project.Name, project.Id));

                    var groups = identityService.ListApplicationGroups(project.Id.ToString(), ReadIdentityOptions.None, null, Microsoft.TeamFoundation.Framework.Common.IdentityPropertyScope.Both);

                    String adminGroupName = String.Format("vstfs:///Classification/TeamProject/{0}\\Project Administrators", project.Id);

                    try
                    {
                        TeamFoundationIdentity adminGroup = groups.First(g => String.Equals(g.UniqueName, adminGroupName, StringComparison.InvariantCultureIgnoreCase));

                        Console.WriteLine(" - Checking Project Administrators group permissions");

                        String securityToken = "PublisherSecurity/" + project.Id;

                        bool hasPermission = hooksSecurity.HasPermission(securityToken, adminGroup.Descriptor, ManagePermissions, false);

                        // Project admin group has "manage" permissions for SH in the project
                        if (hasPermission)
                        {
                            // Remove manage permissions from the project's administrators group (but leave it "view" access)
                            Console.WriteLine(" - Has permissions. Removing...");

                            // Give the admin group only view permissions
                            hooksSecurity.SetPermissions(securityToken, adminGroup.Descriptor, ViewPermissions, 0, false);

                            // check permission again after granting
                            hasPermission = hooksSecurity.HasPermission(securityToken, adminGroup.Descriptor, ManagePermissions, false);
                            if (!hasPermission)
                            {
                                Console.WriteLine(" - Verified permissions correctly removed.");
                            }
                            else
                            {
                                Console.WriteLine(" - Project Administrators Group still has manage permissions.");
                            }
                        }
                        else
                        {
                            Console.WriteLine(" - Does not have permissions to manage service hook subscriptions.");
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(String.Format("Admin group: Not found! ({0})", ex.Message));
                    }

                    Console.WriteLine("");
                }

                // Grant the group manage permissions across the entire collection
                TeamFoundationIdentity specialGroup = identityService.ReadIdentity(IdentitySearchFactor.DisplayName, SpecialGroupName, MembershipQuery.None, ReadIdentityOptions.None);

                if (specialGroup != null)
                {
                    Console.WriteLine("Granting full manage permissions to: {0}", specialGroup.UniqueName);

                    String rootSecurityToken = "PublisherSecurity/";
                    hooksSecurity.SetPermissions(rootSecurityToken, specialGroup.Descriptor, ManagePermissions, 0, false);
                }
                else
                {
                    Console.WriteLine("Could not find this group.");
                }
            }
        }
Beispiel #4
0
        public override int RunInternal(ExportAzureADOptions opts)
        {
            opts.OutPath = opts.OutPath ?? this.LogPathRoot;

            StreamWriter sw = File.CreateText(Path.Combine(opts.OutPath, "IdentityList.csv"));

            sw.AutoFlush = true;
            using (var csv = new CsvWriter(sw))
            {
                csv.WriteHeader <AzureAdGroupItem>();

                TfsTeamProjectCollection sourceCollection = new TfsTeamProjectCollection(opts.CollectionURL);
                sourceCollection.EnsureAuthenticated();
                IIdentityManagementService2 sourceIMS2         = (IIdentityManagementService2)sourceCollection.GetService(typeof(IIdentityManagementService2));
                List <CatalogNode>          sourceTeamProjects = sourceCollection.CatalogNode.QueryChildren(new[] { CatalogResourceTypes.TeamProject }, false, CatalogQueryOptions.None).ToList();
                if (opts.TeamProject != null)
                {
                    sourceTeamProjects = sourceTeamProjects.Where(x => x.Resource.DisplayName == opts.TeamProject).ToList();
                }
                int current = sourceTeamProjects.Count();
                foreach (CatalogNode sourceTeamProject in sourceTeamProjects)
                {
                    Trace.WriteLine(string.Format("---------------{0}\\{1}", current, sourceTeamProjects.Count()));
                    Trace.WriteLine(string.Format("{0}, {1}", sourceTeamProject.Resource.DisplayName, sourceTeamProject.Resource.Identifier));
                    string projectUri = sourceTeamProject.Resource.Properties["ProjectUri"];
                    TeamFoundationIdentity[] appGroups = sourceIMS2.ListApplicationGroups(projectUri, ReadIdentityOptions.None);
                    foreach (TeamFoundationIdentity appGroup in appGroups.Where(x => !x.DisplayName.EndsWith("\\Project Valid Users")))
                    {
                        Trace.WriteLine(string.Format("    {0}", appGroup.DisplayName));
                        TeamFoundationIdentity sourceAppGroup = sourceIMS2.ReadIdentity(appGroup.Descriptor, MembershipQuery.Expanded, ReadIdentityOptions.None);
                        foreach (IdentityDescriptor child in sourceAppGroup.Members.Where(x => x.IdentityType == "Microsoft.TeamFoundation.Identity" || x.IdentityType == "Microsoft.IdentityModel.Claims.ClaimsIdentity"))
                        {
                            TeamFoundationIdentity sourceChildIdentity = sourceIMS2.ReadIdentity(IdentitySearchFactor.Identifier, child.Identifier, MembershipQuery.None, ReadIdentityOptions.ExtendedProperties);
                            var    SpecialType = (string)sourceChildIdentity.GetProperty("SpecialType");
                            var    Account     = (string)sourceChildIdentity.GetProperty("Account");
                            object DirectoryAlias;
                            object Mail;
                            sourceChildIdentity.TryGetProperty("DirectoryAlias", out DirectoryAlias);
                            sourceChildIdentity.TryGetProperty("Mail", out Mail);
                            switch (SpecialType)
                            {
                            case "AzureActiveDirectoryApplicationGroup":
                                Trace.WriteLine(string.Format("     Found AD Group {0}", sourceChildIdentity.DisplayName));
                                csv.WriteRecord <AzureAdGroupItem>(new AzureAdGroupItem
                                {
                                    TeamProject      = sourceTeamProject.Resource.DisplayName,
                                    ApplciationGroup = appGroup.DisplayName,
                                    Account          = Account,
                                    Mail             = (string)Mail,
                                    DirectoryAlias   = (string)DirectoryAlias
                                });
                                break;

                            case "Generic":
                                if (sourceChildIdentity.IsContainer)
                                {
                                    Trace.WriteLine(string.Format("Skipping {0} | {1} - TF GROUP", SpecialType, Account));
                                }
                                else
                                {
                                    Trace.WriteLine(string.Format("     Found AD User {0}", sourceChildIdentity.DisplayName));
                                    csv.WriteRecord <AzureAdGroupItem>(new AzureAdGroupItem
                                    {
                                        TeamProject      = sourceTeamProject.Resource.DisplayName,
                                        ApplciationGroup = appGroup.DisplayName,
                                        Account          = Account,
                                        Mail             = (string)Mail,
                                        DirectoryAlias   = (string)DirectoryAlias
                                    });
                                }
                                break;

                            default:
                                Trace.WriteLine(string.Format("Skipping {0} | {1} - UNKNOWN", SpecialType, Account));
                                break;
                            }
                        }
                    }
                    current--;
                    sw.Flush();
                }
            }
            sw.Close();
            return(0);
        }