mirror of
https://github.com/bitwarden/server
synced 2025-12-22 19:23:45 +00:00
[PM-12607] Move key rotation & validators to km ownership (#4941)
* Move key rotation & validators to km ownership * Fix build errors * Fix build errors * Fix import ordering * Update validator namespace * Move key rotation data to km ownership * Fix linting * Fix namespaces * Fix namespace * Fix namespaces * Move rotateuserkeycommandtests to km ownership
This commit is contained in:
@@ -3,7 +3,7 @@ using Bit.Api.AdminConsole.Models.Response;
|
||||
using Bit.Api.Auth.Models.Request;
|
||||
using Bit.Api.Auth.Models.Request.Accounts;
|
||||
using Bit.Api.Auth.Models.Request.WebAuthn;
|
||||
using Bit.Api.Auth.Validators;
|
||||
using Bit.Api.KeyManagement.Validators;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Api.Models.Request.Accounts;
|
||||
using Bit.Api.Models.Response;
|
||||
@@ -18,7 +18,6 @@ using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
using Bit.Core.Auth.Models.Data;
|
||||
using Bit.Core.Auth.UserFeatures.TdeOffboardingPassword.Interfaces;
|
||||
using Bit.Core.Auth.UserFeatures.UserKey;
|
||||
using Bit.Core.Auth.UserFeatures.UserMasterPassword.Interfaces;
|
||||
using Bit.Core.Billing.Models;
|
||||
using Bit.Core.Billing.Services;
|
||||
@@ -26,6 +25,8 @@ using Bit.Core.Context;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.KeyManagement.Models.Data;
|
||||
using Bit.Core.KeyManagement.UserKey;
|
||||
using Bit.Core.Models.Api.Response;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.Repositories;
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
using Bit.Api.Auth.Models.Request;
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
|
||||
namespace Bit.Api.Auth.Validators;
|
||||
|
||||
public class EmergencyAccessRotationValidator : IRotationValidator<IEnumerable<EmergencyAccessWithIdRequestModel>,
|
||||
IEnumerable<EmergencyAccess>>
|
||||
{
|
||||
private readonly IEmergencyAccessRepository _emergencyAccessRepository;
|
||||
private readonly IUserService _userService;
|
||||
|
||||
public EmergencyAccessRotationValidator(IEmergencyAccessRepository emergencyAccessRepository,
|
||||
IUserService userService)
|
||||
{
|
||||
_emergencyAccessRepository = emergencyAccessRepository;
|
||||
_userService = userService;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<EmergencyAccess>> ValidateAsync(User user,
|
||||
IEnumerable<EmergencyAccessWithIdRequestModel> emergencyAccessKeys)
|
||||
{
|
||||
var result = new List<EmergencyAccess>();
|
||||
|
||||
var existing = await _emergencyAccessRepository.GetManyDetailsByGrantorIdAsync(user.Id);
|
||||
if (existing == null || existing.Count == 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
// Exclude any emergency access that has not been confirmed yet.
|
||||
existing = existing.Where(ea => ea.KeyEncrypted != null).ToList();
|
||||
|
||||
foreach (var ea in existing)
|
||||
{
|
||||
var emergencyAccess = emergencyAccessKeys.FirstOrDefault(c => c.Id == ea.Id);
|
||||
if (emergencyAccess == null)
|
||||
{
|
||||
throw new BadRequestException("All existing emergency access keys must be included in the rotation.");
|
||||
}
|
||||
|
||||
if (emergencyAccess.KeyEncrypted == null)
|
||||
{
|
||||
throw new BadRequestException("Emergency access keys cannot be set to null during rotation.");
|
||||
}
|
||||
|
||||
result.Add(emergencyAccess.ToEmergencyAccess(ea));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Exceptions;
|
||||
|
||||
namespace Bit.Api.Auth.Validators;
|
||||
|
||||
/// <summary>
|
||||
/// A consistent interface for domains to validate re-encrypted data before saved to database. Some examples are:<br/>
|
||||
/// - All available encrypted data is accounted for<br/>
|
||||
/// - All provided encrypted data belongs to the user
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Request model</typeparam>
|
||||
/// <typeparam name="R">Domain model</typeparam>
|
||||
public interface IRotationValidator<T, R>
|
||||
{
|
||||
/// <summary>
|
||||
/// Validates re-encrypted data before being saved to database.
|
||||
/// </summary>
|
||||
/// <param name="user">Request model</param>
|
||||
/// <param name="data">Domain model</param>
|
||||
/// <exception cref="BadRequestException">Throws if data fails validation</exception>
|
||||
Task<R> ValidateAsync(User user, T data);
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
using Bit.Api.Auth.Models.Request.WebAuthn;
|
||||
using Bit.Core.Auth.Models.Data;
|
||||
using Bit.Core.Auth.Repositories;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Exceptions;
|
||||
|
||||
namespace Bit.Api.Auth.Validators;
|
||||
|
||||
public class WebAuthnLoginKeyRotationValidator : IRotationValidator<IEnumerable<WebAuthnLoginRotateKeyRequestModel>, IEnumerable<WebAuthnLoginRotateKeyData>>
|
||||
{
|
||||
private readonly IWebAuthnCredentialRepository _webAuthnCredentialRepository;
|
||||
|
||||
public WebAuthnLoginKeyRotationValidator(IWebAuthnCredentialRepository webAuthnCredentialRepository)
|
||||
{
|
||||
_webAuthnCredentialRepository = webAuthnCredentialRepository;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<WebAuthnLoginRotateKeyData>> ValidateAsync(User user, IEnumerable<WebAuthnLoginRotateKeyRequestModel> keysToRotate)
|
||||
{
|
||||
// 2024-06: Remove after 3 releases, for backward compatibility
|
||||
if (keysToRotate == null)
|
||||
{
|
||||
return new List<WebAuthnLoginRotateKeyData>();
|
||||
}
|
||||
|
||||
var result = new List<WebAuthnLoginRotateKeyData>();
|
||||
var existing = await _webAuthnCredentialRepository.GetManyByUserIdAsync(user.Id);
|
||||
if (existing == null || !existing.Any())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var ea in existing)
|
||||
{
|
||||
var keyToRotate = keysToRotate.FirstOrDefault(c => c.Id == ea.Id);
|
||||
if (keyToRotate == null)
|
||||
{
|
||||
throw new BadRequestException("All existing webauthn prf keys must be included in the rotation.");
|
||||
}
|
||||
|
||||
if (keyToRotate.EncryptedUserKey == null)
|
||||
{
|
||||
throw new BadRequestException("WebAuthn prf keys must have user-key during rotation.");
|
||||
}
|
||||
if (keyToRotate.EncryptedPublicKey == null)
|
||||
{
|
||||
throw new BadRequestException("WebAuthn prf keys must have public-key during rotation.");
|
||||
}
|
||||
|
||||
result.Add(keyToRotate.ToWebAuthnRotateKeyData());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user