Azure kubernetes - Application with Session management? - azure

I am planning to deploy the Asp.net application that uses session on Azure kubernetes. How do I make sure that the incoming request goes to the same pod where session is created.

It is recommended that apps deployed on Kubernetes has a design following the The Twelve Factor App.
Everything will be easier if the app is stateless and share nothing with other instances. See Twelve Factor App - Processes
Twelve-factor processes are stateless and share-nothing. Any data that needs to persist must be stored in a stateful backing service, typically a database.
Some web systems rely on “sticky sessions” – that is, caching user session data in memory of the app’s process and expecting future requests from the same visitor to be routed to the same process. Sticky sessions are a violation of twelve-factor and should never be used or relied upon. Session state data is a good candidate for a datastore that offers time-expiration, such as Memcached or Redis.
Using Redis is one way to store temporary data belonging to the user.
For authentication, I would recommend to use OpenID Connect with JWT tokens in the Authorization: Bearer <token> header. See e.g. Azure Active Directory B2C for an example of an OpenID Connect provider.

Related

.NET Core Dependency Injection and services that utilize frequently rotated authorization keys

Issue Summary
I have multiple ASP.NET Core applications that connect to Azure resources such as CosmosDB, Azure Storage Queues, Azure Event Hubs, etc. All of these resources can utilize Shared Access Signature (SAS) tokens for authentication. These tokens expire which presents a problem when my application starts up and initializes the service once upon startup via services.AddSingleton<T>() (or a similar option).
For example, what I typically do is read the SAS token from a file upon startup (likely mounted to my pod as a volume in Kubernetes but I am not sure that's terribly relevant). That SAS token is then provided to an Azure Storage Queue Client constructor, like this:
string sharedAccessSignature = File.ReadAllText(pathToSasToken);
services.AddSingleton<Azure.Storage.Queues.QueueClient>((sp) =>
{
return new Azure.Storage.Queues.QueueClient(queueUri,
new AzureSasCredential(sharedAccessSignature),
new Azure.Storage.Queues.QueueClientOptions()
{
MessageEncoding = Azure.Storage.Queues.QueueMessageEncoding.Base64
});
});
Unfortunately, I think this means once my SAS token expires, my QueueClient will no longer be able to connect to my Azure Storage Queue without restarting my whole application. Somehow, I need to re-read an updated SAS token from my file while I remain running. (I have another process running in my cluster that provides SAS tokens to my pods).
Possible Solutions
I figure the IOptionsMonitor approach could be useful but unfortunately, the SDKs for these clients don't accept an IOptionsMonitor<T> in their constructors so they don't seem to be capable of re-reading new tokens at runtime -- at least not using IOptionsMonitor.
Another approach could be to use Transient or Scoped service lifetimes but that requires I use the same service lifetimes in my whole dependency chain... So if I have a singleton like a HostedService running, I cannot resolve a Transient or Scoped service from that without unpredictable results (AFAIK). (Update 12/31/2021 - This is actually not true. Microsoft provides guidance on how to consume a scoped service in a HostedService which is actually a good example that demonstrates how one can use Scoped services and manage the lifetimes on your own).
I could also just manually re-create my clients as my code is running but that seems to defeat the purpose of using the .NET service provider and DI pattern.
Am I missing an obvious solution to this that I'm just not seeing in Microsoft's documentation?
I think you're missing Managed Identities. Rather than trust on SAS tokens, you assign a Managed Identity to your ASP.NET app, and grant access to this identity to connect to the required services.
Benefits:
no need to redeploy / acquire new SAS token when it changes / expires
external users won't be able to impersonate this identity (if someone get access to the SAS token, they will be able to use it outside the scope of your app)
More info:
https://learn.microsoft.com/en-us/azure/storage/blobs/authorize-managed-identity
https://learn.microsoft.com/en-us/azure/cosmos-db/managed-identity-based-authentication
https://learn.microsoft.com/en-us/azure/stream-analytics/event-hubs-managed-identity
https://cmatskas.com/setting-up-managed-identities-for-asp-net-core-web-app-running-on-azure-app-service/

Can I use the same Redis instance for storing sessions from more than one application?

We currently use Redis to store the session of one application currently running on Azure. We use it so when Azure scales the application the session is not stored locally in the application itself. We are in the process of placing another application in Azure too, and I'd like to know if we can use that same Redis instance, or if having two applications storing sessions on the same place might cause issues.
I wouldn't use different keys and the same Redis server and database. Your two web apps become co-joined twins. If one web app acts up, it can tank the other one.
If you're deploying the same web app code to two or more web apps, you could use the same Redis server but different databases within the server. Azure Redis Cache has one server, each with 16 databases. However, databases within the same server share service limits.
Or the absolute best thing to do is firewall the two web apps by using two different Azure Redis cache services.
It depends on your key. If you use a key that is only the user name. Then both applications read the same session state. You could do it by creating a composite key with the application name as part of the key.
I would use a seperate instances:
ensuring unique key names across applications adds complexity and risk
high load on one application can impact other applications
if the Redis instance goes down alle your applications fail

Azure web app session and ARR

I have a MVC application deployed to Azure Web app.The web app required to scale out in multiple instances.
I want to use Session object (ASP.NET) to store some user data etc.(lightweight), so that can be retrieved quickly.I believe, session will be In-Proc with ARR ON setting.
I've the following questions
Is it ok to use session object in Azure web apps ,will it give
guarantee to use same In-Proc session if ARR is on.
If ARR turned off ,Should I use session object?
Because using Session itself makes application slow,what are the
other alternatives to store small data within Azure webapp/MVC(once authenticated user profile
related data) for quick access in application?
Using IN-PROC sessions in the cloud is a strict no. The reason to host to cloud is to have high availability which is done by having a distributed environment.
To answer your question, the ARR-Affinity cookie will affinitize the client requests to a specific instance. However, if the Process restarts or App-Domain recycles, then all the sessions will be lost. This is one of the primary reasons why Out-Proc session state management is suggested.
I would recommend against using In-Proc session state in any cloud scenario. I understand speed is a concern for you. For this consider using Redis Cache. Refer the documentation here: https://learn.microsoft.com/en-us/azure/redis-cache/cache-aspnet-session-state-provider
HTH

how to share Azure mobile service tokens across different web app instances

I am planning to have multiple azure mobile service instances, so the first requirement I have is to share the access token of authenticated user across different app instances. I found this article https://cgillum.tech/2016/03/07/app-service-token-store/ that states that right now we can not share the tokens as it is stored locally on machine, and placing it to blob storage is not recommended for production apps. What is the possible solution I have at this time?
I have read the blog you mentioned about App Service Token Store. As mentioned about where the tokens live:
Internally, all these tokens are stored in your app’s local file storage under D:/home/data/.auth/tokens. The tokens themselves are all encrypted in user-specific .json files using app-specific encryption keys and cryptographically signed as per best practice.
I found this article https://cgillum.tech/2016/03/07/app-service-token-store/ that states that right now we can not share the tokens as it is stored locally on machine.
As Azure-runtime-environment states about the Persisted files that an Azure Web App can deal with:
They are rooted in d:\home, which can also be found using the %HOME% environment variable.
These files are persistent, meaning that you can rely on them staying there until you do something to change them. Also, they are shared between all instances of your site (when you scale it up to multiple instances). Internally, the way this works is that they are stored in Azure Storage instead of living on the local file system.
Moreover, Azure app service would enable ARR Affinity to keep a client subsequent requests talking to the same instance. You could disable the session affinity cookie, then requests would be distributed across all the instances. For more details, you could refer to this blog.
Additionally, I have tried to disable ARR Affinity and scale my mobile service to multiple instances, then I could always browser https://[my-website].azurewebsites.net/.auth/me to retrieve information about the current logged-in user.
Per my understanding, you could accomplish the authentication/authorization by yourself to use auth middle-ware into your app. But, this requires more works to be done. Since the platform takes care of it for you, I assume that you could leverage Easy Auth and Token Store and scale your mobile service to multiple instances without worrying about anything.

Server side state management in Windows Azure

I'm working on a distributed application that runs on Windows Azure, but I'm new of this kind of environment. I have a question about server-side state management.
Where should I store global almost static data?
Because it is a distributed environment if a user makes a request to the application, there is no guarantee that subsequent requests will be routed to the same server and so I think that I should use Sql Azure or Table Storage Session Provider (but I've read that can be performance issues) to store the data.
I can also use Windows Azure AppFabric Caching that enables session maintenance.
What is the better solution to store global information that don't need to be secured? Is there something similar to "Application" (like Application["key"] = value)?
Thanks
Please see my responses on the following thread:
Microsoft Azure .NET 4.5 WebForms App : Session TimeOut / InProc / Single Instance
Specifics are below:
If you want to maintain session state you have to use one of the
following options
SQL Session State Provider using Azure SQL
Azure Table Session State
Session State with Azure Redis Cache
You can find details on how to do this at the following links:
Session State Management in Windows Azure Web Roles
Session state with Azure Redis cache in Azure App Service
The easiest way in my opinion is using Azure Redis Cache as noted in
the link above.
Let me know if this helps!
Definitely at that time perhaps, but now Azure Storage Tables :)

Resources