feat: Implement PostgreSQL repositories for various entities
- Added BootstrapInviteRepository for managing bootstrap invites. - Added ClientRepository for handling OAuth/OpenID clients. - Introduced LoginAttemptRepository for logging login attempts. - Created OidcTokenRepository for managing OpenIddict tokens and refresh tokens. - Implemented RevocationExportStateRepository for persisting revocation export state. - Added RevocationRepository for managing revocations. - Introduced ServiceAccountRepository for handling service accounts.
This commit is contained in:
@@ -1,16 +1,10 @@
|
||||
using Net.Pkcs11Interop.Common;
|
||||
using Net.Pkcs11Interop.HighLevelAPI;
|
||||
using Net.Pkcs11Interop.HighLevelAPI.MechanismParams;
|
||||
using Pkcs11 = Net.Pkcs11Interop.HighLevelAPI.Pkcs11;
|
||||
using Slot = Net.Pkcs11Interop.HighLevelAPI.Slot;
|
||||
using ISession = Net.Pkcs11Interop.HighLevelAPI.Session;
|
||||
using ObjectHandle = Net.Pkcs11Interop.HighLevelAPI.ObjectHandle;
|
||||
using ObjectAttribute = Net.Pkcs11Interop.HighLevelAPI.ObjectAttribute;
|
||||
using Mechanism = Net.Pkcs11Interop.HighLevelAPI.Mechanism;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Formats.Asn1;
|
||||
using System.Security.Cryptography;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Net.Pkcs11Interop.Common;
|
||||
using Net.Pkcs11Interop.HighLevelAPI;
|
||||
using Net.Pkcs11Interop.HighLevelAPI.Factories;
|
||||
|
||||
namespace StellaOps.Cryptography.Kms;
|
||||
|
||||
@@ -37,9 +31,10 @@ public sealed record Pkcs11PublicKeyMaterial(
|
||||
internal sealed class Pkcs11InteropFacade : IPkcs11Facade
|
||||
{
|
||||
private readonly Pkcs11Options _options;
|
||||
private readonly Pkcs11 _library;
|
||||
private readonly Slot _slot;
|
||||
private readonly ConcurrentDictionary<string, ObjectAttribute[]> _attributeCache = new(StringComparer.Ordinal);
|
||||
private readonly Pkcs11InteropFactories _factories;
|
||||
private readonly IPkcs11Library _library;
|
||||
private readonly ISlot _slot;
|
||||
private readonly ConcurrentDictionary<string, IObjectAttribute[]> _attributeCache = new(StringComparer.Ordinal);
|
||||
|
||||
public Pkcs11InteropFacade(Pkcs11Options options)
|
||||
{
|
||||
@@ -49,7 +44,8 @@ internal sealed class Pkcs11InteropFacade : IPkcs11Facade
|
||||
throw new ArgumentException("PKCS#11 library path must be provided.", nameof(options));
|
||||
}
|
||||
|
||||
_library = new Pkcs11(_options.LibraryPath, AppType.MultiThreaded);
|
||||
_factories = new Pkcs11InteropFactories();
|
||||
_library = _factories.Pkcs11LibraryFactory.LoadPkcs11Library(_factories, _options.LibraryPath, AppType.MultiThreaded);
|
||||
_slot = ResolveSlot(_library, _options)
|
||||
?? throw new InvalidOperationException("Could not resolve PKCS#11 slot.");
|
||||
}
|
||||
@@ -116,7 +112,7 @@ internal sealed class Pkcs11InteropFacade : IPkcs11Facade
|
||||
var privateHandle = FindKey(session, CKO.CKO_PRIVATE_KEY, _options.PrivateKeyLabel)
|
||||
?? throw new InvalidOperationException("PKCS#11 private key not found.");
|
||||
|
||||
var mechanism = new Mechanism(_options.MechanismId);
|
||||
var mechanism = _factories.MechanismFactory.Create(_options.MechanismId);
|
||||
return session.Sign(mechanism, privateHandle, digest.ToArray());
|
||||
}
|
||||
|
||||
@@ -149,23 +145,23 @@ internal sealed class Pkcs11InteropFacade : IPkcs11Facade
|
||||
}
|
||||
}
|
||||
|
||||
private ObjectHandle? FindKey(ISession session, CKO objectClass, string? label)
|
||||
private IObjectHandle? FindKey(ISession session, CKO objectClass, string? label)
|
||||
{
|
||||
var template = new List<ObjectAttribute>
|
||||
var template = new List<IObjectAttribute>
|
||||
{
|
||||
new(CKA.CKA_CLASS, (uint)objectClass)
|
||||
_factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, (uint)objectClass)
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(label))
|
||||
{
|
||||
template.Add(new ObjectAttribute(CKA.CKA_LABEL, label));
|
||||
template.Add(_factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, label));
|
||||
}
|
||||
|
||||
var handles = session.FindAllObjects(template);
|
||||
return handles.FirstOrDefault();
|
||||
}
|
||||
|
||||
private ObjectAttribute? GetAttribute(ISession session, ObjectHandle handle, CKA type)
|
||||
private IObjectAttribute? GetAttribute(ISession session, IObjectHandle handle, CKA type)
|
||||
{
|
||||
var cacheKey = $"{handle.ObjectId}:{(uint)type}";
|
||||
if (_attributeCache.TryGetValue(cacheKey, out var cached))
|
||||
@@ -174,8 +170,7 @@ internal sealed class Pkcs11InteropFacade : IPkcs11Facade
|
||||
}
|
||||
|
||||
var attributes = session.GetAttributeValue(handle, new List<CKA> { type })
|
||||
?.Select(attr => new ObjectAttribute(attr.Type, attr.GetValueAsByteArray()))
|
||||
.ToArray() ?? Array.Empty<ObjectAttribute>();
|
||||
?.ToArray() ?? Array.Empty<IObjectAttribute>();
|
||||
|
||||
if (attributes.Length > 0)
|
||||
{
|
||||
@@ -186,7 +181,7 @@ internal sealed class Pkcs11InteropFacade : IPkcs11Facade
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Slot? ResolveSlot(Pkcs11 pkcs11, Pkcs11Options options)
|
||||
private static ISlot? ResolveSlot(IPkcs11Library pkcs11, Pkcs11Options options)
|
||||
{
|
||||
var slots = pkcs11.GetSlotList(SlotsType.WithTokenPresent);
|
||||
if (slots.Count == 0)
|
||||
|
||||
Reference in New Issue
Block a user