mirror of
https://github.com/bitwarden/server.git
synced 2024-12-04 14:13:28 +01:00
77f8cc58e8
* SM-1146: SM Organization Counts for Projects, Secrets, Machine Accounts * SM-1146: Project total counts * SM-1146: models object renames * SM-1146: Service Account total counts * SM-1146: Unit test coverage for counts controller * SM-1146: Counts controller simplification, UT update * SM-1146: Service Account total counts from Service Account auth user * SM-1146: Integration Tests for total counts controller * SM-1146: Explicitly denying access for Service Accounts * SM-1146: Fix broken ProjectsController integration test * SM-1146: Integration tests for counts controller * SM-1146: Explicitly denying access for Service Accounts cleanup * SM-1146: Test cleanup * SM-1146: PR review comments fix * SM-1146: People, Service Accounts positive count on write access * Update bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ProjectRepository.cs Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> --------- Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com>
213 lines
9.8 KiB
C#
213 lines
9.8 KiB
C#
#nullable enable
|
|
using System.Security.Claims;
|
|
using Bit.Api.SecretsManager.Controllers;
|
|
using Bit.Api.SecretsManager.Models.Response;
|
|
using Bit.Core.Context;
|
|
using Bit.Core.Enums;
|
|
using Bit.Core.Exceptions;
|
|
using Bit.Core.SecretsManager.Entities;
|
|
using Bit.Core.SecretsManager.Models.Data;
|
|
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 NSubstitute;
|
|
using Xunit;
|
|
|
|
namespace Bit.Api.Test.SecretsManager.Controllers;
|
|
|
|
[ControllerCustomize(typeof(CountsController))]
|
|
[SutProviderCustomize]
|
|
[ProjectCustomize]
|
|
[JsonDocumentCustomize]
|
|
public class CountsControllerTests
|
|
{
|
|
[Theory]
|
|
[BitAutoData]
|
|
public async Task GetByOrganizationAsync_NoAccess_Throws(SutProvider<CountsController> sutProvider,
|
|
Guid organizationId)
|
|
{
|
|
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(organizationId).Returns(false);
|
|
|
|
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetByOrganizationAsync(organizationId));
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData]
|
|
public async Task GetByOrganizationAsync_ServiceAccountAccess_Throws(SutProvider<CountsController> sutProvider,
|
|
Guid organizationId, Guid userId)
|
|
{
|
|
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(organizationId).Returns(true);
|
|
|
|
sutProvider.GetDependency<IAccessClientQuery>()
|
|
.GetAccessClientAsync(Arg.Any<ClaimsPrincipal>(), organizationId)
|
|
.Returns((AccessClientType.ServiceAccount, userId));
|
|
|
|
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetByOrganizationAsync(organizationId));
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData(AccessClientType.NoAccessCheck)]
|
|
[BitAutoData(AccessClientType.User)]
|
|
public async Task GetByOrganizationAsync_HasAccess_Success(AccessClientType accessClientType,
|
|
SutProvider<CountsController> sutProvider, Guid organizationId, Guid userId,
|
|
OrganizationCountsResponseModel expectedCountsResponseModel)
|
|
{
|
|
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(organizationId).Returns(true);
|
|
|
|
sutProvider.GetDependency<IAccessClientQuery>()
|
|
.GetAccessClientAsync(Arg.Any<ClaimsPrincipal>(), organizationId).Returns((accessClientType, userId));
|
|
|
|
sutProvider.GetDependency<IProjectRepository>()
|
|
.GetProjectCountByOrganizationIdAsync(organizationId, userId, accessClientType)
|
|
.Returns(expectedCountsResponseModel.Projects);
|
|
|
|
sutProvider.GetDependency<ISecretRepository>()
|
|
.GetSecretsCountByOrganizationIdAsync(organizationId, userId, accessClientType)
|
|
.Returns(expectedCountsResponseModel.Secrets);
|
|
|
|
sutProvider.GetDependency<IServiceAccountRepository>()
|
|
.GetServiceAccountCountByOrganizationIdAsync(organizationId, userId, accessClientType)
|
|
.Returns(expectedCountsResponseModel.ServiceAccounts);
|
|
|
|
var response = await sutProvider.Sut.GetByOrganizationAsync(organizationId);
|
|
|
|
Assert.Equal(expectedCountsResponseModel.Projects, response.Projects);
|
|
Assert.Equal(expectedCountsResponseModel.Secrets, response.Secrets);
|
|
Assert.Equal(expectedCountsResponseModel.ServiceAccounts, response.ServiceAccounts);
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData]
|
|
public async Task GetByProjectAsync_ProjectNotFound_Throws(SutProvider<CountsController> sutProvider,
|
|
Guid projectId)
|
|
{
|
|
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(projectId).Returns(default(Project));
|
|
|
|
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetByProjectAsync(projectId));
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData]
|
|
public async Task GetByProjectAsync_NoAccess_Throws(SutProvider<CountsController> sutProvider, Project project)
|
|
{
|
|
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(project.Id).Returns(project);
|
|
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(project.OrganizationId).Returns(false);
|
|
|
|
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetByProjectAsync(project.Id));
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData]
|
|
public async Task GetByProjectAsync_ServiceAccountAccess_Throws(SutProvider<CountsController> sutProvider,
|
|
Guid userId, Project project)
|
|
{
|
|
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(project.Id).Returns(project);
|
|
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(project.OrganizationId).Returns(true);
|
|
|
|
sutProvider.GetDependency<IAccessClientQuery>()
|
|
.GetAccessClientAsync(Arg.Any<ClaimsPrincipal>(), project.OrganizationId)
|
|
.Returns((AccessClientType.ServiceAccount, userId));
|
|
|
|
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetByProjectAsync(project.Id));
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData(AccessClientType.NoAccessCheck)]
|
|
[BitAutoData(AccessClientType.User)]
|
|
public async Task GetByProjectAsync_HasAccess_Success(AccessClientType accessClientType,
|
|
SutProvider<CountsController> sutProvider, Guid userId, Project project,
|
|
ProjectCountsResponseModel expectedProjectCountsResponseModel)
|
|
{
|
|
sutProvider.GetDependency<IProjectRepository>().GetByIdAsync(project.Id).Returns(project);
|
|
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(project.OrganizationId).Returns(true);
|
|
sutProvider.GetDependency<IAccessClientQuery>()
|
|
.GetAccessClientAsync(Arg.Any<ClaimsPrincipal>(), project.OrganizationId)
|
|
.Returns((accessClientType, userId));
|
|
|
|
sutProvider.GetDependency<IProjectRepository>()
|
|
.GetProjectCountsByIdAsync(project.Id, userId, accessClientType)
|
|
.Returns(new ProjectCounts
|
|
{
|
|
Secrets = expectedProjectCountsResponseModel.Secrets,
|
|
People = expectedProjectCountsResponseModel.People,
|
|
ServiceAccounts = expectedProjectCountsResponseModel.ServiceAccounts
|
|
});
|
|
|
|
var response = await sutProvider.Sut.GetByProjectAsync(project.Id);
|
|
|
|
Assert.Equal(expectedProjectCountsResponseModel.Secrets, response.Secrets);
|
|
Assert.Equal(expectedProjectCountsResponseModel.People, response.People);
|
|
Assert.Equal(expectedProjectCountsResponseModel.ServiceAccounts, response.ServiceAccounts);
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData]
|
|
public async Task GetByServiceAccountAsync_ServiceAccountNotFound_Throws(SutProvider<CountsController> sutProvider,
|
|
Guid serviceAccountId)
|
|
{
|
|
sutProvider.GetDependency<IServiceAccountRepository>().GetByIdAsync(serviceAccountId)
|
|
.Returns(default(ServiceAccount));
|
|
|
|
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetByServiceAccountAsync(serviceAccountId));
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData]
|
|
public async Task GetByServiceAccountAsync_NoAccess_Throws(SutProvider<CountsController> sutProvider,
|
|
ServiceAccount serviceAccount)
|
|
{
|
|
sutProvider.GetDependency<IServiceAccountRepository>().GetByIdAsync(serviceAccount.Id)
|
|
.Returns(serviceAccount);
|
|
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(serviceAccount.OrganizationId).Returns(false);
|
|
|
|
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetByServiceAccountAsync(serviceAccount.Id));
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData]
|
|
public async Task GetByServiceAccountAsync_ServiceAccountAccess_Throws(SutProvider<CountsController> sutProvider,
|
|
Guid userId, ServiceAccount serviceAccount)
|
|
{
|
|
sutProvider.GetDependency<IServiceAccountRepository>().GetByIdAsync(serviceAccount.Id).Returns(serviceAccount);
|
|
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(serviceAccount.OrganizationId).Returns(true);
|
|
|
|
sutProvider.GetDependency<IAccessClientQuery>()
|
|
.GetAccessClientAsync(Arg.Any<ClaimsPrincipal>(), serviceAccount.OrganizationId)
|
|
.Returns((AccessClientType.ServiceAccount, userId));
|
|
|
|
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetByServiceAccountAsync(serviceAccount.Id));
|
|
}
|
|
|
|
[Theory]
|
|
[BitAutoData(AccessClientType.NoAccessCheck)]
|
|
[BitAutoData(AccessClientType.User)]
|
|
public async Task GetByServiceAccountAsync_HasAccess_Success(AccessClientType accessClientType,
|
|
SutProvider<CountsController> sutProvider, Guid userId, ServiceAccount serviceAccount,
|
|
ServiceAccountCountsResponseModel expectedServiceAccountCountsResponseModel)
|
|
{
|
|
sutProvider.GetDependency<IServiceAccountRepository>().GetByIdAsync(serviceAccount.Id)
|
|
.Returns(serviceAccount);
|
|
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(serviceAccount.OrganizationId).Returns(true);
|
|
sutProvider.GetDependency<IAccessClientQuery>()
|
|
.GetAccessClientAsync(Arg.Any<ClaimsPrincipal>(), serviceAccount.OrganizationId)
|
|
.Returns((accessClientType, userId));
|
|
|
|
sutProvider.GetDependency<IServiceAccountRepository>()
|
|
.GetServiceAccountCountsByIdAsync(serviceAccount.Id, userId, accessClientType)
|
|
.Returns(new ServiceAccountCounts
|
|
{
|
|
Projects = expectedServiceAccountCountsResponseModel.Projects,
|
|
People = expectedServiceAccountCountsResponseModel.People,
|
|
AccessTokens = expectedServiceAccountCountsResponseModel.AccessTokens
|
|
});
|
|
|
|
var response = await sutProvider.Sut.GetByServiceAccountAsync(serviceAccount.Id);
|
|
|
|
Assert.Equal(expectedServiceAccountCountsResponseModel.Projects, response.Projects);
|
|
Assert.Equal(expectedServiceAccountCountsResponseModel.People, response.People);
|
|
Assert.Equal(expectedServiceAccountCountsResponseModel.AccessTokens, response.AccessTokens);
|
|
}
|
|
}
|