Skip to content

Commit

Permalink
Prepare RTM (#487)
Browse files Browse the repository at this point in the history
* Remove preview from workflows

* Bump NSB to v9, fix analyzer errors

* Remove SolutionDir from project file

* Remove Guard and use new language features

* Fix overzealous reformatting disaster

* Tweaks

* Add license notice

* Fix throw helper calls

---------

Co-authored-by: Brandon Ording <bording@gmail.com>
  • Loading branch information
kentdr and bording authored Feb 19, 2024
1 parent e0b3568 commit ff2e0f4
Show file tree
Hide file tree
Showing 15 changed files with 123 additions and 142 deletions.
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ jobs:
uses: actions/setup-dotnet@v4.0.0
with:
dotnet-version: 8.0.x
dotnet-quality: 'preview'
- name: Build
run: dotnet build src --configuration Release
- name: Upload packages
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ jobs:
uses: actions/setup-dotnet@v4.0.0
with:
dotnet-version: 8.0.x
dotnet-quality: 'preview'
- name: Build
run: dotnet build src --configuration Release
- name: Sign NuGet packages
Expand Down
30 changes: 30 additions & 0 deletions THIRD-PARTY-NOTICES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
License notice for rhino-esb
---------------------------------------

https://github.com/hibernating-rhinos/rhino-esb/blob/master/license.txt

Copyright (c) 2005 - 2009 Ayende Rahien (ayende@ayende.com)
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Ayende Rahien nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1 change: 1 addition & 0 deletions src/AcceptanceTests/Infrastructure/DefaultServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public async Task<EndpointConfiguration> GetConfiguration(RunDescriptor runDescr
typesToInclude.AddRange(types);

var configuration = new EndpointConfiguration(endpointConfiguration.EndpointName);
configuration.UseSerialization<SystemJsonSerializer>();

configuration.TypesToIncludeInScan(typesToInclude);
configuration.EnableInstallers();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<ItemGroup>
<PackageReference Include="GitHubActionsTestLogger" Version="2.3.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="NServiceBus.AcceptanceTesting" Version="9.0.0-alpha.1" />
<PackageReference Include="NServiceBus.AcceptanceTesting" Version="9.0.0" />
<PackageReference Include="NUnit" Version="3.14.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
</ItemGroup>
Expand Down
118 changes: 54 additions & 64 deletions src/MessageProperty/AesEncryptionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public AesEncryptionService(
{
encryptionKeyIdentifier, key
}
}, new List<byte[]>(0))
}, [])
{
}

Expand All @@ -62,7 +62,7 @@ public AesEncryptionService(
/// <param name="keys">A dictionary of available encryption keys and their identifiers for encryption and decryption.</param>
public AesEncryptionService(
string encryptionKeyIdentifier,
IDictionary<string, byte[]> keys) : this(encryptionKeyIdentifier, keys, new List<byte[]>(0))
IDictionary<string, byte[]> keys) : this(encryptionKeyIdentifier, keys, [])
{
}

Expand All @@ -77,9 +77,9 @@ public AesEncryptionService(
IDictionary<string, byte[]> keys,
IList<byte[]> decryptionKeys)
{
Guard.AgainstNullAndEmpty(nameof(encryptionKeyIdentifier), encryptionKeyIdentifier);
Guard.AgainstNull(nameof(keys), keys);
Guard.AgainstNull(nameof(decryptionKeys), decryptionKeys);
ArgumentException.ThrowIfNullOrWhiteSpace(encryptionKeyIdentifier);
ArgumentNullException.ThrowIfNull(keys);
ArgumentNullException.ThrowIfNull(decryptionKeys);

this.encryptionKeyIdentifier = encryptionKeyIdentifier;
this.decryptionKeys = decryptionKeys;
Expand Down Expand Up @@ -127,28 +127,26 @@ public EncryptedValue Encrypt(string value, IOutgoingLogicalMessageContext conte

AddKeyIdentifierHeader(context);

using (var aes = Aes.Create())
using var aes = Aes.Create();

aes.Key = encryptionKey;
aes.Mode = CipherMode.CBC;
ConfigureIV(aes);

using var encryptor = aes.CreateEncryptor();
using var memoryStream = new MemoryStream();
using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
using var writer = new StreamWriter(cryptoStream);

writer.Write(value);
writer.Flush();
cryptoStream.Flush();
cryptoStream.FlushFinalBlock();
return new EncryptedValue
{
aes.Key = encryptionKey;
aes.Mode = CipherMode.CBC;
ConfigureIV(aes);

using (var encryptor = aes.CreateEncryptor())
using (var memoryStream = new MemoryStream())
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
using (var writer = new StreamWriter(cryptoStream))
{
writer.Write(value);
writer.Flush();
cryptoStream.Flush();
cryptoStream.FlushFinalBlock();
return new EncryptedValue
{
EncryptedBase64Value = Convert.ToBase64String(memoryStream.ToArray()),
Base64Iv = Convert.ToBase64String(aes.IV)
};
}
}
EncryptedBase64Value = Convert.ToBase64String(memoryStream.ToArray()),
Base64Iv = Convert.ToBase64String(aes.IV)
};
}

string DecryptUsingKeyIdentifier(EncryptedValue encryptedValue, string keyIdentifier)
Expand Down Expand Up @@ -191,20 +189,21 @@ string DecryptUsingAllKeys(EncryptedValue encryptedValue)
static string Decrypt(EncryptedValue encryptedValue, byte[] key)
{
var iv = Convert.FromBase64String(encryptedValue.Base64Iv);
using (var aes = Aes.Create())
{
var encrypted = Convert.FromBase64String(encryptedValue.EncryptedBase64Value);
aes.IV = iv;
aes.Mode = CipherMode.CBC;
aes.Key = key;
using (var decryptor = aes.CreateDecryptor())
using (var memoryStream = new MemoryStream(encrypted))
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
using (var reader = new StreamReader(cryptoStream))
{
return reader.ReadToEnd();
}
}

var encrypted = Convert.FromBase64String(encryptedValue.EncryptedBase64Value);

using var aes = Aes.Create();

aes.IV = iv;
aes.Mode = CipherMode.CBC;
aes.Key = key;

using var decryptor = aes.CreateDecryptor();
using var memoryStream = new MemoryStream(encrypted);
using var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
using var reader = new StreamReader(cryptoStream);

return reader.ReadToEnd();
}

static void VerifyExpiredKeys(IList<byte[]> keys)
Expand Down Expand Up @@ -233,48 +232,39 @@ static void VerifyEncryptionKey(byte[] key)

static bool IsValidKey(byte[] key)
{
using (var aes = Aes.Create())
{
var bitLength = key.Length * 8;
using var aes = Aes.Create();

var maxValidKeyBitLength = aes.LegalKeySizes.Max(keyLength => keyLength.MaxSize);
if (bitLength < maxValidKeyBitLength)
{
Log.WarnFormat("Encryption key is {0} bits which is less than the maximum allowed {1} bits. Consider using a {2}-bit encryption key to obtain the maximum cipher strength", bitLength, maxValidKeyBitLength, maxValidKeyBitLength);
}
var bitLength = key.Length * 8;

return aes.ValidKeySize(bitLength);
var maxValidKeyBitLength = aes.LegalKeySizes.Max(keyLength => keyLength.MaxSize);
if (bitLength < maxValidKeyBitLength)
{
Log.WarnFormat("Encryption key is {0} bits which is less than the maximum allowed {1} bits. Consider using a {2}-bit encryption key to obtain the maximum cipher strength", bitLength, maxValidKeyBitLength, maxValidKeyBitLength);
}

return aes.ValidKeySize(bitLength);
}

/// <summary>
/// Adds the key identifier of the currently used encryption key to the outgoing message's headers.
/// </summary>
protected internal virtual void AddKeyIdentifierHeader(IOutgoingLogicalMessageContext context)
{
context.Headers[EncryptionHeaders.EncryptionKeyIdentifier] = encryptionKeyIdentifier;
}
protected internal virtual void AddKeyIdentifierHeader(IOutgoingLogicalMessageContext context) => context.Headers[EncryptionHeaders.EncryptionKeyIdentifier] = encryptionKeyIdentifier;

/// <summary>
/// Tries to locate an encryption key identifier from an incoming message.
/// </summary>
protected internal virtual bool TryGetKeyIdentifierHeader(out string keyIdentifier, IIncomingLogicalMessageContext context)
{
return context.Headers.TryGetValue(EncryptionHeaders.EncryptionKeyIdentifier, out keyIdentifier);
}
protected internal virtual bool TryGetKeyIdentifierHeader(out string keyIdentifier, IIncomingLogicalMessageContext context) => context.Headers.TryGetValue(EncryptionHeaders.EncryptionKeyIdentifier, out keyIdentifier);

/// <summary>
/// Configures the initialization vector.
/// </summary>
protected internal virtual void ConfigureIV(Aes aes)
{
aes.GenerateIV();
}
protected internal virtual void ConfigureIV(Aes aes) => aes.GenerateIV();

readonly string encryptionKeyIdentifier;
IList<byte[]> decryptionKeys; // Required, as we decrypt in the configured order.
byte[] encryptionKey;
IDictionary<string, byte[]> keys;
readonly IList<byte[]> decryptionKeys; // Required, as we decrypt in the configured order.
readonly byte[] encryptionKey;
readonly IDictionary<string, byte[]> keys;

static readonly ILog Log = LogManager.GetLogger<AesEncryptionService>();
}
}
22 changes: 8 additions & 14 deletions src/MessageProperty/EncryptedString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public EncryptedString()
/// </summary>
public EncryptedString(SerializationInfo info, StreamingContext context)
{
Guard.AgainstNull(nameof(info), info);
ArgumentNullException.ThrowIfNull(info);
EncryptedValue = info.GetValue("EncryptedValue", typeof(EncryptedValue)) as EncryptedValue;
}

Expand All @@ -35,8 +35,8 @@ public EncryptedString(SerializationInfo info, StreamingContext context)
/// </summary>
public EncryptedValue EncryptedValue
{
get { return encryptedValue; }
set { encryptedValue = value; }
get => encryptedValue;
set => encryptedValue = value;
}

// we need to duplicate to make versions > 3.2.7 backwards compatible with 2.X
Expand All @@ -46,28 +46,22 @@ public EncryptedValue EncryptedValue
/// </summary>
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
Guard.AgainstNull(nameof(info), info);
ArgumentNullException.ThrowIfNull(info);
info.AddValue("EncryptedValue", EncryptedValue);
}

/// <summary>
/// Gets the string value from the WireEncryptedString.
/// </summary>
public static implicit operator string(EncryptedString s)
{
return s?.Value;
}
public static implicit operator string(EncryptedString s) => s?.Value;

/// <summary>
/// Creates a new WireEncryptedString from the given string.
/// </summary>
public static implicit operator EncryptedString(string s)
public static implicit operator EncryptedString(string s) => new()
{
return new EncryptedString
{
Value = s
};
}
Value = s
};

EncryptedValue encryptedValue;
}
Expand Down
15 changes: 6 additions & 9 deletions src/MessageProperty/EncryptionConfigurationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ public static class EncryptionConfigurationExtensions
/// <summary>
/// Enable message property encryption using the given encryption service.
/// </summary>
/// <param name="configuration">The endpoint configurartion to extend.</param>
/// <param name="configuration">The endpoint configuration to extend.</param>
/// <param name="encryptionService">The encryption service used to encrypt and decrypt message properties.</param>
public static void EnableMessagePropertyEncryption(this EndpointConfiguration configuration, IEncryptionService encryptionService)
{
Guard.AgainstNull(nameof(configuration), configuration);
Guard.AgainstNull(nameof(encryptionService), encryptionService);
ArgumentNullException.ThrowIfNull(configuration);
ArgumentNullException.ThrowIfNull(encryptionService);

configuration.GetSettings().Set(EncryptionServiceConfigurationKey, encryptionService);
configuration.EnableFeature<MessagePropertyEncryption>();
Expand All @@ -27,21 +27,18 @@ public static void EnableMessagePropertyEncryption(this EndpointConfiguration co
/// <summary>
/// Enable message property encryption using the given encryption service.
/// </summary>
/// <param name="configuration">The endpoint configurartion to extend.</param>
/// <param name="configuration">The endpoint configuration to extend.</param>
/// <param name="encryptionService">The encryption service used to encrypt and decrypt message properties.</param>
/// <param name="encryptedPropertyConvention">The convention which defines which properties should be encrypted. By default, all properties of type <see cref="EncryptedString"/> will be encrypted.</param>
public static void EnableMessagePropertyEncryption(this EndpointConfiguration configuration, IEncryptionService encryptionService, Func<PropertyInfo, bool> encryptedPropertyConvention)
{
Guard.AgainstNull(nameof(encryptedPropertyConvention), encryptedPropertyConvention);
ArgumentNullException.ThrowIfNull(encryptedPropertyConvention);

configuration.EnableMessagePropertyEncryption(encryptionService);
configuration.GetSettings().Set(new IsEncryptedPropertyConvention(encryptedPropertyConvention));
}

internal static IEncryptionService GetEncryptionService(this IReadOnlySettings settings)
{
return settings.Get<IEncryptionService>(EncryptionServiceConfigurationKey);
}
internal static IEncryptionService GetEncryptionService(this IReadOnlySettings settings) => settings.Get<IEncryptionService>(EncryptionServiceConfigurationKey);

const string EncryptionServiceConfigurationKey = "NServiceBus.Encryption.MessageProperty.EncryptionService";
}
Expand Down
4 changes: 2 additions & 2 deletions src/MessageProperty/EncryptionInspector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@ static List<MemberInfo> GetFieldsAndProperties(object target)

IsEncryptedPropertyConvention encryptedPropertyConvention;

static List<MemberInfo> NoMembers = new List<MemberInfo>(0);
static List<MemberInfo> NoMembers = [];

static List<Tuple<object, MemberInfo>> AlreadyVisited = new List<Tuple<object, MemberInfo>>(0);
static List<Tuple<object, MemberInfo>> AlreadyVisited = [];

static ConcurrentDictionary<RuntimeTypeHandle, List<MemberInfo>> cache = new ConcurrentDictionary<RuntimeTypeHandle, List<MemberInfo>>();
}
Expand Down
12 changes: 4 additions & 8 deletions src/MessageProperty/IsEncrytedPropertyConvention.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,12 @@
/// <summary>
/// Message convention definitions.
/// </summary>
class IsEncryptedPropertyConvention
class IsEncryptedPropertyConvention(Func<PropertyInfo, bool> isEncryptedPropertyAction)
{
public IsEncryptedPropertyConvention(Func<PropertyInfo, bool> isEncryptedPropertyAction)
{
IsEncryptedPropertyAction = isEncryptedPropertyAction;
}

public bool IsEncryptedProperty(PropertyInfo property)
{
Guard.AgainstNull(nameof(property), property);
ArgumentNullException.ThrowIfNull(property);

try
{
//the message mutator will cache the whole message so we don't need to cache here
Expand All @@ -27,6 +23,6 @@ public bool IsEncryptedProperty(PropertyInfo property)
}
}

Func<PropertyInfo, bool> IsEncryptedPropertyAction;
readonly Func<PropertyInfo, bool> IsEncryptedPropertyAction = isEncryptedPropertyAction;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SolutionDir)NServiceBus.snk</AssemblyOriginatorKeyFile>
<AssemblyOriginatorKeyFile>..\NServiceBus.snk</AssemblyOriginatorKeyFile>
<Description>Selectively encrypt NServiceBus message properties</Description>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="NServiceBus" Version="9.0.0-alpha.1" />
<PackageReference Include="Particular.Packaging" Version="4.0.0" PrivateAssets="All" />
<PackageReference Include="NServiceBus" Version="[9.0.0, 10.0.0)" />
<PackageReference Include="Fody" Version="6.8.0" PrivateAssets="All" />
<PackageReference Include="Obsolete.Fody" Version="5.3.0" PrivateAssets="All" />
<PackageReference Include="Particular.Packaging" Version="4.0.0" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit ff2e0f4

Please sign in to comment.