One common customer request that comes in is that they would like to collect the Security Event Logs from their Windows Azure roles, in addition to their Application, System and other Event Logs, when collecting diagnostics information using the Windows Azure Diagnostics capabilities. Security event logs are notoriously tricky, because to write them you require administrative privileges, which means you normally have to run as an elevated user account. But the ability to collect these in one place (a Windows Azure Storage Account) across a variety of role instances running in the cloud, can be a major plus for a Security Administrator, and coupled with System Center Operations Manager support for Windows Azure, is quite cool.
So let’s start by taking for example just dumping your Security events to a log file on your Windows machine. In Windows 7 on upwards, you can use the wevtutil tool to do so:
WEVTUTIL epl Security SecurityEventLog.evtx
Note that this will dump the entire log, but you could just dump a few events in XML format, say like the last three:
wevtutil qe Security /c:3 /rd:true /f:xml > SecurityEvents.xml
You can only runs these on your machine from an elevated command prompt, or you will get an “Access is denied.” error.
This is by design, for increased security: Only an administrative user should be able to interrogate the machine’s Security events.
It’s really no different on a Windows Azure VM that runs as one of your Web, Worker or VM role instances.
Thus, configuring diagnostics to collect the systems Security event logs, requires the diagnostics classes to access within the context of a process running as an Administrative user.
However, by default Windows Azure runs code and processes as a standard user.
You generally will feel like you have two choices:
a) Add a new Administrative user, and run your code or diagnostics there, which means creating a new user account, and giving that account Administrative rights.
- To do that programmatically once the VM is started, it means adding a new administrative user, and then impersonating that user with managed code just to run some command line tools to collect the Security Events.
Then you have the issue of moving those events off the machine to Windows Azure Storage, in the format expected, etc.
This is a lot of “heavy lifting” and will end up being unnecessary, as you will shortly see.
- You can define a startup task, with it’s executionContext attribute set to run elevated.
b) Add permissions so that the Security Events could be read by standard users:
NET.EXE localgroup "Event log Readers" "Everyone" /ADD
This approach not only would require you to reboot the Windows Azure VM (losing machine state), but would defeat the security principle of not allowing unprivileged users access to the Security event logs.
Therefore, I would recommend this approach in the least.
But there is a better way. The Diagnostics Plug-In Module configuration. The diagnostics plug-in, which is configured by importing the module, and configuring the default configuration for you, actually runs the diagnostics processes as startup tasks, with an increased priority level.
This configuration is pulled into the Windows Azure Project when it is built, from the Windows Azure SDK folders, which reside on your machine when you install the SDK.
What this meant for me was I could navigate to the plug-in SDK folder, and change the configuration of the plug-in:
a) I navigated to C:\Program Files\Windows Azure SDK\v1.6\bin\plugins\diagnostics and opened the Diagnostics.csplugin folder in Notepad.
b) Changed the startup task Diagnostics uses to run elevated. The file now looked like so:
<?xml version="1.0" ?>
<Task commandLine="DiagnosticsAgent.exe" executionContext="elevated" taskType="background" />
<Task commandLine="DiagnosticsAgent.exe /blockStartup" executionContext="elevated" taskType="simple" />
<Setting name="ConnectionString" />
Now any project I now build, package and deploy to Windows Azure from my machine using Visual Studio’s Windows Azure Tools will configure the plugin to run with the DiagnosticsAgent running in an Administrative context.
I now went ahead and added a diagnostics.wadcfg to my root WorkerRole project, and made sure it’s Build Action was set to Content, and Copy to Output Directory was set to “Always”.
This ensures the file will end up in the E:\approot directory on my Windows Azure VM, where the Diagnostics Plug-In will use it to configure Diagnostics with my declerative request to copy the Security Event Logs.
Since it is running Administrative, it picks up the events as you would expect.
<DiagnosticInfrastructureLogs bufferQuotaInMB="512" scheduledTransferLogLevelFilter="Verbose" scheduledTransferPeriod="PT1M" />
<Logs bufferQuotaInMB="1024" scheduledTransferLogLevelFilter="Verbose" scheduledTransferPeriod="PT5S" />
<Directories bufferQuotaInMB="1024" scheduledTransferPeriod="PT1M">
<!-- These three elements specify the special directories that are set up for the log types -->
<CrashDumps container="wad-crash-dumps" directoryQuotaInMB="512" />
<FailedRequestLogs container="wad-frq" directoryQuotaInMB="512" />
<IISLogs container="wad-iis" directoryQuotaInMB="512" />
<PerformanceCounters bufferQuotaInMB="512" scheduledTransferPeriod="PT1M">
<!-- The counter specifier is in the same format as the imperative diagnostics configuration API -->
<PerformanceCounterConfiguration counterSpecifier="\Processor(_Total)\% Processor Time" sampleRate="PT1M" />
<PerformanceCounterConfiguration counterSpecifier="\Memory\Available Mbytes" sampleRate="PT5S" />
<PerformanceCounterConfiguration counterSpecifier="\ASP.NET Apps v4.0.30319(__Total__)\Requests/Sec" sampleRate="PT1M" />
<DataSource name="System!*" />
<DataSource name="Application!*" />
<DataSource name="Security!*" />
Sure enough, I can see the Security Events seamlessly transfer to my configured Windows Azure Storage account, in this case, I’m using Cerebrata’s Azure Diagnostics Manager v2 to quickly view the events:
Hope this approach will save some of you some time and effort.