Encryption
The end-to-end message encryption in Silverback is handled transparently in the producer and consumer and works independently from the used serializer or other features like chunking.
Symmetric encryption
Enabling the end-to-end encryption using a symmetric algorithm just require an extra configuration in the endpoint.
public class MyEndpointsConfigurator : IEndpointsConfigurator
{
public void Configure(IEndpointsConfigurationBuilder builder) =>
builder
.AddKafkaEndpoints(endpoints => endpoints
.Configure(config =>
{
config.BootstrapServers = "PLAINTEXT://kafka:9092";
})
.AddOutbound<InventoryEvent>(endpoint => endpoint
.ProduceTo("inventory-events")
.EncryptUsingAes(encryptionKey))
.AddInbound(endpoint => endpoint
.ConsumeFrom("order-events")
.Configure(config =>
{
config.GroupId = "my-consumer";
})
.DecryptUsingAes(encryptionKey)));
}
The SymmetricEncryptionSettings class encapsulates all common settings of a symmetric algorithm (block size, initialization vector, ...).
The AlgorithmName
is used to load the algorithm implementation using the SymmetricAlgorithm.Create(string) method. Refer to the SymmetricAlgorithm class documentation to see which implementations are available in .net core are. Silverback uses Aes by default.
Random initialization vector
If no static initialization vector is provided, a random one is automatically generated per each message and prepended to the actual encrypted message. The consumer will automatically extract and use it.
It is recommended to stick to this default behavior, for increased security.
Ket rotation
You can smoothly rotate the key being used to encrypt the messages.
In the outbound endpoint you can specify the current key identifier to be submitted as header, while in the inbound endpoint a custom function can be used to provide the correct key, depending on the value in the header. This simple mechanism allows to consume messages that were encrypted using different keys, enabling key rotation and supporting a rolling update of the producers.
public class MyEndpointsConfigurator : IEndpointsConfigurator
{
public void Configure(IEndpointsConfigurationBuilder builder) =>
builder
.AddKafkaEndpoints(endpoints => endpoints
.Configure(config =>
{
config.BootstrapServers = "PLAINTEXT://kafka:9092";
})
.AddOutbound<InventoryEvent>(endpoint => endpoint
.ProduceTo("inventory-events")
.EncryptUsingAes(encryptionKey, "key1"))
.AddInbound(endpoint => endpoint
.ConsumeFrom("order-events")
.Configure(config =>
{
config.GroupId = "my-consumer";
})
.DecryptUsingAes(keyIdentifier =>
{
switch (keyIdentifier)
{
case "key1":
return encryptionKey1;
default:
return encryptionKey2;
}
})));
}