/
PublicX509CertificateDetailProvider.cs
69 lines (56 loc) · 2.64 KB
/
PublicX509CertificateDetailProvider.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
using Azure.Core;
using Azure.Security.KeyVault.Certificates;
using Microsoft.Extensions.Caching.Memory;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Extensions.Logging;
using Saas.Interface;
using Saas.Identity.Interface;
using Saas.Identity.Model;
using Saas.Identity.Crypto.Util;
namespace Saas.Identity.Crypto;
public class PublicX509CertificateDetailProvider(
IMemoryCache memoryCache,
ILogger<PublicX509CertificateDetailProvider> logger) : IPublicX509CertificateDetailProvider
{
private readonly ILogger _logger = logger;
// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/loggermessage?view=aspnetcore-8.0
private static readonly Action<ILogger, Exception> _logError = LoggerMessage.Define(
LogLevel.Error,
new EventId(1, nameof(PublicX509CertificateDetailProvider)),
"Client Assertion Signing Provider");
private readonly IMemoryCache _memoryCache = memoryCache;
public async Task<IPublicX509CertificateDetail> GetX509Detail(IKeyVaultInfo keyInfo, TokenCredential credential)
{
if (!Uri.TryCreate(keyInfo.KeyVaultUrl, UriKind.Absolute, out Uri? keyVaultUri))
{
throw new UriFormatException($"Invalid Key Vault Url format: '{keyInfo.KeyVaultUrl}'");
}
var cacheItemName = $"{keyInfo.KeyVaultUrl}-{keyInfo.KeyVaultCertificateName}";
if (_memoryCache.TryGetValue<PublicX509CertificateDetail>(cacheItemName, out var cachedCertDetails)
&& cachedCertDetails is not null)
{
return cachedCertDetails;
}
try
{
CertificateClient certClient = new(keyVaultUri, credential);
Azure.Response<KeyVaultCertificateWithPolicy> keyVaultPublicCertResponse =
await certClient.GetCertificateAsync(keyInfo.KeyVaultCertificateName);
X509Certificate2 publicX509Cert = new(keyVaultPublicCertResponse.Value.Cer);
PublicX509CertificateDetail publicX509CertificateDetail = new(
publicX509Cert.GetCertHash().Base64UrlEncode(),
keyVaultPublicCertResponse.Value.KeyId,
keyVaultPublicCertResponse.Value.Name);
// The certificate details are cached for 2 hours since they rarely change.
var cacheOptions = new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromHours(2));
_memoryCache.Set(cacheItemName, publicX509CertificateDetail, cacheOptions);
return publicX509CertificateDetail;
}
catch (Exception ex)
{
_logError(_logger, ex);
throw;
}
}
}