vendrhub / vendr-documentation

Documentation for Vendr, the eCommerce solution for Umbraco v8+
MIT License
7 stars 29 forks source link

Licensing in azure app services with deployment slots #107

Open anh-duc-le opened 2 years ago

anh-duc-le commented 2 years ago

We have recently ran into an issue with licenses refreshing on our Azure App Services and our setup for code deployments.

Context: We self-host Umbraco on Azure App Services and do deployments on App Service Deployment Slots to which we release our code builds. After that we swap the staging Deployment Slot with the primary app service to put our changes live.

Problem: The license is automatically refreshed on our primary app service slots, but not on our deployment slots because they exist in a stopped state unless we release our code builds on it.

So when we swap the staging deployment slot with the primary slot after a code deployment, we end up with a potentially outdated license in the wwwroot\umbraco\licenses folder.

Potential solutions: One solution would be to include a step in the release pipeline to download the licenses folder from the primary slot to the deployment slot before we perform the slot swap.

However, a more preferred solution would be to have the option to store the refreshed licenses on a blob storage container. That way there only needs to be one place to refresh and get the licenses from, without depending on duplicating licenses to a deployment slot.

mattbrailsford commented 2 years ago

Hey @anh-duc-le

I don't really know a great deal about Azure infrastructures, but is there no shared location between slots that you can configure the Vendr.Licensing.LicensesDirectory app setting to point to so your licenses can be stored / refreshed into a directory that doesn't get overwritten?

https://vendr.net/docs/core/2.1.0/umbraco-v9/getting-started/installation/#installing-a-license

anh-duc-le commented 2 years ago

Sadly there is no shared storage between Azure deployment slots, they're considered separate VMs with their own storage. So the only options are to host the license externally (blob storage container) or to copy license files between the two VMs during a release.

mattbrailsford commented 2 years ago

Hmm, that's a bummer.

Best I could suggest right now is either like you say copy the license file on deploy, or if you are using .NET Core, could you imeplement a file provider to point to blob storage and then configure the license app setting to point to that folder? https://www.strathweb.com/2018/08/azure-blob-storage-ifileprovider-for-asp-net-core/

(I've never tried this, but could be worth a shot)

mattbrailsford commented 2 years ago

Hmm, actually, that last suggestion might not work as our code is just using File.Open and not actually using the file provider API. This is likely because we are still currently maintaining v8 backwards compat, but in a future v3 we may be able to swap that out.

mattbrailsford commented 2 years ago

Lol, further investigation shows IFileProvider doesn't actually support write opperations so it looks like a dedicated solution might be required instead.

I'll have to give it some thought as to how to go about it, but it does seem currently your only option will be to copy on build.

mattbrailsford commented 2 years ago

I'm open to suggestions on an API for this as like I say, I'm not too familiar with azure setups. Do you know of any good examples where this is handled well?

anh-duc-le commented 2 years ago

When does the vendr application check and refresh an outdated license? If it is on startup of a web app we could perhaps ping the secondary app slot after deployment and before a swap to trigger that check and refreshing of the license perhaps.

mattbrailsford commented 2 years ago

We check via a background task every 24 hours for "expiring" licenses and then make an external request to update. There should actually also be a button in the back office to force refreshing the license (though we recently found a bug where it's not being displayed) but maybe it's possible to ping that API endpoint in Umbraco to force re-fetch?

/umbraco/backoffice/vendr/licensing/refreshlicense/{license-key}

anh-duc-le commented 2 years ago

How well would the force refresh license endpoint deal with multiple deployments on a day? Would that trigger a new license to be generated for each deployment if I were to trigger it on app startup?

mattbrailsford commented 2 years ago

As long as it's not excesive it should be fine. The end point will also check the expiry date and if it's not within the window will just return the current license.

I guess it depends whether you want any latency between our server to affect your deployments.

anh-duc-le commented 2 years ago

Ah perfect, if it just returns the current license when not expired we should be fine. The latency shouldn't be an issue :)

Thanks for the speedy responses, I will try out the api endpoint and see if that does the job.

anh-duc-le commented 2 years ago

I assume the license key is the <Id> property in the license file?

When calling the endpoint with that specific ID value I seem to get a 417 status result.

)]}', {"Type":null,"Title":null,"Status":417,"Detail":null,"Instance":null,"Extensions":{"traceId":"00-b131325d369fc9eba771d1cb59289c4a-d4d9ad8f5dbfc922-00"}}

mattbrailsford commented 2 years ago

Yes it will be the ID, and ahh, yea, of course, the API end point is an authenticated API controller and so it unfortunately requires you being logged into the back office to access it 🤦‍♂️

Hmm, unfortunately then I think the safest alternative is to copy the license files from disk