mirror of
https://github.com/bitwarden/server.git
synced 2025-06-30 15:42:48 -05:00
[SM-378] Enable SM on a user basis (#2590)
* Add support for giving individual users access to secrets manager
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Core.Context;
|
||||
@ -9,14 +9,16 @@ public class CurrentContentOrganization
|
||||
{
|
||||
public CurrentContentOrganization() { }
|
||||
|
||||
public CurrentContentOrganization(OrganizationUser orgUser)
|
||||
public CurrentContentOrganization(OrganizationUserOrganizationDetails orgUser)
|
||||
{
|
||||
Id = orgUser.OrganizationId;
|
||||
Type = orgUser.Type;
|
||||
Permissions = CoreHelpers.LoadClassFromJsonData<Permissions>(orgUser.Permissions);
|
||||
AccessSecretsManager = orgUser.AccessSecretsManager && orgUser.UseSecretsManager;
|
||||
}
|
||||
|
||||
public Guid Id { get; set; }
|
||||
public OrganizationUserType Type { get; set; }
|
||||
public Permissions Permissions { get; set; }
|
||||
public bool AccessSecretsManager { get; set; }
|
||||
}
|
||||
|
@ -157,6 +157,10 @@ public class CurrentContext : ICurrentContext
|
||||
|
||||
private List<CurrentContentOrganization> GetOrganizations(Dictionary<string, IEnumerable<Claim>> claimsDict, bool orgApi)
|
||||
{
|
||||
var accessSecretsManager = claimsDict.ContainsKey(Claims.SecretsManagerAccess)
|
||||
? claimsDict[Claims.SecretsManagerAccess].ToDictionary(s => s.Value, _ => true)
|
||||
: new Dictionary<string, bool>();
|
||||
|
||||
var organizations = new List<CurrentContentOrganization>();
|
||||
if (claimsDict.ContainsKey(Claims.OrganizationOwner))
|
||||
{
|
||||
@ -164,7 +168,8 @@ public class CurrentContext : ICurrentContext
|
||||
new CurrentContentOrganization
|
||||
{
|
||||
Id = new Guid(c.Value),
|
||||
Type = OrganizationUserType.Owner
|
||||
Type = OrganizationUserType.Owner,
|
||||
AccessSecretsManager = accessSecretsManager.ContainsKey(c.Value),
|
||||
}));
|
||||
}
|
||||
else if (orgApi && OrganizationId.HasValue)
|
||||
@ -172,7 +177,7 @@ public class CurrentContext : ICurrentContext
|
||||
organizations.Add(new CurrentContentOrganization
|
||||
{
|
||||
Id = OrganizationId.Value,
|
||||
Type = OrganizationUserType.Owner
|
||||
Type = OrganizationUserType.Owner,
|
||||
});
|
||||
}
|
||||
|
||||
@ -182,7 +187,8 @@ public class CurrentContext : ICurrentContext
|
||||
new CurrentContentOrganization
|
||||
{
|
||||
Id = new Guid(c.Value),
|
||||
Type = OrganizationUserType.Admin
|
||||
Type = OrganizationUserType.Admin,
|
||||
AccessSecretsManager = accessSecretsManager.ContainsKey(c.Value),
|
||||
}));
|
||||
}
|
||||
|
||||
@ -192,7 +198,8 @@ public class CurrentContext : ICurrentContext
|
||||
new CurrentContentOrganization
|
||||
{
|
||||
Id = new Guid(c.Value),
|
||||
Type = OrganizationUserType.User
|
||||
Type = OrganizationUserType.User,
|
||||
AccessSecretsManager = accessSecretsManager.ContainsKey(c.Value),
|
||||
}));
|
||||
}
|
||||
|
||||
@ -202,7 +209,8 @@ public class CurrentContext : ICurrentContext
|
||||
new CurrentContentOrganization
|
||||
{
|
||||
Id = new Guid(c.Value),
|
||||
Type = OrganizationUserType.Manager
|
||||
Type = OrganizationUserType.Manager,
|
||||
AccessSecretsManager = accessSecretsManager.ContainsKey(c.Value),
|
||||
}));
|
||||
}
|
||||
|
||||
@ -213,7 +221,8 @@ public class CurrentContext : ICurrentContext
|
||||
{
|
||||
Id = new Guid(c.Value),
|
||||
Type = OrganizationUserType.Custom,
|
||||
Permissions = SetOrganizationPermissionsFromClaims(c.Value, claimsDict)
|
||||
Permissions = SetOrganizationPermissionsFromClaims(c.Value, claimsDict),
|
||||
AccessSecretsManager = accessSecretsManager.ContainsKey(c.Value),
|
||||
}));
|
||||
}
|
||||
|
||||
@ -434,12 +443,17 @@ public class CurrentContext : ICurrentContext
|
||||
return po?.ProviderId;
|
||||
}
|
||||
|
||||
public bool AccessSecretsManager(Guid orgId)
|
||||
{
|
||||
return Organizations?.Any(o => o.Id == orgId && o.AccessSecretsManager) ?? false;
|
||||
}
|
||||
|
||||
public async Task<ICollection<CurrentContentOrganization>> OrganizationMembershipAsync(
|
||||
IOrganizationUserRepository organizationUserRepository, Guid userId)
|
||||
{
|
||||
if (Organizations == null)
|
||||
{
|
||||
var userOrgs = await organizationUserRepository.GetManyByUserAsync(userId);
|
||||
var userOrgs = await organizationUserRepository.GetManyDetailsByUserAsync(userId);
|
||||
Organizations = userOrgs.Where(ou => ou.Status == OrganizationUserStatusType.Confirmed)
|
||||
.Select(ou => new CurrentContentOrganization(ou)).ToList();
|
||||
}
|
||||
|
@ -68,4 +68,5 @@ public interface ICurrentContext
|
||||
IProviderUserRepository providerUserRepository, Guid userId);
|
||||
|
||||
Task<Guid?> ProviderIdForOrg(Guid orgId);
|
||||
bool AccessSecretsManager(Guid organizationId);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ public class OrganizationUser : ITableObject<Guid>, IExternal
|
||||
public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
|
||||
public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
|
||||
public string Permissions { get; set; }
|
||||
public bool AccessSecretsManager { get; set; }
|
||||
|
||||
public void SetNewId()
|
||||
{
|
||||
|
@ -6,6 +6,7 @@ public static class Claims
|
||||
public const string SecurityStamp = "sstamp";
|
||||
public const string Premium = "premium";
|
||||
public const string Device = "device";
|
||||
|
||||
public const string OrganizationOwner = "orgowner";
|
||||
public const string OrganizationAdmin = "orgadmin";
|
||||
public const string OrganizationManager = "orgmanager";
|
||||
@ -14,6 +15,8 @@ public static class Claims
|
||||
public const string ProviderAdmin = "providerprovideradmin";
|
||||
public const string ProviderServiceUser = "providerserviceuser";
|
||||
|
||||
public const string SecretsManagerAccess = "accesssecretsmanager";
|
||||
|
||||
// Service Account
|
||||
public const string Organization = "organization";
|
||||
|
||||
|
@ -8,6 +8,7 @@ public class OrganizationUserInvite
|
||||
public IEnumerable<string> Emails { get; set; }
|
||||
public Enums.OrganizationUserType? Type { get; set; }
|
||||
public bool AccessAll { get; set; }
|
||||
public bool AccessSecretsManager { get; set; }
|
||||
public Permissions Permissions { get; set; }
|
||||
public IEnumerable<CollectionAccessSelection> Collections { get; set; }
|
||||
public IEnumerable<Guid> Groups { get; set; }
|
||||
@ -19,6 +20,7 @@ public class OrganizationUserInvite
|
||||
Emails = requestModel.Emails;
|
||||
Type = requestModel.Type;
|
||||
AccessAll = requestModel.AccessAll;
|
||||
AccessSecretsManager = requestModel.AccessSecretsManager;
|
||||
Collections = requestModel.Collections;
|
||||
Groups = requestModel.Groups;
|
||||
Permissions = requestModel.Permissions;
|
||||
|
@ -7,6 +7,7 @@ public class OrganizationUserInviteData
|
||||
public IEnumerable<string> Emails { get; set; }
|
||||
public OrganizationUserType? Type { get; set; }
|
||||
public bool AccessAll { get; set; }
|
||||
public bool AccessSecretsManager { get; set; }
|
||||
public IEnumerable<CollectionAccessSelection> Collections { get; set; }
|
||||
public IEnumerable<Guid> Groups { get; set; }
|
||||
public Permissions Permissions { get; set; }
|
||||
|
@ -41,4 +41,5 @@ public class OrganizationUserOrganizationDetails
|
||||
public DateTime? FamilySponsorshipLastSyncDate { get; set; }
|
||||
public DateTime? FamilySponsorshipValidUntil { get; set; }
|
||||
public bool? FamilySponsorshipToDelete { get; set; }
|
||||
public bool AccessSecretsManager { get; set; }
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ public class OrganizationUserUserDetails : IExternal, ITwoFactorProvidersUser
|
||||
public OrganizationUserStatusType Status { get; set; }
|
||||
public OrganizationUserType Type { get; set; }
|
||||
public bool AccessAll { get; set; }
|
||||
public bool AccessSecretsManager { get; set; }
|
||||
public string ExternalId { get; set; }
|
||||
public string SsoExternalId { get; set; }
|
||||
public string Permissions { get; set; }
|
||||
|
@ -1241,6 +1241,7 @@ public class OrganizationService : IOrganizationService
|
||||
Type = invite.Type.Value,
|
||||
Status = OrganizationUserStatusType.Invited,
|
||||
AccessAll = invite.AccessAll,
|
||||
AccessSecretsManager = invite.AccessSecretsManager,
|
||||
ExternalId = externalId,
|
||||
CreationDate = DateTime.UtcNow,
|
||||
RevisionDate = DateTime.UtcNow,
|
||||
|
@ -692,6 +692,15 @@ public static class CoreHelpers
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Secrets Manager
|
||||
foreach (var org in group)
|
||||
{
|
||||
if (org.AccessSecretsManager)
|
||||
{
|
||||
claims.Add(new KeyValuePair<string, string>(Claims.SecretsManagerAccess, org.Id.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user