using Bit.Api.SecretsManager.Controllers; using Bit.Api.SecretsManager.Models.Request; using Bit.Api.Test.SecretsManager.Enums; using Bit.Core.Context; using Bit.Core.Entities; 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.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 NSubstitute; using NSubstitute.ReturnsExtensions; using Xunit; namespace Bit.Api.Test.SecretsManager.Controllers; [ControllerCustomize(typeof(AccessPoliciesController))] [SutProviderCustomize] [ProjectCustomize] [JsonDocumentCustomize] public class AccessPoliciesControllerTests { 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; } } [Theory] [BitAutoData(PermissionType.RunAsAdmin)] [BitAutoData(PermissionType.RunAsUserWithPermission)] public async void 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); break; case PermissionType.RunAsUserWithPermission: SetupUserWithPermission(sutProvider, data.OrganizationId); sutProvider.GetDependency().UserHasWriteAccessToProject(default, default) .ReturnsForAnyArgs(true); break; } var result = await sutProvider.Sut.GetProjectAccessPoliciesAsync(id); await sutProvider.GetDependency().Received(1) .GetManyByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id))); Assert.Empty(result.GroupAccessPolicies); Assert.Empty(result.UserAccessPolicies); Assert.Empty(result.ServiceAccountAccessPolicies); } [Theory] [BitAutoData] public async void GetProjectAccessPolicies_UserWithoutPermission_Throws( SutProvider sutProvider, Guid id, Project data) { SetupUserWithoutPermission(sutProvider, data.OrganizationId); sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); sutProvider.GetDependency().UserHasWriteAccessToProject(default, default) .ReturnsForAnyArgs(false); await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectAccessPoliciesAsync(id)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .GetManyByGrantedProjectIdAsync(Arg.Any()); } [Theory] [BitAutoData(PermissionType.RunAsAdmin)] [BitAutoData(PermissionType.RunAsUserWithPermission)] public async void 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); break; case PermissionType.RunAsUserWithPermission: SetupUserWithPermission(sutProvider, data.OrganizationId); sutProvider.GetDependency().UserHasWriteAccessToProject(default, default) .ReturnsForAnyArgs(true); break; } sutProvider.GetDependency().GetManyByGrantedProjectIdAsync(default) .ReturnsForAnyArgs(new List { resultAccessPolicy }); var result = await sutProvider.Sut.GetProjectAccessPoliciesAsync(id); await sutProvider.GetDependency().Received(1) .GetManyByGrantedProjectIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id))); Assert.Empty(result.GroupAccessPolicies); Assert.NotEmpty(result.UserAccessPolicies); Assert.Empty(result.ServiceAccountAccessPolicies); } [Theory] [BitAutoData] public async void GetProjectAccessPolicies_ProjectsExist_UserWithoutPermission_Throws( SutProvider sutProvider, Guid id, Project data, UserProjectAccessPolicy resultAccessPolicy) { SetupUserWithoutPermission(sutProvider, data.OrganizationId); sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); sutProvider.GetDependency().UserHasWriteAccessToProject(default, default) .ReturnsForAnyArgs(false); sutProvider.GetDependency().GetManyByGrantedProjectIdAsync(default) .ReturnsForAnyArgs(new List { resultAccessPolicy }); await Assert.ThrowsAsync(() => sutProvider.Sut.GetProjectAccessPoliciesAsync(id)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .GetManyByGrantedProjectIdAsync(Arg.Any()); } [Theory] [BitAutoData(PermissionType.RunAsAdmin)] [BitAutoData(PermissionType.RunAsUserWithPermission)] public async void GetServiceAccountAccessPolicies_ReturnsEmptyList( PermissionType permissionType, SutProvider sutProvider, Guid id, 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.GetServiceAccountAccessPoliciesAsync(id); await sutProvider.GetDependency().Received(1) .GetManyByGrantedServiceAccountIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id))); Assert.Empty(result.UserAccessPolicies); Assert.Empty(result.GroupAccessPolicies); } [Theory] [BitAutoData] public async void GetServiceAccountAccessPolicies_UserWithoutPermission_Throws( SutProvider sutProvider, Guid id, ServiceAccount data) { SetupUserWithoutPermission(sutProvider, data.OrganizationId); sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); sutProvider.GetDependency().UserHasWriteAccessToServiceAccount(default, default) .ReturnsForAnyArgs(false); await Assert.ThrowsAsync(() => sutProvider.Sut.GetServiceAccountAccessPoliciesAsync(id)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .GetManyByGrantedServiceAccountIdAsync(Arg.Any()); } [Theory] [BitAutoData(PermissionType.RunAsAdmin)] [BitAutoData(PermissionType.RunAsUserWithPermission)] public async void GetServiceAccountAccessPolicies_Success( PermissionType permissionType, SutProvider sutProvider, Guid id, 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().GetManyByGrantedServiceAccountIdAsync(default) .ReturnsForAnyArgs(new List { resultAccessPolicy }); var result = await sutProvider.Sut.GetServiceAccountAccessPoliciesAsync(id); await sutProvider.GetDependency().Received(1) .GetManyByGrantedServiceAccountIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id))); Assert.Empty(result.GroupAccessPolicies); Assert.NotEmpty(result.UserAccessPolicies); } [Theory] [BitAutoData] public async void GetServiceAccountAccessPolicies_ServiceAccountExists_UserWithoutPermission_Throws( SutProvider sutProvider, Guid id, ServiceAccount data, UserServiceAccountAccessPolicy resultAccessPolicy) { SetupUserWithoutPermission(sutProvider, data.OrganizationId); sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(data); sutProvider.GetDependency().UserHasWriteAccessToServiceAccount(default, default) .ReturnsForAnyArgs(false); sutProvider.GetDependency().GetManyByGrantedServiceAccountIdAsync(default) .ReturnsForAnyArgs(new List { resultAccessPolicy }); await Assert.ThrowsAsync(() => sutProvider.Sut.GetServiceAccountAccessPoliciesAsync(id)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .GetManyByGrantedServiceAccountIdAsync(Arg.Any()); } [Theory] [BitAutoData] public async void CreateProjectAccessPolicies_Success( SutProvider sutProvider, Guid id, UserProjectAccessPolicy data, AccessPoliciesCreateRequest request) { sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(Guid.NewGuid()); sutProvider.GetDependency().CreateForProjectAsync(default, default, default) .ReturnsForAnyArgs(new List { data }); await sutProvider.Sut.CreateProjectAccessPoliciesAsync(id, request); await sutProvider.GetDependency().Received(1) .CreateForProjectAsync(Arg.Any(), Arg.Any>(), Arg.Any()); } [Theory] [BitAutoData] public async void CreateServiceAccountAccessPolicies_Success( SutProvider sutProvider, Guid id, UserServiceAccountAccessPolicy data, AccessPoliciesCreateRequest request) { sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(Guid.NewGuid()); sutProvider.GetDependency() .CreateForServiceAccountAsync(default, default, default) .ReturnsForAnyArgs(new List { data }); await sutProvider.Sut.CreateServiceAccountAccessPoliciesAsync(id, request); await sutProvider.GetDependency().Received(1) .CreateForServiceAccountAsync(Arg.Any(), Arg.Any>(), Arg.Any()); } [Theory] [BitAutoData] public async void UpdateAccessPolicies_Success( SutProvider sutProvider, Guid id, UserProjectAccessPolicy data, AccessPolicyUpdateRequest request) { sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(Guid.NewGuid()); sutProvider.GetDependency().UpdateAsync(default, 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), Arg.Any()); } [Theory] [BitAutoData] public async void DeleteAccessPolicies_Success(SutProvider sutProvider, Guid id) { sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(Guid.NewGuid()); sutProvider.GetDependency().DeleteAsync(default, default).ReturnsNull(); await sutProvider.Sut.DeleteAccessPolicyAsync(id); await sutProvider.GetDependency().Received(1) .DeleteAsync(Arg.Any(), Arg.Any()); } [Theory] [BitAutoData(PermissionType.RunAsAdmin)] [BitAutoData(PermissionType.RunAsUserWithPermission)] public async void GetPeoplePotentialGrantees_ReturnsEmptyList( PermissionType permissionType, SutProvider sutProvider, Guid id) { SetupPermission(sutProvider, permissionType, id); var result = await sutProvider.Sut.GetPeoplePotentialGranteesAsync(id); await sutProvider.GetDependency().Received(1) .GetManyByOrganizationIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id))); await sutProvider.GetDependency().Received(1) .GetManyDetailsByOrganizationAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id))); Assert.Empty(result.Data); } [Theory] [BitAutoData] public async void 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()); await Assert.ThrowsAsync(() => sutProvider.Sut.GetPeoplePotentialGranteesAsync(id)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .GetManyByOrganizationIdAsync(Arg.Any()); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .GetManyDetailsByOrganizationAsync(Arg.Any()); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .GetManyByOrganizationIdWriteAccessAsync(Arg.Any(), Arg.Any(), Arg.Any()); } [Theory] [BitAutoData(PermissionType.RunAsAdmin)] [BitAutoData(PermissionType.RunAsUserWithPermission)] public async void GetPeoplePotentialGrantees_Success( PermissionType permissionType, SutProvider sutProvider, Guid id, Group mockGroup) { SetupPermission(sutProvider, permissionType, id); sutProvider.GetDependency().GetManyByOrganizationIdAsync(default) .ReturnsForAnyArgs(new List { mockGroup }); var result = await sutProvider.Sut.GetPeoplePotentialGranteesAsync(id); await sutProvider.GetDependency().Received(1) .GetManyByOrganizationIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id))); await sutProvider.GetDependency().Received(1) .GetManyDetailsByOrganizationAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id))); Assert.NotEmpty(result.Data); } [Theory] [BitAutoData(PermissionType.RunAsAdmin)] [BitAutoData(PermissionType.RunAsUserWithPermission)] public async void 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 void 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()); await Assert.ThrowsAsync(() => sutProvider.Sut.GetServiceAccountsPotentialGranteesAsync(id)); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .GetManyByOrganizationIdWriteAccessAsync(Arg.Any(), Arg.Any(), Arg.Any()); } [Theory] [BitAutoData(PermissionType.RunAsAdmin)] [BitAutoData(PermissionType.RunAsUserWithPermission)] public async void GetServiceAccountsPotentialGranteesAsync_Success( PermissionType permissionType, SutProvider sutProvider, Guid id, ServiceAccount mockServiceAccount) { SetupPermission(sutProvider, permissionType, id); sutProvider.GetDependency().GetManyByOrganizationIdWriteAccessAsync(default, default, default) .ReturnsForAnyArgs(new List { mockServiceAccount }); 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); } }