diff --git a/src/Api/Auth/Controllers/AccountsController.cs b/src/Api/Auth/Controllers/AccountsController.cs index 193077dc1..a94e170cb 100644 --- a/src/Api/Auth/Controllers/AccountsController.cs +++ b/src/Api/Auth/Controllers/AccountsController.cs @@ -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; diff --git a/src/Api/Vault/Validators/CipherRotationValidator.cs b/src/Api/KeyManagement/Validators/CipherRotationValidator.cs similarity index 92% rename from src/Api/Vault/Validators/CipherRotationValidator.cs rename to src/Api/KeyManagement/Validators/CipherRotationValidator.cs index 77e437017..ab56db419 100644 --- a/src/Api/Vault/Validators/CipherRotationValidator.cs +++ b/src/Api/KeyManagement/Validators/CipherRotationValidator.cs @@ -1,11 +1,10 @@ -using Bit.Api.Auth.Validators; -using Bit.Api.Vault.Models.Request; +using Bit.Api.Vault.Models.Request; using Bit.Core.Entities; using Bit.Core.Exceptions; using Bit.Core.Vault.Entities; using Bit.Core.Vault.Repositories; -namespace Bit.Api.Vault.Validators; +namespace Bit.Api.KeyManagement.Validators; public class CipherRotationValidator : IRotationValidator, IEnumerable> { diff --git a/src/Api/Auth/Validators/EmergencyAccessRotationValidator.cs b/src/Api/KeyManagement/Validators/EmergencyAccessRotationValidator.cs similarity index 97% rename from src/Api/Auth/Validators/EmergencyAccessRotationValidator.cs rename to src/Api/KeyManagement/Validators/EmergencyAccessRotationValidator.cs index 5a038730e..3fd9273e4 100644 --- a/src/Api/Auth/Validators/EmergencyAccessRotationValidator.cs +++ b/src/Api/KeyManagement/Validators/EmergencyAccessRotationValidator.cs @@ -5,7 +5,7 @@ using Bit.Core.Exceptions; using Bit.Core.Repositories; using Bit.Core.Services; -namespace Bit.Api.Auth.Validators; +namespace Bit.Api.KeyManagement.Validators; public class EmergencyAccessRotationValidator : IRotationValidator, IEnumerable> diff --git a/src/Api/Vault/Validators/FolderRotationValidator.cs b/src/Api/KeyManagement/Validators/FolderRotationValidator.cs similarity index 91% rename from src/Api/Vault/Validators/FolderRotationValidator.cs rename to src/Api/KeyManagement/Validators/FolderRotationValidator.cs index 4290c08b1..add0a46c1 100644 --- a/src/Api/Vault/Validators/FolderRotationValidator.cs +++ b/src/Api/KeyManagement/Validators/FolderRotationValidator.cs @@ -1,11 +1,10 @@ -using Bit.Api.Auth.Validators; -using Bit.Api.Vault.Models.Request; +using Bit.Api.Vault.Models.Request; using Bit.Core.Entities; using Bit.Core.Exceptions; using Bit.Core.Vault.Entities; using Bit.Core.Vault.Repositories; -namespace Bit.Api.Vault.Validators; +namespace Bit.Api.KeyManagement.Validators; public class FolderRotationValidator : IRotationValidator, IEnumerable> { diff --git a/src/Api/Auth/Validators/IRotationValidator.cs b/src/Api/KeyManagement/Validators/IRotationValidator.cs similarity index 94% rename from src/Api/Auth/Validators/IRotationValidator.cs rename to src/Api/KeyManagement/Validators/IRotationValidator.cs index fb6534ebe..50f4dd004 100644 --- a/src/Api/Auth/Validators/IRotationValidator.cs +++ b/src/Api/KeyManagement/Validators/IRotationValidator.cs @@ -1,7 +1,7 @@ using Bit.Core.Entities; using Bit.Core.Exceptions; -namespace Bit.Api.Auth.Validators; +namespace Bit.Api.KeyManagement.Validators; /// /// A consistent interface for domains to validate re-encrypted data before saved to database. Some examples are:
diff --git a/src/Api/AdminConsole/Validators/OrganizationUserRotationValidator.cs b/src/Api/KeyManagement/Validators/OrganizationUserRotationValidator.cs similarity index 96% rename from src/Api/AdminConsole/Validators/OrganizationUserRotationValidator.cs rename to src/Api/KeyManagement/Validators/OrganizationUserRotationValidator.cs index c9cf39ae0..5023521fe 100644 --- a/src/Api/AdminConsole/Validators/OrganizationUserRotationValidator.cs +++ b/src/Api/KeyManagement/Validators/OrganizationUserRotationValidator.cs @@ -1,10 +1,9 @@ using Bit.Api.AdminConsole.Models.Request.Organizations; -using Bit.Api.Auth.Validators; using Bit.Core.Entities; using Bit.Core.Exceptions; using Bit.Core.Repositories; -namespace Bit.Api.AdminConsole.Validators; +namespace Bit.Api.KeyManagement.Validators; /// /// Organization user implementation for diff --git a/src/Api/Tools/Validators/SendRotationValidator.cs b/src/Api/KeyManagement/Validators/SendRotationValidator.cs similarity index 94% rename from src/Api/Tools/Validators/SendRotationValidator.cs rename to src/Api/KeyManagement/Validators/SendRotationValidator.cs index 74b36832f..c39f563b5 100644 --- a/src/Api/Tools/Validators/SendRotationValidator.cs +++ b/src/Api/KeyManagement/Validators/SendRotationValidator.cs @@ -1,12 +1,11 @@ -using Bit.Api.Auth.Validators; -using Bit.Api.Tools.Models.Request; +using Bit.Api.Tools.Models.Request; using Bit.Core.Entities; using Bit.Core.Exceptions; using Bit.Core.Tools.Entities; using Bit.Core.Tools.Repositories; using Bit.Core.Tools.Services; -namespace Bit.Api.Tools.Validators; +namespace Bit.Api.KeyManagement.Validators; /// /// Send implementation for diff --git a/src/Api/Auth/Validators/WebAuthnLoginKeyRotationValidator.cs b/src/Api/KeyManagement/Validators/WebAuthnLoginKeyRotationValidator.cs similarity index 97% rename from src/Api/Auth/Validators/WebAuthnLoginKeyRotationValidator.cs rename to src/Api/KeyManagement/Validators/WebAuthnLoginKeyRotationValidator.cs index 5c4d0ef30..1706aebd7 100644 --- a/src/Api/Auth/Validators/WebAuthnLoginKeyRotationValidator.cs +++ b/src/Api/KeyManagement/Validators/WebAuthnLoginKeyRotationValidator.cs @@ -4,7 +4,7 @@ using Bit.Core.Auth.Repositories; using Bit.Core.Entities; using Bit.Core.Exceptions; -namespace Bit.Api.Auth.Validators; +namespace Bit.Api.KeyManagement.Validators; public class WebAuthnLoginKeyRotationValidator : IRotationValidator, IEnumerable> { diff --git a/src/Api/Startup.cs b/src/Api/Startup.cs index 65935440c..1adf3f67d 100644 --- a/src/Api/Startup.cs +++ b/src/Api/Startup.cs @@ -8,13 +8,10 @@ using Bit.Core.Utilities; using IdentityModel; using System.Globalization; using Bit.Api.AdminConsole.Models.Request.Organizations; -using Bit.Api.AdminConsole.Validators; using Bit.Api.Auth.Models.Request; -using Bit.Api.Auth.Validators; +using Bit.Api.KeyManagement.Validators; using Bit.Api.Tools.Models.Request; -using Bit.Api.Tools.Validators; using Bit.Api.Vault.Models.Request; -using Bit.Api.Vault.Validators; using Bit.Core.Auth.Entities; using Bit.Core.IdentityServer; using Bit.SharedWeb.Health; diff --git a/src/Core/AdminConsole/Repositories/IOrganizationUserRepository.cs b/src/Core/AdminConsole/Repositories/IOrganizationUserRepository.cs index a3a68b5de..cb540c212 100644 --- a/src/Core/AdminConsole/Repositories/IOrganizationUserRepository.cs +++ b/src/Core/AdminConsole/Repositories/IOrganizationUserRepository.cs @@ -1,7 +1,7 @@ using Bit.Core.AdminConsole.Enums; -using Bit.Core.Auth.UserFeatures.UserKey; using Bit.Core.Entities; using Bit.Core.Enums; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Models.Data; using Bit.Core.Models.Data.Organizations.OrganizationUsers; diff --git a/src/Core/Auth/Repositories/IEmergencyAccessRepository.cs b/src/Core/Auth/Repositories/IEmergencyAccessRepository.cs index 6edb941d3..63ec04106 100644 --- a/src/Core/Auth/Repositories/IEmergencyAccessRepository.cs +++ b/src/Core/Auth/Repositories/IEmergencyAccessRepository.cs @@ -1,6 +1,6 @@ using Bit.Core.Auth.Entities; using Bit.Core.Auth.Models.Data; -using Bit.Core.Auth.UserFeatures.UserKey; +using Bit.Core.KeyManagement.UserKey; #nullable enable diff --git a/src/Core/Auth/Repositories/IWebAuthnCredentialRepository.cs b/src/Core/Auth/Repositories/IWebAuthnCredentialRepository.cs index 9a7fc8820..29ed9d221 100644 --- a/src/Core/Auth/Repositories/IWebAuthnCredentialRepository.cs +++ b/src/Core/Auth/Repositories/IWebAuthnCredentialRepository.cs @@ -1,6 +1,6 @@ using Bit.Core.Auth.Entities; using Bit.Core.Auth.Models.Data; -using Bit.Core.Auth.UserFeatures.UserKey; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Repositories; #nullable enable diff --git a/src/Core/Auth/UserFeatures/UserServiceCollectionExtensions.cs b/src/Core/Auth/UserFeatures/UserServiceCollectionExtensions.cs index 2469c124b..df102c855 100644 --- a/src/Core/Auth/UserFeatures/UserServiceCollectionExtensions.cs +++ b/src/Core/Auth/UserFeatures/UserServiceCollectionExtensions.cs @@ -5,12 +5,12 @@ using Bit.Core.Auth.UserFeatures.Registration.Implementations; using Bit.Core.Auth.UserFeatures.TdeOffboardingPassword.Interfaces; using Bit.Core.Auth.UserFeatures.TwoFactorAuth; using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Interfaces; -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; using Bit.Core.Auth.UserFeatures.WebAuthnLogin.Implementations; +using Bit.Core.KeyManagement.UserKey; +using Bit.Core.KeyManagement.UserKey.Implementations; using Bit.Core.Services; using Bit.Core.Settings; using Microsoft.Extensions.DependencyInjection; diff --git a/src/Core/Auth/Models/Data/RotateUserKeyData.cs b/src/Core/KeyManagement/Models/Data/RotateUserKeyData.cs similarity index 89% rename from src/Core/Auth/Models/Data/RotateUserKeyData.cs rename to src/Core/KeyManagement/Models/Data/RotateUserKeyData.cs index f361c2a2c..9813f760f 100644 --- a/src/Core/Auth/Models/Data/RotateUserKeyData.cs +++ b/src/Core/KeyManagement/Models/Data/RotateUserKeyData.cs @@ -1,9 +1,10 @@ using Bit.Core.Auth.Entities; +using Bit.Core.Auth.Models.Data; using Bit.Core.Entities; using Bit.Core.Tools.Entities; using Bit.Core.Vault.Entities; -namespace Bit.Core.Auth.Models.Data; +namespace Bit.Core.KeyManagement.Models.Data; public class RotateUserKeyData { diff --git a/src/Core/KeyManagement/Models/Data/UserAsymmetricKeys.cs b/src/Core/KeyManagement/Models/Data/UserAsymmetricKeys.cs new file mode 100644 index 000000000..3c1362909 --- /dev/null +++ b/src/Core/KeyManagement/Models/Data/UserAsymmetricKeys.cs @@ -0,0 +1,9 @@ +#nullable enable +namespace Bit.Core.KeyManagement.Models.Data; + +public class UserAsymmetricKeys +{ + public Guid UserId { get; set; } + public required string PublicKey { get; set; } + public required string UserKeyEncryptedPrivateKey { get; set; } +} diff --git a/src/Core/KeyManagement/Repositories/IUserAsymmetricKeysRepository.cs b/src/Core/KeyManagement/Repositories/IUserAsymmetricKeysRepository.cs new file mode 100644 index 000000000..fee9aee3b --- /dev/null +++ b/src/Core/KeyManagement/Repositories/IUserAsymmetricKeysRepository.cs @@ -0,0 +1,9 @@ +#nullable enable +using Bit.Core.KeyManagement.Models.Data; + +namespace Bit.Core.KeyManagement.Repositories; + +public interface IUserAsymmetricKeysRepository +{ + Task RegenerateUserAsymmetricKeysAsync(UserAsymmetricKeys userAsymmetricKeys); +} diff --git a/src/Core/Auth/UserFeatures/UserKey/IRotateUserKeyCommand.cs b/src/Core/KeyManagement/UserKey/IRotateUserKeyCommand.cs similarity index 91% rename from src/Core/Auth/UserFeatures/UserKey/IRotateUserKeyCommand.cs rename to src/Core/KeyManagement/UserKey/IRotateUserKeyCommand.cs index cd2df5964..90dc90541 100644 --- a/src/Core/Auth/UserFeatures/UserKey/IRotateUserKeyCommand.cs +++ b/src/Core/KeyManagement/UserKey/IRotateUserKeyCommand.cs @@ -1,9 +1,9 @@ -using Bit.Core.Auth.Models.Data; -using Bit.Core.Entities; +using Bit.Core.Entities; +using Bit.Core.KeyManagement.Models.Data; using Microsoft.AspNetCore.Identity; using Microsoft.Data.SqlClient; -namespace Bit.Core.Auth.UserFeatures.UserKey; +namespace Bit.Core.KeyManagement.UserKey; /// /// Responsible for rotation of a user key and updating database with re-encrypted data diff --git a/src/Core/Auth/UserFeatures/UserKey/Implementations/RotateUserKeyCommand.cs b/src/Core/KeyManagement/UserKey/Implementations/RotateUserKeyCommand.cs similarity index 97% rename from src/Core/Auth/UserFeatures/UserKey/Implementations/RotateUserKeyCommand.cs rename to src/Core/KeyManagement/UserKey/Implementations/RotateUserKeyCommand.cs index 4c7ca2073..68b2c6029 100644 --- a/src/Core/Auth/UserFeatures/UserKey/Implementations/RotateUserKeyCommand.cs +++ b/src/Core/KeyManagement/UserKey/Implementations/RotateUserKeyCommand.cs @@ -1,13 +1,13 @@ -using Bit.Core.Auth.Models.Data; -using Bit.Core.Auth.Repositories; +using Bit.Core.Auth.Repositories; using Bit.Core.Entities; +using Bit.Core.KeyManagement.Models.Data; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Tools.Repositories; using Bit.Core.Vault.Repositories; using Microsoft.AspNetCore.Identity; -namespace Bit.Core.Auth.UserFeatures.UserKey.Implementations; +namespace Bit.Core.KeyManagement.UserKey.Implementations; /// public class RotateUserKeyCommand : IRotateUserKeyCommand diff --git a/src/Core/Repositories/IUserRepository.cs b/src/Core/Repositories/IUserRepository.cs index b7c654f43..22e2ec1a0 100644 --- a/src/Core/Repositories/IUserRepository.cs +++ b/src/Core/Repositories/IUserRepository.cs @@ -1,5 +1,5 @@ -using Bit.Core.Auth.UserFeatures.UserKey; -using Bit.Core.Entities; +using Bit.Core.Entities; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Models.Data; #nullable enable diff --git a/src/Core/Tools/Repositories/ISendRepository.cs b/src/Core/Tools/Repositories/ISendRepository.cs index 2cbcce1f9..6de89f037 100644 --- a/src/Core/Tools/Repositories/ISendRepository.cs +++ b/src/Core/Tools/Repositories/ISendRepository.cs @@ -1,6 +1,6 @@ #nullable enable -using Bit.Core.Auth.UserFeatures.UserKey; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Repositories; using Bit.Core.Tools.Entities; diff --git a/src/Core/Vault/Repositories/ICipherRepository.cs b/src/Core/Vault/Repositories/ICipherRepository.cs index 132aa5ac6..f3f34c595 100644 --- a/src/Core/Vault/Repositories/ICipherRepository.cs +++ b/src/Core/Vault/Repositories/ICipherRepository.cs @@ -1,5 +1,5 @@ -using Bit.Core.Auth.UserFeatures.UserKey; -using Bit.Core.Entities; +using Bit.Core.Entities; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Repositories; using Bit.Core.Vault.Entities; using Bit.Core.Vault.Models.Data; diff --git a/src/Core/Vault/Repositories/IFolderRepository.cs b/src/Core/Vault/Repositories/IFolderRepository.cs index f19243761..c4693b2a1 100644 --- a/src/Core/Vault/Repositories/IFolderRepository.cs +++ b/src/Core/Vault/Repositories/IFolderRepository.cs @@ -1,4 +1,4 @@ -using Bit.Core.Auth.UserFeatures.UserKey; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Repositories; using Bit.Core.Vault.Entities; diff --git a/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationUserRepository.cs b/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationUserRepository.cs index 361b1f058..d5bdd3b6a 100644 --- a/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationUserRepository.cs +++ b/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationUserRepository.cs @@ -2,9 +2,9 @@ using System.Text.Json; using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.Enums; -using Bit.Core.Auth.UserFeatures.UserKey; using Bit.Core.Entities; using Bit.Core.Enums; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Models.Data; using Bit.Core.Models.Data.Organizations.OrganizationUsers; using Bit.Core.Repositories; diff --git a/src/Infrastructure.Dapper/Auth/Repositories/EmergencyAccessRepository.cs b/src/Infrastructure.Dapper/Auth/Repositories/EmergencyAccessRepository.cs index e6bf92bde..4d597ab04 100644 --- a/src/Infrastructure.Dapper/Auth/Repositories/EmergencyAccessRepository.cs +++ b/src/Infrastructure.Dapper/Auth/Repositories/EmergencyAccessRepository.cs @@ -1,7 +1,7 @@ using System.Data; using Bit.Core.Auth.Entities; using Bit.Core.Auth.Models.Data; -using Bit.Core.Auth.UserFeatures.UserKey; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Repositories; using Bit.Core.Settings; using Bit.Infrastructure.Dapper.Auth.Helpers; diff --git a/src/Infrastructure.Dapper/Auth/Repositories/WebAuthnCredentialRepository.cs b/src/Infrastructure.Dapper/Auth/Repositories/WebAuthnCredentialRepository.cs index 0f7e1ea1b..7dfcd15d4 100644 --- a/src/Infrastructure.Dapper/Auth/Repositories/WebAuthnCredentialRepository.cs +++ b/src/Infrastructure.Dapper/Auth/Repositories/WebAuthnCredentialRepository.cs @@ -2,7 +2,7 @@ using Bit.Core.Auth.Entities; using Bit.Core.Auth.Models.Data; using Bit.Core.Auth.Repositories; -using Bit.Core.Auth.UserFeatures.UserKey; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Settings; using Bit.Core.Utilities; using Bit.Infrastructure.Dapper.Repositories; diff --git a/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs b/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs index 550c572cf..c873f84aa 100644 --- a/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs +++ b/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs @@ -1,6 +1,7 @@ using Bit.Core.AdminConsole.Repositories; using Bit.Core.Auth.Repositories; using Bit.Core.Billing.Repositories; +using Bit.Core.KeyManagement.Repositories; using Bit.Core.NotificationCenter.Repositories; using Bit.Core.Repositories; using Bit.Core.SecretsManager.Repositories; @@ -9,6 +10,7 @@ using Bit.Core.Vault.Repositories; using Bit.Infrastructure.Dapper.AdminConsole.Repositories; using Bit.Infrastructure.Dapper.Auth.Repositories; using Bit.Infrastructure.Dapper.Billing.Repositories; +using Bit.Infrastructure.Dapper.KeyManagement.Repositories; using Bit.Infrastructure.Dapper.NotificationCenter.Repositories; using Bit.Infrastructure.Dapper.Repositories; using Bit.Infrastructure.Dapper.SecretsManager.Repositories; @@ -60,6 +62,7 @@ public static class DapperServiceCollectionExtensions .AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); if (selfHosted) { diff --git a/src/Infrastructure.Dapper/KeyManagement/Repositories/UserAsymmetricKeysRepository.cs b/src/Infrastructure.Dapper/KeyManagement/Repositories/UserAsymmetricKeysRepository.cs new file mode 100644 index 000000000..f176327f4 --- /dev/null +++ b/src/Infrastructure.Dapper/KeyManagement/Repositories/UserAsymmetricKeysRepository.cs @@ -0,0 +1,36 @@ +#nullable enable +using System.Data; +using Bit.Core.KeyManagement.Models.Data; +using Bit.Core.KeyManagement.Repositories; +using Bit.Core.Settings; +using Bit.Infrastructure.Dapper.Repositories; +using Dapper; +using Microsoft.Data.SqlClient; + +namespace Bit.Infrastructure.Dapper.KeyManagement.Repositories; + +public class UserAsymmetricKeysRepository : BaseRepository, IUserAsymmetricKeysRepository +{ + public UserAsymmetricKeysRepository(GlobalSettings globalSettings) + : this(globalSettings.SqlServer.ConnectionString, globalSettings.SqlServer.ReadOnlyConnectionString) + { + } + + public UserAsymmetricKeysRepository(string connectionString, string readOnlyConnectionString) : base( + connectionString, readOnlyConnectionString) + { + } + + public async Task RegenerateUserAsymmetricKeysAsync(UserAsymmetricKeys userAsymmetricKeys) + { + await using var connection = new SqlConnection(ConnectionString); + + await connection.ExecuteAsync("[dbo].[UserAsymmetricKeys_Regenerate]", + new + { + userAsymmetricKeys.UserId, + userAsymmetricKeys.PublicKey, + PrivateKey = userAsymmetricKeys.UserKeyEncryptedPrivateKey + }, commandType: CommandType.StoredProcedure); + } +} diff --git a/src/Infrastructure.Dapper/Repositories/UserRepository.cs b/src/Infrastructure.Dapper/Repositories/UserRepository.cs index a96c98677..9e613fdf0 100644 --- a/src/Infrastructure.Dapper/Repositories/UserRepository.cs +++ b/src/Infrastructure.Dapper/Repositories/UserRepository.cs @@ -1,8 +1,8 @@ using System.Data; using System.Text.Json; using Bit.Core; -using Bit.Core.Auth.UserFeatures.UserKey; using Bit.Core.Entities; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Models.Data; using Bit.Core.Repositories; using Bit.Core.Settings; diff --git a/src/Infrastructure.Dapper/Tools/Repositories/SendRepository.cs b/src/Infrastructure.Dapper/Tools/Repositories/SendRepository.cs index 12fbbd4eb..81a94f0f7 100644 --- a/src/Infrastructure.Dapper/Tools/Repositories/SendRepository.cs +++ b/src/Infrastructure.Dapper/Tools/Repositories/SendRepository.cs @@ -1,7 +1,7 @@ #nullable enable using System.Data; -using Bit.Core.Auth.UserFeatures.UserKey; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Settings; using Bit.Core.Tools.Entities; using Bit.Core.Tools.Repositories; diff --git a/src/Infrastructure.Dapper/Vault/Repositories/CipherRepository.cs b/src/Infrastructure.Dapper/Vault/Repositories/CipherRepository.cs index 697edb3f3..69b1383f4 100644 --- a/src/Infrastructure.Dapper/Vault/Repositories/CipherRepository.cs +++ b/src/Infrastructure.Dapper/Vault/Repositories/CipherRepository.cs @@ -1,7 +1,7 @@ using System.Data; using System.Text.Json; -using Bit.Core.Auth.UserFeatures.UserKey; using Bit.Core.Entities; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Settings; using Bit.Core.Tools.Entities; using Bit.Core.Vault.Entities; diff --git a/src/Infrastructure.Dapper/Vault/Repositories/FolderRepository.cs b/src/Infrastructure.Dapper/Vault/Repositories/FolderRepository.cs index bf1548b24..a6f6f2ee2 100644 --- a/src/Infrastructure.Dapper/Vault/Repositories/FolderRepository.cs +++ b/src/Infrastructure.Dapper/Vault/Repositories/FolderRepository.cs @@ -1,5 +1,5 @@ using System.Data; -using Bit.Core.Auth.UserFeatures.UserKey; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Settings; using Bit.Core.Vault.Entities; using Bit.Core.Vault.Repositories; diff --git a/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs b/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs index 0c9f1d0b9..a64c19704 100644 --- a/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs +++ b/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs @@ -1,7 +1,7 @@ using AutoMapper; using Bit.Core.AdminConsole.Enums; -using Bit.Core.Auth.UserFeatures.UserKey; using Bit.Core.Enums; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Models.Data; using Bit.Core.Models.Data.Organizations.OrganizationUsers; using Bit.Core.Repositories; diff --git a/src/Infrastructure.EntityFramework/Auth/Repositories/EmergencyAccessRepository.cs b/src/Infrastructure.EntityFramework/Auth/Repositories/EmergencyAccessRepository.cs index 22ca89fa0..e1ea9bc03 100644 --- a/src/Infrastructure.EntityFramework/Auth/Repositories/EmergencyAccessRepository.cs +++ b/src/Infrastructure.EntityFramework/Auth/Repositories/EmergencyAccessRepository.cs @@ -1,7 +1,7 @@ using AutoMapper; using Bit.Core.Auth.Enums; using Bit.Core.Auth.Models.Data; -using Bit.Core.Auth.UserFeatures.UserKey; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Repositories; using Bit.Infrastructure.EntityFramework.Auth.Models; using Bit.Infrastructure.EntityFramework.Auth.Repositories.Queries; diff --git a/src/Infrastructure.EntityFramework/Auth/Repositories/WebAuthnCredentialRepository.cs b/src/Infrastructure.EntityFramework/Auth/Repositories/WebAuthnCredentialRepository.cs index b670a3f1d..e198a5f79 100644 --- a/src/Infrastructure.EntityFramework/Auth/Repositories/WebAuthnCredentialRepository.cs +++ b/src/Infrastructure.EntityFramework/Auth/Repositories/WebAuthnCredentialRepository.cs @@ -1,7 +1,7 @@ using AutoMapper; using Bit.Core.Auth.Models.Data; using Bit.Core.Auth.Repositories; -using Bit.Core.Auth.UserFeatures.UserKey; +using Bit.Core.KeyManagement.UserKey; using Bit.Infrastructure.EntityFramework.Auth.Models; using Bit.Infrastructure.EntityFramework.Repositories; using Microsoft.EntityFrameworkCore; diff --git a/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs b/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs index b8c84f649..b2eefe452 100644 --- a/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs +++ b/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs @@ -2,6 +2,7 @@ using Bit.Core.Auth.Repositories; using Bit.Core.Billing.Repositories; using Bit.Core.Enums; +using Bit.Core.KeyManagement.Repositories; using Bit.Core.NotificationCenter.Repositories; using Bit.Core.Repositories; using Bit.Core.SecretsManager.Repositories; @@ -10,6 +11,7 @@ using Bit.Core.Vault.Repositories; using Bit.Infrastructure.EntityFramework.AdminConsole.Repositories; using Bit.Infrastructure.EntityFramework.Auth.Repositories; using Bit.Infrastructure.EntityFramework.Billing.Repositories; +using Bit.Infrastructure.EntityFramework.KeyManagement.Repositories; using Bit.Infrastructure.EntityFramework.NotificationCenter.Repositories; using Bit.Infrastructure.EntityFramework.Repositories; using Bit.Infrastructure.EntityFramework.SecretsManager.Repositories; @@ -97,6 +99,7 @@ public static class EntityFrameworkServiceCollectionExtensions .AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); if (selfHosted) { diff --git a/src/Infrastructure.EntityFramework/KeyManagement/Repositories/UserAsymmetricKeysRepository.cs b/src/Infrastructure.EntityFramework/KeyManagement/Repositories/UserAsymmetricKeysRepository.cs new file mode 100644 index 000000000..c680424f5 --- /dev/null +++ b/src/Infrastructure.EntityFramework/KeyManagement/Repositories/UserAsymmetricKeysRepository.cs @@ -0,0 +1,34 @@ +#nullable enable +using AutoMapper; +using Bit.Core.KeyManagement.Models.Data; +using Bit.Core.KeyManagement.Repositories; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Infrastructure.EntityFramework.KeyManagement.Repositories; + +public class UserAsymmetricKeysRepository : BaseEntityFrameworkRepository, IUserAsymmetricKeysRepository +{ + public UserAsymmetricKeysRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) : base( + serviceScopeFactory, + mapper) + { + } + + public async Task RegenerateUserAsymmetricKeysAsync(UserAsymmetricKeys userAsymmetricKeys) + { + await using var scope = ServiceScopeFactory.CreateAsyncScope(); + var dbContext = GetDatabaseContext(scope); + + var entity = await dbContext.Users.FindAsync(userAsymmetricKeys.UserId); + if (entity != null) + { + var utcNow = DateTime.UtcNow; + entity.PublicKey = userAsymmetricKeys.PublicKey; + entity.PrivateKey = userAsymmetricKeys.UserKeyEncryptedPrivateKey; + entity.RevisionDate = utcNow; + entity.AccountRevisionDate = utcNow; + await dbContext.SaveChangesAsync(); + } + } +} diff --git a/src/Infrastructure.EntityFramework/Repositories/UserRepository.cs b/src/Infrastructure.EntityFramework/Repositories/UserRepository.cs index 735625ce4..d234d2545 100644 --- a/src/Infrastructure.EntityFramework/Repositories/UserRepository.cs +++ b/src/Infrastructure.EntityFramework/Repositories/UserRepository.cs @@ -1,5 +1,5 @@ using AutoMapper; -using Bit.Core.Auth.UserFeatures.UserKey; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Repositories; using Bit.Infrastructure.EntityFramework.Models; using Microsoft.EntityFrameworkCore; diff --git a/src/Infrastructure.EntityFramework/Tools/Repositories/SendRepository.cs b/src/Infrastructure.EntityFramework/Tools/Repositories/SendRepository.cs index 2db07f154..adf3fcc1f 100644 --- a/src/Infrastructure.EntityFramework/Tools/Repositories/SendRepository.cs +++ b/src/Infrastructure.EntityFramework/Tools/Repositories/SendRepository.cs @@ -1,7 +1,7 @@ #nullable enable using AutoMapper; -using Bit.Core.Auth.UserFeatures.UserKey; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Tools.Repositories; using Bit.Infrastructure.EntityFramework.Models; using Bit.Infrastructure.EntityFramework.Repositories; diff --git a/src/Infrastructure.EntityFramework/Vault/Repositories/CipherRepository.cs b/src/Infrastructure.EntityFramework/Vault/Repositories/CipherRepository.cs index b94cbad7c..c12167a78 100644 --- a/src/Infrastructure.EntityFramework/Vault/Repositories/CipherRepository.cs +++ b/src/Infrastructure.EntityFramework/Vault/Repositories/CipherRepository.cs @@ -1,7 +1,7 @@ using System.Text.Json; using System.Text.Json.Nodes; using AutoMapper; -using Bit.Core.Auth.UserFeatures.UserKey; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Utilities; using Bit.Core.Vault.Enums; using Bit.Core.Vault.Models.Data; diff --git a/src/Infrastructure.EntityFramework/Vault/Repositories/FolderRepository.cs b/src/Infrastructure.EntityFramework/Vault/Repositories/FolderRepository.cs index 0bab189de..09ac25633 100644 --- a/src/Infrastructure.EntityFramework/Vault/Repositories/FolderRepository.cs +++ b/src/Infrastructure.EntityFramework/Vault/Repositories/FolderRepository.cs @@ -1,5 +1,5 @@ using AutoMapper; -using Bit.Core.Auth.UserFeatures.UserKey; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Vault.Repositories; using Bit.Infrastructure.EntityFramework.Repositories; using Bit.Infrastructure.EntityFramework.Vault.Models; diff --git a/src/Sql/KeyManagement/dbo/Stored Procedures/UserAsymmetricKeys_Regenerate.sql b/src/Sql/KeyManagement/dbo/Stored Procedures/UserAsymmetricKeys_Regenerate.sql new file mode 100644 index 000000000..26d0c4018 --- /dev/null +++ b/src/Sql/KeyManagement/dbo/Stored Procedures/UserAsymmetricKeys_Regenerate.sql @@ -0,0 +1,16 @@ +CREATE PROCEDURE [dbo].[UserAsymmetricKeys_Regenerate] + @UserId UNIQUEIDENTIFIER, + @PublicKey VARCHAR(MAX), + @PrivateKey VARCHAR(MAX) +AS +BEGIN + SET NOCOUNT ON + DECLARE @UtcNow DATETIME2(7) = GETUTCDATE(); + + UPDATE [dbo].[User] + SET [PublicKey] = @PublicKey, + [PrivateKey] = @PrivateKey, + [RevisionDate] = @UtcNow, + [AccountRevisionDate] = @UtcNow + WHERE [Id] = @UserId +END diff --git a/test/Api.Test/Auth/Controllers/AccountsControllerTests.cs b/test/Api.Test/Auth/Controllers/AccountsControllerTests.cs index 13c80f856..4a0a29a5d 100644 --- a/test/Api.Test/Auth/Controllers/AccountsControllerTests.cs +++ b/test/Api.Test/Auth/Controllers/AccountsControllerTests.cs @@ -4,7 +4,7 @@ using Bit.Api.Auth.Controllers; 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.Tools.Models.Request; using Bit.Api.Vault.Models.Request; using Bit.Core; @@ -14,12 +14,12 @@ 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.Services; using Bit.Core.Context; using Bit.Core.Entities; using Bit.Core.Exceptions; +using Bit.Core.KeyManagement.UserKey; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Settings; diff --git a/test/Api.Test/Vault/Validators/CipherRotationValidatorTests.cs b/test/Api.Test/KeyManagement/Validators/CipherRotationValidatorTests.cs similarity index 94% rename from test/Api.Test/Vault/Validators/CipherRotationValidatorTests.cs rename to test/Api.Test/KeyManagement/Validators/CipherRotationValidatorTests.cs index 632bb4967..a4633e78c 100644 --- a/test/Api.Test/Vault/Validators/CipherRotationValidatorTests.cs +++ b/test/Api.Test/KeyManagement/Validators/CipherRotationValidatorTests.cs @@ -1,5 +1,5 @@ -using Bit.Api.Vault.Models.Request; -using Bit.Api.Vault.Validators; +using Bit.Api.KeyManagement.Validators; +using Bit.Api.Vault.Models.Request; using Bit.Core.Entities; using Bit.Core.Exceptions; using Bit.Core.Vault.Models.Data; @@ -9,7 +9,7 @@ using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; -namespace Bit.Api.Test.Vault.Validators; +namespace Bit.Api.Test.KeyManagement.Validators; [SutProviderCustomize] public class CipherRotationValidatorTests diff --git a/test/Api.Test/Auth/Validators/EmergencyAccessRotationValidatorTests.cs b/test/Api.Test/KeyManagement/Validators/EmergencyAccessRotationValidatorTests.cs similarity index 98% rename from test/Api.Test/Auth/Validators/EmergencyAccessRotationValidatorTests.cs rename to test/Api.Test/KeyManagement/Validators/EmergencyAccessRotationValidatorTests.cs index c75ccd643..e00129fd8 100644 --- a/test/Api.Test/Auth/Validators/EmergencyAccessRotationValidatorTests.cs +++ b/test/Api.Test/KeyManagement/Validators/EmergencyAccessRotationValidatorTests.cs @@ -1,5 +1,5 @@ using Bit.Api.Auth.Models.Request; -using Bit.Api.Auth.Validators; +using Bit.Api.KeyManagement.Validators; using Bit.Core.Auth.Models.Data; using Bit.Core.Entities; using Bit.Core.Exceptions; @@ -10,7 +10,7 @@ using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; -namespace Bit.Api.Test.Auth.Validators; +namespace Bit.Api.Test.KeyManagement.Validators; [SutProviderCustomize] public class EmergencyAccessRotationValidatorTests diff --git a/test/Api.Test/Vault/Validators/FolderRotationValidatorTests.cs b/test/Api.Test/KeyManagement/Validators/FolderRotationValidatorTests.cs similarity index 94% rename from test/Api.Test/Vault/Validators/FolderRotationValidatorTests.cs rename to test/Api.Test/KeyManagement/Validators/FolderRotationValidatorTests.cs index 0888fd32d..3778741bb 100644 --- a/test/Api.Test/Vault/Validators/FolderRotationValidatorTests.cs +++ b/test/Api.Test/KeyManagement/Validators/FolderRotationValidatorTests.cs @@ -1,5 +1,5 @@ -using Bit.Api.Vault.Models.Request; -using Bit.Api.Vault.Validators; +using Bit.Api.KeyManagement.Validators; +using Bit.Api.Vault.Models.Request; using Bit.Core.Entities; using Bit.Core.Exceptions; using Bit.Core.Vault.Entities; @@ -9,7 +9,7 @@ using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; -namespace Bit.Api.Test.Vault.Validators; +namespace Bit.Api.Test.KeyManagement.Validators; [SutProviderCustomize] public class FolderRotationValidatorTests diff --git a/test/Api.Test/AdminConsole/Validators/OrganizationUserRotationValidatorTests.cs b/test/Api.Test/KeyManagement/Validators/OrganizationUserRotationValidatorTests.cs similarity index 98% rename from test/Api.Test/AdminConsole/Validators/OrganizationUserRotationValidatorTests.cs rename to test/Api.Test/KeyManagement/Validators/OrganizationUserRotationValidatorTests.cs index 5d4ffeef6..964c80190 100644 --- a/test/Api.Test/AdminConsole/Validators/OrganizationUserRotationValidatorTests.cs +++ b/test/Api.Test/KeyManagement/Validators/OrganizationUserRotationValidatorTests.cs @@ -1,5 +1,5 @@ using Bit.Api.AdminConsole.Models.Request.Organizations; -using Bit.Api.AdminConsole.Validators; +using Bit.Api.KeyManagement.Validators; using Bit.Core.Entities; using Bit.Core.Exceptions; using Bit.Core.Repositories; @@ -8,7 +8,7 @@ using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; -namespace Bit.Api.Test.AdminConsole.Validators; +namespace Bit.Api.Test.KeyManagement.Validators; [SutProviderCustomize] public class OrganizationUserRotationValidatorTests diff --git a/test/Api.Test/Tools/Validators/SendRotationValidatorTests.cs b/test/Api.Test/KeyManagement/Validators/SendRotationValidatorTests.cs similarity index 98% rename from test/Api.Test/Tools/Validators/SendRotationValidatorTests.cs rename to test/Api.Test/KeyManagement/Validators/SendRotationValidatorTests.cs index 76f938d1c..842343ba3 100644 --- a/test/Api.Test/Tools/Validators/SendRotationValidatorTests.cs +++ b/test/Api.Test/KeyManagement/Validators/SendRotationValidatorTests.cs @@ -1,7 +1,7 @@ using System.Text.Json; +using Bit.Api.KeyManagement.Validators; using Bit.Api.Tools.Models; using Bit.Api.Tools.Models.Request; -using Bit.Api.Tools.Validators; using Bit.Core.Entities; using Bit.Core.Exceptions; using Bit.Core.Tools.Entities; @@ -14,7 +14,7 @@ using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; -namespace Bit.Api.Test.Tools.Validators; +namespace Bit.Api.Test.KeyManagement.Validators; [SutProviderCustomize] public class SendRotationValidatorTests diff --git a/test/Api.Test/Auth/Validators/WebauthnLoginKeyRotationValidatorTests.cs b/test/Api.Test/KeyManagement/Validators/WebauthnLoginKeyRotationValidatorTests.cs similarity index 97% rename from test/Api.Test/Auth/Validators/WebauthnLoginKeyRotationValidatorTests.cs rename to test/Api.Test/KeyManagement/Validators/WebauthnLoginKeyRotationValidatorTests.cs index 97eadcbdc..de661497e 100644 --- a/test/Api.Test/Auth/Validators/WebauthnLoginKeyRotationValidatorTests.cs +++ b/test/Api.Test/KeyManagement/Validators/WebauthnLoginKeyRotationValidatorTests.cs @@ -1,5 +1,5 @@ using Bit.Api.Auth.Models.Request.WebAuthn; -using Bit.Api.Auth.Validators; +using Bit.Api.KeyManagement.Validators; using Bit.Core.Auth.Entities; using Bit.Core.Auth.Repositories; using Bit.Core.Entities; @@ -9,7 +9,7 @@ using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; -namespace Bit.Api.Test.Auth.Validators; +namespace Bit.Api.Test.KeyManagement.Validators; [SutProviderCustomize] public class WebAuthnLoginKeyRotationValidatorTests diff --git a/test/Core.Test/Auth/UserFeatures/UserKey/RotateUserKeyCommandTests.cs b/test/Core.Test/KeyManagement/UserKey/RotateUserKeyCommandTests.cs similarity index 95% rename from test/Core.Test/Auth/UserFeatures/UserKey/RotateUserKeyCommandTests.cs rename to test/Core.Test/KeyManagement/UserKey/RotateUserKeyCommandTests.cs index 41c78f427..b650d1724 100644 --- a/test/Core.Test/Auth/UserFeatures/UserKey/RotateUserKeyCommandTests.cs +++ b/test/Core.Test/KeyManagement/UserKey/RotateUserKeyCommandTests.cs @@ -1,8 +1,8 @@ using Bit.Core.Auth.Entities; -using Bit.Core.Auth.Models.Data; using Bit.Core.Auth.Repositories; -using Bit.Core.Auth.UserFeatures.UserKey.Implementations; using Bit.Core.Entities; +using Bit.Core.KeyManagement.Models.Data; +using Bit.Core.KeyManagement.UserKey.Implementations; using Bit.Core.Services; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; @@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Identity; using NSubstitute; using Xunit; -namespace Bit.Core.Test.Auth.UserFeatures.UserKey; +namespace Bit.Core.Test.KeyManagement.UserFeatures.UserKey; [SutProviderCustomize] public class RotateUserKeyCommandTests diff --git a/util/Migrator/DbScripts/2024-11-21_00_AddUserAsymmetricKeysRegenerate.sql b/util/Migrator/DbScripts/2024-11-21_00_AddUserAsymmetricKeysRegenerate.sql new file mode 100644 index 000000000..e1f543114 --- /dev/null +++ b/util/Migrator/DbScripts/2024-11-21_00_AddUserAsymmetricKeysRegenerate.sql @@ -0,0 +1,16 @@ +CREATE OR ALTER PROCEDURE [dbo].[UserAsymmetricKeys_Regenerate] + @UserId UNIQUEIDENTIFIER, + @PublicKey VARCHAR(MAX), + @PrivateKey VARCHAR(MAX) +AS +BEGIN + SET NOCOUNT ON + DECLARE @UtcNow DATETIME2(7) = GETUTCDATE(); + + UPDATE [dbo].[User] + SET [PublicKey] = @PublicKey, + [PrivateKey] = @PrivateKey, + [RevisionDate] = @UtcNow, + [AccountRevisionDate] = @UtcNow + WHERE [Id] = @UserId +END