private static async Task RunAsync(string orgName, string outputFileName, string cacheLocation) { var isForExcel = outputFileName == null; var client = await GitHubClientFactory.CreateAsync(); var cachedOrg = await CachedOrg.LoadAsync(client, orgName, Console.Out, cacheLocation, forceUpdate : false); var csvDocument = new CsvDocument("repo", "repo-state", "repo-last-pushed", "principal-kind", "principal", "permission", "via-team"); using (var writer = csvDocument.Append()) { foreach (var repo in cachedOrg.Repos) { var publicPrivate = repo.IsPrivate ? "private" : "public"; var lastPush = repo.LastPush.ToLocalTime().DateTime.ToString(); foreach (var teamAccess in repo.Teams) { var permissions = teamAccess.Permission.ToString().ToLower(); var teamName = teamAccess.Team.Name; var teamUrl = teamAccess.Team.Url; writer.WriteHyperlink(repo.Url, repo.Name, isForExcel); writer.Write(publicPrivate); writer.Write(lastPush); writer.Write("team"); writer.WriteHyperlink(teamUrl, teamName, isForExcel); writer.Write(permissions); writer.Write(teamName); writer.WriteLine(); } foreach (var userAccess in repo.Users) { var via = userAccess.Describe().ToString(); var userUrl = CachedOrg.GetUserUrl(userAccess.UserLogin); var permissions = userAccess.Permission.ToString().ToLower(); writer.WriteHyperlink(repo.Url, repo.Name, isForExcel); writer.Write(publicPrivate); writer.Write(lastPush); writer.Write("user"); writer.WriteHyperlink(userUrl, userAccess.UserLogin, isForExcel); writer.Write(permissions); writer.Write(via); writer.WriteLine(); } } } if (outputFileName == null) { csvDocument.ViewInExcel(); } else { csvDocument.Save(outputFileName); } }
private static IReadOnlyCollection <CachedUser> ComputeAssignees(CachedOrg org, CachedRepo repo, CachedTeam team, CachedUser user, IReadOnlyCollection <CachedUser> assignees) { if (assignees != null && assignees.Count > 0) { return(assignees); } if (repo != null) { return(repo.GetAdministrators().ToArray()); } if (team != null) { return(team.GetMaintainers().ToArray()); } if (user != null) { return new[] { user } } ; return(org.GetOwners().ToArray()); }
public PolicyViolation(PolicyDescriptor descriptor, string title, string body, CachedOrg org, CachedRepo repo = null, CachedTeam team = null, CachedUser user = null, IReadOnlyCollection <CachedUser> assignees = null) { Descriptor = descriptor; Fingerprint = ComputeFingerprint(descriptor.DiagnosticId, repo, user, team); Title = title; Body = UnindentAndTrim(body); Org = org; Repo = repo; Team = team; User = user; Assignees = ComputeAssignees(org, repo, team, user, assignees); }
private static async Task RunAsync(string orgName, string outputFileName, string cacheLocation, string githubToken, string ospoToken, string policyRepo) { var isForExcel = outputFileName == null; var gitHubClient = await GitHubClientFactory.CreateAsync(githubToken); var ospoClient = await OspoClientFactory.CreateAsync(ospoToken); var cachedOrg = await CachedOrg.LoadAsync(gitHubClient, orgName, Console.Out, cacheLocation, forceUpdate : false); var userLinks = await MicrosoftUserLinks.LoadAsync(ospoClient); var context = new PolicyAnalysisContext(cachedOrg, userLinks); var violations = PolicyRunner.Run(context); SaveVioloations(orgName, outputFileName, isForExcel, violations); if (!string.IsNullOrEmpty(policyRepo)) { await FilePolicyViolationsAsync(gitHubClient, orgName, policyRepo, violations); } }
private static Func <CachedUser, bool> CreateUserFilter(CachedOrg cachedOrg, List <string> logins) { if (!logins.Any()) { return(_ => true); } var userByLogin = cachedOrg.Users.ToDictionary(u => u.Login, StringComparer.OrdinalIgnoreCase); var includedUsers = new HashSet <CachedUser>(); foreach (var login in logins) { if (!userByLogin.TryGetValue(login, out var user)) { Console.Error.WriteLine($"warning: User '{login}' doesn't exist"); } else { includedUsers.Add(user); } } return(includedUsers.Contains); }
private static Func <CachedTeam, bool> CreateTeamFilter(CachedOrg cachedOrg, List <string> names) { if (!names.Any()) { return(_ => true); } var teamByName = cachedOrg.Teams.ToDictionary(t => t.Name, StringComparer.OrdinalIgnoreCase); var includedTeams = new HashSet <CachedTeam>(); foreach (var name in names) { if (!teamByName.TryGetValue(name, out var team)) { Console.Error.WriteLine($"warning: Team '{name}' doesn't exist"); } else { includedTeams.Add(team); } } return(includedTeams.Contains); }
private static Func <CachedRepo, bool> CreateRepoFilter(CachedOrg cachedOrg, List <string> names) { if (!names.Any()) { return(_ => true); } var repoByName = cachedOrg.Repos.ToDictionary(r => r.Name, StringComparer.OrdinalIgnoreCase); var includedRepos = new HashSet <CachedRepo>(); foreach (var name in names) { if (!repoByName.TryGetValue(name, out var repo)) { Console.Error.WriteLine($"warning: Repo '{name}' doesn't exist"); } else { includedRepos.Add(repo); } } return(includedRepos.Contains); }
public PolicyAnalysisContext(CachedOrg org, MicrosoftUserLinks userLinks) { Org = org; UserLinks = userLinks; }
private static async Task RunAsync(string orgName, List <string> repoNames, List <string> teamNames, List <string> userNames, string outputFileName, string cacheLocation) { Console.WriteLine("Loading org data..."); var cachedOrg = await CachedOrg.LoadFromCacheAsync(orgName, cacheLocation); if (cachedOrg == null) { Console.Error.WriteLine("The org wasn't loaded yet or the cache isn't valid anymore."); return; } var repoFilter = CreateRepoFilter(cachedOrg, repoNames); var teamFilter = CreateTeamFilter(cachedOrg, teamNames); var userFilter = CreateUserFilter(cachedOrg, userNames); Console.WriteLine("Loading Microsoft links..."); var ospoClient = await OspoClientFactory.CreateAsync(); var links = await ospoClient.GetAllAsync(); Console.WriteLine("Computing result..."); var emailByUser = new Dictionary <CachedUser, string>(); var nameByUser = new Dictionary <CachedUser, string>(); var microsoftLink = links.ToDictionary(l => l.GitHubInfo.Login); foreach (var user in cachedOrg.Users) { emailByUser[user] = user.Email; nameByUser[user] = user.Name; if (microsoftLink.TryGetValue(user.Login, out var link)) { if (!string.IsNullOrEmpty(link.MicrosoftInfo.EmailAddress)) { emailByUser[user] = link.MicrosoftInfo.EmailAddress; } if (!string.IsNullOrEmpty(link.MicrosoftInfo.PreferredName)) { nameByUser[user] = link.MicrosoftInfo.PreferredName; } } } var isForExcel = outputFileName == null; var csvDocument = new CsvDocument("team", "repo", "user", "user-name", "user-email", "is-microsoft", "change", "repo-admins"); using (var writer = csvDocument.Append()) { foreach (var userAccess in cachedOrg.Collaborators) { var repo = userAccess.Repo; var user = userAccess.User; if (!repoFilter(repo) || !userFilter(user)) { continue; } foreach (var team in cachedOrg.Teams) { if (!teamFilter(team)) { continue; } var whatIfRemoved = userAccess.WhatIfRemovedFromTeam(team); var change = whatIfRemoved.ToString(); if (whatIfRemoved.IsUnchanged) { continue; } var isMicrosoft = microsoftLink.ContainsKey(user.Login) ? "Yes" : "No"; var repoAdmins = repo.GetAdministrators() .Select(u => (Email: emailByUser[u], Name: nameByUser[u])) .Where(t => !string.IsNullOrEmpty(t.Email)) .Select(t => $"{t.Name}<{t.Email}>"); var repoAdminList = string.Join("; ", repoAdmins); writer.WriteHyperlink(team.Url, team.Name, isForExcel); writer.WriteHyperlink(repo.Url, repo.Name, isForExcel); writer.WriteHyperlink(user.Url, user.Login, isForExcel); writer.Write(nameByUser[user]); writer.Write(emailByUser[user]); writer.Write(isMicrosoft); writer.Write(change); writer.Write(repoAdminList); writer.WriteLine(); } } } if (outputFileName != null) { csvDocument.Save(outputFileName); } else { csvDocument.ViewInExcel(); } }
public static IEnumerable <CachedUser> GetOwners(this CachedOrg org) { return(org.Users.Where(u => u.IsOwner && !u.IsBot())); }
public static CachedTeam GetBotsTeam(this CachedOrg org) { return(org.Teams.SingleOrDefault(t => string.Equals(t.Name, "bots", StringComparison.OrdinalIgnoreCase))); }