From 39a75284cc8abcc0f1f7bcfd18185ecf8b2b5cde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Thu, 11 Jun 2020 16:20:32 +0200 Subject: [PATCH] Enable FxCop code analysis --- Directory.Build.props | 9 +- OpenIddict.sln | 1 + eng/CodeAnalysis.ruleset | 343 ++++++++++++++++++ eng/Versions.props | 2 + .../Caches/OpenIddictApplicationCache.cs | 1 + .../Caches/OpenIddictAuthorizationCache.cs | 1 + .../Caches/OpenIddictScopeCache.cs | 1 + .../Caches/OpenIddictTokenCache.cs | 1 + .../Managers/OpenIddictApplicationManager.cs | 3 + .../OpenIddictServerBuilder.cs | 15 + .../OpenIddictValidationBuilder.cs | 3 + .../Primitives/OpenIddictParameterTests.cs | 2 +- .../OpenIddictMongoDbContextTests.cs | 18 +- ...ctServerAspNetCoreIntegrationTestServer.cs | 3 + ...nIddictServerAspNetCoreIntegrationTests.cs | 3 + .../OpenIddictServerIntegrationTestClient.cs | 5 +- ...nIddictServerIntegrationTests.Discovery.cs | 2 +- ...enIddictServerOwinIntegrationTestServer.cs | 3 + .../OpenIddictServerOwinIntegrationTests.cs | 3 + 19 files changed, 404 insertions(+), 15 deletions(-) create mode 100644 eng/CodeAnalysis.ruleset diff --git a/Directory.Build.props b/Directory.Build.props index 47ab3d0e..2f31401b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -7,11 +7,12 @@ $(NoWarn);CS1591;NU5128 true true + $(MSBuildThisFileDirectory)eng\CodeAnalysis.ruleset OpenIddict - $(MSBuildThisFileDirectory)\eng\key.snk + $(MSBuildThisFileDirectory)eng\key.snk true false false @@ -64,8 +65,10 @@ $([System.DateTime]::Now.ToString(yyyyMMdd)).$(_AppVeyorBuildRevision) - - + + + diff --git a/OpenIddict.sln b/OpenIddict.sln index 974ad7dd..c491c42c 100644 --- a/OpenIddict.sln +++ b/OpenIddict.sln @@ -59,6 +59,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenIddict.Owin", "src\Open EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "eng", "eng", "{6E8E862C-3F26-47D9-9C20-E3E87FD7CDFC}" ProjectSection(SolutionItems) = preProject + eng\CodeAnalysis.ruleset = eng\CodeAnalysis.ruleset eng\key.snk = eng\key.snk eng\Signing.props = eng\Signing.props eng\Version.Details.xml = eng\Version.Details.xml diff --git a/eng/CodeAnalysis.ruleset b/eng/CodeAnalysis.ruleset new file mode 100644 index 00000000..443912d2 --- /dev/null +++ b/eng/CodeAnalysis.ruleset @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/eng/Versions.props b/eng/Versions.props index 2c2dc38d..6e7db7a4 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -35,6 +35,7 @@ 1.8.6.7 4.7.0 6.4.0 + 3.0.0 2019.1.3 6.6.0 1.7.0 @@ -42,6 +43,7 @@ 2.9.0 4.13.1 4.1.0 + 1.0.0 3.2.0 4.7.1 4.5.4 diff --git a/src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs b/src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs index f4f11f5a..f633e493 100644 --- a/src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs +++ b/src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs @@ -385,6 +385,7 @@ namespace OpenIddict.Core if (_signals.TryRemove(identifier, out CancellationTokenSource signal)) { signal.Cancel(); + signal.Dispose(); } } diff --git a/src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs b/src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs index a8c68e19..5268f22a 100644 --- a/src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs +++ b/src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs @@ -609,6 +609,7 @@ namespace OpenIddict.Core if (_signals.TryRemove(identifier, out CancellationTokenSource signal)) { signal.Cancel(); + signal.Dispose(); } } diff --git a/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs b/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs index 56d205f2..3dab926b 100644 --- a/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs +++ b/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs @@ -347,6 +347,7 @@ namespace OpenIddict.Core if (_signals.TryRemove(identifier, out CancellationTokenSource signal)) { signal.Cancel(); + signal.Dispose(); } } diff --git a/src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs b/src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs index dfffc62a..b8c98056 100644 --- a/src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs +++ b/src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs @@ -698,6 +698,7 @@ namespace OpenIddict.Core if (_signals.TryRemove(identifier, out CancellationTokenSource signal)) { signal.Cancel(); + signal.Dispose(); } } diff --git a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs index 80de65bd..a880ba88 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs @@ -20,6 +20,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; +using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute; #if !SUPPORTS_KEY_DERIVATION_WITH_SPECIFIED_HASH_ALGORITHM using Org.BouncyCastle.Crypto; @@ -1329,6 +1330,8 @@ namespace OpenIddict.Core } } + [SuppressMessage("Security", "CA5379:Do not use weak key derivation function algorithm", + Justification = "The SHA-1 digest algorithm is still supported for backward compatibility.")] private static byte[] DeriveKey(string secret, ReadOnlySpan salt, HashAlgorithmName algorithm, int iterations, int length) { diff --git a/src/OpenIddict.Server/OpenIddictServerBuilder.cs b/src/OpenIddict.Server/OpenIddictServerBuilder.cs index b16031eb..3884a285 100644 --- a/src/OpenIddict.Server/OpenIddictServerBuilder.cs +++ b/src/OpenIddict.Server/OpenIddictServerBuilder.cs @@ -18,6 +18,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.IdentityModel.Tokens; using OpenIddict.Server; using static OpenIddict.Abstractions.OpenIddictConstants; +using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute; namespace Microsoft.Extensions.DependencyInjection { @@ -213,6 +214,8 @@ namespace Microsoft.Extensions.DependencyInjection /// /// The subject name associated with the certificate. /// The . + [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", + Justification = "The X.509 certificate is attached to the server options.")] public OpenIddictServerBuilder AddDevelopmentEncryptionCertificate([NotNull] X500DistinguishedName subject) { if (subject == null) @@ -341,6 +344,8 @@ namespace Microsoft.Extensions.DependencyInjection return new SymmetricSecurityKey(data); } + [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", + Justification = "The generated RSA key is attached to the server options.")] static RsaSecurityKey CreateRsaSecurityKey(int size) { #if SUPPORTS_DIRECT_KEY_CREATION_WITH_SPECIFIED_SIZE @@ -486,6 +491,8 @@ namespace Microsoft.Extensions.DependencyInjection /// to store the private key of the certificate. /// /// The . + [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", + Justification = "The X.509 certificate is attached to the server options.")] public OpenIddictServerBuilder AddEncryptionCertificate( [NotNull] Stream stream, [NotNull] string password, X509KeyStorageFlags flags) { @@ -662,6 +669,8 @@ namespace Microsoft.Extensions.DependencyInjection /// /// The subject name associated with the certificate. /// The . + [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", + Justification = "The X.509 certificate is attached to the server options.")] public OpenIddictServerBuilder AddDevelopmentSigningCertificate([NotNull] X500DistinguishedName subject) { if (subject == null) @@ -755,6 +764,8 @@ namespace Microsoft.Extensions.DependencyInjection /// /// The algorithm associated with the signing key. /// The . + [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", + Justification = "The X.509 certificate is attached to the server options.")] public OpenIddictServerBuilder AddEphemeralSigningKey([NotNull] string algorithm) { if (string.IsNullOrEmpty(algorithm)) @@ -807,6 +818,8 @@ namespace Microsoft.Extensions.DependencyInjection default: throw new InvalidOperationException("The specified algorithm is not supported."); } + [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", + Justification = "The generated RSA key is attached to the server options.")] static RsaSecurityKey CreateRsaSecurityKey(int size) { #if SUPPORTS_DIRECT_KEY_CREATION_WITH_SPECIFIED_SIZE @@ -952,6 +965,8 @@ namespace Microsoft.Extensions.DependencyInjection /// to store the private key of the certificate. /// /// The . + [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", + Justification = "The X.509 certificate is attached to the server options.")] public OpenIddictServerBuilder AddSigningCertificate( [NotNull] Stream stream, [NotNull] string password, X509KeyStorageFlags flags) { diff --git a/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs b/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs index e4fe851e..c7289835 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs @@ -17,6 +17,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Tokens; using OpenIddict.Validation; +using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute; namespace Microsoft.Extensions.DependencyInjection { @@ -303,6 +304,8 @@ namespace Microsoft.Extensions.DependencyInjection /// to store the private key of the certificate. /// /// The . + [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", + Justification = "The X.509 certificate is attached to the server options.")] public OpenIddictValidationBuilder AddEncryptionCertificate( [NotNull] Stream stream, [NotNull] string password, X509KeyStorageFlags flags) { diff --git a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs index 44e6cac7..d6b0a115 100644 --- a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs +++ b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs @@ -499,7 +499,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives { // Arrange, act and assert Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(string.Empty))); - Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(new string[0]))); + Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(Array.Empty()))); Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter( JsonSerializer.Deserialize("[]")))); diff --git a/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs b/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs index ad1bcd56..82e5ac48 100644 --- a/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs +++ b/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs @@ -30,7 +30,7 @@ namespace OpenIddict.MongoDb.Tests var options = Mock.Of>(); var token = new CancellationToken(canceled: true); - var context = new OpenIddictMongoDbContext(options, provider); + using var context = new OpenIddictMongoDbContext(options, provider); // Act and assert var exception = await Assert.ThrowsAsync(async delegate @@ -51,7 +51,7 @@ namespace OpenIddict.MongoDb.Tests var database = GetDatabase(); var options = Mock.Of>(); - var context = new OpenIddictMongoDbContext(options, provider); + using var context = new OpenIddictMongoDbContext(options, provider); // Act and assert var exception = await Assert.ThrowsAsync(async delegate @@ -92,7 +92,7 @@ namespace OpenIddict.MongoDb.Tests InitializationTimeout = TimeSpan.FromMilliseconds(50) }); - var context = new OpenIddictMongoDbContext(options, provider); + using var context = new OpenIddictMongoDbContext(options, provider); // Act and assert var exception = await Assert.ThrowsAsync(delegate @@ -127,7 +127,7 @@ namespace OpenIddict.MongoDb.Tests Database = database.Object }); - var context = new OpenIddictMongoDbContext(options, provider); + using var context = new OpenIddictMongoDbContext(options, provider); // Act and assert Assert.Same(database.Object, await context.GetDatabaseAsync(CancellationToken.None)); @@ -147,7 +147,7 @@ namespace OpenIddict.MongoDb.Tests Database = null }); - var context = new OpenIddictMongoDbContext(options, provider); + using var context = new OpenIddictMongoDbContext(options, provider); // Act and assert var exception = await Assert.ThrowsAsync(async delegate @@ -181,7 +181,7 @@ namespace OpenIddict.MongoDb.Tests Database = null }); - var context = new OpenIddictMongoDbContext(options, provider); + using var context = new OpenIddictMongoDbContext(options, provider); // Act and assert Assert.Same(database.Object, await context.GetDatabaseAsync(CancellationToken.None)); @@ -202,7 +202,7 @@ namespace OpenIddict.MongoDb.Tests DisableInitialization = true }); - var context = new OpenIddictMongoDbContext(options, provider); + using var context = new OpenIddictMongoDbContext(options, provider); // Act await context.GetDatabaseAsync(CancellationToken.None); @@ -228,7 +228,7 @@ namespace OpenIddict.MongoDb.Tests Database = database.Object }); - var context = new OpenIddictMongoDbContext(options, provider); + using var context = new OpenIddictMongoDbContext(options, provider); // Act and assert Assert.Same(database.Object, await context.GetDatabaseAsync(CancellationToken.None)); @@ -272,7 +272,7 @@ namespace OpenIddict.MongoDb.Tests Database = database.Object }); - var context = new OpenIddictMongoDbContext(options, provider); + using var context = new OpenIddictMongoDbContext(options, provider); // Act and assert await Assert.ThrowsAsync(async () => await context.GetDatabaseAsync(CancellationToken.None)); diff --git a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTestServer.cs b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTestServer.cs index 3a8d8705..586ac727 100644 --- a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTestServer.cs +++ b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTestServer.cs @@ -4,6 +4,7 @@ * the license and the contributors participating to this project. */ +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.Hosting; @@ -39,6 +40,8 @@ namespace OpenIddict.Server.AspNetCore.FunctionalTests public IHost Host { get; } #endif + [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", + Justification = "The caller is responsible of disposing the test client.")] public override ValueTask CreateClientAsync() => new ValueTask( new OpenIddictServerIntegrationTestClient(Server.CreateClient())); diff --git a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs index 08d4902e..f8af0d0f 100644 --- a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs +++ b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Security.Claims; using System.Text.Json; @@ -415,6 +416,8 @@ namespace OpenIddict.Server.AspNetCore.FunctionalTests Assert.Equal("Bob l'Eponge", (string) response["string_parameter"]); } + [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", + Justification = "The caller is responsible of disposing the test server.")] protected override #if SUPPORTS_GENERIC_HOST async diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs index e1798de4..710cb12a 100644 --- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs +++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs @@ -244,7 +244,10 @@ namespace OpenIddict.Server.FunctionalTests "is associated with the HTTP client.", nameof(uri)); } - return await GetResponseAsync(await HttpClient.SendAsync(CreateRequestMessage(request, method, uri))); + using var message = CreateRequestMessage(request, method, uri); + using var response = await HttpClient.SendAsync(message); + + return await GetResponseAsync(response); } private HttpRequestMessage CreateRequestMessage(OpenIddictRequest request, HttpMethod method, Uri uri) diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs index f5026dd1..3a220d85 100644 --- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs +++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs @@ -1306,7 +1306,7 @@ namespace OpenIddict.Server.FunctionalTests } }; - var algorithm = ECDsa.Create(parameters); + using var algorithm = ECDsa.Create(parameters); await using var server = await CreateServerAsync(options => { diff --git a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTestServer.cs b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTestServer.cs index 9aae2a54..49d7f993 100644 --- a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTestServer.cs +++ b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTestServer.cs @@ -4,6 +4,7 @@ * the license and the contributors participating to this project. */ +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Microsoft.Owin.Testing; using OpenIddict.Server.FunctionalTests; @@ -23,6 +24,8 @@ namespace OpenIddict.Server.Owin.FunctionalTests /// public TestServer Server { get; } + [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", + Justification = "The caller is responsible of disposing the test client.")] public override ValueTask CreateClientAsync() => new ValueTask( new OpenIddictServerIntegrationTestClient(Server.HttpClient)); diff --git a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs index 6d1714c6..2b6de1be 100644 --- a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs +++ b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Security.Claims; using System.Text.Json; @@ -298,6 +299,8 @@ namespace OpenIddict.Server.Owin.FunctionalTests Assert.Equal("Bob le Magnifique", (string) response["name"]); } + [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", + Justification = "The caller is responsible of disposing the test server.")] protected override ValueTask CreateServerAsync(Action configuration = null) { var services = new ServiceCollection();