mirror of
https://github.com/bitwarden/server.git
synced 2025-06-30 15:42:48 -05:00
[SM-919] Add project people access policy management endpoints (#3285)
* Expose access policy discriminators * Add people policy model and auth handler * Add unit tests for authz handler * Add people policies support in repo * Add new endpoints and request/response models * Update tests
This commit is contained in:
@ -2,14 +2,12 @@
|
||||
using Bit.Api.SecretsManager.Controllers;
|
||||
using Bit.Api.SecretsManager.Models.Request;
|
||||
using Bit.Api.Test.SecretsManager.Enums;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces;
|
||||
using Bit.Core.SecretsManager.Entities;
|
||||
using Bit.Core.SecretsManager.Models.Data;
|
||||
using Bit.Core.SecretsManager.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Test.SecretsManager.AutoFixture.ProjectsFixture;
|
||||
@ -806,14 +804,17 @@ public class AccessPoliciesControllerTests
|
||||
Guid id)
|
||||
{
|
||||
SetupPermission(sutProvider, permissionType, id);
|
||||
sutProvider.GetDependency<IAccessPolicyRepository>().GetPeopleGranteesAsync(default, default)
|
||||
.ReturnsForAnyArgs(new PeopleGrantees
|
||||
{
|
||||
UserGrantees = new List<UserGrantee>(),
|
||||
GroupGrantees = new List<GroupGrantee>()
|
||||
});
|
||||
|
||||
var result = await sutProvider.Sut.GetPeoplePotentialGranteesAsync(id);
|
||||
|
||||
await sutProvider.GetDependency<IGroupRepository>().Received(1)
|
||||
.GetManyByOrganizationIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)));
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1)
|
||||
.GetManyDetailsByOrganizationAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)));
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().Received(1)
|
||||
.GetPeopleGranteesAsync(id, Arg.Any<Guid>());
|
||||
Assert.Empty(result.Data);
|
||||
}
|
||||
|
||||
@ -826,17 +827,17 @@ public class AccessPoliciesControllerTests
|
||||
sutProvider.GetDependency<ICurrentContext>().OrganizationAdmin(id).Returns(false);
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(default).ReturnsForAnyArgs(false);
|
||||
sutProvider.GetDependency<IUserService>().GetProperUserId(default).ReturnsForAnyArgs(Guid.NewGuid());
|
||||
sutProvider.GetDependency<IAccessPolicyRepository>().GetPeopleGranteesAsync(default, default)
|
||||
.ReturnsForAnyArgs(new PeopleGrantees
|
||||
{
|
||||
UserGrantees = new List<UserGrantee>(),
|
||||
GroupGrantees = new List<GroupGrantee>()
|
||||
});
|
||||
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetPeoplePotentialGranteesAsync(id));
|
||||
|
||||
await sutProvider.GetDependency<IGroupRepository>().DidNotReceiveWithAnyArgs()
|
||||
.GetManyByOrganizationIdAsync(Arg.Any<Guid>());
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationUserRepository>().DidNotReceiveWithAnyArgs()
|
||||
.GetManyDetailsByOrganizationAsync(Arg.Any<Guid>());
|
||||
|
||||
await sutProvider.GetDependency<IServiceAccountRepository>().DidNotReceiveWithAnyArgs()
|
||||
.GetManyByOrganizationIdWriteAccessAsync(Arg.Any<Guid>(), Arg.Any<Guid>(), Arg.Any<AccessClientType>());
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
|
||||
.GetPeopleGranteesAsync(id, Arg.Any<Guid>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@ -846,19 +847,20 @@ public class AccessPoliciesControllerTests
|
||||
PermissionType permissionType,
|
||||
SutProvider<AccessPoliciesController> sutProvider,
|
||||
Guid id,
|
||||
Group mockGroup)
|
||||
GroupGrantee groupGrantee)
|
||||
{
|
||||
SetupPermission(sutProvider, permissionType, id);
|
||||
sutProvider.GetDependency<IGroupRepository>().GetManyByOrganizationIdAsync(default)
|
||||
.ReturnsForAnyArgs(new List<Group> { mockGroup });
|
||||
sutProvider.GetDependency<IAccessPolicyRepository>().GetPeopleGranteesAsync(default, default)
|
||||
.ReturnsForAnyArgs(new PeopleGrantees
|
||||
{
|
||||
UserGrantees = new List<UserGrantee>(),
|
||||
GroupGrantees = new List<GroupGrantee> { groupGrantee }
|
||||
});
|
||||
|
||||
var result = await sutProvider.Sut.GetPeoplePotentialGranteesAsync(id);
|
||||
|
||||
await sutProvider.GetDependency<IGroupRepository>().Received(1)
|
||||
.GetManyByOrganizationIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)));
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1)
|
||||
.GetManyDetailsByOrganizationAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)));
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().Received(1)
|
||||
.GetPeopleGranteesAsync(id, Arg.Any<Guid>());
|
||||
|
||||
Assert.NotEmpty(result.Data);
|
||||
}
|
||||
@ -980,4 +982,195 @@ public class AccessPoliciesControllerTests
|
||||
|
||||
Assert.NotEmpty(result.Data);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PermissionType.RunAsAdmin)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission)]
|
||||
public async void GetProjectPeopleAccessPolicies_ReturnsEmptyList(
|
||||
PermissionType permissionType,
|
||||
SutProvider<AccessPoliciesController> sutProvider,
|
||||
Guid id, Project data)
|
||||
{
|
||||
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(default).ReturnsForAnyArgs(data);
|
||||
|
||||
switch (permissionType)
|
||||
{
|
||||
case PermissionType.RunAsAdmin:
|
||||
SetupAdmin(sutProvider, data.OrganizationId);
|
||||
sutProvider.GetDependency<IProjectRepository>().AccessToProjectAsync(Arg.Any<Guid>(), Arg.Any<Guid>(),
|
||||
AccessClientType.NoAccessCheck)
|
||||
.Returns((true, true));
|
||||
break;
|
||||
case PermissionType.RunAsUserWithPermission:
|
||||
SetupUserWithPermission(sutProvider, data.OrganizationId);
|
||||
sutProvider.GetDependency<IProjectRepository>()
|
||||
.AccessToProjectAsync(Arg.Any<Guid>(), Arg.Any<Guid>(), AccessClientType.User)
|
||||
.Returns((true, true));
|
||||
break;
|
||||
}
|
||||
|
||||
var result = await sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(id);
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().Received(1)
|
||||
.GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)), Arg.Any<Guid>());
|
||||
|
||||
Assert.Empty(result.GroupAccessPolicies);
|
||||
Assert.Empty(result.UserAccessPolicies);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async void GetProjectPeopleAccessPolicies_UserWithoutPermission_Throws(
|
||||
SutProvider<AccessPoliciesController> sutProvider,
|
||||
Guid id,
|
||||
Project data)
|
||||
{
|
||||
SetupUserWithoutPermission(sutProvider, data.OrganizationId);
|
||||
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(default).ReturnsForAnyArgs(data);
|
||||
sutProvider.GetDependency<IProjectRepository>().AccessToProjectAsync(default, default, default)
|
||||
.Returns((false, false));
|
||||
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(id));
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
|
||||
.GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Any<Guid>(), Arg.Any<Guid>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async void GetProjectPeopleAccessPolicies_ProjectsExist_UserWithoutPermission_Throws(
|
||||
SutProvider<AccessPoliciesController> sutProvider,
|
||||
Guid id,
|
||||
Project data,
|
||||
UserProjectAccessPolicy resultAccessPolicy)
|
||||
{
|
||||
SetupUserWithoutPermission(sutProvider, data.OrganizationId);
|
||||
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(default).ReturnsForAnyArgs(data);
|
||||
sutProvider.GetDependency<IProjectRepository>().AccessToProjectAsync(default, default, default)
|
||||
.Returns((false, false));
|
||||
|
||||
sutProvider.GetDependency<IAccessPolicyRepository>().GetPeoplePoliciesByGrantedProjectIdAsync(default, default)
|
||||
.ReturnsForAnyArgs(new List<BaseAccessPolicy> { resultAccessPolicy });
|
||||
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(id));
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
|
||||
.GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Any<Guid>(), Arg.Any<Guid>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PermissionType.RunAsAdmin)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission)]
|
||||
public async void GetProjectPeopleAccessPolicies_Success(
|
||||
PermissionType permissionType,
|
||||
SutProvider<AccessPoliciesController> sutProvider,
|
||||
Guid id,
|
||||
Project data,
|
||||
UserProjectAccessPolicy resultUserPolicy,
|
||||
GroupProjectAccessPolicy resultGroupPolicy)
|
||||
{
|
||||
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(default).ReturnsForAnyArgs(data);
|
||||
switch (permissionType)
|
||||
{
|
||||
case PermissionType.RunAsAdmin:
|
||||
SetupAdmin(sutProvider, data.OrganizationId);
|
||||
sutProvider.GetDependency<IProjectRepository>().AccessToProjectAsync(Arg.Any<Guid>(), Arg.Any<Guid>(),
|
||||
AccessClientType.NoAccessCheck)
|
||||
.Returns((true, true));
|
||||
break;
|
||||
case PermissionType.RunAsUserWithPermission:
|
||||
SetupUserWithPermission(sutProvider, data.OrganizationId);
|
||||
sutProvider.GetDependency<IProjectRepository>()
|
||||
.AccessToProjectAsync(Arg.Any<Guid>(), Arg.Any<Guid>(), AccessClientType.User)
|
||||
.Returns((true, true));
|
||||
break;
|
||||
}
|
||||
|
||||
sutProvider.GetDependency<IAccessPolicyRepository>().GetPeoplePoliciesByGrantedProjectIdAsync(default, default)
|
||||
.ReturnsForAnyArgs(new List<BaseAccessPolicy> { resultUserPolicy, resultGroupPolicy });
|
||||
|
||||
var result = await sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(id);
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().Received(1)
|
||||
.GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)), Arg.Any<Guid>());
|
||||
|
||||
Assert.NotEmpty(result.GroupAccessPolicies);
|
||||
Assert.NotEmpty(result.UserAccessPolicies);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async void PutProjectPeopleAccessPolicies_ProjectDoesNotExist_Throws(
|
||||
SutProvider<AccessPoliciesController> sutProvider,
|
||||
Guid id,
|
||||
PeopleAccessPoliciesRequestModel request)
|
||||
{
|
||||
await Assert.ThrowsAsync<NotFoundException>(() =>
|
||||
sutProvider.Sut.PutProjectPeopleAccessPoliciesAsync(id, request));
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
|
||||
.ReplaceProjectPeopleAsync(Arg.Any<ProjectPeopleAccessPolicies>(), Arg.Any<Guid>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async void PutProjectPeopleAccessPoliciesAsync_DuplicatePolicy_Throws(
|
||||
SutProvider<AccessPoliciesController> sutProvider,
|
||||
Project project,
|
||||
PeopleAccessPoliciesRequestModel request)
|
||||
{
|
||||
var dup = new AccessPolicyRequest { GranteeId = Guid.NewGuid(), Read = true, Write = true };
|
||||
request.UserAccessPolicyRequests = new[] { dup, dup };
|
||||
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(default).ReturnsForAnyArgs(project);
|
||||
|
||||
await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.PutProjectPeopleAccessPoliciesAsync(project.Id, request));
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
|
||||
.ReplaceProjectPeopleAsync(Arg.Any<ProjectPeopleAccessPolicies>(), Arg.Any<Guid>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async void PutProjectPeopleAccessPoliciesAsync_NoAccess_Throws(
|
||||
SutProvider<AccessPoliciesController> sutProvider,
|
||||
Project project,
|
||||
PeopleAccessPoliciesRequestModel request)
|
||||
{
|
||||
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(default).ReturnsForAnyArgs(project);
|
||||
var peoplePolicies = request.ToProjectPeopleAccessPolicies(project.Id, project.OrganizationId);
|
||||
sutProvider.GetDependency<IAuthorizationService>()
|
||||
.AuthorizeAsync(Arg.Any<ClaimsPrincipal>(), peoplePolicies,
|
||||
Arg.Any<IEnumerable<IAuthorizationRequirement>>()).ReturnsForAnyArgs(AuthorizationResult.Failed());
|
||||
|
||||
await Assert.ThrowsAsync<NotFoundException>(() =>
|
||||
sutProvider.Sut.PutProjectPeopleAccessPoliciesAsync(project.Id, request));
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
|
||||
.ReplaceProjectPeopleAsync(Arg.Any<ProjectPeopleAccessPolicies>(), Arg.Any<Guid>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async void PutProjectPeopleAccessPoliciesAsync_Success(
|
||||
SutProvider<AccessPoliciesController> sutProvider,
|
||||
Guid userId,
|
||||
Project project,
|
||||
PeopleAccessPoliciesRequestModel request)
|
||||
{
|
||||
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(default).ReturnsForAnyArgs(project);
|
||||
sutProvider.GetDependency<IUserService>().GetProperUserId(default).ReturnsForAnyArgs(userId);
|
||||
var peoplePolicies = request.ToProjectPeopleAccessPolicies(project.Id, project.OrganizationId);
|
||||
sutProvider.GetDependency<IAuthorizationService>()
|
||||
.AuthorizeAsync(Arg.Any<ClaimsPrincipal>(), peoplePolicies,
|
||||
Arg.Any<IEnumerable<IAuthorizationRequirement>>()).ReturnsForAnyArgs(AuthorizationResult.Success());
|
||||
|
||||
sutProvider.GetDependency<IAccessPolicyRepository>().ReplaceProjectPeopleAsync(peoplePolicies, Arg.Any<Guid>())
|
||||
.Returns(peoplePolicies.ToBaseAccessPolicies());
|
||||
|
||||
await sutProvider.Sut.PutProjectPeopleAccessPoliciesAsync(project.Id, request);
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().Received(1)
|
||||
.ReplaceProjectPeopleAsync(Arg.Any<ProjectPeopleAccessPolicies>(), Arg.Any<Guid>());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user