{"id":80565,"date":"2016-11-09T00:01:33","date_gmt":"2016-11-09T08:01:33","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/?p=80565"},"modified":"2019-02-18T09:10:22","modified_gmt":"2019-02-18T16:10:22","slug":"part-3-use-azure-automation-dsc-to-configure-linux-and-execute-powershell-scripts","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/part-3-use-azure-automation-dsc-to-configure-linux-and-execute-powershell-scripts\/","title":{"rendered":"Part 3 \u2013 Use Azure Automation DSC to Configure Linux and execute PowerShell scripts"},"content":{"rendered":"<p><strong>Summary<\/strong>: Learn how to configure and use PowerShell, Bash, and DSC with Linux.<\/p>\n<p>Hi, my name is Stefan Roth (Blog: <a target=\"_blank\" href=\"http:\/\/stefanroth.net\">http:\/\/stefanroth.net<\/a> \/ Twitter: <a target=\"_blank\" href=\"https:\/\/twitter.com\/stefanroth_net\">@stefanroth_net<\/a>), and I am a Cloud and Datacenter MVP. In my last post of this three-part series, I would like to show you how we are able to hook up the previously installed Linux system to Azure Automation desired state configuration (DSC), deploy a DSC configuration, and apply it to our Linux system. What we are actually going to do is create a cronjob on Linux via Azure Automation DSC. This cronjob will run a PowerShell script on Linux every five minutes to send the current connected users to <a target=\"_blank\" href=\"https:\/\/azure.microsoft.com\/de-de\/documentation\/articles\/log-analytics-data-collector-api\/\">Azure Log Analytics HTTP Data Collector API<\/a>.<\/p>\n<p>The first step is to hook up our system to Azure Automation DSC. Simply run the following script on the Linux system.<\/p>\n<p style=\"padding-left: 60px\"><code>\/opt\/microsoft\/dsc\/Scripts\/Register.py &lt;PRIMARY ACCESS KEY&gt; &lt;URL&gt;<\/code><\/p>\n<p>This script will configure the local machine\u2019s Local Configuration Manager (LCM) and also register on Azure Automation DSC. You find the primary access key and the URL\u00a0in the Azure portal.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1-HSG-110916.png\" alt=\"The primary access key and the URL in the Azure portal\" width=\"537\" height=\"291\" class=\"alignnone size-full wp-image-80575\" \/><\/a><\/p>\n<p>After you ran the script on the Linux system, you should get an output like in this screenshot.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2-HSG-110916.png\" alt=\"Output from the script\" width=\"327\" height=\"162\" class=\"alignnone size-full wp-image-80576\" \/><\/a><\/p>\n<p>Of course, you will see your registered server in the Azure portal as well.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3-HSG-110916.png\" alt=\"The registered server in the Azure portal\" width=\"668\" height=\"165\" class=\"alignnone size-full wp-image-80585\" \/><\/a><\/p>\n<p>The first step has been done. The next step will supply the actual DSC configuration script, which we will run from Azure Automation DSC. Before we actually can do that, we need to upload the <em>nx<\/em> DSC module, which contains the script resource.<\/p>\n<p>First, download the module to your Windows computer, for example,\u00a0C:\\Temp. Use the <strong>Save-Module<\/strong> cmdlet to download and save the module locally. Next, just ZIP the <em>nx<\/em> module folder to a file <em>nx.zip<\/em>.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4-HSG-110916.png\" alt=\"Use the Save-Module cmdlet download and save the module locally\" width=\"607\" height=\"130\" class=\"alignnone size-full wp-image-80595\" \/><\/a><\/p>\n<p>Azure Automation needs the <a target=\"_blank\" href=\"https:\/\/azure.microsoft.com\/de-de\/blog\/authoring-integration-modules-for-azure-automation\/\">module in the ZIP format to successfully install<\/a><span> the module<\/span>. Then, upload the ZIP file to Azure Automation.\u00a0This screenshot provides the steps.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5-HSG-110916.png\" alt=\"Upload the ZIP file to Azure Automation\" width=\"648\" height=\"259\" class=\"alignnone size-full wp-image-80605\" \/><\/a><\/p>\n<p>After few minutes the module will appear as a listed module.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/6-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/6-HSG-110916.png\" alt=\"The module appears in the list of modules\" width=\"458\" height=\"122\" class=\"alignnone size-full wp-image-80615\" \/><\/a><\/p>\n<p>If you don\u2019t upload this module and you try to compile a DSC configuration, the compilation will fail and shoot an exception.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7-HSG-110916.png\" alt=\"Demonstration of failure because the module was not uploaded\" width=\"566\" height=\"282\" class=\"alignnone size-full wp-image-80625\" \/><\/a><\/p>\n<p>At this moment, we are ready to upload the actual DSC configuration file, which will create the cronjob. A cronjob is similar to a scheduled job in Windows. This specific cronjob will run every five\u00a0minutes and run a script,\u00a0<em>\/tmp\/Send-Login.ps1<\/em>, which we will create in an upcoming step. The <code>TestScript<\/code> part checks if the cronjob has been created.\u00a0If not, it will execute the <code>SetScript<\/code> section which will add the cronjob. What&#8217;s interesting here is that we are actually using the PowerShell binary to\u00a0execute a native PowerShell script on Linux.<\/p>\n<p><em>DSC_CronJob.ps1<\/em><\/p>\n<p style=\"padding-left: 30px\"><code># DSC configuration CronJob\nconfiguration CronJob\n{<\/code><\/p>\n<p style=\"padding-left: 60px\"><code># Import the DSC module nx\nImport-DSCResource -Module nx<\/code><\/p>\n<p style=\"padding-left: 60px\"><code># Node name or IP\nnode centos.localdomain\n{<\/code><\/p>\n<p style=\"padding-left: 90px\"><code># Use the nxScript resource to create a cronjob.\nnxScript CronJob{<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>GetScript = @\"<\/code><\/p>\n<p style=\"padding-left: 90px\"><code>#!\/bin\/bash\ncrontab -l | grep -q \"powershell -c \/tmp\/Send-Login.ps1\" &amp;&amp; echo 'Job exists' || echo 'Job does not exist'\n\"@<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>SetScript = @\"<\/code><\/p>\n<p style=\"padding-left: 90px\"><code>#!\/bin\/bash\n(crontab -l | grep -v -F \"powershell -c \/tmp\/Send-Login.ps1\" ; echo \"*\/5 * * * * powershell -c \/tmp\/Send-Login.ps1\" ) | crontab\n\"@<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>TestScript = @'<\/code><\/p>\n<p style=\"padding-left: 90px\"><code>#!\/bin\/bash\ncrontab -l | grep -q \"powershell -c \/tmp\/Send-Login.ps1\" &amp;&amp; exit 0 || exit 1\n'@<\/code><\/p>\n<p style=\"padding-left: 90px\"><code>}<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>}<\/code><\/p>\n<p style=\"padding-left: 30px\"><code>}<\/code><\/p>\n<p>Within the Azure portal, go to <strong>DSC Configuration<\/strong>\u00a0&gt; <strong>Add a configuration<\/strong>, provide the configuration file, and then click <strong>OK<\/strong>.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/8-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/8-HSG-110916.png\" alt=\"Provide the configuration file to DSC Configurations\" width=\"596\" height=\"195\" class=\"alignnone size-full wp-image-80635\" \/><\/a><\/p>\n<p>Remember, we just provided the PowerShell script code.\u00a0Next, we need to create the MOF file from\u00a0this code.\u00a0To generate the MOF file, simply select the DSC configuration, and select <strong>Compile<\/strong>.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/9-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/9-HSG-110916.png\" alt=\"Click the Compile button in DSC Configurations\" width=\"587\" height=\"152\" class=\"alignnone size-full wp-image-80636\" \/><\/a><\/p>\n<p>The compilation job starts and deploys the file to the DSC pull server. It takes a couple of minutes for the job to finish.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/10-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/10-HSG-110916.png\" alt=\"Progress of the compilation job\" width=\"543\" height=\"156\" class=\"alignnone size-full wp-image-80645\" \/><\/a><\/p>\n<p>After completion, go to <strong>DSC Nodes<\/strong>, select your node, and then click <strong>Assign node configuration<\/strong>. This step assigns the DSC configuration to the Linux machine.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/11-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/11-HSG-110916.png\" alt=\"Assigning the DSC configuration to the Linux machine\" width=\"586\" height=\"243\" class=\"alignnone size-full wp-image-80655\" \/><\/a><\/p>\n<p>Make sure you will see the proper Node configuration and the status.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/12-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/12-HSG-110916.png\" alt=\"The Node configuration and status\" width=\"525\" height=\"312\" class=\"alignnone size-full wp-image-80665\" \/><\/a><\/p>\n<p>After your next configuration update cycle, the DSC configuration will be applied to your Linux system.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/13-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/13-HSG-110916.png\" alt=\"The DSC configuration applied to your Linux system\" width=\"608\" height=\"177\" class=\"alignnone size-full wp-image-80675\" \/><\/a><\/p>\n<p>If you want to check whether\u00a0the DSC configuration has been applied, sign in to your Linux server as root, and type <strong>crontab -l<\/strong><em>,<\/em> which will display the configured cronjob.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/14-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/14-HSG-110916.png\" alt=\"Display of the configured cronjob\" width=\"385\" height=\"112\" class=\"alignnone size-full wp-image-80685\" \/><\/a><\/p>\n<p>The last step is to create the <em>Send-Login.ps1<\/em> PowerShell script in the <em>\/tmp <\/em>directory. I use vi editor to create the file and copy the code. These are the steps to\u00a0create the PowerShell script:<\/p>\n<ol>\n<li>vi \/tmp\/Send-Login.ps1 (launches an empty file called Send-Login.ps1)<\/li>\n<li>Type <strong>i<\/strong> (for inserting text)<\/li>\n<li>Paste the <em>Send-Login.ps1<\/em> script below<\/li>\n<li>Type <strong>Esc-Key<\/strong> (changing vi editor mode)<\/li>\n<li>Type <strong>:<\/strong><\/li>\n<li>Type <strong>wq!<\/strong> (write and quite)<\/li>\n<\/ol>\n<p>If you are connected via Windows Bash to your Linux system (which I recommend), it will look similar to this screenshot.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/15-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/15-HSG-110916.png\" alt=\"Windows Bash\" width=\"589\" height=\"310\" class=\"alignnone size-full wp-image-80695\" \/><\/a><\/p>\n<p>As a next step, make the script executable.<\/p>\n<p style=\"padding-left: 30px\"><code>chmod +x \/tmp\/Send-Login.ps1<\/code><\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/16-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/16-HSG-110916.png\" alt=\"Making the script executable\" width=\"383\" height=\"142\" class=\"alignnone size-full wp-image-80705\" \/><\/a><\/p>\n<p>The <em>Send-Login.ps1<\/em> script is based on a script from <a target=\"_blank\" href=\"https:\/\/azure.microsoft.com\/en-us\/documentation\/articles\/log-analytics-data-collector-api\/\">Log Analytics HTTP Data Collector API documentation<\/a> . I actually added just an additional function <strong>Get-UserData<\/strong>.<\/p>\n<p>The <strong>Get-UserData<\/strong> function returns the current logged in user from Linux by using the <strong>who<\/strong> command (it is a Linux command, not a PowerShell command!). Here is a sample output of the <strong>who<\/strong> command.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/17-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/17-HSG-110916.png\" alt=\"Sample output of the who command\" width=\"468\" height=\"153\" class=\"alignnone size-full wp-image-80715\" \/><\/a><\/p>\n<p>The output of the <strong>who<\/strong> command is assigned to <strong>$Logins<\/strong> variable. Next, for each logged in user the user name, terminal (pseudo terminal or pts) where the user is signed in, the sign-in date\/time, and from which device the user is logged in is extracted. For each login, a PowerShell custom object is created. The last line of code converts the login object array to plain JSON output.<\/p>\n<p style=\"padding-left: 30px\"><code># Get logged-in user and create a custom object\nFunction Get-UserData\n{<\/code><\/p>\n<p style=\"padding-left: 60px\"><code># Use who command from Linux to get logged in users\n$Logins = who\n$Users = @()\nForEach ($Login in $Logins)\n{<\/code><\/p>\n<p style=\"padding-left: 90px\"><code># Extract the data for each login, sample data looks like \"root\u00a0\u00a0\u00a0\u00a0 pts\/1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 2016-09-21 22:46 (192.168.32.11)\"\n$Login -match '([a-z][a-z]+)\\s+(.*\\d)\\s+(\\d{4}-\\d{2}-\\d{2}\\s+\\d*:\\d*)\\s+(.*)' | Out-Null\n# Create a collection of custom objects for each user\n$Users += New-Object -TypeName PSObject -Property @{<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>Name\u00a0\u00a0\u00a0\u00a0 = $Matches[1]\nTerminal = $Matches[2]\nDate\u00a0\u00a0\u00a0\u00a0 = '{0:MM\/dd\/yyyy hh:mm:ss}' -f [DateTime]$Matches[3]\nDevice\u00a0\u00a0 = ($Matches[4]).replace('(','').replace(')','')<\/code><\/p>\n<p style=\"padding-left: 90px\"><code>}<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>}<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>return $Users<\/code><\/p>\n<p style=\"padding-left: 30px\"><code>}<\/code><\/p>\n<p style=\"padding-left: 30px\"><code># Convert the $users collection into JSON\n$Json = Get-UserData | ConvertTo-Json<\/code><\/p>\n<p>If the script is executed it will send the user JSON data (user login data) to <a target=\"_blank\" href=\"https:\/\/azure.microsoft.com\/en-us\/documentation\/articles\/log-analytics-data-collector-api\/\">Log Analytics HTTP Data Collector API<\/a>.<\/p>\n<p>#####################################################################################<\/p>\n<p><em>Send-Login.ps1<\/em><\/p>\n<p style=\"padding-left: 30px\"><code># Replace with your Workspace ID\n$CustomerId = [YOUR WORKSPACE ID]<\/code><\/p>\n<p style=\"padding-left: 30px\"><code># Replace with your Primary Key\n$SharedKey = [YOUR PRIMARY KEY FROM YOUR OMS WORKSPACE]<\/code><\/p>\n<p style=\"padding-left: 30px\"><code># Specify the name of the record type that you'll be creating\n$LogType = 'LinuxLogin'<\/code><\/p>\n<p style=\"padding-left: 30px\"><code># Specify a time in the format YYYY-MM-DDThh:mm:ssZ to specify a created time for the records\n$TimeStampField = ''<\/code><\/p>\n<p style=\"padding-left: 30px\"><code># Create the function to create the authorization signature\nFunction Build-Signature ($CustomerId, $SharedKey, $Date, $ContentLength, $Method, $ContentType, $Resource)\n{<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>$xHeaders = \"x-ms-date:\" + $Date\n$StringToHash = $Method + \"`n\" + $ContentLength + \"`n\" + $ContentType + \"`n\" + $xHeaders + \"`n\" + $Resource<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>$BytesToHash = [Text.Encoding]::UTF8.GetBytes($StringToHash)\n$KeyBytes = [Convert]::FromBase64String($SharedKey)<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>$Sha256 = New-Object System.Security.Cryptography.HMACSHA256\n$Sha256.Key = $KeyBytes\n$CalculatedHash = $Sha256.ComputeHash($BytesToHash)\n$EncodedHash = [Convert]::ToBase64String($CalculatedHash)\n$Authorization = 'SharedKey {0}:{1}' -f $CustomerId,$EncodedHash\nreturn $Authorization<\/code><\/p>\n<p style=\"padding-left: 30px\"><code>}\n# Create the function to create and post the request\nFunction Post-OMSData($CustomerId, $SharedKey, $Body, $LogType)\n{<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>$Method = \"POST\"\n$ContentType = \"application\/json\"\n$Resource = \"\/api\/logs\"\n$Rfc1123date = [DateTime]::UtcNow.ToString(\"r\")\n$ContentLength = $Body.Length\n$Signature = Build-Signature `\n-customerId $CustomerId `\n-sharedKey $SharedKey `\n-date $Rfc1123date `\n-contentLength $ContentLength `\n-fileName $FileName `\n-method $Method `\n-contentType $ContentType `\n-resource $Resource\n$uri = \"https:\/\/\" + $CustomerId + \".ods.opinsights.azure.com\" + $Resource + \"?api-version=2016-04-01\"<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>$Headers = @{<\/code><\/p>\n<p style=\"padding-left: 90px\"><code>\"Authorization\" = $Signature;\n\"Log-Type\" = $LogType;\n\"x-ms-date\" = $Rfc1123date;\n\"time-generated-field\" = $TimeStampField;<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>}<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>$Response = Invoke-WebRequest -Uri $uri -Method $Method -ContentType $ContentType -Headers\n$Headers -Body $Body -UseBasicParsing\nreturn $Response.StatusCode<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>}\n# Get logged-in user and create a custom object\nFunction Get-UserData\n{<\/code><\/p>\n<p style=\"padding-left: 90px\"><code># Use who command from Linux to get logged in users\n$Logins = who\n$Users = @()\nForEach ($Login in $Logins)\n{<\/code><\/p>\n<p style=\"padding-left: 120px\"><code># Extract the data for each login, sample data looks like \"root\u00a0\u00a0\u00a0\u00a0 pts\/1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 2016-09-21 22:46 (192.168.32.11)\"\n$Login -match '([a-z][a-z]+)\\s+(.*\\d)\\s+(\\d{4}-\\d{2}-\\d{2}\\s+\\d*:\\d*)\\s+(.*)' | Out-Null\n# Create a collection of custom objects for each user\n$Users += New-Object -TypeName PSObject -Property @{<\/code><\/p>\n<p style=\"padding-left: 150px\"><code>Name\u00a0\u00a0\u00a0\u00a0 = $Matches[1]\nTerminal = $Matches[2]\nDate\u00a0\u00a0\u00a0\u00a0 = '{0:MM\/dd\/yyyy hh:mm:ss}' -f [DateTime]$Matches[3]\nDevice\u00a0\u00a0 = ($Matches[4]).replace('(','').replace(')','')<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>}<\/code><\/p>\n<p style=\"padding-left: 90px\"><code>}<\/code><\/p>\n<p style=\"padding-left: 90px\"><code>return $Users<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>}<\/code><\/p>\n<p style=\"padding-left: 60px\"><code># Convert the $users collection into JSON\n$Json = Get-UserData | ConvertTo-Json<\/code><\/p>\n<p style=\"padding-left: 60px\"><code># Submit the data to the API endpoint\nPost-OMSData -customerId $CustomerId -sharedKey $SharedKey -body ([System.Text.Encoding]::UTF8.GetBytes($Json)) -logType $LogType\n#####################################################################################<\/code><\/p>\n<p>Finally, we have everything set up and just need to wait for the scheduled job to run. If everything works correctly, you should see the results in the <em>LinuxLogin_CL<\/em> custom log or whatever name you have configured in the script (<strong>$LogType<\/strong>).<\/p>\n<p>When the script fires, it takes about 2-3 minutes for the data to appear in OMS Log Search. In this case, we run a search query <em>* Type=LinuxLogin_CL<\/em>, and see the results immediately.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/18-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/18-HSG-110916.png\" alt=\"Results of the * Type=LinuxLogin_CL query\" width=\"654\" height=\"798\" class=\"alignnone size-full wp-image-80725\" \/><\/a><\/p>\n<p>Of course, now you could start to play with this data and run some queries on it. For example, here we are able to see when a new user (hacker) connected, from which system, and at which time.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/19-HSG-110916.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/19-HSG-110916.png\" alt=\"Results of a query that shows suspicious activity\" width=\"623\" height=\"129\" class=\"alignnone size-full wp-image-80735\" \/><\/a><\/p>\n<p>Another advanced way to\u00a0display the data would be to use OMS View Designer to build some nice dashboards.<\/p>\n<p><strong><u>Summary<\/u><\/strong>: In this post, we connected the Linux server to Azure Automation DSC. Then, we assigned a DSC configuration, which will run some Bash commands to create a cronjob on Linux. This cronjob executes a PowerShell script on Linux (yes, native PowerShell code!) to send the current connected users to OMS via <a target=\"_blank\" href=\"https:\/\/azure.microsoft.com\/de-de\/documentation\/articles\/log-analytics-data-collector-api\/\">Azure Log Analytics HTTP Data Collector API<\/a><span>. <\/span><\/p>\n<p>I am fascinated how I am able to use Linux native command and use it together with PowerShell and vice versa. When you run a command on Linux, the output is just a string.\u00a0With \u00a0PowerShell on board, you can\u00a0convert the output from Bash commands to objects \u2013 PowerShell objects. Working with objects unleashes all the power there is in PowerShell and more.<\/p>\n<p>This example is not meant for a production-ready scenario. Instead, it gives you an idea which direction Microsoft is taking. It gives you an idea how we are able to mix Microsoft and Linux\/Open Source technologies to take the best from both worlds to achieve our goal in less time and have some real fun.<\/p>\n<p>Thank you, Stefan.<\/p>\n<p>I invite you to follow me on <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingguystwitter\">Twitter<\/a> and <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send email to me at <a target=\"_blank\" href=\"mailto:scripter@microsoft.com\">scripter@microsoft.com<\/a>, or post your questions on the <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingforum\">Official Scripting Guys Forum<\/a>. Also, check out my <a target=\"_blank\" href=\"https:\/\/blogs.technet.microsoft.com\/msoms\/\">Microsoft Operations Management Suite Blog<\/a>. Until next time, peace.<\/p>\n<p><strong>Ed Wilson<\/strong>\nMicrosoft Scripting Guy<\/p>\n<div class=\"site container-fluid\" id=\"page\">\n<div class=\"site-content row\" id=\"site-content\">\n<div class=\"content-area col-sm-9\" id=\"primary\">\n<div class=\"div-content\" id=\"single-content\">\n<article class=\"post-80255 post type-post status-publish format-standard hentry category-hey-scripting-guy category-windows-powershell tag-bash tag-guest-blogger tag-scripting-guy tag-stefan-roth tag-windows-powershell\" id=\"post-80255\">\n<div class=\"entry-content single\">\n<p>&nbsp;<\/p>\n<\/div>\n<\/article>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Learn how to configure and use PowerShell, Bash, and DSC with Linux. Hi, my name is Stefan Roth (Blog: http:\/\/stefanroth.net \/ Twitter: @stefanroth_net), and I am a Cloud and Datacenter MVP. In my last post of this three-part series, I would like to show you how we are able to hook up the previously [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[568,641],"tags":[698,56,3,699,45],"class_list":["post-80565","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hey-scripting-guy","category-windows-powershell","tag-bash","tag-guest-blogger","tag-scripting-guy","tag-stefan-roth","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Learn how to configure and use PowerShell, Bash, and DSC with Linux. Hi, my name is Stefan Roth (Blog: http:\/\/stefanroth.net \/ Twitter: @stefanroth_net), and I am a Cloud and Datacenter MVP. In my last post of this three-part series, I would like to show you how we are able to hook up the previously [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/80565","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=80565"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/80565\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=80565"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=80565"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=80565"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}