Update database EF Core Azure build step - azure

I've defined steps to build and run tests for my ASP.NET Core MVC app and it all works fine.
Now I want to add a step that actually runs the migrations (if any) and that step to works (it doesn' fail :). Allthough I can't understand why it works since it probably uses the setting from appsettings.json, which don't have any connection strings, they're defined in user secrets.
So my question is: Is there any easy way to get the connection string defined in the App Service for the site I want to build?
A neat option would be to define a variable with the same name, e.g ConnectionStrings:db that check if there is any app setting with the specified key in the Azure portal and then use it.
Thanks

The better way is using Azure Key Vault. You can refer to this blog for detail steps of protecting secrets using VSTS and azure key value.
Another way is that you can use secure variable in build/release, and replace the specified value in appsettings.json by using JSON vairble substitution of Azure App Service Deploy task. (match the key, so appsettings.json file should contain connectionstring key).

Related

Azure app service - slot app settings with nested resource

I have an ARM template, that performs resource group deployment. It mainly consist of web apps and key vault. I want to go with blue/green deployment and sometimes need to add only blue slot settings to web app.
When we are deploying web app site all as one resource (https://learn.microsoft.com/en-us/azure/templates/microsoft.web/sites?tabs=json), it's quite easy as appSettings are being defined as key-values and we can add 3rd key as "slotSetting": true.
However, in my scenario, I want to deploy all in Complete mode, in the same time add dynamically key vault access policies. So based on this doc - https://learn.microsoft.com/en-us/azure/app-service/app-service-key-vault-references#azure-resource-manager-deployment - I need to configure appSettings as separate resource, which is an object, so there's no way to add this additional property.
With this, I have 2 questions:
Is there a way to add this slotSetting when deploying appSettings as separate resource?
Those are little bit off topic but about that case as well:
but I'm trying to find a best practise, when it comes to deploying resources + key vault and dynamic access policies. As on complete mode we can't just conditionally not deploy key vault (because it will try to remove it) and on the other hand when we define it, we need to add empty array of AccessPolicies (empty because we need to add accessPolicies in separate resources so we could loop over all web apps and get identity), so by and large, the apps are down for some time. Not the best practise when you want to reach 0 downtime deployment.
In what exact scenarios we want to use Complete mode deployment? My team leads are pushing for it but I don't see much added value. If we have ARM template well defined, all manual changes will be changed or moved to defaults in Incremental as well as Complete. Just additional resources are deleted. Do you have any interesting use case to share?
Not really sure I fully understand your question but when deploying slots you can deploy different app settings to the individual slot in the ARM template simply by specifying them in the slot setting itself when you create it.
You can create the RBAC policies first for the Vault and then apply them to the Vault at creation time but it gets a little complicated, and why dont you just use incremental mode, the only difference is that things not specified wont be deleted.
I have never found a good use case for Complete mode other than dev instances where I can specify a single resource and have it clean up all other things, but in a produciton environment running Complete mode seems to be totally weird

How do you integrate Key Vault into an application in a secure way?

I am trying to integrate KeyVault into my Azure App service. I have a KeyVault client library embedded in my application. In order for this client library to connect to KeyVault and access stored secrets, some configurations must be available for the client to connect. There are 4 types of credential objects that the client attempts to use, in a specific order, during initialization for authentication/authorization. The first credential object it tries to use is an environment based object. This object attempts to gather 4 environment variables from the hosting system to initialize the KeyVault client. One of these variables must contain the ClientSecret of the application trying to connect to KeyVault via the client lib. The problem I am running into is this. In my azure release pipeline I am trying to set the environment variables of the deployed host appropriately for the application to use. However, it appears that the release tasks all run on the same host, until you get to the actual deployment task of the app service. Apparently this task runs on a different host? When running the hostname command on previous tasks they all returned one hostname while the hostname command added to the deployment task returned a another. I am a little stuck and having trouble finding more clarity about setting environment variables for an app service through documentation. Does anyone have any ideas? Am I going about integrating KeyVault correctly or is there something I am missing? Please let me know if clarification is needed or more information is required to assist me. Thank you very much.
If you are using Azure App Services, this is way easier. You directly link application configuration from KeyVault using Managed Identities.
Sample config value will look like this:
#Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931)
This way you
don't have to change anything in your application code. The app reads
secrets from KeyVault just like any other configuration
do not need to manage any client-side credentials to access KeyVault.
You need to create the Variables in your Pipeline and retrieve them (from Key Vault), during the release process.
PS: Your app will receive/read them as Environment Variables.
Azure DevOps Variable Group not applying in Azure Function Configuration

Keeping asp.net core config out of your source and your pipelines

I'm working on an asp.net core project and I'm trying to figure out how to keep my source and my pipelines 100% secret free.
I've got a VM running the azure agent and an azure dev ops pipelines for build and release.
If i delete the site on the VM, the release pipeline will auto-magically recreate it for me and deploy the latest build.
Super cool.
Now I read up on best practices for configuring a .Net core app and I found this article: https://www.humankode.com/asp-net-core/asp-net-core-configuration-best-practices-for-keeping-secrets-out-of-source-control
So its a bad idea to keep secrets in code, that makes perfect sense.
But if i apply the same security principals to Yaml, then surely I shouldn't place secrets in my pipelines either.
But I need the pipelines to be able to just recreate the site from scratch and it should just work. Somehow the site needs to know where its default sql connection is, or it needs to have a key to the azure app config service. I shouldn't have to log onto the VM and create an appsettings.json manually after every release!
So whatever the site needs to operate needs to be included in the pipeline, therefore some artifact, or included in the code.
I've googled for days, but I can't seem to find any info on how to fully automate this.
I've considered creating a custom configuration provider that reads from the actual VM registry, but that feels wrong too.
I basically need a config option that is NOT hosted in the site itself. So i set it up once on the VM and never again.
The approach that Lex Li lists in the comments is the Microsoft recommended way of securing "secrets" in pipelines.
Ben Smith's answer in my opinion is just as good, maybe slightly less secure.
I use this approach in our organization. All of our release pipelines do the final configuration transformation with the appropriate settings based on the environment they are being deployed to.
i.e db connections are transformed at the dev, test and UAT and production deployment stages.
I keep the relevant secrets in the pipeline variables as protected secrets. I do this for 2 reasons:
Only a select number of trusted personnel have access to the release pipeline definitions.
Even if someone does have access to those definitions - you cannot see a secured variable. Even you you "undo the padlock" on the variable tab - you cannot see what the setting is.
Our actual secrets are then stored in our enterprise secret vault.
Using the Azure Key Vault is definitely a good approach. However we already have a centralized place to keep our stuff; I don't want it in 3 spots.
I would be remiss to not include Variable Groups as part of the pipeline process. Same concept as the build / release variables - the difference is you can now share them in one spot.
These are all opinions of course. This is just one way of doing this; which I feel is a pretty good balance of security and flexibility.
In addition to the suggestions in your questions comments, you can also store secrets in the pipeline "Variables" section.
In here you can add variables and then mark them as secret by selecting "Keep this value secret". Once you've saved a secret its value is then obfuscated i.e. you can make use of it but you can no long see its original value within Azure Devops (which admittedly can be rather frustrating if you want to revisit the variable to check it!).
You can then reference the secret variable in your pipeline YAML using the syntax:
$(variable-name)
So this approach keeps secrets safe within Azure Devops until they need to be resolved by the pipeline YAML script.

Azure Deployment using Github web.config transformations

In azure web apps, there's a tab called "Deployment option" that allows a push from a github branch to azure web apps.
Currently I'm developing a website in Umbraco and is trying to get this option to work properly.
I have been able to successfully connect connect web app and sync the build from that branch from github.
However, after the deploy, the connection is wrong so I have deduced that it's potentially a connection string problem.
Therefore, is there a way to perform web.config transforms while using this deployment option?
Generally, you should not attempt to transform your web.config with connection strings during deployment, as doing this leaves you with physical files containing secrets (dangerous practice).
Instead, you need to set your connection strings using the Azure Portal (or ARM API). Just keep a 'dummy' entry in your web.config to mark that you have this key, and then override the value with the real connection string in the portal.
See doc for related info.

How to pass Azure credentials to a Release Management deployment script on a secure manner?

What I want to accomplish:
I want to deploy an Azure Cloud Service via Release Management. I managed to get this working by following the steps outlined in this post. In the post the Azure publishsettings file is added to the project and used in Release Management to deploy the Azure package to a Cloud Service. So far so good.
What is the issue:
The Azure publishsettings file will also contain information about the production environment. I don't want that information to be available to all the developers and therefor I would like to have a more secure alternative.
What did I try:
I created a custom action which takes 3 arguments: subscription id, subscription name and certificate key. This way the Azure information stays in Release Management and can be passed to a script. This didn't work because the action is not shown in the Release Template Toolbox.
What is my question:
What is the best way to pass Azure credentials to a deployment script via Release Management on a secure manner?
We have a solution for Build today that will work for RM in the future.
Publish Settings file is an important one with which anybody can get access to certain activities. And once how ever the way you pass on the publish settings file, it can be misused (if tried).
So along with the publish settings file, you need to add a bit of process to the deployment like -
Inactive or remove the management certificate which will in turn invalidate the given publish settings and anyone should request for a new set of publish settings file before they actually start any release procedures.
Even though it adds a rough edge to your smooth flow of deployment process, as it is a live or production system, it is always better to tight the process and make it idiot proof.

Resources