public async static Task CheckBypassRulesPermission(WorkItemClientConnection client, string project) { try { var securityHttpClient = client.Connection.GetClient <SecurityHttpClient>(); var namespaces = await securityHttpClient.QuerySecurityNamespacesAsync(ProjectSecurityNamespace); if (namespaces.SelectMany(n => n.Actions).Any(a => a.Bit == BypassRulesPermission)) { await CheckPermission(client, project, ProjectSecurityNamespace, BypassRulesPermission); await CheckPermission(client, project, ProjectSecurityNamespace, SuppressNotificationsPermission); Logger.LogSuccess(LogDestination.All, $"Verified {client.Connection.AuthorizedIdentity.DisplayName} has bypass rules permission in {project}"); return; } } catch (ValidationException) { // no op, fallback to the legacy check } catch (Exception e) when(e.InnerException is VssUnauthorizedException) { throw new ValidationException(client.Connection.Uri.ToString(), (VssUnauthorizedException)e.InnerException); } catch (Exception e) { throw new ValidationException("An unexpected error occurred while validating project permissions", e); } // granular permissions not available, or the check failed. falling back to legacy PCA check await CheckLegacyBypassRulesPermission(client, project); }
private async static Task CheckProjectPermission(WorkItemClientConnection client, string project, int requestedPermission) { Logger.LogInformation($"Checking project security permissions for {client.Connection.AuthorizedIdentity.DisplayName} in {project}"); SecurityHttpClient securityHttpClient = null; ProjectHttpClient projectHttpClient = null; TeamProject teamProject = null; try { securityHttpClient = client.Connection.GetClient <SecurityHttpClient>(); projectHttpClient = client.Connection.GetClient <ProjectHttpClient>(); teamProject = await projectHttpClient.GetProject(project); } catch (Exception e) when(e.InnerException is VssUnauthorizedException) { throw new ValidationException(client.Connection.Uri.ToString(), (VssUnauthorizedException)e.InnerException); } catch (Exception e) { throw new ValidationException("An unexpected error occurred while reading the classification nodes to validate project permissions", e); } await HasPermission(securityHttpClient, project, $"$PROJECT:vstfs:///Classification/TeamProject/{teamProject.Id}", ProjectSecurityNamespace, requestedPermission); }
public async static Task CheckConnection(WorkItemClientConnection client, string project, int requestedPermission) { Logger.LogInformation($"Checking security permissions for {client.Connection.AuthorizedIdentity.DisplayName} in {project}"); bool hasPermission = false; SecurityHttpClient securityHttpClient = null; WorkItemClassificationNode result = null; try { securityHttpClient = client.Connection.GetClient <SecurityHttpClient>(); result = await WorkItemTrackingHelpers.GetClassificationNode(client.WorkItemTrackingHttpClient, project, TreeStructureGroup.Areas); } catch (Exception e) when(e.InnerException is VssUnauthorizedException) { throw new ValidationException(client.Connection.Uri.ToString(), (VssUnauthorizedException)e.InnerException); } catch (Exception e) { throw new ValidationException("An unexpected error occurred while reading the classification nodes to validate project permissions", e); } //construct the token by appending the id string token = $"vstfs:///Classification/Node/{result.Identifier}"; //WORK_ITEM guid is hardcoded below //securityNameSpaceId for WORK_ITEM is 83e28ad4-2d72-4ceb-97b0-c7726d5502c3 try { hasPermission = await securityHttpClient.HasPermissionAsync( new Guid("83e28ad4-2d72-4ceb-97b0-c7726d5502c3"), token, requestedPermission, false); } catch (Exception e) { throw new ValidationException($"An unexpected error occurred while trying to check permissions for project {project}", e); } if (hasPermission) { Logger.LogSuccess(LogDestination.All, $"Verified security permissions for {project} project"); } else { throw new ValidationException($"You do not have the necessary security permissions for {project}, work item {(requestedPermission == WritePermission ? "write" : "read")} permissions are required."); } }
private async static Task CheckPermission(WorkItemClientConnection client, string project, Guid securityNamespace, int requestedPermission) { Logger.LogInformation($"Checking security permissions for {client.Connection.AuthorizedIdentity.DisplayName} in {project}"); bool hasPermission = false; SecurityHttpClient securityHttpClient = null; WorkItemClassificationNode result = null; try { securityHttpClient = client.Connection.GetClient <SecurityHttpClient>(); result = await WorkItemTrackingHelpers.GetClassificationNode(client.WorkItemTrackingHttpClient, project, TreeStructureGroup.Areas); } catch (Exception e) when(e.InnerException is VssUnauthorizedException) { throw new ValidationException(client.Connection.Uri.ToString(), (VssUnauthorizedException)e.InnerException); } catch (Exception e) { throw new ValidationException("An unexpected error occurred while reading the classification nodes to validate project permissions", e); } //construct the token by appending the id string token = $"vstfs:///Classification/Node/{result.Identifier}"; try { hasPermission = await securityHttpClient.HasPermissionAsync( securityNamespace, token, requestedPermission, false); } catch (Exception e) { throw new ValidationException($"An unexpected error occurred while trying to check permissions for project {project} in namespace {securityNamespace}", e); } if (hasPermission) { Logger.LogSuccess(LogDestination.All, $"Verified security permissions for {project} project"); } else { throw new ValidationException($"You do not have the necessary security permissions for {project}, work item permission: {requestedPermission} is required."); } }
public async static Task CheckIdentity(WorkItemClientConnection client, string project) { IdentityHttpClient targetIdentityClient = null; var currentUserIdentity = client.Connection.AuthorizedIdentity; IdentityDescriptor adminId = null; Logger.LogInformation($"Checking administrative permissions for {client.Connection.AuthorizedIdentity.DisplayName} in {project}"); try { targetIdentityClient = client.Connection.GetClient <IdentityHttpClient>(); var targetIdentity = (await targetIdentityClient.ReadIdentitiesAsync(IdentitySearchFilter.General, "Project Collection Administrators", queryMembership: QueryMembership.Expanded)).FirstOrDefault(); if (targetIdentity != null) { //Check if the current user account running the tool is a member of project collection administrators #region HackRegion adminId = targetIdentity.Members.Where(a => string.Equals(a.Identifier, currentUserIdentity.Descriptor.Identifier, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); //We can replace the above code with the following two statements when they work //var me = targetIdentityClient.GetIdentitySelfAsync().Result; //var isMember = targetIdentityClient.IsMember(targetIdentity.Descriptor, currentUserIdentity.Descriptor).Result; #endregion } } catch (Exception e) when(e.InnerException is VssUnauthorizedException) { throw new ValidationException(client.Connection.Uri.ToString(), (VssUnauthorizedException)e.InnerException); } catch (Exception e) { throw new ValidationException("An unexpected error occurred while checking administrative permissions", e); } if (adminId != null) { Logger.LogSuccess(LogDestination.All, $"Verified {client.Connection.AuthorizedIdentity.DisplayName} is a Project Collection Administrator in {project}"); } else { throw new ValidationException($"{currentUserIdentity.Descriptor.Identifier} is not a Project Collection Administrator in {project}. Please follow https://www.visualstudio.com/en-us/docs/setup-admin/add-administrator-tfs on how to add the account to the project collection administrators"); } }
private async static Task CheckCssPermission(WorkItemClientConnection client, string project, int requestedPermission) { Logger.LogInformation($"Checking css security permissions for {client.Connection.AuthorizedIdentity.DisplayName} in {project}"); SecurityHttpClient securityHttpClient = null; WorkItemClassificationNode result = null; try { securityHttpClient = client.Connection.GetClient <SecurityHttpClient>(); result = await WorkItemTrackingHelpers.GetClassificationNode(client.WorkItemTrackingHttpClient, project, TreeStructureGroup.Areas); } catch (Exception e) when(e.InnerException is VssUnauthorizedException) { throw new ValidationException(client.Connection.Uri.ToString(), (VssUnauthorizedException)e.InnerException); } catch (Exception e) { throw new ValidationException("An unexpected error occurred while reading the classification nodes to validate project permissions", e); } await HasPermission(securityHttpClient, project, $"vstfs:///Classification/Node/{result.Identifier}", CssSecurityNamespace, requestedPermission); }
public async static Task CheckReadPermission(WorkItemClientConnection client, string project) { await CheckPermission(client, project, CssSecurityNamespace, ReadPermission); }
public async static Task CheckReadPermission(WorkItemClientConnection client, string project) { await CheckCssPermission(client, project, ReadPermission); }