1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-20 02:48:03 -05:00

Merge branch 'km/signing-api-changes' of github.com:bitwarden/server into km/signing-api-changes

This commit is contained in:
Bernd Schoolmann 2025-06-12 16:02:33 +02:00
commit 343452fb7f
No known key found for this signature in database
9 changed files with 31 additions and 37 deletions

View File

@ -23,10 +23,9 @@ public class UsersController(
} }
[HttpGet("{id}/keys")] [HttpGet("{id}/keys")]
public async Task<PublicKeysResponseModel> GetAccountKeysAsync(string id) public async Task<PublicKeysResponseModel> GetAccountKeysAsync([FromRoute]Guid id)
{ {
var guidId = new Guid(id); var user = await _userRepository.GetByIdAsync(id) ?? throw new NotFoundException();
var user = await _userRepository.GetByIdAsync(guidId) ?? throw new NotFoundException();
var accountKeys = await _userAccountKeysQuery.Run(user) ?? throw new NotFoundException("User account keys not found."); var accountKeys = await _userAccountKeysQuery.Run(user) ?? throw new NotFoundException("User account keys not found.");
return new PublicKeysResponseModel(accountKeys); return new PublicKeysResponseModel(accountKeys);
} }

View File

@ -7,7 +7,7 @@ namespace Bit.Api.KeyManagement.Models.Response;
#nullable enable #nullable enable
/// <summary> /// <summary>
/// This response model is used to return the the asymmetric encryption keys, /// This response model is used to return the asymmetric encryption keys,
/// and signature keys of an entity. This includes the private keys of the key pairs, /// and signature keys of an entity. This includes the private keys of the key pairs,
/// (private key, signing key), and the public keys of the key pairs (unsigned public key, /// (private key, signing key), and the public keys of the key pairs (unsigned public key,
/// signed public key, verification key). /// signed public key, verification key).

View File

@ -1,5 +1,4 @@
using System.ComponentModel.DataAnnotations; using Bit.Core.Entities;
using Bit.Core.Entities;
using Bit.Core.KeyManagement.Enums; using Bit.Core.KeyManagement.Enums;
using Bit.Core.KeyManagement.Models.Data; using Bit.Core.KeyManagement.Models.Data;
using Bit.Core.Utilities; using Bit.Core.Utilities;
@ -14,9 +13,7 @@ public class UserSignatureKeyPair : ITableObject<Guid>, IRevisable
public Guid UserId { get; set; } public Guid UserId { get; set; }
public SignatureAlgorithm SignatureAlgorithm { get; set; } public SignatureAlgorithm SignatureAlgorithm { get; set; }
[MaxLength(500)]
required public string VerifyingKey { get; set; } required public string VerifyingKey { get; set; }
[MaxLength(500)]
required public string SigningKey { get; set; } required public string SigningKey { get; set; }
public DateTime CreationDate { get; set; } = DateTime.UtcNow; public DateTime CreationDate { get; set; } = DateTime.UtcNow;

View File

@ -11,13 +11,13 @@ using Microsoft.Extensions.DependencyInjection;
namespace Bit.Infrastructure.EntityFramework.KeyManagement.Repositories; namespace Bit.Infrastructure.EntityFramework.KeyManagement.Repositories;
public class UserSignatureKeyPairRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) : Repository<Core.KeyManagement.Entities.UserSignatureKeyPair, Models.UserSignatureKeyPair, Guid>(serviceScopeFactory, mapper, context => context.UserSignatureKeyPair), IUserSignatureKeyPairRepository public class UserSignatureKeyPairRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) : Repository<Core.KeyManagement.Entities.UserSignatureKeyPair, Models.UserSignatureKeyPair, Guid>(serviceScopeFactory, mapper, context => context.UserSignatureKeyPairs), IUserSignatureKeyPairRepository
{ {
public async Task<SignatureKeyPairData?> GetByUserIdAsync(Guid userId) public async Task<SignatureKeyPairData?> GetByUserIdAsync(Guid userId)
{ {
await using var scope = ServiceScopeFactory.CreateAsyncScope(); await using var scope = ServiceScopeFactory.CreateAsyncScope();
var dbContext = GetDatabaseContext(scope); var dbContext = GetDatabaseContext(scope);
var signingKeys = await dbContext.UserSignatureKeyPair.FindAsync(userId); var signingKeys = await dbContext.UserSignatureKeyPairs.FindAsync(userId);
if (signingKeys == null) if (signingKeys == null)
{ {
return null; return null;
@ -42,7 +42,7 @@ public class UserSignatureKeyPairRepository(IServiceScopeFactory serviceScopeFac
CreationDate = DateTime.UtcNow, CreationDate = DateTime.UtcNow,
RevisionDate = DateTime.UtcNow, RevisionDate = DateTime.UtcNow,
}; };
await dbContext.UserSignatureKeyPair.AddAsync(entity); await dbContext.UserSignatureKeyPairs.AddAsync(entity);
await dbContext.SaveChangesAsync(); await dbContext.SaveChangesAsync();
}; };
} }
@ -53,7 +53,7 @@ public class UserSignatureKeyPairRepository(IServiceScopeFactory serviceScopeFac
{ {
await using var scope = ServiceScopeFactory.CreateAsyncScope(); await using var scope = ServiceScopeFactory.CreateAsyncScope();
var dbContext = GetDatabaseContext(scope); var dbContext = GetDatabaseContext(scope);
var entity = await dbContext.UserSignatureKeyPair.FirstOrDefaultAsync(x => x.UserId == grantorId); var entity = await dbContext.UserSignatureKeyPairs.FirstOrDefaultAsync(x => x.UserId == grantorId);
if (entity != null) if (entity != null)
{ {
entity.SignatureAlgorithm = signingKeys.SignatureAlgorithm; entity.SignatureAlgorithm = signingKeys.SignatureAlgorithm;

View File

@ -71,7 +71,7 @@ public class DatabaseContext : DbContext
public DbSet<TaxRate> TaxRates { get; set; } public DbSet<TaxRate> TaxRates { get; set; }
public DbSet<Transaction> Transactions { get; set; } public DbSet<Transaction> Transactions { get; set; }
public DbSet<User> Users { get; set; } public DbSet<User> Users { get; set; }
public DbSet<UserSignatureKeyPair> UserSignatureKeyPair { get; set; } public DbSet<UserSignatureKeyPair> UserSignatureKeyPairs { get; set; }
public DbSet<AuthRequest> AuthRequests { get; set; } public DbSet<AuthRequest> AuthRequests { get; set; }
public DbSet<OrganizationDomain> OrganizationDomains { get; set; } public DbSet<OrganizationDomain> OrganizationDomains { get; set; }
public DbSet<WebAuthnCredential> WebAuthnCredentials { get; set; } public DbSet<WebAuthnCredential> WebAuthnCredentials { get; set; }

View File

@ -1,14 +1,18 @@
CREATE TABLE [dbo].[UserSignatureKeyPair] ( IF OBJECT_ID('[dbo].[UserSignatureKeyPair]') IS NULL
[Id] UNIQUEIDENTIFIER NOT NULL, BEGIN
[UserId] UNIQUEIDENTIFIER NOT NULL, CREATE TABLE [dbo].[UserSignatureKeyPair]
[SignatureKeyPairAlgorithm] TINYINT NOT NULL, (
[SigningKey] VARCHAR(MAX) NOT NULL, [Id] UNIQUEIDENTIFIER NOT NULL,
[VerifyingKey] VARCHAR(MAX) NOT NULL, [UserId] UNIQUEIDENTIFIER NOT NULL,
[CreationDate] DATETIME2 (7) NOT NULL, [SignatureKeyPairAlgorithm] TINYINT NOT NULL,
[RevisionDate] DATETIME2 (7) NOT NULL, [SigningKey] VARCHAR(MAX) NOT NULL,
CONSTRAINT [PK_UserSignatureKeyPair] PRIMARY KEY CLUSTERED ([Id] ASC), [VerifyingKey] VARCHAR(MAX) NOT NULL,
CONSTRAINT [FK_UserSignatureKeyPair_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]) [CreationDate] DATETIME2 (7) NOT NULL,
); [RevisionDate] DATETIME2 (7) NOT NULL,
CONSTRAINT [PK_UserSignatureKeyPair] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_UserSignatureKeyPair_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id])
);
END
GO GO
IF NOT EXISTS(SELECT name IF NOT EXISTS(SELECT name
@ -29,7 +33,7 @@ FROM
[dbo].[UserSignatureKeyPair] [dbo].[UserSignatureKeyPair]
GO GO
CREATE PROCEDURE [dbo].[UserSignatureKeyPair_ReadByUserId] CREATE OR ALTER PROCEDURE [dbo].[UserSignatureKeyPair_ReadByUserId]
@UserId UNIQUEIDENTIFIER @UserId UNIQUEIDENTIFIER
AS AS
BEGIN BEGIN
@ -39,7 +43,7 @@ BEGIN
END END
GO GO
CREATE PROCEDURE [dbo].[UserSignatureKeyPair_UpdateForRotation] CREATE OR ALTER PROCEDURE [dbo].[UserSignatureKeyPair_UpdateForRotation]
@UserId UNIQUEIDENTIFIER, @UserId UNIQUEIDENTIFIER,
@SignatureKeyPairAlgorithm TINYINT, @SignatureKeyPairAlgorithm TINYINT,
@SigningKey VARCHAR(MAX), @SigningKey VARCHAR(MAX),
@ -56,7 +60,7 @@ BEGIN
END END
GO GO
CREATE PROCEDURE [dbo].[UserSignatureKeyPair_SetForRotation] CREATE OR ALTER PROCEDURE [dbo].[UserSignatureKeyPair_SetForRotation]
@Id UNIQUEIDENTIFIER, @Id UNIQUEIDENTIFIER,
@UserId UNIQUEIDENTIFIER, @UserId UNIQUEIDENTIFIER,
@SignatureKeyPairAlgorithm TINYINT, @SignatureKeyPairAlgorithm TINYINT,

View File

@ -1752,16 +1752,14 @@ namespace Bit.MySqlMigrations.Migrations
b.Property<string>("SigningKey") b.Property<string>("SigningKey")
.IsRequired() .IsRequired()
.HasMaxLength(500) .HasColumnType("longtext");
.HasColumnType("varchar(500)");
b.Property<Guid>("UserId") b.Property<Guid>("UserId")
.HasColumnType("char(36)"); .HasColumnType("char(36)");
b.Property<string>("VerifyingKey") b.Property<string>("VerifyingKey")
.IsRequired() .IsRequired()
.HasMaxLength(500) .HasColumnType("longtext");
.HasColumnType("varchar(500)");
b.HasKey("Id"); b.HasKey("Id");

View File

@ -1758,16 +1758,14 @@ namespace Bit.PostgresMigrations.Migrations
b.Property<string>("SigningKey") b.Property<string>("SigningKey")
.IsRequired() .IsRequired()
.HasMaxLength(500) .HasColumnType("text");
.HasColumnType("character varying(500)");
b.Property<Guid>("UserId") b.Property<Guid>("UserId")
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<string>("VerifyingKey") b.Property<string>("VerifyingKey")
.IsRequired() .IsRequired()
.HasMaxLength(500) .HasColumnType("text");
.HasColumnType("character varying(500)");
b.HasKey("Id"); b.HasKey("Id");

View File

@ -1741,7 +1741,6 @@ namespace Bit.SqliteMigrations.Migrations
b.Property<string>("SigningKey") b.Property<string>("SigningKey")
.IsRequired() .IsRequired()
.HasMaxLength(500)
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<Guid>("UserId") b.Property<Guid>("UserId")
@ -1749,7 +1748,6 @@ namespace Bit.SqliteMigrations.Migrations
b.Property<string>("VerifyingKey") b.Property<string>("VerifyingKey")
.IsRequired() .IsRequired()
.HasMaxLength(500)
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.HasKey("Id"); b.HasKey("Id");