mirror of
https://github.com/bitwarden/server.git
synced 2025-04-04 20:50:21 -05:00
Parse claims upfront, define custom permissions
This commit is contained in:
parent
ef30805d0e
commit
72ce1f147d
@ -4,23 +4,29 @@ using System.Security.Claims;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Identity;
|
||||
using Bit.Core.Models.Data;
|
||||
|
||||
namespace Bit.Api.AdminConsole.Authorization;
|
||||
|
||||
public static class ClaimsExtensions
|
||||
{
|
||||
// Relevant claim types for organization roles, SM access, and custom permissions
|
||||
private static readonly IEnumerable<string> _relevantClaimTypes = new List<string>{
|
||||
Claims.OrganizationOwner,
|
||||
Claims.OrganizationAdmin,
|
||||
Claims.OrganizationCustom,
|
||||
Claims.OrganizationUser,
|
||||
Claims.SecretsManagerAccess,
|
||||
}.Concat(new Permissions().ClaimsMap.Select(c => c.ClaimName));
|
||||
|
||||
public static CurrentContextOrganization? GetCurrentContextOrganization(this ClaimsPrincipal user, Guid organizationId)
|
||||
{
|
||||
var claimsDict = user.Claims
|
||||
.Where(c => _relevantClaimTypes.Contains(c.Type) && Guid.TryParse(c.Value, out _))
|
||||
.GroupBy(c => c.Type)
|
||||
.ToDictionary(c => c.Key, c => c.Select(v => v));
|
||||
|
||||
var accessSecretsManager = claimsDict.TryGetValue(Claims.SecretsManagerAccess, out var value)
|
||||
? value
|
||||
.Where(s => Guid.TryParse(s.Value, out _))
|
||||
.Select(s => new Guid(s.Value))
|
||||
.ToHashSet()
|
||||
: [];
|
||||
.ToDictionary(
|
||||
c => c.Key,
|
||||
c => c.Select(v => new Guid(v.Value)));
|
||||
|
||||
var role = claimsDict.GetRoleForOrganizationId(organizationId);
|
||||
if (!role.HasValue)
|
||||
@ -33,19 +39,19 @@ public static class ClaimsExtensions
|
||||
{
|
||||
Id = organizationId,
|
||||
Type = role.Value,
|
||||
AccessSecretsManager = accessSecretsManager.Contains(organizationId),
|
||||
AccessSecretsManager = claimsDict.ContainsOrganizationId(Claims.SecretsManagerAccess, organizationId),
|
||||
Permissions = role == OrganizationUserType.Custom
|
||||
? CurrentContext.SetOrganizationPermissionsFromClaims(organizationId.ToString(), claimsDict)
|
||||
? claimsDict.GetPermissionsFromClaims(organizationId)
|
||||
: null
|
||||
};
|
||||
}
|
||||
|
||||
private static bool ContainsOrganizationId(this Dictionary<string, IEnumerable<Claim>> claimsDict, string claimType,
|
||||
private static bool ContainsOrganizationId(this Dictionary<string, IEnumerable<Guid>> claimsDict, string claimType,
|
||||
Guid organizationId)
|
||||
=> claimsDict.TryGetValue(claimType, out var claimValue) &&
|
||||
claimValue.Any(c => c.Value.EqualsGuid(organizationId));
|
||||
claimValue.Any(guid => guid == organizationId);
|
||||
|
||||
private static OrganizationUserType? GetRoleForOrganizationId(this Dictionary<string, IEnumerable<Claim>> claimsDict,
|
||||
private static OrganizationUserType? GetRoleForOrganizationId(this Dictionary<string, IEnumerable<Guid>> claimsDict,
|
||||
Guid organizationId)
|
||||
{
|
||||
if (claimsDict.ContainsOrganizationId(Claims.OrganizationOwner, organizationId))
|
||||
@ -71,6 +77,22 @@ public static class ClaimsExtensions
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool EqualsGuid(this string value, Guid guid)
|
||||
=> Guid.TryParse(value, out var parsedValue) && parsedValue == guid;
|
||||
private static Permissions GetPermissionsFromClaims(this Dictionary<string, IEnumerable<Guid>> claimsDict, Guid organizationId)
|
||||
{
|
||||
return new Permissions
|
||||
{
|
||||
AccessEventLogs = claimsDict.ContainsOrganizationId(Claims.AccessEventLogs, organizationId),
|
||||
AccessImportExport = claimsDict.ContainsOrganizationId(Claims.AccessImportExport, organizationId),
|
||||
AccessReports = claimsDict.ContainsOrganizationId(Claims.AccessReports, organizationId),
|
||||
CreateNewCollections = claimsDict.ContainsOrganizationId(Claims.CreateNewCollections, organizationId),
|
||||
EditAnyCollection = claimsDict.ContainsOrganizationId(Claims.EditAnyCollection, organizationId),
|
||||
DeleteAnyCollection = claimsDict.ContainsOrganizationId(Claims.DeleteAnyCollection, organizationId),
|
||||
ManageGroups = claimsDict.ContainsOrganizationId(Claims.ManageGroups, organizationId),
|
||||
ManagePolicies = claimsDict.ContainsOrganizationId(Claims.ManagePolicies, organizationId),
|
||||
ManageSso = claimsDict.ContainsOrganizationId(Claims.ManageSso, organizationId),
|
||||
ManageUsers = claimsDict.ContainsOrganizationId(Claims.ManageUsers, organizationId),
|
||||
ManageResetPassword = claimsDict.ContainsOrganizationId(Claims.ManageResetPassword, organizationId),
|
||||
ManageScim = claimsDict.ContainsOrganizationId(Claims.ManageScim, organizationId),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using Bit.Core.Identity;
|
||||
|
||||
namespace Bit.Core.Models.Data;
|
||||
|
||||
@ -20,17 +21,17 @@ public class Permissions
|
||||
[JsonIgnore]
|
||||
public List<(bool Permission, string ClaimName)> ClaimsMap => new()
|
||||
{
|
||||
(AccessEventLogs, "accesseventlogs"),
|
||||
(AccessImportExport, "accessimportexport"),
|
||||
(AccessReports, "accessreports"),
|
||||
(CreateNewCollections, "createnewcollections"),
|
||||
(EditAnyCollection, "editanycollection"),
|
||||
(DeleteAnyCollection, "deleteanycollection"),
|
||||
(ManageGroups, "managegroups"),
|
||||
(ManagePolicies, "managepolicies"),
|
||||
(ManageSso, "managesso"),
|
||||
(ManageUsers, "manageusers"),
|
||||
(ManageResetPassword, "manageresetpassword"),
|
||||
(ManageScim, "managescim"),
|
||||
(AccessEventLogs, Claims.AccessEventLogs),
|
||||
(AccessImportExport, Claims.AccessImportExport),
|
||||
(AccessReports, Claims.AccessReports),
|
||||
(CreateNewCollections, Claims.CreateNewCollections),
|
||||
(EditAnyCollection, Claims.EditAnyCollection),
|
||||
(DeleteAnyCollection, Claims.DeleteAnyCollection),
|
||||
(ManageGroups, Claims.ManageGroups),
|
||||
(ManagePolicies, Claims.ManagePolicies),
|
||||
(ManageSso, Claims.ManageSso),
|
||||
(ManageUsers, Claims.ManageUsers),
|
||||
(ManageResetPassword, Claims.ManageResetPassword),
|
||||
(ManageScim, Claims.ManageScim),
|
||||
};
|
||||
}
|
||||
|
@ -22,4 +22,18 @@ public static class Claims
|
||||
|
||||
// General
|
||||
public const string Type = "type";
|
||||
|
||||
// Organization permissions
|
||||
public const string AccessEventLogs = "accesseventlogs";
|
||||
public const string AccessImportExport = "accessimportexport";
|
||||
public const string AccessReports = "accessreports";
|
||||
public const string CreateNewCollections = "createnewcollections";
|
||||
public const string EditAnyCollection = "editanycollection";
|
||||
public const string DeleteAnyCollection = "deleteanycollection";
|
||||
public const string ManageGroups = "managegroups";
|
||||
public const string ManagePolicies = "managepolicies";
|
||||
public const string ManageSso = "managesso";
|
||||
public const string ManageUsers = "manageusers";
|
||||
public const string ManageResetPassword = "manageresetpassword";
|
||||
public const string ManageScim = "managescim";
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user