Sharing configuration settings between Windows Azure roles - azure

My Azure project have Web Role and a worker Role. Both roles have some common configurations.
How I could share the configurations instead repeating for both roles.
Now the cscfg file looks like this
<ServiceConfiguration serviceName="xxx" ....>
<Role name="WebRole1">
<Instances count="1" />
<ConfigurationSettings>
....
<Setting name="setting1" value="" />
<Setting name="setting2" value="" />
</ConfigurationSettings>
<Certificates>
.....
</Certificates>
</Role>
<Role name="WorkerRole1">
<Instances count="1" />
<ConfigurationSettings>
....
<Setting name="setting1" value="" />
<Setting name="setting2" value="" />
</ConfigurationSettings>
<Certificates>
.....
</Certificates>
</Role>
</ServiceConfiguration>
After googling I found this http://www.simple-talk.com/blogs/2011/03/16/sharing-configuration-settings-between-windows-azure-roles/ - is there any simple way to achieve the same?

What you've found is really interesting approach, but the mentioned attachment is missing anyway. It is also questionable what will happen if I still have some role-specific settings and I add it(them) to the specific role. That approach (most probably) is limited to providing same settings for all the roles.
What I would do to achieve your goal is a bit different. I would use an Azure Table Storage to store my configuration settings. This might be a bit harder to implement the first time, but from then on, you are free to reuse it in all the projects. The harder bit is that you have to implement your own monitoring logic to monitor for configuration changes. And that's it. You have a common store for settings. You can read/update settings with any free or paid Azure Storage *explorer like tool.

Related

Unable to enable AntiMalware for Azure Cloud Service (Classic)

We are trying to configure AntiMalware extensions for classic Azure Cloud Services by changing the service definition file (csdef). We know we can do this via powershell/portal, but we want this to be part of the definition so that re-deployments don't wipe out the config each time.
We've added the import entry:
<Import moduleName="AntiMalware" />
As well as the settings definitions:
<Setting name="Microsoft.WindowsAzure.Plugins.Antimalware.ServiceLocation" />
<Setting name="Microsoft.WindowsAzure.Plugins.Antimalware.EnableAntimalware" />
<Setting name="Microsoft.WindowsAzure.Plugins.Antimalware.EnableRealtimeProtection" />
<Setting name="Microsoft.WindowsAzure.Plugins.Antimalware.EnableWeeklyScheduledScans" />
<Setting name="Microsoft.WindowsAzure.Plugins.Antimalware.DayForWeeklyScheduledScans" />
<Setting name="Microsoft.WindowsAzure.Plugins.Antimalware.TimeForWeeklyScheduledScans" />
<Setting name="Microsoft.WindowsAzure.Plugins.Antimalware.ExcludedExtensions" />
<Setting name="Microsoft.WindowsAzure.Plugins.Antimalware.ExcludedPaths" />
<Setting name="Microsoft.WindowsAzure.Plugins.Antimalware.ExcludedProcesses" />
But when I try to build/package the cloud service using Visual Studio 2019 v16.8.2 and I get the following error:
Unable to import module AntiMalware. No manifest was found.
There seems to be virtually no documentation on this outside of very out dated blog posts. I'm wondering if the name of this module changed?
I agree that you provide the method in the link, use the definition and use the ps1 file to install AntiMalware.
Searching a lot of documents and materials, your needs should be achievable, and there are detailed steps in the 2012 official documents.
Microsoft Endpoint Protection for Windows Azure Customer Technology Preview Now Available For Free Download
There are also blogs explaining about this .csdef file, using <Import moduleName="AntiMalware" />.
How to Protect Against Malware on Windows Azure
Suggestions, raise a support ticket on the portal, and seek official final advice. Because this document is too old, I did not try it.

Azure config - not connection string or app setting

When deploying a cloud service worker role to Azure, I always set the various connection strings and app settings/configuration settings via the cscfg files and then via the Azure web interface if they need to change at run time, which all works fine.
Is it possible to do something similar for configs which are not connection strings or app settings/configuration settings?
Specifically I have something similar to the following:
<log4net>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="1" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<!-- This is the connection string I would like to store in Azure -->
<connectionString value="Server=tcp:azure.sql.server,1433;Database=MyAzureSqlDbName;User ID=my-user-name#my-server;Password=my-password;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;Application Name=log4net" />
<commandText value="INSERT INTO [MyLogTableName] ( [Date], [etc] ) VALUES ( #log_date, etc)" />
<parameter>
<parameterName value="#log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
</appender>
</log4net>
Is there any way of putting that connection string into cscfg files or Azure like my other settings? It's a pain to keep changing it manually in the app.config when I deploy, I keep forgetting (!) which means another re-deploy which is takes 4/5 minutes each time.
I can't use transforms btw as these settings are stored in app.config file of my worker role app and my understanding is that transforms only work with web.config files.
I think the easiest way will be for you to change the settings of the appender at runtime. If you add some logic in your global.asax.cs Application_Start method, you can change the connection string using the CloudConfigurationManager which will then either pull it from the cscfg or the app.config.
Steps would be:
add an appSetting in the app.config to hold the connection string you want to use when running locally
add a setting to your cscfg with the same name as your appSetting to hold the azure db connection string
install the Microsoft.WindowsAzure.ConfigurationManager nuget package if you don't already use it
Add the following code to your global.asax.cs Application_Start:
protected void Application_Start()
{
var hier = (Hierarchy)LogManager.GetRepository();
if (hier != null)
{
var appenders = hier.GetAppenders().OfType<AdoNetAppender>();
foreach (var appender in appenders)
{
appender.ConnectionString =
CloudConfigurationManager.GetSetting(connectionStringKey);
appender.ActivateOptions();
}
}
}
Two helpful links for you:
4 Tips for using Log4NET's ADONetAppender in ASP.NET
Changing Log4net Connection String at Runtime
The cscfg file is just name/value pairs, and is there for you to set any parameters you might need (specifically, ones you would like to be able to set/change without redeploying your app).
But more importantly: The only config file exposed externally is the .cscfg. You cannot arbitrarily access a different config file in the same way. You'd need to modify the config file yourself, based on cscfg changes. Alternatively, you can download your config file from somewhere (e.g. storage blob) on startup. This lets you modify a config, push to blob storage, and have your app download/use the new config (you'd just need to come up with a trigger mechanism to signal your role instances to re-initialize with the new config).

Test/Production configuration for Azure WebJob

I have an Azure WebSite project with WebJob project accosiated with it. The WebJob project needs to connect to external SOAP service. AS a result I have to put in the app.config the following block:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_MyExternalClassName">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="<<external URL>>" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_MyExternalClassName" contract="xxxxx" name="WSHttpBinding_MyExternalClassName" />
</client>
</system.serviceModel>
The problem is that I need to change value of <<external URL>> in "endpoint" node for different deployment scenarios - testing and production.
WebJob SDK seems to take Connection strings and app settigns from parent application, but what abount this specific SOAP-related service setting ?
How can I manage testing/production scenario?
Put the soap URL appSettings section inside web.config. Then read it using ConfigurationManager or CloudConfigurationManager. Obviously you have to manually set the url in code when you create the wcf client.
<appSettings>
<add key="soapurl" value="http://..." />
</appSettings>

How do I enable the cscfg overrides to work with NServiceBus Azure configuration

When using NServiceBus the Transport connection string doesn't seem to be fetched from the applicable Cloud configuration first but immediately from the app.config.
Options I've tried:
Using the configuration section (:
cscfg
<ConfigurationSettings>
<Setting name="AzureServiceBusQueueConfig.ConnectionString" value="Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=yyy" />
</ConfigurationSettings>
app.config
<AzureServiceBusQueueConfig ConnectionString="Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=yyy" />
Using a custom connection string name:
cscfg
<ConfigurationSettings>
<Setting name="NServiceBus.Transport" value="Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=yyy" />
</ConfigurationSettings>
app.config
<connectionStrings>
<add name="NServiceBus.Transport" connectionString="Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=yyy"/>
</connectionStrings>
Also tried to override it by using the following line of code, since this issue is still open (https://github.com/Particular/NServiceBus.AzureServiceBus/issues/20):
configuration.UseTransport<AzureServiceBusTransport>().ConnectionString(CloudConfigurationManager.GetSetting("AzureServiceBusQueueConfig.ConnectionString"));
Or tried to set the connection string name manually, which works again using the app.config but doesn't let the cscfg override.
configuration.UseTransport<AzureServiceBusTransport>().ConnectionStringName("NServiceBus.Transport");
Did you turn the azure configuration source on? You can do so using following extension method on the bus configuration:
.AzureConfigurationSource()

store nlog generated logs to Azure Blob Storage, in seperate columns

I've enabled diagnostics logging to Blob Storage for an Azure Website I am trying on. I've also set Nlog to write to Trace, so that they are then in turn written to the Azure blob. Nlog layout is set to CSV. This works, and the generated logs are outputted to the blob storage. If this was logging to a traditional file, that file would be a CSV file which I can open in excel, to analyse better the log files.
Nlog configuration file copied below:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!--
See http://nlog-project.org/wiki/Configuration_file
for information on customizing logging rules and outputs.
-->
<targets>
<!-- add your targets here -->
<!--
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
-->
<target xsi:type="Trace" name="trace" >
<layout xsi:type="CsvLayout" >
<column name="shortdate" layout="${shortdate}" />
<column name="time" layout="${time}" />
<column name="logger" layout="${logger}"/>
<column name="level" layout="${level}"/>
<column name="machinename" layout="${machinename}"/>
<column name="processid" layout="${processid}"/>
<column name="threadid" layout="${threadid}"/>
<column name="threadname" layout="${threadname}"/>
<column name="message" layout="${message}" />
<column name="exception" layout="${exception:format=tostring}" />
</layout>
</target>
</targets>
<rules>
<!-- add your logging rules here -->
<logger name="*" minlevel="Trace" writeTo="trace" />
<!--
<logger name="*" minlevel="Trace" writeTo="f" />
-->
</rules>
</nlog>
Windows Azure diagnostics saves the diagnostics info as a CSV file in the blob storage. The CSV file has the below columns.
date,level,applicationName,instanceId,eventTickCount,eventId,pid,tid,message,activityId
However, the entire NLog message is written in the Message column. This is probably because it saves the Diagnostics.Trace message there, in which NLog is saving it'slogs. For example:
2014-05-07T12:18:49,Information,KarlCassarTestAzure1,10cd67,635350619297036217,0,2984,1,"2014-05-07,12:18:49.6254,TestAzureWebApplication1.MvcApplication,Info,RD0003FF410F59,2984,1,,Application_Start,",
The NLog message is the below:
"2014-05-07,12:18:49.6254,TestAzureWebApplication1.MvcApplication,Info,RD0003FF410F59,2984,1,,Application_Start,"
It is escaped, and fits entirely in the CSV column, which I wouldn't wish. Any idea if there is something to do about this?
For what you're trying to accomplish, you would need to rely on Custom Diagnostics functionality of Azure Diagnostics. The way it would work is that your NLog logger would write log files in CSV format to local storage in your cloud service VM and then Azure Diagnostics module will transfer this data to blob storage periodically.
For implementation details, I would recommend looking into Cloud Service Fundamentals project by Azure CAT team. They have described the process quite extensively in their blog post which you can read here: http://social.technet.microsoft.com/wiki/contents/articles/17987.cloud-service-fundamentals.aspx. What you would want to do there is read all blog posts under Telemetry section. For the services we have built, we have actually implemented this and it works just great.

Resources