Access Azure Storage Configuration Setting from class library - string

I have a Azure project which uses the Azure Storage. The connection string for the Azure Storage is saved in the Configuration Settings for the Azure Project.
Now I have created a class library. I want to be able to load the connection string in the class library. What is the best way of doing this?
For example, do I put the connection string in the app.config for the class library? If so, will the Azure project override this automatically when I run the solution?

You may be looking for Microsoft.WindowsAzure.CloudConfigurationManager. The GetSetting method attempts to pull the setting from the Cloud configuration, but if the role isn't available (for instance because you're in a unit test), it reads from the <AppSettings> element inside your app.config or web.config file.
Here's the basic syntax:
using Microsoft.WindowsAzure;
...
var settingValue = CloudConfigurationManager.GetSetting("SettingKey");
MSDN[1] says the syntax is deprecated with the release of Storage 3.0, but the class and method aren't attributed as such, so the documentation may just have a bit of copy pasta in it.
[1] http://msdn.microsoft.com/en-us/library/windowsazure/microsoft.windowsazure.cloudconfigurationmanager.aspx

RoleEnvironment.GetConfigurationSettingValue("") is what I was looking for.

Related

Storing connection strings in Azure App Service Settings

I have an ASP .Net Core 2.2 Web API which connects to a MySQL Database.
It is hosted on Azure App Service.
Currently I am storing the connection strings in the appsettings.json file:
"ConnectionStrings": {
"MyDataContext": "Server=server1.mysql.database.azure.com;user id=username;Pwd=password;persistsecurityinfo=True;database=db1;"
}
And I read the connection strings in Startup.cs (in the ConfigureServices method) like this:
services.AddDbContext<MyContext>(options => options.UseMySql(Configuration.GetConnectionString("MyDataContext")));
I read that I can store these connection strings in the Azure App Service Settings instead, as it offers some advantages. I've been trying to do this, but am struggling to get it to work.
My first question is, when adding the connection string to Azure App Service Settings (under the Connection Strings section), what do I put in for Name in the Name/Value pairs? Do I just put "MyDataContext" or do I put in "ConnectionStrings:MyDataContext"? (I'm trying to keep the same structure as I have in the appsettings.json file).
My second question is, can I still read the connections string in my Startup.ConfigureServices method the same way I am doing now? From what I understand, Azure App Service will automatically inject the connection string store in Settings into the Configuration object in the API? I'm not sure if I'm missing something, but it's not working...
Yes and yes.
Yes, you can name the connection string as almost anything you want, though I've discovered recently that certain characters aren't allowed, but Azure doesn't tell you this, it will just strip them out and not tell you, so to be safe I'd only use alphanumeric characters, you can use CamelCasing if you need to. You don't need to prefix with anything like ConnectionStrings: as this is done automatically by Azure, and the syntax has changed in the most recent version anyway.
And yes, if you haven't specified your own ConfigurationBuilder, your web app should call CreateDefaultBuilder which will add environment variables at runtime. The code you've written will stay the same and you can delete the connection string from your appsettings.json file, if you keep it in there it will get overridden anyway.
It is a good idea to remove connection strings from the appsettings.json file if you are able to store them in Azure instead for security reasons, so that you are not storing either database server address nor connection credentials in your source code. One step up from this is using Managed Identity in conjunction with Active Directory, where you specify an AD username in the connection string but no password, then assign that user (or the user's group) as the server admin.
It looks like there's a slight delay (a couple of seconds at least) when changing the Settings of an Azure App Service - I was too quick...

Azure Application Settings not overriding my appsettings.json file values

I have tried adding DefaultConnection from my appsettings.json file to Azure's Application Settings but Azure will not override the connection string.
Any article or blog I can find states that all I should need to do is add the connection string name as it states in the appsettings.json file and Azure should do the rest (e.g. https://tehremo.wordpress.com/2016/10/07/override-connection-strings-app-settings-in-asp-net-core-and-azure-app-service/) however when the application is published it is using my local connection string.
My Startup.cs file looks like the following:
NOTE: I am publishing using VSTS continuous delivery with "Deploy Azure App Service" release task.
I just had a similar problem (the problem was with PostgreSQL connection string type, I had to change it to custom) and now it works for me, so these are the pieces:
This is my appsettings.json file. I have a value for 'Psql' set in my appsettings.Development.json, but in the appsettings.json it is left empty.
These are the settings which are set in the Azure portal. Please note, that there are two ways to override the connection string.
This is the part of my Startup.cs file. Pay attention to the order of how the settings are applied in the Startup constructor and the way I get the connection string in the ConfigureServices method (GetConnectionString is a standard extension method).
Additional info from my comments below:
Azure GUI (Connection strings, Application settings) uses environment variables internally, so the appsettings.json will stay the same.
If there is a need for an appsettings.json's value to be overwritten during VSTS release activity (before it will be published to Azure), Colin's ALM Corner Build & Release Tools can be used. Here are the links to Colin's ALM Corner Build & Release Tools and tutorial.
Thanks #pasul, your help was much appreciated and helped me find an alternative solution. In order to deploy using VSTS task and replace application settings, you will need to add variables to the release task and pass into the task the json file in question for variable substitution.
When in "Deploy Azure App Service" release task you should see a "File Transforms and Variable Substitution" section. In here you will supply the path to the json file you want to swap variable values.
Then you will need to click on the options button on the release environment. You will see an option to configure variables in the pop out menu.
From here you can add the json property you want to modify as a variable. In my case the connection string. Which will look like the following:
"ConnectionStrings.DefaultConnection"
Then just put in your connection string value. VSTS will then swap out these values for you when deploying.

Do I need an Azure Storage Account to run a WebJob?

So I'm fairly new to working with Azure and there are some things I can't quite wrap my head around. One of them being the Azure Storage Account.
My web jobs keeps stopping with the following error "Unhandled Exception: System.InvalidOperationException: The account credentials for '[account_name]' are incorrect." Understanding the error however is not the problem, at least that's what I think. The problem lies in understanding why I need an Azure Storage Account to overcome it.
Please read on as I try to take you through the steps taken thus far. Hopefuly the real question will become more clear to you.
In my efforts to deploy a WebJob on Azure we have created the following resources so far:
App Service Plan
App Service
SQL server
SQL database
I'm using the following code snippet to prevent my web job from exiting:
JobHostConfiguration config = new JobHostConfiguration();
config.DashboardConnectionString = null;
new JobHost(config).RunAndBlock();
To my understanding from other sources the Dashboard connection string is optional but the AzureWebJobsStorage connection string is required.
I tried setting the required connection string in portal using the configuration found here.
DefaultEndpointsProtocol=[http|https];AccountName=myAccountName;AccountKey=myAccountKey
Looking further I found this answer that clearly states where I would get the values needed, namely an/my missing Azure Storage Account.
So now for the actualy question: Why do I need an Azure Storage Account when I seemingly have all the resources I need place for the WebJob to run? What does it do? Is it a billing thing, cause I thought we had that defined in the App Service Plan. I've tried reading up on Azure Storage Accounts over here but I need a bit more help understanding how it relates to everything.
From the docs:
An Azure storage account provides resources for storing queue and blob data in the cloud.
It's also used by the WebJobs SDK to store logging data for the dashboard.
Refer to the getting started guide and documentation for further information
The answer to your question is "No", it is not mandatory to use Azure Storage when you are trying to setup and run a Azure web job.
If you are using JobHost or JobHostConfiguration then there is indeed a dependency for Storage accounts.
Sample code snippet is give below.
class Program
{
static void Main()
{
Functions.ExecuteTask();
}
}
public class Functions
{
[NoAutomaticTrigger]
public static void ExecuteTask()
{
// Execute your task here
}
}
The answer is no, you don't. You can have a WebJob run without being tied to an Azure Storage Account. Like Murray mentioned, your WebJob dashboard does use a storage account to log data but that's completely independent.

How can I programatically (C#) read the autoscale settings for a WebApp?

I'm trying to build a small program to change the autoscale settings for our Azure WebApps, using the Microsoft.WindowsAzure.Management.Monitoring and Microsoft.WindowsAzure.Management.WebSites NuGet packages.
I have been roughly following the guide here.
However, we are interested in scaling WebApps / App Services rather than Cloud Services, so I am trying to use the same code to read the autoscale settings but providing a resource ID for our WebApp. I have already got the credentials required for making a connection (using a browser window popup for Active Directory authentication, but I understand we can use X.509 management certificates for non-interactive programs).
This is the request I'm trying to make. Credentials already established, and an exception is thrown earlier if they're not valid.
AutoscaleClient autoscaleClient = new AutoscaleClient(credentials);
var resourceId = AutoscaleResourceIdBuilder.BuildWebSiteResourceId(webspaceName: WebSpaceNames.NorthEuropeWebSpace, serverFarmName: "Default2");
AutoscaleSettingGetResponse get = autoscaleClient.Settings.Get(resourceId); // exception here
The WebApp (let's call it "MyWebApp") is part of an App Service Plan called "Default2" (Standard: 1 small), in a Resource Group called "WebDevResources", in the North Europe region. I expect that my problem is that I am using the wrong names to build the resourceId in the code - the naming conventions in the library don't map well onto what I can see in the Azure Portal.
I'm assuming that BuildWebSiteResourceId is the correct method to call, see MSDN documentation here.
However the two parameters it takes are webspaceName and serverFarmName, neither of which match anything in the Azure portal (or Google). I found another example which seemed to be using the WebApp's geo region for webSpaceName, so I've used the predefined value for North Europe where our app is hosted.
While trying to find the correct value for serverFarmName in the Azure Portal, I found the Resource ID for the App Service Plan, which looks like this:
/subscriptions/{subscription-guid}/resourceGroups/WebDevResources/providers/Microsoft.Web/serverfarms/Default2
That resource ID isn't valid for the call I'm trying to make, but it does support the idea that a 'serverfarm' is the same as an App Service Plan.
When I run the code, regardless of whether the resourceId parameters seem to be correct or garbage, I get this error response:
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
{"Code":"SettingNotFound","Message":"Could not find the autoscale settings."}
</string>
So, how can I construct the correct resource ID for my WebApp or App Service Plan? Or alternatively, is there a different tree I should be barking up to programatially manage WebApp scaling?
Update:
The solution below got the info I wanted. I also found the Azure resource explorer at resources.azure.com extremely useful to browse existing resources and find the correct names. For example, the name for my autoscale settings is actually "Default2-WebDevResources", i.e. "{AppServicePlan}-{ResourceGroup}" which I wouldn't have expected.
There is a preview service https://resources.azure.com/ where you can inspect all your resources easily. If you search for autoscale in the UI you will easily find the settings for your resource. It will also show you how to call the relevant REST Api endpoint to read or update that resorce.
It's a great tool for revealing a lot of details for your deployed resources and it will actually give you an ARM template stub for the resource you are looking at.
And to answer your question, you could programmatically call the REST API from a client with updated settings for autoscale. The REST API is one way of doing this, the SDK another and PowerShell a third.
The guide which you're following is based on the Azure Service Management model, aka Classic mode, which is deprecated and only exists mainly for backward compatibility support.
You should use the latest
Microsoft.Azure.Insights nuget package for getting the autoscale settings.
Sample code using the nuget above is as below:
using Microsoft.Azure.Management.Insights;
using Microsoft.Rest;
//... Get necessary values for the required parameters
var client = new InsightsManagementClient(new TokenCredentials(token));
client.AutoscaleSettings.Get(resourceGroupName, autoScaleSettingName);
Besides, the autoscalesettings is a resource under the "Microsoft.Insights" provider and not under the "Microsoft.Web" provider, which explains why you are not able to find it with your serverfarm resourceId.
See the REST API Reference below for getting the autoscale settings.
GET
https://management.azure.com/subscriptions/{subscription-id}/resourceGroups/{resource-group-name}/providers/microsoft.insights/autoscaleSettings/{autoscale-setting-name}?api-version={api-version}

How do deploy a public Github project that contains secret API keys to Azure?

I have a project which I plan to open-source at some point. Currently I keep all of my API keys in a class which is not checked in - I have just linked the project to Azure but the API key class not being present causes the deployment to fail.
How can I hide secret API keys in a public project and still have it deploy to Azure?
I have read quite a few posts (this one for instance) but cannot find a solution that allows me to do what I want - does anyone know what I should do here? Is it possible?
For an Azure Web App, you can specify config values on the Configure tab in the portal (under "app settings"). These will override values specified in your Web.config file.
This means you can leave these settings out of your public repository.
For developing locally, you can put the settings in a separate XML file. To do this, update the appSettings in your Web.config like this:
<appSettings file="mysettings.xml" />
Then create mysettings.xml and put your actual settings in a new <appSettings> element there.
You can then add mysettings.xml to your .gitignore file so it won't be checked in to your public repository.
Azure doesn't mind that your mysettings.xml file doesn't exist, and will pick up the settings you specify in the portal instead.

Resources