Part 4 - Implement IXmlRepository for Parameter Store

In the previous sections, you set up the ASP.NET Core MVC project to use DynamoDB as the backing store for the Session middleware. However, the Session middleware encrypts the session cookie it uses to track users with encryption keys that are generated locally and not shared by default. This means that if you have multiple copies of your web application running - on multiple EC2 instances, containers or Lambda functions for example - they cannot decrypt each other’s session cookies. This will break session state unless you configure a load balancer to use “sticky sessions”, which is not always feasible, nor desirable.

Luckily, we can configure ASP.NET Core to use whatever repository we choose to store the encryption keys, so that they can be shared across multiple running instances of an application. You could choose, for instance, to store the keys in a DynamoDB table. However, AWS has a service, called Parameter Store (part of Simple Systems Manager) that can store parameters up to 4K in length, and retrieve them by path. You can optionally choose to encrypt values stored in Parameter Store with AWS Key Management Service (KMS) to keep them secure (recommended for any production environment). For this lab, we’ll just store them as plaintext in order to view them.

Follow the steps below to add an implementation of IXmlRespository that stores cookie encryption keys in AWS Parameter Store.

1. Add the NuGet package, “AWSSDK.SimpleSystemsManagement” to your project.

2. Download the file PsXmlRepository.cs from https://s3-us-west-2.amazonaws.com/dotnet-immersionday/PsXmlRepository.cs

3. Copy the file to the Session folder of your project, and open it in the Visual Studio editor.

Note: This is example code for use with this lab, and should not be considered production-ready. There is no error handling, testing, or other features required for production applications.

4. Review the PsXmlRepository class (in the above file), which implements IXmlRepository. Note that it only has two methods: GetAllElements and StoreElement, plus a constructor. Both methods are called by the Session middleware, not by our own code.

StoreElement takes in a XElement and stores it as a parameter in Parameter Store, with the name set to "CookieEncryptionKey" plus the friendly name (a GUID) passed in by the middleware.  

GetAllElements uses the GetParametersByPathAsync method of Parameter Store to get all parameters that begin with, "CookieEncryptionKey", and returns them as a collection of XElement.

5. Open the Startup.cs file, and add the following four using statements to the top of the file:

   using Amazon.SimpleSystemsManagement;                                                                                                                
   using Microsoft.AspNetCore.DataProtection;                                                                                                           
   using Microsoft.AspNetCore.DataProtection.Repositories;                                                                                              
   using Session;

6. Find the ConfigureServices method, and add the following lines of code after the call to services.AddMvc.

   services.AddAWSService<IAmazonSimpleSystemsManagement>();
   services.AddSingleton<IXmlRepository, PsXmlRepository>();
   var sp = services.BuildServiceProvider();
   services.AddDataProtection().AddKeyManagementOptions(o => o.XmlRepository = sp.GetService<IXmlRepository>());

7. Review the code you just added. It registers the IAmazonSimpleSystemsManagement type with the ASP.NET Core dependency injection framework, it adds a singleton copy of PsXmlRepository to the services middleware collection, and configures the Data Protection options to use that repository to store the encryption keys as XML.

9. In the AWS Management Console, navigate to the AWS Systems Manager console (search for “ssm”), and then click “Parameter Store” at the bottom of the left-navigation menu.

10. You should see a new parameter of type String with a name beginning with “CookieEncryptionKey”. Click on that parameter name to view the contents.

11. Note that the value of the key is XML, which includes a comment warning that the encryption key itself is not encrypted. In a production environment, you would use a parameter of type SecureString, and then assign permissions to the role used by your application to decrypt it.

You could not deploy this web application to a web-server farm, or as multiple containers in Amazon ECS or EKS, or add Lambda support to the project and deploy it to Lambda, and the session state would work across the multiple copies. Also, note that the code you

Actually deploying it to those environments is outside the scope of this lab, but feel free to try it out at home!

##Conclusion

In this lab, you learned how to use DynamoDB as the backing store for ASP.NET Core’s Session middleware, and optionally, to use Parameter Store to enable using the solution for a distributed web application.

You also tested out your solution running locally on your laptop or PC, and looked at the session item(s) in DynamoDB, and optionally looked the encryption key XML as stored in AWS Parameter Store.