#nullable enable using System.Security.Claims; using Bit.Api.SecretsManager.Controllers; using Bit.Api.SecretsManager.Models.Request; using Bit.Core.Context; using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces; using Bit.Core.SecretsManager.Entities; using Bit.Core.SecretsManager.Models.Data; using Bit.Core.SecretsManager.Models.Data.AccessPolicyUpdates; using Bit.Core.SecretsManager.Queries.Interfaces; using Bit.Core.SecretsManager.Repositories; using Bit.Core.Services; using Bit.Core.Test.SecretsManager.AutoFixture.ProjectsFixture; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using Bit.Test.Common.Helpers; using Microsoft.AspNetCore.Authorization; using NSubstitute; using NSubstitute.ReturnsExtensions; using Xunit; namespace Bit.Api.Test.SecretsManager.Controllers; [ControllerCustomize(typeof(AccessPoliciesController))] [SutProviderCustomize] [ProjectCustomize] [JsonDocumentCustomize] public class AccessPoliciesControllerTests { [Theory] [BitAutoData] public async Task GetPeoplePotentialGrantees_UserWithoutPermission_ThrowsNotFound( SutProvider sutProvider, Guid id) { 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(), GroupGrantees = new List() }); var result = await sutProvider.Sut.GetPeoplePotentialGranteesAsync(id); await sutProvider.GetDependency().Received(1) .GetPeopleGranteesAsync(id, Arg.Any()); Assert.Empty(result.Data); } [Theory] [BitAutoData] public async Task GetPeoplePotentialGrantees_Success( SutProvider sutProvider, Guid id, GroupGrantee groupGrantee) { 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(), GroupGrantees = new List { groupGrantee } }); var result = await sutProvider.Sut.GetPeoplePotentialGranteesAsync(id); await sutProvider.GetDependency().Received(1) .GetPeopleGranteesAsync(id, Arg.Any()); Assert.NotEmpty(result.Data); } [Theory] [BitAutoData] public async Task GetServiceAccountsPotentialGranteesAsync_UserWithoutPermission_Throws( SutProvider sutProvider, Guid id) { sutProvider.GetDependency().AccessSecretsManager(id).Returns(false); await Assert.ThrowsAsync(() => sutProvider.Sut.GetServiceAccountsPotentialGranteesAsync(id)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .GetManyByOrganizationIdWriteAccessAsync(Arg.Any(), Arg.Any(), Arg.Any()); } [Theory] [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( SutProvider sutProvider, Guid id, ServiceAccount serviceAccount) { sutProvider.GetDependency().AccessSecretsManager(id).Returns(true); sutProvider.GetDependency() .GetManyByOrganizationIdWriteAccessAsync(Arg.Any(), Arg.Any(), Arg.Any()) .ReturnsForAnyArgs(new List { serviceAccount }); 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.NotEmpty(result.Data); } [Theory] [BitAutoData] public async Task GetProjectPotentialGrantees_UserWithoutPermission_Throws( SutProvider sutProvider, Guid 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) .GetManyByOrganizationIdWriteAccessAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)), Arg.Is(AssertHelper.AssertPropertyEqual(id)), Arg.Any()); Assert.Empty(result.Data); } [Theory] [BitAutoData] public async Task GetProjectPotentialGrantees_Success( SutProvider sutProvider, Guid id, Project project) { sutProvider.GetDependency().AccessSecretsManager(id).Returns(true); sutProvider.GetDependency() .GetManyByOrganizationIdWriteAccessAsync(default, default, default) .ReturnsForAnyArgs(new List { project }); var result = await sutProvider.Sut.GetProjectPotentialGranteesAsync(id); await sutProvider.GetDependency().Received(1) .GetManyByOrganizationIdWriteAccessAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id)), Arg.Is(AssertHelper.AssertPropertyEqual(id)), Arg.Any()); Assert.NotEmpty(result.Data); } [Theory] [BitAutoData] public async Task GetProjectPeopleAccessPolicies_ProjectDoesNotExist_ThrowsNotFound( SutProvider sutProvider, Project data) { sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsNull(); await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(data.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(data.Id)), Arg.Any()); Assert.Empty(result.GroupAccessPolicies); Assert.Empty(result.UserAccessPolicies); } [Theory] [BitAutoData(AccessClientType.NoAccessCheck)] [BitAutoData(AccessClientType.User)] public async Task GetProjectPeopleAccessPolicies_Success( AccessClientType accessClientType, SutProvider sutProvider, Project data, UserProjectAccessPolicy resultUserPolicy, GroupProjectAccessPolicy resultGroupPolicy) { SetupProjectAccessPoliciesTest(sutProvider, data, accessClientType); sutProvider.GetDependency().GetPeoplePoliciesByGrantedProjectIdAsync(default, default) .ReturnsForAnyArgs(new List { resultUserPolicy, resultGroupPolicy }); var result = await sutProvider.Sut.GetProjectPeopleAccessPoliciesAsync(data.Id); await sutProvider.GetDependency().Received(1) .GetPeoplePoliciesByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data.Id)), Arg.Any()); Assert.NotEmpty(result.GroupAccessPolicies); Assert.NotEmpty(result.UserAccessPolicies); } [Theory] [BitAutoData] public async Task PutProjectPeopleAccessPolicies_ProjectDoesNotExist_Throws( SutProvider sutProvider, Guid id, PeopleAccessPoliciesRequestModel request) { await Assert.ThrowsAsync(() => sutProvider.Sut.PutProjectPeopleAccessPoliciesAsync(id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .ReplaceProjectPeopleAsync(Arg.Any(), Arg.Any()); } [Theory] [BitAutoData] public async Task PutProjectPeopleAccessPoliciesAsync_DuplicatePolicy_Throws( SutProvider sutProvider, Project project, PeopleAccessPoliciesRequestModel request) { var dup = new AccessPolicyRequest { GranteeId = Guid.NewGuid(), Read = true, Write = true }; request.UserAccessPolicyRequests = new[] { dup, dup }; sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(project); await Assert.ThrowsAsync(() => sutProvider.Sut.PutProjectPeopleAccessPoliciesAsync(project.Id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .ReplaceProjectPeopleAsync(Arg.Any(), Arg.Any()); } [Theory] [BitAutoData] public async Task PutProjectPeopleAccessPoliciesAsync_NoAccess_Throws( SutProvider sutProvider, Project project, PeopleAccessPoliciesRequestModel request) { sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(project); var peoplePolicies = request.ToProjectPeopleAccessPolicies(project.Id, project.OrganizationId); sutProvider.GetDependency() .AuthorizeAsync(Arg.Any(), peoplePolicies, Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Failed()); await Assert.ThrowsAsync(() => sutProvider.Sut.PutProjectPeopleAccessPoliciesAsync(project.Id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .ReplaceProjectPeopleAsync(Arg.Any(), Arg.Any()); } [Theory] [BitAutoData] public async Task PutProjectPeopleAccessPoliciesAsync_Success( SutProvider sutProvider, Guid userId, Project project, PeopleAccessPoliciesRequestModel request) { sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(project); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); var peoplePolicies = request.ToProjectPeopleAccessPolicies(project.Id, project.OrganizationId); sutProvider.GetDependency() .AuthorizeAsync(Arg.Any(), peoplePolicies, Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Success()); sutProvider.GetDependency().ReplaceProjectPeopleAsync(peoplePolicies, Arg.Any()) .Returns(peoplePolicies.ToBaseAccessPolicies()); await sutProvider.Sut.PutProjectPeopleAccessPoliciesAsync(project.Id, request); await sutProvider.GetDependency().Received(1) .ReplaceProjectPeopleAsync(Arg.Any(), Arg.Any()); } [Theory] [BitAutoData] public async Task GetServiceAccountPeopleAccessPoliciesAsync_ServiceAccountDoesntExist_ThrowsNotFound( SutProvider sutProvider, ServiceAccount data) { sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsNull(); await Assert.ThrowsAsync(() => sutProvider.Sut.GetServiceAccountPeopleAccessPoliciesAsync(data.Id)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .GetPeoplePoliciesByGrantedServiceAccountIdAsync(Arg.Any(), Arg.Any()); } [Theory] [BitAutoData] public async Task GetServiceAccountPeopleAccessPoliciesAsync_NoAccessSecretsManager_ThrowsNotFound( SutProvider sutProvider, ServiceAccount data) { sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); sutProvider.GetDependency().AccessSecretsManager(data.OrganizationId) .ReturnsForAnyArgs(false); await Assert.ThrowsAsync(() => sutProvider.Sut.GetServiceAccountPeopleAccessPoliciesAsync(data.Id)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .GetPeoplePoliciesByGrantedServiceAccountIdAsync(Arg.Any(), Arg.Any()); } [Theory] [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( SutProvider sutProvider, ServiceAccount data, UserServiceAccountAccessPolicy resultAccessPolicy) { 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) .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()); Assert.Empty(result.GroupAccessPolicies); Assert.NotEmpty(result.UserAccessPolicies); } [Theory] [BitAutoData] public async Task PutServiceAccountPeopleAccessPolicies_ServiceAccountDoesNotExist_Throws( SutProvider sutProvider, ServiceAccount data, PeopleAccessPoliciesRequestModel request) { await Assert.ThrowsAsync(() => sutProvider.Sut.PutServiceAccountPeopleAccessPoliciesAsync(data.Id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .ReplaceServiceAccountPeopleAsync(Arg.Any(), Arg.Any()); } [Theory] [BitAutoData] public async Task PutServiceAccountPeopleAccessPolicies_DuplicatePolicy_Throws( SutProvider sutProvider, ServiceAccount data, PeopleAccessPoliciesRequestModel request) { var dup = new AccessPolicyRequest { GranteeId = Guid.NewGuid(), Read = true, Write = true }; request.UserAccessPolicyRequests = new[] { dup, dup }; sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); await Assert.ThrowsAsync(() => sutProvider.Sut.PutServiceAccountPeopleAccessPoliciesAsync(data.Id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .ReplaceServiceAccountPeopleAsync(Arg.Any(), Arg.Any()); } [Theory] [BitAutoData] public async Task PutServiceAccountPeopleAccessPolicies_NotCanReadWrite_Throws( SutProvider sutProvider, ServiceAccount data, PeopleAccessPoliciesRequestModel request) { request.UserAccessPolicyRequests.First().Read = false; sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); await Assert.ThrowsAsync(() => sutProvider.Sut.PutServiceAccountPeopleAccessPoliciesAsync(data.Id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .ReplaceServiceAccountPeopleAsync(Arg.Any(), Arg.Any()); } [Theory] [BitAutoData] public async Task PutServiceAccountPeopleAccessPolicies_NoAccess_Throws( SutProvider sutProvider, ServiceAccount data, PeopleAccessPoliciesRequestModel request) { request = SetRequestToCanReadWrite(request); sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); var peoplePolicies = request.ToServiceAccountPeopleAccessPolicies(data.Id, data.OrganizationId); sutProvider.GetDependency() .AuthorizeAsync(Arg.Any(), peoplePolicies, Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Failed()); await Assert.ThrowsAsync(() => sutProvider.Sut.PutServiceAccountPeopleAccessPoliciesAsync(data.Id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .ReplaceServiceAccountPeopleAsync(Arg.Any(), Arg.Any()); } [Theory] [BitAutoData] public async Task PutServiceAccountPeopleAccessPolicies_Success( SutProvider sutProvider, ServiceAccount data, Guid userId, PeopleAccessPoliciesRequestModel request) { request = SetRequestToCanReadWrite(request); sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); var peoplePolicies = request.ToServiceAccountPeopleAccessPolicies(data.Id, data.OrganizationId); sutProvider.GetDependency() .AuthorizeAsync(Arg.Any(), peoplePolicies, Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Success()); sutProvider.GetDependency() .ReplaceServiceAccountPeopleAsync(peoplePolicies, Arg.Any()) .Returns(peoplePolicies.ToBaseAccessPolicies()); await sutProvider.Sut.PutServiceAccountPeopleAccessPoliciesAsync(data.Id, request); await sutProvider.GetDependency().Received(1) .ReplaceServiceAccountPeopleAsync(Arg.Any(), Arg.Any()); } [Theory] [BitAutoData] public async Task GetServiceAccountGrantedPoliciesAsync_NoAccess_ThrowsNotFound( SutProvider sutProvider, ServiceAccount data) { sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); sutProvider.GetDependency() .AuthorizeAsync(Arg.Any(), data, Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Failed()); await Assert.ThrowsAsync(() => sutProvider.Sut.GetServiceAccountGrantedPoliciesAsync(data.Id)); await sutProvider.GetDependency().Received(0) .GetServiceAccountGrantedPoliciesPermissionDetailsAsync(Arg.Any(), Arg.Any(), Arg.Any()); } [Theory] [BitAutoData(AccessClientType.NoAccessCheck)] [BitAutoData(AccessClientType.User)] public async Task GetServiceAccountGrantedPoliciesAsync_HasAccessNoPolicies_ReturnsEmptyList( AccessClientType accessClientType, SutProvider sutProvider, Guid userId, ServiceAccount data) { sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); sutProvider.GetDependency() .AuthorizeAsync(Arg.Any(), data, Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Success()); sutProvider.GetDependency() .GetAccessClientAsync(Arg.Any(), data.OrganizationId).Returns((accessClientType, userId)); sutProvider.GetDependency() .GetServiceAccountGrantedPoliciesPermissionDetailsAsync(Arg.Any(), Arg.Any(), Arg.Any()) .ReturnsNull(); var result = await sutProvider.Sut.GetServiceAccountGrantedPoliciesAsync(data.Id); Assert.Empty(result.GrantedProjectPolicies); } [Theory] [BitAutoData(AccessClientType.NoAccessCheck)] [BitAutoData(AccessClientType.User)] public async Task GetServiceAccountGrantedPoliciesAsync_HasAccess_Success( AccessClientType accessClientType, SutProvider sutProvider, Guid userId, ServiceAccountGrantedPoliciesPermissionDetails policies, ServiceAccount data) { sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); sutProvider.GetDependency() .AuthorizeAsync(Arg.Any(), data, Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Success()); sutProvider.GetDependency() .GetAccessClientAsync(Arg.Any(), data.OrganizationId).Returns((accessClientType, userId)); sutProvider.GetDependency() .GetServiceAccountGrantedPoliciesPermissionDetailsAsync(Arg.Any(), Arg.Any(), Arg.Any()) .Returns(policies); var result = await sutProvider.Sut.GetServiceAccountGrantedPoliciesAsync(data.Id); Assert.NotEmpty(result.GrantedProjectPolicies); Assert.Equal(policies.ProjectGrantedPolicies.Count(), result.GrantedProjectPolicies.Count); } [Theory] [BitAutoData] public async Task PutServiceAccountGrantedPoliciesAsync_ServiceAccountDoesNotExist_Throws( SutProvider sutProvider, ServiceAccount data, ServiceAccountGrantedPoliciesRequestModel request) { await Assert.ThrowsAsync(() => sutProvider.Sut.PutServiceAccountGrantedPoliciesAsync(data.Id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .UpdateAsync(Arg.Any()); } [Theory] [BitAutoData] public async Task PutServiceAccountGrantedPoliciesAsync_DuplicatePolicyRequest_ThrowsBadRequestException( SutProvider sutProvider, ServiceAccount data, ServiceAccountGrantedPoliciesRequestModel request) { var dup = new GrantedAccessPolicyRequest { GrantedId = Guid.NewGuid(), Read = true, Write = true }; request.ProjectGrantedPolicyRequests = new[] { dup, dup }; sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); await Assert.ThrowsAsync(() => sutProvider.Sut.PutServiceAccountGrantedPoliciesAsync(data.Id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .UpdateAsync(Arg.Any()); } [Theory] [BitAutoData] public async Task PutServiceAccountGrantedPoliciesAsync_InvalidPolicyRequest_ThrowsBadRequestException( SutProvider sutProvider, ServiceAccount data, ServiceAccountGrantedPoliciesRequestModel request) { var policyRequest = new GrantedAccessPolicyRequest { GrantedId = Guid.NewGuid(), Read = false, Write = true }; request.ProjectGrantedPolicyRequests = new[] { policyRequest }; sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); await Assert.ThrowsAsync(() => sutProvider.Sut.PutServiceAccountGrantedPoliciesAsync(data.Id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .UpdateAsync(Arg.Any()); } [Theory] [BitAutoData] public async Task PutServiceAccountGrantedPoliciesAsync_UserHasNoAccess_ThrowsNotFoundException( SutProvider sutProvider, ServiceAccount data, ServiceAccountGrantedPoliciesRequestModel request) { request = SetupValidRequest(request); sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); sutProvider.GetDependency() .AuthorizeAsync(Arg.Any(), Arg.Any(), Arg.Any>()).Returns(AuthorizationResult.Failed()); await Assert.ThrowsAsync(() => sutProvider.Sut.PutServiceAccountGrantedPoliciesAsync(data.Id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .UpdateAsync(Arg.Any()); } [Theory] [BitAutoData] public async Task PutServiceAccountGrantedPoliciesAsync_Success( SutProvider sutProvider, ServiceAccount data, ServiceAccountGrantedPoliciesRequestModel request) { request = SetupValidRequest(request); sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); sutProvider.GetDependency() .AuthorizeAsync(Arg.Any(), Arg.Any(), Arg.Any>()).Returns(AuthorizationResult.Success()); await sutProvider.Sut.PutServiceAccountGrantedPoliciesAsync(data.Id, request); await sutProvider.GetDependency().Received(1) .UpdateAsync(Arg.Any()); } [Theory] [BitAutoData] public async Task GetProjectServiceAccountsAccessPoliciesAsync_ProjectDoesntExist_ThrowsNotFound( SutProvider sutProvider, ServiceAccount data) { sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsNull(); await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectServiceAccountsAccessPoliciesAsync(data.Id)); await sutProvider.GetDependency().Received(0) .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) { sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); sutProvider.GetDependency().AccessSecretsManager(default).ReturnsForAnyArgs(true); sutProvider.GetDependency().AccessToProjectAsync(default, default, default) .ReturnsForAnyArgs((false, false)); await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectServiceAccountsAccessPoliciesAsync(data.Id)); await sutProvider.GetDependency().Received(0) .GetProjectServiceAccountsAccessPoliciesAsync(Arg.Any()); } [Theory] [BitAutoData] public async Task GetProjectServiceAccountsAccessPoliciesAsync_ClientIsServiceAccount_ThrowsNotFound( SutProvider sutProvider, Project data) { SetupProjectAccessPoliciesTest(sutProvider, data, AccessClientType.ServiceAccount); await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectServiceAccountsAccessPoliciesAsync(data.Id)); await sutProvider.GetDependency().Received(0) .GetProjectServiceAccountsAccessPoliciesAsync(Arg.Any()); } [Theory] [BitAutoData(AccessClientType.NoAccessCheck)] [BitAutoData(AccessClientType.User)] public async Task GetProjectServiceAccountsAccessPoliciesAsync_HasAccessNoPolicies_ReturnsEmptyList( AccessClientType accessClientType, SutProvider sutProvider, Project data) { SetupProjectAccessPoliciesTest(sutProvider, data, accessClientType); sutProvider.GetDependency() .GetProjectServiceAccountsAccessPoliciesAsync(Arg.Any()) .ReturnsNullForAnyArgs(); var result = await sutProvider.Sut.GetProjectServiceAccountsAccessPoliciesAsync(data.Id); Assert.Empty(result.ServiceAccountAccessPolicies); } [Theory] [BitAutoData(AccessClientType.NoAccessCheck)] [BitAutoData(AccessClientType.User)] public async Task GetProjectServiceAccountsAccessPoliciesAsync_HasAccess_Success( AccessClientType accessClientType, SutProvider sutProvider, ProjectServiceAccountsAccessPolicies policies, Project data) { SetupProjectAccessPoliciesTest(sutProvider, data, accessClientType); sutProvider.GetDependency() .GetProjectServiceAccountsAccessPoliciesAsync(Arg.Any()) .ReturnsForAnyArgs(policies); var result = await sutProvider.Sut.GetProjectServiceAccountsAccessPoliciesAsync(data.Id); Assert.NotEmpty(result.ServiceAccountAccessPolicies); Assert.Equal(policies.ServiceAccountAccessPolicies.Count(), result.ServiceAccountAccessPolicies.Count); } [Theory] [BitAutoData] public async Task PutProjectServiceAccountsAccessPoliciesAsync_ProjectDoesNotExist_Throws( SutProvider sutProvider, Project data, ProjectServiceAccountsAccessPoliciesRequestModel request) { await Assert.ThrowsAsync(() => sutProvider.Sut.PutProjectServiceAccountsAccessPoliciesAsync(data.Id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .UpdateAsync(Arg.Any()); } [Theory] [BitAutoData] public async Task PutProjectServiceAccountsAccessPoliciesAsync_DuplicatePolicyRequest_ThrowsBadRequestException( SutProvider sutProvider, Project data, ProjectServiceAccountsAccessPoliciesRequestModel request) { var dup = new AccessPolicyRequest { GranteeId = Guid.NewGuid(), Read = true, Write = true }; request.ServiceAccountAccessPolicyRequests = [dup, dup]; sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); await Assert.ThrowsAsync(() => sutProvider.Sut.PutProjectServiceAccountsAccessPoliciesAsync(data.Id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .UpdateAsync(Arg.Any()); } [Theory] [BitAutoData] public async Task PutProjectServiceAccountsAccessPoliciesAsync_InvalidPolicyRequest_ThrowsBadRequestException( SutProvider sutProvider, Project data, ProjectServiceAccountsAccessPoliciesRequestModel request) { var policyRequest = new AccessPolicyRequest { GranteeId = Guid.NewGuid(), Read = false, Write = true }; request.ServiceAccountAccessPolicyRequests = [policyRequest]; sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); await Assert.ThrowsAsync(() => sutProvider.Sut.PutProjectServiceAccountsAccessPoliciesAsync(data.Id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .UpdateAsync(Arg.Any()); } [Theory] [BitAutoData] public async Task PutProjectServiceAccountsAccessPoliciesAsync_UserHasNoAccess_ThrowsNotFoundException( SutProvider sutProvider, Project data, ProjectServiceAccountsAccessPoliciesRequestModel request) { request = SetupValidRequest(request); sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); sutProvider.GetDependency() .AuthorizeAsync(Arg.Any(), Arg.Any(), Arg.Any>()).Returns(AuthorizationResult.Failed()); await Assert.ThrowsAsync(() => sutProvider.Sut.PutProjectServiceAccountsAccessPoliciesAsync(data.Id, request)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .UpdateAsync(Arg.Any()); } [Theory] [BitAutoData] public async Task PutProjectServiceAccountsAccessPoliciesAsync_Success( SutProvider sutProvider, Project data, ProjectServiceAccountsAccessPoliciesRequestModel request) { request = SetupValidRequest(request); sutProvider.GetDependency().GetByIdAsync(data.Id).ReturnsForAnyArgs(data); sutProvider.GetDependency() .AuthorizeAsync(Arg.Any(), Arg.Any(), Arg.Any>()).Returns(AuthorizationResult.Success()); await sutProvider.Sut.PutProjectServiceAccountsAccessPoliciesAsync(data.Id, request); await sutProvider.GetDependency().Received(1) .UpdateAsync(Arg.Any()); } [Theory] [BitAutoData] public async Task GetSecretAccessPoliciesAsync_NoAccess_ThrowsNotFound( SutProvider sutProvider, Secret data) { sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); sutProvider.GetDependency() .AuthorizeAsync(Arg.Any(), data, Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Failed()); await Assert.ThrowsAsync(() => sutProvider.Sut.GetSecretAccessPoliciesAsync(data.Id)); await sutProvider.GetDependency().Received(0) .GetSecretAccessPoliciesAsync(Arg.Any(), Arg.Any()); } [Theory] [BitAutoData] public async Task GetSecretAccessPoliciesAsync_HasAccessNoPolicies_ReturnsEmptyList( SutProvider sutProvider, Secret data) { SetupSecretAccessPoliciesTest(sutProvider, data); sutProvider.GetDependency() .GetSecretAccessPoliciesAsync(Arg.Any(), Arg.Any()) .ReturnsNull(); var result = await sutProvider.Sut.GetSecretAccessPoliciesAsync(data.Id); Assert.Empty(result.UserAccessPolicies); Assert.Empty(result.GroupAccessPolicies); Assert.Empty(result.ServiceAccountAccessPolicies); } [Theory] [BitAutoData] public async Task GetSecretAccessPoliciesAsync_HasAccess_Success( SutProvider sutProvider, SecretAccessPolicies policies, Secret data) { SetupSecretAccessPoliciesTest(sutProvider, data); sutProvider.GetDependency() .GetSecretAccessPoliciesAsync(Arg.Any(), Arg.Any()) .Returns(policies); var result = await sutProvider.Sut.GetSecretAccessPoliciesAsync(data.Id); Assert.NotEmpty(result.UserAccessPolicies); Assert.NotEmpty(result.GroupAccessPolicies); Assert.NotEmpty(result.ServiceAccountAccessPolicies); } private static PeopleAccessPoliciesRequestModel SetRequestToCanReadWrite(PeopleAccessPoliciesRequestModel request) { foreach (var ap in request.UserAccessPolicyRequests) { ap.Read = true; ap.Write = true; } foreach (var ap in request.GroupAccessPolicyRequests) { ap.Read = true; ap.Write = true; } return request; } private static ServiceAccountGrantedPoliciesRequestModel SetupValidRequest( ServiceAccountGrantedPoliciesRequestModel request) { foreach (var policyRequest in request.ProjectGrantedPolicyRequests) { policyRequest.Read = true; } return request; } private static ProjectServiceAccountsAccessPoliciesRequestModel SetupValidRequest( ProjectServiceAccountsAccessPoliciesRequestModel request) { foreach (var policyRequest in request.ServiceAccountAccessPolicyRequests) { policyRequest.Read = true; } 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())); } private static void SetupSecretAccessPoliciesTest(SutProvider sutProvider, Secret data) { sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); sutProvider.GetDependency() .AuthorizeAsync(Arg.Any(), data, Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Success()); sutProvider.GetDependency().GetProperUserId(Arg.Any()).Returns(Guid.NewGuid()); } }