https://github.com/charleszipp/azure-durable-entities-encryption
Demonstrates how application level encryption can be implemented for durable entities
https://github.com/charleszipp/azure-durable-entities-encryption
azure-functions azure-functions-v3 durable-entities durable-functions
Last synced: about 1 year ago
JSON representation
Demonstrates how application level encryption can be implemented for durable entities
- Host: GitHub
- URL: https://github.com/charleszipp/azure-durable-entities-encryption
- Owner: charleszipp
- License: mit
- Created: 2020-05-13T20:23:16.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2020-05-18T13:46:41.000Z (about 6 years ago)
- Last Synced: 2025-02-23T23:41:20.532Z (over 1 year ago)
- Topics: azure-functions, azure-functions-v3, durable-entities, durable-functions
- Language: C#
- Homepage:
- Size: 23.4 KB
- Stars: 6
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Application Level Encryption for Azure Durable Entities
The code within this repository demonstrates a means by which durable entity state can be encrypted at the application layer. A key is configured for the function app. That key is then used during the serialization process to encrypt any properties annotated with the `Encrypted` attribute.
## Dependencies
- [.NET Core 3.1](https://dotnet.microsoft.com/download)
- [Azure Storage Emulator](https://go.microsoft.com/fwlink/?linkid=717179&clcid=0x409)
- [Azure Storage Explorer](https://azure.microsoft.com/en-us/features/storage-explorer/)
## Bootstrapping Encryption
As part of the `Configure` method in the `FunctionsStartup` class register the dependencies necessary to enable encryption
Register how to resolve the encryption options/configuration. The key is expected to come from a key management solution such as Azure Key Vault. See [Azure Key Vault Configuration Provider in ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/security/key-vault-configuration?view=aspnetcore-3.1) for how to retrieve secrets from Azure Key Vault.
```csharp
builder.Services.AddSingleton(sp => new EncryptionOptions(config["ENCRYPTIONKey"]));
```
Register the implementation of `IEncryptionService` to be used
```csharp
builder.Services.AddSingleton();
```
Register customization to `IMessageSerializerSettingsFactory` to customize how durable functions serializes the state
```csharp
//necessary to engage custom settings during serialization
builder.Services.AddSingleton();
builder.Services.AddSingleton(sp => new JsonSerializerSettings { ContractResolver = sp.GetService() });
builder.Services.AddSingleton();
```
Register customization to Json.NET's default serialization settings to customize how durable functions deserializes the state
```csharp
//necessary to engage custom settings during deserialization
JsonConvert.DefaultSettings = () => builder.Services.BuildServiceProvider().GetService();
```
### Annotate Properties for Encryption
To indicate which entity properties should be encrypted, annotate the properties with the `Encrypted` attribute. The `EncryptedContractResolver` will scan for this attribute to determine which properties need to be encrypted/decrypted.
```csharp
[JsonObject(MemberSerialization = MemberSerialization.OptOut)]
public class AccountEntity : IAccountEntity
{
// ensure account number is encrypted when saved
[Encrypted]
public string AccountNumber { get; set; }
public void Set(string accountNumber) => AccountNumber = accountNumber;
[FunctionName(nameof(AccountEntity))]
public static Task Run([EntityTrigger] IDurableEntityContext ctx) => ctx.DispatchAsync();
}
```
### Testing The Encryption
To test the encryption/decryption in this sample, the following two endpoints can be used.
#### PUT /accounts/{accountId}
This will set the account number to a value for the account of the provided `accountId`.
The value when saved to Azure Table Storage should be encrypted. The following is from the Hub Instances table; Input column for the row that represents the Durable Entity.
```json
{"exists":true,"state":"{\"AccountNumber\":\"A1k9ufGmHFMgM83sE/8EdCMls/TLeXbWDEU32ZXrhE4=\"}","sorter":{}}
```
#### GET /accounts/{accountId}
This will retrieve the account entity for the account of the provided `accountId`.
The returned value should be decrypted
```json
{ "accountNumber": "123ABC" }
```
### Customize the Encryption
To customize the specific encryption algorithm used, a new implementation of `IEncryptionService` can be created. This will not change what properties are selected for encryption. It will only change how the properties annotated are encrypted & decrypted. If for example, something other than `AesManaged` is needed, a new implementation of IEncryptionService could be created to use a different cryptography implementation.
```csharp
public interface IEncryptionService
{
string Decrypt(string value);
string Encrypt(string value);
}
public class MyEncryptionService
{
public string Encrypt(string value)
{
//todo: return encrypted value
}
public string Decrypt(string value)
{
//todo: return the decrypted value
}
}
```
Then, register the new implementation with the IServiceProvider
```csharp
builder.Services.AddSingleton();
```