1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-03 00:52:49 -05:00

[PM-3797 Part 5] Add reset password keys to key rotation (#3445)

* Add reset password validator with tests

* add organization user rotation methods to repository
- move organization user TVP helper to admin console ownership

* rename account recovery to reset password

* formatting

* move registration of RotateUserKeyCommand to Core and make internal

* add admin console ValidatorServiceCollectionExtensions
This commit is contained in:
Jake Fink
2023-12-14 15:05:19 -05:00
committed by GitHub
parent da0bf77a39
commit b77ee017e3
15 changed files with 372 additions and 42 deletions

View File

@ -1,4 +1,5 @@
using Bit.Core.AdminConsole.Enums;
using Bit.Core.Auth.UserFeatures.UserKey;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
@ -42,4 +43,13 @@ public interface IOrganizationUserRepository : IRepository<OrganizationUser, Gui
Task RestoreAsync(Guid id, OrganizationUserStatusType status);
Task<IEnumerable<OrganizationUserPolicyDetails>> GetByUserIdWithPolicyDetailsAsync(Guid userId, PolicyType policyType);
Task<int> GetOccupiedSmSeatCountByOrganizationIdAsync(Guid organizationId);
/// <summary>
/// Updates encrypted data for organization users during a key rotation
/// </summary>
/// <param name="userId">The user that initiated the key rotation</param>
/// <param name="resetPasswordKeys">A list of organization users with updated reset password keys</param>
UpdateEncryptedDataForKeyRotation UpdateForKeyRotation(Guid userId,
IEnumerable<OrganizationUser> resetPasswordKeys);
}

View File

@ -13,6 +13,6 @@ public class RotateUserKeyData
public IEnumerable<Cipher> Ciphers { get; set; }
public IEnumerable<Folder> Folders { get; set; }
public IReadOnlyList<Send> Sends { get; set; }
public IEnumerable<EmergencyAccess> EmergencyAccessKeys { get; set; }
public IEnumerable<OrganizationUser> ResetPasswordKeys { get; set; }
public IEnumerable<EmergencyAccess> EmergencyAccesses { get; set; }
public IReadOnlyList<OrganizationUser> OrganizationUsers { get; set; }
}

View File

@ -17,6 +17,7 @@ public class RotateUserKeyCommand : IRotateUserKeyCommand
private readonly IFolderRepository _folderRepository;
private readonly ISendRepository _sendRepository;
private readonly IEmergencyAccessRepository _emergencyAccessRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly IPushNotificationService _pushService;
private readonly IdentityErrorDescriber _identityErrorDescriber;
@ -33,7 +34,7 @@ public class RotateUserKeyCommand : IRotateUserKeyCommand
/// <param name="errors">Provides a password mismatch error if master password hash validation fails</param>
public RotateUserKeyCommand(IUserService userService, IUserRepository userRepository,
ICipherRepository cipherRepository, IFolderRepository folderRepository, ISendRepository sendRepository,
IEmergencyAccessRepository emergencyAccessRepository,
IEmergencyAccessRepository emergencyAccessRepository, IOrganizationUserRepository organizationUserRepository,
IPushNotificationService pushService, IdentityErrorDescriber errors)
{
_userService = userService;
@ -42,6 +43,7 @@ public class RotateUserKeyCommand : IRotateUserKeyCommand
_folderRepository = folderRepository;
_sendRepository = sendRepository;
_emergencyAccessRepository = emergencyAccessRepository;
_organizationUserRepository = organizationUserRepository;
_pushService = pushService;
_identityErrorDescriber = errors;
}
@ -65,8 +67,8 @@ public class RotateUserKeyCommand : IRotateUserKeyCommand
user.SecurityStamp = Guid.NewGuid().ToString();
user.Key = model.Key;
user.PrivateKey = model.PrivateKey;
if (model.Ciphers.Any() || model.Folders.Any() || model.Sends.Any() || model.EmergencyAccessKeys.Any() ||
model.ResetPasswordKeys.Any())
if (model.Ciphers.Any() || model.Folders.Any() || model.Sends.Any() || model.EmergencyAccesses.Any() ||
model.OrganizationUsers.Any())
{
List<UpdateEncryptedDataForKeyRotation> saveEncryptedDataActions = new();
@ -85,10 +87,16 @@ public class RotateUserKeyCommand : IRotateUserKeyCommand
saveEncryptedDataActions.Add(_sendRepository.UpdateForKeyRotation(user.Id, model.Sends));
}
if (model.EmergencyAccessKeys.Any())
if (model.EmergencyAccesses.Any())
{
saveEncryptedDataActions.Add(
_emergencyAccessRepository.UpdateForKeyRotation(user.Id, model.EmergencyAccessKeys));
_emergencyAccessRepository.UpdateForKeyRotation(user.Id, model.EmergencyAccesses));
}
if (model.OrganizationUsers.Any())
{
saveEncryptedDataActions.Add(
_organizationUserRepository.UpdateForKeyRotation(user.Id, model.OrganizationUsers));
}
await _userRepository.UpdateUserKeyAndEncryptedDataAsync(user, saveEncryptedDataActions);

View File

@ -1,5 +1,7 @@

using Bit.Core.Auth.UserFeatures.UserKey;
using Bit.Core.Auth.UserFeatures.UserKey.Implementations;
using Bit.Core.Auth.UserFeatures.UserMasterPassword;
using Bit.Core.Auth.UserFeatures.UserMasterPassword.Interfaces;
using Bit.Core.Auth.UserFeatures.WebAuthnLogin;
@ -19,6 +21,11 @@ public static class UserServiceCollectionExtensions
services.AddWebAuthnLoginCommands();
}
public static void AddUserKeyCommands(this IServiceCollection services, IGlobalSettings globalSettings)
{
services.AddScoped<IRotateUserKeyCommand, RotateUserKeyCommand>();
}
private static void AddUserPasswordCommands(this IServiceCollection services)
{
services.AddScoped<ISetInitialMasterPasswordCommand, SetInitialMasterPasswordCommand>();