mirror of
https://github.com/bitwarden/server.git
synced 2025-02-16 01:51:21 +01:00
WIP initial authz work
This commit is contained in:
parent
e16cad50b1
commit
f661f9599b
@ -0,0 +1,40 @@
|
||||
using System.Security.Claims;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Shared.Authorization;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Enums;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Bit.Core.Tools.Authorization;
|
||||
|
||||
public class VaultExportAuthorizationHandler(ICurrentContext currentContext)
|
||||
: AuthorizationHandler<VaultExportOperationRequirement, OrganizationScope>
|
||||
{
|
||||
|
||||
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
|
||||
VaultExportOperationRequirement requirement, OrganizationScope organizationScope)
|
||||
{
|
||||
var org = currentContext.GetOrganization(organizationScope);
|
||||
|
||||
var authorized = requirement switch
|
||||
{
|
||||
not null when requirement.Name == nameof(VaultExportOperations.ExportAll) =>
|
||||
CanExportAll(org),
|
||||
not null when requirement.Name == nameof(VaultExportOperations.ExportPartial) =>
|
||||
CanExportPartial(org),
|
||||
_ => false
|
||||
};
|
||||
|
||||
if (requirement is not null && authorized)
|
||||
{
|
||||
context.Succeed(requirement);
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
private bool CanExportAll(CurrentContextOrganization organization) => organization is
|
||||
{ Type: OrganizationUserType.Owner or OrganizationUserType.Admin } or
|
||||
{ Type: OrganizationUserType.Custom, Permissions.AccessImportExport: true };
|
||||
|
||||
private bool CanExportPartial(CurrentContextOrganization organization) => organization is not null;
|
||||
}
|
21
src/Core/Tools/Authorization/VaultExportOperations.cs
Normal file
21
src/Core/Tools/Authorization/VaultExportOperations.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Authorization.Infrastructure;
|
||||
|
||||
namespace Bit.Core.Tools.Authorization;
|
||||
|
||||
public class VaultExportOperationRequirement : OperationAuthorizationRequirement;
|
||||
|
||||
public static class VaultExportOperations
|
||||
{
|
||||
/// <summary>
|
||||
/// Exporting the entire organization vault.
|
||||
/// </summary>
|
||||
public static readonly VaultExportOperationRequirement ExportAll =
|
||||
new() { Name = nameof(ExportAll) };
|
||||
|
||||
/// <summary>
|
||||
/// Exporting only the organization items that the user has Can Manage permissions for
|
||||
/// </summary>
|
||||
public static readonly VaultExportOperationRequirement ExportPartial =
|
||||
new() { Name = nameof(ExportPartial) };
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
using System.Security.Claims;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Shared.Authorization;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Tools.Authorization;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Api.Test.Tools.Authorization;
|
||||
|
||||
[SutProviderCustomize]
|
||||
public class VaultExportAuthorizationHandlerTests
|
||||
{
|
||||
public static IEnumerable<object[]> CanExportEntireVault => new[]
|
||||
{
|
||||
new CurrentContextOrganization { Type = OrganizationUserType.Owner },
|
||||
new CurrentContextOrganization { Type = OrganizationUserType.Admin },
|
||||
new CurrentContextOrganization
|
||||
{
|
||||
Type = OrganizationUserType.Custom, Permissions = new Permissions { AccessImportExport = true }
|
||||
}
|
||||
}.Select(org => new []{org});
|
||||
|
||||
[Theory]
|
||||
[BitMemberAutoData(nameof(CanExportEntireVault))]
|
||||
public async Task ExportAll_PermittedRoles_Success(CurrentContextOrganization org, OrganizationScope orgScope, ClaimsPrincipal user,
|
||||
SutProvider<VaultExportAuthorizationHandler> sutProvider)
|
||||
{
|
||||
org.Id = orgScope;
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(orgScope).Returns(org);
|
||||
|
||||
var authContext = new AuthorizationHandlerContext(new[] { VaultExportOperations.ExportAll }, user, orgScope);
|
||||
await sutProvider.Sut.HandleAsync(authContext);
|
||||
|
||||
Assert.True(authContext.HasSucceeded);
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> CannotExportEntireVault => new[]
|
||||
{
|
||||
new CurrentContextOrganization { Type = OrganizationUserType.User },
|
||||
new CurrentContextOrganization
|
||||
{
|
||||
Type = OrganizationUserType.Custom, Permissions = FlipPermissions(new Permissions { AccessImportExport = true })
|
||||
}
|
||||
}.Select(org => new []{org});
|
||||
|
||||
[Theory]
|
||||
[BitMemberAutoData(nameof(CannotExportEntireVault))]
|
||||
public async Task ExportAll_NotPermitted_Failure(CurrentContextOrganization org, OrganizationScope orgScope, ClaimsPrincipal user,
|
||||
SutProvider<VaultExportAuthorizationHandler> sutProvider)
|
||||
{
|
||||
org.Id = orgScope;
|
||||
sutProvider.GetDependency<ICurrentContext>().GetOrganization(orgScope).Returns(org);
|
||||
|
||||
var authContext = new AuthorizationHandlerContext(new[] { VaultExportOperations.ExportAll }, user, orgScope);
|
||||
await sutProvider.Sut.HandleAsync(authContext);
|
||||
|
||||
Assert.False(authContext.HasSucceeded);
|
||||
}
|
||||
|
||||
private static Permissions FlipPermissions(Permissions permissions)
|
||||
{
|
||||
// Get all false boolean properties of input object
|
||||
var inputsToFlip = permissions
|
||||
.GetType()
|
||||
.GetProperties()
|
||||
.Where(p =>
|
||||
p.PropertyType == typeof(bool) &&
|
||||
(bool)p.GetValue(permissions, null)! == false)
|
||||
.Select(p => p.Name);
|
||||
|
||||
var result = new Permissions();
|
||||
|
||||
// Set these to true on the result object
|
||||
result
|
||||
.GetType()
|
||||
.GetProperties()
|
||||
.Where(p => inputsToFlip.Contains(p.Name))
|
||||
.ToList()
|
||||
.ForEach(p => p.SetValue(result, true));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user