diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/AuthorizationHandlers/AccessPolicies/AccessPolicyAuthorizationHandler.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/AuthorizationHandlers/AccessPolicies/AccessPolicyAuthorizationHandler.cs deleted file mode 100644 index 4cb90223e..000000000 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/AuthorizationHandlers/AccessPolicies/AccessPolicyAuthorizationHandler.cs +++ /dev/null @@ -1,267 +0,0 @@ -using Bit.Core.AdminConsole.Repositories; -using Bit.Core.Context; -using Bit.Core.Enums; -using Bit.Core.Repositories; -using Bit.Core.SecretsManager.AuthorizationRequirements; -using Bit.Core.SecretsManager.Entities; -using Bit.Core.SecretsManager.Queries.Interfaces; -using Bit.Core.SecretsManager.Repositories; -using Microsoft.AspNetCore.Authorization; - -namespace Bit.Commercial.Core.SecretsManager.AuthorizationHandlers.AccessPolicies; - -public class AccessPolicyAuthorizationHandler : AuthorizationHandler -{ - private readonly ICurrentContext _currentContext; - private readonly IAccessClientQuery _accessClientQuery; - private readonly IGroupRepository _groupRepository; - private readonly IOrganizationUserRepository _organizationUserRepository; - private readonly IProjectRepository _projectRepository; - private readonly IServiceAccountRepository _serviceAccountRepository; - - public AccessPolicyAuthorizationHandler(ICurrentContext currentContext, - IAccessClientQuery accessClientQuery, - IGroupRepository groupRepository, - IOrganizationUserRepository organizationUserRepository, - IProjectRepository projectRepository, - IServiceAccountRepository serviceAccountRepository) - { - _currentContext = currentContext; - _accessClientQuery = accessClientQuery; - _groupRepository = groupRepository; - _organizationUserRepository = organizationUserRepository; - _projectRepository = projectRepository; - _serviceAccountRepository = serviceAccountRepository; - } - - protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, - AccessPolicyOperationRequirement requirement, - BaseAccessPolicy resource) - { - switch (requirement) - { - case not null when requirement == AccessPolicyOperations.Create: - await CanCreateAccessPolicyAsync(context, requirement, resource); - break; - case not null when requirement == AccessPolicyOperations.Update: - await CanUpdateAccessPolicyAsync(context, requirement, resource); - break; - case not null when requirement == AccessPolicyOperations.Delete: - await CanDeleteAccessPolicyAsync(context, requirement, resource); - break; - default: - throw new ArgumentException("Unsupported operation requirement type provided.", - nameof(requirement)); - } - } - - private async Task CanCreateAccessPolicyAsync(AuthorizationHandlerContext context, - AccessPolicyOperationRequirement requirement, BaseAccessPolicy resource) - { - switch (resource) - { - case UserProjectAccessPolicy ap: - await CanCreateAsync(context, requirement, ap); - break; - case GroupProjectAccessPolicy ap: - await CanCreateAsync(context, requirement, ap); - break; - case ServiceAccountProjectAccessPolicy ap: - await CanCreateAsync(context, requirement, ap); - break; - case UserServiceAccountAccessPolicy ap: - await CanCreateAsync(context, requirement, ap); - break; - case GroupServiceAccountAccessPolicy ap: - await CanCreateAsync(context, requirement, ap); - break; - default: - throw new ArgumentException("Unsupported access policy type provided."); - } - } - - private async Task CanUpdateAccessPolicyAsync(AuthorizationHandlerContext context, - AccessPolicyOperationRequirement requirement, BaseAccessPolicy resource) - { - var access = await GetAccessPolicyAccessAsync(context, resource); - - if (access.Write) - { - context.Succeed(requirement); - } - } - - private async Task CanDeleteAccessPolicyAsync(AuthorizationHandlerContext context, - AccessPolicyOperationRequirement requirement, BaseAccessPolicy resource) - { - var access = await GetAccessPolicyAccessAsync(context, resource); - - if (access.Write) - { - context.Succeed(requirement); - } - } - - private async Task CanCreateAsync(AuthorizationHandlerContext context, - AccessPolicyOperationRequirement requirement, UserProjectAccessPolicy resource) - { - var user = await _organizationUserRepository.GetByIdAsync(resource.OrganizationUserId!.Value); - if (user.OrganizationId != resource.GrantedProject?.OrganizationId) - { - return; - } - - var access = await GetAccessAsync(context, resource.GrantedProject!.OrganizationId, resource.GrantedProjectId); - - if (access.Write) - { - context.Succeed(requirement); - } - } - - private async Task CanCreateAsync(AuthorizationHandlerContext context, - AccessPolicyOperationRequirement requirement, GroupProjectAccessPolicy resource) - { - var group = await _groupRepository.GetByIdAsync(resource.GroupId!.Value); - if (group.OrganizationId != resource.GrantedProject?.OrganizationId) - { - return; - } - - var access = await GetAccessAsync(context, resource.GrantedProject!.OrganizationId, resource.GrantedProjectId); - - if (access.Write) - { - context.Succeed(requirement); - } - } - - private async Task CanCreateAsync(AuthorizationHandlerContext context, - AccessPolicyOperationRequirement requirement, ServiceAccountProjectAccessPolicy resource) - { - var projectOrganizationId = resource.GrantedProject?.OrganizationId; - var serviceAccountOrgId = resource.ServiceAccount?.OrganizationId; - - if (projectOrganizationId == null) - { - var project = await _projectRepository.GetByIdAsync(resource.GrantedProjectId!.Value); - projectOrganizationId = project?.OrganizationId; - } - - if (serviceAccountOrgId == null) - { - var serviceAccount = await _serviceAccountRepository.GetByIdAsync(resource.ServiceAccountId!.Value); - serviceAccountOrgId = serviceAccount?.OrganizationId; - } - - if (!serviceAccountOrgId.HasValue || !projectOrganizationId.HasValue || - serviceAccountOrgId != projectOrganizationId) - { - return; - } - - var access = await GetAccessAsync(context, projectOrganizationId.Value, resource.GrantedProjectId, - resource.ServiceAccountId); - - if (access.Write) - { - context.Succeed(requirement); - } - } - - private async Task CanCreateAsync(AuthorizationHandlerContext context, - AccessPolicyOperationRequirement requirement, UserServiceAccountAccessPolicy resource) - { - var user = await _organizationUserRepository.GetByIdAsync(resource.OrganizationUserId!.Value); - if (user.OrganizationId != resource.GrantedServiceAccount!.OrganizationId) - { - return; - } - - var access = await GetAccessAsync(context, resource.GrantedServiceAccount!.OrganizationId, - serviceAccountIdToCheck: resource.GrantedServiceAccountId); - - if (access.Write) - { - context.Succeed(requirement); - } - } - - private async Task CanCreateAsync(AuthorizationHandlerContext context, - AccessPolicyOperationRequirement requirement, GroupServiceAccountAccessPolicy resource) - { - var group = await _groupRepository.GetByIdAsync(resource.GroupId!.Value); - if (group.OrganizationId != resource.GrantedServiceAccount!.OrganizationId) - { - return; - } - - var access = await GetAccessAsync(context, resource.GrantedServiceAccount!.OrganizationId, - serviceAccountIdToCheck: resource.GrantedServiceAccountId); - - if (access.Write) - { - context.Succeed(requirement); - } - } - - private async Task<(bool Read, bool Write)> GetAccessPolicyAccessAsync(AuthorizationHandlerContext context, - BaseAccessPolicy resource) => - resource switch - { - UserProjectAccessPolicy ap => await GetAccessAsync(context, ap.GrantedProject!.OrganizationId, - ap.GrantedProjectId), - GroupProjectAccessPolicy ap => await GetAccessAsync(context, ap.GrantedProject!.OrganizationId, - ap.GrantedProjectId), - ServiceAccountProjectAccessPolicy ap => await GetAccessAsync(context, ap.GrantedProject!.OrganizationId, - ap.GrantedProjectId), - UserServiceAccountAccessPolicy ap => await GetAccessAsync(context, ap.GrantedServiceAccount!.OrganizationId, - serviceAccountIdToCheck: ap.GrantedServiceAccountId), - GroupServiceAccountAccessPolicy ap => await GetAccessAsync(context, - ap.GrantedServiceAccount!.OrganizationId, serviceAccountIdToCheck: ap.GrantedServiceAccountId), - _ => throw new ArgumentException("Unsupported access policy type provided."), - }; - - private async Task<(bool Read, bool Write)> GetAccessAsync(AuthorizationHandlerContext context, - Guid organizationId, Guid? projectIdToCheck = null, - Guid? serviceAccountIdToCheck = null) - { - if (!_currentContext.AccessSecretsManager(organizationId)) - { - return (false, false); - } - - var (accessClient, userId) = await _accessClientQuery.GetAccessClientAsync(context.User, organizationId); - - // Only users and admins should be able to manipulate access policies - if (accessClient != AccessClientType.User && accessClient != AccessClientType.NoAccessCheck) - { - return (false, false); - } - - if (projectIdToCheck.HasValue && serviceAccountIdToCheck.HasValue) - { - var projectAccess = - await _projectRepository.AccessToProjectAsync(projectIdToCheck.Value, userId, accessClient); - var serviceAccountAccess = - await _serviceAccountRepository.AccessToServiceAccountAsync(serviceAccountIdToCheck.Value, userId, - accessClient); - return ( - projectAccess.Read && serviceAccountAccess.Read, - projectAccess.Write && serviceAccountAccess.Write); - } - - if (projectIdToCheck.HasValue) - { - return await _projectRepository.AccessToProjectAsync(projectIdToCheck.Value, userId, accessClient); - } - - if (serviceAccountIdToCheck.HasValue) - { - return await _serviceAccountRepository.AccessToServiceAccountAsync(serviceAccountIdToCheck.Value, userId, - accessClient); - } - - throw new ArgumentException("No ID to check provided."); - } -} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/CreateAccessPoliciesCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/CreateAccessPoliciesCommand.cs deleted file mode 100644 index ada5ebd04..000000000 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/CreateAccessPoliciesCommand.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Bit.Core.Exceptions; -using Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces; -using Bit.Core.SecretsManager.Entities; -using Bit.Core.SecretsManager.Repositories; - -namespace Bit.Commercial.Core.SecretsManager.Commands.AccessPolicies; - -public class CreateAccessPoliciesCommand : ICreateAccessPoliciesCommand -{ - private readonly IAccessPolicyRepository _accessPolicyRepository; - - public CreateAccessPoliciesCommand(IAccessPolicyRepository accessPolicyRepository) - { - _accessPolicyRepository = accessPolicyRepository; - } - - public async Task> CreateManyAsync(List accessPolicies) - { - await CheckAccessPoliciesDoNotExistAsync(accessPolicies); - return await _accessPolicyRepository.CreateManyAsync(accessPolicies); - } - - private async Task CheckAccessPoliciesDoNotExistAsync(List accessPolicies) - { - foreach (var accessPolicy in accessPolicies) - { - if (await _accessPolicyRepository.AccessPolicyExists(accessPolicy)) - { - throw new BadRequestException("Resource already exists"); - } - } - } -} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/DeleteAccessPolicyCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/DeleteAccessPolicyCommand.cs deleted file mode 100644 index 9ac807ce2..000000000 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/DeleteAccessPolicyCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces; -using Bit.Core.SecretsManager.Repositories; - -namespace Bit.Commercial.Core.SecretsManager.Commands.AccessPolicies; - -public class DeleteAccessPolicyCommand : IDeleteAccessPolicyCommand -{ - private readonly IAccessPolicyRepository _accessPolicyRepository; - - public DeleteAccessPolicyCommand(IAccessPolicyRepository accessPolicyRepository) - { - _accessPolicyRepository = accessPolicyRepository; - } - - public async Task DeleteAsync(Guid id) - { - await _accessPolicyRepository.DeleteAsync(id); - } -} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/UpdateAccessPolicyCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/UpdateAccessPolicyCommand.cs deleted file mode 100644 index f014b247e..000000000 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/UpdateAccessPolicyCommand.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Bit.Core.Exceptions; -using Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces; -using Bit.Core.SecretsManager.Entities; -using Bit.Core.SecretsManager.Repositories; - -namespace Bit.Commercial.Core.SecretsManager.Commands.AccessPolicies; - -public class UpdateAccessPolicyCommand : IUpdateAccessPolicyCommand -{ - private readonly IAccessPolicyRepository _accessPolicyRepository; - - public UpdateAccessPolicyCommand(IAccessPolicyRepository accessPolicyRepository) - { - _accessPolicyRepository = accessPolicyRepository; - } - - public async Task UpdateAsync(Guid id, bool read, bool write) - { - var accessPolicy = await _accessPolicyRepository.GetByIdAsync(id); - if (accessPolicy == null) - { - throw new NotFoundException(); - } - - accessPolicy.Read = read; - accessPolicy.Write = write; - accessPolicy.RevisionDate = DateTime.UtcNow; - await _accessPolicyRepository.ReplaceAsync(accessPolicy); - return accessPolicy; - } -} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/SecretsManagerCollectionExtensions.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/SecretsManagerCollectionExtensions.cs index 2f4e31926..bd3709717 100644 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/SecretsManagerCollectionExtensions.cs +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/SecretsManagerCollectionExtensions.cs @@ -38,7 +38,6 @@ public static class SecretsManagerCollectionExtensions services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -62,9 +61,6 @@ public static class SecretsManagerCollectionExtensions services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/AccessPolicyRepository.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/AccessPolicyRepository.cs index 2066e3ae6..8ac904bce 100644 --- a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/AccessPolicyRepository.cs +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/AccessPolicyRepository.cs @@ -81,138 +81,6 @@ public class AccessPolicyRepository : BaseEntityFrameworkRepository, IAccessPoli return baseAccessPolicies; } - public async Task AccessPolicyExists(Core.SecretsManager.Entities.BaseAccessPolicy baseAccessPolicy) - { - using var scope = ServiceScopeFactory.CreateScope(); - var dbContext = GetDatabaseContext(scope); - switch (baseAccessPolicy) - { - case Core.SecretsManager.Entities.UserProjectAccessPolicy accessPolicy: - { - var policy = await dbContext.UserProjectAccessPolicy - .Where(c => c.OrganizationUserId == accessPolicy.OrganizationUserId && - c.GrantedProjectId == accessPolicy.GrantedProjectId) - .FirstOrDefaultAsync(); - return policy != null; - } - case Core.SecretsManager.Entities.GroupProjectAccessPolicy accessPolicy: - { - var policy = await dbContext.GroupProjectAccessPolicy - .Where(c => c.GroupId == accessPolicy.GroupId && - c.GrantedProjectId == accessPolicy.GrantedProjectId) - .FirstOrDefaultAsync(); - return policy != null; - } - case Core.SecretsManager.Entities.ServiceAccountProjectAccessPolicy accessPolicy: - { - var policy = await dbContext.ServiceAccountProjectAccessPolicy - .Where(c => c.ServiceAccountId == accessPolicy.ServiceAccountId && - c.GrantedProjectId == accessPolicy.GrantedProjectId) - .FirstOrDefaultAsync(); - return policy != null; - } - case Core.SecretsManager.Entities.UserServiceAccountAccessPolicy accessPolicy: - { - var policy = await dbContext.UserServiceAccountAccessPolicy - .Where(c => c.OrganizationUserId == accessPolicy.OrganizationUserId && - c.GrantedServiceAccountId == accessPolicy.GrantedServiceAccountId) - .FirstOrDefaultAsync(); - return policy != null; - } - case Core.SecretsManager.Entities.GroupServiceAccountAccessPolicy accessPolicy: - { - var policy = await dbContext.GroupServiceAccountAccessPolicy - .Where(c => c.GroupId == accessPolicy.GroupId && - c.GrantedServiceAccountId == accessPolicy.GrantedServiceAccountId) - .FirstOrDefaultAsync(); - return policy != null; - } - default: - throw new ArgumentException("Unsupported access policy type provided.", nameof(baseAccessPolicy)); - } - } - - public async Task GetByIdAsync(Guid id) - { - using var scope = ServiceScopeFactory.CreateScope(); - var dbContext = GetDatabaseContext(scope); - var entity = await dbContext.AccessPolicies.Where(ap => ap.Id == id) - .Include(ap => ((UserProjectAccessPolicy)ap).OrganizationUser.User) - .Include(ap => ((UserProjectAccessPolicy)ap).GrantedProject) - .Include(ap => ((GroupProjectAccessPolicy)ap).Group) - .Include(ap => ((GroupProjectAccessPolicy)ap).GrantedProject) - .Include(ap => ((ServiceAccountProjectAccessPolicy)ap).ServiceAccount) - .Include(ap => ((ServiceAccountProjectAccessPolicy)ap).GrantedProject) - .Include(ap => ((UserServiceAccountAccessPolicy)ap).OrganizationUser.User) - .Include(ap => ((UserServiceAccountAccessPolicy)ap).GrantedServiceAccount) - .Include(ap => ((GroupServiceAccountAccessPolicy)ap).Group) - .Include(ap => ((GroupServiceAccountAccessPolicy)ap).GrantedServiceAccount) - .FirstOrDefaultAsync(); - - return entity == null ? null : MapToCore(entity); - } - - public async Task ReplaceAsync(Core.SecretsManager.Entities.BaseAccessPolicy baseAccessPolicy) - { - using var scope = ServiceScopeFactory.CreateScope(); - var dbContext = GetDatabaseContext(scope); - var entity = await dbContext.AccessPolicies.FindAsync(baseAccessPolicy.Id); - if (entity != null) - { - dbContext.AccessPolicies.Attach(entity); - entity.Write = baseAccessPolicy.Write; - entity.Read = baseAccessPolicy.Read; - entity.RevisionDate = baseAccessPolicy.RevisionDate; - await dbContext.SaveChangesAsync(); - } - } - - public async Task> GetManyByGrantedProjectIdAsync(Guid id, Guid userId) - { - using var scope = ServiceScopeFactory.CreateScope(); - var dbContext = GetDatabaseContext(scope); - - var entities = await dbContext.AccessPolicies.Where(ap => - ((UserProjectAccessPolicy)ap).GrantedProjectId == id || - ((GroupProjectAccessPolicy)ap).GrantedProjectId == id || - ((ServiceAccountProjectAccessPolicy)ap).GrantedProjectId == id) - .Include(ap => ((UserProjectAccessPolicy)ap).OrganizationUser.User) - .Include(ap => ((GroupProjectAccessPolicy)ap).Group) - .Include(ap => ((ServiceAccountProjectAccessPolicy)ap).ServiceAccount) - .Select(ap => new - { - ap, - CurrentUserInGroup = ap is GroupProjectAccessPolicy && - ((GroupProjectAccessPolicy)ap).Group.GroupUsers.Any(g => - g.OrganizationUser.User.Id == userId), - }) - .ToListAsync(); - - return entities.Select(e => MapToCore(e.ap, e.CurrentUserInGroup)); - } - - public async Task DeleteAsync(Guid id) - { - using var scope = ServiceScopeFactory.CreateScope(); - var dbContext = GetDatabaseContext(scope); - var entity = await dbContext.AccessPolicies.FindAsync(id); - if (entity != null) - { - if (entity is ServiceAccountProjectAccessPolicy serviceAccountProjectAccessPolicy) - { - var serviceAccount = - await dbContext.ServiceAccount.FindAsync(serviceAccountProjectAccessPolicy.ServiceAccountId); - if (serviceAccount != null) - { - serviceAccount.RevisionDate = DateTime.UtcNow; - } - } - - dbContext.Remove(entity); - await dbContext.SaveChangesAsync(); - } - } - public async Task GetPeopleGranteesAsync(Guid organizationId, Guid currentUserId) { using var scope = ServiceScopeFactory.CreateScope(); diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ServiceAccountRepository.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ServiceAccountRepository.cs index cf9fa8a2f..10fe0bea4 100644 --- a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ServiceAccountRepository.cs +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ServiceAccountRepository.cs @@ -43,28 +43,6 @@ public class ServiceAccountRepository : Repository>(serviceAccounts); } - public async Task UserHasReadAccessToServiceAccount(Guid id, Guid userId) - { - using var scope = ServiceScopeFactory.CreateScope(); - var dbContext = GetDatabaseContext(scope); - var query = dbContext.ServiceAccount - .Where(sa => sa.Id == id) - .Where(UserHasReadAccessToServiceAccount(userId)); - - return await query.AnyAsync(); - } - - public async Task UserHasWriteAccessToServiceAccount(Guid id, Guid userId) - { - using var scope = ServiceScopeFactory.CreateScope(); - var dbContext = GetDatabaseContext(scope); - var query = dbContext.ServiceAccount - .Where(sa => sa.Id == id) - .Where(UserHasWriteAccessToServiceAccount(userId)); - - return await query.AnyAsync(); - } - public async Task> GetManyByOrganizationIdWriteAccessAsync(Guid organizationId, Guid userId, AccessClientType accessType) { using var scope = ServiceScopeFactory.CreateScope(); diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AuthorizationHandlers/AccessPolicies/AccessPolicyAuthorizationHandlerTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AuthorizationHandlers/AccessPolicies/AccessPolicyAuthorizationHandlerTests.cs deleted file mode 100644 index b6779394c..000000000 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AuthorizationHandlers/AccessPolicies/AccessPolicyAuthorizationHandlerTests.cs +++ /dev/null @@ -1,763 +0,0 @@ -using System.Reflection; -using System.Security.Claims; -using Bit.Commercial.Core.SecretsManager.AuthorizationHandlers.AccessPolicies; -using Bit.Commercial.Core.Test.SecretsManager.Enums; -using Bit.Core.AdminConsole.Entities; -using Bit.Core.AdminConsole.Repositories; -using Bit.Core.Context; -using Bit.Core.Entities; -using Bit.Core.Enums; -using Bit.Core.Repositories; -using Bit.Core.SecretsManager.AuthorizationRequirements; -using Bit.Core.SecretsManager.Entities; -using Bit.Core.SecretsManager.Queries.Interfaces; -using Bit.Core.SecretsManager.Repositories; -using Bit.Core.Test.SecretsManager.AutoFixture.ProjectsFixture; -using Bit.Test.Common.AutoFixture; -using Bit.Test.Common.AutoFixture.Attributes; -using Microsoft.AspNetCore.Authorization; -using NSubstitute; -using Xunit; - -namespace Bit.Commercial.Core.Test.SecretsManager.AuthorizationHandlers.AccessPolicies; - -[SutProviderCustomize] -[ProjectCustomize] -public class AccessPolicyAuthorizationHandlerTests -{ - private static void SetupCurrentUserPermission(SutProvider sutProvider, - PermissionType permissionType, Guid organizationId, Guid userId = new()) - { - sutProvider.GetDependency().AccessSecretsManager(organizationId) - .Returns(true); - - switch (permissionType) - { - case PermissionType.RunAsAdmin: - sutProvider.GetDependency().GetAccessClientAsync(default, organizationId).ReturnsForAnyArgs( - (AccessClientType.NoAccessCheck, userId)); - break; - case PermissionType.RunAsUserWithPermission: - sutProvider.GetDependency().GetAccessClientAsync(default, organizationId).ReturnsForAnyArgs( - (AccessClientType.User, userId)); - break; - default: - throw new ArgumentOutOfRangeException(nameof(permissionType), permissionType, null); - } - } - - private static BaseAccessPolicy CreatePolicy(AccessPolicyType accessPolicyType, Project grantedProject, - ServiceAccount grantedServiceAccount, Guid? serviceAccountId = null) - { - switch (accessPolicyType) - { - case AccessPolicyType.UserProjectAccessPolicy: - return - new UserProjectAccessPolicy - { - Id = Guid.NewGuid(), - OrganizationUserId = Guid.NewGuid(), - Read = true, - Write = true, - GrantedProjectId = grantedProject.Id, - GrantedProject = grantedProject, - }; - case AccessPolicyType.GroupProjectAccessPolicy: - return - new GroupProjectAccessPolicy - { - Id = Guid.NewGuid(), - GroupId = Guid.NewGuid(), - GrantedProjectId = grantedProject.Id, - Read = true, - Write = true, - GrantedProject = grantedProject, - }; - case AccessPolicyType.ServiceAccountProjectAccessPolicy: - return new ServiceAccountProjectAccessPolicy - { - Id = Guid.NewGuid(), - ServiceAccountId = serviceAccountId, - GrantedProjectId = grantedProject.Id, - Read = true, - Write = true, - GrantedProject = grantedProject, - }; - case AccessPolicyType.UserServiceAccountAccessPolicy: - return - new UserServiceAccountAccessPolicy - { - Id = Guid.NewGuid(), - OrganizationUserId = Guid.NewGuid(), - Read = true, - Write = true, - GrantedServiceAccountId = grantedServiceAccount.Id, - GrantedServiceAccount = grantedServiceAccount, - }; - case AccessPolicyType.GroupServiceAccountAccessPolicy: - return new GroupServiceAccountAccessPolicy - { - Id = Guid.NewGuid(), - GroupId = Guid.NewGuid(), - GrantedServiceAccountId = grantedServiceAccount.Id, - GrantedServiceAccount = grantedServiceAccount, - Read = true, - Write = true, - }; - default: - throw new ArgumentOutOfRangeException(nameof(accessPolicyType), accessPolicyType, null); - } - } - - private static void SetupMockAccess(SutProvider sutProvider, - Guid userId, BaseAccessPolicy accessPolicy, bool read, bool write) - { - switch (accessPolicy) - { - case UserProjectAccessPolicy ap: - sutProvider.GetDependency() - .AccessToProjectAsync(ap.GrantedProjectId!.Value, userId, Arg.Any()) - .Returns((read, write)); - break; - case GroupProjectAccessPolicy ap: - sutProvider.GetDependency() - .AccessToProjectAsync(ap.GrantedProjectId!.Value, userId, Arg.Any()) - .Returns((read, write)); - break; - case UserServiceAccountAccessPolicy ap: - sutProvider.GetDependency() - .AccessToServiceAccountAsync(ap.GrantedServiceAccountId!.Value, userId, Arg.Any()) - .Returns((read, write)); - break; - case GroupServiceAccountAccessPolicy ap: - sutProvider.GetDependency() - .AccessToServiceAccountAsync(ap.GrantedServiceAccountId!.Value, userId, Arg.Any()) - .Returns((read, write)); - break; - case ServiceAccountProjectAccessPolicy ap: - sutProvider.GetDependency() - .AccessToProjectAsync(ap.GrantedProjectId!.Value, userId, Arg.Any()) - .Returns((read, write)); - sutProvider.GetDependency() - .AccessToServiceAccountAsync(ap.ServiceAccountId!.Value, userId, Arg.Any()) - .Returns((read, write)); - break; - } - } - - private static void SetupOrganizationMismatch(SutProvider sutProvider, - BaseAccessPolicy accessPolicy) - { - switch (accessPolicy) - { - case UserProjectAccessPolicy resource: - sutProvider.GetDependency() - .GetByIdAsync(resource.OrganizationUserId!.Value) - .Returns(new OrganizationUser - { - Id = resource.OrganizationUserId!.Value, - OrganizationId = Guid.NewGuid() - }); - break; - case GroupProjectAccessPolicy resource: - sutProvider.GetDependency().GetByIdAsync(resource.GroupId!.Value) - .Returns(new Group { Id = resource.GroupId!.Value, OrganizationId = Guid.NewGuid() }); - break; - case UserServiceAccountAccessPolicy resource: - sutProvider.GetDependency() - .GetByIdAsync(resource.OrganizationUserId!.Value) - .Returns(new OrganizationUser - { - Id = resource.OrganizationUserId!.Value, - OrganizationId = Guid.NewGuid() - }); - break; - case GroupServiceAccountAccessPolicy resource: - sutProvider.GetDependency().GetByIdAsync(resource.GroupId!.Value) - .Returns(new Group { Id = resource.GroupId!.Value, OrganizationId = Guid.NewGuid() }); - break; - default: - throw new ArgumentOutOfRangeException(nameof(accessPolicy), accessPolicy, null); - } - } - - private static void SetupOrganizationMatch(SutProvider sutProvider, - BaseAccessPolicy accessPolicy, Guid organizationId) - { - switch (accessPolicy) - { - case UserProjectAccessPolicy resource: - sutProvider.GetDependency() - .GetByIdAsync(resource.OrganizationUserId!.Value) - .Returns(new OrganizationUser - { - Id = resource.OrganizationUserId!.Value, - OrganizationId = organizationId - }); - break; - case GroupProjectAccessPolicy resource: - sutProvider.GetDependency().GetByIdAsync(resource.GroupId!.Value) - .Returns(new Group { Id = resource.GroupId!.Value, OrganizationId = organizationId }); - break; - case UserServiceAccountAccessPolicy resource: - sutProvider.GetDependency() - .GetByIdAsync(resource.OrganizationUserId!.Value) - .Returns(new OrganizationUser - { - Id = resource.OrganizationUserId!.Value, - OrganizationId = organizationId - }); - break; - case GroupServiceAccountAccessPolicy resource: - sutProvider.GetDependency().GetByIdAsync(resource.GroupId!.Value) - .Returns(new Group { Id = resource.GroupId!.Value, OrganizationId = organizationId }); - break; - default: - throw new ArgumentOutOfRangeException(nameof(accessPolicy), accessPolicy, null); - } - } - - [Fact] - public void AccessPolicyOperations_OnlyPublicStatic() - { - var publicStaticFields = typeof(AccessPolicyOperations).GetFields(BindingFlags.Public | BindingFlags.Static); - var allFields = typeof(AccessPolicyOperations).GetFields(); - Assert.Equal(publicStaticFields.Length, allFields.Length); - } - - [Theory] - [BitAutoData] - public async Task Handler_UnsupportedAccessPolicyOperationRequirement_Throws( - SutProvider sutProvider, UserProjectAccessPolicy resource, - ClaimsPrincipal claimsPrincipal) - { - var requirement = new AccessPolicyOperationRequirement(); - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await Assert.ThrowsAsync(() => sutProvider.Sut.HandleAsync(authzContext)); - } - - [Theory] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy)] - public async Task CanCreate_OrgMismatch_DoesNotSucceed( - AccessPolicyType accessPolicyType, - SutProvider sutProvider, - Project mockGrantedProject, - ServiceAccount mockGrantedServiceAccount, - ClaimsPrincipal claimsPrincipal) - { - var requirement = AccessPolicyOperations.Create; - var resource = CreatePolicy(accessPolicyType, mockGrantedProject, mockGrantedServiceAccount); - SetupOrganizationMismatch(sutProvider, resource); - - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.False(authzContext.HasSucceeded); - } - - [Theory] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy)] - public async Task CanCreate_AccessToSecretsManagerFalse_DoesNotSucceed( - AccessPolicyType accessPolicyType, - SutProvider sutProvider, - Guid organizationId, - Project mockGrantedProject, - ServiceAccount mockGrantedServiceAccount, - ClaimsPrincipal claimsPrincipal) - { - var requirement = AccessPolicyOperations.Create; - mockGrantedProject.OrganizationId = organizationId; - mockGrantedServiceAccount.OrganizationId = organizationId; - var resource = CreatePolicy(accessPolicyType, mockGrantedProject, mockGrantedServiceAccount); - SetupOrganizationMatch(sutProvider, resource, organizationId); - sutProvider.GetDependency().AccessSecretsManager(organizationId) - .Returns(false); - - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.False(authzContext.HasSucceeded); - } - - [Theory] - [BitAutoData(AccessClientType.ServiceAccount, AccessPolicyType.UserProjectAccessPolicy)] - [BitAutoData(AccessClientType.ServiceAccount, AccessPolicyType.GroupProjectAccessPolicy)] - [BitAutoData(AccessClientType.ServiceAccount, AccessPolicyType.UserServiceAccountAccessPolicy)] - [BitAutoData(AccessClientType.ServiceAccount, AccessPolicyType.GroupServiceAccountAccessPolicy)] - [BitAutoData(AccessClientType.Organization, AccessPolicyType.UserProjectAccessPolicy)] - [BitAutoData(AccessClientType.Organization, AccessPolicyType.GroupProjectAccessPolicy)] - [BitAutoData(AccessClientType.Organization, AccessPolicyType.UserServiceAccountAccessPolicy)] - [BitAutoData(AccessClientType.Organization, AccessPolicyType.GroupServiceAccountAccessPolicy)] - public async Task CanCreate_UnsupportedClientTypes_DoesNotSucceed( - AccessClientType clientType, - AccessPolicyType accessPolicyType, - SutProvider sutProvider, - Guid organizationId, - Project mockGrantedProject, - ServiceAccount mockGrantedServiceAccount, - ClaimsPrincipal claimsPrincipal) - { - var requirement = AccessPolicyOperations.Create; - mockGrantedProject.OrganizationId = organizationId; - mockGrantedServiceAccount.OrganizationId = organizationId; - var resource = CreatePolicy(accessPolicyType, mockGrantedProject, mockGrantedServiceAccount); - SetupOrganizationMatch(sutProvider, resource, organizationId); - sutProvider.GetDependency().AccessSecretsManager(organizationId) - .Returns(true); - sutProvider.GetDependency().GetAccessClientAsync(default, organizationId).ReturnsForAnyArgs( - (clientType, Guid.NewGuid())); - - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.False(authzContext.HasSucceeded); - } - - [Theory] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsAdmin, true, true, true)] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, false, false)] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, true, true)] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, false, false)] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, true, true)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsAdmin, true, true, true)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, false, false)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, true, true)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, false, false)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, true, true)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsAdmin, true, true, true)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, false, false, false)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, false, true, true)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, true, false, false)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, true, true, true)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsAdmin, true, true, true)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, false, false, false)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, false, true, true)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, true, false, false)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, true, true, true)] - public async Task CanCreate_AccessCheck( - AccessPolicyType accessPolicyType, - PermissionType permissionType, - bool read, bool write, bool expected, - SutProvider sutProvider, - Guid organizationId, - Guid userId, - Guid serviceAccountId, - Project mockGrantedProject, - ServiceAccount mockGrantedServiceAccount, - ClaimsPrincipal claimsPrincipal) - { - var requirement = AccessPolicyOperations.Create; - mockGrantedProject.OrganizationId = organizationId; - mockGrantedServiceAccount.OrganizationId = organizationId; - var resource = CreatePolicy(accessPolicyType, mockGrantedProject, mockGrantedServiceAccount, serviceAccountId); - SetupCurrentUserPermission(sutProvider, permissionType, organizationId, userId); - SetupOrganizationMatch(sutProvider, resource, organizationId); - SetupMockAccess(sutProvider, userId, resource, read, write); - - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.Equal(expected, authzContext.HasSucceeded); - } - - [Theory] - [BitAutoData(false, false)] - [BitAutoData(false, true)] - [BitAutoData(true, false)] - public async Task CanCreate_ServiceAccountProjectAccessPolicy_TargetsDontExist_DoesNotSucceed(bool projectExists, - bool serviceAccountExists, - SutProvider sutProvider, ServiceAccountProjectAccessPolicy resource, - Project mockProject, ServiceAccount mockServiceAccount, - ClaimsPrincipal claimsPrincipal) - { - var requirement = AccessPolicyOperations.Create; - resource.GrantedProject = null; - resource.ServiceAccount = null; - - if (projectExists) - { - resource.GrantedProject = null; - mockProject.Id = resource.GrantedProjectId!.Value; - sutProvider.GetDependency().GetByIdAsync(resource.GrantedProjectId!.Value) - .Returns(mockProject); - } - - if (serviceAccountExists) - { - resource.ServiceAccount = null; - sutProvider.GetDependency().GetByIdAsync(resource.ServiceAccountId!.Value) - .Returns(mockServiceAccount); - } - - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.False(authzContext.HasSucceeded); - } - - [Theory] - [BitAutoData(false, false)] - [BitAutoData(false, true)] - [BitAutoData(true, false)] - [BitAutoData(true, true)] - public async Task CanCreate_ServiceAccountProjectAccessPolicy_OrgMismatch_DoesNotSucceed(bool fetchProject, - bool fetchSa, - SutProvider sutProvider, ServiceAccountProjectAccessPolicy resource, - Project mockProject, ServiceAccount mockServiceAccount, - ClaimsPrincipal claimsPrincipal) - { - var requirement = AccessPolicyOperations.Create; - - if (fetchProject) - { - resource.GrantedProject = null; - mockProject.Id = resource.GrantedProjectId!.Value; - sutProvider.GetDependency().GetByIdAsync(resource.GrantedProjectId!.Value) - .Returns(mockProject); - } - - if (fetchSa) - { - resource.ServiceAccount = null; - mockServiceAccount.Id = resource.ServiceAccountId!.Value; - sutProvider.GetDependency().GetByIdAsync(resource.ServiceAccountId!.Value) - .Returns(mockServiceAccount); - } - - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.False(authzContext.HasSucceeded); - } - - [Theory] - [BitAutoData] - public async Task CanCreate_ServiceAccountProjectAccessPolicy_AccessToSecretsManagerFalse_DoesNotSucceed( - SutProvider sutProvider, ServiceAccountProjectAccessPolicy resource, - ClaimsPrincipal claimsPrincipal) - { - var requirement = AccessPolicyOperations.Create; - resource.ServiceAccount!.OrganizationId = resource.GrantedProject!.OrganizationId; - sutProvider.GetDependency().AccessSecretsManager(resource.GrantedProject!.OrganizationId) - .Returns(false); - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.False(authzContext.HasSucceeded); - } - - [Theory] - [BitAutoData(AccessClientType.ServiceAccount)] - [BitAutoData(AccessClientType.Organization)] - public async Task CanCreate_ServiceAccountProjectAccessPolicy_UnsupportedClientTypes_DoesNotSucceed( - AccessClientType clientType, - SutProvider sutProvider, ServiceAccountProjectAccessPolicy resource, - ClaimsPrincipal claimsPrincipal) - { - var requirement = AccessPolicyOperations.Create; - resource.ServiceAccount!.OrganizationId = resource.GrantedProject!.OrganizationId; - sutProvider.GetDependency().AccessSecretsManager(resource.GrantedProject!.OrganizationId) - .Returns(true); - sutProvider.GetDependency().GetAccessClientAsync(default, resource.ServiceAccount!.OrganizationId).ReturnsForAnyArgs( - (clientType, new Guid())); - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.False(authzContext.HasSucceeded); - } - - [Theory] - [BitAutoData(PermissionType.RunAsAdmin, true, true, true, true, true)] - [BitAutoData(PermissionType.RunAsUserWithPermission, false, false, false, false, false)] - [BitAutoData(PermissionType.RunAsUserWithPermission, false, false, false, true, false)] - [BitAutoData(PermissionType.RunAsUserWithPermission, false, false, true, false, false)] - [BitAutoData(PermissionType.RunAsUserWithPermission, false, false, true, true, false)] - [BitAutoData(PermissionType.RunAsUserWithPermission, false, true, false, false, false)] - [BitAutoData(PermissionType.RunAsUserWithPermission, false, true, false, true, true)] - [BitAutoData(PermissionType.RunAsUserWithPermission, false, true, true, false, false)] - [BitAutoData(PermissionType.RunAsUserWithPermission, false, true, true, true, true)] - [BitAutoData(PermissionType.RunAsUserWithPermission, true, false, false, false, false)] - [BitAutoData(PermissionType.RunAsUserWithPermission, true, false, false, true, false)] - [BitAutoData(PermissionType.RunAsUserWithPermission, true, false, true, false, false)] - [BitAutoData(PermissionType.RunAsUserWithPermission, true, false, true, true, false)] - [BitAutoData(PermissionType.RunAsUserWithPermission, true, true, false, false, false)] - [BitAutoData(PermissionType.RunAsUserWithPermission, true, true, false, true, true)] - [BitAutoData(PermissionType.RunAsUserWithPermission, true, true, true, false, false)] - [BitAutoData(PermissionType.RunAsUserWithPermission, true, true, true, true, true)] - public async Task CanCreate_ServiceAccountProjectAccessPolicy_AccessCheck(PermissionType permissionType, - bool projectRead, - bool projectWrite, bool saRead, bool saWrite, bool expected, - SutProvider sutProvider, ServiceAccountProjectAccessPolicy resource, - ClaimsPrincipal claimsPrincipal, Guid userId) - { - var requirement = AccessPolicyOperations.Create; - resource.ServiceAccount!.OrganizationId = resource.GrantedProject!.OrganizationId; - SetupCurrentUserPermission(sutProvider, permissionType, resource.GrantedProject!.OrganizationId, userId); - sutProvider.GetDependency() - .AccessToProjectAsync(resource.GrantedProjectId!.Value, userId, Arg.Any()) - .Returns((projectRead, projectWrite)); - sutProvider.GetDependency() - .AccessToServiceAccountAsync(resource.ServiceAccountId!.Value, userId, Arg.Any()) - .Returns((saRead, saWrite)); - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.Equal(expected, authzContext.HasSucceeded); - } - - [Theory] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy)] - [BitAutoData(AccessPolicyType.ServiceAccountProjectAccessPolicy)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy)] - public async Task CanUpdate_AccessToSecretsManagerFalse_DoesNotSucceed(AccessPolicyType accessPolicyType, - SutProvider sutProvider, - Guid organizationId, - Project mockGrantedProject, - ServiceAccount mockGrantedServiceAccount, - ClaimsPrincipal claimsPrincipal) - { - var requirement = AccessPolicyOperations.Update; - mockGrantedProject.OrganizationId = organizationId; - mockGrantedServiceAccount.OrganizationId = organizationId; - var resource = CreatePolicy(accessPolicyType, mockGrantedProject, mockGrantedServiceAccount); - sutProvider.GetDependency().AccessSecretsManager(organizationId).Returns(false); - - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.False(authzContext.HasSucceeded); - } - - [Theory] - [BitAutoData(AccessClientType.ServiceAccount, AccessPolicyType.UserProjectAccessPolicy)] - [BitAutoData(AccessClientType.ServiceAccount, AccessPolicyType.GroupProjectAccessPolicy)] - [BitAutoData(AccessClientType.ServiceAccount, AccessPolicyType.ServiceAccountProjectAccessPolicy)] - [BitAutoData(AccessClientType.ServiceAccount, AccessPolicyType.UserServiceAccountAccessPolicy)] - [BitAutoData(AccessClientType.ServiceAccount, AccessPolicyType.GroupServiceAccountAccessPolicy)] - [BitAutoData(AccessClientType.Organization, AccessPolicyType.UserProjectAccessPolicy)] - [BitAutoData(AccessClientType.Organization, AccessPolicyType.GroupProjectAccessPolicy)] - [BitAutoData(AccessClientType.Organization, AccessPolicyType.ServiceAccountProjectAccessPolicy)] - [BitAutoData(AccessClientType.Organization, AccessPolicyType.UserServiceAccountAccessPolicy)] - [BitAutoData(AccessClientType.Organization, AccessPolicyType.GroupServiceAccountAccessPolicy)] - public async Task CanUpdate_UnsupportedClientTypes_DoesNotSucceed( - AccessClientType clientType, - AccessPolicyType accessPolicyType, - SutProvider sutProvider, - Guid organizationId, - Project mockGrantedProject, - ServiceAccount mockGrantedServiceAccount, - ClaimsPrincipal claimsPrincipal) - { - var requirement = AccessPolicyOperations.Update; - mockGrantedProject.OrganizationId = organizationId; - mockGrantedServiceAccount.OrganizationId = organizationId; - var resource = CreatePolicy(accessPolicyType, mockGrantedProject, mockGrantedServiceAccount); - sutProvider.GetDependency().AccessSecretsManager(organizationId).Returns(true); - sutProvider.GetDependency().GetAccessClientAsync(default, organizationId).ReturnsForAnyArgs( - (clientType, new Guid())); - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.False(authzContext.HasSucceeded); - } - - [Theory] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsAdmin, true, true, true)] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, false, false)] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, true, true)] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, false, false)] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, true, true)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsAdmin, true, true, true)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, false, false)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, true, true)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, false, false)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, true, true)] - [BitAutoData(AccessPolicyType.ServiceAccountProjectAccessPolicy, PermissionType.RunAsAdmin, true, true, true)] - [BitAutoData(AccessPolicyType.ServiceAccountProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, false, false)] - [BitAutoData(AccessPolicyType.ServiceAccountProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, true, true)] - [BitAutoData(AccessPolicyType.ServiceAccountProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, false, false)] - [BitAutoData(AccessPolicyType.ServiceAccountProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, true, true)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsAdmin, true, true, true)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, false, false, false)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, false, true, true)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, true, false, false)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, true, true, true)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsAdmin, true, true, true)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, false, false, false)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, false, true, true)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, true, false, false)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, true, true, true)] - public async Task CanUpdate_AccessCheck( - AccessPolicyType accessPolicyType, - PermissionType permissionType, bool read, - bool write, bool expected, - SutProvider sutProvider, - Guid organizationId, - Project mockGrantedProject, - ServiceAccount mockGrantedServiceAccount, - ClaimsPrincipal claimsPrincipal, Guid userId, Guid serviceAccountId) - { - var requirement = AccessPolicyOperations.Update; - mockGrantedProject.OrganizationId = organizationId; - mockGrantedServiceAccount.OrganizationId = organizationId; - - var resource = CreatePolicy(accessPolicyType, mockGrantedProject, mockGrantedServiceAccount, - serviceAccountId); - SetupCurrentUserPermission(sutProvider, permissionType, organizationId, userId); - SetupMockAccess(sutProvider, userId, resource, read, write); - - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.Equal(expected, authzContext.HasSucceeded); - } - - [Theory] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy)] - [BitAutoData(AccessPolicyType.ServiceAccountProjectAccessPolicy)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy)] - public async Task CanDelete_AccessToSecretsManagerFalse_DoesNotSucceed(AccessPolicyType accessPolicyType, - SutProvider sutProvider, - Guid organizationId, - Project mockGrantedProject, - ServiceAccount mockGrantedServiceAccount, - ClaimsPrincipal claimsPrincipal) - { - var requirement = AccessPolicyOperations.Delete; - mockGrantedProject.OrganizationId = organizationId; - mockGrantedServiceAccount.OrganizationId = organizationId; - var resource = CreatePolicy(accessPolicyType, mockGrantedProject, mockGrantedServiceAccount); - sutProvider.GetDependency().AccessSecretsManager(organizationId).Returns(false); - - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.False(authzContext.HasSucceeded); - } - - [Theory] - [BitAutoData(AccessClientType.ServiceAccount, AccessPolicyType.UserProjectAccessPolicy)] - [BitAutoData(AccessClientType.ServiceAccount, AccessPolicyType.GroupProjectAccessPolicy)] - [BitAutoData(AccessClientType.ServiceAccount, AccessPolicyType.ServiceAccountProjectAccessPolicy)] - [BitAutoData(AccessClientType.ServiceAccount, AccessPolicyType.UserServiceAccountAccessPolicy)] - [BitAutoData(AccessClientType.ServiceAccount, AccessPolicyType.GroupServiceAccountAccessPolicy)] - [BitAutoData(AccessClientType.Organization, AccessPolicyType.UserProjectAccessPolicy)] - [BitAutoData(AccessClientType.Organization, AccessPolicyType.GroupProjectAccessPolicy)] - [BitAutoData(AccessClientType.Organization, AccessPolicyType.ServiceAccountProjectAccessPolicy)] - [BitAutoData(AccessClientType.Organization, AccessPolicyType.UserServiceAccountAccessPolicy)] - [BitAutoData(AccessClientType.Organization, AccessPolicyType.GroupServiceAccountAccessPolicy)] - public async Task CanDelete_UnsupportedClientTypes_DoesNotSucceed( - AccessClientType clientType, - AccessPolicyType accessPolicyType, - SutProvider sutProvider, - Guid organizationId, - Project mockGrantedProject, - ServiceAccount mockGrantedServiceAccount, - ClaimsPrincipal claimsPrincipal) - { - var requirement = AccessPolicyOperations.Delete; - mockGrantedProject.OrganizationId = organizationId; - mockGrantedServiceAccount.OrganizationId = organizationId; - var resource = CreatePolicy(accessPolicyType, mockGrantedProject, mockGrantedServiceAccount); - sutProvider.GetDependency().AccessSecretsManager(organizationId).Returns(true); - sutProvider.GetDependency().GetAccessClientAsync(default, organizationId).ReturnsForAnyArgs( - (clientType, new Guid())); - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.False(authzContext.HasSucceeded); - } - - [Theory] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsAdmin, true, true, true)] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, false, false)] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, true, true)] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, false, false)] - [BitAutoData(AccessPolicyType.UserProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, true, true)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsAdmin, true, true, true)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, false, false)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, true, true)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, false, false)] - [BitAutoData(AccessPolicyType.GroupProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, true, true)] - [BitAutoData(AccessPolicyType.ServiceAccountProjectAccessPolicy, PermissionType.RunAsAdmin, true, true, true)] - [BitAutoData(AccessPolicyType.ServiceAccountProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, false, false)] - [BitAutoData(AccessPolicyType.ServiceAccountProjectAccessPolicy, PermissionType.RunAsUserWithPermission, false, true, true)] - [BitAutoData(AccessPolicyType.ServiceAccountProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, false, false)] - [BitAutoData(AccessPolicyType.ServiceAccountProjectAccessPolicy, PermissionType.RunAsUserWithPermission, true, true, true)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsAdmin, true, true, true)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, false, false, false)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, false, true, true)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, true, false, false)] - [BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, true, true, true)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsAdmin, true, true, true)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, false, false, false)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, false, true, true)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, true, false, false)] - [BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy, PermissionType.RunAsUserWithPermission, true, true, true)] - public async Task CanDelete_AccessCheck( - AccessPolicyType accessPolicyType, - PermissionType permissionType, - bool read, bool write, bool expected, - SutProvider sutProvider, - Guid organizationId, - Project mockGrantedProject, - ServiceAccount mockGrantedServiceAccount, - ClaimsPrincipal claimsPrincipal, Guid userId, Guid serviceAccountId) - { - var requirement = AccessPolicyOperations.Delete; - mockGrantedProject.OrganizationId = organizationId; - mockGrantedServiceAccount.OrganizationId = organizationId; - - var resource = CreatePolicy(accessPolicyType, mockGrantedProject, mockGrantedServiceAccount, - serviceAccountId); - SetupCurrentUserPermission(sutProvider, permissionType, organizationId, userId); - SetupMockAccess(sutProvider, userId, resource, read, write); - - var authzContext = new AuthorizationHandlerContext(new List { requirement }, - claimsPrincipal, resource); - - await sutProvider.Sut.HandleAsync(authzContext); - - Assert.Equal(expected, authzContext.HasSucceeded); - } -} diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Commands/AccessPolicies/CreateAccessPoliciesCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Commands/AccessPolicies/CreateAccessPoliciesCommandTests.cs deleted file mode 100644 index bf26d6234..000000000 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Commands/AccessPolicies/CreateAccessPoliciesCommandTests.cs +++ /dev/null @@ -1,136 +0,0 @@ -using Bit.Commercial.Core.SecretsManager.Commands.AccessPolicies; -using Bit.Core.Exceptions; -using Bit.Core.SecretsManager.Entities; -using Bit.Core.SecretsManager.Repositories; -using Bit.Core.Test.SecretsManager.AutoFixture.ProjectsFixture; -using Bit.Test.Common.AutoFixture; -using Bit.Test.Common.AutoFixture.Attributes; -using Bit.Test.Common.Helpers; -using NSubstitute; -using Xunit; - -namespace Bit.Commercial.Core.Test.SecretsManager.Commands.AccessPolicies; - -[SutProviderCustomize] -[ProjectCustomize] -public class CreateAccessPoliciesCommandTests -{ - private static List MakeGrantedProjectAccessPolicies(Guid grantedProjectId, List userProjectAccessPolicies, - List groupProjectAccessPolicies, - List serviceAccountProjectAccessPolicies) - { - var data = new List(); - foreach (var ap in userProjectAccessPolicies) - { - ap.GrantedProjectId = grantedProjectId; - ap.GrantedProject = null; - ap.User = null; - } - foreach (var ap in groupProjectAccessPolicies) - { - ap.GrantedProjectId = grantedProjectId; - ap.GrantedProject = null; - ap.Group = null; - } - foreach (var ap in serviceAccountProjectAccessPolicies) - { - ap.GrantedProjectId = grantedProjectId; - ap.GrantedProject = null; - ap.ServiceAccount = null; - } - data.AddRange(userProjectAccessPolicies); - data.AddRange(groupProjectAccessPolicies); - data.AddRange(serviceAccountProjectAccessPolicies); - return data; - } - - private static List MakeGrantedServiceAccountAccessPolicies(Guid grantedServiceAccountId, List userServiceAccountAccessPolicies, - List groupServiceAccountAccessPolicies) - { - var data = new List(); - foreach (var ap in userServiceAccountAccessPolicies) - { - ap.GrantedServiceAccountId = grantedServiceAccountId; - ap.GrantedServiceAccount = null; - ap.User = null; - } - foreach (var ap in groupServiceAccountAccessPolicies) - { - ap.GrantedServiceAccountId = grantedServiceAccountId; - ap.GrantedServiceAccount = null; - ap.Group = null; - } - data.AddRange(userServiceAccountAccessPolicies); - data.AddRange(groupServiceAccountAccessPolicies); - return data; - } - - [Theory] - [BitAutoData] - public async Task CreateMany_AlreadyExists_Throws_BadRequestException( - Project project, - ServiceAccount serviceAccount, - List userProjectAccessPolicies, - List groupProjectAccessPolicies, - List serviceAccountProjectAccessPolicies, - List userServiceAccountAccessPolicies, - List groupServiceAccountAccessPolicies, - SutProvider sutProvider) - { - var data = MakeGrantedProjectAccessPolicies(project.Id, userProjectAccessPolicies, groupProjectAccessPolicies, - serviceAccountProjectAccessPolicies); - var saData = MakeGrantedServiceAccountAccessPolicies(serviceAccount.Id, userServiceAccountAccessPolicies, groupServiceAccountAccessPolicies); - data = data.Concat(saData).ToList(); - - sutProvider.GetDependency().AccessPolicyExists(Arg.Any()) - .Returns(true); - - await Assert.ThrowsAsync(() => - sutProvider.Sut.CreateManyAsync(data)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().CreateManyAsync(default!); - } - - [Theory] - [BitAutoData] - public async Task CreateMany_ClearsReferences(SutProvider sutProvider, Guid projectId) - { - var userProjectAp = new UserProjectAccessPolicy - { - GrantedProjectId = projectId, - OrganizationUserId = new Guid(), - }; - var data = new List() { userProjectAp, }; - - userProjectAp.GrantedProject = new Project() { Id = new Guid() }; - var expectedCall = new List() { userProjectAp, }; - - await sutProvider.Sut.CreateManyAsync(data); - - await sutProvider.GetDependency().Received(1) - .CreateManyAsync(Arg.Is(AssertHelper.AssertPropertyEqual(expectedCall))); - } - - [Theory] - [BitAutoData] - public async Task CreateMany_Success( - Project project, - ServiceAccount serviceAccount, - List userProjectAccessPolicies, - List groupProjectAccessPolicies, - List serviceAccountProjectAccessPolicies, - List userServiceAccountAccessPolicies, - List groupServiceAccountAccessPolicies, - SutProvider sutProvider) - { - var data = MakeGrantedProjectAccessPolicies(project.Id, userProjectAccessPolicies, groupProjectAccessPolicies, - serviceAccountProjectAccessPolicies); - var saData = MakeGrantedServiceAccountAccessPolicies(serviceAccount.Id, userServiceAccountAccessPolicies, groupServiceAccountAccessPolicies); - data = data.Concat(saData).ToList(); - - await sutProvider.Sut.CreateManyAsync(data); - - await sutProvider.GetDependency().Received(1) - .CreateManyAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data))); - } -} diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Commands/AccessPolicies/DeleteAccessPolicyCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Commands/AccessPolicies/DeleteAccessPolicyCommandTests.cs deleted file mode 100644 index 39025012b..000000000 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Commands/AccessPolicies/DeleteAccessPolicyCommandTests.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Bit.Commercial.Core.SecretsManager.Commands.AccessPolicies; -using Bit.Core.SecretsManager.Repositories; -using Bit.Core.Test.SecretsManager.AutoFixture.ProjectsFixture; -using Bit.Test.Common.AutoFixture; -using Bit.Test.Common.AutoFixture.Attributes; -using Bit.Test.Common.Helpers; -using NSubstitute; -using Xunit; - -namespace Bit.Commercial.Core.Test.SecretsManager.Commands.AccessPolicies; - -[SutProviderCustomize] -[ProjectCustomize] -public class DeleteAccessPolicyCommandTests -{ - [Theory] - [BitAutoData] - public async Task DeleteAsync_Success(SutProvider sutProvider, Guid data) - { - await sutProvider.Sut.DeleteAsync(data); - - await sutProvider.GetDependency().Received(1) - .DeleteAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data))); - } -} diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Commands/AccessPolicies/UpdateAccessPolicyCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Commands/AccessPolicies/UpdateAccessPolicyCommandTests.cs deleted file mode 100644 index e96aa810c..000000000 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Commands/AccessPolicies/UpdateAccessPolicyCommandTests.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Bit.Commercial.Core.SecretsManager.Commands.AccessPolicies; -using Bit.Core.Exceptions; -using Bit.Core.SecretsManager.Entities; -using Bit.Core.SecretsManager.Repositories; -using Bit.Core.Test.SecretsManager.AutoFixture.ProjectsFixture; -using Bit.Test.Common.AutoFixture; -using Bit.Test.Common.AutoFixture.Attributes; -using Bit.Test.Common.Helpers; -using NSubstitute; -using Xunit; - -namespace Bit.Commercial.Core.Test.SecretsManager.Commands.AccessPolicies; - -[SutProviderCustomize] -[ProjectCustomize] -public class UpdateAccessPolicyCommandTests -{ - [Theory] - [BitAutoData] - public async Task UpdateAsync_DoesNotExist_ThrowsNotFound(Guid data, bool read, bool write, - SutProvider sutProvider) - { - await Assert.ThrowsAsync(() => sutProvider.Sut.UpdateAsync(data, read, write)); - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().ReplaceAsync(Arg.Any()); - } - - [Theory] - [BitAutoData] - public async Task UpdateAsync_Success(Guid data, bool read, bool write, UserProjectAccessPolicy accessPolicy, - SutProvider sutProvider) - { - accessPolicy.Id = data; - sutProvider.GetDependency().GetByIdAsync(data).Returns(accessPolicy); - - var result = await sutProvider.Sut.UpdateAsync(data, read, write); - - await sutProvider.GetDependency().Received(1) - .ReplaceAsync(Arg.Any()); - - AssertHelper.AssertRecent(result.RevisionDate); - Assert.Equal(read, result.Read); - Assert.Equal(write, result.Write); - } -} diff --git a/src/Api/SecretsManager/Controllers/AccessPoliciesController.cs b/src/Api/SecretsManager/Controllers/AccessPoliciesController.cs index 54f699e05..5a7df0405 100644 --- a/src/Api/SecretsManager/Controllers/AccessPoliciesController.cs +++ b/src/Api/SecretsManager/Controllers/AccessPoliciesController.cs @@ -17,24 +17,22 @@ using Microsoft.AspNetCore.Mvc; namespace Bit.Api.SecretsManager.Controllers; [Authorize("secrets")] -[Route("access-policies")] public class AccessPoliciesController : Controller { - private const int _maxBulkCreation = 15; - private readonly IAccessPolicyRepository _accessPolicyRepository; - private readonly ICreateAccessPoliciesCommand _createAccessPoliciesCommand; - private readonly ICurrentContext _currentContext; - private readonly IDeleteAccessPolicyCommand _deleteAccessPolicyCommand; - private readonly IProjectRepository _projectRepository; - private readonly IServiceAccountRepository _serviceAccountRepository; - private readonly IUpdateAccessPolicyCommand _updateAccessPolicyCommand; - private readonly IUpdateServiceAccountGrantedPoliciesCommand _updateServiceAccountGrantedPoliciesCommand; - private readonly IUpdateProjectServiceAccountsAccessPoliciesCommand _updateProjectServiceAccountsAccessPoliciesCommand; private readonly IAccessClientQuery _accessClientQuery; - private readonly IServiceAccountGrantedPolicyUpdatesQuery _serviceAccountGrantedPolicyUpdatesQuery; - private readonly IProjectServiceAccountsAccessPoliciesUpdatesQuery _projectServiceAccountsAccessPoliciesUpdatesQuery; - private readonly IUserService _userService; + private readonly IAccessPolicyRepository _accessPolicyRepository; private readonly IAuthorizationService _authorizationService; + private readonly ICurrentContext _currentContext; + private readonly IProjectRepository _projectRepository; + private readonly IServiceAccountGrantedPolicyUpdatesQuery _serviceAccountGrantedPolicyUpdatesQuery; + private readonly IServiceAccountRepository _serviceAccountRepository; + private readonly IUpdateServiceAccountGrantedPoliciesCommand _updateServiceAccountGrantedPoliciesCommand; + private readonly IUserService _userService; + private readonly IProjectServiceAccountsAccessPoliciesUpdatesQuery + _projectServiceAccountsAccessPoliciesUpdatesQuery; + private readonly IUpdateProjectServiceAccountsAccessPoliciesCommand + _updateProjectServiceAccountsAccessPoliciesCommand; + public AccessPoliciesController( IAuthorizationService authorizationService, @@ -47,10 +45,7 @@ public class AccessPoliciesController : Controller IServiceAccountGrantedPolicyUpdatesQuery serviceAccountGrantedPolicyUpdatesQuery, IProjectServiceAccountsAccessPoliciesUpdatesQuery projectServiceAccountsAccessPoliciesUpdatesQuery, IUpdateServiceAccountGrantedPoliciesCommand updateServiceAccountGrantedPoliciesCommand, - ICreateAccessPoliciesCommand createAccessPoliciesCommand, - IDeleteAccessPolicyCommand deleteAccessPolicyCommand, - IUpdateProjectServiceAccountsAccessPoliciesCommand updateProjectServiceAccountsAccessPoliciesCommand, - IUpdateAccessPolicyCommand updateAccessPolicyCommand) + IUpdateProjectServiceAccountsAccessPoliciesCommand updateProjectServiceAccountsAccessPoliciesCommand) { _authorizationService = authorizationService; _userService = userService; @@ -58,9 +53,6 @@ public class AccessPoliciesController : Controller _serviceAccountRepository = serviceAccountRepository; _projectRepository = projectRepository; _accessPolicyRepository = accessPolicyRepository; - _createAccessPoliciesCommand = createAccessPoliciesCommand; - _deleteAccessPolicyCommand = deleteAccessPolicyCommand; - _updateAccessPolicyCommand = updateAccessPolicyCommand; _updateServiceAccountGrantedPoliciesCommand = updateServiceAccountGrantedPoliciesCommand; _accessClientQuery = accessClientQuery; _serviceAccountGrantedPolicyUpdatesQuery = serviceAccountGrantedPolicyUpdatesQuery; @@ -68,86 +60,6 @@ public class AccessPoliciesController : Controller _updateProjectServiceAccountsAccessPoliciesCommand = updateProjectServiceAccountsAccessPoliciesCommand; } - [HttpPost("/projects/{id}/access-policies")] - public async Task CreateProjectAccessPoliciesAsync([FromRoute] Guid id, - [FromBody] AccessPoliciesCreateRequest request) - { - if (request.Count() > _maxBulkCreation) - { - throw new BadRequestException($"Can process no more than {_maxBulkCreation} creation requests at once."); - } - - var project = await _projectRepository.GetByIdAsync(id); - if (project == null) - { - throw new NotFoundException(); - } - - var policies = request.ToBaseAccessPoliciesForProject(id, project.OrganizationId); - foreach (var policy in policies) - { - var authorizationResult = await _authorizationService.AuthorizeAsync(User, policy, AccessPolicyOperations.Create); - if (!authorizationResult.Succeeded) - { - throw new NotFoundException(); - } - } - - var results = await _createAccessPoliciesCommand.CreateManyAsync(policies); - return new ProjectAccessPoliciesResponseModel(results); - } - - [HttpGet("/projects/{id}/access-policies")] - public async Task GetProjectAccessPoliciesAsync([FromRoute] Guid id) - { - var project = await _projectRepository.GetByIdAsync(id); - var (_, userId) = await CheckUserHasWriteAccessToProjectAsync(project); - var results = await _accessPolicyRepository.GetManyByGrantedProjectIdAsync(id, userId); - return new ProjectAccessPoliciesResponseModel(results); - } - - [HttpPut("{id}")] - public async Task UpdateAccessPolicyAsync([FromRoute] Guid id, - [FromBody] AccessPolicyUpdateRequest request) - { - var ap = await _accessPolicyRepository.GetByIdAsync(id); - var authorizationResult = - await _authorizationService.AuthorizeAsync(User, ap, AccessPolicyOperations.Update); - if (!authorizationResult.Succeeded) - { - throw new NotFoundException(); - } - - var result = await _updateAccessPolicyCommand.UpdateAsync(id, request.Read, request.Write); - - return result switch - { - UserProjectAccessPolicy accessPolicy => new UserProjectAccessPolicyResponseModel(accessPolicy), - UserServiceAccountAccessPolicy accessPolicy => - new UserServiceAccountAccessPolicyResponseModel(accessPolicy), - GroupProjectAccessPolicy accessPolicy => new GroupProjectAccessPolicyResponseModel(accessPolicy), - GroupServiceAccountAccessPolicy accessPolicy => new GroupServiceAccountAccessPolicyResponseModel( - accessPolicy), - ServiceAccountProjectAccessPolicy accessPolicy => new ServiceAccountProjectAccessPolicyResponseModel( - accessPolicy), - _ => throw new ArgumentException("Unsupported access policy type provided."), - }; - } - - [HttpDelete("{id}")] - public async Task DeleteAccessPolicyAsync([FromRoute] Guid id) - { - var ap = await _accessPolicyRepository.GetByIdAsync(id); - var authorizationResult = - await _authorizationService.AuthorizeAsync(User, ap, AccessPolicyOperations.Delete); - if (!authorizationResult.Succeeded) - { - throw new NotFoundException(); - } - - await _deleteAccessPolicyCommand.DeleteAsync(id); - } - [HttpGet("/organizations/{id}/access-policies/people/potential-grantees")] public async Task> GetPeoplePotentialGranteesAsync( [FromRoute] Guid id) @@ -157,7 +69,7 @@ public class AccessPoliciesController : Controller throw new NotFoundException(); } - var userId = _userService.GetProperUserId(User).Value; + var userId = _userService.GetProperUserId(User)!.Value; var peopleGrantees = await _accessPolicyRepository.GetPeopleGranteesAsync(id, userId); var userResponses = peopleGrantees.UserGrantees.Select(ug => new PotentialGranteeResponseModel(ug)); @@ -169,7 +81,12 @@ public class AccessPoliciesController : Controller public async Task> GetServiceAccountsPotentialGranteesAsync( [FromRoute] Guid id) { - var (accessClient, userId) = await GetAccessClientTypeAsync(id); + if (!_currentContext.AccessSecretsManager(id)) + { + throw new NotFoundException(); + } + + var (accessClient, userId) = await _accessClientQuery.GetAccessClientAsync(User, id); var serviceAccounts = await _serviceAccountRepository.GetManyByOrganizationIdWriteAccessAsync(id, @@ -185,7 +102,12 @@ public class AccessPoliciesController : Controller public async Task> GetProjectPotentialGranteesAsync( [FromRoute] Guid id) { - var (accessClient, userId) = await GetAccessClientTypeAsync(id); + if (!_currentContext.AccessSecretsManager(id)) + { + throw new NotFoundException(); + } + + var (accessClient, userId) = await _accessClientQuery.GetAccessClientAsync(User, id); var projects = await _projectRepository.GetManyByOrganizationIdWriteAccessAsync(id, @@ -225,7 +147,7 @@ public class AccessPoliciesController : Controller throw new NotFoundException(); } - var userId = _userService.GetProperUserId(User).Value; + var userId = _userService.GetProperUserId(User)!.Value; var results = await _accessPolicyRepository.ReplaceProjectPeopleAsync(peopleAccessPolicies, userId); return new ProjectPeopleAccessPoliciesResponseModel(results, userId); } @@ -337,39 +259,48 @@ public class AccessPoliciesController : Controller return new ProjectServiceAccountsAccessPoliciesResponseModel(results); } - private async Task<(AccessClientType AccessClientType, Guid UserId)> CheckUserHasWriteAccessToProjectAsync(Project project) + private async Task<(AccessClientType AccessClientType, Guid UserId)> CheckUserHasWriteAccessToProjectAsync( + Project project) { if (project == null) { throw new NotFoundException(); } - var (accessClient, userId) = await GetAccessClientTypeAsync(project.OrganizationId); + if (!_currentContext.AccessSecretsManager(project.OrganizationId)) + { + throw new NotFoundException(); + } + + var (accessClient, userId) = await _accessClientQuery.GetAccessClientAsync(User, project.OrganizationId); + var access = await _projectRepository.AccessToProjectAsync(project.Id, userId, accessClient); if (!access.Write || accessClient == AccessClientType.ServiceAccount) { throw new NotFoundException(); } + return (accessClient, userId); } - private async Task<(AccessClientType AccessClientType, Guid UserId)> CheckUserHasWriteAccessToServiceAccountAsync(ServiceAccount serviceAccount) + private async Task<(AccessClientType AccessClientType, Guid UserId)> CheckUserHasWriteAccessToServiceAccountAsync( + ServiceAccount serviceAccount) { if (serviceAccount == null) { throw new NotFoundException(); } - var (accessClient, userId) = await GetAccessClientTypeAsync(serviceAccount.OrganizationId); - var hasAccess = accessClient switch + if (!_currentContext.AccessSecretsManager(serviceAccount.OrganizationId)) { - AccessClientType.NoAccessCheck => true, - AccessClientType.User => await _serviceAccountRepository.UserHasWriteAccessToServiceAccount( - serviceAccount.Id, userId), - _ => false, - }; + throw new NotFoundException(); + } - if (!hasAccess) + var (accessClient, userId) = await _accessClientQuery.GetAccessClientAsync(User, serviceAccount.OrganizationId); + + var access = + await _serviceAccountRepository.AccessToServiceAccountAsync(serviceAccount.Id, userId, accessClient); + if (!access.Write) { throw new NotFoundException(); } @@ -377,23 +308,13 @@ public class AccessPoliciesController : Controller return (accessClient, userId); } - private async Task<(AccessClientType AccessClientType, Guid UserId)> GetAccessClientTypeAsync(Guid organizationId) - { - if (!_currentContext.AccessSecretsManager(organizationId)) - { - throw new NotFoundException(); - } - - var userId = _userService.GetProperUserId(User).Value; - var orgAdmin = await _currentContext.OrganizationAdmin(organizationId); - var accessClient = AccessClientHelper.ToAccessClient(_currentContext.ClientType, orgAdmin); - return (accessClient, userId); - } - - private async Task GetServiceAccountGrantedPoliciesAsync(ServiceAccount serviceAccount) + private async Task + GetServiceAccountGrantedPoliciesAsync(ServiceAccount serviceAccount) { var (accessClient, userId) = await _accessClientQuery.GetAccessClientAsync(User, serviceAccount.OrganizationId); - var results = await _accessPolicyRepository.GetServiceAccountGrantedPoliciesPermissionDetailsAsync(serviceAccount.Id, userId, accessClient); + var results = + await _accessPolicyRepository.GetServiceAccountGrantedPoliciesPermissionDetailsAsync(serviceAccount.Id, + userId, accessClient); return new ServiceAccountGrantedPoliciesPermissionDetailsResponseModel(results); } } diff --git a/src/Api/SecretsManager/Models/Request/AccessPoliciesCreateRequest.cs b/src/Api/SecretsManager/Models/Request/AccessPoliciesCreateRequest.cs deleted file mode 100644 index 727d0ab25..000000000 --- a/src/Api/SecretsManager/Models/Request/AccessPoliciesCreateRequest.cs +++ /dev/null @@ -1,184 +0,0 @@ -#nullable enable -using System.ComponentModel.DataAnnotations; -using Bit.Core.Exceptions; -using Bit.Core.SecretsManager.Entities; - -namespace Bit.Api.SecretsManager.Models.Request; - -public class AccessPoliciesCreateRequest -{ - private static void CheckForDistinctAccessPolicies(IReadOnlyCollection accessPolicies) - { - var distinctAccessPolicies = accessPolicies.DistinctBy(baseAccessPolicy => - { - return baseAccessPolicy switch - { - UserProjectAccessPolicy ap => new Tuple(ap.OrganizationUserId, ap.GrantedProjectId), - GroupProjectAccessPolicy ap => new Tuple(ap.GroupId, ap.GrantedProjectId), - ServiceAccountProjectAccessPolicy ap => new Tuple(ap.ServiceAccountId, - ap.GrantedProjectId), - UserServiceAccountAccessPolicy ap => new Tuple(ap.OrganizationUserId, - ap.GrantedServiceAccountId), - GroupServiceAccountAccessPolicy ap => new Tuple(ap.GroupId, ap.GrantedServiceAccountId), - _ => throw new ArgumentException("Unsupported access policy type provided.", nameof(baseAccessPolicy)), - }; - }).ToList(); - - if (accessPolicies.Count != distinctAccessPolicies.Count) - { - throw new BadRequestException("Resources must be unique"); - } - } - - public IEnumerable? UserAccessPolicyRequests { get; set; } - - public IEnumerable? GroupAccessPolicyRequests { get; set; } - - public IEnumerable? ServiceAccountAccessPolicyRequests { get; set; } - - public List ToBaseAccessPoliciesForProject(Guid grantedProjectId, Guid organizationId) - { - if (UserAccessPolicyRequests == null && GroupAccessPolicyRequests == null && ServiceAccountAccessPolicyRequests == null) - { - throw new BadRequestException("No creation requests provided."); - } - - var userAccessPolicies = UserAccessPolicyRequests? - .Select(x => x.ToUserProjectAccessPolicy(grantedProjectId, organizationId)).ToList(); - - var groupAccessPolicies = GroupAccessPolicyRequests? - .Select(x => x.ToGroupProjectAccessPolicy(grantedProjectId, organizationId)).ToList(); - - var serviceAccountAccessPolicies = ServiceAccountAccessPolicyRequests? - .Select(x => x.ToServiceAccountProjectAccessPolicy(grantedProjectId, organizationId)).ToList(); - - var policies = new List(); - if (userAccessPolicies != null) - { - policies.AddRange(userAccessPolicies); - } - - if (groupAccessPolicies != null) - { - policies.AddRange(groupAccessPolicies); - } - - if (serviceAccountAccessPolicies != null) - { - policies.AddRange(serviceAccountAccessPolicies); - } - - CheckForDistinctAccessPolicies(policies); - return policies; - } - - public List ToBaseAccessPoliciesForServiceAccount(Guid grantedServiceAccountId, Guid organizationId) - { - if (UserAccessPolicyRequests == null && GroupAccessPolicyRequests == null) - { - throw new BadRequestException("No creation requests provided."); - } - - var userAccessPolicies = UserAccessPolicyRequests? - .Select(x => x.ToUserServiceAccountAccessPolicy(grantedServiceAccountId, organizationId)).ToList(); - - var groupAccessPolicies = GroupAccessPolicyRequests? - .Select(x => x.ToGroupServiceAccountAccessPolicy(grantedServiceAccountId, organizationId)).ToList(); - - var policies = new List(); - if (userAccessPolicies != null) - { - policies.AddRange(userAccessPolicies); - } - - if (groupAccessPolicies != null) - { - policies.AddRange(groupAccessPolicies); - } - - CheckForDistinctAccessPolicies(policies); - return policies; - } - - public int Count() - { - var total = 0; - - if (UserAccessPolicyRequests != null) - { - total += UserAccessPolicyRequests.Count(); - } - if (GroupAccessPolicyRequests != null) - { - total += GroupAccessPolicyRequests.Count(); - } - if (ServiceAccountAccessPolicyRequests != null) - { - total += ServiceAccountAccessPolicyRequests.Count(); - } - - return total; - } -} - -public class AccessPolicyRequest -{ - [Required] - public Guid GranteeId { get; set; } - - [Required] - public bool Read { get; set; } - - [Required] - public bool Write { get; set; } - - public UserProjectAccessPolicy ToUserProjectAccessPolicy(Guid projectId, Guid organizationId) => - new() - { - OrganizationUserId = GranteeId, - GrantedProjectId = projectId, - GrantedProject = new Project { OrganizationId = organizationId, Id = projectId }, - Read = Read, - Write = Write - }; - - public GroupProjectAccessPolicy ToGroupProjectAccessPolicy(Guid projectId, Guid organizationId) => - new() - { - GroupId = GranteeId, - GrantedProjectId = projectId, - GrantedProject = new Project { OrganizationId = organizationId, Id = projectId }, - Read = Read, - Write = Write - }; - - public ServiceAccountProjectAccessPolicy ToServiceAccountProjectAccessPolicy(Guid projectId, Guid organizationId) => - new() - { - ServiceAccountId = GranteeId, - GrantedProjectId = projectId, - GrantedProject = new Project { OrganizationId = organizationId, Id = projectId }, - Read = Read, - Write = Write - }; - - public UserServiceAccountAccessPolicy ToUserServiceAccountAccessPolicy(Guid id, Guid organizationId) => - new() - { - OrganizationUserId = GranteeId, - GrantedServiceAccountId = id, - GrantedServiceAccount = new ServiceAccount() { OrganizationId = organizationId, Id = id }, - Read = Read, - Write = Write - }; - - public GroupServiceAccountAccessPolicy ToGroupServiceAccountAccessPolicy(Guid id, Guid organizationId) => - new() - { - GroupId = GranteeId, - GrantedServiceAccountId = id, - GrantedServiceAccount = new ServiceAccount() { OrganizationId = organizationId, Id = id }, - Read = Read, - Write = Write - }; -} diff --git a/src/Api/SecretsManager/Models/Request/AccessPolicyRequest.cs b/src/Api/SecretsManager/Models/Request/AccessPolicyRequest.cs new file mode 100644 index 000000000..eef6181c9 --- /dev/null +++ b/src/Api/SecretsManager/Models/Request/AccessPolicyRequest.cs @@ -0,0 +1,67 @@ +#nullable enable +using System.ComponentModel.DataAnnotations; +using Bit.Core.SecretsManager.Entities; + +namespace Bit.Api.SecretsManager.Models.Request; + +public class AccessPolicyRequest +{ + [Required] + public Guid GranteeId { get; set; } + + [Required] + public bool Read { get; set; } + + [Required] + public bool Write { get; set; } + + public UserProjectAccessPolicy ToUserProjectAccessPolicy(Guid projectId, Guid organizationId) => + new() + { + OrganizationUserId = GranteeId, + GrantedProjectId = projectId, + GrantedProject = new Project { OrganizationId = organizationId, Id = projectId }, + Read = Read, + Write = Write + }; + + public GroupProjectAccessPolicy ToGroupProjectAccessPolicy(Guid projectId, Guid organizationId) => + new() + { + GroupId = GranteeId, + GrantedProjectId = projectId, + GrantedProject = new Project { OrganizationId = organizationId, Id = projectId }, + Read = Read, + Write = Write + }; + + public ServiceAccountProjectAccessPolicy ToServiceAccountProjectAccessPolicy(Guid projectId, Guid organizationId) => + new() + { + ServiceAccountId = GranteeId, + GrantedProjectId = projectId, + GrantedProject = new Project { OrganizationId = organizationId, Id = projectId }, + Read = Read, + Write = Write + }; + + public UserServiceAccountAccessPolicy ToUserServiceAccountAccessPolicy(Guid id, Guid organizationId) => + new() + { + OrganizationUserId = GranteeId, + GrantedServiceAccountId = id, + GrantedServiceAccount = new ServiceAccount() { OrganizationId = organizationId, Id = id }, + Read = Read, + Write = Write + }; + + public GroupServiceAccountAccessPolicy ToGroupServiceAccountAccessPolicy(Guid id, Guid organizationId) => + new() + { + GroupId = GranteeId, + GrantedServiceAccountId = id, + GrantedServiceAccount = new ServiceAccount() { OrganizationId = organizationId, Id = id }, + Read = Read, + Write = Write + }; +} diff --git a/src/Api/SecretsManager/Models/Request/AccessPolicyUpdateRequest.cs b/src/Api/SecretsManager/Models/Request/AccessPolicyUpdateRequest.cs deleted file mode 100644 index bb918a62d..000000000 --- a/src/Api/SecretsManager/Models/Request/AccessPolicyUpdateRequest.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Bit.Api.SecretsManager.Models.Request; - -public class AccessPolicyUpdateRequest -{ - [Required] - public bool Read { get; set; } - - [Required] - public bool Write { get; set; } -} diff --git a/src/Api/SecretsManager/Models/Request/PeopleAccessPoliciesRequestModel.cs b/src/Api/SecretsManager/Models/Request/PeopleAccessPoliciesRequestModel.cs index b792b8ef2..1ce74aca3 100644 --- a/src/Api/SecretsManager/Models/Request/PeopleAccessPoliciesRequestModel.cs +++ b/src/Api/SecretsManager/Models/Request/PeopleAccessPoliciesRequestModel.cs @@ -1,4 +1,5 @@ -using Bit.Core.Exceptions; +using Bit.Api.SecretsManager.Utilities; +using Bit.Core.Exceptions; using Bit.Core.SecretsManager.Entities; using Bit.Core.SecretsManager.Models.Data; @@ -10,29 +11,6 @@ public class PeopleAccessPoliciesRequestModel public IEnumerable GroupAccessPolicyRequests { get; set; } - private static void CheckForDistinctAccessPolicies(IReadOnlyCollection accessPolicies) - { - var distinctAccessPolicies = accessPolicies.DistinctBy(baseAccessPolicy => - { - return baseAccessPolicy switch - { - UserProjectAccessPolicy ap => new Tuple(ap.OrganizationUserId, ap.GrantedProjectId), - GroupProjectAccessPolicy ap => new Tuple(ap.GroupId, ap.GrantedProjectId), - ServiceAccountProjectAccessPolicy ap => new Tuple(ap.ServiceAccountId, - ap.GrantedProjectId), - UserServiceAccountAccessPolicy ap => new Tuple(ap.OrganizationUserId, - ap.GrantedServiceAccountId), - GroupServiceAccountAccessPolicy ap => new Tuple(ap.GroupId, ap.GrantedServiceAccountId), - _ => throw new ArgumentException("Unsupported access policy type provided.", nameof(baseAccessPolicy)) - }; - }).ToList(); - - if (accessPolicies.Count != distinctAccessPolicies.Count) - { - throw new BadRequestException("Resources must be unique"); - } - } - public ProjectPeopleAccessPolicies ToProjectPeopleAccessPolicies(Guid grantedProjectId, Guid organizationId) { var userAccessPolicies = UserAccessPolicyRequests? @@ -51,7 +29,8 @@ public class PeopleAccessPoliciesRequestModel policies.AddRange(groupAccessPolicies); } - CheckForDistinctAccessPolicies(policies); + AccessPolicyHelpers.CheckForDistinctAccessPolicies(policies); + AccessPolicyHelpers.CheckAccessPoliciesHaveReadPermission(policies); return new ProjectPeopleAccessPolicies { @@ -62,7 +41,8 @@ public class PeopleAccessPoliciesRequestModel }; } - public ServiceAccountPeopleAccessPolicies ToServiceAccountPeopleAccessPolicies(Guid grantedServiceAccountId, Guid organizationId) + public ServiceAccountPeopleAccessPolicies ToServiceAccountPeopleAccessPolicies(Guid grantedServiceAccountId, + Guid organizationId) { var userAccessPolicies = UserAccessPolicyRequests? .Select(x => x.ToUserServiceAccountAccessPolicy(grantedServiceAccountId, organizationId)).ToList(); @@ -81,7 +61,7 @@ public class PeopleAccessPoliciesRequestModel policies.AddRange(groupAccessPolicies); } - CheckForDistinctAccessPolicies(policies); + AccessPolicyHelpers.CheckForDistinctAccessPolicies(policies); if (!policies.All(ap => ap.Read && ap.Write)) { diff --git a/src/Api/SecretsManager/Models/Response/ProjectAccessPoliciesResponseModel.cs b/src/Api/SecretsManager/Models/Response/ProjectAccessPoliciesResponseModel.cs deleted file mode 100644 index 7308d1833..000000000 --- a/src/Api/SecretsManager/Models/Response/ProjectAccessPoliciesResponseModel.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Bit.Core.Models.Api; -using Bit.Core.SecretsManager.Entities; - -namespace Bit.Api.SecretsManager.Models.Response; - -public class ProjectAccessPoliciesResponseModel : ResponseModel -{ - private const string _objectName = "projectAccessPolicies"; - - public ProjectAccessPoliciesResponseModel(IEnumerable baseAccessPolicies) - : base(_objectName) - { - foreach (var baseAccessPolicy in baseAccessPolicies) - { - switch (baseAccessPolicy) - { - case UserProjectAccessPolicy accessPolicy: - UserAccessPolicies.Add(new UserProjectAccessPolicyResponseModel(accessPolicy)); - break; - case GroupProjectAccessPolicy accessPolicy: - GroupAccessPolicies.Add(new GroupProjectAccessPolicyResponseModel(accessPolicy)); - break; - case ServiceAccountProjectAccessPolicy accessPolicy: - ServiceAccountAccessPolicies.Add( - new ServiceAccountProjectAccessPolicyResponseModel(accessPolicy)); - break; - } - } - } - - public ProjectAccessPoliciesResponseModel() : base(_objectName) - { - } - - public List UserAccessPolicies { get; set; } = new(); - - public List GroupAccessPolicies { get; set; } = new(); - - public List ServiceAccountAccessPolicies { get; set; } = new(); -} diff --git a/src/Core/SecretsManager/AuthorizationRequirements/AccessPolicyOperationRequirement.cs b/src/Core/SecretsManager/AuthorizationRequirements/AccessPolicyOperationRequirement.cs deleted file mode 100644 index b1ab18979..000000000 --- a/src/Core/SecretsManager/AuthorizationRequirements/AccessPolicyOperationRequirement.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Microsoft.AspNetCore.Authorization.Infrastructure; - -namespace Bit.Core.SecretsManager.AuthorizationRequirements; - -public class AccessPolicyOperationRequirement : OperationAuthorizationRequirement -{ -} - -public static class AccessPolicyOperations -{ - public static readonly AccessPolicyOperationRequirement Create = new() { Name = nameof(Create) }; - public static readonly AccessPolicyOperationRequirement Update = new() { Name = nameof(Update) }; - public static readonly AccessPolicyOperationRequirement Delete = new() { Name = nameof(Delete) }; -} diff --git a/src/Core/SecretsManager/Commands/AccessPolicies/Interfaces/ICreateAccessPoliciesCommand.cs b/src/Core/SecretsManager/Commands/AccessPolicies/Interfaces/ICreateAccessPoliciesCommand.cs deleted file mode 100644 index 2d0fdd987..000000000 --- a/src/Core/SecretsManager/Commands/AccessPolicies/Interfaces/ICreateAccessPoliciesCommand.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Bit.Core.SecretsManager.Entities; - -namespace Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces; - -public interface ICreateAccessPoliciesCommand -{ - Task> CreateManyAsync(List accessPolicies); -} diff --git a/src/Core/SecretsManager/Commands/AccessPolicies/Interfaces/IDeleteAccessPolicyCommand.cs b/src/Core/SecretsManager/Commands/AccessPolicies/Interfaces/IDeleteAccessPolicyCommand.cs deleted file mode 100644 index de3215a02..000000000 --- a/src/Core/SecretsManager/Commands/AccessPolicies/Interfaces/IDeleteAccessPolicyCommand.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces; - -public interface IDeleteAccessPolicyCommand -{ - Task DeleteAsync(Guid id); -} diff --git a/src/Core/SecretsManager/Commands/AccessPolicies/Interfaces/IUpdateAccessPolicyCommand.cs b/src/Core/SecretsManager/Commands/AccessPolicies/Interfaces/IUpdateAccessPolicyCommand.cs deleted file mode 100644 index 225f6a752..000000000 --- a/src/Core/SecretsManager/Commands/AccessPolicies/Interfaces/IUpdateAccessPolicyCommand.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Bit.Core.SecretsManager.Entities; - -namespace Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces; - -public interface IUpdateAccessPolicyCommand -{ - public Task UpdateAsync(Guid id, bool read, bool write); -} diff --git a/src/Core/SecretsManager/Repositories/IAccessPolicyRepository.cs b/src/Core/SecretsManager/Repositories/IAccessPolicyRepository.cs index ed20f754e..8696e9051 100644 --- a/src/Core/SecretsManager/Repositories/IAccessPolicyRepository.cs +++ b/src/Core/SecretsManager/Repositories/IAccessPolicyRepository.cs @@ -9,11 +9,6 @@ namespace Bit.Core.SecretsManager.Repositories; public interface IAccessPolicyRepository { Task> CreateManyAsync(List baseAccessPolicies); - Task AccessPolicyExists(BaseAccessPolicy baseAccessPolicy); - Task GetByIdAsync(Guid id); - Task> GetManyByGrantedProjectIdAsync(Guid id, Guid userId); - Task ReplaceAsync(BaseAccessPolicy baseAccessPolicy); - Task DeleteAsync(Guid id); Task> GetPeoplePoliciesByGrantedProjectIdAsync(Guid id, Guid userId); Task> ReplaceProjectPeopleAsync(ProjectPeopleAccessPolicies peopleAccessPolicies, Guid userId); Task GetPeopleGranteesAsync(Guid organizationId, Guid currentUserId); diff --git a/src/Core/SecretsManager/Repositories/IServiceAccountRepository.cs b/src/Core/SecretsManager/Repositories/IServiceAccountRepository.cs index 5c871fbf8..9fa412ddf 100644 --- a/src/Core/SecretsManager/Repositories/IServiceAccountRepository.cs +++ b/src/Core/SecretsManager/Repositories/IServiceAccountRepository.cs @@ -12,8 +12,6 @@ public interface IServiceAccountRepository Task CreateAsync(ServiceAccount serviceAccount); Task ReplaceAsync(ServiceAccount serviceAccount); Task DeleteManyByIdAsync(IEnumerable ids); - Task UserHasReadAccessToServiceAccount(Guid id, Guid userId); - Task UserHasWriteAccessToServiceAccount(Guid id, Guid userId); Task> GetManyByOrganizationIdWriteAccessAsync(Guid organizationId, Guid userId, AccessClientType accessType); Task<(bool Read, bool Write)> AccessToServiceAccountAsync(Guid id, Guid userId, AccessClientType accessType); Task> AccessToServiceAccountsAsync(IEnumerable ids, Guid userId, diff --git a/test/Api.IntegrationTest/SecretsManager/Controllers/AccessPoliciesControllerTests.cs b/test/Api.IntegrationTest/SecretsManager/Controllers/AccessPoliciesControllerTests.cs index 9a7db1876..aacf33860 100644 --- a/test/Api.IntegrationTest/SecretsManager/Controllers/AccessPoliciesControllerTests.cs +++ b/test/Api.IntegrationTest/SecretsManager/Controllers/AccessPoliciesControllerTests.cs @@ -11,7 +11,6 @@ using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.SecretsManager.Entities; using Bit.Core.SecretsManager.Repositories; -using Bit.Test.Common.Helpers; using Xunit; namespace Bit.Api.IntegrationTest.SecretsManager.Controllers; @@ -25,10 +24,10 @@ public class AccessPoliciesControllerTests : IClassFixture - { - new() { GranteeId = serviceAccountId, Read = true, Write = true }, - }, - }; - - var response = await _client.PostAsJsonAsync($"/projects/{projectId}/access-policies", request); - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - - [Fact] - public async Task CreateProjectAccessPolicies_NoPermission() - { - // Create a new account as a user - var (org, _) = await _organizationHelper.Initialize(true, true, true); - var (email, _) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true); - await _loginHelper.LoginAsync(email); - - var (projectId, serviceAccountId) = await CreateProjectAndServiceAccountAsync(org.Id); - var request = new AccessPoliciesCreateRequest - { - ServiceAccountAccessPolicyRequests = new List - { - new() { GranteeId = serviceAccountId, Read = true, Write = true }, - }, - }; - - var response = await _client.PostAsJsonAsync($"/projects/{projectId}/access-policies", request); - - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - - [Theory] - [InlineData(PermissionType.RunAsAdmin)] - [InlineData(PermissionType.RunAsUserWithPermission)] - public async Task CreateProjectAccessPolicies_MismatchedOrgIds_NotFound(PermissionType permissionType) - { - var (org, _) = await _organizationHelper.Initialize(true, true, true); - await _loginHelper.LoginAsync(_email); - - var (projectId, serviceAccountId) = await CreateProjectAndServiceAccountAsync(org.Id, true); - await SetupProjectAndServiceAccountPermissionAsync(permissionType, projectId, serviceAccountId); - - var request = new AccessPoliciesCreateRequest - { - ServiceAccountAccessPolicyRequests = new List - { - new() { GranteeId = serviceAccountId, Read = true, Write = true }, - }, - }; - - - var response = await _client.PostAsJsonAsync($"/projects/{projectId}/access-policies", request); - - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - - [Theory] - [InlineData(PermissionType.RunAsAdmin)] - [InlineData(PermissionType.RunAsUserWithPermission)] - public async Task CreateProjectAccessPolicies_Success(PermissionType permissionType) - { - var (org, _) = await _organizationHelper.Initialize(true, true, true); - await _loginHelper.LoginAsync(_email); - - var (projectId, serviceAccountId) = await CreateProjectAndServiceAccountAsync(org.Id); - await SetupProjectAndServiceAccountPermissionAsync(permissionType, projectId, serviceAccountId); - - var request = new AccessPoliciesCreateRequest - { - ServiceAccountAccessPolicyRequests = new List - { - new() { GranteeId = serviceAccountId, Read = true, Write = true }, - }, - }; - - var response = await _client.PostAsJsonAsync($"/projects/{projectId}/access-policies", request); - response.EnsureSuccessStatusCode(); - - var result = await response.Content.ReadFromJsonAsync(); - - Assert.NotNull(result); - Assert.Equal(serviceAccountId, result.ServiceAccountAccessPolicies.First().ServiceAccountId); - Assert.True(result.ServiceAccountAccessPolicies.First().Read); - Assert.True(result.ServiceAccountAccessPolicies.First().Write); - AssertHelper.AssertRecent(result.ServiceAccountAccessPolicies.First().RevisionDate); - AssertHelper.AssertRecent(result.ServiceAccountAccessPolicies.First().CreationDate); - - var createdAccessPolicy = - await _accessPolicyRepository.GetByIdAsync(result.ServiceAccountAccessPolicies.First().Id); - Assert.NotNull(createdAccessPolicy); - Assert.Equal(result.ServiceAccountAccessPolicies.First().Read, createdAccessPolicy.Read); - Assert.Equal(result.ServiceAccountAccessPolicies.First().Write, createdAccessPolicy.Write); - Assert.Equal(result.ServiceAccountAccessPolicies.First().Id, createdAccessPolicy.Id); - AssertHelper.AssertRecent(createdAccessPolicy.CreationDate); - AssertHelper.AssertRecent(createdAccessPolicy.RevisionDate); - } - - [Theory] - [InlineData(false, false, false)] - [InlineData(false, false, true)] - [InlineData(false, true, false)] - [InlineData(false, true, true)] - [InlineData(true, false, false)] - [InlineData(true, false, true)] - [InlineData(true, true, false)] - public async Task UpdateAccessPolicy_SmAccessDenied_NotFound(bool useSecrets, bool accessSecrets, bool organizationEnabled) - { - var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets, organizationEnabled); - await _loginHelper.LoginAsync(_email); - var initData = await SetupAccessPolicyRequest(org.Id); - - const bool expectedRead = true; - const bool expectedWrite = false; - var request = new AccessPolicyUpdateRequest { Read = expectedRead, Write = expectedWrite }; - - var response = await _client.PutAsJsonAsync($"/access-policies/{initData.AccessPolicyId}", request); - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - - [Fact] - public async Task UpdateAccessPolicy_NoPermission() - { - // Create a new account as a user - await _organizationHelper.Initialize(true, true, true); - var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true); - await _loginHelper.LoginAsync(email); - - var initData = await SetupAccessPolicyRequest(orgUser.OrganizationId); - - const bool expectedRead = true; - const bool expectedWrite = false; - var request = new AccessPolicyUpdateRequest { Read = expectedRead, Write = expectedWrite }; - - var response = await _client.PutAsJsonAsync($"/access-policies/{initData.AccessPolicyId}", request); - - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - - [Theory] - [InlineData(PermissionType.RunAsAdmin)] - [InlineData(PermissionType.RunAsUserWithPermission)] - public async Task UpdateAccessPolicy_Success(PermissionType permissionType) - { - var (org, _) = await _organizationHelper.Initialize(true, true, true); - await _loginHelper.LoginAsync(_email); - var initData = await SetupAccessPolicyRequest(org.Id); - - if (permissionType == PermissionType.RunAsUserWithPermission) - { - var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true); - await _loginHelper.LoginAsync(email); - var accessPolicies = new List - { - new UserProjectAccessPolicy - { - GrantedProjectId = initData.ProjectId, OrganizationUserId = orgUser.Id, Read = true, Write = true, - }, - }; - await _accessPolicyRepository.CreateManyAsync(accessPolicies); - } - - const bool expectedRead = true; - const bool expectedWrite = false; - var request = new AccessPolicyUpdateRequest { Read = expectedRead, Write = expectedWrite }; - - var response = await _client.PutAsJsonAsync($"/access-policies/{initData.AccessPolicyId}", request); - response.EnsureSuccessStatusCode(); - - var result = await response.Content.ReadFromJsonAsync(); - - Assert.NotNull(result); - Assert.Equal(expectedRead, result.Read); - Assert.Equal(expectedWrite, result.Write); - AssertHelper.AssertRecent(result.RevisionDate); - - var updatedAccessPolicy = await _accessPolicyRepository.GetByIdAsync(result.Id); - Assert.NotNull(updatedAccessPolicy); - Assert.Equal(expectedRead, updatedAccessPolicy.Read); - Assert.Equal(expectedWrite, updatedAccessPolicy.Write); - AssertHelper.AssertRecent(updatedAccessPolicy.RevisionDate); - } - - [Theory] - [InlineData(false, false, false)] - [InlineData(false, false, true)] - [InlineData(false, true, false)] - [InlineData(false, true, true)] - [InlineData(true, false, false)] - [InlineData(true, false, true)] - [InlineData(true, true, false)] - public async Task DeleteAccessPolicy_SmAccessDenied_NotFound(bool useSecrets, bool accessSecrets, bool organizationEnabled) - { - var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets, organizationEnabled); - await _loginHelper.LoginAsync(_email); - var initData = await SetupAccessPolicyRequest(org.Id); - - var response = await _client.DeleteAsync($"/access-policies/{initData.AccessPolicyId}"); - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - - [Fact] - public async Task DeleteAccessPolicy_NoPermission() - { - // Create a new account as a user - await _organizationHelper.Initialize(true, true, true); - var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true); - await _loginHelper.LoginAsync(email); - - var initData = await SetupAccessPolicyRequest(orgUser.OrganizationId); - - var response = await _client.DeleteAsync($"/access-policies/{initData.AccessPolicyId}"); - - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - - [Theory] - [InlineData(PermissionType.RunAsAdmin)] - [InlineData(PermissionType.RunAsUserWithPermission)] - public async Task DeleteAccessPolicy_Success(PermissionType permissionType) - { - var (org, _) = await _organizationHelper.Initialize(true, true, true); - await _loginHelper.LoginAsync(_email); - var initData = await SetupAccessPolicyRequest(org.Id); - - if (permissionType == PermissionType.RunAsUserWithPermission) - { - var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true); - await _loginHelper.LoginAsync(email); - var accessPolicies = new List - { - new UserProjectAccessPolicy - { - GrantedProjectId = initData.ProjectId, OrganizationUserId = orgUser.Id, Read = true, Write = true, - }, - }; - await _accessPolicyRepository.CreateManyAsync(accessPolicies); - } - - var response = await _client.DeleteAsync($"/access-policies/{initData.AccessPolicyId}"); - response.EnsureSuccessStatusCode(); - - var test = await _accessPolicyRepository.GetByIdAsync(initData.AccessPolicyId); - Assert.Null(test); - } - - [Fact] - public async Task GetProjectAccessPolicies_ReturnsEmpty() - { - var (org, _) = await _organizationHelper.Initialize(true, true, true); - await _loginHelper.LoginAsync(_email); - - var project = await _projectRepository.CreateAsync(new Project - { - OrganizationId = org.Id, - Name = _mockEncryptedString, - }); - - var response = await _client.GetAsync($"/projects/{project.Id}/access-policies"); - response.EnsureSuccessStatusCode(); - - var result = await response.Content.ReadFromJsonAsync(); - - Assert.NotNull(result); - Assert.Empty(result.UserAccessPolicies); - Assert.Empty(result.GroupAccessPolicies); - Assert.Empty(result.ServiceAccountAccessPolicies); - } - - [Theory] - [InlineData(false, false, false)] - [InlineData(false, false, true)] - [InlineData(false, true, false)] - [InlineData(false, true, true)] - [InlineData(true, false, false)] - [InlineData(true, false, true)] - [InlineData(true, true, false)] - public async Task GetProjectAccessPolicies_SmAccessDenied_NotFound(bool useSecrets, bool accessSecrets, bool organizationEnabled) - { - var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets, organizationEnabled); - await _loginHelper.LoginAsync(_email); - - var initData = await SetupAccessPolicyRequest(org.Id); - - var response = await _client.GetAsync($"/projects/{initData.ProjectId}/access-policies"); - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - - [Fact] - public async Task GetProjectAccessPolicies_NoPermission() - { - // Create a new account as a user - await _organizationHelper.Initialize(true, true, true); - var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true); - await _loginHelper.LoginAsync(email); - - var initData = await SetupAccessPolicyRequest(orgUser.OrganizationId); - - var response = await _client.GetAsync($"/projects/{initData.ProjectId}/access-policies"); - - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - - [Theory] - [InlineData(PermissionType.RunAsAdmin)] - [InlineData(PermissionType.RunAsUserWithPermission)] - public async Task GetProjectAccessPolicies(PermissionType permissionType) - { - var (org, _) = await _organizationHelper.Initialize(true, true, true); - await _loginHelper.LoginAsync(_email); - var initData = await SetupAccessPolicyRequest(org.Id); - - if (permissionType == PermissionType.RunAsUserWithPermission) - { - var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true); - await _loginHelper.LoginAsync(email); - var accessPolicies = new List - { - new UserProjectAccessPolicy - { - GrantedProjectId = initData.ProjectId, OrganizationUserId = orgUser.Id, Read = true, Write = true, - }, - }; - await _accessPolicyRepository.CreateManyAsync(accessPolicies); - } - - var response = await _client.GetAsync($"/projects/{initData.ProjectId}/access-policies"); - response.EnsureSuccessStatusCode(); - - var result = await response.Content.ReadFromJsonAsync(); - - Assert.NotNull(result?.ServiceAccountAccessPolicies); - Assert.Single(result.ServiceAccountAccessPolicies); - } - - [Theory] - [InlineData(false, false, false)] - [InlineData(false, false, true)] - [InlineData(false, true, false)] - [InlineData(false, true, true)] - [InlineData(true, false, false)] - [InlineData(true, false, true)] - [InlineData(true, true, false)] - public async Task GetPeoplePotentialGrantees_SmAccessDenied_NotFound(bool useSecrets, bool accessSecrets, bool organizationEnabled) + public async Task GetPeoplePotentialGrantees_SmAccessDenied_NotFound(bool useSecrets, bool accessSecrets, + bool organizationEnabled) { var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets, organizationEnabled); await _loginHelper.LoginAsync(_email); @@ -460,7 +108,8 @@ public class AccessPoliciesControllerTests : IClassFixture + [ + new UserServiceAccountAccessPolicy { - new UserServiceAccountAccessPolicy - { - GrantedServiceAccountId = serviceAccount.Id, - OrganizationUserId = orgUser.Id, - Read = true, - Write = true, - }, - }); + GrantedServiceAccountId = serviceAccount.Id, + OrganizationUserId = orgUser.Id, + Read = true, + Write = true + } + ]); } var response = @@ -549,7 +197,8 @@ public class AccessPoliciesControllerTests : IClassFixture + [ + new UserProjectAccessPolicy { - new UserProjectAccessPolicy - { - GrantedProjectId = project.Id, OrganizationUserId = orgUser.Id, Read = true, Write = true, - }, - }); + GrantedProjectId = project.Id, + OrganizationUserId = orgUser.Id, + Read = true, + Write = true + } + ]); } var response = @@ -631,7 +282,8 @@ public class AccessPoliciesControllerTests : IClassFixture(); @@ -976,13 +631,6 @@ public class AccessPoliciesControllerTests : IClassFixture(); + var result = await response.Content + .ReadFromJsonAsync(); Assert.NotNull(result); Assert.Empty(result.GrantedProjectPolicies); @@ -1032,7 +682,7 @@ public class AccessPoliciesControllerTests : IClassFixture(); + var result = await response.Content + .ReadFromJsonAsync(); Assert.NotNull(result); Assert.Equal(request.ProjectGrantedPolicyRequests.First().GrantedId, @@ -1177,11 +839,12 @@ public class AccessPoliciesControllerTests : IClassFixture SetupAccessPolicyRequest(Guid organizationId) + private async Task<(Guid ProjectId, Guid ServiceAccountId)> CreateServiceAccountProjectAccessPolicyAsync( + Guid organizationId) { - var project = await _projectRepository.CreateAsync(new Project - { - OrganizationId = organizationId, - Name = _mockEncryptedString, - }); + var (projectId, serviceAccountId) = await CreateProjectAndServiceAccountAsync(organizationId); - var serviceAccount = await _serviceAccountRepository.CreateAsync(new ServiceAccount - { - OrganizationId = organizationId, - Name = _mockEncryptedString, - }); - - var accessPolicy = await _accessPolicyRepository.CreateManyAsync( + await _accessPolicyRepository.CreateManyAsync( [ new ServiceAccountProjectAccessPolicy { Read = true, Write = true, - ServiceAccountId = serviceAccount.Id, - GrantedProjectId = project.Id, + ServiceAccountId = serviceAccountId, + GrantedProjectId = projectId } ]); - return new RequestSetupData - { - ProjectId = project.Id, - ServiceAccountId = serviceAccount.Id, - AccessPolicyId = accessPolicy.First().Id, - }; + return (projectId, serviceAccountId); } private async Task<(Project project, OrganizationUser currentUser)> SetupProjectPeoplePermissionAsync( @@ -1437,14 +1089,15 @@ public class AccessPoliciesControllerTests : IClassFixture SetupServiceAccountPeoplePermissionAsync( - PermissionType permissionType, - OrganizationUser organizationUser) + private async Task<(ServiceAccount serviceAccount, OrganizationUser currentUser)> + SetupServiceAccountPeoplePermissionAsync( + PermissionType permissionType, + OrganizationUser organizationUser) { var serviceAccount = await _serviceAccountRepository.CreateAsync(new ServiceAccount { OrganizationId = organizationUser.OrganizationId, - Name = _mockEncryptedString, + Name = _mockEncryptedString }); if (permissionType == PermissionType.RunAsUserWithPermission) @@ -1484,10 +1137,12 @@ public class AccessPoliciesControllerTests : IClassFixture SetupServiceAccountPeopleRequestAsync( - PermissionType permissionType, OrganizationUser organizationUser) + private async Task<(ServiceAccount serviceAccount, PeopleAccessPoliciesRequestModel request)> + SetupServiceAccountPeopleRequestAsync( + PermissionType permissionType, OrganizationUser organizationUser) { - var (serviceAccount, currentUser) = await SetupServiceAccountPeoplePermissionAsync(permissionType, organizationUser); + var (serviceAccount, currentUser) = + await SetupServiceAccountPeoplePermissionAsync(permissionType, organizationUser); var request = new PeopleAccessPoliciesRequestModel { UserAccessPolicyRequests = new List @@ -1510,47 +1165,24 @@ public class AccessPoliciesControllerTests : IClassFixture + SetupServiceAccountGrantedPoliciesRequestAsync( + PermissionType permissionType, OrganizationUser organizationUser, bool createPreviousAccessPolicy) { - if (permissionType == PermissionType.RunAsUserWithPermission) - { - var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true); - await _loginHelper.LoginAsync(email); - var accessPolicies = new List - { - new UserProjectAccessPolicy - { - GrantedProjectId = projectId, OrganizationUserId = orgUser.Id, Read = true, Write = true, - }, - new UserServiceAccountAccessPolicy - { - GrantedServiceAccountId = serviceAccountId, - OrganizationUserId = orgUser.Id, - Read = true, - Write = true, - }, - }; - await _accessPolicyRepository.CreateManyAsync(accessPolicies); - } - } - - private async Task<(ServiceAccount serviceAccount, ServiceAccountGrantedPoliciesRequestModel request)> SetupServiceAccountGrantedPoliciesRequestAsync( - PermissionType permissionType, OrganizationUser organizationUser, bool createPreviousAccessPolicy) - { - var (serviceAccount, currentUser) = await SetupServiceAccountPeoplePermissionAsync(permissionType, organizationUser); + var (serviceAccount, currentUser) = + await SetupServiceAccountPeoplePermissionAsync(permissionType, organizationUser); var project = await _projectRepository.CreateAsync(new Project { Name = _mockEncryptedString, @@ -1560,8 +1192,8 @@ public class AccessPoliciesControllerTests : IClassFixture, IAs Assert.Null(createdProject.DeletedDate); // Check permissions have been bootstrapped. - var accessPolicies = await _accessPolicyRepository.GetManyByGrantedProjectIdAsync(createdProject.Id, currentUserId); + var accessPolicies = await _accessPolicyRepository.GetPeoplePoliciesByGrantedProjectIdAsync(createdProject.Id, currentUserId); Assert.NotNull(accessPolicies); var ap = (UserProjectAccessPolicy)accessPolicies.First(); Assert.Equal(createdProject.Id, ap.GrantedProjectId); diff --git a/test/Api.Test/SecretsManager/Controllers/AccessPoliciesControllerTests.cs b/test/Api.Test/SecretsManager/Controllers/AccessPoliciesControllerTests.cs index 7b4224f15..41ce62f87 100644 --- a/test/Api.Test/SecretsManager/Controllers/AccessPoliciesControllerTests.cs +++ b/test/Api.Test/SecretsManager/Controllers/AccessPoliciesControllerTests.cs @@ -2,11 +2,9 @@ using System.Security.Claims; using Bit.Api.SecretsManager.Controllers; using Bit.Api.SecretsManager.Models.Request; -using Bit.Api.Test.SecretsManager.Enums; using Bit.Core.Context; using Bit.Core.Enums; using Bit.Core.Exceptions; -using Bit.Core.Identity; using Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces; using Bit.Core.SecretsManager.Entities; using Bit.Core.SecretsManager.Models.Data; @@ -31,324 +29,29 @@ namespace Bit.Api.Test.SecretsManager.Controllers; [JsonDocumentCustomize] public class AccessPoliciesControllerTests { - private const int _overMax = 16; - - [Theory] - [BitAutoData(PermissionType.RunAsAdmin)] - [BitAutoData(PermissionType.RunAsUserWithPermission)] - public async Task GetProjectAccessPolicies_ReturnsEmptyList( - PermissionType permissionType, - SutProvider sutProvider, - Guid id, Project data) - { - sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); - - switch (permissionType) - { - case PermissionType.RunAsAdmin: - SetupAdmin(sutProvider, data.OrganizationId); - sutProvider.GetDependency().AccessToProjectAsync(Arg.Any(), Arg.Any(), - AccessClientType.NoAccessCheck) - .Returns((true, true)); - break; - case PermissionType.RunAsUserWithPermission: - SetupUserWithPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency() - .AccessToProjectAsync(Arg.Any(), Arg.Any(), AccessClientType.User) - .Returns((true, true)); - break; - } - - var result = await sutProvider.Sut.GetProjectAccessPoliciesAsync(id); - - await sutProvider.GetDependency().Received(1) - .GetManyByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)), Arg.Any()); - - Assert.Empty(result.GroupAccessPolicies); - Assert.Empty(result.UserAccessPolicies); - Assert.Empty(result.ServiceAccountAccessPolicies); - } - [Theory] [BitAutoData] - public async Task GetProjectAccessPolicies_UserWithoutPermission_Throws( - SutProvider sutProvider, - Guid id, - Project data) - { - SetupUserWithoutPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); - sutProvider.GetDependency().AccessToProjectAsync(default, default, default) - .Returns((false, false)); - - await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectAccessPoliciesAsync(id)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() - .GetManyByGrantedProjectIdAsync(Arg.Any(), Arg.Any()); - } - - [Theory] - [BitAutoData(PermissionType.RunAsAdmin)] - [BitAutoData(PermissionType.RunAsUserWithPermission)] - public async Task GetProjectAccessPolicies_Success( - PermissionType permissionType, - SutProvider sutProvider, - Guid id, - Project data, - UserProjectAccessPolicy resultAccessPolicy) - { - sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); - switch (permissionType) - { - case PermissionType.RunAsAdmin: - SetupAdmin(sutProvider, data.OrganizationId); - sutProvider.GetDependency().AccessToProjectAsync(Arg.Any(), Arg.Any(), - AccessClientType.NoAccessCheck) - .Returns((true, true)); - break; - case PermissionType.RunAsUserWithPermission: - SetupUserWithPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency() - .AccessToProjectAsync(Arg.Any(), Arg.Any(), AccessClientType.User) - .Returns((true, true)); - break; - } - - sutProvider.GetDependency().GetManyByGrantedProjectIdAsync(default, default) - .ReturnsForAnyArgs(new List { resultAccessPolicy }); - - var result = await sutProvider.Sut.GetProjectAccessPoliciesAsync(id); - - await sutProvider.GetDependency().Received(1) - .GetManyByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)), Arg.Any()); - - Assert.Empty(result.GroupAccessPolicies); - Assert.NotEmpty(result.UserAccessPolicies); - Assert.Empty(result.ServiceAccountAccessPolicies); - } - - [Theory] - [BitAutoData] - public async Task GetProjectAccessPolicies_ProjectsExist_UserWithoutPermission_Throws( - SutProvider sutProvider, - Guid id, - Project data, - UserProjectAccessPolicy resultAccessPolicy) - { - SetupUserWithoutPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); - sutProvider.GetDependency().AccessToProjectAsync(default, default, default) - .Returns((false, false)); - - sutProvider.GetDependency().GetManyByGrantedProjectIdAsync(default, default) - .ReturnsForAnyArgs(new List { resultAccessPolicy }); - - await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectAccessPoliciesAsync(id)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() - .GetManyByGrantedProjectIdAsync(Arg.Any(), Arg.Any()); - } - - [Theory] - [BitAutoData] - public async Task CreateProjectAccessPolicies_RequestMoreThanMax_Throws( - SutProvider sutProvider, - Guid id, - Project mockProject, - UserProjectAccessPolicy data, - AccessPoliciesCreateRequest request) - { - sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(mockProject); - sutProvider.GetDependency().CreateManyAsync(default) - .ReturnsForAnyArgs(new List { data }); - - request = AddRequestsOverMax(request); - - await Assert.ThrowsAsync(() => - sutProvider.Sut.CreateProjectAccessPoliciesAsync(id, request)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() - .CreateManyAsync(Arg.Any>()); - } - - [Theory] - [BitAutoData] - public async Task CreateProjectAccessPolicies_ProjectDoesNotExist_Throws( - SutProvider sutProvider, - Guid id, - AccessPoliciesCreateRequest request) - { - await Assert.ThrowsAsync(() => - sutProvider.Sut.CreateProjectAccessPoliciesAsync(id, request)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() - .CreateManyAsync(Arg.Any>()); - } - - [Theory] - [BitAutoData] - public async Task CreateProjectAccessPolicies_DuplicatePolicy_Throws( - SutProvider sutProvider, - Guid id, - Project mockProject, - UserProjectAccessPolicy data, - AccessPoliciesCreateRequest request) - { - var dup = new AccessPolicyRequest { GranteeId = Guid.NewGuid(), Read = true, Write = true }; - request.UserAccessPolicyRequests = new[] { dup, dup }; - mockProject.Id = id; - sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(mockProject); - sutProvider.GetDependency().CreateManyAsync(default) - .ReturnsForAnyArgs(new List { data }); - - await Assert.ThrowsAsync(() => - sutProvider.Sut.CreateProjectAccessPoliciesAsync(id, request)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() - .CreateManyAsync(Arg.Any>()); - } - - [Theory] - [BitAutoData] - public async Task CreateProjectAccessPolicies_NoAccess_Throws( - SutProvider sutProvider, - Guid id, - Project mockProject, - UserProjectAccessPolicy data, - AccessPoliciesCreateRequest request) - { - mockProject.Id = id; - sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(mockProject); - var policies = request.ToBaseAccessPoliciesForProject(id, mockProject.OrganizationId); - foreach (var policy in policies) - { - sutProvider.GetDependency() - .AuthorizeAsync(Arg.Any(), policy, - Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Failed()); - } - - sutProvider.GetDependency().CreateManyAsync(default) - .ReturnsForAnyArgs(new List { data }); - - await Assert.ThrowsAsync(() => - sutProvider.Sut.CreateProjectAccessPoliciesAsync(id, request)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() - .CreateManyAsync(Arg.Any>()); - } - - [Theory] - [BitAutoData] - public async Task CreateProjectAccessPolicies_Success( - SutProvider sutProvider, - Guid id, - Project mockProject, - UserProjectAccessPolicy data, - AccessPoliciesCreateRequest request) - { - mockProject.Id = id; - sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(mockProject); - var policies = request.ToBaseAccessPoliciesForProject(id, mockProject.OrganizationId); - foreach (var policy in policies) - { - sutProvider.GetDependency() - .AuthorizeAsync(Arg.Any(), policy, - Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Success()); - } - - sutProvider.GetDependency().CreateManyAsync(default) - .ReturnsForAnyArgs(new List { data }); - - await sutProvider.Sut.CreateProjectAccessPoliciesAsync(id, request); - - await sutProvider.GetDependency().Received(1) - .CreateManyAsync(Arg.Any>()); - } - - [Theory] - [BitAutoData] - public async Task UpdateAccessPolicies_NoAccess_Throws( - SutProvider sutProvider, - Guid id, - UserProjectAccessPolicy data, - AccessPolicyUpdateRequest request) - { - sutProvider.GetDependency() - .AuthorizeAsync(Arg.Any(), data, - Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Failed()); - sutProvider.GetDependency().GetByIdAsync(id).Returns(data); - sutProvider.GetDependency().UpdateAsync(default, default, default) - .ReturnsForAnyArgs(data); - - await Assert.ThrowsAsync(() => - sutProvider.Sut.UpdateAccessPolicyAsync(id, request)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() - .UpdateAsync(Arg.Any(), Arg.Is(request.Read), Arg.Is(request.Write)); - } - - [Theory] - [BitAutoData] - public async Task UpdateAccessPolicies_Success( - SutProvider sutProvider, - Guid id, - UserProjectAccessPolicy data, - AccessPolicyUpdateRequest request) - { - sutProvider.GetDependency() - .AuthorizeAsync(Arg.Any(), data, - Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Success()); - sutProvider.GetDependency().GetByIdAsync(id).Returns(data); - sutProvider.GetDependency().UpdateAsync(default, default, default) - .ReturnsForAnyArgs(data); - - await sutProvider.Sut.UpdateAccessPolicyAsync(id, request); - - await sutProvider.GetDependency().Received(1) - .UpdateAsync(Arg.Any(), Arg.Is(request.Read), Arg.Is(request.Write)); - } - - [Theory] - [BitAutoData] - public async Task DeleteAccessPolicies_NoAccess_Throws(SutProvider sutProvider, Guid id) - { - sutProvider.GetDependency() - .AuthorizeAsync(Arg.Any(), new UserProjectAccessPolicy(), - Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Failed()); - sutProvider.GetDependency().DeleteAsync(default).ReturnsNull(); - - await Assert.ThrowsAsync(() => - sutProvider.Sut.DeleteAccessPolicyAsync(id)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() - .DeleteAsync(Arg.Any()); - } - - [Theory] - [BitAutoData] - public async Task DeleteAccessPolicies_Success(SutProvider sutProvider, Guid id) - { - sutProvider.GetDependency() - .AuthorizeAsync(Arg.Any(), new UserProjectAccessPolicy(), - Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Success()); - sutProvider.GetDependency().DeleteAsync(default).ReturnsNull(); - - await sutProvider.Sut.DeleteAccessPolicyAsync(id); - - await sutProvider.GetDependency().Received(1) - .DeleteAsync(Arg.Any()); - } - - [Theory] - [BitAutoData(PermissionType.RunAsAdmin)] - [BitAutoData(PermissionType.RunAsUserWithPermission)] - public async Task GetPeoplePotentialGrantees_ReturnsEmptyList( - PermissionType permissionType, + public async Task GetPeoplePotentialGrantees_UserWithoutPermission_ThrowsNotFound( SutProvider sutProvider, Guid id) { - SetupPermission(sutProvider, permissionType, id); - sutProvider.GetDependency().GetPeopleGranteesAsync(default, default) + sutProvider.GetDependency().AccessSecretsManager(id).Returns(false); + + await Assert.ThrowsAsync(() => sutProvider.Sut.GetPeoplePotentialGranteesAsync(id)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() + .GetPeopleGranteesAsync(id, Arg.Any()); + } + + [Theory] + [BitAutoData] + public async Task GetPeoplePotentialGrantees_HasAccessNoPotentialGrantees_ReturnsEmptyList( + SutProvider sutProvider, + Guid id) + { + sutProvider.GetDependency().AccessSecretsManager(id).Returns(true); + sutProvider.GetDependency().GetProperUserId(Arg.Any()).Returns(Guid.NewGuid()); + sutProvider.GetDependency().GetPeopleGranteesAsync(id, Arg.Any()) .ReturnsForAnyArgs(new PeopleGrantees { UserGrantees = new List(), @@ -364,37 +67,14 @@ public class AccessPoliciesControllerTests [Theory] [BitAutoData] - public async Task GetPeoplePotentialGrantees_UserWithoutPermission_Throws( - SutProvider sutProvider, - Guid id) - { - sutProvider.GetDependency().OrganizationAdmin(id).Returns(false); - sutProvider.GetDependency().AccessSecretsManager(default).ReturnsForAnyArgs(false); - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(Guid.NewGuid()); - sutProvider.GetDependency().GetPeopleGranteesAsync(default, default) - .ReturnsForAnyArgs(new PeopleGrantees - { - UserGrantees = new List(), - GroupGrantees = new List() - }); - - await Assert.ThrowsAsync(() => sutProvider.Sut.GetPeoplePotentialGranteesAsync(id)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() - .GetPeopleGranteesAsync(id, Arg.Any()); - } - - [Theory] - [BitAutoData(PermissionType.RunAsAdmin)] - [BitAutoData(PermissionType.RunAsUserWithPermission)] public async Task GetPeoplePotentialGrantees_Success( - PermissionType permissionType, SutProvider sutProvider, Guid id, GroupGrantee groupGrantee) { - SetupPermission(sutProvider, permissionType, id); - sutProvider.GetDependency().GetPeopleGranteesAsync(default, default) + sutProvider.GetDependency().AccessSecretsManager(id).Returns(true); + sutProvider.GetDependency().GetProperUserId(Arg.Any()).Returns(Guid.NewGuid()); + sutProvider.GetDependency().GetPeopleGranteesAsync(id, Arg.Any()) .ReturnsForAnyArgs(new PeopleGrantees { UserGrantees = new List(), @@ -409,34 +89,13 @@ public class AccessPoliciesControllerTests Assert.NotEmpty(result.Data); } - [Theory] - [BitAutoData(PermissionType.RunAsAdmin)] - [BitAutoData(PermissionType.RunAsUserWithPermission)] - public async Task GetServiceAccountsPotentialGrantees_ReturnsEmptyList( - PermissionType permissionType, - SutProvider sutProvider, - Guid id) - { - SetupPermission(sutProvider, permissionType, id); - var result = await sutProvider.Sut.GetServiceAccountsPotentialGranteesAsync(id); - - await sutProvider.GetDependency().Received(1) - .GetManyByOrganizationIdWriteAccessAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)), - Arg.Is(AssertHelper.AssertPropertyEqual(id)), - Arg.Any()); - - Assert.Empty(result.Data); - } - [Theory] [BitAutoData] public async Task GetServiceAccountsPotentialGranteesAsync_UserWithoutPermission_Throws( SutProvider sutProvider, Guid id) { - sutProvider.GetDependency().OrganizationAdmin(id).Returns(false); - sutProvider.GetDependency().AccessSecretsManager(default).ReturnsForAnyArgs(false); - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(Guid.NewGuid()); + sutProvider.GetDependency().AccessSecretsManager(id).Returns(false); await Assert.ThrowsAsync(() => sutProvider.Sut.GetServiceAccountsPotentialGranteesAsync(id)); @@ -445,18 +104,34 @@ public class AccessPoliciesControllerTests } [Theory] - [BitAutoData(PermissionType.RunAsAdmin)] - [BitAutoData(PermissionType.RunAsUserWithPermission)] + [BitAutoData] + public async Task GetServiceAccountsPotentialGrantees_HasAccessNoPotentialGrantees_ReturnsEmptyList( + SutProvider sutProvider, + Guid id) + { + sutProvider.GetDependency().AccessSecretsManager(id).Returns(true); + + var result = await sutProvider.Sut.GetServiceAccountsPotentialGranteesAsync(id); + + await sutProvider.GetDependency().Received(1) + .GetManyByOrganizationIdWriteAccessAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)), + Arg.Is(AssertHelper.AssertPropertyEqual(id)), + Arg.Any()); + + Assert.Empty(result.Data); + } + + [Theory] + [BitAutoData] public async Task GetServiceAccountsPotentialGranteesAsync_Success( - PermissionType permissionType, SutProvider sutProvider, Guid id, - ServiceAccount mockServiceAccount) + ServiceAccount serviceAccount) { - SetupPermission(sutProvider, permissionType, id); + sutProvider.GetDependency().AccessSecretsManager(id).Returns(true); sutProvider.GetDependency() - .GetManyByOrganizationIdWriteAccessAsync(default, default, default) - .ReturnsForAnyArgs(new List { mockServiceAccount }); + .GetManyByOrganizationIdWriteAccessAsync(Arg.Any(), Arg.Any(), Arg.Any()) + .ReturnsForAnyArgs(new List { serviceAccount }); var result = await sutProvider.Sut.GetServiceAccountsPotentialGranteesAsync(id); @@ -469,14 +144,27 @@ public class AccessPoliciesControllerTests } [Theory] - [BitAutoData(PermissionType.RunAsAdmin)] - [BitAutoData(PermissionType.RunAsUserWithPermission)] - public async Task GetProjectPotentialGrantees_ReturnsEmptyList( - PermissionType permissionType, + [BitAutoData] + public async Task GetProjectPotentialGrantees_UserWithoutPermission_Throws( SutProvider sutProvider, Guid id) { - SetupPermission(sutProvider, permissionType, id); + sutProvider.GetDependency().AccessSecretsManager(id).Returns(false); + + await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectPotentialGranteesAsync(id)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() + .GetManyByOrganizationIdWriteAccessAsync(Arg.Any(), Arg.Any(), Arg.Any()); + } + + [Theory] + [BitAutoData] + public async Task GetProjectPotentialGrantees_HasAccessNoPotentialGrantees_ReturnsEmptyList( + SutProvider sutProvider, + Guid id) + { + sutProvider.GetDependency().AccessSecretsManager(id).Returns(true); + var result = await sutProvider.Sut.GetProjectPotentialGranteesAsync(id); await sutProvider.GetDependency().Received(1) @@ -489,33 +177,15 @@ public class AccessPoliciesControllerTests [Theory] [BitAutoData] - public async Task GetProjectPotentialGrantees_UserWithoutPermission_Throws( - SutProvider sutProvider, - Guid id) - { - sutProvider.GetDependency().OrganizationAdmin(id).Returns(false); - sutProvider.GetDependency().AccessSecretsManager(default).ReturnsForAnyArgs(false); - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(Guid.NewGuid()); - - await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectPotentialGranteesAsync(id)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() - .GetManyByOrganizationIdWriteAccessAsync(Arg.Any(), Arg.Any(), Arg.Any()); - } - - [Theory] - [BitAutoData(PermissionType.RunAsAdmin)] - [BitAutoData(PermissionType.RunAsUserWithPermission)] public async Task GetProjectPotentialGrantees_Success( - PermissionType permissionType, SutProvider sutProvider, Guid id, - Project mockProject) + Project project) { - SetupPermission(sutProvider, permissionType, id); + sutProvider.GetDependency().AccessSecretsManager(id).Returns(true); sutProvider.GetDependency() .GetManyByOrganizationIdWriteAccessAsync(default, default, default) - .ReturnsForAnyArgs(new List { mockProject }); + .ReturnsForAnyArgs(new List { project }); var result = await sutProvider.Sut.GetProjectPotentialGranteesAsync(id); @@ -528,115 +198,110 @@ public class AccessPoliciesControllerTests } [Theory] - [BitAutoData(PermissionType.RunAsAdmin)] - [BitAutoData(PermissionType.RunAsUserWithPermission)] - public async Task GetProjectPeopleAccessPolicies_ReturnsEmptyList( - PermissionType permissionType, + [BitAutoData] + public async Task GetProjectPeopleAccessPolicies_ProjectDoesNotExist_ThrowsNotFound( SutProvider sutProvider, - Guid id, Project data) + Project data) { - sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); + sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsNull(); - switch (permissionType) - { - case PermissionType.RunAsAdmin: - SetupAdmin(sutProvider, data.OrganizationId); - sutProvider.GetDependency().AccessToProjectAsync(Arg.Any(), Arg.Any(), - AccessClientType.NoAccessCheck) - .Returns((true, true)); - break; - case PermissionType.RunAsUserWithPermission: - SetupUserWithPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency() - .AccessToProjectAsync(Arg.Any(), Arg.Any(), AccessClientType.User) - .Returns((true, true)); - break; - } + await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(data.Id)); - var result = await sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(id); + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() + .GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Any(), Arg.Any()); + } + + [Theory] + [BitAutoData] + public async Task GetProjectPeopleAccessPolicies_NoAccessSecretsManager_ThrowsNotFound( + SutProvider sutProvider, + Project data) + { + sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); + sutProvider.GetDependency().AccessSecretsManager(Arg.Any()) + .ReturnsForAnyArgs(false); + + await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(data.Id)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() + .GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Any(), Arg.Any()); + } + + [Theory] + [BitAutoData(true)] + [BitAutoData(false)] + public async Task GetProjectPeopleAccessPolicies_UserWithoutPermission_ThrowsNotFound( + bool canRead, + SutProvider sutProvider, + Project data) + { + sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); + sutProvider.GetDependency().AccessSecretsManager(Arg.Any()) + .ReturnsForAnyArgs(true); + sutProvider.GetDependency() + .AccessToProjectAsync(Arg.Any(), Arg.Any(), Arg.Any()) + .ReturnsForAnyArgs((canRead, false)); + + await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(data.Id)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() + .GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Any(), Arg.Any()); + } + + [Theory] + [BitAutoData] + public async Task GetProjectPeopleAccessPolicies_ServiceAccountClient_ThrowsNotFound( + SutProvider sutProvider, + Project data) + { + SetupProjectAccessPoliciesTest(sutProvider, data, AccessClientType.ServiceAccount); + + await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(data.Id)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() + .GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Any(), Arg.Any()); + } + + [Theory] + [BitAutoData(AccessClientType.NoAccessCheck)] + [BitAutoData(AccessClientType.User)] + public async Task GetProjectPeopleAccessPolicies_ReturnsEmptyList( + AccessClientType accessClientType, + SutProvider sutProvider, + Project data) + { + SetupProjectAccessPoliciesTest(sutProvider, data, accessClientType); + + var result = await sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(data.Id); await sutProvider.GetDependency().Received(1) - .GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)), Arg.Any()); + .GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data.Id)), + Arg.Any()); Assert.Empty(result.GroupAccessPolicies); Assert.Empty(result.UserAccessPolicies); } [Theory] - [BitAutoData] - public async Task GetProjectPeopleAccessPolicies_UserWithoutPermission_Throws( - SutProvider sutProvider, - Guid id, - Project data) - { - SetupUserWithoutPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); - sutProvider.GetDependency().AccessToProjectAsync(default, default, default) - .Returns((false, false)); - - await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(id)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() - .GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Any(), Arg.Any()); - } - - [Theory] - [BitAutoData] - public async Task GetProjectPeopleAccessPolicies_ProjectsExist_UserWithoutPermission_Throws( - SutProvider sutProvider, - Guid id, - Project data, - UserProjectAccessPolicy resultAccessPolicy) - { - SetupUserWithoutPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); - sutProvider.GetDependency().AccessToProjectAsync(default, default, default) - .Returns((false, false)); - - sutProvider.GetDependency().GetPeoplePoliciesByGrantedProjectIdAsync(default, default) - .ReturnsForAnyArgs(new List { resultAccessPolicy }); - - await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(id)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() - .GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Any(), Arg.Any()); - } - - [Theory] - [BitAutoData(PermissionType.RunAsAdmin)] - [BitAutoData(PermissionType.RunAsUserWithPermission)] + [BitAutoData(AccessClientType.NoAccessCheck)] + [BitAutoData(AccessClientType.User)] public async Task GetProjectPeopleAccessPolicies_Success( - PermissionType permissionType, + AccessClientType accessClientType, SutProvider sutProvider, - Guid id, Project data, UserProjectAccessPolicy resultUserPolicy, GroupProjectAccessPolicy resultGroupPolicy) { - sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); - switch (permissionType) - { - case PermissionType.RunAsAdmin: - SetupAdmin(sutProvider, data.OrganizationId); - sutProvider.GetDependency().AccessToProjectAsync(Arg.Any(), Arg.Any(), - AccessClientType.NoAccessCheck) - .Returns((true, true)); - break; - case PermissionType.RunAsUserWithPermission: - SetupUserWithPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency() - .AccessToProjectAsync(Arg.Any(), Arg.Any(), AccessClientType.User) - .Returns((true, true)); - break; - } + SetupProjectAccessPoliciesTest(sutProvider, data, accessClientType); sutProvider.GetDependency().GetPeoplePoliciesByGrantedProjectIdAsync(default, default) .ReturnsForAnyArgs(new List { resultUserPolicy, resultGroupPolicy }); - var result = await sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(id); + var result = await sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(data.Id); await sutProvider.GetDependency().Received(1) - .GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)), Arg.Any()); + .GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data.Id)), + Arg.Any()); Assert.NotEmpty(result.GroupAccessPolicies); Assert.NotEmpty(result.UserAccessPolicies); @@ -734,46 +399,13 @@ public class AccessPoliciesControllerTests } [Theory] - [BitAutoData(PermissionType.RunAsAdmin)] - [BitAutoData(PermissionType.RunAsUserWithPermission)] - public async Task GetServiceAccountPeopleAccessPoliciesAsync_ReturnsEmptyList( - PermissionType permissionType, + [BitAutoData] + public async Task GetServiceAccountPeopleAccessPoliciesAsync_NoAccessSecretsManager_ThrowsNotFound( SutProvider sutProvider, ServiceAccount data) { sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); - - switch (permissionType) - { - case PermissionType.RunAsAdmin: - SetupAdmin(sutProvider, data.OrganizationId); - break; - case PermissionType.RunAsUserWithPermission: - SetupUserWithPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency() - .UserHasWriteAccessToServiceAccount(default, default) - .ReturnsForAnyArgs(true); - break; - } - - var result = await sutProvider.Sut.GetServiceAccountPeopleAccessPoliciesAsync(data.Id); - - await sutProvider.GetDependency().Received(1) - .GetPeoplePoliciesByGrantedServiceAccountIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data.Id)), Arg.Any()); - - Assert.Empty(result.UserAccessPolicies); - Assert.Empty(result.GroupAccessPolicies); - } - - [Theory] - [BitAutoData] - public async Task GetServiceAccountPeopleAccessPoliciesAsync_UserWithoutPermission_Throws( - SutProvider sutProvider, - ServiceAccount data) - { - SetupUserWithoutPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); - sutProvider.GetDependency().UserHasWriteAccessToServiceAccount(default, default) + sutProvider.GetDependency().AccessSecretsManager(data.OrganizationId) .ReturnsForAnyArgs(false); await Assert.ThrowsAsync(() => @@ -784,35 +416,73 @@ public class AccessPoliciesControllerTests } [Theory] - [BitAutoData(PermissionType.RunAsAdmin)] - [BitAutoData(PermissionType.RunAsUserWithPermission)] + [BitAutoData(true)] + [BitAutoData(false)] + public async Task GetServiceAccountPeopleAccessPoliciesAsync_UserWithoutPermission_Throws( + bool canRead, + SutProvider sutProvider, + ServiceAccount data) + { + sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); + sutProvider.GetDependency().AccessSecretsManager(data.OrganizationId) + .ReturnsForAnyArgs(true); + sutProvider.GetDependency() + .AccessToServiceAccountAsync(Arg.Any(), Arg.Any(), Arg.Any()) + .ReturnsForAnyArgs((canRead, false)); + + await Assert.ThrowsAsync(() => + sutProvider.Sut.GetServiceAccountPeopleAccessPoliciesAsync(data.Id)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() + .GetPeoplePoliciesByGrantedServiceAccountIdAsync(Arg.Any(), Arg.Any()); + } + + [Theory] + [BitAutoData] + public async Task GetServiceAccountPeopleAccessPoliciesAsync_HasPermissionNoPolicies_ReturnsEmptyList( + SutProvider sutProvider, + ServiceAccount data) + { + sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); + sutProvider.GetDependency().AccessSecretsManager(default) + .ReturnsForAnyArgs(true); + sutProvider.GetDependency() + .AccessToServiceAccountAsync(Arg.Any(), Arg.Any(), Arg.Any()) + .ReturnsForAnyArgs((true, true)); + + var result = await sutProvider.Sut.GetServiceAccountPeopleAccessPoliciesAsync(data.Id); + + await sutProvider.GetDependency().Received(1) + .GetPeoplePoliciesByGrantedServiceAccountIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data.Id)), + Arg.Any()); + + Assert.Empty(result.UserAccessPolicies); + Assert.Empty(result.GroupAccessPolicies); + } + + [Theory] + [BitAutoData] public async Task GetServiceAccountPeopleAccessPoliciesAsync_Success( - PermissionType permissionType, SutProvider sutProvider, ServiceAccount data, UserServiceAccountAccessPolicy resultAccessPolicy) { - sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); - switch (permissionType) - { - case PermissionType.RunAsAdmin: - SetupAdmin(sutProvider, data.OrganizationId); - break; - case PermissionType.RunAsUserWithPermission: - SetupUserWithPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency() - .UserHasWriteAccessToServiceAccount(default, default) - .ReturnsForAnyArgs(true); - break; - } + sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); + sutProvider.GetDependency().AccessSecretsManager(default) + .ReturnsForAnyArgs(true); + sutProvider.GetDependency() + .AccessToServiceAccountAsync(Arg.Any(), Arg.Any(), Arg.Any()) + .ReturnsForAnyArgs((true, true)); - sutProvider.GetDependency().GetPeoplePoliciesByGrantedServiceAccountIdAsync(default, default) + sutProvider.GetDependency() + .GetPeoplePoliciesByGrantedServiceAccountIdAsync(default, default) .ReturnsForAnyArgs(new List { resultAccessPolicy }); var result = await sutProvider.Sut.GetServiceAccountPeopleAccessPoliciesAsync(data.Id); await sutProvider.GetDependency().Received(1) - .GetPeoplePoliciesByGrantedServiceAccountIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data.Id)), Arg.Any()); + .GetPeoplePoliciesByGrantedServiceAccountIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data.Id)), + Arg.Any()); Assert.Empty(result.GroupAccessPolicies); Assert.NotEmpty(result.UserAccessPolicies); @@ -904,7 +574,8 @@ public class AccessPoliciesControllerTests .AuthorizeAsync(Arg.Any(), peoplePolicies, Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Success()); - sutProvider.GetDependency().ReplaceServiceAccountPeopleAsync(peoplePolicies, Arg.Any()) + sutProvider.GetDependency() + .ReplaceServiceAccountPeopleAsync(peoplePolicies, Arg.Any()) .Returns(peoplePolicies.ToBaseAccessPolicies()); await sutProvider.Sut.PutServiceAccountPeopleAccessPoliciesAsync(data.Id, request); @@ -1099,14 +770,30 @@ public class AccessPoliciesControllerTests .GetProjectServiceAccountsAccessPoliciesAsync(Arg.Any()); } + [Theory] + [BitAutoData] + public async Task GetProjectServiceAccountsAccessPoliciesAsync_NoAccessSecretsManager_ThrowsNotFound( + SutProvider sutProvider, + Project data) + { + sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); + sutProvider.GetDependency().AccessSecretsManager(Arg.Any()).ReturnsForAnyArgs(false); + + await Assert.ThrowsAsync(() => + sutProvider.Sut.GetProjectServiceAccountsAccessPoliciesAsync(data.Id)); + + await sutProvider.GetDependency().Received(0) + .GetProjectServiceAccountsAccessPoliciesAsync(Arg.Any()); + } + [Theory] [BitAutoData] public async Task GetProjectServiceAccountsAccessPoliciesAsync_NoAccess_ThrowsNotFound( SutProvider sutProvider, Project data) { - SetupUserWithoutPermission(sutProvider, data.OrganizationId); sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); + sutProvider.GetDependency().AccessSecretsManager(default).ReturnsForAnyArgs(true); sutProvider.GetDependency().AccessToProjectAsync(default, default, default) .ReturnsForAnyArgs((false, false)); @@ -1123,11 +810,7 @@ public class AccessPoliciesControllerTests SutProvider sutProvider, Project data) { - SetupUserWithoutPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); - sutProvider.GetDependency().ClientType = ClientType.ServiceAccount; - sutProvider.GetDependency().AccessToProjectAsync(default, default, default) - .ReturnsForAnyArgs((true, true)); + SetupProjectAccessPoliciesTest(sutProvider, data, AccessClientType.ServiceAccount); await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectServiceAccountsAccessPoliciesAsync(data.Id)); @@ -1137,16 +820,15 @@ public class AccessPoliciesControllerTests } [Theory] - [BitAutoData] + [BitAutoData(AccessClientType.NoAccessCheck)] + [BitAutoData(AccessClientType.User)] public async Task GetProjectServiceAccountsAccessPoliciesAsync_HasAccessNoPolicies_ReturnsEmptyList( + AccessClientType accessClientType, SutProvider sutProvider, Project data) { - SetupUserWithoutPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); - sutProvider.GetDependency().AccessToProjectAsync(default, default, default) - .ReturnsForAnyArgs((true, true)); - + // FIX ME + SetupProjectAccessPoliciesTest(sutProvider, data, accessClientType); sutProvider.GetDependency() .GetProjectServiceAccountsAccessPoliciesAsync(Arg.Any()) @@ -1158,16 +840,15 @@ public class AccessPoliciesControllerTests } [Theory] - [BitAutoData] + [BitAutoData(AccessClientType.NoAccessCheck)] + [BitAutoData(AccessClientType.User)] public async Task GetProjectServiceAccountsAccessPoliciesAsync_HasAccess_Success( + AccessClientType accessClientType, SutProvider sutProvider, ProjectServiceAccountsAccessPolicies policies, Project data) { - SetupUserWithoutPermission(sutProvider, data.OrganizationId); - sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); - sutProvider.GetDependency().AccessToProjectAsync(default, default, default) - .ReturnsForAnyArgs((true, true)); + SetupProjectAccessPoliciesTest(sutProvider, data, accessClientType); sutProvider.GetDependency() .GetProjectServiceAccountsAccessPoliciesAsync(Arg.Any()) @@ -1250,7 +931,6 @@ public class AccessPoliciesControllerTests await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .UpdateAsync(Arg.Any()); - ; } [Theory] @@ -1273,28 +953,6 @@ public class AccessPoliciesControllerTests .UpdateAsync(Arg.Any()); } - private static AccessPoliciesCreateRequest AddRequestsOverMax(AccessPoliciesCreateRequest request) - { - var newRequests = new List(); - for (var i = 0; i < _overMax; i++) - { - newRequests.Add(new AccessPolicyRequest { GranteeId = new Guid(), Read = true, Write = true }); - } - - request.UserAccessPolicyRequests = newRequests; - return request; - } - - private static List AddRequestsOverMax(List request) - { - for (var i = 0; i < _overMax; i++) - { - request.Add(new GrantedAccessPolicyRequest { GrantedId = new Guid() }); - } - - return request; - } - private static PeopleAccessPoliciesRequestModel SetRequestToCanReadWrite(PeopleAccessPoliciesRequestModel request) { foreach (var ap in request.UserAccessPolicyRequests) @@ -1312,45 +970,8 @@ public class AccessPoliciesControllerTests return request; } - private static void SetupAdmin(SutProvider sutProvider, Guid organizationId) - { - sutProvider.GetDependency().AccessSecretsManager(default).ReturnsForAnyArgs(true); - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(Guid.NewGuid()); - sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(true); - } - - private static void SetupUserWithPermission(SutProvider sutProvider, Guid organizationId) - { - sutProvider.GetDependency().AccessSecretsManager(default).ReturnsForAnyArgs(true); - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(Guid.NewGuid()); - sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(false); - sutProvider.GetDependency().OrganizationUser(default).ReturnsForAnyArgs(true); - } - - private static void SetupUserWithoutPermission(SutProvider sutProvider, - Guid organizationId) - { - sutProvider.GetDependency().AccessSecretsManager(default).ReturnsForAnyArgs(true); - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(Guid.NewGuid()); - sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(false); - sutProvider.GetDependency().OrganizationUser(default).ReturnsForAnyArgs(true); - } - - private static void SetupPermission(SutProvider sutProvider, - PermissionType permissionType, Guid orgId) - { - switch (permissionType) - { - case PermissionType.RunAsAdmin: - SetupAdmin(sutProvider, orgId); - break; - case PermissionType.RunAsUserWithPermission: - SetupUserWithPermission(sutProvider, orgId); - break; - } - } - - private static ServiceAccountGrantedPoliciesRequestModel SetupValidRequest(ServiceAccountGrantedPoliciesRequestModel request) + private static ServiceAccountGrantedPoliciesRequestModel SetupValidRequest( + ServiceAccountGrantedPoliciesRequestModel request) { foreach (var policyRequest in request.ProjectGrantedPolicyRequests) { @@ -1360,7 +981,8 @@ public class AccessPoliciesControllerTests return request; } - private static ProjectServiceAccountsAccessPoliciesRequestModel SetupValidRequest(ProjectServiceAccountsAccessPoliciesRequestModel request) + private static ProjectServiceAccountsAccessPoliciesRequestModel SetupValidRequest( + ProjectServiceAccountsAccessPoliciesRequestModel request) { foreach (var policyRequest in request.ServiceAccountAccessPolicyRequests) { @@ -1369,4 +991,18 @@ public class AccessPoliciesControllerTests return request; } + + private static void SetupProjectAccessPoliciesTest(SutProvider sutProvider, Project data, + AccessClientType accessClientType) + { + sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); + sutProvider.GetDependency().AccessSecretsManager(Arg.Any()) + .ReturnsForAnyArgs(true); + sutProvider.GetDependency() + .AccessToProjectAsync(Arg.Any(), Arg.Any(), Arg.Any()) + .ReturnsForAnyArgs((true, true)); + sutProvider.GetDependency() + .GetAccessClientAsync(Arg.Any(), Arg.Any()) + .ReturnsForAnyArgs((accessClientType, Guid.NewGuid())); + } }