Skip to content

Commit 689cc25

Browse files
authored
Fix | Replaced System.Runtime.Caching with Microsoft.Extensions.Caching.Memory (#2493)
1 parent ffd8771 commit 689cc25

18 files changed

+125
-72
lines changed

src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
<Compile Include="..\..\ref\Microsoft.Data.SqlClient.Batch.NetCoreApp.cs" />
1818
</ItemGroup>
1919
<ItemGroup>
20+
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="$(MicrosoftExtensionsCachingMemoryVersion)" />
2021
<PackageReference Include="System.Security.Cryptography.Cng" Version="$(SystemSecurityCryptographyCngVersion)" />
2122
<PackageReference Include="Microsoft.Identity.Client" Version="$(MicrosoftIdentityClientVersion)" />
2223
</ItemGroup>

src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -938,10 +938,10 @@
938938
<!-- Package References Etc -->
939939
<ItemGroup Condition="'$(TargetGroup)' == 'netcoreapp'">
940940
<PackageReference Include="System.Configuration.ConfigurationManager" Version="$(SystemConfigurationConfigurationManagerVersion)" />
941-
<PackageReference Include="System.Runtime.Caching" Version="$(SystemRuntimeCachingVersion)" />
942941
</ItemGroup>
943942
<ItemGroup>
944943
<PackageReference Include="Microsoft.Data.SqlClient.SNI.runtime" Version="$(MicrosoftDataSqlClientSNIRuntimeVersion)" />
944+
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="$(MicrosoftExtensionsCachingMemoryVersion)" />
945945
<!-- Enable the project reference for debugging purposes. -->
946946
<!-- <ProjectReference Include="$(SqlServerSourceCode)\Microsoft.SqlServer.Server.csproj" /> -->
947947
<PackageReference Include="Microsoft.SqlServer.Server" Version="$(MicrosoftSqlServerServerVersion)" />

src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<Reference Include="System.Transactions" />
1717
</ItemGroup>
1818
<ItemGroup>
19+
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="$(MicrosoftExtensionsCachingMemoryVersion)" />
1920
<PackageReference Include="Microsoft.Identity.Client" Version="$(MicrosoftIdentityClientVersion)" />
2021
</ItemGroup>
2122
</Project>

src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,7 @@
740740
</COMReference>
741741
</ItemGroup>
742742
<ItemGroup>
743+
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="$(MicrosoftExtensionsCachingMemoryVersion)" />
743744
<PackageReference Include="System.Text.Encodings.Web">
744745
<Version>$(SystemTextEncodingsWebVersion)</Version>
745746
</PackageReference>

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
using System;
66
using System.Collections.Concurrent;
77
using System.Linq;
8-
using System.Runtime.Caching;
98
using System.Security.Cryptography;
109
using System.Text;
1110
using System.Threading;
1211
using System.Threading.Tasks;
1312
using Azure.Core;
1413
using Azure.Identity;
14+
using Microsoft.Extensions.Caching.Memory;
1515
using Microsoft.Identity.Client;
1616
using Microsoft.Identity.Client.Extensibility;
1717

@@ -27,7 +27,7 @@ public sealed class ActiveDirectoryAuthenticationProvider : SqlAuthenticationPro
2727
/// </summary>
2828
private static ConcurrentDictionary<PublicClientAppKey, IPublicClientApplication> s_pcaMap
2929
= new ConcurrentDictionary<PublicClientAppKey, IPublicClientApplication>();
30-
private static readonly MemoryCache s_accountPwCache = new(nameof(ActiveDirectoryAuthenticationProvider));
30+
private static readonly MemoryCache s_accountPwCache = new MemoryCache(new MemoryCacheOptions());
3131
private static readonly int s_accountPwCacheTtlInHours = 2;
3232
private static readonly string s_nativeClientRedirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient";
3333
private static readonly string s_defaultScopeSuffix = "/.default";
@@ -270,11 +270,11 @@ previousPw is byte[] previousPwBytes &&
270270
// We cache the password hash to ensure future connection requests include a validated password
271271
// when we check for a cached MSAL account. Otherwise, a connection request with the same username
272272
// against the same tenant could succeed with an invalid password when we re-use the cached token.
273-
if (!s_accountPwCache.Add(pwCacheKey, GetHash(parameters.Password), DateTime.UtcNow.AddHours(s_accountPwCacheTtlInHours)))
273+
using (ICacheEntry entry = s_accountPwCache.CreateEntry(pwCacheKey))
274274
{
275-
s_accountPwCache.Remove(pwCacheKey);
276-
s_accountPwCache.Add(pwCacheKey, GetHash(parameters.Password), DateTime.UtcNow.AddHours(s_accountPwCacheTtlInHours));
277-
}
275+
entry.Value = GetHash(parameters.Password);
276+
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(s_accountPwCacheTtlInHours);
277+
};
278278

279279
SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Active Directory Password auth mode. Expiry Time: {0}", result?.ExpiresOn);
280280
}

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
using System.Collections.Generic;
77
using System.Diagnostics;
88
using System.IdentityModel.Tokens.Jwt;
9-
using System.Runtime.Caching;
109
using System.Security.Claims;
1110
using System.Security.Cryptography;
1211
using System.Text;
1312
using System.Threading;
13+
using Microsoft.Extensions.Caching.Memory;
1414
using Microsoft.IdentityModel.JsonWebTokens;
1515
using Microsoft.IdentityModel.Logging;
1616
using Microsoft.IdentityModel.Protocols;
@@ -59,7 +59,7 @@ internal class AzureAttestationEnclaveProvider : EnclaveProviderBase
5959
// such as https://sql.azure.attest.com/.well-known/openid-configuration
6060
private const string AttestationUrlSuffix = @"/.well-known/openid-configuration";
6161

62-
private static readonly MemoryCache OpenIdConnectConfigurationCache = new MemoryCache("OpenIdConnectConfigurationCache");
62+
private static readonly MemoryCache OpenIdConnectConfigurationCache = new MemoryCache(new MemoryCacheOptions());
6363
#endregion
6464

6565
#region Internal methods
@@ -332,7 +332,7 @@ private static string GetInnerMostExceptionMessage(Exception exception)
332332
// It also caches that information for 1 day to avoid DDOS attacks.
333333
private OpenIdConnectConfiguration GetOpenIdConfigForSigningKeys(string url, bool forceUpdate)
334334
{
335-
OpenIdConnectConfiguration openIdConnectConfig = OpenIdConnectConfigurationCache[url] as OpenIdConnectConfiguration;
335+
OpenIdConnectConfiguration openIdConnectConfig = OpenIdConnectConfigurationCache.Get<OpenIdConnectConfiguration>(url);
336336
if (forceUpdate || openIdConnectConfig == null)
337337
{
338338
// Compute the meta data endpoint
@@ -348,7 +348,11 @@ private OpenIdConnectConfiguration GetOpenIdConfigForSigningKeys(string url, boo
348348
throw SQL.AttestationFailed(string.Format(Strings.GetAttestationTokenSigningKeysFailed, GetInnerMostExceptionMessage(exception)), exception);
349349
}
350350

351-
OpenIdConnectConfigurationCache.Add(url, openIdConnectConfig, DateTime.UtcNow.AddDays(1));
351+
MemoryCacheEntryOptions options = new MemoryCacheEntryOptions
352+
{
353+
AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(1)
354+
};
355+
OpenIdConnectConfigurationCache.Set<OpenIdConnectConfiguration>(url, openIdConnectConfig, options);
352356
}
353357

354358
return openIdConnectConfig;

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveProviderBase.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6-
using System.Runtime.Caching;
76
using System.Security.Cryptography;
87
using System.Threading;
8+
using Microsoft.Extensions.Caching.Memory;
99

1010
// Enclave session locking model
1111
// 1. For doing the enclave attestation, driver makes either 1, 2 or 3 API calls(in order)
@@ -84,7 +84,7 @@ internal abstract class EnclaveProviderBase : SqlColumnEncryptionEnclaveProvider
8484
private static readonly Object lockUpdateSessionLock = new Object();
8585

8686
// It is used to save the attestation url and nonce value across API calls
87-
protected static readonly MemoryCache ThreadRetryCache = new MemoryCache("ThreadRetryCache");
87+
protected static readonly MemoryCache ThreadRetryCache = new MemoryCache(new MemoryCacheOptions());
8888
#endregion
8989

9090
#region protected methods
@@ -102,7 +102,7 @@ protected void GetEnclaveSessionHelper(EnclaveSessionParameters enclaveSessionPa
102102

103103
// In case if on some thread we are running SQL workload which don't require attestation, then in those cases we don't want same thread to wait for event to be signaled.
104104
// hence skipping it
105-
string retryThreadID = ThreadRetryCache[Thread.CurrentThread.ManagedThreadId.ToString()] as string;
105+
string retryThreadID = ThreadRetryCache.Get<string>(Thread.CurrentThread.ManagedThreadId.ToString());
106106
if (!string.IsNullOrEmpty(retryThreadID))
107107
{
108108
sameThreadRetry = true;
@@ -167,7 +167,11 @@ protected void GetEnclaveSessionHelper(EnclaveSessionParameters enclaveSessionPa
167167
retryThreadID = Thread.CurrentThread.ManagedThreadId.ToString();
168168
}
169169

170-
ThreadRetryCache.Set(Thread.CurrentThread.ManagedThreadId.ToString(), retryThreadID, DateTime.UtcNow.AddMinutes(ThreadRetryCacheTimeoutInMinutes));
170+
MemoryCacheEntryOptions options = new MemoryCacheEntryOptions
171+
{
172+
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(ThreadRetryCacheTimeoutInMinutes)
173+
};
174+
ThreadRetryCache.Set<string>(Thread.CurrentThread.ManagedThreadId.ToString(), retryThreadID, options);
171175
}
172176
}
173177
}

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveSessionCache.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6-
using System.Runtime.Caching;
6+
using Microsoft.Extensions.Caching.Memory;
77
using System.Threading;
88

99
namespace Microsoft.Data.SqlClient
1010
{
1111
// Maintains a cache of SqlEnclaveSession instances
1212
internal class EnclaveSessionCache
1313
{
14-
private readonly MemoryCache enclaveMemoryCache = new MemoryCache("EnclaveMemoryCache");
14+
private readonly MemoryCache enclaveMemoryCache = new MemoryCache(new MemoryCacheOptions());
1515
private readonly object enclaveCacheLock = new object();
1616

1717
// Nonce for each message sent by the client to the server to prevent replay attacks by the server,
@@ -25,7 +25,7 @@ internal class EnclaveSessionCache
2525
internal SqlEnclaveSession GetEnclaveSession(EnclaveSessionParameters enclaveSessionParameters, out long counter)
2626
{
2727
string cacheKey = GenerateCacheKey(enclaveSessionParameters);
28-
SqlEnclaveSession enclaveSession = enclaveMemoryCache[cacheKey] as SqlEnclaveSession;
28+
SqlEnclaveSession enclaveSession = enclaveMemoryCache.Get<SqlEnclaveSession>(cacheKey);
2929
counter = Interlocked.Increment(ref _counter);
3030
return enclaveSession;
3131
}
@@ -41,8 +41,12 @@ internal void InvalidateSession(EnclaveSessionParameters enclaveSessionParameter
4141

4242
if (enclaveSession != null && enclaveSession.SessionId == enclaveSessionToInvalidate.SessionId)
4343
{
44-
SqlEnclaveSession enclaveSessionRemoved = enclaveMemoryCache.Remove(cacheKey) as SqlEnclaveSession;
45-
if (enclaveSessionRemoved == null)
44+
enclaveMemoryCache.TryGetValue<SqlEnclaveSession>(cacheKey, out SqlEnclaveSession enclaveSessionToRemove);
45+
if (enclaveSessionToRemove != null)
46+
{
47+
enclaveMemoryCache.Remove(cacheKey);
48+
}
49+
else
4650
{
4751
throw new InvalidOperationException(Strings.EnclaveSessionInvalidationFailed);
4852
}
@@ -58,7 +62,11 @@ internal SqlEnclaveSession CreateSession(EnclaveSessionParameters enclaveSession
5862
lock (enclaveCacheLock)
5963
{
6064
enclaveSession = new SqlEnclaveSession(sharedSecret, sessionId);
61-
enclaveMemoryCache.Add(cacheKey, enclaveSession, DateTime.UtcNow.AddHours(enclaveCacheTimeOutInHours));
65+
MemoryCacheEntryOptions options = new MemoryCacheEntryOptions
66+
{
67+
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(enclaveCacheTimeOutInHours)
68+
};
69+
enclaveMemoryCache.Set<SqlEnclaveSession>(cacheKey, enclaveSession, options);
6270
counter = Interlocked.Increment(ref _counter);
6371
}
6472

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SignatureVerificationCache.cs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6-
using System.Runtime.Caching;
76
using System.Text;
87
using System.Threading;
8+
using Microsoft.Extensions.Caching.Memory;
99

1010
namespace Microsoft.Data.SqlClient
1111
{
@@ -35,7 +35,7 @@ internal class ColumnMasterKeyMetadataSignatureVerificationCache
3535

3636
private ColumnMasterKeyMetadataSignatureVerificationCache()
3737
{
38-
_cache = new MemoryCache(_className);
38+
_cache = new MemoryCache(new MemoryCacheOptions());
3939
_inTrim = 0;
4040
}
4141

@@ -46,17 +46,15 @@ private ColumnMasterKeyMetadataSignatureVerificationCache()
4646
/// <param name="masterKeyPath">Key Path for CMK</param>
4747
/// <param name="allowEnclaveComputations">boolean indicating whether the key can be sent to enclave</param>
4848
/// <param name="signature">Signature for the CMK metadata</param>
49-
/// <returns>null if the data is not found in cache otherwise returns true/false indicating signature verification success/failure</returns>
50-
internal bool? GetSignatureVerificationResult(string keyStoreName, string masterKeyPath, bool allowEnclaveComputations, byte[] signature)
49+
internal bool GetSignatureVerificationResult(string keyStoreName, string masterKeyPath, bool allowEnclaveComputations, byte[] signature)
5150
{
52-
5351
ValidateStringArgumentNotNullOrEmpty(masterKeyPath, _masterkeypathArgumentName, _getSignatureVerificationResultMethodName);
5452
ValidateStringArgumentNotNullOrEmpty(keyStoreName, _keyStoreNameArgumentName, _getSignatureVerificationResultMethodName);
5553
ValidateSignatureNotNullOrEmpty(signature, _getSignatureVerificationResultMethodName);
5654

5755
string cacheLookupKey = GetCacheLookupKey(masterKeyPath, allowEnclaveComputations, signature, keyStoreName);
5856

59-
return _cache.Get(cacheLookupKey) as bool?;
57+
return _cache.TryGetValue<bool>(cacheLookupKey, out bool value);
6058
}
6159

6260
/// <summary>
@@ -69,7 +67,6 @@ private ColumnMasterKeyMetadataSignatureVerificationCache()
6967
/// <param name="result">result indicating signature verification success/failure</param>
7068
internal void AddSignatureVerificationResult(string keyStoreName, string masterKeyPath, bool allowEnclaveComputations, byte[] signature, bool result)
7169
{
72-
7370
ValidateStringArgumentNotNullOrEmpty(masterKeyPath, _masterkeypathArgumentName, _addSignatureVerificationResultMethodName);
7471
ValidateStringArgumentNotNullOrEmpty(keyStoreName, _keyStoreNameArgumentName, _addSignatureVerificationResultMethodName);
7572
ValidateSignatureNotNullOrEmpty(signature, _addSignatureVerificationResultMethodName);
@@ -79,7 +76,11 @@ internal void AddSignatureVerificationResult(string keyStoreName, string masterK
7976
TrimCacheIfNeeded();
8077

8178
// By default evict after 10 days.
82-
_cache.Set(cacheLookupKey, result, DateTimeOffset.UtcNow.AddDays(10));
79+
MemoryCacheEntryOptions options = new MemoryCacheEntryOptions
80+
{
81+
AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(10)
82+
};
83+
_cache.Set<bool>(cacheLookupKey, result, options);
8384
}
8485

8586
private void ValidateSignatureNotNullOrEmpty(byte[] signature, string methodName)
@@ -115,15 +116,17 @@ private void ValidateStringArgumentNotNullOrEmpty(string stringArgValue, string
115116
private void TrimCacheIfNeeded()
116117
{
117118
// If the size of the cache exceeds the threshold, set that we are in trimming and trim the cache accordingly.
118-
long currentCacheSize = _cache.GetCount();
119+
long currentCacheSize = _cache.Count;
119120
if ((currentCacheSize > _cacheSize + _cacheTrimThreshold) && (0 == Interlocked.CompareExchange(ref _inTrim, 1, 0)))
120121
{
121122
try
122123
{
123-
_cache.Trim((int)(((double)(currentCacheSize - _cacheSize) / (double)currentCacheSize) * 100));
124+
// Example: 2301 - 2000 = 301; 301 / 2301 = 0.1308 * 100 = 13% compacting
125+
_cache.Compact((((double)(currentCacheSize - _cacheSize) / (double)currentCacheSize) * 100));
124126
}
125127
finally
126128
{
129+
// Reset _inTrim flag
127130
Interlocked.CompareExchange(ref _inTrim, 0, 1);
128131
}
129132
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy