mirror of
https://github.com/bitwarden/server.git
synced 2025-07-01 08:02:49 -05:00
[SM-473] Access Policies - Service Accounts (#2658)
* Add service account access policy endpoints * Add unit & integration tests for new endpoints * Fix formatting on response models * Cleanup unit tests
This commit is contained in:
@ -17,9 +17,127 @@ namespace Bit.Commercial.Core.Test.SecretsManager.AccessPolicies;
|
||||
[ProjectCustomize]
|
||||
public class CreateAccessPoliciesCommandTests
|
||||
{
|
||||
private static List<BaseAccessPolicy> MakeDuplicate(List<BaseAccessPolicy> data, AccessPolicyType accessPolicyType)
|
||||
{
|
||||
switch (accessPolicyType)
|
||||
{
|
||||
case AccessPolicyType.UserProjectAccessPolicy:
|
||||
{
|
||||
var mockAccessPolicy = new UserProjectAccessPolicy
|
||||
{
|
||||
OrganizationUserId = Guid.NewGuid(),
|
||||
GrantedProjectId = Guid.NewGuid(),
|
||||
};
|
||||
data.Add(mockAccessPolicy);
|
||||
|
||||
// Add a duplicate policy
|
||||
data.Add(mockAccessPolicy);
|
||||
break;
|
||||
}
|
||||
case AccessPolicyType.GroupProjectAccessPolicy:
|
||||
{
|
||||
var mockAccessPolicy = new GroupProjectAccessPolicy
|
||||
{
|
||||
GroupId = Guid.NewGuid(),
|
||||
GrantedProjectId = Guid.NewGuid(),
|
||||
};
|
||||
data.Add(mockAccessPolicy);
|
||||
|
||||
// Add a duplicate policy
|
||||
data.Add(mockAccessPolicy);
|
||||
break;
|
||||
}
|
||||
case AccessPolicyType.ServiceAccountProjectAccessPolicy:
|
||||
{
|
||||
var mockAccessPolicy = new ServiceAccountProjectAccessPolicy
|
||||
{
|
||||
ServiceAccountId = Guid.NewGuid(),
|
||||
GrantedProjectId = Guid.NewGuid(),
|
||||
};
|
||||
data.Add(mockAccessPolicy);
|
||||
|
||||
// Add a duplicate policy
|
||||
data.Add(mockAccessPolicy);
|
||||
break;
|
||||
}
|
||||
case AccessPolicyType.UserServiceAccountAccessPolicy:
|
||||
{
|
||||
var mockAccessPolicy = new UserServiceAccountAccessPolicy
|
||||
{
|
||||
OrganizationUserId = Guid.NewGuid(),
|
||||
GrantedServiceAccountId = Guid.NewGuid(),
|
||||
};
|
||||
data.Add(mockAccessPolicy);
|
||||
|
||||
// Add a duplicate policy
|
||||
data.Add(mockAccessPolicy);
|
||||
break;
|
||||
}
|
||||
case AccessPolicyType.GroupServiceAccountAccessPolicy:
|
||||
{
|
||||
var mockAccessPolicy = new GroupServiceAccountAccessPolicy
|
||||
{
|
||||
GroupId = Guid.NewGuid(),
|
||||
GrantedServiceAccountId = Guid.NewGuid(),
|
||||
};
|
||||
data.Add(mockAccessPolicy);
|
||||
|
||||
// Add a duplicate policy
|
||||
data.Add(mockAccessPolicy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private static void SetupAdmin(SutProvider<CreateAccessPoliciesCommand> sutProvider, Guid organizationId)
|
||||
{
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(organizationId).Returns(true);
|
||||
sutProvider.GetDependency<ICurrentContext>().OrganizationAdmin(organizationId).Returns(true);
|
||||
}
|
||||
|
||||
private static void SetupUser(SutProvider<CreateAccessPoliciesCommand> sutProvider, Guid organizationId)
|
||||
{
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(organizationId).Returns(true);
|
||||
sutProvider.GetDependency<ICurrentContext>().OrganizationAdmin(organizationId).Returns(false);
|
||||
}
|
||||
|
||||
private static void SetupPermission(SutProvider<CreateAccessPoliciesCommand> sutProvider,
|
||||
PermissionType permissionType, Project project, Guid userId)
|
||||
{
|
||||
switch (permissionType)
|
||||
{
|
||||
case PermissionType.RunAsAdmin:
|
||||
SetupAdmin(sutProvider, project.OrganizationId);
|
||||
break;
|
||||
case PermissionType.RunAsUserWithPermission:
|
||||
SetupUser(sutProvider, project.OrganizationId);
|
||||
sutProvider.GetDependency<IProjectRepository>().UserHasWriteAccessToProject(project.Id, userId)
|
||||
.Returns(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetupPermission(SutProvider<CreateAccessPoliciesCommand> sutProvider,
|
||||
PermissionType permissionType, ServiceAccount serviceAccount, Guid userId)
|
||||
{
|
||||
switch (permissionType)
|
||||
{
|
||||
case PermissionType.RunAsAdmin:
|
||||
SetupAdmin(sutProvider, serviceAccount.OrganizationId);
|
||||
break;
|
||||
case PermissionType.RunAsUserWithPermission:
|
||||
SetupUser(sutProvider, serviceAccount.OrganizationId);
|
||||
sutProvider.GetDependency<IServiceAccountRepository>()
|
||||
.UserHasWriteAccessToServiceAccount(serviceAccount.Id, userId).Returns(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task CreateAsync_SmNotEnabled_Throws(
|
||||
public async Task CreateForProject_SmNotEnabled_Throws(
|
||||
Guid userId,
|
||||
Project project,
|
||||
List<UserProjectAccessPolicy> userProjectAccessPolicies,
|
||||
@ -42,7 +160,7 @@ public class CreateAccessPoliciesCommandTests
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task CreateAsync_AlreadyExists_Throws_BadRequestException(
|
||||
public async Task CreateForProject_AlreadyExists_Throws_BadRequestException(
|
||||
Guid userId,
|
||||
Project project,
|
||||
List<UserProjectAccessPolicy> userProjectAccessPolicies,
|
||||
@ -55,10 +173,8 @@ public class CreateAccessPoliciesCommandTests
|
||||
data.AddRange(groupProjectAccessPolicies);
|
||||
data.AddRange(serviceAccountProjectAccessPolicies);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(Arg.Any<Guid>()).Returns(true);
|
||||
SetupAdmin(sutProvider, project.OrganizationId);
|
||||
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(project.Id).Returns(project);
|
||||
sutProvider.GetDependency<ICurrentContext>().OrganizationAdmin(project.OrganizationId).Returns(true);
|
||||
|
||||
sutProvider.GetDependency<IAccessPolicyRepository>().AccessPolicyExists(Arg.Any<BaseAccessPolicy>())
|
||||
.Returns(true);
|
||||
|
||||
@ -69,17 +185,13 @@ public class CreateAccessPoliciesCommandTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(true, false, false)]
|
||||
[BitAutoData(false, true, false)]
|
||||
[BitAutoData(true, true, false)]
|
||||
[BitAutoData(false, false, true)]
|
||||
[BitAutoData(true, false, true)]
|
||||
[BitAutoData(false, true, true)]
|
||||
[BitAutoData(true, true, true)]
|
||||
public async Task CreateAsync_NotUnique_ThrowsException(
|
||||
bool testUserPolicies,
|
||||
bool testGroupPolicies,
|
||||
bool testServiceAccountPolicies,
|
||||
[BitAutoData(AccessPolicyType.UserProjectAccessPolicy)]
|
||||
[BitAutoData(AccessPolicyType.GroupProjectAccessPolicy)]
|
||||
[BitAutoData(AccessPolicyType.ServiceAccountProjectAccessPolicy)]
|
||||
[BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy)]
|
||||
[BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy)]
|
||||
public async Task CreateForProjectAsync_NotUnique_ThrowsException(
|
||||
AccessPolicyType accessPolicyType,
|
||||
Guid userId,
|
||||
Project project,
|
||||
List<UserProjectAccessPolicy> userProjectAccessPolicies,
|
||||
@ -92,64 +204,24 @@ public class CreateAccessPoliciesCommandTests
|
||||
data.AddRange(userProjectAccessPolicies);
|
||||
data.AddRange(groupProjectAccessPolicies);
|
||||
data.AddRange(serviceAccountProjectAccessPolicies);
|
||||
data = MakeDuplicate(data, accessPolicyType);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(Arg.Any<Guid>()).Returns(true);
|
||||
SetupAdmin(sutProvider, project.OrganizationId);
|
||||
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(project.Id).Returns(project);
|
||||
sutProvider.GetDependency<ICurrentContext>().OrganizationAdmin(project.OrganizationId).Returns(true);
|
||||
|
||||
if (testUserPolicies)
|
||||
{
|
||||
var mockUserPolicy = new UserProjectAccessPolicy
|
||||
{
|
||||
OrganizationUserId = Guid.NewGuid(),
|
||||
GrantedProjectId = Guid.NewGuid(),
|
||||
};
|
||||
data.Add(mockUserPolicy);
|
||||
|
||||
// Add a duplicate policy
|
||||
data.Add(mockUserPolicy);
|
||||
}
|
||||
|
||||
if (testGroupPolicies)
|
||||
{
|
||||
var mockGroupPolicy = new GroupProjectAccessPolicy
|
||||
{
|
||||
GroupId = Guid.NewGuid(),
|
||||
GrantedProjectId = Guid.NewGuid(),
|
||||
};
|
||||
data.Add(mockGroupPolicy);
|
||||
|
||||
// Add a duplicate policy
|
||||
data.Add(mockGroupPolicy);
|
||||
}
|
||||
|
||||
if (testServiceAccountPolicies)
|
||||
{
|
||||
var mockServiceAccountPolicy = new ServiceAccountProjectAccessPolicy
|
||||
{
|
||||
ServiceAccountId = Guid.NewGuid(),
|
||||
GrantedProjectId = Guid.NewGuid(),
|
||||
};
|
||||
data.Add(mockServiceAccountPolicy);
|
||||
|
||||
// Add a duplicate policy
|
||||
data.Add(mockServiceAccountPolicy);
|
||||
}
|
||||
|
||||
|
||||
sutProvider.GetDependency<IAccessPolicyRepository>().AccessPolicyExists(Arg.Any<BaseAccessPolicy>())
|
||||
.Returns(true);
|
||||
|
||||
await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.CreateForProjectAsync(project.Id, data, userId));
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs().CreateManyAsync(default);
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
|
||||
.CreateManyAsync(Arg.Any<List<BaseAccessPolicy>>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PermissionType.RunAsAdmin)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission)]
|
||||
public async Task CreateAsync_Success(
|
||||
public async Task CreateForProject_Success(
|
||||
PermissionType permissionType,
|
||||
Guid userId,
|
||||
Project project,
|
||||
@ -163,18 +235,8 @@ public class CreateAccessPoliciesCommandTests
|
||||
data.AddRange(groupProjectAccessPolicies);
|
||||
data.AddRange(serviceAccountProjectAccessPolicies);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(Arg.Any<Guid>()).Returns(true);
|
||||
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(project.Id).Returns(project);
|
||||
|
||||
switch (permissionType)
|
||||
{
|
||||
case PermissionType.RunAsAdmin:
|
||||
sutProvider.GetDependency<ICurrentContext>().OrganizationAdmin(project.OrganizationId).Returns(true);
|
||||
break;
|
||||
case PermissionType.RunAsUserWithPermission:
|
||||
sutProvider.GetDependency<IProjectRepository>().UserHasWriteAccessToProject(project.Id, userId).Returns(true);
|
||||
break;
|
||||
}
|
||||
SetupPermission(sutProvider, permissionType, project, userId);
|
||||
|
||||
await sutProvider.Sut.CreateForProjectAsync(project.Id, data, userId);
|
||||
|
||||
@ -184,7 +246,7 @@ public class CreateAccessPoliciesCommandTests
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task CreateAsync_User_NoPermission(
|
||||
public async Task CreateForProject_UserNoPermission_ThrowsNotFound(
|
||||
Guid userId,
|
||||
Project project,
|
||||
List<UserProjectAccessPolicy> userProjectAccessPolicies,
|
||||
@ -197,13 +259,148 @@ public class CreateAccessPoliciesCommandTests
|
||||
data.AddRange(groupProjectAccessPolicies);
|
||||
data.AddRange(serviceAccountProjectAccessPolicies);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(Arg.Any<Guid>()).Returns(true);
|
||||
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(project.Id).Returns(project);
|
||||
SetupUser(sutProvider, project.OrganizationId);
|
||||
sutProvider.GetDependency<IProjectRepository>().UserHasWriteAccessToProject(project.Id, userId).Returns(false);
|
||||
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(project.Id).Returns(project);
|
||||
|
||||
await Assert.ThrowsAsync<NotFoundException>(() =>
|
||||
sutProvider.Sut.CreateForProjectAsync(project.Id, data, userId));
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs().CreateManyAsync(default);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task CreateForServiceAccount_SmNotEnabled_Throws(
|
||||
Guid userId,
|
||||
ServiceAccount serviceAccount,
|
||||
List<UserProjectAccessPolicy> userProjectAccessPolicies,
|
||||
List<GroupProjectAccessPolicy> groupProjectAccessPolicies,
|
||||
List<ServiceAccountProjectAccessPolicy> serviceAccountProjectAccessPolicies,
|
||||
SutProvider<CreateAccessPoliciesCommand> sutProvider)
|
||||
{
|
||||
var data = new List<BaseAccessPolicy>();
|
||||
data.AddRange(userProjectAccessPolicies);
|
||||
data.AddRange(groupProjectAccessPolicies);
|
||||
data.AddRange(serviceAccountProjectAccessPolicies);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(Arg.Any<Guid>()).Returns(false);
|
||||
|
||||
await Assert.ThrowsAsync<NotFoundException>(() =>
|
||||
sutProvider.Sut.CreateForServiceAccountAsync(serviceAccount.Id, data, userId));
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
|
||||
.CreateManyAsync(Arg.Any<List<BaseAccessPolicy>>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task CreateForServiceAccount_AlreadyExists_ThrowsBadRequestException(
|
||||
Guid userId,
|
||||
ServiceAccount serviceAccount,
|
||||
List<UserProjectAccessPolicy> userProjectAccessPolicies,
|
||||
List<GroupProjectAccessPolicy> groupProjectAccessPolicies,
|
||||
List<ServiceAccountProjectAccessPolicy> serviceAccountProjectAccessPolicies,
|
||||
SutProvider<CreateAccessPoliciesCommand> sutProvider)
|
||||
{
|
||||
var data = new List<BaseAccessPolicy>();
|
||||
data.AddRange(userProjectAccessPolicies);
|
||||
data.AddRange(groupProjectAccessPolicies);
|
||||
data.AddRange(serviceAccountProjectAccessPolicies);
|
||||
|
||||
SetupAdmin(sutProvider, serviceAccount.OrganizationId);
|
||||
sutProvider.GetDependency<IServiceAccountRepository>().GetByIdAsync(serviceAccount.Id).Returns(serviceAccount);
|
||||
sutProvider.GetDependency<IAccessPolicyRepository>().AccessPolicyExists(Arg.Any<BaseAccessPolicy>())
|
||||
.Returns(true);
|
||||
|
||||
await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.CreateForServiceAccountAsync(serviceAccount.Id, data, userId));
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
|
||||
.CreateManyAsync(Arg.Any<List<BaseAccessPolicy>>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(AccessPolicyType.UserProjectAccessPolicy)]
|
||||
[BitAutoData(AccessPolicyType.GroupProjectAccessPolicy)]
|
||||
[BitAutoData(AccessPolicyType.ServiceAccountProjectAccessPolicy)]
|
||||
[BitAutoData(AccessPolicyType.UserServiceAccountAccessPolicy)]
|
||||
[BitAutoData(AccessPolicyType.GroupServiceAccountAccessPolicy)]
|
||||
public async Task CreateForServiceAccount_NotUnique_Throws(
|
||||
AccessPolicyType accessPolicyType,
|
||||
Guid userId,
|
||||
ServiceAccount serviceAccount,
|
||||
List<UserProjectAccessPolicy> userProjectAccessPolicies,
|
||||
List<GroupProjectAccessPolicy> groupProjectAccessPolicies,
|
||||
List<ServiceAccountProjectAccessPolicy> serviceAccountProjectAccessPolicies,
|
||||
SutProvider<CreateAccessPoliciesCommand> sutProvider
|
||||
)
|
||||
{
|
||||
var data = new List<BaseAccessPolicy>();
|
||||
data.AddRange(userProjectAccessPolicies);
|
||||
data.AddRange(groupProjectAccessPolicies);
|
||||
data.AddRange(serviceAccountProjectAccessPolicies);
|
||||
data = MakeDuplicate(data, accessPolicyType);
|
||||
|
||||
SetupAdmin(sutProvider, serviceAccount.OrganizationId);
|
||||
sutProvider.GetDependency<IServiceAccountRepository>().GetByIdAsync(serviceAccount.Id).Returns(serviceAccount);
|
||||
sutProvider.GetDependency<IAccessPolicyRepository>().AccessPolicyExists(Arg.Any<BaseAccessPolicy>())
|
||||
.Returns(true);
|
||||
|
||||
await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.CreateForServiceAccountAsync(serviceAccount.Id, data, userId));
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
|
||||
.CreateManyAsync(Arg.Any<List<BaseAccessPolicy>>());
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PermissionType.RunAsAdmin)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission)]
|
||||
public async Task CreateForServiceAccount_Success(
|
||||
PermissionType permissionType,
|
||||
Guid userId,
|
||||
ServiceAccount serviceAccount,
|
||||
List<UserServiceAccountAccessPolicy> userServiceAccountAccessPolicies,
|
||||
List<GroupServiceAccountAccessPolicy> groupServiceAccountAccessPolicies,
|
||||
SutProvider<CreateAccessPoliciesCommand> sutProvider)
|
||||
{
|
||||
var data = new List<BaseAccessPolicy>();
|
||||
data.AddRange(userServiceAccountAccessPolicies);
|
||||
data.AddRange(groupServiceAccountAccessPolicies);
|
||||
|
||||
sutProvider.GetDependency<IServiceAccountRepository>().GetByIdAsync(serviceAccount.Id).Returns(serviceAccount);
|
||||
SetupPermission(sutProvider, permissionType, serviceAccount, userId);
|
||||
|
||||
await sutProvider.Sut.CreateForServiceAccountAsync(serviceAccount.Id, data, userId);
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().Received(1)
|
||||
.CreateManyAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task CreateForServiceAccount_UserWithoutPermission_ThrowsNotFound(
|
||||
Guid userId,
|
||||
ServiceAccount serviceAccount,
|
||||
List<UserServiceAccountAccessPolicy> userServiceAccountAccessPolicies,
|
||||
List<GroupServiceAccountAccessPolicy> groupServiceAccountAccessPolicies,
|
||||
SutProvider<CreateAccessPoliciesCommand> sutProvider)
|
||||
{
|
||||
var data = new List<BaseAccessPolicy>();
|
||||
data.AddRange(userServiceAccountAccessPolicies);
|
||||
data.AddRange(groupServiceAccountAccessPolicies);
|
||||
|
||||
SetupUser(sutProvider, serviceAccount.OrganizationId);
|
||||
sutProvider.GetDependency<IServiceAccountRepository>().GetByIdAsync(serviceAccount.Id).Returns(serviceAccount);
|
||||
sutProvider.GetDependency<IServiceAccountRepository>()
|
||||
.UserHasWriteAccessToServiceAccount(serviceAccount.Id, userId).Returns(false);
|
||||
|
||||
await Assert.ThrowsAsync<NotFoundException>(() =>
|
||||
sutProvider.Sut.CreateForServiceAccountAsync(serviceAccount.Id, data, userId));
|
||||
|
||||
await sutProvider.GetDependency<IAccessPolicyRepository>().DidNotReceiveWithAnyArgs()
|
||||
.CreateManyAsync(Arg.Any<List<BaseAccessPolicy>>());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user