mirror of
https://github.com/bitwarden/server
synced 2026-01-19 08:53:57 +00:00
[PM-2199] Implement userkey rotation for all TDE devices (#5446)
* Implement userkey rotation v2 * Update request models * Cleanup * Update tests * Improve test * Add tests * Fix formatting * Fix test * Remove whitespace * Fix namespace * Enable nullable on models * Fix build * Add tests and enable nullable on masterpasswordunlockdatamodel * Fix test * Remove rollback * Add tests * Make masterpassword hint optional * Update user query * Add EF test * Improve test * Cleanup * Set masterpassword hint * Remove connection close * Add tests for invalid kdf types * Update test/Core.Test/KeyManagement/UserKey/RotateUserAccountKeysCommandTests.cs Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> * Fix formatting * Update src/Api/KeyManagement/Models/Requests/RotateAccountKeysAndDataRequestModel.cs Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> * Update src/Api/Auth/Models/Request/Accounts/MasterPasswordUnlockDataModel.cs Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> * Update src/Api/Auth/Models/Request/Accounts/MasterPasswordUnlockDataModel.cs Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> * Update src/Api/KeyManagement/Models/Requests/AccountKeysRequestModel.cs Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> * Fix imports * Fix tests * Add poc for tde rotation * Improve rotation transaction safety * Add validator tests * Clean up validator * Add newline * Add devicekey unlock data to integration test * Fix tests * Fix tests * Remove null check * Remove null check * Fix IsTrusted returning wrong result * Add rollback * Cleanup * Address feedback * Further renames --------- Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Core.Auth.Models.Api.Request;
|
||||
@@ -7,6 +8,13 @@ public class OtherDeviceKeysUpdateRequestModel : DeviceKeysUpdateRequestModel
|
||||
{
|
||||
[Required]
|
||||
public Guid DeviceId { get; set; }
|
||||
|
||||
public Device ToDevice(Device existingDevice)
|
||||
{
|
||||
existingDevice.EncryptedPublicKey = EncryptedPublicKey;
|
||||
existingDevice.EncryptedUserKey = EncryptedUserKey;
|
||||
return existingDevice;
|
||||
}
|
||||
}
|
||||
|
||||
public class DeviceKeysUpdateRequestModel
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Bit.Core.Auth.Models.Data;
|
||||
using Bit.Core.Auth.Utilities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Api;
|
||||
|
||||
@@ -19,7 +18,7 @@ public class DeviceAuthRequestResponseModel : ResponseModel
|
||||
Type = deviceAuthDetails.Type,
|
||||
Identifier = deviceAuthDetails.Identifier,
|
||||
CreationDate = deviceAuthDetails.CreationDate,
|
||||
IsTrusted = deviceAuthDetails.IsTrusted()
|
||||
IsTrusted = deviceAuthDetails.IsTrusted,
|
||||
};
|
||||
|
||||
if (deviceAuthDetails.AuthRequestId != null && deviceAuthDetails.AuthRequestCreatedAt != null)
|
||||
|
||||
@@ -20,6 +20,7 @@ public class RotateUserAccountKeysData
|
||||
public IEnumerable<EmergencyAccess> EmergencyAccesses { get; set; }
|
||||
public IReadOnlyList<OrganizationUser> OrganizationUsers { get; set; }
|
||||
public IEnumerable<WebAuthnLoginRotateKeyData> WebAuthnKeys { get; set; }
|
||||
public IEnumerable<Device> DeviceKeys { get; set; }
|
||||
|
||||
// User vault data encrypted by the userkey
|
||||
public IEnumerable<Cipher> Ciphers { get; set; }
|
||||
|
||||
@@ -20,6 +20,7 @@ public class RotateUserAccountKeysCommand : IRotateUserAccountKeysCommand
|
||||
private readonly ISendRepository _sendRepository;
|
||||
private readonly IEmergencyAccessRepository _emergencyAccessRepository;
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly IDeviceRepository _deviceRepository;
|
||||
private readonly IPushNotificationService _pushService;
|
||||
private readonly IdentityErrorDescriber _identityErrorDescriber;
|
||||
private readonly IWebAuthnCredentialRepository _credentialRepository;
|
||||
@@ -42,6 +43,7 @@ public class RotateUserAccountKeysCommand : IRotateUserAccountKeysCommand
|
||||
public RotateUserAccountKeysCommand(IUserService userService, IUserRepository userRepository,
|
||||
ICipherRepository cipherRepository, IFolderRepository folderRepository, ISendRepository sendRepository,
|
||||
IEmergencyAccessRepository emergencyAccessRepository, IOrganizationUserRepository organizationUserRepository,
|
||||
IDeviceRepository deviceRepository,
|
||||
IPasswordHasher<User> passwordHasher,
|
||||
IPushNotificationService pushService, IdentityErrorDescriber errors, IWebAuthnCredentialRepository credentialRepository)
|
||||
{
|
||||
@@ -52,6 +54,7 @@ public class RotateUserAccountKeysCommand : IRotateUserAccountKeysCommand
|
||||
_sendRepository = sendRepository;
|
||||
_emergencyAccessRepository = emergencyAccessRepository;
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_deviceRepository = deviceRepository;
|
||||
_pushService = pushService;
|
||||
_identityErrorDescriber = errors;
|
||||
_credentialRepository = credentialRepository;
|
||||
@@ -127,6 +130,11 @@ public class RotateUserAccountKeysCommand : IRotateUserAccountKeysCommand
|
||||
saveEncryptedDataActions.Add(_credentialRepository.UpdateKeysForRotationAsync(user.Id, model.WebAuthnKeys));
|
||||
}
|
||||
|
||||
if (model.DeviceKeys.Any())
|
||||
{
|
||||
saveEncryptedDataActions.Add(_deviceRepository.UpdateKeysForRotationAsync(user.Id, model.DeviceKeys));
|
||||
}
|
||||
|
||||
await _userRepository.UpdateUserKeyAndEncryptedDataV2Async(user, saveEncryptedDataActions);
|
||||
await _pushService.PushLogOutAsync(user.Id);
|
||||
return IdentityResult.Success;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Bit.Core.Auth.Models.Data;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.KeyManagement.UserKey;
|
||||
|
||||
#nullable enable
|
||||
|
||||
@@ -16,4 +17,5 @@ public interface IDeviceRepository : IRepository<Device, Guid>
|
||||
// other requests.
|
||||
Task<ICollection<DeviceAuthDetails>> GetManyByUserIdWithDeviceAuth(Guid userId);
|
||||
Task ClearPushTokenAsync(Guid id);
|
||||
UpdateEncryptedDataForKeyRotation UpdateKeysForRotationAsync(Guid userId, IEnumerable<Device> devices);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user