5-improve-encrypted-storage (#6)
Added the use of DEK's for encryption of secrets. Both the KEK's and DEK's are stored in a way that you can have multiple key of which one is active. But the others are still available for decrypting. This allows for implementing key rotation. Co-authored-by: eelke <eelke@eelkeklein.nl> Co-authored-by: Eelke76 <31384324+Eelke76@users.noreply.github.com> Reviewed-on: #6
This commit is contained in:
parent
138f335af0
commit
07393f57fc
87 changed files with 1903 additions and 533 deletions
|
|
@ -1,7 +1,9 @@
|
|||
using IdentityShroud.Core.Contracts;
|
||||
using IdentityShroud.Core.Model;
|
||||
using IdentityShroud.Core.Security;
|
||||
using IdentityShroud.Core.Security.Keys;
|
||||
using IdentityShroud.Core.Services;
|
||||
using IdentityShroud.Core.Tests.Fixtures;
|
||||
using IdentityShroud.TestUtils.Substitutes;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace IdentityShroud.Core.Tests.Services;
|
||||
|
|
@ -9,7 +11,7 @@ namespace IdentityShroud.Core.Tests.Services;
|
|||
public class RealmServiceTests : IClassFixture<DbFixture>
|
||||
{
|
||||
private readonly DbFixture _dbFixture;
|
||||
private readonly IEncryptionService _encryptionService = EncryptionServiceSubstitute.CreatePassthrough();
|
||||
private readonly IKeyService _keyService = Substitute.For<IKeyService>();
|
||||
|
||||
public RealmServiceTests(DbFixture dbFixture)
|
||||
{
|
||||
|
|
@ -34,25 +36,43 @@ public class RealmServiceTests : IClassFixture<DbFixture>
|
|||
if (idString is not null)
|
||||
realmId = new(idString);
|
||||
|
||||
using Db db = _dbFixture.CreateDbContext();
|
||||
RealmService sut = new(db, _encryptionService);
|
||||
// Act
|
||||
|
||||
var response = await sut.Create(
|
||||
new(realmId, "slug", "New realm"),
|
||||
TestContext.Current.CancellationToken);
|
||||
|
||||
// Verify
|
||||
RealmCreateResponse val = ResultAssert.Success(response);
|
||||
if (realmId.HasValue)
|
||||
Assert.Equal(realmId, val.Id);
|
||||
else
|
||||
Assert.NotEqual(Guid.Empty, val.Id);
|
||||
|
||||
Assert.Equal("slug", val.Slug);
|
||||
Assert.Equal("New realm", val.Name);
|
||||
|
||||
// TODO verify data has been stored!
|
||||
RealmCreateResponse? val;
|
||||
await using (var db = _dbFixture.CreateDbContext())
|
||||
{
|
||||
_keyService.CreateKey(Arg.Any<KeyPolicy>())
|
||||
.Returns(new RealmKey()
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
KeyType = "TST",
|
||||
Key = new(KekId.NewId(), [21]),
|
||||
CreatedAt = DateTime.UtcNow
|
||||
});
|
||||
// Act
|
||||
RealmService sut = new(db, _keyService);
|
||||
var response = await sut.Create(
|
||||
new(realmId, "slug", "New realm"),
|
||||
TestContext.Current.CancellationToken);
|
||||
|
||||
// Verify
|
||||
val = ResultAssert.Success(response);
|
||||
if (realmId.HasValue)
|
||||
Assert.Equal(realmId, val.Id);
|
||||
else
|
||||
Assert.NotEqual(Guid.Empty, val.Id);
|
||||
|
||||
Assert.Equal("slug", val.Slug);
|
||||
Assert.Equal("New realm", val.Name);
|
||||
|
||||
_keyService.Received().CreateKey(Arg.Any<KeyPolicy>());
|
||||
}
|
||||
|
||||
await using (var db = _dbFixture.CreateDbContext())
|
||||
{
|
||||
var dbRecord = await db.Realms
|
||||
.Include(e => e.Keys)
|
||||
.SingleAsync(e => e.Id == val.Id, TestContext.Current.CancellationToken);
|
||||
Assert.Equal("TST", dbRecord.Keys[0].KeyType);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -60,7 +80,7 @@ public class RealmServiceTests : IClassFixture<DbFixture>
|
|||
[InlineData("foo", "Foo")]
|
||||
public async Task FindBySlug(string slug, string? name)
|
||||
{
|
||||
using (var setupContext = _dbFixture.CreateDbContext())
|
||||
await using (var setupContext = _dbFixture.CreateDbContext())
|
||||
{
|
||||
setupContext.Realms.Add(new()
|
||||
{
|
||||
|
|
@ -76,11 +96,48 @@ public class RealmServiceTests : IClassFixture<DbFixture>
|
|||
await setupContext.SaveChangesAsync(TestContext.Current.CancellationToken);
|
||||
}
|
||||
|
||||
using Db actContext = _dbFixture.CreateDbContext();
|
||||
RealmService sut = new(actContext, _encryptionService);
|
||||
await using var actContext = _dbFixture.CreateDbContext();
|
||||
// Act
|
||||
RealmService sut = new(actContext, _keyService);
|
||||
var result = await sut.FindBySlug(slug, TestContext.Current.CancellationToken);
|
||||
|
||||
// Verify
|
||||
Assert.Equal(name, result?.Name);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("b0423bba-2411-497b-a5b6-c5adf404b862", true)]
|
||||
[InlineData("65ac9dba-6d43-4fa4-b57f-133ed639fbcb", false)]
|
||||
public async Task FindById(string idString, bool shouldFind)
|
||||
{
|
||||
Guid id = new(idString);
|
||||
await using (var setupContext = _dbFixture.CreateDbContext())
|
||||
{
|
||||
setupContext.Realms.Add(new()
|
||||
{
|
||||
Id = new("b0423bba-2411-497b-a5b6-c5adf404b862"),
|
||||
Slug = "foo",
|
||||
Name = "Foo",
|
||||
});
|
||||
setupContext.Realms.Add(new()
|
||||
{
|
||||
Id = new("d4ffc7d0-7b2c-4f02-82b9-a74610435b0d"),
|
||||
Slug = "bar",
|
||||
Name = "Bar",
|
||||
});
|
||||
|
||||
await setupContext.SaveChangesAsync(TestContext.Current.CancellationToken);
|
||||
}
|
||||
|
||||
await using var actContext = _dbFixture.CreateDbContext();
|
||||
// Act
|
||||
RealmService sut = new(actContext, _keyService);
|
||||
Realm? result = await sut.FindById(id, TestContext.Current.CancellationToken);
|
||||
|
||||
// Verify
|
||||
if (shouldFind)
|
||||
Assert.NotNull(result);
|
||||
else
|
||||
Assert.Null(result);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue